Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

SnConfigFrame.cpp

Committer:
uci1
Date:
2013-01-23
Revision:
31:b5bd3b189150
Parent:
28:484943132bb0
Child:
39:2f17131d22a5

File content as of revision 31:b5bd3b189150:

#include "SnConfigFrame.h"

#include "mbed.h"

#include "SnBitUtils.h"
#include "SnHeaderFrame.h"
#include "Watchdog.h"

extern "C" void mbed_mac_address(char *);

bool              SnConfigFrame::fgApplySafetyNets     = true;
const uint8_t     SnConfigFrame::kIOVers               = 4;
const char* const SnConfigFrame::kDefConfFile          = "/local/DEFCONF.DAT";
const char* const SnConfigFrame::kDefIPflag            = "DEF";
const uint32_t    SnConfigFrame::kMinCommWinPrdLowPwr  = 14400;    // exclusive min low power comm win period (s)
const uint32_t    SnConfigFrame::kMaxCommWinPrdLowPwr  = 259200;   // exclusive max low power comm win period (s)
const uint32_t    SnConfigFrame::kMinCommWinDurLowPwr  = 300;      // exclusive min low power comm win duration (s)
const uint32_t    SnConfigFrame::kMaxCommWinDurLowPwr  = 3600;     // exclusive max low power comm win duration (s)
const uint8_t     SnConfigFrame::kConfLblLen;

uint64_t       SnConfigFrame::fgMacAdr              = 0;

void SnConfigFrame::SetMacAddress() {
    static const uint8_t b64 = sizeof(uint64_t);
    static char c[b64];
    mbed_mac_address(&(c[0]));
    // like a big endian union
    fgMacAdr = 0;
    const char* a = c+(b64-1);
    for (uint8_t i=0; i<b64; i++, a--) {
        fgMacAdr |= static_cast<uint64_t>(*a) << (i<<3);
    }
}

void SnConfigFrame::SetHardDefaults() {
    sprintf(fLabel,"HardDefaults");
    fConfTime           = 1338854400u; // Tue, 05 Jun 2012 00:00:00 GMT
    fRun                = 0;
    fFirstEvt           = 0;
    fEvtsPerSeq         = 1000;
    fRunMode            = 0;
    fStreamHiLoPlas     = 0;
    fWvLoseLSB          = 0;
    fWvLoseMSB          = 4;
    fWvBaseline         = 0;
    fDatPackType        = ~0;
    uint16_t* dc = &(fDAC[0][0]);
    for (uint16_t i=0; i<kTotDacs; i++, dc++) {
        *dc             = 3072u;
    }
    fNumPlas            = 1;
    uint16_t* pl = &(fPLA[0]);
    for (uint8_t j=0; j<kNplas; j++, pl++) {
        *pl             = 0x7FFFu;
    }
    fNumCardsMajLog     = 2;
    fEnableThermTrig    = 1;
    fForceTrigPeriod    = 67u;
    fHeartBeatPeriod    = 0;
    fAmpsOn             = 0x0Fu;
    fEvtThrtlPeriodMs   = 50u;
    fPowerMode          = kAmpsDatTak|kCardDatTak|kAmpsComWin|kCardComWin|kIridComWin|kAfarComWin;
    fBatVoltLowPwr      = 0;
    fVoltCheckPeriod    = 600u;
    fCommWinPeriod      = 3600u;
    fCommWinDuration    = 600u;
    fCommSendData       = static_cast<int16_t>(kUseBits);
    fCommWinPrdLowPwr   = 86100u;
    fCommWinDurLowPwr   = 300u;
    fWatchDogPeriod     = WDFAILSAFE;
    SetDefaultIPs();
    fIsLowPower         = false;
    memcpy(fNormLabel, fLabel, kConfLblLen);
    fNormPowerMode      = fPowerMode;
    

}

void SnConfigFrame::SetDefaultRemoteServ() {
    sprintf(fRemoteServer,"%s","128.195.204.151");
}

void SnConfigFrame::SetDefaultRemotePort() {
    fRemotePort         = 6655;
}

void SnConfigFrame::SetDefaultMbedIP() {
    const uint64_t ip = GetMacAddress();
    switch (ip) {
        case 0x0002F7F0C3B60000: // station 3
            sprintf(fMbedIP,"%s","157.132.94.35");
            break;
        case 0x0002F7F0C41C0000: // station 4
            sprintf(fMbedIP,"%s","157.132.94.37");
            break;
        case 0x0002F7F0AEE00000: // station 5
            sprintf(fMbedIP,"%s","157.132.94.39");
            break;
        case 0x0002F7F0C4450000: // station 6
            sprintf(fMbedIP,"%s","157.132.94.41");
            break;
        case 0x0002F7F0D2880000: // station 7
            sprintf(fMbedIP,"%s","157.132.94.43");
            break;
        case 0x0002F7F0C0F80000: // station 8
            sprintf(fMbedIP,"%s","157.132.94.45");
            break;
        default: // what??
            sprintf(fMbedIP,"%s","157.132.94.30"); // anciet station
            break;
    };
}
// brian dornick 3107
void SnConfigFrame::SetDefaultMaskIP() {
    sprintf(fMbedMask,"%s","255.255.255.0");
}

void SnConfigFrame::SetDefaultGateIP() {
    sprintf(fMbedGate,"%s","157.132.94.1");
}

void SnConfigFrame::SetDefaultIPs() {
    SetDefaultRemoteServ();
    SetDefaultRemotePort();
    SetDefaultMbedIP();
    SetDefaultMaskIP();
    SetDefaultGateIP();
}

void SnConfigFrame::ApplySafetyNets() {
    if (fNumPlas>kNplas) {
        fNumPlas=kNplas;
    }
    if (fNumCardsMajLog>kNchans) {
        fNumCardsMajLog=kNchans;
    }
    if (fNumCardsMajLog<1u) {
        fNumCardsMajLog=1u;
    }
    if ( (fForceTrigPeriod>0) &&
         (fForceTrigPeriod<kMinForcePer) ) {
        fForceTrigPeriod = kMinForcePer;
    }
    if (fEvtThrtlPeriodMs>kMaxThrottlePerMs) {
        fEvtThrtlPeriodMs=kMaxThrottlePerMs;
    }
    if ( (IsPoweredFor(kIridComWin)==false) &&
         (IsPoweredFor(kAfarComWin)==false) ) {
        EnablePowerFor(kIridComWin);
        EnablePowerFor(kAfarComWin);
    }
    if (fBatVoltLowPwr>kMaxBatVoltLowPwr) {
        fBatVoltLowPwr=kMaxBatVoltLowPwr;
    }
    if (fCommWinPeriod>kMaxCommWinPeriod) {
        fCommWinPeriod=kMaxCommWinPeriod;
    }
    if (fCommWinDuration<kMinCommWinDur) {
        fCommWinDuration=kMinCommWinDur;
    }
    if (fCommWinPrdLowPwr>kMaxCommWinPeriod) {
        fCommWinPrdLowPwr=kMaxCommWinPeriod;
    }
    if (fCommWinDurLowPwr<kMinCommWinDur) {
        fCommWinDurLowPwr=kMinCommWinDur;
    }
    if (fWatchDogPeriod>kMaxWatchDogPer) {
        fWatchDogPeriod=kMaxWatchDogPer;
    }
    if (fWatchDogPeriod<kMinWatchDogPer) {
        fWatchDogPeriod=kMinWatchDogPer;
    }
}

uint32_t SnConfigFrame::GetTimeoutTime(const uint32_t startTime,
                                       const uint32_t delta) const {
    const uint32_t ct = time(0);
    uint32_t lst = time(0)-startTime;
    if ( (ct<startTime) || (ct==0) ||
         (lst>kSecsPerDay) ) {
        // possible clock problems
        lst = kDefTimeout;
    }
    const uint32_t lio = 
        ((lst+delta) < GetCommWinDuration()) ?
          lst+delta  : GetCommWinDuration();
    return lio+startTime;
}

void SnConfigFrame::ChangeToLowPower() {
    
    // save old label
    memcpy(fNormLabel, fLabel, kConfLblLen);
    
    // append label
    // this will allow the new config to be put in the DB
    int slen = strlen(fLabel);
    static const char* tag = "_LOWPOW";
    const int ml = strlen(tag)+1;
    if (slen > (kConfLblLen-ml) ) {
        memset(fLabel+kConfLblLen-ml, '\0', ml);
    }
    strncat(fLabel, tag, ml-1);
    
    // save power settings
    fNormPowerMode = fPowerMode;
    
    // change power settings
    DisablePowerFor(kAmpsDatTak);
    DisablePowerFor(kCardDatTak);
    DisablePowerFor(kIridDatTak);
    DisablePowerFor(kAfarDatTak);
    DisablePowerFor(kAmpsComWin);
    DisablePowerFor(kCardComWin);
    if ( (IsPoweredFor(kIridComWin)==false) &&
         (IsPoweredFor(kAfarComWin)==false) ) {
        // TODO: turn on only iridum maybe?
        EnablePowerFor(kIridComWin);
        EnablePowerFor(kAfarComWin);
    }
    // set mode to low power
    fIsLowPower = true;
}

void SnConfigFrame::ChangeToNormPower() {
    // put label back
    memcpy(fLabel, fNormLabel, kConfLblLen);
    // put power settings back
    fPowerMode = fNormPowerMode;
    // set mode to normal
    fIsLowPower = false;
}

void SnConfigFrame::GetPackParsFor(const EDatPackBit d,
                                   uint8_t& loseLSB, uint8_t& loseMSB,
                                   uint16_t& wvBase) const {
    const bool pack = IsDatPackedFor(d);
    loseLSB = pack ? GetWvLoseLSB()  : 0u;
    loseMSB = pack ? GetWvLoseMSB()  : 0u;
    wvBase  = pack ? GetWvBaseline() : 0u;
}

void SnConfigFrame::GetHiLoPlas(const uint16_t pla,
                                uint16_t& hiPla,
                                uint16_t& loPla,
                                const bool r2l) {
   // split the PLA bitword into 2: one for the high threshold
   // and one for the low threshold. "lows" in the string will become
   // "highs" in the low threshold PLA.
   // 
   // example 1)
   // PLA string = HLHL....
   // hi thresh  = H.H.....
   // lo thresh  = .H.H....
   //
   // example 2)
   // PLA string = HBL.....
   // hi thresh  = HL......
   // lo thresh  = .LH.....
   //
   // (with . = A here, to make the example more readable)
   //
   // A = 11, B = 00
   // H = 01 or 10, alternating
   // L = 10 or 01, alternating
   // 01 at leftmost bits is H
   // for example:
   // 0x7FFF = 01 11 11 11 11 11 11 11
   // => HAAAAAAA for LEFT TO RIGHT
   // => AAAAAAAH for RIGHT TO LEFT
   // 0x56FF = 01 01 01 10 11 11 11 11
   // => HLHHAAAA for LEFT TO RIGHT
   // => AAAAHHLH for RIGHT TO LEFT
   //
   // so HHHHHHHH is
   // 01 10 01 10 01 10 01 10 always (r2l or l2r)
   //
   // r2l = whether to read bits right to left (true) or not (false)
   // Mahshid liked right to left
   // Liang liked left to right
   // so we allow for either
   
   const int8_t start = (r2l) ?             0 : BITS_IN_SHORT-2;
   const int8_t end   = (r2l) ? BITS_IN_SHORT : -2;
   const int8_t step  = (r2l) ?                        2 : -2;
   
   uint8_t hi= (r2l) ? 0x2 : 0x1;
   uint8_t lo= (r2l) ? 0x1 : 0x2;
   
   // set all bits to 0
   hiPla = 0;
   loPla = 0;
   
   for (int8_t i=start; i!=end; i+=step, hi^=0x3, lo^=0x3) {
      const uint8_t b = (pla & (0x3<<i)) >> i;
      if (b==hi) {
         hiPla |=  hi << i;
         loPla |= 0x3 << i;
      } else if (b==lo) {
         hiPla |= 0x3 << i;
         loPla |=  hi << i;
      } else if (b==0x3) {
         // any
         hiPla |= 0x3 << i;
         loPla |= 0x3 << i;
      } else {
         // no check that b is something else.. should be impossible.
         // between
         hiPla |=  lo << i;
         loPla |=  lo << i;
      }
   }
   
}

bool SnConfigFrame::ReadFromFile(const char* cfile) {
    // intended only for reading default config file
    
    /*
    DIR* d;
    struct dirent* dent;
    printf("files in /local:\r\n");
    if ( (d = opendir( "/local" ))!=NULL ) {
        while ( (dent = readdir(d))!=NULL ) {
            printf("%s\r\n",dent->d_name);
        }
        closedir(d);
    }
    */
    bool ret = false;
    FILE* cf = fopen(cfile,"rb");
    if (cf!=0) {
        // check the header and file size to be
        // protect a bit against corruption
        uint8_t hc; uint32_t hl;
        SnHeaderFrame::ReadFrom(cf, hc, hl);
        if (hc==SnHeaderFrame::kConfigCode) {
            const int fpos = ftell(cf);
            // how many bytes?
            fseek(cf, 0, SEEK_END); // go to end
            const int fend = ftell(cf);
            fseek(cf, fpos, SEEK_SET); // go back
            
            if (hl == fend-fpos) {
                ReadFrom(cf);
                ret = (ferror(cf)==0);
            }
        }
        fclose(cf);
    }
    return ret;
}

bool SnConfigFrame::WriteToFile(const char* cfile) const {
    // intended only for writing default config file
    
    bool ret = false;
    FILE* cf = fopen(cfile,"wb");
    if (cf!=0) {
        WriteTo(cf);
        ret = (ferror(cf)==0);
        fclose(cf);
    }
    return ret;
}