Index: trunk/BNC/src/RTCM3/RTCM3Decoder.cpp
===================================================================
--- trunk/BNC/src/RTCM3/RTCM3Decoder.cpp	(revision 8782)
+++ trunk/BNC/src/RTCM3/RTCM3Decoder.cpp	(revision 8783)
@@ -421,4 +421,44 @@
     };
 
+/**
+ * MSM signal types for IRNSS
+ *
+ * NOTE: Uses 0.0, 1.0 for wavelength as sat index dependence is done later!
+ */
+static struct CodeData irn[RTCM3_MSM_NUMSIG] = {
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {IRNSS_WAVELENGTH_S, "9A"},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {IRNSS_WAVELENGTH_L5, "5A"},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0},
+        {0.0, 0}
+    };
+
 #define UINT64(c) c ## ULL
 
@@ -438,5 +478,5 @@
   /* id */
   char sys;
-  if (type >= 1121)
+  if      (type >= 1121)
     sys = 'C';
   else if (type >= 1111)
@@ -448,9 +488,11 @@
   else if (type >= 1081)
     sys = 'R';
-  else
+  else if (type >= 1071)
     sys = 'G';
+  else if (type >=   21) // test
+    sys = 'I';
 
   bncTime CurrentObsTime;
-  if (sys == 'C') /* BDS */ {
+  if      (sys == 'C') /* BDS */ {
     GETBITS(i, 30)
     CurrentObsTime.setBDS(i);
@@ -700,4 +742,7 @@
               cd = gal[RTCM3_MSM_NUMSIG - j - 1];
               break;
+            case 'I':
+              cd = irn[RTCM3_MSM_NUMSIG - j - 1];
+              break;
           }
           if (cd.code) {
@@ -1002,18 +1047,15 @@
     i <<= 4;
     eph._TOC.set(i * 1000);
-    GETFLOATSIGN(eph._clock_driftrate, 8,
-        1.0 / (double )(1 << 30) / (double )(1 << 25))
-    GETFLOATSIGN(eph._clock_drift, 16,
-        1.0 / (double )(1 << 30) / (double )(1 << 13))
-    GETFLOATSIGN(eph._clock_bias, 22,
-        1.0 / (double )(1 << 30) / (double )(1 << 1))
+    GETFLOATSIGN(eph._clock_driftrate, 8, 1.0 / (double )(1 << 30) / (double )(1 << 25))
+    GETFLOATSIGN(eph._clock_drift,    16, 1.0 / (double )(1 << 30) / (double )(1 << 13))
+    GETFLOATSIGN(eph._clock_bias,     22, 1.0 / (double )(1 << 30) / (double )(1 << 1))
     GETBITS(eph._IODC, 10)
-    GETFLOATSIGN(eph._Crs, 16, 1.0 / (double )(1 << 5))
-    GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
-    GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Cuc, 16, 1.0 / (double )(1 << 29))
-    GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
-    GETFLOATSIGN(eph._Cus, 16, 1.0 / (double )(1 << 29))
-    GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
+    GETFLOATSIGN(eph._Crs,            16, 1.0 / (double )(1 << 5))
+    GETFLOATSIGN(eph._Delta_n,        16, R2R_PI/(double)(1<<30)/(double)(1<<13))
+    GETFLOATSIGN(eph._M0,             32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cuc,            16, 1.0 / (double )(1 << 29))
+    GETFLOAT(eph._e,                  32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
+    GETFLOATSIGN(eph._Cus,            16, 1.0 / (double )(1 << 29))
+    GETFLOAT(eph._sqrt_A,             32, 1.0 / (double )(1 << 19))
     GETBITS(i, 16)
     i <<= 4;
@@ -1027,12 +1069,12 @@
     if (eph._TOEweek > week + 1 || eph._TOEweek < week - 1) /* invalid week */
       return false;
-    GETFLOATSIGN(eph._Cic, 16, 1.0 / (double )(1 << 29))
-    GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Cis, 16, 1.0 / (double )(1 << 29))
-    GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Crc, 16, 1.0 / (double )(1 << 5))
-    GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cic,      16, 1.0 / (double )(1 << 29))
+    GETFLOATSIGN(eph._OMEGA0,   32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cis,      16, 1.0 / (double )(1 << 29))
+    GETFLOATSIGN(eph._i0,       32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Crc,      16, 1.0 / (double )(1 << 5))
+    GETFLOATSIGN(eph._omega,    32, R2R_PI/(double)(1<<30)/(double)(1<<1))
     GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
-    GETFLOATSIGN(eph._TGD, 8, 1.0 / (double )(1 << 30) / (double )(1 << 1))
+    GETFLOATSIGN(eph._TGD,       8, 1.0 / (double )(1 << 30) / (double )(1 << 1))
     GETBITS(eph._health, 6)
     GETBITS(eph._L2PFlag, 1)
@@ -1082,30 +1124,30 @@
     eph._TOC.setTk(i * 15 * 60 * 1000); /* tb */
 
-    GETFLOATSIGNM(eph._x_velocity, 24, 1.0 / (double )(1 << 20))
-    GETFLOATSIGNM(eph._x_pos, 27, 1.0 / (double )(1 << 11))
+    GETFLOATSIGNM(eph._x_velocity,    24, 1.0 / (double )(1 << 20))
+    GETFLOATSIGNM(eph._x_pos,         27, 1.0 / (double )(1 << 11))
     GETFLOATSIGNM(eph._x_acceleration, 5, 1.0 / (double )(1 << 30))
-    GETFLOATSIGNM(eph._y_velocity, 24, 1.0 / (double )(1 << 20))
-    GETFLOATSIGNM(eph._y_pos, 27, 1.0 / (double )(1 << 11))
+    GETFLOATSIGNM(eph._y_velocity,    24, 1.0 / (double )(1 << 20))
+    GETFLOATSIGNM(eph._y_pos,         27, 1.0 / (double )(1 << 11))
     GETFLOATSIGNM(eph._y_acceleration, 5, 1.0 / (double )(1 << 30))
-    GETFLOATSIGNM(eph._z_velocity, 24, 1.0 / (double )(1 << 20))
-    GETFLOATSIGNM(eph._z_pos, 27, 1.0 / (double )(1 << 11))
+    GETFLOATSIGNM(eph._z_velocity,    24, 1.0 / (double )(1 << 20))
+    GETFLOATSIGNM(eph._z_pos,         27, 1.0 / (double )(1 << 11))
     GETFLOATSIGNM(eph._z_acceleration, 5, 1.0 / (double )(1 << 30))
 
     GETBITS(eph._P3, 1)    /* P3 */
-    GETFLOATSIGNM(eph._gamma, 11, 1.0 / (double )(1 << 30) / (double )(1 << 10))
-    GETBITS(eph._M_P, 2) /* GLONASS-M P, */
+    GETFLOATSIGNM(eph._gamma,      11, 1.0 / (double )(1 << 30) / (double )(1 << 10))
+    GETBITS(eph._M_P,  2) /* GLONASS-M P, */
     GETBITS(eph._M_l3, 1) /*GLONASS-M ln (third string) */
-    GETFLOATSIGNM(eph._tau, 22, 1.0 / (double )(1 << 30))    /* GLONASS tau n(tb) */
+    GETFLOATSIGNM(eph._tau,        22, 1.0 / (double )(1 << 30))    /* GLONASS tau n(tb) */
     GETFLOATSIGNM(eph._M_delta_tau, 5, 1.0 / (double )(1 << 30))  /* GLONASS-M delta tau n(tb) */
     GETBITS(eph._E, 5)
-    GETBITS(eph._M_P4, 1) /* GLONASS-M P4 */
-    GETBITS(eph._M_FT, 4) /* GLONASS-M Ft */
+    GETBITS(eph._M_P4,  1) /* GLONASS-M P4 */
+    GETBITS(eph._M_FT,  4) /* GLONASS-M Ft */
     GETBITS(eph._M_NT, 11) /* GLONASS-M Nt */
-    GETBITS(eph._M_M, 2) /* GLONASS-M M */
+    GETBITS(eph._M_M,   2) /* GLONASS-M M */
     GETBITS(eph._additional_data_availability, 1) /* GLONASS-M The Availability of Additional Data */
-    GETBITS(eph._NA, 11) /* GLONASS-M Na */
-    GETFLOATSIGNM(eph._tauC, 32, 1.0/(double)(1<<30)/(double)(1<<1)) /* GLONASS tau c */
+    GETBITS(eph._NA,  11) /* GLONASS-M Na */
+    GETFLOATSIGNM(eph._tauC,       32, 1.0/(double)(1<<30)/(double)(1<<1)) /* GLONASS tau c */
     GETBITS(eph._M_N4, 5) /* GLONASS-M N4 */
-    GETFLOATSIGNM(eph._M_tau_GPS, 22, 1.0/(double)(1<<30)) /* GLONASS-M tau GPS */
+    GETFLOATSIGNM(eph._M_tau_GPS,  22, 1.0/(double)(1<<30)) /* GLONASS-M tau GPS */
     GETBITS(eph._M_l5, 1) /* GLONASS-M ln (fifth string) */
 
@@ -1114,5 +1156,5 @@
     eph._gps_utc = gnumleap(year, month, day);
     eph._tt = eph._TOC;
-    
+
     eph._xv(1) = eph._x_pos * 1.e3;
     eph._xv(2) = eph._y_pos * 1.e3;
@@ -1154,18 +1196,15 @@
     eph._TOC.set(i * 1000);
 
-    GETFLOATSIGN(eph._clock_driftrate, 8,
-        1.0 / (double )(1 << 30) / (double )(1 << 25))
-    GETFLOATSIGN(eph._clock_drift, 16,
-        1.0 / (double )(1 << 30) / (double )(1 << 13))
-    GETFLOATSIGN(eph._clock_bias, 22,
-        1.0 / (double )(1 << 30) / (double )(1 << 1))
+    GETFLOATSIGN(eph._clock_driftrate, 8, 1.0 / (double )(1 << 30) / (double )(1 << 25))
+    GETFLOATSIGN(eph._clock_drift,    16, 1.0 / (double )(1 << 30) / (double )(1 << 13))
+    GETFLOATSIGN(eph._clock_bias,     22, 1.0 / (double )(1 << 30) / (double )(1 << 1))
     GETBITS(eph._IODE, 8)
-    GETFLOATSIGN(eph._Crs, 16, 1.0 / (double )(1 << 5))
+    GETFLOATSIGN(eph._Crs,     16, 1.0 / (double )(1 << 5))
     GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
-    GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Cuc, 16, 1.0 / (double )(1 << 29))
-    GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
-    GETFLOATSIGN(eph._Cus, 16, 1.0 / (double )(1 << 29))
-    GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
+    GETFLOATSIGN(eph._M0,      32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cuc,     16, 1.0 / (double )(1 << 29))
+    GETFLOAT(eph._e,           32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
+    GETFLOATSIGN(eph._Cus,     16, 1.0 / (double )(1 << 29))
+    GETFLOAT(eph._sqrt_A,      32, 1.0 / (double )(1 << 19))
     GETBITS(i, 16)
     i <<= 4;
@@ -1174,12 +1213,12 @@
     t.set(i*1000);
     eph._TOEweek = t.gpsw();
-    GETFLOATSIGN(eph._Cic, 16, 1.0 / (double )(1 << 29))
-    GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Cis, 16, 1.0 / (double )(1 << 29))
-    GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Crc, 16, 1.0 / (double )(1 << 5))
-    GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cic,      16, 1.0 / (double )(1 << 29))
+    GETFLOATSIGN(eph._OMEGA0,   32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cis,      16, 1.0 / (double )(1 << 29))
+    GETFLOATSIGN(eph._i0,       32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Crc,      16, 1.0 / (double )(1 << 5))
+    GETFLOATSIGN(eph._omega,    32, R2R_PI/(double)(1<<30)/(double)(1<<1))
     GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
-    GETFLOATSIGN(eph._IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
+    GETFLOATSIGN(eph._IDOT,     14, R2R_PI/(double)(1<<30)/(double)(1<<13))
     GETBITS(eph._L2Codes, 2)
     GETBITS(week, 10)
@@ -1196,9 +1235,90 @@
       eph._ura = ceil(10.0 * pow(2.0, i / 2.0)) / 10.0;
     GETBITS(eph._health, 6)
-    GETFLOATSIGN(eph._TGD, 8, 1.0 / (double )(1 << 30) / (double )(1 << 1))
+    GETFLOATSIGN(eph._TGD,       8, 1.0 / (double )(1 << 30) / (double )(1 << 1))
     GETBITS(eph._IODC, 10)
     GETBITS(eph._fitInterval, 1)
     eph._TOT = 0.9999e9;
-    eph._L2PFlag = 0; /* does not exist for QZSS */
+
+    emit newGPSEph(eph);
+    decoded = true;
+  }
+  return decoded;
+}
+
+//
+////////////////////////////////////////////////////////////////////////////
+bool RTCM3Decoder::DecodeIRNSSEphemeris(unsigned char* data, int size) {
+  bool decoded = false;
+
+  if (size == 67) {
+    t_ephGPS eph;
+    int i, week, L5Flag, SFlag;
+    uint64_t numbits = 0, bitfield = 0;
+
+    data += 3; /* header */
+    size -= 6; /* header + crc */
+    SKIPBITS(12)
+
+    eph._receptDateTime = currentDateAndTimeGPS();
+
+    GETBITS(i, 6)
+    eph._prn.set('I', i);
+    GETBITS(week, 10)
+    GETFLOATSIGN(eph._clock_bias,     22, 1.0 / (double )(1 << 30) / (double )(1 << 1))
+    GETFLOATSIGN(eph._clock_drift,    16, 1.0 / (double )(1 << 30) / (double )(1 << 13))
+    GETFLOATSIGN(eph._clock_driftrate, 8, 1.0 / (double )(1 << 30) / (double )(1 << 25))
+    GETBITS(i, 4)
+    eph._ura = accuracyFromIndex(i, eph.type());
+    GETBITS(i, 16)
+    i <<= 4;
+    eph._TOC.set(i * 1000);
+    GETFLOATSIGN(eph._TGD, 8, 1.0 / (double )(1 << 30) / (double )(1 <<  1))
+    GETFLOATSIGN(eph._Delta_n, 22, R2R_PI/(double)(1<<30)/(double)(1 << 11))
+    // IODCE
+    GETBITS(eph._IODE, 8)
+    eph._IODC = eph._IODE;
+    SKIPBITS(10)
+    GETBITS(L5Flag, 1)
+    GETBITS(SFlag, 1)
+    if      (L5Flag == 0 && SFlag == 0) {
+      eph._health = 0.0;
+    }
+    else if (L5Flag == 0 && SFlag == 1) {
+      eph._health = 1.0;
+    }
+    else if (L5Flag == 1 && SFlag == 0) {
+      eph._health = 2.0;
+    }
+    else if (L5Flag == 1 && SFlag == 1) {
+      eph._health = 3.0;
+    }
+    GETFLOATSIGN(eph._Cuc,  15, 1.0 / (double )(1 << 28))
+    GETFLOATSIGN(eph._Cus,  15, 1.0 / (double )(1 << 28))
+    GETFLOATSIGN(eph._Cic,  15, 1.0 / (double )(1 << 28))
+    GETFLOATSIGN(eph._Cis,  15, 1.0 / (double )(1 << 28))
+    GETFLOATSIGN(eph._Crc,  15, 1.0 / (double )(1 <<  4))
+    GETFLOATSIGN(eph._Crs,  15, 1.0 / (double )(1 <<  4))
+    GETFLOATSIGN(eph._IDOT, 14, R2R_PI/(double)(1<<30)/(double)(1<<13))
+    GETFLOATSIGN(eph._M0,   32, R2R_PI/(double)(1<<30)/(double)(1<< 1))
+    GETBITS(i, 16)
+    i <<= 4;
+    eph._TOEsec = i;
+    bncTime t;
+    t.set(i * 1000);
+    eph._TOEweek = t.gpsw();
+    int numOfRollOvers = int(floor(t.gpsw()/1024.0));
+    week += (numOfRollOvers * 1024);
+    /* week from HOW, differs from TOC, TOE week, we use adapted value instead */
+    if (eph._TOEweek > week + 1 || eph._TOEweek < week - 1) /* invalid week */
+      return false;
+    GETFLOAT(eph._e,            32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
+    GETFLOAT(eph._sqrt_A,       32, 1.0 / (double )(1 << 19))
+    GETFLOATSIGN(eph._OMEGA0,   32, R2R_PI/(double)(1<<30)/(double)(1<< 1))
+    GETFLOATSIGN(eph._omega,    32, R2R_PI/(double)(1<<30)/(double)(1<< 1))
+    GETFLOATSIGN(eph._OMEGADOT, 22, R2R_PI/(double)(1<<30)/(double)(1<<11))
+    GETFLOATSIGN(eph._i0,       32, R2R_PI/(double)(1<<30)/(double)(1<< 1))
+    SKIPBITS(2)
+    SKIPBITS(2)
+    eph._TOT = 0.9999e9;
 
     emit newGPSEph(eph);
@@ -1274,5 +1394,5 @@
     eph._prn.set('E', i, eph._inav ? 1 : 0);
 
-    GETBITS(eph._TOEweek, 12)
+    GETBITS(eph._TOEweek, 12) //FIXME: roll-over after week 4095!!
     GETBITS(eph._IODnav, 10)
     GETBITS(i, 8)
@@ -1281,26 +1401,23 @@
     GETBITSFACTOR(i, 14, 60)
     eph._TOC.set(1024 + eph._TOEweek, i);
-    GETFLOATSIGN(eph._clock_driftrate, 6,
-        1.0 / (double )(1 << 30) / (double )(1 << 29))
-    GETFLOATSIGN(eph._clock_drift, 21,
-        1.0 / (double )(1 << 30) / (double )(1 << 16))
-    GETFLOATSIGN(eph._clock_bias, 31,
-        1.0 / (double )(1 << 30) / (double )(1 << 4))
-    GETFLOATSIGN(eph._Crs, 16, 1.0 / (double )(1 << 5))
-    GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
-    GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Cuc, 16, 1.0 / (double )(1 << 29))
-    GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
-    GETFLOATSIGN(eph._Cus, 16, 1.0 / (double )(1 << 29))
-    GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
+    GETFLOATSIGN(eph._clock_driftrate, 6, 1.0 / (double )(1 << 30) / (double )(1 << 29))
+    GETFLOATSIGN(eph._clock_drift,    21, 1.0 / (double )(1 << 30) / (double )(1 << 16))
+    GETFLOATSIGN(eph._clock_bias,     31, 1.0 / (double )(1 << 30) / (double )(1 << 4))
+    GETFLOATSIGN(eph._Crs,            16, 1.0 / (double )(1 << 5))
+    GETFLOATSIGN(eph._Delta_n,        16, R2R_PI/(double)(1<<30)/(double)(1<<13))
+    GETFLOATSIGN(eph._M0,             32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cuc,            16, 1.0 / (double )(1 << 29))
+    GETFLOAT(eph._e,                  32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
+    GETFLOATSIGN(eph._Cus,            16, 1.0 / (double )(1 << 29))
+    GETFLOAT(eph._sqrt_A,             32, 1.0 / (double )(1 << 19))
     GETBITSFACTOR(eph._TOEsec, 14, 60)
     /* FIXME: overwrite value, copied from old code */
     eph._TOEsec = eph._TOC.gpssec();
-    GETFLOATSIGN(eph._Cic, 16, 1.0 / (double )(1 << 29))
-    GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Cis, 16, 1.0 / (double )(1 << 29))
-    GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Crc, 16, 1.0 / (double )(1 << 5))
-    GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cic,      16, 1.0 / (double )(1 << 29))
+    GETFLOATSIGN(eph._OMEGA0,   32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cis,      16, 1.0 / (double )(1 << 29))
+    GETFLOATSIGN(eph._i0,       32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Crc,      16, 1.0 / (double )(1 << 5))
+    GETFLOATSIGN(eph._omega,    32, R2R_PI/(double)(1<<30)/(double)(1<<1))
     GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
     GETFLOATSIGN(eph._BGD_1_5A, 10,
@@ -1311,6 +1428,5 @@
       eph._e5aDataInValid = false;
 
-      GETFLOATSIGN(eph._BGD_1_5B, 10,
-          1.0 / (double )(1 << 30) / (double )(1 << 2))
+      GETFLOATSIGN(eph._BGD_1_5B, 10, 1.0 / (double )(1 << 30) / (double )(1 << 2))
       GETBITS(eph._E5bHS, 2)
       GETBITS(eph._e5bDataInValid, 1)
@@ -1365,31 +1481,28 @@
     i <<= 3;
     eph._TOC.setBDS(i * 1000);
-    GETFLOATSIGN(eph._clock_driftrate, 11,
-        1.0 / (double )(1 << 30) / (double )(1 << 30) / (double )(1 << 6))
-    GETFLOATSIGN(eph._clock_drift, 22,
-        1.0 / (double )(1 << 30) / (double )(1 << 20))
-    GETFLOATSIGN(eph._clock_bias, 24,
-        1.0 / (double )(1 << 30) / (double )(1 << 3))
+    GETFLOATSIGN(eph._clock_driftrate, 11,  1.0 / (double )(1 << 30) / (double )(1 << 30) / (double )(1 << 6))
+    GETFLOATSIGN(eph._clock_drift,     22,  1.0 / (double )(1 << 30) / (double )(1 << 20))
+    GETFLOATSIGN(eph._clock_bias,      24,  1.0 / (double )(1 << 30) / (double )(1 << 3))
     GETBITS(eph._AODC, 5)
-    GETFLOATSIGN(eph._Crs, 18, 1.0 / (double )(1 << 6))
+    GETFLOATSIGN(eph._Crs,     18, 1.0 / (double )(1 << 6))
     GETFLOATSIGN(eph._Delta_n, 16, R2R_PI/(double)(1<<30)/(double)(1<<13))
-    GETFLOATSIGN(eph._M0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Cuc, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
-    GETFLOAT(eph._e, 32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
-    GETFLOATSIGN(eph._Cus, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
-    GETFLOAT(eph._sqrt_A, 32, 1.0 / (double )(1 << 19))
+    GETFLOATSIGN(eph._M0,      32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cuc,     18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
+    GETFLOAT(eph._e,           32, 1.0 / (double )(1 << 30) / (double )(1 << 3))
+    GETFLOATSIGN(eph._Cus,     18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
+    GETFLOAT(eph._sqrt_A,      32, 1.0 / (double )(1 << 19))
     GETBITS(i, 17)
     i <<= 3;
     eph._TOEsec = i;
     eph._TOE.setBDS(i * 1000);
-    GETFLOATSIGN(eph._Cic, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
-    GETFLOATSIGN(eph._OMEGA0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Cis, 18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
-    GETFLOATSIGN(eph._i0, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
-    GETFLOATSIGN(eph._Crc, 18, 1.0 / (double )(1 << 6))
-    GETFLOATSIGN(eph._omega, 32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cic,      18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
+    GETFLOATSIGN(eph._OMEGA0,   32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Cis,      18, 1.0 / (double )(1 << 30) / (double )(1 << 1))
+    GETFLOATSIGN(eph._i0,       32, R2R_PI/(double)(1<<30)/(double)(1<<1))
+    GETFLOATSIGN(eph._Crc,      18, 1.0 / (double )(1 << 6))
+    GETFLOATSIGN(eph._omega,    32, R2R_PI/(double)(1<<30)/(double)(1<<1))
     GETFLOATSIGN(eph._OMEGADOT, 24, R2R_PI/(double)(1<<30)/(double)(1<<13))
-    GETFLOATSIGN(eph._TGD1, 10, 0.0000000001)
-    GETFLOATSIGN(eph._TGD2, 10, 0.0000000001)
+    GETFLOATSIGN(eph._TGD1,     10, 0.0000000001)
+    GETFLOATSIGN(eph._TGD2,     10, 0.0000000001)
     GETBITS(eph._SatH1, 1)
 
@@ -1529,5 +1642,6 @@
         }
       }
-      else if (id >= 1070 && id <= 1229) /* MSM */ {
+      else if ((id >= 1070 && id <= 1229) ||
+               (id >=   21 && id <=   27)) /* MSM */ {
         if (DecodeRTCM3MSM(_Message, _BlockSize))
           decoded = true;
@@ -1573,4 +1687,8 @@
               decoded = true;
             break;
+          case 29:
+            if (DecodeIRNSSEphemeris(_Message, _BlockSize))
+              decoded = true;
+            break;
           case 1045:
           case 1046:
Index: trunk/BNC/src/RTCM3/RTCM3Decoder.h
===================================================================
--- trunk/BNC/src/RTCM3/RTCM3Decoder.h	(revision 8782)
+++ trunk/BNC/src/RTCM3/RTCM3Decoder.h	(revision 8783)
@@ -132,4 +132,11 @@
   bool DecodeQZSSEphemeris(unsigned char* buffer, int bufLen);
   /**
+   * Extract ephemeris data from 29 (allocated for testing) RTCM3 messages.
+   * @param buffer the buffer containing an 29 RTCM block
+   * @param bufLen the length of the buffer (the message length including header+crc)
+   * @return <code>true</code> when data block was decodable
+   */
+  bool DecodeIRNSSEphemeris(unsigned char* buffer, int bufLen);
+  /**
    * Extract ephemeris data from 1045 and 1046 RTCM3 messages.
    * @param buffer the buffer containing an 1045 and 1046 RTCM block
Index: trunk/BNC/src/RTCM3/gnss.h
===================================================================
--- trunk/BNC/src/RTCM3/gnss.h	(revision 8782)
+++ trunk/BNC/src/RTCM3/gnss.h	(revision 8783)
@@ -70,4 +70,9 @@
 #define BDS_WAVELENGTH_B3  (LIGHTSPEED / BDS_FREQU_B3) /* m */
 
+#define IRNSS_FREQU_L5     1176450000.0 /* Hz */
+#define IRNSS_FREQU_S      2492028000.0 /* Hz */
+#define IRNSS_WAVELENGTH_L5 (LIGHTSPEED / IRNSS_FREQU_L5) /* m */
+#define IRNSS_WAVELENGTH_S  (LIGHTSPEED / IRNSS_FREQU_S)  /* m */
+
 #define R2R_PI          3.1415926535898
 
