Index: trunk/BNC/src/rinex/corrfile.cpp
===================================================================
--- trunk/BNC/src/rinex/corrfile.cpp	(revision 11036)
+++ trunk/BNC/src/rinex/corrfile.cpp	(revision 11037)
@@ -124,4 +124,9 @@
       emit newMetaData(metaData);
     }
+    else if (corrType == t_corrSSR::satAntenna) {
+      QList<t_satAntenna> satAntennaList;
+      t_satAntenna::readEpoch(_lastLine, _stream, satAntennaList);
+      emit newSatAntennas(satAntennaList);
+    }
 
     _lastLine.clear();
Index: trunk/BNC/src/rinex/corrfile.h
===================================================================
--- trunk/BNC/src/rinex/corrfile.h	(revision 11036)
+++ trunk/BNC/src/rinex/corrfile.h	(revision 11037)
@@ -49,4 +49,5 @@
   void newTec(t_vTec);
   void newMetaData(t_metaData);
+  void newSatAntennas(QList<t_satAntenna>);
 
  private:
Index: trunk/BNC/src/satObs.cpp
===================================================================
--- trunk/BNC/src/satObs.cpp	(revision 11036)
+++ trunk/BNC/src/satObs.cpp	(revision 11037)
@@ -493,4 +493,99 @@
 //
 ////////////////////////////////////////////////////////////////////////////
+void t_satAntenna::writeEpoch(ostream* out, const QList<t_satAntenna>& antList) {
+  if (!out || antList.size() == 0) {
+    return;
+  }
+  out->setf(ios::fixed);
+  bncTime epoTime;
+  QListIterator<t_satAntenna> it(antList);
+  while (it.hasNext()) {
+    const t_satAntenna& satAntenna = it.next();
+    if (!epoTime.valid()) {
+      epoTime = satAntenna._time;
+      *out << "> SAT_ANTENNA " << epoTime.datestr(' ') << ' ' << epoTime.timestr(1, ' ') << " "
+        << 0 << " " << antList.size() << ' ' << satAntenna._staID << endl;
+    }
+    // header fields are genuinely per system (e.g. GPS/GLONASS/Galileo carry
+    // different maximumOffNadirAngle), so they are written per satellite
+    // rather than once per epoch like t_satPhaseBias's metadata line
+    *out << satAntenna._prn.toString() << ' '
+      << setw(4) << satAntenna._ssrProviderID << ' '
+      << setw(2) << satAntenna._satelliteAntennaIOD << ' '
+      << setw(1) << satAntenna._phaseCenterInfoInd << ' '
+      << setw(1) << satAntenna._groupDelayInfoInd << ' '
+      << setw(1) << satAntenna._nadirAngleDependentCorrInd << ' '
+      << setw(2) << satAntenna._maximumOffNadirAngle << ' '
+      << setw(2) << satAntenna._nadirAngleRangeExtension << "   "
+      << setw(2) << satAntenna._freq.size();
+    for (unsigned ii = 0; ii < satAntenna._freq.size(); ii++) {
+      const t_frqAntenna& frqAntenna = satAntenna._freq[ii];
+      *out << "   " << frqAntenna._freqIndex << ' '
+        << frqAntenna._nadirCorrectionIndicator << ' '
+        << setw(10) << setprecision(4) << frqAntenna._nadirCorrection;
+      for (unsigned jj = 0; jj < frqAntenna._nadirAngleCorrection.size(); jj++) {
+        *out << ' ' << setw(9) << setprecision(4) << frqAntenna._nadirAngleCorrection[jj];
+      }
+    }
+    *out << endl;
+  }
+  out->flush();
+}
+
+//
+////////////////////////////////////////////////////////////////////////////
+void t_satAntenna::readEpoch(const string& epoLine, istream& inStream, QList<t_satAntenna>& antList) {
+  bncTime epoTime;
+  unsigned int updateInt;
+  int numSat;
+  string staID;
+  if (t_corrSSR::readEpoLine(epoLine, epoTime, updateInt, numSat, staID) != t_corrSSR::satAntenna) {
+    return;
+  }
+  for (int ii = 0; ii < numSat; ii++) {
+    t_satAntenna satAntenna;
+    satAntenna._time = epoTime;
+    satAntenna._staID = staID;
+
+    string line;
+    getline(inStream, line);
+    istringstream in(line.c_str());
+
+    int numFreq;
+    in >> satAntenna._prn
+       >> satAntenna._ssrProviderID
+       >> satAntenna._satelliteAntennaIOD
+       >> satAntenna._phaseCenterInfoInd
+       >> satAntenna._groupDelayInfoInd
+       >> satAntenna._nadirAngleDependentCorrInd
+       >> satAntenna._maximumOffNadirAngle
+       >> satAntenna._nadirAngleRangeExtension
+       >> numFreq;
+
+    char sys = satAntenna._prn.system();
+    int num = satAntenna._prn.number();
+    int flag = t_corrSSR::getSsrNavTypeFlag(sys, num);
+    satAntenna._prn.setFlag(flag);
+
+    unsigned int numAngles = satAntenna._nadirAngleDependentCorrInd ?
+                              satAntenna._maximumOffNadirAngle + 1 : 0;
+
+    for (int jj = 0; jj < numFreq; jj++) {
+      t_frqAntenna frqAntenna;
+      in >> frqAntenna._freqIndex >> frqAntenna._nadirCorrectionIndicator >> frqAntenna._nadirCorrection;
+      for (unsigned kk = 0; kk < numAngles; kk++) {
+        double val;
+        in >> val;
+        frqAntenna._nadirAngleCorrection.push_back(val);
+      }
+      satAntenna._freq.push_back(frqAntenna);
+    }
+
+    antList.push_back(satAntenna);
+  }
+}
+
+//
+////////////////////////////////////////////////////////////////////////////
 void t_metaData::write(ostream* out, const t_metaData& md) {
   if (!out || md._entries.size() == 0) {
@@ -582,4 +677,7 @@
     else if (typeString == "META_DATA") {
       return metaData;
+    }
+    else if (typeString == "SAT_ANTENNA") {
+      return satAntenna;
     }
   }
Index: trunk/BNC/src/satObs.h
===================================================================
--- trunk/BNC/src/satObs.h	(revision 11036)
+++ trunk/BNC/src/satObs.h	(revision 11037)
@@ -280,7 +280,46 @@
 };
 
+class t_frqAntenna {
+ public:
+  t_frqAntenna() {
+    _freqIndex                = 0;
+    _nadirCorrectionIndicator = false;
+    _nadirCorrection          = 0.0;
+  }
+  unsigned int        _freqIndex; // 0 .. ANT_MAXFREQUENCIES-1, DF+018 bit position
+  bool                _nadirCorrectionIndicator;
+  double              _nadirCorrection;      // m, only valid if _nadirCorrectionIndicator
+  std::vector<double> _nadirAngleCorrection; // m, one entry per nadir angle bin
+};
+
+class t_satAntenna {
+ public:
+  t_satAntenna() {
+    _ssrProviderID              = 0;
+    _satelliteAntennaIOD        = 0;
+    _phaseCenterInfoInd         = false;
+    _groupDelayInfoInd          = false;
+    _nadirAngleDependentCorrInd = false;
+    _maximumOffNadirAngle       = 0;
+    _nadirAngleRangeExtension   = 0;
+  }
+  static void writeEpoch(std::ostream* out, const QList<t_satAntenna>& antList);
+  static void readEpoch(const std::string& epoLine, std::istream& in, QList<t_satAntenna>& antList);
+  std::string               _staID;
+  t_prn                     _prn;
+  bncTime                   _time;                       // time this message was decoded (no epoch field on the wire)
+  unsigned int               _ssrProviderID;              // not satellite specific
+  unsigned int               _satelliteAntennaIOD;        // not satellite specific; unique per provider within a 64-day window
+  bool                       _phaseCenterInfoInd;         // not satellite specific
+  bool                       _groupDelayInfoInd;          // not satellite specific
+  bool                       _nadirAngleDependentCorrInd; // not satellite specific
+  unsigned int               _maximumOffNadirAngle;       // not satellite specific
+  unsigned int               _nadirAngleRangeExtension;   // not satellite specific
+  std::vector<t_frqAntenna> _freq;
+};
+
 class t_corrSSR {
  public:
-  enum e_type {clkCorr, orbCorr, codeBias, phaseBias, vTec, URA, metaData, unknown};
+  enum e_type {clkCorr, orbCorr, codeBias, phaseBias, vTec, URA, metaData, satAntenna, unknown};
   static e_type readEpoLine(const std::string& line, bncTime& epoTime,
                             unsigned int& updateInt, int& numEntries, std::string& staID);
