Index: /trunk/BNC/CHANGELOG.md
===================================================================
--- /trunk/BNC/CHANGELOG.md	(revision 11098)
+++ /trunk/BNC/CHANGELOG.md	(revision 11099)
@@ -11,4 +11,6 @@
 - ADDED: Combination: hourly report of AC satellites persistently rejected as outliers, and of satellites skipped because fewer than 2 ACs provide corrections
 - CHANGED: Combination: the orbits of a system come from the first stream in the table providing that system; after an outage of that stream, BNC switches back to it once it delivers again for 60 s (before, a single missing epoch moved the orbits permanently to another stream)
+- CHANGED: Combination: the random walk of the AC satellite offsets is defined per time (1 cm per 10 s) instead of per epoch, so the result no longer depends on the sampling interval (at 5 s the offsets were sqrt(2) noisier per hour)
+- CHANGED: Combination: an AC excluded from the clock datum because of inconsistent code biases is used again only after 12 passing checks in a row (1 hour), not after the first one (a borderline AC changed the clock datum every 5 minutes)
 - ADDED: Combination of APC (SSRA) and CoM (SSRC) streams together: with an ANTEX file the combination is done in the CoM frame, the orbits of the APC streams are converted to CoM; ACs not combined because of a different reference point are reported
 - ADDED: Option 'Reference Signals' (key ssrRefSignals): reference signals of the satellite clocks per GNSS for the combination (AC clock referral, code biases from the Bias SINEX file) and the SSR QC, default IGS Real-Time convention G:1W&2W R:1P&2P E:1C&5Q C:2I&6I J:1C&2L S:1C&5Q, e.g. for a switch of BDS to C1P/C5P or of QZSS to L1/L5
Index: /trunk/BNC/src/combination/bnccomb.cpp
===================================================================
--- /trunk/BNC/src/combination/bnccomb.cpp	(revision 11098)
+++ /trunk/BNC/src/combination/bnccomb.cpp	(revision 11099)
@@ -34,5 +34,6 @@
 
 const double sig0_offACSat = 1000.0;
-const double sigP_offACSat =   0.01;
+const double sigP_offACSat =   0.01; // per REF_SAMPL_offACSat, scaled with the time between the epochs
+const double REF_SAMPL_offACSat = 10.0; // [s]
 
 const double sig0_clkSat   =  100.0;
@@ -1183,4 +1184,12 @@
   // Prediction Step
   // ---------------
+  // The random walk of the AC satellite offsets is defined per time, not per
+  // epoch (sigP_offACSat per REF_SAMPL_offACSat seconds), so that the result
+  // does not depend on the combination sampling interval
+  double dt = _lastFilterEpoch[sys].valid() ? epoTime - _lastFilterEpoch[sys] : double(_cmbSampl);
+  if (dt <= 0.0) {
+    dt = double(_cmbSampl);
+  }
+  _lastFilterEpoch[sys] = epoTime;
   int nPar = _params[sys].size();
   ColumnVector x0(nPar);
@@ -1194,5 +1203,6 @@
     }
     else {
-      _QQ[sys](iPar,iPar) += pp->sigP * pp->sigP;
+      double fac = (pp->type == cmbParam::offACSat) ? dt / REF_SAMPL_offACSat : 1.0;
+      _QQ[sys](iPar,iPar) += pp->sigP * pp->sigP * fac;
     }
     x0(iPar) = pp->xx;
@@ -1349,5 +1359,15 @@
     double slope     = (sxx > 0.0) ? sxy / sxx : 0.0;
     double corrCoeff = (sxx > 0.0 && syy > 0.0) ? sxy / sqrt(sxx * syy) : 0.0;
+    // Hysteresis: a flagged AC is used for the clock datum again only after
+    // REINCLUDE_CHECKS passing checks in a row (1 hour). Right after the
+    // exclusion the offsets are reset and not yet converged, so a single
+    // passing check does not prove consistency; a borderline AC would
+    // otherwise change the clock datum every few minutes.
+    const int REINCLUDE_CHECKS = 12;
     if (spread < MIN_SPREAD || slope < MIN_SLOPE || corrCoeff < MIN_CORR) {
+      if (_biasInconsistent.contains(key) && ++_biasConsistentChecks[key] < REINCLUDE_CHECKS) {
+        continue;
+      }
+      _biasConsistentChecks.remove(key);
       if (_biasInconsistent.remove(key)) {
         QString msg = QString("%1 %2 code biases consistent with its clocks again, "
@@ -1372,4 +1392,5 @@
                   .arg(acName).arg(sys).arg(refSig).arg(nn)
                   .arg(spread, 0, 'f', 3).arg(slope, 0, 'f', 2).arg(corrCoeff, 0, 'f', 2);
+    _biasConsistentChecks[key] = 0;
     if (!_biasInconsistent.contains(key)) {
       _biasInconsistent.insert(key);
Index: /trunk/BNC/src/combination/bnccomb.h
===================================================================
--- /trunk/BNC/src/combination/bnccomb.h	(revision 11098)
+++ /trunk/BNC/src/combination/bnccomb.h	(revision 11099)
@@ -257,4 +257,6 @@
   QMap<QString, bncTime>                     _biasCheckWarned; // last inconsistency warning per AC and system
   QSet<QString>                              _biasInconsistent; // AC+system excluded from the clock datum
+  QMap<QString, int>                         _biasConsistentChecks; // flagged AC+system: passing checks in a row
+  QMap<char, bncTime>                        _lastFilterEpoch;      // per system: last epoch of the filter prediction
   void checkBiasConsistency(bncTime epoTime, char sys, QTextStream& out);
   void checkPersistentOutliers(bncTime epoTime, char sys, QTextStream& out);
