Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

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