Index: trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm_new.cpp
===================================================================
--- trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm_new.cpp	(revision 11045)
+++ trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm_new.cpp	(revision 11046)
@@ -11,4 +11,5 @@
 #include <stdio.h>
 #include <string.h>
+#include <climits>
 #ifndef sparc
 #include <stdint.h>
@@ -502,4 +503,5 @@
   unsigned int satPositions[64], numSatPositions;
   unsigned int freqPositions[ANT_MAXFREQUENCIES], numFreqPositions;
+  uint64_t satMask;
 
   STARTDATA
@@ -522,13 +524,17 @@
         }
         E_SATELLITE_SET_INDICATOR(a->SatelliteSetIndicator[s])
-        E_SATELLITE_MASK(a->SatelliteMask[s])
-
-        /* same MSB-first mask convention as D_SATELLITE_MASK/GetSSR */
+
+        /* same MSB-first mask convention as D_SATELLITE_MASK/GetSSR; bits
+           beyond the satellites supported for this system are cleared, since
+           no Sat[] data exists for them and the mask must match the blocks */
         numSatPositions = 0;
+        satMask = 0;
         for (k = 0; k < 64 && satoffset[s] + k < satoffset[s + 1]; ++k) {
           if ((a->SatelliteMask[s] >> (63 - k)) & 1ULL) {
             satPositions[numSatPositions++] = satoffset[s] + k;
-          }
-        }
+            satMask |= 1ULL << (63 - k);
+          }
+        }
+        E_SATELLITE_MASK(satMask)
         numSatBlocks = a->SatelliteSetIndicator[s] ? (numSatPositions ? 1 : 0) : numSatPositions;
 
@@ -557,7 +563,15 @@
             }
             if (a->NadirAngleDependentCorrectionIndicator[s]) {
+              /* DF+021: NaN (invalid) and values outside the range of
+                 int(3 + DF+015) are sent as the invalid value -2^(n-1) */
+              unsigned int nb  = 3 + a->NadirAngleDependentCorrectionRangeExtension[s];
+              double       lim = ldexp(1.0, nb - 1);
               for (deg = 0; deg <= a->maximumOffNadirAngle[s] && deg < ANT_MAXNADIRDEGREES; ++deg) {
-                E_NADIR_ANGLE_DEPENDENT_CORRECTION(satBlock.Freq[f].NadirAngleCorrection[deg],
-                  a->NadirAngleDependentCorrectionRangeExtension[s])
+                double val = satBlock.Freq[f].NadirAngleCorrection[deg];
+                double mm  = std::isnan(val) ? -lim : floor(val * 1000.0 + 0.5);
+                if (mm <= -lim || mm >= lim) {
+                  mm = -lim;
+                }
+                ADDBITS(nb, (int64_t)mm)
               }
             }
@@ -1218,8 +1232,12 @@
 
       /* DF394 satellite mask: MSB (bit 63) = satellite 1 within this system,
-         same convention as the MSM satellite mask that shares this field. */
-      for (k = 0; k < 64 && satoffset[s] + k < satoffset[s + 1]; ++k) {
+         same convention as the MSM satellite mask that shares this field.
+         All 64 bits count: a satellite beyond the number supported for this
+         system still has its own block on the wire (DF+016 unset), which
+         must be read to stay aligned - it is marked UINT_MAX and discarded. */
+      for (k = 0; k < 64; ++k) {
         if ((a->SatelliteMask[s] >> (63 - k)) & 1ULL)
-          satPositions[numSatPositions++] = satoffset[s] + k;
+          satPositions[numSatPositions++] =
+            (satoffset[s] + k < satoffset[s + 1]) ? satoffset[s] + k : UINT_MAX;
       }
       numSatBlocks = a->SatelliteSetIndicator[s] ? (numSatPositions ? 1 : 0) : numSatPositions;
@@ -1241,5 +1259,6 @@
           fprintf(stderr, " sat block (shared, PRNs");
           for (k = 0; k < numSatPositions; ++k)
-            fprintf(stderr, " %d", satPositions[k] - satoffset[s] + 1);
+            if (satPositions[k] != UINT_MAX)
+              fprintf(stderr, " %d", satPositions[k] - satoffset[s] + 1);
           fprintf(stderr, ") freqSetInd %d freqMask %02x\n",
             satBlock.FrequencySetIndicator, satBlock.GnssFrequencyMask);
@@ -1247,5 +1266,5 @@
         else {
           fprintf(stderr, " sat block PRN %d freqSetInd %d freqMask %02x\n",
-            satPositions[satBlockIdx] - satoffset[s] + 1,
+            satPositions[satBlockIdx] != UINT_MAX ? (int)(satPositions[satBlockIdx] - satoffset[s] + 1) : -1,
             satBlock.FrequencySetIndicator, satBlock.GnssFrequencyMask);
         }
@@ -1267,7 +1286,13 @@
             D_NADIR_CORRECTION(satBlock.Freq[f].NadirCorrection)
           if (a->NadirAngleDependentCorrectionIndicator[s]) {
-            for (deg = 0; deg <= a->maximumOffNadirAngle[s] && deg < ANT_MAXNADIRDEGREES; ++deg)
-              D_NADIR_ANGLE_DEPENDENT_CORRECTION(satBlock.Freq[f].NadirAngleCorrection[deg],
-                a->NadirAngleDependentCorrectionRangeExtension[s])
+            /* DF+021: int(3 + DF+015) in mm; the minimum value -2^(n-1)
+               means "invalid" and is stored as NaN */
+            unsigned int nb = 3 + a->NadirAngleDependentCorrectionRangeExtension[s];
+            for (deg = 0; deg <= a->maximumOffNadirAngle[s] && deg < ANT_MAXNADIRDEGREES; ++deg) {
+              double raw;
+              GETSSRFLOATSIGN(raw, nb, 1.0)
+              satBlock.Freq[f].NadirAngleCorrection[deg] =
+                (raw == -ldexp(1.0, nb - 1)) ? NAN : raw / 1000.0;
+            }
           }
 #ifdef BNC_DEBUG_SSR
@@ -1288,7 +1313,8 @@
         if (a->SatelliteSetIndicator[s]) {
           for (k = 0; k < numSatPositions; ++k)
-            a->Sat[satPositions[k]] = satBlock;
-        }
-        else {
+            if (satPositions[k] != UINT_MAX)
+              a->Sat[satPositions[k]] = satBlock;
+        }
+        else if (satPositions[satBlockIdx] != UINT_MAX) {
           a->Sat[satPositions[satBlockIdx]] = satBlock;
         }
@@ -1296,5 +1322,5 @@
     }
     else {
-      /* COBOFS_SATANT / COBOFS_REGIONO: message numbers are
+      /* COBOFS_REGIONO: message numbers are
          recognized (see setCorType()) but decoding is not implemented yet */
       return GCOBR_UNKNOWNTYPE;
@@ -1522,7 +1548,9 @@
     if (freqIndex == 0) return "C2"; // B1
     if (freqIndex == 1) return "C6"; // B3
-    if (freqIndex == 2) return "C7"; // B2
-    if (freqIndex == 3) return "C5"; // B2a
-    if (freqIndex == 4) return "C7"; // B2b (same t_frequency::type as B2)
+    if (freqIndex == 2) return "C7";  // B2  (BDS-2)
+    if (freqIndex == 3) return "C5";  // B2a
+    if (freqIndex == 4) return "C7b"; // B2b (BDS-3) - same carrier and t_frequency::type as B2,
+                                      // own label so that PPP can select by satellite generation
+                                      // (see t_pppSatObs::cmpModel())
     if (freqIndex == 5) return "C1"; // B1C
     break;
