Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
Diff: main.cpp
- Revision:
- 116:8099b754fbb4
- Parent:
- 114:554fa3a956b4
- Child:
- 119:b3d7699d0eb0
--- a/main.cpp Fri Dec 04 02:57:12 2015 +0000 +++ b/main.cpp Tue May 03 02:01:35 2016 +0000 @@ -12,15 +12,37 @@ #include "SnConstants.h" #ifndef USE_INTERFACE_CHIP -// to avoid calling the interface chip, -// the mac address is hard coded (ugh!) +#include "SnUIDtoMac.h" extern "C" void mbed_mac_address(char * mac) { #ifdef DEBUG printf("calling MY mbed_mac_address\r\n"); #endif - memmove(mac, kDefaultMacAdress, sizeof(kDefaultMacAdress)); + // to avoid calling the interface chip, the mac address may be hard coded (ugh!) + + // even though SnConfigFrame will cache the mac address, + // it appears some low level code (in Ethernet?) calls this + // function. altho searching the code for mbed_mac_address doesn't + // find it, this function still gets called. + // so -- cache the result and return it. + static char cachedMac[sizeof(uint64_t)]; + static bool cached = false; + if (cached) { + memmove(mac, cachedMac, sizeof(uint64_t)); +#ifdef DEBUG + printf("using cached mac=%02X%02X%02X%02X%02X%02X\r\n", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); +#endif + } else { + SnUIDtoMac::GetMacAddress(mac); + memmove(cachedMac, mac, sizeof(uint64_t)); + cached = true; +#ifdef DEBUG + printf("got new mac mac=%02X%02X%02X%02X%02X%02X\r\n", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); +#endif + } }; -#endif +#endif // USE_INTERFACE_CHIP #ifdef DEBUG #include "SnMemMonitor.h" @@ -78,6 +100,10 @@ DigitalOut led3(LED3,1); DigitalOut led4(LED4,1); +#ifndef CHIPBOARD +#error CHIPBOARD is not defined! Define it in SnPreCompOptions.h +#endif + // Set up power pins - Note that it's Zero for "on" in ATWD2013, but high for "on" in SST2014 #if CHIPBOARD==ATWD4CH DigitalOut PIN_turn_on_system(p17,1); // this turns off the system @@ -163,8 +189,10 @@ #define MAIN_SERIALTYPE Serial #endif // USE_MODSERIAL +//#if defined(DEBUG) || defined(ENABLE_USB_COMM) || defined(EVT_TIME_PROFILE) // this needs to be first in case some other global uses a print statement static MAIN_SERIALTYPE gCpu( USBTX, USBRX ); // defined here so it might be used for debugging output +//#endif // DEBUG or ENABLE_USB_COMM static MAIN_SERIALTYPE gSBDport(p28, p27, #ifdef USE_MODSERIAL @@ -185,7 +213,7 @@ void ReadAllRegisters(); void ReadRegister(const uint8_t chan, int16_t* dev); void SaveHeartbeat(); -void SaveEvent(const int32_t etms); +bool SaveEvent(const int32_t etms); void WaitTrigAndSendClock(); void SetConfigAndMakeOutputFile(); SnCommWin::ECommWinResult OpenCommWin(const bool forceReconfig=false, @@ -209,12 +237,18 @@ void InitTempProbe(); #endif void ResetCountersClearEvt(); +/* void CalcRate(const uint32_t numtrgs, const double tottime_ms, float& rate); void GetRates(float& thmrate, float& evtrate); -void AddToRate(const double dt, const bool isThm); +void AddToRate(const double dt, const bool isThm, + const uint32_t nev=1u); +*/ bool IsSeqComplete(); +void PrepForSeqClose(); +void PrepForNewSeq(double& etms); +float GetSeqLivetime(); void procForceTrigger(); void procHeartbeat(); void procPowerCheck(); @@ -247,10 +281,11 @@ static Ticker gTempCheckTicker; #endif // USE_RTOS static Timer gAllTrgTimer; -static Timer gThmTrgTimer; +static Timer gTrgLiveTimer; // in case the sequence is "short" +//static Timer gThmTrgTimer; static Timer gAdcToMBtimer; -static Timer gSinceClkSet; +static Timer gSinceClkSet; // this timer can roll over; the offline software accounts for it static SnClockSetFrame gClkSet; static SnSignalStrengthFrame gSigStr; #ifdef DISABLE_CONFIG_SAFETYNETS @@ -279,6 +314,7 @@ //static uint32_t gTrgNum[kNumTrgs] = {0}; // num of this type of trg received static uint32_t gNumThmTrigs = 0; // number of thermal triggers counted static uint32_t gNumFrcTrigs = 0; // number of forced triggers counted +static uint32_t gNumSavedEvts = 0; // number of events saved. differs from gEvtNum as this one always starts at 0, no matter the current sequence number static uint8_t gL1ScaledownCount = 0; // write an event every X L1 failures // i/o static time_t gLastCommWin = 0; // time @@ -291,14 +327,15 @@ static volatile bool gHrtbtFired = false; static uint32_t gHrtbtNum = 0; // rates -static double gThmDtSum = 0; // sum of all time diffs between thermal trigs -static double gEvtDtSum = 0; // sum of all time diffs between events -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 +//static double gThmDtSum = 0; // sum of all time diffs between thermal trigs +//static double gEvtDtSum = 0; // sum of all time diffs between events +//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 - + SnEventFrame::kMaxSizeOf // (this is redundant and could be removed if mem is sparse) - + 256; // breathing room + + SnEventFrame::kMaxSizeOf // this is too big, because max status frame already includes an ATWD 4*128samp event (as of status i/o v9) + //- SnEventFrame::kMaxSizeOfV1 // so we should be able to do this.. but requires long term testing as of 2016-04-26 + + 256; // some breathing room static char gGenBuf[gBufSize]; // must be big enough for event or status or config! static SnCommWin* gComms[kNcomms] = { 0 }; // order => priority. afar uses RTOS, and must be made inside main #if defined(ENABLE_AFAR_TWITTER) && defined(ENABLE_AFAR_COMM) @@ -574,14 +611,15 @@ gEvtNum = evtStartCurSeq; gPowNum = evtStartCurSeq; // memset(gTrgNum, 0, sizeof(uint32_t)*kNumTrgs); + gNumSavedEvts = 0; gNumThmTrigs = 0; gNumFrcTrigs = 0; gForcedTrig = false; // reset rate counters - gThmDtSum = 0; - gThmNumDt = 0; - gEvtDtSum = 0; - gEvtNumDt = 0; +// gThmDtSum = 0; +// gThmNumDt = 0; +// gEvtDtSum = 0; +// gEvtNumDt = 0; // reset heartbeat counters gLastHrtbt = 0; gHrtbtFired = false; @@ -598,6 +636,7 @@ #endif } +/* void CalcRate(const uint32_t numtrgs, const double tottime_ms, float& rate) { @@ -625,13 +664,17 @@ CalcRate(gEvtNumDt, gEvtDtSum, evtrate); } -void AddToRate(const double dt, const bool isThm) { + +void AddToRate(const double dt, const bool isThm, + const uint32_t nev) { + // isThm==true => specifically a thermal trigger, not necessarily saved + // isThm==false => ANY event (thermal or forced) that gets saved if (isThm) { gThmDtSum += dt; - gThmNumDt += 1u; + gThmNumDt += nev; } else { gEvtDtSum += dt; - gEvtNumDt += 1u; + gEvtNumDt += nev; } #ifdef DEBUG printf("** AddToRate: dt=%g, isThm=%d\r\n",dt,(int)isThm); @@ -640,6 +683,7 @@ gThmNumDt, gThmDtSum, gEvtNumDt, gEvtDtSum); #endif } +*/ bool IsSeqComplete() { #ifdef DEBUG @@ -838,7 +882,9 @@ #endif Watchdog::kick(gConf.GetWatchdogPeriod()); +//#if defined(DEBUG) || defined(ENABLE_USB_COMM) || defined(EVT_TIME_PROFILE) gCpu.baud(CPUBAUD_SN); +//#endif // DEBUG or ENABLE_USB_COMM { #if defined(SSNOTIFY) || defined(DEBUG) @@ -1029,16 +1075,29 @@ SnSDUtils::WriteTrigWaitWinTime(SnSDUtils::GetCurFile(), gClkSet, true); - gThmTrgTimer.reset(); gThmTrgTimer.start(); +// gThmTrgTimer.reset(); gThmTrgTimer.start(); gAllTrgTimer.reset(); gAllTrgTimer.start(); + gTrgLiveTimer.reset(); gTrgLiveTimer.start(); gStTrgStartClk = gClkSet; #if CHIPBOARD!=ATWD4CH // reset in case a trigger arrived before we were ready // this is mostly to ensure that the chip gets reset on soft // reboot, in case it got stopped prior to the reboot - PIN_ResetChips = 1; - PIN_ResetChips = 0; + if (gConf.IsSkippingTrgStartReset()==false) { +#ifdef DEBUG + printf("-----------------------------------------\r\n"); + printf("trigger start reset\r\n"); #endif + PIN_ResetChips = 1; + PIN_ResetChips = 0; + } +#ifdef DEBUG + else { + printf("-----------------------------------------\r\n"); + printf("SKIP trig start reset\r\n"); + } +#endif // DEBUG +#endif // not atwd4ch } #if CHIPBOARD==ATWD4CH @@ -1060,13 +1119,14 @@ led1 = 0; led4 = 1; // signal reading out - const double ttms = gThmTrgTimer.read_us() / 1e3; // for rate calculation +// const double ttms = gThmTrgTimer.read_us() / 1e3; // for rate calculation const double atms = gAllTrgTimer.read_us() / 1e3; // for throttle -// if (gEvent.IsForcedTrg()==false) { +/* if (gForcedTrig==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 @@ -1080,7 +1140,7 @@ if (gForcedTrig==false) { // ++(gTrgNum[kThmTrg]); ++gNumThmTrigs; - AddToRate(ttms, true); +// AddToRate(ttms, true); } if ( gForcedTrig || gFirstEvt || @@ -1091,17 +1151,28 @@ #endif // EVT_TIME_PROFILE // want to keep this event. save it (and check if it passes L1) - SaveEvent(etms); - AddToRate(etms, false); - etms=0; + const bool saved = SaveEvent(etms); + if (saved) { +// AddToRate(etms, false); + ++gNumSavedEvts; + etms=0; + } #ifdef EVT_TIME_PROFILE gProfiler.stop(); aftSaveEvt=gProfiler.read_us(); gProfiler.start(); #endif // EVT_TIME_PROFILE - + } else { #if CHIPBOARD!=ATWD4CH - // reset in case a trigger arrived before we were ready + // got a trigger, but don't want the event. reset the chip to continue triggering +#ifdef DEBUG + printf(">>>>>>> THROW EVENT AWAY! forced=%s, first=%s, " + "etms=%g, throttle=%hu, etms>=thr=%s\r\n", + (gForcedTrig ? "true" : "false"), + (gFirstEvt ? "true" : "false"), + etms, gConf.GetEvtThrtlPeriodMs(), + (etms>=gConf.GetEvtThrtlPeriodMs() ? "true" : "false")); +#endif // DEBUG PIN_ResetChips = 1; PIN_ResetChips = 0; #endif @@ -1165,21 +1236,14 @@ if (gOpenCommWin) { #ifdef DEBUG printf("gOpenComWin=%s, opening\r\n",gOpenCommWin?"true":"false"); - printf("WriteTrigWaitWinTime (stop)\r\n"); #endif - gClkSet.UpdateClock( gSinceClkSet ); - SnSDUtils::WriteTrigWaitWinTime(SnSDUtils::GetCurFile(), - gClkSet, - false); - gStTrgStopClk = gClkSet; + PrepForSeqClose(); led1 = 0; // signal not waiting OpenCommWin(); led1 = 1; // end signal not waiting gOpenCommWin=false; - gFirstEvt = true; - gAllTrgTimer.reset(); - gThmTrgTimer.reset(); - etms=0; + PrepForNewSeq(etms); + } else { #ifdef DEBUG printf("gOpenCommWin=false, gCommWinChecks=%u, gNcommWinChecks=%u\r\n", @@ -1194,19 +1258,11 @@ if (IsSeqComplete()) { #ifdef DEBUG printf("seq complete. sngseq=%d\r\n",gConf.IsSingleSeqRunMode()); - printf("WriteTrigWaitWinTime (stop)\r\n"); #endif led1 = 1; led2 = 1; led4 = 1; // signal saving file - gClkSet.UpdateClock( gSinceClkSet ); - SnSDUtils::WriteTrigWaitWinTime(SnSDUtils::GetCurFile(), - gClkSet, - false); - gStTrgStopClk = gClkSet; + PrepForSeqClose(); MakeOutputFile(gConf.IsSingleSeqRunMode()); - gFirstEvt = true; - gThmTrgTimer.reset(); - gAllTrgTimer.reset(); - etms=0; + PrepForNewSeq(etms); led1 = 1; led2 = 0; led4 = 0; // end signal saving file } #ifdef EVT_TIME_PROFILE @@ -1236,6 +1292,46 @@ } +float GetSeqLivetime() { + const float dt = gStTrgStopClk.GetCurTime() - gStTrgStartClk.GetCurTime(); + if ( dt < kAbsMaxTimer ) { + // the timer should be valid (not rolled over) + return gTrgLiveTimer.read(); + } else { + // lose the sub-second resolution, but who cares + return dt; + } +} + +void PrepForSeqClose() { +#ifdef DEBUG + printf("WriteTrigWaitWinTime (stop)\r\n"); +#endif + // add on time since last trigger/event so rates are better calculated + // do not increment trigger/event counters, however +// AddToRate( gThmTrgTimer.read_us() / 1e3, true, 0 ); +// AddToRate( gAllTrgTimer.read_us() / 1e3, false, 0 ); + gTrgLiveTimer.stop(); + // write the trigger stop time + gClkSet.UpdateClock( gSinceClkSet ); + SnSDUtils::WriteTrigWaitWinTime(SnSDUtils::GetCurFile(), + gClkSet, + false); + // save copy of trig stop time so it can be sent in status data pack + gStTrgStopClk = gClkSet; +} + +void PrepForNewSeq(double& etms) { + // reset timers, first event flag and the time since last saved event + gFirstEvt = true; + gAllTrgTimer.reset(); +// gThmTrgTimer.reset(); + gTrgLiveTimer.reset(); + etms=0; +} + + + // // save a heartbeat tag // @@ -1256,8 +1352,9 @@ // // save the event // -void SaveEvent(const int32_t etms) { +bool SaveEvent(const int32_t etms) { // write the event + bool didSave = false; #ifdef DEBUG // check that the event is still the same as gLastEvent @@ -1287,6 +1384,7 @@ // read data & calc CRC #ifdef EVT_TIME_PROFILE int befReadWv=0, aftReadWv=0, befWriteEvt=0, aftWriteEvt=0; + int befL1=0, aftL1=0; gProfiler.stop(); befReadWv=gProfiler.read_us(); gProfiler.start(); #endif // EVT_TIME_PROFILE @@ -1295,7 +1393,7 @@ gEvent.ReadWaveformsATWD(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit); #else gEvent.ReadWaveformsSST(PIN_spi, PIN_readingData); - // reset in case a trigger arrived before we were ready + // reset the digitizer so it will continue waiting for a trigger PIN_ResetChips = 1; // wait_us(1); PIN_ResetChips = 0; @@ -1359,6 +1457,10 @@ gConf.GetSingleFreqSuppRatio()); #endif +#ifdef EVT_TIME_PROFILE + gProfiler.stop(); befL1=gProfiler.read_us(); gProfiler.start(); +#endif // EVT_TIME_PROFILE + // TODO: move the FFT calculation out here so that // other L1's could use it too. haven't done this already // in order to save RAM and not cache the whole thing when @@ -1393,6 +1495,7 @@ // ----- #ifdef EVT_TIME_PROFILE + gProfiler.stop(); aftL1=gProfiler.read_us(); gProfiler.start(); gProfiler.stop(); befWriteEvt=gProfiler.read_us(); gProfiler.start(); #endif // EVT_TIME_PROFILE @@ -1402,14 +1505,16 @@ #else PIN_readingData = 0; // unlock so we can talk to the SD card #endif - + // scale down to override L1 trigger failures if ( (L1okToSave==false) && (gConf.GetL1Scaledown()!=0) ) { ++gL1ScaledownCount; - if ( gL1ScaledownCount == gConf.GetL1Scaledown() ) { + // check with >= in case the config changes + if ( gL1ScaledownCount >= gConf.GetL1Scaledown() ) { gL1ScaledownCount = 0; L1okToSave = true; + gEvent.SetTrgBit(kL1Scaledown); #ifdef DEBUG printf("))) L1 scaledown!\r\n"); #endif @@ -1432,6 +1537,9 @@ // a good event gStNewEvent = true; + // mark that the event was actually accepted + didSave = true; + // send it? if ( gConf.IsCommWindowEachEvent() ) { #ifdef DEBUG @@ -1445,6 +1553,7 @@ gProfiler.stop(); aftWriteEvt=gProfiler.read_us(); gProfiler.start(); printf("befReadWv=%d, aftReadWv=%d, befWriteEvt=%d, aftWriteEvt=%d\r\n", befReadWv, aftReadWv, befWriteEvt, aftWriteEvt); + printf("befL1=%d, aftL1=%d\r\n", befL1, aftL1); #endif // EVT_TIME_PROFILE // make a copy in case we need to send it with the status @@ -1458,6 +1567,8 @@ #ifdef DEBUG printf("next gEvtNum=%u\r\n",gEvtNum); #endif + + return didSave; } void MakeOutputFile(const bool stopRunning) { @@ -2207,11 +2318,13 @@ SnCommWin::ECommWinResult res = SnCommWin::kUndefFail; // get the trigger rates - float thmrate=0, evtrate=0; - GetRates(thmrate, evtrate); +// float thmrate=0, evtrate=0; +// GetRates(thmrate, evtrate); + const float seqlive = GetSeqLivetime(); #ifdef DEBUG printf("config=%s\r\n", gConf.GetLabel()); - printf("thmrate=%g, evtrate=%g\r\n",thmrate,evtrate); +// printf("thmrate=%g, evtrate=%g\r\n",thmrate,evtrate); + printf("SEQ livetime = %g\r\n", seqlive); printf("Free memory = %d\r\n", FreeMem()); #endif @@ -2359,7 +2472,9 @@ // status has not yet been sent over this peripheral) // const SnCommWin::ECommWinResult conres = (*cw)->OpenWindow( *ss, - gConf, gPower, gEvent, SnSDUtils::GetCurSeqNum(), thmrate, evtrate, + gConf, gPower, gEvent, SnSDUtils::GetCurSeqNum(), +// thmrate, evtrate, + gNumThmTrigs, gNumSavedEvts, seqlive, gPowerOnTime, gTemperature, gGenBuf, gConf.GetTimeoutTime(gLastCommWin, conto)); @@ -2545,7 +2660,8 @@ const uint32_t extraDiscTime = gLastCommWin + gConf.GetCommWinConnectTO((*cw)->GetCommType()); (*cw)->CloseConn( - gConf.GetTimeoutTime(extraDiscTime, gConf.GetCommWinDuration())); + gConf.GetTimeoutTime(extraDiscTime, gConf.GetCommWinDuration()), + gGenBuf, true); // send the "closing window" signal *nc = false; } @@ -2626,6 +2742,7 @@ const uint32_t extraDiscTime = gLastCommWin + gConf.GetCommWinConnectTO((*cw)->GetCommType()); (*cw)->CloseConn(gConf.GetTimeoutTime(extraDiscTime, gConf.GetCommWinDuration())); + // no "close window" signal sent here... *nc = false; } } // end loop: check time, close conns