Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SnConfigFrame.cpp Source File

SnConfigFrame.cpp

00001 #include "SnConfigFrame.h"
00002 
00003 #include "mbed.h"
00004 
00005 //#define DEBUG
00006 
00007 #include "SnBitUtils.h"
00008 #include "SnHeaderFrame.h"
00009 #include "Watchdog.h"
00010 #include "SnSDUtils.h"
00011 
00012 extern "C" void mbed_mac_address(char *);
00013 
00014 bool              SnConfigFrame::fgApplySafetyNets     = true;
00015 #if CHIPBOARD==ATWD4CH
00016 const uint8_t     SnConfigFrame::kIOVers               = 11;
00017 #elif CHIPBOARD==SST4CH
00018 const uint8_t     SnConfigFrame::kIOVers               = 12;
00019 #elif CHIPBOARD==SST4CH_1GHz
00020 const uint8_t     SnConfigFrame::kIOVers               = 13;
00021 #elif CHIPBOARD==SST4CH512
00022 const uint8_t     SnConfigFrame::kIOVers               = 14;
00023 #elif CHIPBOARD==SST4CH512_1GHz
00024 const uint8_t     SnConfigFrame::kIOVers               = 15;
00025 #elif CHIPBOARD==SST8CH
00026 const uint8_t     SnConfigFrame::kIOVers               = 16;
00027 #elif CHIPBOARD==SST8CH_1GHz
00028 const uint8_t     SnConfigFrame::kIOVers               = 17;
00029 #else
00030 #error CHIPBOARD value not used in config frame i/o version
00031 #endif
00032 
00033 #if defined(LOAD_DEFAULT_CONFIG_FROM_SD)
00034 const char* const SnConfigFrame::kDefConfFile          = "/sd/DEFCONF.DAT";
00035 const char* const SnConfigFrame::kDefRemIpFilen        = "/sd/REMOTIP.TXT";
00036 const char* const SnConfigFrame::kDefRemPortFilen      = "/sd/REMOTPRT.TXT";
00037 const char* const SnConfigFrame::kDefMbedIPFilen       = "/sd/MBEDIP.TXT";
00038 const char* const SnConfigFrame::kDefMbedMaskFilen     = "/sd/MBEDMASK.TXT";
00039 const char* const SnConfigFrame::kDefMbedGateFilen     = "/sd/MBEDGATE.TXT";
00040 #elif defined(USE_INTERFACE_CHIP)
00041 const char* const SnConfigFrame::kDefConfFile          = "/local/DEFCONF.DAT";
00042 const char* const SnConfigFrame::kDefRemIpFilen        = "/local/REMOTIP.TXT";
00043 const char* const SnConfigFrame::kDefRemPortFilen      = "/local/REMOTPRT.TXT";
00044 const char* const SnConfigFrame::kDefMbedIPFilen       = "/local/MBEDIP.TXT";
00045 const char* const SnConfigFrame::kDefMbedMaskFilen     = "/local/MBEDMASK.TXT";
00046 const char* const SnConfigFrame::kDefMbedGateFilen     = "/local/MBEDGATE.TXT";
00047 #endif
00048 
00049 const char* const SnConfigFrame::kDefIPflag            = "DEF";
00050 const uint32_t    SnConfigFrame::kDefIPvalue           = 0;
00051 const uint32_t    SnConfigFrame::kMinCommWinPrdLowPwr  = 14400;    // exclusive min low power comm win period (s)
00052 const uint32_t    SnConfigFrame::kMaxCommWinPrdLowPwr  = 259200;   // exclusive max low power comm win period (s)
00053 const uint32_t    SnConfigFrame::kMinCommWinDurLowPwr  = 300;      // exclusive min low power comm win duration (s)
00054 const uint32_t    SnConfigFrame::kMaxCommWinDurLowPwr  = 3600;     // exclusive max low power comm win duration (s)
00055 const uint8_t     SnConfigFrame::kConfLblLen;
00056 
00057 uint64_t       SnConfigFrame::fgMacAdr              = 0;
00058 
00059 void SnConfigFrame::SetMacAddress() {
00060     static const uint8_t b64 = sizeof(uint64_t);
00061     static char c[b64];
00062     // NOTE: the function below may not be the one provided by MBED!
00063     // see main.cpp
00064     mbed_mac_address(&(c[0]));
00065     // like a big endian union
00066     fgMacAdr = 0;
00067     const char* a = c+(b64-1);
00068     for (uint8_t i=0; i<b64; i++, a--) {
00069         fgMacAdr |= static_cast<uint64_t>(*a) << (i<<3);
00070     }
00071 #ifdef DEBUG
00072     printf("MAC=%012llX\r\n", fgMacAdr>>16); // 64 -> 48 bits
00073 #endif
00074 }
00075 
00076 void SnConfigFrame::SetHardDefaults() {
00077     sprintf(fLabel,"Default_rev124");
00078     fConfTime           = 1338854400u; // Tue, 05 Jun 2012 00:00:00 GMT
00079     fRun                = 0;
00080     fFirstSeq           = 0;
00081     fEvtsPerSeq         = 300;
00082 #if CHIPBOARD==ATWD4CH
00083     fRunMode            = kRSListOneCW;
00084     fStreamHiLoPlas     = 0;
00085 #else // not ATWD4CH
00086     fRunMode            = kDualThreshBit | kDiffTrigBit | kRSListOneCW;
00087 #endif
00088     fWvLoseLSB          = 0;
00089     fWvLoseMSB          = 4;
00090     fWvBaseline         = 0;
00091     fDatPackType        = kSDcard | kIrid | kAfar | kUSB; // starting with io vers 11+, this is no longer changeable
00092     uint16_t* dc = &(fDAC[0][0]);
00093     for (uint16_t i=0; i<kTotDacs; i++, dc++) {
00094         *dc             = 3072u;
00095     }
00096 #if CHIPBOARD==ATWD4CH
00097     fNumPlas            = 1;
00098     uint16_t* pl = &(fPLA[0]);
00099     for (uint8_t j=0; j<kNplas; j++, pl++) {
00100         *pl             = 0x7FFFu;
00101     }
00102 #endif
00103     fNumCardsMajLog     = 2;
00104     fEnableThermTrig    = 0;
00105     fForceTrigPeriod    = 0;
00106     fHeartBeatPeriod    = 0;
00107     //fAmpsOn             = 0x0Fu; removed vers 11+
00108     fEvtThrtlPeriodMs   = 0;
00109 #ifdef AFAR_ON_FIRST_COMM_HARDCONF
00110     fPowerMode          = kIridComWin | kAfarComWin;
00111 #else
00112     fPowerMode          = kIridComWin; 
00113 #endif
00114     fBatVoltToLowPwr    = 0;
00115     fBatVoltFromLowPwr  = 0;
00116     fVoltCheckPeriod    = 127u; 
00117     fCommWinPeriod      = 300u;
00118     fCommWinDuration    = 600u;
00119     fCommSendData       = static_cast<int16_t>(kUseBits);
00120     fCommWinPrdLowPwr   = 86100u;
00121     fCommWinDurLowPwr   = 300u;
00122     for (uint8_t i=0; i<kNumDatStreams; ++i) {
00123         fCommWinConnTOMins[i] = GetDefaultConnTOMinOf(GetDataStreamForIndex(i));
00124         fCommWinListTOMins[i] = GetDefaultListTOMinOf(GetDataStreamForIndex(i));
00125     }
00126     fWatchDogPeriod     = WDFAILSAFE;
00127 #if CHIPBOARD==ATWD4CH
00128 //    fTempCheckPeriod    = 0;
00129 #else // not ATWD4CH
00130     fTempCheckPeriod    = -8;
00131 #endif
00132     SetDefaultIPs();
00133     fIsLowPower         = false;
00134     memcpy(fNormLabel, fLabel, kConfLblLen);
00135     fNormPowerMode      = fPowerMode;
00136     
00137     ApplyConnectListenSafetyNets();
00138 }
00139 
00140 void SnConfigFrame::SetDefaultRemoteServ() {
00141     if (false==ReadDefaultRemoteServer()) {
00142         sprintf(fRemoteServer,"%s","128.195.204.151");
00143     }
00144 }
00145 
00146 void SnConfigFrame::SetDefaultRemotePort() {
00147     if (false==ReadDefaultRemotePort()) {
00148         fRemotePort         = 6655;
00149     }
00150 }
00151 
00152 void SnConfigFrame::SetDefaultMbedIP() {
00153     // see ReadDefaultIPFile
00154     //
00155     // these hardcoded defaults are only here
00156     // "in case". they make it difficult/impossible
00157     // to swap boards in the field without internet
00158     // access to change the mbed program
00159     const uint64_t ip = GetMacAddress();
00160     if (false==ReadDefaultMbedIP()) {
00161         switch (ip) {
00162             case 0x0002F7F0AEE00000: // stn 20, atwd mb 1
00163                 sprintf(fMbedIP,"%s","157.132.94.30");
00164                 break;
00165             case 0x0002F7F2244B0000: // stn 13, board 102
00166                 sprintf(fMbedIP,"%s","157.132.94.31");
00167                 break;
00168             case 0x0002F7F20A9C0000: // stn 14, board 104
00169                 sprintf(fMbedIP,"%s","157.132.94.33");
00170                 break;
00171             case 0x0002F7F21A8A0000: // board 111
00172                 sprintf(fMbedIP,"%s","157.132.94.34");
00173                 break;                
00174             case 0x0002F7F0C3B60000: // station 3, atwd mb 5
00175                 sprintf(fMbedIP,"%s","157.132.94.35");
00176                 break;
00177             case 0x0002F7F0C41C0000: // station 4
00178             case 0x0002F7F1F7A80000: // stn 15, board 110
00179                 sprintf(fMbedIP,"%s","157.132.94.37");
00180                 break;
00181             case 0x0002F7F0C61A0000: // station 10, atwd mb 8
00182                 sprintf(fMbedIP,"%s","157.132.94.39");
00183                 break;
00184             case 0x0002F7F0C4450000: // station 6
00185             case 0x0002F7F1E9ED0000: // HCR stn 40, board 108
00186                 sprintf(fMbedIP,"%s","157.132.94.50");
00187                 break;
00188             case 0x0002F7F1F7C60000: // stn41, board 101
00189                 sprintf(fMbedIP,"%s","157.132.94.53");
00190                 break;
00191             case 0x0002F7F224440000: // stn 19, board 105
00192                 sprintf(fMbedIP,"%s","157.132.94.41");
00193                 break;
00194             case 0x0002F7F175B70000: // station 11
00195             case 0x0002F7F202C10000: // stn 17, board 109
00196                 sprintf(fMbedIP,"%s","157.132.94.43");
00197                 break;
00198             case 0x0002F7F1F6340000: // stn 31, board 107
00199                 sprintf(fMbedIP,"%s","157.132.94.47");
00200                 break;
00201             case 0x0002F7F1F21A0000: // stn 32, board 112
00202                 sprintf(fMbedIP,"%s","157.132.94.48");
00203                 break;
00204             case 0x0002F7F1F2120000: // stn 30, board 113
00205                 sprintf(fMbedIP,"%s","157.132.94.49");
00206                 break;
00207             case 0x0002F7F2E24B0000: // stn 50, board 202
00208                 sprintf(fMbedIP,"%s","157.132.94.26");
00209                 break;
00210             case 0x0002F7F2E7B90000: // stn 51, board 203
00211                 sprintf(fMbedIP,"%s","157.132.94.27");
00212                 break;
00213             case 0x0002F7F2E1CE0000: // stn 52, board 204
00214                 sprintf(fMbedIP,"%s","157.132.94.28");
00215                 break;
00216             case 0x0002F7F2EC550000: // board 207
00217                 sprintf(fMbedIP,"%s","157.132.94.29");
00218                 break;
00219             case 0x0002F7F2EDFF0000: // board 208
00220                 sprintf(fMbedIP,"%s","157.132.94.30");
00221                 break;
00222             default: // what??
00223                 sprintf(fMbedIP,"%s","157.132.94.46"); // usually for tent
00224                 break;
00225         };
00226     }
00227 }
00228 // brian dornick 3107
00229 void SnConfigFrame::SetDefaultMaskIP() {
00230     if (false==ReadDefaultMbedMask()) {
00231         sprintf(fMbedMask,"%s","255.255.255.0");
00232     }
00233 }
00234 
00235 void SnConfigFrame::SetDefaultGateIP() {
00236     if (false==ReadDefaultMbedGate()) {
00237         sprintf(fMbedGate,"%s","157.132.94.1");
00238     }
00239 }
00240 
00241 #ifdef USE_INTERFACE_CHIP
00242 bool SnConfigFrame::ReadOneIPFrom(const char* ipfname,
00243                                   char* ipstr) {
00244     bool ok = false;
00245     FILE* ipf = fopen(ipfname, "r");
00246     if (ipf!=0) {
00247         uint8_t ipbytes[4] = {0,0,0,0};
00248         const int nr = fscanf(ipf,"%hhu.%hhu.%hhu.%hhu\n",
00249             &(ipbytes[0]), &(ipbytes[1]),
00250             &(ipbytes[2]), &(ipbytes[3]));
00251         if (4==nr) {
00252             const int nc = 
00253                 sprintf(ipstr,"%hhu.%hhu.%hhu.%hhu",
00254                     ipbytes[0], ipbytes[1],
00255                     ipbytes[2], ipbytes[3]);
00256             ok = nc>0;
00257         }
00258         fclose(ipf);
00259     }
00260 #ifdef DEBUG
00261     printf("ReadOneIPInto : ipstr=[%s], ok=%d\r\n",
00262         ipstr, (int)ok);
00263 #endif
00264     return ok;
00265 }
00266 #endif
00267 
00268 bool SnConfigFrame::ReadDefaultRemoteServer() {
00269 #ifdef USE_INTERFACE_CHIP
00270     const bool ok = ReadOneIPFrom(kDefRemIpFilen, fRemoteServer);    
00271 #ifdef DEBUG
00272     printf("remote = %s\r\n", fRemoteServer);
00273 #endif
00274     return ok;
00275 #else // do not USE_INTERFACE_CHIP
00276     return false;
00277 #endif // USE_INTERFACE_CHIP
00278 }
00279 
00280 bool SnConfigFrame::ReadDefaultRemotePort() {
00281 #ifdef USE_INTERFACE_CHIP
00282     bool ok = false;
00283     FILE* pf = fopen(kDefRemPortFilen, "r"); 
00284     if (pf!=0) {
00285         ok = (1==fscanf(pf, "%hu\n", &fRemotePort));
00286         fclose(pf);
00287     }
00288 #ifdef DEBUG
00289     printf("port   = %hu\r\n", fRemotePort);
00290 #endif
00291     return ok;
00292 #else // do not USE_INTERFACE_CHIP
00293     return false;
00294 #endif // USE_INTERFACE_CHIP
00295 }
00296 
00297 bool SnConfigFrame::ReadDefaultMbedIP() {
00298 #ifdef USE_INTERFACE_CHIP
00299     const bool ok = ReadOneIPFrom(kDefMbedIPFilen, fMbedIP);    
00300 #ifdef DEBUG
00301     printf("mbed   = %s\r\n", fMbedIP);
00302 #endif
00303     return ok;
00304 #else // do not USE_INTERFACE_CHIP
00305     return false;
00306 #endif // USE_INTERFACE_CHIP
00307 }
00308 
00309 bool SnConfigFrame::ReadDefaultMbedMask() {
00310 #ifdef USE_INTERFACE_CHIP
00311     const bool ok = ReadOneIPFrom(kDefMbedMaskFilen, fMbedMask);    
00312 #ifdef DEBUG
00313     printf("mask   = %s\r\n", fMbedMask);
00314 #endif
00315     return ok;
00316 #else // do not USE_INTERFACE_CHIP
00317     return false;
00318 #endif // USE_INTERFACE_CHIP
00319 }
00320 
00321 bool SnConfigFrame::ReadDefaultMbedGate() {
00322 #ifdef USE_INTERFACE_CHIP
00323     const bool ok = ReadOneIPFrom(kDefMbedGateFilen, fMbedGate);
00324 #ifdef DEBUG
00325     printf("gate   = %s\r\n", fMbedGate);
00326 #endif
00327     return ok;
00328 #else // do not USE_INTERFACE_CHIP
00329     return false;
00330 #endif // USE_INTERFACE_CHIP
00331 }
00332 
00333 
00334 void SnConfigFrame::SetDefaultIPs() {
00335     GetMacAddress(); // just to make sure it gets read
00336     SetDefaultRemoteServ();
00337     SetDefaultRemotePort();
00338     SetDefaultMbedIP();
00339     SetDefaultMaskIP();
00340     SetDefaultGateIP();
00341 }
00342 
00343 void SnConfigFrame::ApplyConnectListenSafetyNets(const uint8_t dataStreamIdx) {
00344     const float maxto_f = (fCommWinDuration/(60.*static_cast<float>(kNcomms)));
00345     const uint8_t maxto = (maxto_f < kDefTimeoutMin) ? kDefTimeoutMin :
00346         (maxto_f > 255.0) ? kDefTimeoutSafe : static_cast<uint8_t>(maxto_f);
00347     if (fCommWinConnTOMins[dataStreamIdx] < kDefTimeoutMin) {
00348         fCommWinConnTOMins[dataStreamIdx] = kDefTimeoutMin;
00349     }
00350     if (fCommWinConnTOMins[dataStreamIdx] > maxto) {
00351         fCommWinConnTOMins[dataStreamIdx] = maxto;
00352     }
00353     if (fCommWinListTOMins[dataStreamIdx] < kDefTimeoutMin) {
00354         fCommWinListTOMins[dataStreamIdx] = kDefTimeoutMin;
00355     }
00356     if (fCommWinListTOMins[dataStreamIdx] > maxto) {
00357         fCommWinListTOMins[dataStreamIdx] = maxto;
00358     }
00359 }
00360 
00361 void SnConfigFrame::ApplyConnectListenSafetyNets() {
00362     for (uint8_t i=0; i<kNumDatStreams; ++i) {
00363         ApplyConnectListenSafetyNets(i);
00364     }
00365 }
00366 
00367 void SnConfigFrame::ApplySafetyNets() {
00368     if (fFirstSeq>kMaxFirstSeq) {
00369         fFirstSeq=kMaxFirstSeq;
00370     }
00371 #if CHIPBOARD==ATWD4CH
00372     if (fNumPlas>kNplas) {
00373         fNumPlas=kNplas;
00374     }
00375 #endif
00376     if (fNumCardsMajLog>kNchans) {
00377         fNumCardsMajLog=kNchans;
00378     }
00379     if (fNumCardsMajLog<1u) {
00380         fNumCardsMajLog=1u;
00381     }
00382     if ( (fForceTrigPeriod>0) &&
00383          (fForceTrigPeriod<kMinForcePer) ) {
00384         fForceTrigPeriod = kMinForcePer;
00385     }
00386     if (fEvtThrtlPeriodMs>kMaxThrottlePerMs) {
00387         fEvtThrtlPeriodMs=kMaxThrottlePerMs;
00388     }
00389     if ( (IsPoweredFor(kIridComWin)==false) &&
00390          (IsPoweredFor(kAfarComWin)==false) ) {
00391         EnablePowerFor(kIridComWin);
00392         EnablePowerFor(kAfarComWin);
00393     }
00394     if (fBatVoltToLowPwr>kMaxBatVoltLowPwr) {
00395         fBatVoltToLowPwr=kMaxBatVoltLowPwr;
00396     }
00397     if (fBatVoltFromLowPwr>kMaxBatVoltLowPwr) {
00398         fBatVoltFromLowPwr=kMaxBatVoltLowPwr;
00399     }
00400     if (fBatVoltFromLowPwr<fBatVoltToLowPwr) {
00401         fBatVoltFromLowPwr=fBatVoltToLowPwr;
00402     }
00403     if (fCommWinPeriod>kMaxCommWinPeriod) {
00404         fCommWinPeriod=kMaxCommWinPeriod;
00405     }
00406     if (fCommWinPeriod<kMinCommWinPeriod) {
00407         fCommWinPeriod=kMinCommWinPeriod;
00408     }
00409     if (fCommWinDuration<kMinCommWinDur) {
00410         fCommWinDuration=kMinCommWinDur;
00411     }
00412     if (fCommWinPrdLowPwr>kMaxCommWinPeriod) {
00413         fCommWinPrdLowPwr=kMaxCommWinPeriod;
00414     }
00415     if (fCommWinDurLowPwr<kMinCommWinDur) {
00416         fCommWinDurLowPwr=kMinCommWinDur;
00417     }
00418     ApplyConnectListenSafetyNets();
00419     if (fWatchDogPeriod>kMaxWatchDogPer) {
00420         fWatchDogPeriod=kMaxWatchDogPer;
00421     }
00422     if (fWatchDogPeriod<kMinWatchDogPer) {
00423         fWatchDogPeriod=kMinWatchDogPer;
00424     }
00425     if (fSnglFreqRatio<kMinSingleFreqSuppRatio) {
00426         fSnglFreqRatio=kDefSingleFreqSuppRatio;
00427     }
00428     if (fSnglFreqRatio>kMaxSingleFreqSuppRatio) {
00429         fSnglFreqRatio=kDefSingleFreqSuppRatio;
00430     }
00431 #ifdef DEBUG
00432     printf("||||||||| safety: fSnglFreqRatio=%hhu\r\n", fSnglFreqRatio);
00433 #endif
00434 }
00435 
00436 uint32_t SnConfigFrame::GetTimeoutTime(const uint32_t startTime,
00437                                        const uint32_t delta) const {
00438     //  --.-----lst------.--delta--.--
00439     //    .              .         .
00440     //   start        current    returnVal
00441     //
00442     //   lio=lst+delta bound by comm wind dur
00443     //   returns start + lio
00444     
00445     const uint32_t ct = time(0);
00446     uint32_t lst = ct-startTime;
00447     if ( (ct<startTime) || (ct==0) ||
00448          (lst>kSecsPerDay) ) {
00449         // possible clock problems
00450         lst = static_cast<uint32_t>(kDefTimeoutSafe)*60u;
00451     }
00452     const uint32_t lio = 
00453         ((lst+delta) < GetCommWinDuration()) ?
00454           lst+delta  : GetCommWinDuration();
00455     return lio+startTime;
00456 }
00457 
00458 void SnConfigFrame::ChangeToLowPower() {
00459     
00460     // save old label
00461     memcpy(fNormLabel, fLabel, kConfLblLen);
00462     
00463     // append label
00464     // this will allow the new config to be put in the DB
00465     int slen = strlen(fLabel);
00466     static const char* tag = "_LOWPOW";
00467     const int ml = strlen(tag)+1;
00468     if (slen > (kConfLblLen-ml) ) {
00469         memset(fLabel+kConfLblLen-ml, '\0', ml);
00470     }
00471     strncat(fLabel, tag, ml-1);
00472     
00473     // save power settings
00474     fNormPowerMode = fPowerMode;
00475     
00476     // change power settings
00477     DisablePowerFor(kAmpsDatTak);
00478     DisablePowerFor(kCardDatTak);
00479     DisablePowerFor(kIridDatTak);
00480     DisablePowerFor(kAfarDatTak);
00481     DisablePowerFor(kAmpsComWin);
00482     DisablePowerFor(kCardComWin);
00483     if ( IsSBDonlyLowPwrMode() ) {
00484         EnablePowerFor(kIridComWin);
00485         DisablePowerFor(kAfarComWin);
00486     } else if ( (IsPoweredFor(kIridComWin)==false) &&
00487                 (IsPoweredFor(kAfarComWin)==false) ) {
00488         // TODO: turn on only iridum maybe?
00489         EnablePowerFor(kIridComWin);
00490         EnablePowerFor(kAfarComWin);
00491     } // else same as normal for Irid and Afar Com Win
00492 
00493     // set mode to low power
00494     fIsLowPower = true;
00495 
00496     if (fgApplySafetyNets) {
00497         ApplySafetyNets();
00498     }
00499 }
00500 
00501 void SnConfigFrame::ChangeToNormPower() {
00502     // put label back
00503     memcpy(fLabel, fNormLabel, kConfLblLen);
00504     // put power settings back
00505     fPowerMode = fNormPowerMode;
00506     // set mode to normal
00507     fIsLowPower = false;
00508 
00509     if (fgApplySafetyNets) {
00510         ApplySafetyNets();
00511     }
00512 }
00513 
00514 void SnConfigFrame::GetPackParsFor(const EDatPackBit d,
00515                                    uint8_t& loseLSB, uint8_t& loseMSB,
00516                                    uint16_t& wvBase) const {
00517     const bool pack = IsDatPackedFor(d);
00518     loseLSB = pack ? GetWvLoseLSB()  : 0u;
00519     loseMSB = pack ? GetWvLoseMSB()  : 0u;
00520     wvBase  = pack ? GetWvBaseline() : 0u;
00521 }
00522 
00523 void SnConfigFrame::GetHiLoPlas(const uint16_t pla,
00524                                 uint16_t& hiPla,
00525                                 uint16_t& loPla,
00526                                 const bool r2l) {
00527    // split the PLA bitword into 2: one for the high threshold
00528    // and one for the low threshold. "lows" in the string will become
00529    // "highs" in the low threshold PLA.
00530    // 
00531    // example 1)
00532    // PLA string = HLHL....
00533    // hi thresh  = H.H.....
00534    // lo thresh  = .H.H....
00535    //
00536    // example 2)
00537    // PLA string = HBL.....
00538    // hi thresh  = HL......
00539    // lo thresh  = .LH.....
00540    //
00541    // (with . = A here, to make the example more readable)
00542    //
00543    // A = 11, B = 00
00544    // H = 01 or 10, alternating
00545    // L = 10 or 01, alternating
00546    // 01 at leftmost bits is H
00547    // for example:
00548    // 0x7FFF = 01 11 11 11 11 11 11 11
00549    // => HAAAAAAA for LEFT TO RIGHT
00550    // => AAAAAAAH for RIGHT TO LEFT
00551    // 0x56FF = 01 01 01 10 11 11 11 11
00552    // => HLHHAAAA for LEFT TO RIGHT
00553    // => AAAAHHLH for RIGHT TO LEFT
00554    //
00555    // so HHHHHHHH is
00556    // 01 10 01 10 01 10 01 10 always (r2l or l2r)
00557    //
00558    // r2l = whether to read bits right to left (true) or not (false)
00559    // Mahshid liked right to left
00560    // Liang liked left to right
00561    // so we allow for either
00562    
00563    const int8_t start = (r2l) ?             0 : BITS_IN_SHORT-2;
00564    const int8_t end   = (r2l) ? BITS_IN_SHORT : -2;
00565    const int8_t step  = (r2l) ?             2 : -2;
00566    
00567    uint8_t hi= (r2l) ? 0x2 : 0x1;
00568    uint8_t lo= (r2l) ? 0x1 : 0x2;
00569    
00570    // set all bits to 0
00571    hiPla = 0;
00572    loPla = 0;
00573    
00574    for (int8_t i=start; i!=end; i+=step, hi^=0x3, lo^=0x3) {
00575       const uint8_t b = (pla & (0x3<<i)) >> i;
00576       if (b==hi) {
00577          hiPla |=  hi << i;
00578          loPla |= 0x3 << i;
00579       } else if (b==lo) {
00580          hiPla |= 0x3 << i;
00581          loPla |=  hi << i;
00582       } else if (b==0x3) {
00583          // any
00584          hiPla |= 0x3 << i;
00585          loPla |= 0x3 << i;
00586       } else {
00587          // no check that b is something else.. should be impossible.
00588          // between
00589          hiPla |=  lo << i;
00590          loPla |=  lo << i;
00591       }
00592    }
00593    
00594 }
00595 
00596 bool SnConfigFrame::ReadFromFile(const char* cfile) {
00597     // intended only for reading default config file
00598     
00599     /*
00600     DIR* d;
00601     struct dirent* dent;
00602     printf("files in /local:\r\n");
00603     if ( (d = opendir( "/local" ))!=NULL ) {
00604         while ( (dent = readdir(d))!=NULL ) {
00605             printf("%s\r\n",dent->d_name);
00606         }
00607         closedir(d);
00608     }
00609     */
00610 #ifdef DEBUG
00611     printf("trying to read config [%s]\r\n",cfile);
00612 #endif
00613     bool ret = false;
00614     FILE* cf = fopen(cfile,"rb");
00615     if (cf!=0) {
00616 #ifdef DEBUG
00617         printf("opened file\r\n");
00618 #endif
00619         // check the header and file size to be
00620         // protect a bit against corruption
00621         uint8_t hc; uint32_t hl;
00622         SnHeaderFrame::ReadFrom(cf, hc, hl);
00623 #ifdef DEBUG
00624         printf("hc=%hhu, hl=%u\r\n",hc,hl);
00625 #endif
00626         if (hc==SnHeaderFrame::kConfigCode) {
00627             const int fpos = ftell(cf);
00628             // how many bytes?
00629             fseek(cf, 0, SEEK_END); // go to end
00630             const int fend = ftell(cf);
00631             fseek(cf, fpos, SEEK_SET); // go back
00632 
00633 #ifdef DEBUG
00634             printf("fend-fpos=%d-%d=%d\r\n",fend,fpos,fend-fpos);
00635 #endif            
00636             if (hl == fend-fpos) {
00637                 ReadFrom(cf);
00638                 ret = (ferror(cf)==0);
00639 #ifdef DEBUG
00640                 printf("ret = %d\r\n",(int)ret);
00641 #endif
00642             }
00643         }
00644         fclose(cf);
00645     }
00646     return ret;
00647 }
00648 
00649 bool SnConfigFrame::WriteToFile(const char* cfile) const {
00650     // intended only for writing default config file
00651     
00652     bool ret = false;
00653     FILE* cf = fopen(cfile,"wb");
00654     if (cf!=0) {
00655         WriteTo(cf);
00656         ret = (ferror(cf)==0);
00657         fclose(cf);
00658     }
00659     return ret;
00660 }
00661 
00662 void SnConfigFrame::SetSDNeedToInitFlag() {
00663     // reset the SD card init cache, in case the SD ignore run mode changed
00664     SnSDUtils::SetDoNeedToInit();
00665 }
00666 
00667 void SnConfigFrame::GetIpStrFromVal(const uint32_t ip,
00668                                     char(& str)[SnConfigFrame::kIPLen]) {
00669     if (ip==kDefIPvalue) {
00670         snprintf(str, kIPLen, kDefIPflag);
00671     } else {
00672         // little endian, but same method is used in ipToVal so the
00673         // conversions will be consistent on this machine, but of course,
00674         // the remote machine better send the right integer...
00675         union {
00676           uint8_t  c[4];
00677           uint32_t u;
00678         } x;
00679         x.u = ip;
00680         snprintf(str, kIPLen, "%hhu.%hhu.%hhu.%hhu",
00681                 x.c[3], x.c[2], x.c[1], x.c[0]);
00682     }
00683 }
00684 
00685 uint32_t SnConfigFrame::GetIpValFromStr(const char(& str)[SnConfigFrame::kIPLen]) {
00686     if (strncmp(str, kDefIPflag, kIPLen)==0) {
00687         return kDefIPvalue;
00688     } else {
00689         union {
00690           uint8_t  c[4];
00691           uint32_t u;
00692         } x;
00693         // 17 = space for terminating null
00694         // little endian, but same method is used in ipToVal so the
00695         // conversions will be consistent on this machine, but of course,
00696         // the remote machine better send the right integer...
00697         sscanf(str, "%hhu.%hhu.%hhu.%hhu",
00698               x.c+3, x.c+2, x.c+1, x.c);
00699         return x.u;
00700     }
00701 }