Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Revision:
3:24c5f0f50bf1
Parent:
1:e392595b4b76
Child:
4:a91682e19d6b
--- a/SnConfigFrame.h	Tue Jul 24 02:07:23 2012 +0000
+++ b/SnConfigFrame.h	Tue Jul 31 04:59:16 2012 +0000
@@ -1,298 +1,347 @@
-#ifndef SN_SnConfigFrame
-#define SN_SnConfigFrame
-
-#include <stdint.h>
-#include "SnConstants.h"
-#include "SnBitUtils.h"
-
-class SnConfigFrame {
- public:
-    static const uint32_t    kMinCommWinPrdLowPwr; // exclusive min low power comm win period (s)
-    static const uint32_t    kMaxCommWinPrdLowPwr; // exclusive max low power comm win period (s)
-    static const uint32_t    kMinCommWinDurLowPwr; // exclusive min low power comm win duration (s)
-    static const uint32_t    kMaxCommWinDurLowPwr; // exclusive max low power comm win duration (s)
-    static const uint8_t     kConfLblLen=64;       // length of configuration label char array (63+'\0')
-    
-    static const char* const kDefConfFile;  // default configuration file
-
-    static const uint32_t   kMaxSizeOf = 
-            + (9u*sizeof(uint32_t)) + (6u*sizeof(uint16_t))
-            + (10u*sizeof(uint8_t)) + (3u*kNplas*sizeof(uint16_t))
-            + (kTotDacs*sizeof(uint16_t))
-            + (kConfLblLen*sizeof(uint8_t));
-
-    
-    enum EDatPackBit {
-        kSDcard = BIT(0),
-        kIrid   = BIT(1),
-        kAfar   = BIT(2),
-        kUSB    = BIT(3)
-    };
-    
-    enum ESendDataBit {
-        // can't use BIT(0)! (-0 = 0 => send nothing)
-        kAllFiles =  BIT(1), // if bit=0 => send most recent file
-        kTimeout  =  BIT(2), // if bit=0 => ignore timeout
-        kDelete   =  BIT(3), // if bit=0 => do not delete sent files
-        kUseBits  = -BIT(10) // useful to initialize fCommSendData as a bit word
-    };
-    
-    // i/o version
-    static const uint8_t     kIOVers;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
-    
- private:
-    // !!
-    // !! If any member variables change, update: SizeOf function and kIOVers value! (also if kNchans, etc. change!)
-    // !!
-    
-    // mbed mac address
-    static uint64_t fgMacAdr;              // mbed mac address
-    // conf header
-    char        fLabel[kConfLblLen];       // configuration label
-    uint32_t    fConfTime;                 // cpu config time
-    uint32_t    fRun;                      // run number
-    uint32_t    fFirstEvt;                 // starting event number
-    uint8_t     fStreamHiLoPlas;           // (1byte bool) if true, add the separated hi/lo thresh PLA patterns to the i/o
-    // data packing
-    uint8_t     fWvLoseLSB;                // number of least significant bits to lose when packing waveform data
-    uint8_t     fWvLoseMSB;                // number of  most significant bits to lose when packing waveform data
-    uint16_t    fWvBaseline;               // global baseline to use when packing data (useful to reduce clipping on the high end)
-    uint8_t     fDatPackType;              // type of data packing. OR'd bitword: if bit 1, will pack for writing. see EDatPackBit. default: always pack (all 1's)
-    // trigger setup
-    uint16_t    fDAC[kNchans][kNfpgaDacs]; //[card id][dac id] values should be 0-4095 here (not checked tho)
-    uint8_t     fNumPlas;                  // number of patterns to use. must be <= kNplas.
-    uint16_t    fPLA[kNplas];              //[pattern id] (same for each card)
-    uint8_t     fNumCardsMajLog;           // number of cards participating in the MajLogic trigger (1 to 4)
-    uint8_t     fEnableThermTrig;          // (1byte bool) whether or not to allow thermal triggers
-    uint16_t    fForceTrigPeriod;          // number of seconds between force triggers (0=none)
-    uint16_t    fHeartBeatPeriod;          // number of seconds between heartbeats (0=none)
-    uint8_t     fAmpsOn;                   // which amps are on (bit word. uint8_t => 8 amps max)
-    uint16_t    fEvtThrtlPeriodMs;         // throttle period to write events (ms)
-    // power
-    uint8_t     fPowerMode;                // power mode bit word
-    int16_t     fBatVoltLowPwr;            // battery level at which to switch to low power (not used?)
-    // communication
-    uint32_t    fCommWinPeriod;            // seconds between communication window startup (0=always on)
-    uint32_t    fCommWinDuration;          // seconds that communication window stays open (0=always open)
-    int16_t     fCommSendData;             // data to send during comm win (=0: none, >0=send up to x events from last file until comm win closes, <0=see ESendDataBit)
-    uint32_t    fCommWinPrdLowPwr;         // low power communication window period (seconds) (range enforced)
-    uint32_t    fCommWinDurLowPwr;         // low power communication window duration (seconds) (range enforced)
-    // watchdog
-    uint32_t    fWatchDogPeriod;           // number of seconds of inactivity for watchdog to issue a reset
-    
-    void SetHardDefaults();
-    
-    static
-    uint32_t    SizeOf(const bool streamHiLoPlas,
-                       const uint8_t nplas,
-                       const uint8_t lblLen) {
-        // private because it cannot be used to read from a buffer
-        // (the label length and fStreamHiLoPlas are not known a priori)
-        // returns the num of bytes needed to stream this object
-        // = size of member vars + 1 for i/o version + extra PLA strings (maybe)
-        uint32_t sz = kMaxSizeOf - kConfLblLen + lblLen;
-        static const uint32_t mhlp = 2u*kNplas*sizeof(uint16_t);
-        const int32_t dp = (nplas-kNplas)*sizeof(uint16_t);
-        const uint8_t fac = (streamHiLoPlas) ? 3u : 1u;
-        sz -= (fac*dp);
-        if (streamHiLoPlas==false) {
-            sz -= mhlp;
-        }
-        return sz;
-    }
-   
- public:
-    SnConfigFrame() { Reset(); }
-    virtual ~SnConfigFrame() {}
-    
-    const char* GetLabel() const { return fLabel; }
-    uint32_t GetLabelStrLen() const { return strlen(fLabel); }
-    uint32_t GetRun() const { return fRun; }
-    uint32_t GetFirstEvt() const { return fFirstEvt; }
-    uint16_t GetEvtThrtlPeriodMs() const { return fEvtThrtlPeriodMs; }
-    uint16_t GetForceTrigPeriod() const { return fForceTrigPeriod; }
-    uint32_t GetWatchdogPeriod() const { return fWatchDogPeriod; }
-    uint16_t GetDac(const uint8_t ch, const uint8_t dn) const { return fDAC[ch][dn]; }
-    uint8_t  GetNumPlas() const { return fNumPlas; }
-    uint16_t GetPla(const uint8_t pn) const { return fPLA[pn]; }
-    uint8_t  GetNumCardsMajLog() const { return fNumCardsMajLog; }
-    bool     IsThermTrigEnabled() const { return fEnableThermTrig!=0; }
-    bool     IsEachAmpOn() const {
-        bool allon=true;
-        for (uint8_t i=0; (i<kNchans) && allon; i++) {
-            allon = (fAmpsOn & BIT(i))!=0;
-        }
-        return allon;
-    }
-    // TODO: allow check for individual amps, when they can be turned on individually
-    
-    uint32_t GetCommWinPeriod() const { return fCommWinPeriod; }
-    uint32_t GetCommWinDuration() const { return fCommWinDuration; }
-    int16_t  GetCommSendData() const { return fCommSendData; }
-    
-    bool     IsSendingAllFiles() const
-        { return (fCommSendData<0) && ((fCommSendData & kAllFiles)!=0); }
-    bool     IsObeyingTimeout() const
-        { return (fCommSendData<0) && ((fCommSendData & kTimeout)!=0); }
-    bool     IsDeletingFiles() const
-        { return (fCommSendData<0) && ((fCommSendData & kDelete)!=0); }
-    
-    
-    const char* GetOutFileName(const char* dir) const;
-    
-    // waveform packing info
-    uint16_t GetWvBaseline() const { return fWvBaseline; }
-    uint8_t  GetWvLoseLSB() const { return fWvLoseLSB; }
-    uint8_t  GetWvLoseMSB() const { return fWvLoseMSB; }
-    bool     IsDatPackedFor(const EDatPackBit d) const { return (fDatPackType & d)!=0; }
-    void     GetPackParsFor(const EDatPackBit d,
-                            uint8_t& loseLSB, uint8_t& loseMSB,
-                            uint16_t& wvBase) const;
-    
-    // i/o
-    template<class T>
-    void ReadFrom(T& b) {
-        // no check on the length of buf is done here
-        // that should be been done already
-        //
-        // must match WriteTo
-        
-        uint8_t Rv=0;
-        b               = SnBitUtils::ReadFrom(b, Rv); // i/o version
-        if (Rv>0) {
-            uint32_t llen=kConfLblLen;
-            b           = SnBitUtils::ReadFrom(b, llen);
-            b           = SnBitUtils::ReadFrom(b, fLabel, llen);
-            b           = SnBitUtils::ReadFrom(b, fConfTime);
-            b           = SnBitUtils::ReadFrom(b, fRun);
-            b           = SnBitUtils::ReadFrom(b, fFirstEvt);
-            b           = SnBitUtils::ReadFrom(b, fStreamHiLoPlas);
-            b           = SnBitUtils::ReadFrom(b, fWvLoseLSB);
-            b           = SnBitUtils::ReadFrom(b, fWvLoseMSB);
-            b           = SnBitUtils::ReadFrom(b, fWvBaseline);
-            b           = SnBitUtils::ReadFrom(b, fDatPackType);
-            uint16_t* dc = &(fDAC[0][0]);
-            for (uint16_t i=0; i<kTotDacs; i++, dc++) {
-                b       = SnBitUtils::ReadFrom(b, *dc);
-            }
-            b           = SnBitUtils::ReadFrom(b, fNumPlas);
-            uint16_t* pl = &(fPLA[0]);
-            for (uint8_t j=0; j<fNumPlas; j++, pl++) {
-                b       = SnBitUtils::ReadFrom(b, *pl);
-            }
-            b           = SnBitUtils::ReadFrom(b, fNumCardsMajLog);
-            b           = SnBitUtils::ReadFrom(b, fEnableThermTrig);
-            b           = SnBitUtils::ReadFrom(b, fForceTrigPeriod);
-            b           = SnBitUtils::ReadFrom(b, fHeartBeatPeriod);
-            b           = SnBitUtils::ReadFrom(b, fAmpsOn);
-            b           = SnBitUtils::ReadFrom(b, fEvtThrtlPeriodMs);
-            b           = SnBitUtils::ReadFrom(b, fPowerMode);
-            b           = SnBitUtils::ReadFrom(b, fBatVoltLowPwr);
-            b           = SnBitUtils::ReadFrom(b, fCommWinPeriod);
-            b           = SnBitUtils::ReadFrom(b, fCommWinDuration);
-            b           = SnBitUtils::ReadFrom(b, fCommSendData);
-            b           = SnBitUtils::ReadFrom(b, fCommWinPrdLowPwr);
-            b           = SnBitUtils::ReadFrom(b, fCommWinDurLowPwr);
-            b           = SnBitUtils::ReadFrom(b, fWatchDogPeriod);
-            if (fStreamHiLoPlas!=0) {
-                uint16_t hi, lo;
-                for (uint8_t j=0; j<fNumPlas; j++) {
-                    b   = SnBitUtils::ReadFrom(b, hi);
-                    b   = SnBitUtils::ReadFrom(b, lo);
-                    // don't save these
-                }
-            }
-        }
-    }
-    
-    template <class T>
-    void WriteTo(T& b) const {
-        // no check on the length of the buf is done here
-        // that should be done already
-        //
-        // must match ReadFromBuf
-        //
-        // intentionally not writing mac address here, so we don't have to read it in
-        
-        const uint32_t llen = strlen(fLabel);
-        
-        b           = SnBitUtils::WriteTo(b, kIOVers); // i/o version
-        b           = SnBitUtils::WriteTo(b, llen);
-        b           = SnBitUtils::WriteTo(b, fLabel, llen);
-        b           = SnBitUtils::WriteTo(b, fConfTime);
-        b           = SnBitUtils::WriteTo(b, fRun);
-        b           = SnBitUtils::WriteTo(b, fFirstEvt);
-        b           = SnBitUtils::WriteTo(b, fStreamHiLoPlas);
-        b           = SnBitUtils::WriteTo(b, fWvLoseLSB);
-        b           = SnBitUtils::WriteTo(b, fWvLoseMSB);
-        b           = SnBitUtils::WriteTo(b, fWvBaseline);
-        b           = SnBitUtils::WriteTo(b, fDatPackType);
-        const uint16_t* dc = &(fDAC[0][0]);
-        for (uint16_t i=0; i<kTotDacs; i++, dc++) {
-            b       = SnBitUtils::WriteTo(b, *dc);
-        }
-        b           = SnBitUtils::WriteTo(b, fNumPlas);
-        const uint16_t* pl = &(fPLA[0]);
-        for (uint8_t j=0; j<fNumPlas; j++, pl++) {
-            b       = SnBitUtils::WriteTo(b, *pl);
-        }
-        b           = SnBitUtils::WriteTo(b, fNumCardsMajLog);
-        b           = SnBitUtils::WriteTo(b, fEnableThermTrig);
-        b           = SnBitUtils::WriteTo(b, fForceTrigPeriod);
-        b           = SnBitUtils::WriteTo(b, fHeartBeatPeriod);
-        b           = SnBitUtils::WriteTo(b, fAmpsOn);
-        b           = SnBitUtils::WriteTo(b, fEvtThrtlPeriodMs);
-        b           = SnBitUtils::WriteTo(b, fPowerMode);
-        b           = SnBitUtils::WriteTo(b, fBatVoltLowPwr);
-        b           = SnBitUtils::WriteTo(b, fCommWinPeriod);
-        b           = SnBitUtils::WriteTo(b, fCommWinDuration);
-        b           = SnBitUtils::WriteTo(b, fCommSendData);
-        b           = SnBitUtils::WriteTo(b, fCommWinPrdLowPwr);
-        b           = SnBitUtils::WriteTo(b, fCommWinDurLowPwr);
-        b           = SnBitUtils::WriteTo(b, fWatchDogPeriod);
-        if (fStreamHiLoPlas!=0) {
-            pl = fPLA;
-            uint16_t hi, lo;
-            for (uint8_t j=0; j<fNumPlas; j++, pl++) {
-                GetHiLoPlas(*pl, hi, lo);
-                b   = SnBitUtils::WriteTo(b, hi);
-                b   = SnBitUtils::WriteTo(b, lo);
-            }
-        }
-    }
-    
-    bool ReadFromFile(const char* cfile);
-    bool WriteToFile(const char* cfile) const;
-    
-    void Reset() {
-        memset(fLabel, 0, sizeof(char)*kConfLblLen);
-        if (ReadFromFile(kDefConfFile)==false) {
-            // couldn't get default. use hardcoded version.
-            SetHardDefaults();
-        }
-    }
-        
-    uint32_t    SizeOf() const {
-        // returns the num of bytes needed to stream this object
-        // = size of member vars + 1 for i/o version + extra PLA strings (maybe)
-        //   + length of label string
-        return SizeOf(fStreamHiLoPlas!=0, fNumPlas, strlen(fLabel));
-    }
-
-    static void     SetMacAddress();
-    static uint64_t GetMacAddress() {
-        if (fgMacAdr==0) {
-            SetMacAddress();
-        }
-        return fgMacAdr;
-    }
-    
-    static uint32_t GetLabelMaxLen() { return kConfLblLen; }
-
-    static void GetHiLoPlas(const uint16_t pla,
-                            uint16_t& hiPla,
-                            uint16_t& loPla,
-                            const bool r2l=false);
-};
-
-#endif // SN_SnConfigFrame
+#ifndef SN_SnConfigFrame
+#define SN_SnConfigFrame
+
+#include <stdint.h>
+#include "SnConstants.h"
+#include "SnBitUtils.h"
+
+class SnConfigFrame {
+ public:
+    static const uint32_t    kMinCommWinPrdLowPwr; // exclusive min low power comm win period (s)
+    static const uint32_t    kMaxCommWinPrdLowPwr; // exclusive max low power comm win period (s)
+    static const uint32_t    kMinCommWinDurLowPwr; // exclusive min low power comm win duration (s)
+    static const uint32_t    kMaxCommWinDurLowPwr; // exclusive max low power comm win duration (s)
+    static const uint8_t     kConfLblLen=64;       // length of configuration label char array (63+'\0')
+    
+    static const char* const kDefConfFile;  // default configuration file
+
+    static const uint32_t   kMaxSizeOf = 
+            + (10u*sizeof(uint32_t)) + (6u*sizeof(uint16_t))
+            + (11u*sizeof(uint8_t)) + (3u*kNplas*sizeof(uint16_t))
+            + (kTotDacs*sizeof(uint16_t))
+            + (kConfLblLen*sizeof(uint8_t));
+
+    
+    enum EDatPackBit {
+        kSDcard = BIT(0),
+        kIrid   = BIT(1),
+        kAfar   = BIT(2),
+        kUSB    = BIT(3)
+    };
+    
+    enum ESendDataBit {
+        // can't use BIT(0)! (-0 = 0 => send nothing)
+        kAllFiles =  BIT(1), // if bit=0 => send most recent file
+        kTimeout  =  BIT(2), // if bit=0 => ignore timeout
+        kDelete   =  BIT(3), // if bit=0 => do not delete sent files
+        kUseBits  = -BIT(10) // useful to initialize fCommSendData as a bit word
+    };
+    
+    enum ERunMode {
+        kInfSeqs   = 0,
+        kSingleSeq = 1
+    };
+    
+    // i/o version
+    static const uint8_t     kIOVers;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
+    
+ private:
+    // !!
+    // !! If any member variables change, update: SizeOf function and kIOVers value! (also if kNchans, etc. change!)
+    // !!
+    
+    // mbed mac address
+    static uint64_t fgMacAdr;              // mbed mac address
+    // conf header
+    char        fLabel[kConfLblLen];       // configuration label
+    uint32_t    fConfTime;                 // cpu config time
+    uint32_t    fRun;                      // run number
+    uint32_t    fFirstEvt;                 // starting event number
+    uint32_t    fEvtsPerSeq;               // number of events per file
+    uint8_t     fRunMode;                  // mode of running (see ERunMode)
+    uint8_t     fStreamHiLoPlas;           // (1byte bool) if true, add the separated hi/lo thresh PLA patterns to the i/o
+    // data packing
+    uint8_t     fWvLoseLSB;                // number of least significant bits to lose when packing waveform data
+    uint8_t     fWvLoseMSB;                // number of  most significant bits to lose when packing waveform data
+    uint16_t    fWvBaseline;               // global baseline to use when packing data (useful to reduce clipping on the high end)
+    uint8_t     fDatPackType;              // type of data packing. OR'd bitword: if bit 1, will pack for writing. see EDatPackBit. default: always pack (all 1's)
+    // trigger setup
+    uint16_t    fDAC[kNchans][kNfpgaDacs]; //[card id][dac id] values should be 0-4095 here (not checked tho)
+    uint8_t     fNumPlas;                  // number of patterns to use. must be <= kNplas.
+    uint16_t    fPLA[kNplas];              //[pattern id] (same for each card)
+    uint8_t     fNumCardsMajLog;           // number of cards participating in the MajLogic trigger (1 to 4)
+    uint8_t     fEnableThermTrig;          // (1byte bool) whether or not to allow thermal triggers
+    uint16_t    fForceTrigPeriod;          // number of seconds between force triggers (0=none)
+    uint16_t    fHeartBeatPeriod;          // number of seconds between heartbeats (0=none)
+    uint8_t     fAmpsOn;                   // which amps are on (bit word. uint8_t => 8 amps max)
+    uint16_t    fEvtThrtlPeriodMs;         // throttle period to write events (ms)
+    // power
+    uint8_t     fPowerMode;                // power mode bit word
+    int16_t     fBatVoltLowPwr;            // battery level at which to switch to low power (not used?)
+    // communication
+    uint32_t    fCommWinPeriod;            // seconds between communication window startup (0=always on)
+    uint32_t    fCommWinDuration;          // seconds that communication window stays open (0=always open)
+    int16_t     fCommSendData;             // data to send during comm win (=0: none, >0=send up to x events from last file until comm win closes, <0=see ESendDataBit)
+    uint32_t    fCommWinPrdLowPwr;         // low power communication window period (seconds) (range enforced)
+    uint32_t    fCommWinDurLowPwr;         // low power communication window duration (seconds) (range enforced)
+    // watchdog
+    uint32_t    fWatchDogPeriod;           // number of seconds of inactivity for watchdog to issue a reset
+    
+    void SetHardDefaults();
+    
+    static
+    uint32_t    SizeOf(const bool streamHiLoPlas,
+                       const uint8_t nplas,
+                       const uint8_t lblLen) {
+        // private because it cannot be used to read from a buffer
+        // (the label length and fStreamHiLoPlas are not known a priori)
+        // returns the num of bytes needed to stream this object
+        // = size of member vars + 1 for i/o version + extra PLA strings (maybe)
+        uint32_t sz = kMaxSizeOf - kConfLblLen + lblLen;
+        static const uint32_t mhlp = 2u*kNplas*sizeof(uint16_t);
+        const int32_t dp = (nplas-kNplas)*sizeof(uint16_t);
+        const uint8_t fac = (streamHiLoPlas) ? 3u : 1u;
+        sz += (fac*dp);
+        if (streamHiLoPlas==false) {
+            sz -= mhlp;
+        }
+        return sz;
+    }
+   
+ public:
+    SnConfigFrame() { Reset(); }
+    virtual ~SnConfigFrame() {}
+    
+    const char* GetLabel() const { return fLabel; }
+    uint32_t GetLabelStrLen() const { return strlen(fLabel); }
+    uint32_t GetRun() const { return fRun; }
+    uint32_t GetFirstEvt() const { return fFirstEvt; }
+    uint32_t GetEvtsPerFile() const { return fEvtsPerSeq; }
+    bool     IsSingleSeqRunMode() const { return fRunMode==kSingleSeq; }
+    uint16_t GetEvtThrtlPeriodMs() const { return fEvtThrtlPeriodMs; }
+    uint16_t GetForceTrigPeriod() const { return fForceTrigPeriod; }
+    uint16_t GetHeartbeatPeriod() const { return fHeartBeatPeriod; }
+    uint32_t GetWatchdogPeriod() const { return fWatchDogPeriod; }
+    uint16_t GetDac(const uint8_t ch, const uint8_t dn) const { return fDAC[ch][dn]; }
+    uint8_t  GetNumPlas() const { return fNumPlas; }
+    uint16_t GetPla(const uint8_t pn) const { return fPLA[pn]; }
+    uint8_t  GetNumCardsMajLog() const { return fNumCardsMajLog; }
+    bool     IsThermTrigEnabled() const { return fEnableThermTrig!=0; }
+    bool     IsEachAmpOn() const {
+        bool allon=true;
+        for (uint8_t i=0; (i<kNchans) && allon; i++) {
+            allon = (fAmpsOn & BIT(i))!=0;
+        }
+        return allon;
+    }
+    // TODO: allow check for individual amps, when they can be turned on individually
+    
+    uint32_t GetCommWinPeriod() const { return fCommWinPeriod; }
+    uint32_t GetCommWinDuration() const { return fCommWinDuration; }
+    int16_t  GetCommSendData() const { return fCommSendData; }
+    
+    bool     IsSendingAllFiles() const
+        { return (fCommSendData<0) && ((fCommSendData & kAllFiles)!=0); }
+    bool     IsObeyingTimeout() const
+        { return (fCommSendData<0) && ((fCommSendData & kTimeout)!=0); }
+    bool     IsDeletingFiles() const
+        { return (fCommSendData<0) && ((fCommSendData & kDelete)!=0); }
+    
+    
+    const char* GetOutFileName(const char* dir) const;
+    
+    // waveform packing info
+    uint16_t GetWvBaseline() const { return fWvBaseline; }
+    uint8_t  GetWvLoseLSB() const { return fWvLoseLSB; }
+    uint8_t  GetWvLoseMSB() const { return fWvLoseMSB; }
+    bool     IsDatPackedFor(const EDatPackBit d) const { return (fDatPackType & d)!=0; }
+    void     GetPackParsFor(const EDatPackBit d,
+                            uint8_t& loseLSB, uint8_t& loseMSB,
+                            uint16_t& wvBase) const;
+    
+    // i/o
+    template<class T>
+    void ReadFrom(T& b) {
+        // no check on the length of buf is done here
+        // that should be been done already
+        //
+        // must match WriteTo
+        
+        uint8_t Rv=0;
+        b               = SnBitUtils::ReadFrom(b, Rv); // i/o version
+        printf("Rv=%hhu\r\n",Rv);
+        if (Rv>0) {
+            uint32_t llen=kConfLblLen;
+            b           = SnBitUtils::ReadFrom(b, llen);
+            printf("llen=%u\r\n",llen);
+            b           = SnBitUtils::ReadFrom(b, fLabel, llen);
+            printf("lbl=%s\r\n",fLabel);
+            b           = SnBitUtils::ReadFrom(b, fConfTime);
+            printf("ct=%u\r\n",fConfTime);
+            b           = SnBitUtils::ReadFrom(b, fRun);
+            printf("run=%u\r\n",fRun);
+            b           = SnBitUtils::ReadFrom(b, fFirstEvt);
+            printf("fe=%u\r\n",fFirstEvt);
+            if (Rv>1) {
+                b       = SnBitUtils::ReadFrom(b, fEvtsPerSeq);
+                printf("eps=%u\r\n",fEvtsPerSeq);
+                b       = SnBitUtils::ReadFrom(b, fRunMode);
+                printf("rm=%hhu\r\n",fRunMode);
+            }
+            b           = SnBitUtils::ReadFrom(b, fStreamHiLoPlas);
+            printf("shilo=%d\r\n",(int)fStreamHiLoPlas);
+            b           = SnBitUtils::ReadFrom(b, fWvLoseLSB);
+            printf("lsb=%hhu\r\n",fWvLoseLSB);
+            b           = SnBitUtils::ReadFrom(b, fWvLoseMSB);
+            printf("msb=%hhu\r\n",fWvLoseMSB);
+            b           = SnBitUtils::ReadFrom(b, fWvBaseline);
+            printf("bl=%hu\r\n",fWvBaseline);
+            b           = SnBitUtils::ReadFrom(b, fDatPackType);
+            printf("dp=%hhu\r\n",fDatPackType);
+            uint16_t* dc = &(fDAC[0][0]);
+            for (uint16_t i=0; i<kTotDacs; i++, dc++) {
+                b       = SnBitUtils::ReadFrom(b, *dc);
+                printf("dac[%hu]=%hu\r\n",i,*dc);
+            }
+            b           = SnBitUtils::ReadFrom(b, fNumPlas);
+            printf("npla=%hhu\r\n",fNumPlas);
+            uint16_t* pl = &(fPLA[0]);
+            for (uint8_t j=0; j<fNumPlas; j++, pl++) {
+                b       = SnBitUtils::ReadFrom(b, *pl);
+                printf("pla[%hhu]=%hu\r\n",j,*pl);
+            }
+            b           = SnBitUtils::ReadFrom(b, fNumCardsMajLog);
+            printf("mj=%hhu\r\n",fNumCardsMajLog);
+            b           = SnBitUtils::ReadFrom(b, fEnableThermTrig);
+            printf("thm=%d\r\n",(int)fEnableThermTrig);
+            b           = SnBitUtils::ReadFrom(b, fForceTrigPeriod);
+            printf("force=%hu\r\n",fForceTrigPeriod);
+            b           = SnBitUtils::ReadFrom(b, fHeartBeatPeriod);
+            printf("heart=%hu\r\n",fHeartBeatPeriod);
+            b           = SnBitUtils::ReadFrom(b, fAmpsOn);
+            printf("amps=%hhu\r\n",fAmpsOn);
+            b           = SnBitUtils::ReadFrom(b, fEvtThrtlPeriodMs);
+            printf("throt=%hu\r\n",fEvtThrtlPeriodMs);
+            b           = SnBitUtils::ReadFrom(b, fPowerMode);
+            printf("pow=%hhu\r\n",fPowerMode);
+            b           = SnBitUtils::ReadFrom(b, fBatVoltLowPwr);
+            printf("batlow=%d\r\n",fBatVoltLowPwr);
+            b           = SnBitUtils::ReadFrom(b, fCommWinPeriod);
+            printf("cmper=%u\r\n",fCommWinPeriod);
+            b           = SnBitUtils::ReadFrom(b, fCommWinDuration);
+            printf("cmdur=%u\r\n",fCommWinDuration);
+            b           = SnBitUtils::ReadFrom(b, fCommSendData);
+            printf("send=%d\r\n",fCommSendData);
+            b           = SnBitUtils::ReadFrom(b, fCommWinPrdLowPwr);
+            printf("cmperlp=%u\r\n",fCommWinPrdLowPwr);
+            b           = SnBitUtils::ReadFrom(b, fCommWinDurLowPwr);
+            printf("cmdurlp=%u\r\n",fCommWinDurLowPwr);
+            b           = SnBitUtils::ReadFrom(b, fWatchDogPeriod);
+            printf("watch=%u\r\n",fWatchDogPeriod);
+            if (fStreamHiLoPlas!=0) {
+                uint16_t hi, lo;
+                for (uint8_t j=0; j<fNumPlas; j++) {
+                    b   = SnBitUtils::ReadFrom(b, hi);
+                    printf("hi=%hu\r\n",hi);
+                    b   = SnBitUtils::ReadFrom(b, lo);
+                    printf("lo=%hu\r\n",lo);
+                    // don't save these
+                }
+            }
+        }
+        printf("read from done\r\n");
+    }
+    
+    template <class T>
+    void WriteTo(T& b) const {
+        // no check on the length of the buf is done here
+        // that should be done already
+        //
+        // must match ReadFromBuf
+        //
+        // intentionally not writing mac address here, so we don't have to read it in
+        
+        const uint32_t llen = strlen(fLabel);
+        
+        b           = SnBitUtils::WriteTo(b, kIOVers); // i/o version
+        b           = SnBitUtils::WriteTo(b, llen);
+        b           = SnBitUtils::WriteTo(b, fLabel, llen);
+        b           = SnBitUtils::WriteTo(b, fConfTime);
+        b           = SnBitUtils::WriteTo(b, fRun);
+        b           = SnBitUtils::WriteTo(b, fFirstEvt);
+        b           = SnBitUtils::WriteTo(b, fEvtsPerSeq);
+        b           = SnBitUtils::WriteTo(b, fRunMode);
+        b           = SnBitUtils::WriteTo(b, fStreamHiLoPlas);
+        b           = SnBitUtils::WriteTo(b, fWvLoseLSB);
+        b           = SnBitUtils::WriteTo(b, fWvLoseMSB);
+        b           = SnBitUtils::WriteTo(b, fWvBaseline);
+        b           = SnBitUtils::WriteTo(b, fDatPackType);
+        const uint16_t* dc = &(fDAC[0][0]);
+        for (uint16_t i=0; i<kTotDacs; i++, dc++) {
+            b       = SnBitUtils::WriteTo(b, *dc);
+        }
+        b           = SnBitUtils::WriteTo(b, fNumPlas);
+        const uint16_t* pl = &(fPLA[0]);
+        for (uint8_t j=0; j<fNumPlas; j++, pl++) {
+            b       = SnBitUtils::WriteTo(b, *pl);
+        }
+        b           = SnBitUtils::WriteTo(b, fNumCardsMajLog);
+        b           = SnBitUtils::WriteTo(b, fEnableThermTrig);
+        b           = SnBitUtils::WriteTo(b, fForceTrigPeriod);
+        b           = SnBitUtils::WriteTo(b, fHeartBeatPeriod);
+        b           = SnBitUtils::WriteTo(b, fAmpsOn);
+        b           = SnBitUtils::WriteTo(b, fEvtThrtlPeriodMs);
+        b           = SnBitUtils::WriteTo(b, fPowerMode);
+        b           = SnBitUtils::WriteTo(b, fBatVoltLowPwr);
+        b           = SnBitUtils::WriteTo(b, fCommWinPeriod);
+        b           = SnBitUtils::WriteTo(b, fCommWinDuration);
+        b           = SnBitUtils::WriteTo(b, fCommSendData);
+        b           = SnBitUtils::WriteTo(b, fCommWinPrdLowPwr);
+        b           = SnBitUtils::WriteTo(b, fCommWinDurLowPwr);
+        b           = SnBitUtils::WriteTo(b, fWatchDogPeriod);
+        if (fStreamHiLoPlas!=0) {
+            pl = fPLA;
+            uint16_t hi, lo;
+            for (uint8_t j=0; j<fNumPlas; j++, pl++) {
+                GetHiLoPlas(*pl, hi, lo);
+                b   = SnBitUtils::WriteTo(b, hi);
+                b   = SnBitUtils::WriteTo(b, lo);
+            }
+        }
+    }
+    
+    bool ReadFromFile(const char* cfile);
+    bool WriteToFile(const char* cfile) const;
+    
+    void Reset() {
+        memset(fLabel, 0, sizeof(char)*kConfLblLen);
+        if (ReadFromFile(kDefConfFile)==false) {
+            // couldn't get default. use hardcoded version.
+            SetHardDefaults();
+        }
+    }
+        
+    uint32_t    SizeOf() const {
+        // returns the num of bytes needed to stream this object
+        // = size of member vars + 1 for i/o version + extra PLA strings (maybe)
+        //   + length of label string
+        return SizeOf(fStreamHiLoPlas!=0, fNumPlas, strlen(fLabel));
+    }
+
+    static void     SetMacAddress();
+    static uint64_t GetMacAddress() {
+        if (fgMacAdr==0) {
+            SetMacAddress();
+        }
+        return fgMacAdr;
+    }
+    
+    static uint32_t GetLabelMaxLen() { return kConfLblLen; }
+
+    static void GetHiLoPlas(const uint16_t pla,
+                            uint16_t& hiPla,
+                            uint16_t& loPla,
+                            const bool r2l=false);
+};
+
+#endif // SN_SnConfigFrame