diff --git a/core/detectors/rich/CbmRichDigiMapManager.cxx b/core/detectors/rich/CbmRichDigiMapManager.cxx
index 5e264b0e5cd36f455694cf7df4d22de8c3f96067..6b2485bbbfe0af5b1fd28e68fa9480558cc5349e 100644
--- a/core/detectors/rich/CbmRichDigiMapManager.cxx
+++ b/core/detectors/rich/CbmRichDigiMapManager.cxx
@@ -1,4 +1,4 @@
-/* Copyright (C) 2015-2023 GSI/JINR-LIT, Darmstadt/Dubna
+/* Copyright (C) 2015-2024 GSI/JINR-LIT, Darmstadt/Dubna
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Semen Lebedev, Martin Beyer, Adrian Amatus Weber, Andrey Lebedev [committer], Florian Uhlig */
 
@@ -322,7 +322,8 @@ CbmRichPmtData* CbmRichDigiMapManager::GetPmtDataById(Int_t id)
   return it->second;
 }
 
-vector<Int_t> CbmRichDigiMapManager::GetNeighbourPixels(Int_t address, Int_t n, Bool_t direct, Bool_t diagonal)
+vector<Int_t> CbmRichDigiMapManager::GetNeighbourPixels(Int_t address, Int_t n, Bool_t horizontal, Bool_t vertical,
+                                                        Bool_t diagonal)
 {
   vector<Int_t> neighbourPixels;
   if (n == 0) return neighbourPixels;
@@ -335,18 +336,25 @@ vector<Int_t> CbmRichDigiMapManager::GetNeighbourPixels(Int_t address, Int_t n,
     CbmRichPixelData* iPixelData = GetPixelDataByAddress(iAddr);
     Int_t iIndX                  = iPixelData->fPixelId % 8;
     Int_t iIndY                  = iPixelData->fPixelId / 8;
-    if (direct && !diagonal && n == 1) {  // direct neighbours
-      if ((abs(iIndX - indX) + abs(iIndY - indY)) == 1) neighbourPixels.push_back(iAddr);
+    if (horizontal && !vertical && !diagonal && n == 1) {  // direct horizontal neighbours
+      if (abs(iIndX - indX) == 1 && abs(iIndY - indY) == 0) neighbourPixels.push_back(iAddr);
+    }
+    else if (vertical && !horizontal && !diagonal && n == 1) {  // direct vertical neighbours
+      if (abs(iIndX - indX) == 0 && abs(iIndY - indY) == 1) neighbourPixels.push_back(iAddr);
     }
-    else if (!direct && diagonal && n == 1) {  // diagonal neighbours
+    else if (!horizontal && !vertical && diagonal && n == 1) {  // diagonal neighbours
       if ((abs(iIndX - indX) == 1) && (abs(iIndY - indY) == 1)) neighbourPixels.push_back(iAddr);
     }
-    else if (direct && diagonal) {  // all neighbours in (2N+1)*(2N+1) grid
+    else if (horizontal && vertical && !diagonal && n == 1) {  // direct horizontal and vertical neighbours
+      if ((abs(iIndX - indX) + abs(iIndY - indY)) == 1) neighbourPixels.push_back(iAddr);
+    }
+    else if (horizontal && vertical && diagonal) {  // all neighbours in (2N+1)*(2N+1) grid
       if ((abs(iIndX - indX) <= n) && (abs(iIndY - indY) <= n)) neighbourPixels.push_back(iAddr);
     }
     else {
       LOG(error) << "ERROR: Unrecogniced option in CbmRichDigiMapManager::GetNeighbourPixels " << endl
-                 << " n = " << n << " direct = " << direct << " diagonal = " << diagonal;
+                 << " n = " << n << " horizontal = " << horizontal << " vertical = " << vertical
+                 << " diagonal = " << diagonal;
     }
   }
   return neighbourPixels;
diff --git a/core/detectors/rich/CbmRichDigiMapManager.h b/core/detectors/rich/CbmRichDigiMapManager.h
index d4a9604081b12fb4b047ee46558af8ca4775cf99..31234c1d9ca923c04b111ba6cebd26e93e99b2a7 100644
--- a/core/detectors/rich/CbmRichDigiMapManager.h
+++ b/core/detectors/rich/CbmRichDigiMapManager.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2015-2023 GSI/JINR-LIT, Darmstadt/Dubna
+/* Copyright (C) 2015-2024 GSI/JINR-LIT, Darmstadt/Dubna
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Semen Lebedev, Martin Beyer, Andrey Lebedev [committer], Florian Uhlig */
 
@@ -23,12 +23,12 @@ class CbmRichPixelData;
 class CbmRichPmtData;
 
 class CbmRichDigiMapManager {
-private:
+ private:
   CbmRichDigiMapManager();
 
-public:
+ public:
   /**
-   * Return Instance of CbmRichGeoManager.
+   * \brief Return Instance of CbmRichGeoManager.
    */
   static CbmRichDigiMapManager& GetInstance()
   {
@@ -36,58 +36,66 @@ public:
     return fInstance;
   }
 
-  /*
+  /**
    * \brief Return digi address by path to node.
    */
   Int_t GetPixelAddressByPath(const std::string& path);
 
-  /*
+  /**
    * \brief Return CbmRichDataPixel by digi address.
    */
   CbmRichPixelData* GetPixelDataByAddress(Int_t address);
 
-  /*
+  /**
    * \brief Return random address. Needed for noise digi.
    */
   Int_t GetRandomPixelAddress();
 
-  /*
+  /**
    * \brief Return addresses of all pixels
    */
   std::vector<Int_t> GetPixelAddresses();
 
-  /*
+  /**
    * \brief Return ids for all pmts
    */
   std::vector<Int_t> GetPmtIds();
 
-  /*
+  /**
    * \brief Return CbmRichDataPmt by id.
    */
   CbmRichPmtData* GetPmtDataById(Int_t id);
 
-  /*
+  /**
    * \brief Return the addresses of the neighbour pixels.
    * \param address Pixel address
    * \param n Size of the grid (2n+1)*(2n+1)
-   * \param direct return direct neighbours
+   * \param horizontal return horizontal neighbours
+   * \param vertical return vertical neighbours
    * \param diagonal return diagonal neighbours
    */
-  std::vector<Int_t> GetNeighbourPixels(Int_t address, Int_t N, Bool_t direct = true, Bool_t diagonal = true);
+  std::vector<Int_t> GetNeighbourPixels(Int_t address, Int_t N, Bool_t horizontal = true, Bool_t vertical = true,
+                                        Bool_t diagonal = true);
 
-  /*
+  /**
    * \brief Return the addresses of the direct neighbour pixels.
    * \param address Pixel address
    */
-  std::vector<Int_t> GetDirectNeighbourPixels(Int_t address) { return GetNeighbourPixels(address, 1, true, false); }
+  std::vector<Int_t> GetDirectNeighbourPixels(Int_t address, Bool_t horizontal = true, Bool_t vertical = true)
+  {
+    return GetNeighbourPixels(address, 1, horizontal, vertical, false);
+  }
 
-  /*
+  /**
    * \brief Return the addresses of the diagonal neighbour pixels.
    * \param address Pixel address
    */
-  std::vector<Int_t> GetDiagonalNeighbourPixels(Int_t address) { return GetNeighbourPixels(address, 1, false, true); }
+  std::vector<Int_t> GetDiagonalNeighbourPixels(Int_t address)
+  {
+    return GetNeighbourPixels(address, 1, false, false, true);
+  }
 
-  /*
+  /**
    * \brief Return the addresses of pixels in a (2n+1)*(2n+1) grid,
    * with the address pixel in the center of the grid.
    * Addresses are limited to the same MAPMT as the input address.
@@ -97,13 +105,13 @@ public:
    */
   std::vector<Int_t> GetNxNNeighbourPixels(Int_t address, Int_t n)
   {
-    return GetNeighbourPixels(address, n, true, true);
+    return GetNeighbourPixels(address, n, true, true, true);
   }
 
-public:
+ public:
   virtual ~CbmRichDigiMapManager();
 
-private:
+ private:
   std::map<std::string, Int_t> fPixelPathToAddressMap;
   std::map<Int_t, CbmRichPixelData*> fPixelAddressToDataMap;
   std::vector<Int_t> fPixelAddresses;  // vector of all  pixel addresses
@@ -114,7 +122,7 @@ private:
 
   int getDetectorSetup(TString const nodePath);
 
-  /*
+  /**
    * \brief Initialize maps.
    */
   void Init();
diff --git a/reco/detectors/rich/qa/CbmRichDigiQa.cxx b/reco/detectors/rich/qa/CbmRichDigiQa.cxx
index 4524ad7b3695664afa90a1f0ca9adcf15e85b9c4..6be538dc2f8492bc5faf76b98d2c4e162a0a216b 100644
--- a/reco/detectors/rich/qa/CbmRichDigiQa.cxx
+++ b/reco/detectors/rich/qa/CbmRichDigiQa.cxx
@@ -83,14 +83,14 @@ void CbmRichDigiQa::Exec(Option_t* /*option*/)
     }
   }
 
-  // Fill crosstalk digis
+  // Fill neighbour digis
   for (auto& [pmt, digis] : fPmtDigisTimeAddress) {
     std::sort(digis.begin(), digis.end());
     for (auto it0 = digis.begin(); it0 != digis.end(); ++it0) {
       Int_t indX0 = CbmRichDigiMapManager::GetInstance().GetPixelDataByAddress(it0->second)->fPixelId % 8;
       Int_t indY0 = CbmRichDigiMapManager::GetInstance().GetPixelDataByAddress(it0->second)->fPixelId / 8;
       for (auto it1 = it0 + 1; it1 != digis.end(); ++it1) {
-        if (abs(it0->first - it1->first) < fCrosstalkTimeLimit) {
+        if (abs(it0->first - it1->first) < fNeighbourTimeLimit) {
           Int_t indX1 = CbmRichDigiMapManager::GetInstance().GetPixelDataByAddress(it1->second)->fPixelId % 8;
           Int_t indY1 = CbmRichDigiMapManager::GetInstance().GetPixelDataByAddress(it1->second)->fPixelId / 8;
           if (indX0 == indX1 && indY0 == indY1) continue;
@@ -99,7 +99,7 @@ void CbmRichDigiQa::Exec(Option_t* /*option*/)
           if (abs(indX0 - indX1) > 1 || abs(indY0 - indY1) > 1) continue;
           fHM->H2("fhDigiNeighbours")->Fill(indX1 - indX0, indY0 - indY1);
         }
-        else if (it1->first - it0->first > fCrosstalkTimeLimit) {
+        else if (it1->first - it0->first > fNeighbourTimeLimit) {
           break;
         }
       }
diff --git a/reco/detectors/rich/qa/CbmRichDigiQa.h b/reco/detectors/rich/qa/CbmRichDigiQa.h
index 25822a5c28a7266e4a63c1fbf2da77b5be8541f9..cc6daaa6cb69dd627fcd7793470e6953122fc4c3 100644
--- a/reco/detectors/rich/qa/CbmRichDigiQa.h
+++ b/reco/detectors/rich/qa/CbmRichDigiQa.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2023-2023 UGiessen, Giessen
+/* Copyright (C) 2023-2024 UGiessen, Giessen
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Martin Beyer [committer] */
 
@@ -67,12 +67,12 @@ public:
   }
 
   /**
-    * \brief Set time limit in which a neighbour digi is considered crosstalk
+    * \brief Set time limit in which a digi is considered neighbour.
     * \param[in] limit absolue time limit
     */
-  void SetCrosstalkTimeLimit(Double_t limit) { fCrosstalkTimeLimit = limit; }
+  void SetNeighbourTimeLimit(Double_t limit) { fNeighbourTimeLimit = limit; }
 
-private:
+ private:
   int fEventNum {};
 
   CbmDigiManager* fDigiMan {nullptr};
@@ -84,7 +84,7 @@ private:
   std::map<Int_t, std::vector<std::pair<Double_t, Int_t>>>
     fPmtDigisTimeAddress {};  // Store times and addresses of fired digis for each pmt in Ts
 
-  Double_t fCrosstalkTimeLimit {5.};  // Time in which a neighbour digi is considered crosstalk
+  Double_t fNeighbourTimeLimit{5.};   // Time in which digi is considered a neighbour
   Double_t fToTLimitLow {-1.};        // Lower limit for ToT cut
   Double_t fToTLimitHigh {-1.};       // Upper limit for ToT cut
 
diff --git a/sim/detectors/rich/CbmRichDigitizer.cxx b/sim/detectors/rich/CbmRichDigitizer.cxx
index db6fe7fcc0a1ba8cbaa7258e70ae7ad2616f5dfb..d915fa55bac27a453b48b8d95ac31840825eef8d 100644
--- a/sim/detectors/rich/CbmRichDigitizer.cxx
+++ b/sim/detectors/rich/CbmRichDigitizer.cxx
@@ -1,4 +1,4 @@
-/* Copyright (C) 2015-2023 GSI/JINR-LIT, Darmstadt/Dubna
+/* Copyright (C) 2015-2024 GSI/JINR-LIT, Darmstadt/Dubna
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Martin Beyer, Andrey Lebedev [committer], Volker Friese, Florian Uhlig, Semen Lebedev */
 
@@ -188,7 +188,9 @@ void CbmRichDigitizer::ProcessPoint(CbmRichPoint* point, Int_t pointId, Int_t ev
     CbmLink link(1., pointId, eventNum, inputNum);
     AddSignalToBuffer(address, time, link);
     if (gcode == 50000050 && address > 0) AddCrossTalk(address, time, link);
-    if (mcTrack->GetCharge() != 0. && address > 0) AddChargedParticleCluster(address, time, eventNum, inputNum);
+    if (fClusterSize > 0 && mcTrack->GetCharge() != 0. && address > 0) {
+      AddChargedParticleCluster(address, time, eventNum, inputNum);
+    }
   }
 }
 
@@ -199,18 +201,30 @@ void CbmRichDigitizer::AddSignalToBuffer(Int_t address, Double_t time, const Cbm
 
 void CbmRichDigitizer::AddCrossTalk(Int_t address, Double_t time, const CbmLink& link)
 {
-  std::vector<Int_t> directPixels   = CbmRichDigiMapManager::GetInstance().GetDirectNeighbourPixels(address);
+  std::vector<Int_t> directHorizontalPixels =
+    CbmRichDigiMapManager::GetInstance().GetDirectNeighbourPixels(address, true, false);
+  std::vector<Int_t> directVerticalPixels =
+    CbmRichDigiMapManager::GetInstance().GetDirectNeighbourPixels(address, false, true);
   std::vector<Int_t> diagonalPixels = CbmRichDigiMapManager::GetInstance().GetDiagonalNeighbourPixels(address);
   /* clang-format off */
-  Double_t crosstalkCreatedProbability = 1 - pow(1 - fCrossTalkProbability, directPixels.size()) *
-                                             pow(1 - fCrossTalkProbability / 4., diagonalPixels.size());
+  Double_t crosstalkProbability = 1 - pow(1 - fCrossTalkProbability[0], directHorizontalPixels.size()) *
+                                      pow(1 - fCrossTalkProbability[1], directVerticalPixels.size()) *
+                                      pow(1 - fCrossTalkProbability[2], diagonalPixels.size());
   Int_t crosstalkAddress = -1;
-  if (gRandom->Uniform() < crosstalkCreatedProbability) {
-    Double_t thresholdDirectDiagonal =
-      static_cast<Double_t>(directPixels.size())
-      / (static_cast<Double_t>(directPixels.size()) + static_cast<Double_t>(diagonalPixels.size()) / 4.);
-    if (gRandom->Uniform() < thresholdDirectDiagonal) {
-      crosstalkAddress = directPixels[gRandom->Integer(directPixels.size())];
+  if (gRandom->Uniform() < crosstalkProbability) {
+    // Split into 3 intervals based on crosstalk probability and number of pixels
+    Double_t denom = directHorizontalPixels.size() * fCrossTalkProbability[0] + 
+                     directVerticalPixels.size()   * fCrossTalkProbability[1] + 
+                     diagonalPixels.size()         * fCrossTalkProbability[2];
+    // Threshold values for end of each interval
+    Double_t thHorizontal = directHorizontalPixels.size() * fCrossTalkProbability[0] / denom;
+    Double_t thVertical = directVerticalPixels.size()     * fCrossTalkProbability[1] / denom + thHorizontal;    
+    Double_t rnd = gRandom->Uniform();
+    if (rnd < thHorizontal) {
+      crosstalkAddress = directHorizontalPixels[gRandom->Integer(directHorizontalPixels.size())];
+    }
+    else if (rnd < thVertical) {
+      crosstalkAddress = directVerticalPixels[gRandom->Integer(directVerticalPixels.size())];
     } else {
       crosstalkAddress = diagonalPixels[gRandom->Integer(diagonalPixels.size())];
     }
diff --git a/sim/detectors/rich/CbmRichDigitizer.h b/sim/detectors/rich/CbmRichDigitizer.h
index 9d4af0a302ed2c9e3788664b494fb713c66dad9e..a7cd837e7247b33e1ac03ee75fe45f33ace0c9f0 100644
--- a/sim/detectors/rich/CbmRichDigitizer.h
+++ b/sim/detectors/rich/CbmRichDigitizer.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2015-2023 GSI/JINR-LIT, Darmstadt/Dubna
+/* Copyright (C) 2015-2024 GSI/JINR-LIT, Darmstadt/Dubna
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Semen Lebedev, Andrey Lebedev [committer], Martin Beyer */
 
@@ -76,8 +76,18 @@ public:
     */
   void SetPixelDeadTime(Double_t dt) { fPixelDeadTime = dt; }
 
-  /** Set crosstalk probability */
-  void SetCrossTalkProbability(Double_t crosstalk) { fCrossTalkProbability = crosstalk; }
+  /** 
+   * \brief Set crosstalk probability for horizontal, vertical and diagonal directions.
+   * \param horizontal probability of crosstalk for direct horizontal pixels
+   * \param vertical probability of crosstalk for direct vertical pixels
+   * \param diagonal probability of crosstalk for direct diagonal pixels
+   */
+  void SetCrossTalkProbability(Double_t horizontal, Double_t vertical, Double_t diagonal)
+  {
+    fCrossTalkProbability[0] = horizontal;
+    fCrossTalkProbability[1] = vertical;
+    fCrossTalkProbability[2] = diagonal;
+  }
 
   /**
     * \brief Set event noise rate per McRichPoint / per  pixel / per second :
@@ -130,7 +140,9 @@ private:
 
   Double_t fTimeResolution {1.};              // in ns, time resolution for digis
   Double_t fPixelDeadTime {50.};              // in ns, deadtime for one pixel
-  Double_t fCrossTalkProbability {0.02};      // probability of the crosstalk for direct neighbor for one pixel
+  // probability of crosstalk depending on direction of neighbour pixel
+  // index 0: horizontal, 1: vertical, 2: diagonal
+  std::array<Double_t, 3> fCrossTalkProbability{0.02, 0.02, 0.005};
   Double_t fEventNoiseRate {5.};              // noise rate per McRichPoint / per  pixel / per second
   Double_t fEventNoiseInterval {50.};         // in ns, interval to generate event noise signals
   Double_t fDarkRatePerPixel {1000.};         // dark rate per pixel in Hz