Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
Diff: main.cpp
- Revision:
- 40:1324da35afd4
- Parent:
- 39:2f17131d22a5
- Child:
- 41:d6f5e2f09e07
--- a/main.cpp Tue Jul 30 02:03:21 2013 +0000 +++ b/main.cpp Sat Oct 05 04:45:22 2013 +0000 @@ -6,11 +6,11 @@ #define DISABLE_CONFIG_SAFETYNETS #define ENABLE_AFAR_COMM -#define ENABLE_SBD_COMM +//#define ENABLE_SBD_COMM //#define ENABLE_USB_COMM //#define ENABLE_AFAR_TWITTER -//#define USE_RTOS_TIMER +//#define USE_RTOS // change in CommConstants and EthernetPower also //#define USE_ETH_INTERFACE //#define EVT_TIME_PROFILE //#define DEBUG @@ -35,6 +35,7 @@ #include "SnStatusFrame.h" #include "SnHeaderFrame.h" #include "SnHeartbeatFrame.h" +#include "SnClockSetFrame.h" #include "SnCommWin.h" #ifdef USE_ETH_INTERFACE #include "SnCommAfarTCP.h" @@ -55,6 +56,7 @@ #include "RtosTimer.h" #endif +extern "C" void mbed_reset(); // // MBED PINS (ordered by number) @@ -131,14 +133,15 @@ void SaveEvent(const int32_t etms); void WaitTrigAndSendClock(); void SetConfigAndMakeOutputFile(); -SnCommWin::ECommWinResult OpenCommWin(const bool forceReconfig=false); +SnCommWin::ECommWinResult OpenCommWin(const bool forceReconfig=false, + const bool isStartupWin=false); void MakeOutputFile(const bool stopRunning=false); void SetPower(const bool isCommWin); void procForceTrigger(); void procHeartbeat(); void procPowerCheck(); void procCommWin(); -#ifdef USE_RTOS_TIMER +#ifdef USE_RTOS void procForceTrigger(void const *) { return procForceTrigger(); } void procHeartbeat(void const *) { return procHeartbeat(); } void procPowerCheck(void const *) { return procPowerCheck(); } @@ -150,7 +153,7 @@ // // readout objs // TODO: use RtosTimer instead of Ticker? -#ifdef USE_RTOS_TIMER +#ifdef USE_RTOS static rtos::RtosTimer* gForceTicker; static rtos::RtosTimer* gHeartbeatTicker; static rtos::RtosTimer* gCommWinTicker; @@ -161,14 +164,17 @@ static Ticker gCommWinTicker; static Ticker gPowerCheckTicker; #endif -static Timer gTrgTimer; +static Timer gAllTrgTimer; +static Timer gThmTrgTimer; static Timer gAdcToMBtimer; +static SnClockSetFrame gClkSet; #ifdef DISABLE_CONFIG_SAFETYNETS static SnConfigFrame gConf(false); #else static SnConfigFrame gConf; #endif static SnEventFrame gEvent; +static SnEventFrame gLastEvent; static SnPowerFrame gPower; // parameters static bool gCardsPowered = false; @@ -184,6 +190,7 @@ static time_t gLastCommWin = 0; // time static uint32_t gCommWinChecks = 0; static uint32_t gNcommWinChecks = 0; +static uint16_t gConsecCommFails = 0; // heartbeat static time_t gLastHrtbt = 0; static volatile bool gHrtbtFired = false; @@ -194,7 +201,8 @@ static uint32_t gThmNumDt = 0; // number of thermal trig time diffs added up static uint32_t gEvtNumDt = 0; // number of event time diffs added up // this should be bigger than anything that will actually be used -static const uint32_t gBufSize=SnStatusFrame::kMaxSizeOf + (2u*SnHeaderFrame::kMaxSizeOf) + SnPowerFrame::kMaxSizeOf; +static const uint32_t gBufSize=SnStatusFrame::kMaxSizeOf + (2u*SnHeaderFrame::kMaxSizeOf) + SnPowerFrame::kMaxSizeOf + + SnEventFrame::kMaxSizeOf; // (this is redundant and could be removed if mem is sparse) //static const uint32_t gB64Bsize=BASE64ENC_LEN(gBufSize)+1; //static char gB64Buf[gB64Bsize]; static char gGenBuf[gBufSize]; // must be big enough for event or status or config! @@ -352,7 +360,7 @@ const uint32_t evtStartCurSeq = (SnSDUtils::GetCurSeqNum()) // no -1; start with seq=0 * gConf.GetEvtsPerFile(); gEvent.ClearEvent(); - gEvtNum = gConf.GetFirstEvt() + evtStartCurSeq; + gEvtNum = evtStartCurSeq; gPowNum = evtStartCurSeq; memset(gTrgNum, 0, sizeof(uint32_t)*kNumTrgs); // reset rate counters @@ -402,9 +410,9 @@ bool IsSeqComplete() { #ifdef DEBUG - printf("IsSeqComplete: eps=%u, cntpow=%d, fe=%u, pow=%u, evt=%u, seq=%hu\r\n", + printf("IsSeqComplete: eps=%u, cntpow=%d, pow=%u, evt=%u, seq=%hu\r\n", gConf.GetEvtsPerFile(), (int)gConf.IsCountingPowerReadings(), - gConf.GetFirstEvt(), gPowNum, gEvtNum, SnSDUtils::GetCurSeqNum()); + gPowNum, gEvtNum, SnSDUtils::GetCurSeqNum()); #endif if (gConf.GetEvtsPerFile()>0) { const uint32_t evtEndCurSeq = (SnSDUtils::GetCurSeqNum()+1) // account for seq=0 @@ -416,14 +424,14 @@ return (gPowNum>=evtEndCurSeq); } else { // first event num is a one-time per run offset, not one per sequence - return (gEvtNum>=(gConf.GetFirstEvt()+evtEndCurSeq)); + return (gEvtNum>=evtEndCurSeq); } } else { return false; } } -#ifdef USE_RTOS_TIMER +#ifdef USE_RTOS void stopTicker(rtos::RtosTimer* tik) { if (tik!=0) { tik->stop(); @@ -435,7 +443,7 @@ } #endif -#ifdef USE_RTOS_TIMER +#ifdef USE_RTOS float resetTicker(rtos::RtosTimer* tik, const float timSec, const float maxTimSec) { if (tik!=0) { @@ -470,16 +478,16 @@ } void ResetAllTickers() { -#ifdef USE_RTOS_TIMER +#ifdef USE_RTOS const float ftp = resetTicker(gForceTicker, gConf.GetForceTrigPeriod(), kAbsMaxTimer); - wait_ms(131); // make it less likely for multiple triggers to fire too close together + Thread::wait(131); // make it less likely for multiple triggers to fire too close together const float hbp = resetTicker(gHeartbeatTicker, gConf.GetHeartbeatPeriod(), kAbsMaxTimer); - wait_ms(173); // make it less likely for multiple triggers to fire too close together + Thread::wait(173); // make it less likely for multiple triggers to fire too close together const float cwp = resetTicker(gCommWinTicker, gConf.GetCommWinPeriod(), kCommWinLongPrdTk); - wait_ms(169); // make it less likely for multiple triggers to fire too close together + Thread::wait(169); // make it less likely for multiple triggers to fire too close together const float pcp = resetTicker(gPowerCheckTicker, gConf.GetVoltCheckPeriod(), kAbsMaxTimer); #else @@ -511,14 +519,34 @@ OpenCommWin(); while (true) { led3 = 1; led4=1; +#ifdef USE_RTOS + Thread::wait(500); +#else wait(0.5); +#endif led3 = 0; led4=0; +#ifdef USE_RTOS + Thread::wait(500); +#else wait(0.5); +#endif // don't kick the watchdog // if we do, the station is unrecoverable without physical access } } + +void InitSDCard() { +#ifdef DEBUG + printf("initializing SD card..\r\n"); +#endif + // initialize the SD card. this should prevent the issue with + // seq 0 being overwritten upon power up or the SD card first + // being insterted + sd.disk_initialize(); +} + + int main() { // a failsafe Watchdog::kick(WDFAILSAFE); @@ -528,32 +556,22 @@ #if defined(SSNOTIFY) || defined(DEBUG) printf("main: start\r\n"); #endif +#ifdef USE_RTOS + led1=1; Thread::wait(200); + led1=0; led2=1; Thread::wait(200); + led2=0; led3=1; Thread::wait(200); + led3=0; led4=1; Thread::wait(200); +#else led1=1; wait(0.2); led1=0; led2=1; wait(0.2); led2=0; led3=1; wait(0.2); led3=0; led4=1; wait(0.2); +#endif led4=0; } -#ifdef DEBUG - printf("initializing SD card..\r\n"); -#endif - // initialize the SD card. this should prevent the issue with - // seq 0 being overwritten upon power up or the SD card first - // being insterted - sd.disk_initialize(); - - /* - { - uint32_t nfls=0; float totkb=0; - SnSDUtils::GetDirProps(SnSDUtils::kSDdir, nfls, totkb); - totkb /= 1e3; // KB -#ifdef DEBUG - printf("nfiles=%u, tb=%g kb (%g)\r\n",nfls,totkb,totkb/1024.0); -#endif - } - */ - + SnSDUtils::fgDoInit = &InitSDCard; + #ifdef DEBUG printf("making comm objects\r\n"); #endif @@ -572,19 +590,23 @@ #endif #endif #ifdef ENABLE_SBD_COMM - //gComms[comi++] = new SnCommSBD(&gSBDport, &gCpu); - gComms[comi++] = new SnCommWinSBD(&gSBDport, &gCpu); + gComms[comi++] = new SnCommWinSBD(&gSBDport); #endif #ifdef ENABLE_USB_COMM - //gComms[comi++] = new SnCommUsb(&gCpu); gComms[comi++] = new SnCommWinUsb(&gCpu); #endif #ifdef DEBUG printf("made comm objects\r\n"); #endif - -#ifdef USE_RTOS_TIMER + + if (comi!=kNcomms) { + error("comi=[%hhu] != kNcomms=[%hhu]\r\n", + comi, kNcomms); + // will die here with blue lights of death + } + +#ifdef USE_RTOS gForceTicker = new rtos::RtosTimer(&procForceTrigger); gHeartbeatTicker = new rtos::RtosTimer(&procHeartbeat); gCommWinTicker = new rtos::RtosTimer(&procCommWin); @@ -592,7 +614,6 @@ #endif led2=1; - //wait_ms(100); #ifdef DEBUG printf("\n\n\n\n\n\nstarting\r\n"); @@ -607,7 +628,7 @@ #endif gLastCommWin = time(0); // prevent comm win proc -#ifdef USE_RTOS_TIMER +#ifdef USE_RTOS gForceTicker->stop(); #else gForceTicker.detach(); @@ -623,7 +644,7 @@ #ifdef DEBUG printf("call OpenCommWin\r\n"); #endif - OpenCommWin(true); // alwasy configure, even if no new config + OpenCommWin(true, true); // alwasy configure, even if no new config // get ready to trigger PIN_spi.format( 16, 1 ); // change to data readout format @@ -633,7 +654,6 @@ // the main event loop. wait for triggers in SendClock AreCardsPowered(true); // TODO: should this be an if? - gTrgTimer.start(); register int32_t etms=0; // time between written events while( true ) { @@ -647,6 +667,13 @@ printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false"); printf("readingout=%d\r\n",(int)gReadingOut); #endif + if (gFirstEvt) { + SnSDUtils::WriteTrigWaitWinTime(SnSDUtils::GetCurFile(), + gClkSet, + true); + gThmTrgTimer.reset(); gThmTrgTimer.start(); + gAllTrgTimer.reset(); gAllTrgTimer.start(); + } PIN_lockRegisters = 0; // allow data to come from DFPGA WaitTrigAndSendClock(); PIN_lockRegisters = 1; // block registers during readout @@ -660,9 +687,14 @@ if (gReadingOut) { - const int32_t ttms = gTrgTimer.read_ms(); // time since last trigger - gTrgTimer.reset(); gTrgTimer.start(); // restart trigger timer - etms += ttms; + const int32_t ttms = gThmTrgTimer.read_ms(); // for rate calculation + const int32_t atms = gAllTrgTimer.read_ms(); // for throttle + if (gEvent.IsForcedTrg()==false) { + // don't reset if not a thermal trigger + gThmTrgTimer.reset(); gThmTrgTimer.start(); + } + gAllTrgTimer.reset(); gAllTrgTimer.start(); // restart trigger timer + etms += atms; // time between events Watchdog::kick(); // don't reset! @@ -760,10 +792,14 @@ #ifdef DEBUG printf("gOpenComWin=%s, opening\r\n",gOpenCommWin?"true":"false"); #endif + SnSDUtils::WriteTrigWaitWinTime(SnSDUtils::GetCurFile(), + gClkSet, + false); OpenCommWin(); gOpenCommWin=false; gFirstEvt = true; - gTrgTimer.reset(); + gAllTrgTimer.reset(); + gThmTrgTimer.reset(); etms=0; } else { #ifdef DEBUG @@ -780,9 +816,13 @@ #ifdef DEBUG printf("seq complete. sngseq=%d\r\n",gConf.IsSingleSeqRunMode()); #endif + SnSDUtils::WriteTrigWaitWinTime(SnSDUtils::GetCurFile(), + gClkSet, + false); MakeOutputFile(gConf.IsSingleSeqRunMode()); gFirstEvt = true; - gTrgTimer.reset(); + gThmTrgTimer.reset(); + gAllTrgTimer.reset(); etms=0; } #ifdef EVT_TIME_PROFILE @@ -844,6 +884,11 @@ PIN_lockRegisters = 0; // unlock so we can talk to SD card. SnSDUtils::WriteEventTo(SnSDUtils::GetCurFile(), gGenBuf, gEvent, gConf); + // make a copy in case we need to send it with the status + // (copy it because we are going to clear this event while + // waiting for the next trigger) + gEvent.CopyTo(gLastEvent); + // increment event number ++gEvtNum; @@ -868,11 +913,16 @@ StopRunning(); } FILE* cf = SnSDUtils::OpenNewOutputFile(gConf.GetMacAddress(), - gConf.GetRun()); + gConf.GetRun(), + gConf.GetFirstSeq()); // reset event, timers, trigger counters ResetCountersClearEvt(); if (cf!=0) { +#ifdef USE_RTOS + Thread::wait(200); +#else wait_ms(200); +#endif GetAvePowerReading(); #ifdef DEBUG printf("writing power. v1=%g, v2=%g, r1=%g, r2=%g, t=%u, pownum=%u\r\n", @@ -892,6 +942,20 @@ #endif } +bool PowerDownCommPeriph(const SnConfigFrame::EDatPackBit type) { + + SnCommWin** cw = gComms; + for (uint8_t i=0; i<kNcomms; i++, cw++) { + if ((*cw)==0) { + continue; + } else if ((*cw)->GetCommType()==type) { + return (*cw)->PowerDown(gConf.GetTimeoutTime(time(0), + gConf.GetCommWinConnectTO())); + } + } + return false; +} + // // power stuff // @@ -914,31 +978,94 @@ afarpb = SnConfigFrame::kAfarComWin; } // TODO: turn on amps individually, when that's possible + + // change cards power +#ifdef DEBUG + printf("setting cards pin power\r\n"); +#endif PIN_turn_on_system = gConf.GetPowPinSetting(cardpb); +#ifdef USE_RTOS + Thread::wait(10); +#else wait_ms(10); +#endif + // change amps power +#ifdef DEBUG + printf("setting amps pin power\r\n"); +#endif PIN_turn_on_amps = gConf.GetPowPinSetting(ampspb); +#ifdef USE_RTOS + Thread::wait(10); +#else wait_ms(10); - PIN_iridSbd_power = (kIridAfarPwrSame) +#endif + // change iridium power + // power down periph if going from on to off + const bool iridToOn = (kIridPwrFromAfar) ? + gConf.IsPoweredFor(afarpb) : + gConf.IsPoweredFor(iridpb); + const bool iridFromOn = PIN_iridSbd_power.read()== + (kIridPwrFromAfar ? gConf.GetPowPinSetting(afarpb, true) + : gConf.GetPowPinSetting(iridpb, true)); + if ( iridFromOn && (iridToOn==false) ) { +#ifdef DEBUG + printf("calling PowerDown for Iridium\r\n"); +#endif + PowerDownCommPeriph(SnConfigFrame::kIrid); + } +#ifdef DEBUG + printf("setting iridium pin power\r\n"); +#endif + PIN_iridSbd_power = (kIridPwrFromAfar) ? gConf.GetPowPinSetting(iridpb, false) // leave the iridium relay off. use afar relay. : gConf.GetPowPinSetting(iridpb); +#ifdef USE_RTOS + Thread::wait(10); +#else wait_ms(10); +#endif + // change ethernet PHY port power #ifdef DEBUG printf("afar pin=%d, com powsetting=%d\r\n",PIN_afar_power.read(), gConf.GetPowPinSetting(afarpb)); #endif - if (gConf.IsPoweredFor(afarpb)) { + if (gConf.IsPoweredFor(afarpb) || + (kIridPwrFromAfar && gConf.IsPoweredFor(iridpb)) ) { #ifdef DEBUG printf("PHY cowin powering up\r\n"); #endif - PHY_PowerUp(); wait(1); + PHY_PowerUp(); +#ifdef USE_RTOS + Thread::wait(1000); +#else + wait(1); +#endif #ifdef DEBUG printf("PHY cowin powered up\r\n"); #endif } else { + // change afar power + // power down periph if going from on to off + // change afar power + int afon = gConf.GetPowPinSetting(afarpb, true); + if (kIridPwrFromAfar) { + // NOTE: the following only works because for the + // irid & afar pins, 1 = on! + afon |= gConf.GetPowPinSetting(iridpb, true); + } + const bool afarFromOn = (PIN_afar_power.read()==afon); + if (afarFromOn) { + PowerDownCommPeriph(SnConfigFrame::kAfar); + } #ifdef DEBUG printf("PHY cowin powering down\r\n"); #endif - PHY_PowerDown(); wait(1); + PHY_PowerDown(); +#ifdef USE_RTOS + Thread::wait(1000); +#else + wait(1); +#endif #ifdef DEBUG printf("PHY cowin powered down\r\n"); #endif @@ -946,13 +1073,24 @@ #ifdef DEBUG printf("PHY done\r\n"); #endif +#ifdef USE_RTOS + Thread::wait(100); +#else wait_ms(100); +#endif + // change afar power int afpp = gConf.GetPowPinSetting(afarpb); - if (kIridAfarPwrSame) { + if (kIridPwrFromAfar) { + // NOTE: the following only works because for the + // irid & afar pins, 1 = on! afpp |= gConf.GetPowPinSetting(iridpb); } PIN_afar_power = afpp; - wait(1.5); // let things power up +#ifdef USE_RTOS + Thread::wait(1500); +#else + wait(1.5); +#endif #ifdef DEBUG printf("aft: pconp=%u (%08x), pcenet=%u (%08x)\r\n", LPC_SC->PCONP, LPC_SC->PCONP, LPC1768_PCONP_PCENET, LPC1768_PCONP_PCENET); @@ -983,7 +1121,11 @@ PIN_DoNotRestartAllClocks = 1; PIN_forceTrigger = 0; PIN_heartbeat = 0; +#ifdef USE_RTOS + Thread::wait(20); +#else wait_ms(20); +#endif gCommWinChecks = 0; gNcommWinChecks = gConf.GetCommWinPeriod() / kCommWinLongPrdTk; @@ -998,7 +1140,11 @@ uint16_t hi, lo; PIN_PLA_cs=1; +#ifdef USE_RTOS + Thread::wait(4000); +#else wait(4); +#endif for (uint8_t pi=0; pi<kNplas; pi++) { if (pi < gConf.GetNumPlas()) { SnConfigFrame::GetHiLoPlas(gConf.GetPla(pi), hi, lo); @@ -1016,9 +1162,17 @@ } Watchdog::kick(); } +#ifdef USE_RTOS + Thread::wait(3000); +#else wait(3); +#endif PIN_PLA_cs=0; +#ifdef USE_RTOS + Thread::wait(3000); +#else wait(3); +#endif // DAC values // @@ -1059,7 +1213,11 @@ #ifdef DEBUG printf("dacs set\r\n"); #endif +#ifdef USE_RTOS + Thread::wait(20); +#else wait_ms(20); +#endif } else { #ifdef DEBUG printf("cards off. skipping PLA and DAC setting\r\n"); @@ -1078,7 +1236,11 @@ // make new output file // put after PLA/DAC, in case they affect the power readings +#ifdef USE_RTOS + Thread::wait(200); +#else wait_ms(200); +#endif MakeOutputFile(); // reset tickers @@ -1204,7 +1366,34 @@ } } -SnCommWin::ECommWinResult OpenCommWin(const bool forceReconfig) { +bool IsPinPowered(const SnCommWin* cw) { + bool havePower = false; + switch (cw->GetCommType()) { + case SnConfigFrame::kIrid: + havePower = gConf.IsPoweredFor(SnConfigFrame::kIridComWin) + && ( (kIridPwrFromAfar) + ? PIN_afar_power.read() + : PIN_iridSbd_power.read() == + gConf.GetPowPinSetting(SnConfigFrame::kIridComWin)); + break; + case SnConfigFrame::kAfar: + havePower = gConf.IsPoweredFor(SnConfigFrame::kAfarComWin) + && (PIN_afar_power.read() == + gConf.GetPowPinSetting(SnConfigFrame::kAfarComWin)); + break; + case SnConfigFrame::kUSB: + havePower = true; // USB always on (for now) + break; + case SnConfigFrame::kSDcard: // shouldn't happen. skip it + default: // unknown.. skip it + break; + }; + return havePower; +} + + +SnCommWin::ECommWinResult OpenCommWin(const bool forceReconfig, + const bool isStartupWin) { // loop through each comm mode: // a) try to connect // b) if connected, listen for config @@ -1231,7 +1420,7 @@ #endif StopAllTickers(); - + if (gConf.GetCommWinDuration()==0) { // TODO: set min so this is not possible res = SnCommWin::kOkNoMsg; @@ -1252,16 +1441,19 @@ printf("curfile=%p, filename=%s\r\n",SnSDUtils::GetCurFile(), SnSDUtils::GetCurFileName()); #endif - PIN_lockRegisters = 0; // unlock so we can talk to SD card. + + if (isStartupWin==false) { + PIN_lockRegisters = 0; // unlock so we can talk to SD card. #ifdef DEBUG - printf("closing output file\r\n"); + printf("closing output file\r\n"); #endif - SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile()); + SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile()); #ifdef DEBUG - printf("open existing file (%d)\r\n",strlen(SnSDUtils::GetCurFileName())); + printf("open existing file (%d)\r\n",strlen(SnSDUtils::GetCurFileName())); #endif - SnSDUtils::OpenExistingFile(SnSDUtils::GetCurFileName(), true, false); - + SnSDUtils::OpenExistingFile(SnSDUtils::GetCurFileName(), true, false); + } + #ifdef DEBUG printf("setting power\r\n"); #endif @@ -1269,7 +1461,9 @@ SetPower(true); // time to recount files for the status update - SnStatusFrame::fgRecalcFiles = true; + // for the startup win, don't access SD card in case we + // rebooted due to a problem with the SD card + SnStatusFrame::fgRecalcFiles = !isStartupWin; #if defined(ENABLE_AFAR_TWITTER) && defined(ENABLE_AFAR_COMM) bool doTwitter = false; @@ -1300,56 +1494,47 @@ // port is powered down, making an Ethernet obejct // (done in netif) will stall forever waiting for the clock. // Do it here to keep all PIN usage in main.cpp - bool havePower=false; - switch ((*cw)->GetCommType()) { - case SnConfigFrame::kIrid: - havePower = gConf.IsPoweredFor(SnConfigFrame::kIridComWin) - && ( (kIridAfarPwrSame) - ? PIN_afar_power.read() - : PIN_iridSbd_power.read() == - gConf.GetPowPinSetting(SnConfigFrame::kIridComWin)); - break; - case SnConfigFrame::kAfar: - havePower = gConf.IsPoweredFor(SnConfigFrame::kAfarComWin) - && (PIN_afar_power.read() == - gConf.GetPowPinSetting(SnConfigFrame::kAfarComWin)); - break; - case SnConfigFrame::kUSB: - havePower = true; // USB always on (for now) - break; - case SnConfigFrame::kSDcard: // shouldn't happen. skip it - default: // unknown.. skip it - break; - }; + const bool havePower=IsPinPowered(*cw); if (havePower==false) { continue; } - + + // always apply safety nets to connection and listen so + // that we don't accidently shut down comms (i.e. with + // connectTO or listnTO being 0) + gConf.ApplyConnectListenSafetyNets(); const uint32_t conto = - (gConf.GetCommWinDuration() < (*cw)->GetConnectTimeout()) ? - gConf.GetCommWinDuration() : (*cw)->GetConnectTimeout(); + (gConf.GetCommWinDuration() < gConf.GetCommWinConnectTO()) ? + gConf.GetCommWinDuration() : gConf.GetCommWinConnectTO(); const uint32_t listo = - (gConf.GetCommWinDuration() < (*cw)->GetListenTimeout()) ? - gConf.GetCommWinDuration() : (*cw)->GetListenTimeout(); - + (gConf.GetCommWinDuration() < gConf.GetCommWinListenTO()) ? + gConf.GetCommWinDuration() : gConf.GetCommWinListenTO(); + // update power reading in case we want to send it in status GetAvePowerReading(); // open window and (mabye) send status update #ifdef DEBUG printf("calling OpenWindow. ss=%d\r\n",(int)(*ss)); + printf("conto=%u, listo=%u, dur=%u, connTO=%u, lisTO=%u\r\n", + conto,listo,gConf.GetCommWinDuration(), + gConf.GetCommWinConnectTO(), gConf.GetCommWinListenTO()); printf("gtt=%u, ct=%d, lcw=%d, dur=%u\r\n",gConf.GetTimeoutTime(gLastCommWin,conto), time(0), gLastCommWin, gConf.GetCommWinDuration()); #endif const SnCommWin::ECommWinResult conres = (*cw)->OpenWindow( - gConf.GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gEvent, gPower, +// gConf.GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gEvent, gPower, + gConf.GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gLastEvent, gPower, SnSDUtils::GetCurSeqNum(), thmrate, evtrate, gGenBuf); if (conres>=SnCommWin::kConnected) { Watchdog::kick(); // don't reset! // connected. listen for config *ss = false; // don't send status next time - + + // clear watchdog reset bit now that we've told someone + Watchdog::clearResetFlag(); + #if defined(ENABLE_AFAR_TWITTER) && defined(ENABLE_AFAR_COMM) if ((*cw)->GetCommType()==SnConfigFrame::kAfar) { // if we connected by Afar @@ -1373,17 +1558,34 @@ // send data if need be (files, some events, etc) const uint32_t winto = gConf.GetTimeoutTime(gLastCommWin, gConf.GetCommWinDuration()); - const uint32_t gtt = gConf.IsObeyingTimeout() ? winto : 0; + //const uint32_t gtt = gConf.IsObeyingTimeout() ? winto : 0; + + // check if there are any requests before sending data + if (gConf.IsWaitingHndShkBeforeSendData()) { + // send handshake request + (*cw)->SendHndshkReq(gGenBuf, winto); + // wait for response + uint8_t hndshk(0); uint32_t hndshkLen(0); + res = (*cw)->WaitHandshake(gConf, winto, gGenBuf, gBufSize, hndshk, + &hndshkLen); + // handle response + if (SnCommWin::kOkWithMsg==res) { + res = (*cw)->HandleHandshake(SnSDUtils::GetCurFile(), + SnSDUtils::GetCurFileName(), + gConf, gLastEvent, gPower, gGenBuf, gBufSize, + winto, hndshk, hndshkLen); + } + } if (gConf.GetCommSendData()!=0) { #ifdef DEBUG - printf("sending data, gtt=%u. lcw=%u, dur=%u, obey=%s\r\n", - gConf.GetTimeoutTime(gLastCommWin, gConf.GetCommWinDuration()), + printf("sending data, winto=%u. lcw=%u, dur=%u, obey=%s\r\n", + winto, gLastCommWin, gConf.GetCommWinDuration(), gConf.IsObeyingTimeout() ? "true" : "false"); #endif - res = (*cw)->SendData(gConf, gEvent, gPower, gGenBuf, gBufSize, - gtt, gConf.GetCommWinDuration()); + res = (*cw)->SendData(gConf, gLastEvent, gPower, gGenBuf, gBufSize, + winto); } else { // don't send anything res = cfgres; @@ -1395,6 +1597,7 @@ break; } } else { + // OpenWindow did not connect (*cw)->CloseConn(gConf.GetTimeoutTime(gLastCommWin, listo)); } // if connected @@ -1407,26 +1610,31 @@ if ((*cw)==0) { continue; } + const bool havePower=IsPinPowered(*cw); + if (havePower==false) { + continue; + } + // check Iridium time - // add on the SBD connect timeout so that we have a - // chance to set the clock even if we never got a response from UCI - const uint32_t extraTime = gLastCommWin + kConnectSBDTO; if ((*cw)->GetCommType()==SnConfigFrame::kIrid) { #ifdef DEBUG printf("try to set iridium time\r\n"); #endif // set the clock before closing connection const bool con = - (*cw)->Connect(gConf.GetTimeoutTime(extraTime, + (*cw)->Connect(gConf.GetTimeoutTime(gLastCommWin, gConf.GetCommWinDuration())); if (con) { - const uint32_t nt = (*cw)->TrySetSysTimeUnix( - gConf.GetTimeoutTime(extraTime,gConf.GetCommWinDuration())); + uint32_t prvTime(0), setTime(0); + const bool settime = (*cw)->TrySetSysTimeUnix( + gConf.GetTimeoutTime(gLastCommWin, + gConf.GetCommWinDuration()), + prvTime, setTime); + gClkSet.SetClocks(prvTime, setTime); } } - // close the connection - (*cw)->CloseConn(gConf.GetTimeoutTime(extraTime,gConf.GetCommWinDuration())); - Watchdog::kick(); // don't reset! + // close the connection -- this must be why Twitter didn't work! + //(*cw)->CloseConn(gConf.GetTimeoutTime(gLastCommWin,gConf.GetCommWinDuration())); // after normal Afar connection closed, try to tweet #if defined(ENABLE_AFAR_TWITTER) && defined(ENABLE_AFAR_COMM) if ((*cw)->GetCommType()==SnConfigFrame::kAfar) { @@ -1448,7 +1656,7 @@ #endif const SnCommWin::ECommWinResult conres = gTwit->OpenWindow( gConf.GetTimeoutTime(gLastCommWin, conto), false, gConf, - gEvent, gPower, + gLastEvent, gPower, SnSDUtils::GetCurSeqNum(), thmrate, evtrate, gGenBuf); if (conres>=SnCommWin::kConnected) { @@ -1457,9 +1665,22 @@ gConf.GetTimeoutTime(time(0), listo)); } } - } + } // end tweet block #endif + Watchdog::kick(); // don't reset! + } // end loop: check time, tweet, etc + + // close connections + const uint32_t extraDiscTime = gLastCommWin + gConf.GetCommWinConnectTO(); + cw = gComms; + for (uint8_t i=0; i<kNcomms; i++, cw++) { + if ((*cw)==0) { + continue; + } else { + (*cw)->CloseConn(gConf.GetTimeoutTime(extraDiscTime, gConf.GetCommWinDuration())); + } } + } // if duration >0 /* not working. must use DEFCONF.DAT to change IP's. @@ -1473,6 +1694,25 @@ } } */ + + + // check if we missed too many consecutive connections + if (res<=SnCommWin::kAllFails) { + ++gConsecCommFails; +#ifdef DEBUG + printf("gConsecCommFails=%hu, kMaxConsecCommFails=%hu\r\n", + gConsecCommFails,kMaxConsecCommFails); +#endif + if (gConsecCommFails>kMaxConsecCommFails) { +#ifdef DEBUG + printf("rebooting\r\n"); +#endif + // goodbye cruel world, it's over. walk on by... + mbed_reset(); + } + } else { + gConsecCommFails=0; + } // (probably) power down comms and power up cards,amps SetPower(false);