Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Revision:
22:f957c4f840ad
Parent:
21:ce51bb0ba4a5
Child:
23:ccf39298f205
--- a/main.cpp	Wed Oct 10 05:54:12 2012 +0000
+++ b/main.cpp	Tue Oct 16 04:47:44 2012 +0000
@@ -1,10 +1,11 @@
 #include "mbed.h"
+// start a watchdog as soon as possible
+#include "Watchdog.h"
+Watchdog::SnKickStarter gKickStarter(WDFAILSAFE);
 
 //#define USE_RTOS_TIMER
 //#define USE_ETH_INTERFACE
-
 //#define EVT_TIME_PROFILE
-
 //#define DEBUG
 //#define SSNOTIFY
 #define USE_MODSERIAL
@@ -17,7 +18,6 @@
 #define MODSERIAL_TX_BUF_SIZE 512
 #endif
 #include "FATDirHandle.h"
-#include "Watchdog.h"
 #include "EthernetPowerControl.h"
 #include "SnConstants.h"
 #include "SnBitUtils.h"
@@ -26,6 +26,7 @@
 #include "SnEventFrame.h"
 #include "SnStatusFrame.h"
 #include "SnHeaderFrame.h"
+#include "SnHeartbeatFrame.h"
 #include "SnCommWin.h"
 #ifdef USE_ETH_INTERFACE
 #include "SnCommAfarTCP.h"
@@ -110,6 +111,7 @@
 //
 void                      ReadAllRegisters();
 void                      ReadRegister(const uint8_t chan, int16_t* dev);
+void                      SaveHeartbeat();
 void                      SaveEvent(const int32_t etms);
 void                      WaitTrigAndSendClock();
 void                      SetConfigAndMakeOutputFile();
@@ -160,11 +162,17 @@
 static uint32_t       gTrgNum[kNumTrgs] = {0}; // num of this type of trg received
 // i/o
 static time_t         gLastCommWin      = 0; // time
-static uint32_t       gRecentCountTime  = 0; // time of most recent event (for rate)
-static uint32_t       gLastCountReset   = 0; // start time of event count (for rate)
-static uint32_t       gLastEventReset   = 0; // start event number (for rate)
-static uint32_t       gRecentEvtNum     = 0; // number of most recent event (for rate)
-static bool           gDoResetLastCount = false;
+static uint32_t       gCommWinChecks    = 0;
+static uint32_t       gNcommWinChecks   = 0;
+// heartbeat
+static time_t         gLastHrtbt        = 0;
+static 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
 // 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 gB64Bsize=BASE64ENC_LEN(gBufSize)+1;
@@ -200,6 +208,9 @@
         PIN_heartbeat = 0;
         PIN_heartbeat = 1; // heartbeat pulse
         PIN_heartbeat = 0;
+        gLastHrtbt    = time(0);
+        gHrtbtFired   = true;
+        ++gHrtbtNum;
     }
 }
 
@@ -211,8 +222,14 @@
 }
 
 void procCommWin() {
+    ++gCommWinChecks;
     if (gReadingOut==false && gCommWinOpen==false) {
-        if ( (time(0) - gLastCommWin) > gConf.GetCommWinPeriod() ) {
+        //if ( (time(0) - gLastCommWin) > gConf.GetCommWinPeriod() ) {
+#ifdef DEBUG
+        printf("<><><><><><> gCommWinChecks=%u, gNcommWinChecks=%u\r\n",
+            gCommWinChecks, gNcommWinChecks);
+#endif
+        if ( gCommWinChecks >= gNcommWinChecks ) {
 #ifdef DEBUG
             printf("proc comm win\r\n"); 
 #endif
@@ -317,7 +334,15 @@
     gEvtNum = gConf.GetFirstEvt() + evtStartCurSeq;
     gPowNum = evtStartCurSeq;
     memset(gTrgNum, 0, sizeof(uint32_t)*kNumTrgs);
-    gDoResetLastCount = true;
+    // reset rate counters
+    gThmDtSum = 0;
+    gThmNumDt = 0;
+    gEvtDtSum = 0;
+    gEvtNumDt = 0;
+    // reset heartbeat counters
+    gLastHrtbt  = 0;
+    gHrtbtFired = false;
+    gHrtbtNum   = 0;
 #ifdef DEBUG
     printf("Reset: gEvtNum=%u, gPowNum=%u, evtStartCS=%u\r\n",
         gEvtNum, gPowNum, evtStartCurSeq);
@@ -326,12 +351,32 @@
 
 void GetRates(float& thmrate, float& evtrate) {
     thmrate = evtrate = 0;
-    const uint32_t dt = gRecentCountTime - gLastCountReset;
-    if (dt>0) {
-        const float fdt = static_cast<float>(dt);
-        thmrate = static_cast<float>(gTrgNum[kThmTrg]) / fdt;
-        evtrate = static_cast<float>(gRecentEvtNum - gLastEventReset) / fdt;
+#ifdef DEBUG
+    printf("** Getting rates: gThmNumDt=%d, gThmDtSum=%g, "
+           "gEvtNumDt=%d, gEvtDtSum=%g\r\n",
+           gThmNumDt, gThmDtSum, gEvtNumDt, gEvtDtSum);
+#endif
+    
+    thmrate = (gThmDtSum>0.0) ? static_cast<float>(gThmNumDt) / (gThmDtSum/1e3)
+                              : 0;
+    evtrate = (gEvtDtSum>0.0) ? static_cast<float>(gEvtNumDt) / (gEvtDtSum/1e3)
+                              : 0;
+}
+
+void AddToRate(const float dt, const bool isThm) {
+    if (isThm) {
+        gThmDtSum += dt;
+        gThmNumDt += 1u;
+    } else {
+        gEvtDtSum += dt;
+        gEvtNumDt += 1u;
     }
+#ifdef DEBUG
+    printf("** AddToRate: dt=%g, isThm=%d\r\n",dt,(int)isThm);
+    printf("** AddToRate: gThmNumDt=%d, gThmDtSum=%g, "
+           "gEvtNumDt=%d, gEvtDtSum=%g\r\n",
+           gThmNumDt, gThmDtSum, gEvtNumDt, gEvtDtSum);
+#endif
 }
 
 bool IsSeqComplete() {
@@ -377,12 +422,6 @@
         if (timSec>0) {
             float tp = timSec > maxTimSec ? maxTimSec : timSec;
             tp *= 1000u; // ms
-            /*
-            if (tik==gForceTicker) {
-                tik->start((1./10.)*1e3);
-                return ((1./10.)*1e3);
-            } else
-            */
             tik->start(tp);
             return tp;
         }
@@ -448,11 +487,15 @@
         wait(0.5);
         led3 = 0; led4=0;
         wait(0.5);
-        //Watchdog::kick(); - if we kick the watchdog, the station is unrecoverable without physical access
+        // don't kick the watchdog
+        // if we do, the station is unrecoverable without physical access
     }
 }
 
 int main() {
+    // a failsafe
+    Watchdog::kick(WDFAILSAFE);
+    
     {
         gCpu.baud(115200);
 #if defined(SSNOTIFY) || defined(DEBUG)
@@ -506,9 +549,6 @@
     printf("\n\n\n\n\n\nstarting\r\n");
 #endif
         
-    // a failsafe
-    Watchdog::kick(kWDFailsafe);
-    
     // set the clock to the BS time, if it's not set
     if ( (static_cast<int32_t>(time(0)))<0 ) {
         set_time(kBStime);
@@ -562,6 +602,12 @@
         WaitTrigAndSendClock();
         PIN_lockRegisters = 1; // block registers during readout
         
+        
+        if (gHrtbtFired) {
+            SaveHeartbeat();
+            gHrtbtFired=false;
+        }
+        
 #ifdef EVT_TIME_PROFILE
         Timer prof;
         prof.start();
@@ -583,37 +629,38 @@
             
             led4=1;
             
-            // read data & calc CRC
+            if ( gEvent.IsForcedTrg() || gFirstEvt ||
+                (etms>gConf.GetEvtThrtlPeriodMs()) ) {
+
+                // read data & calc CRC
 #ifdef EVT_TIME_PROFILE
-            prof.stop(); befReadWv=prof.read_us(); prof.start();
+                prof.stop(); befReadWv=prof.read_us(); prof.start();
 #endif
 
-            // get the data to the MBED
-            gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit);
+                // get the data to the MBED
+                gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit);
             
 #ifdef EVT_TIME_PROFILE
-            prof.stop(); aftReadWv=prof.read_us(); prof.start();
+                prof.stop(); aftReadWv=prof.read_us(); prof.start();
 #endif
 
-            gEvent.SetCurMbedTime();
-            // TODO: no way to check for external trigger?
-            if (gEvent.IsForcedTrg()==false) {
-                gEvent.SetTrgBit(kThmTrg);
-                gEvent.SetTrgNum(++(gTrgNum[kThmTrg]));
-            } // else already set by procForceTrigger
-            // (no need to calc if we throw this event away)
-            
-            Watchdog::kick(); // don't reset!
-    
+                gEvent.SetCurMbedTime();
+                // TODO: no way to check for external trigger?
+                if (gEvent.IsForcedTrg()==false) {
+                    gEvent.SetTrgBit(kThmTrg);
+                    gEvent.SetTrgNum(++(gTrgNum[kThmTrg]));
+                    AddToRate(ttms, true);
+                } // else already set by procForceTrigger
+                // (no need to calc if we throw this event away)
+                
+                Watchdog::kick(); // don't reset!
+        
 #ifdef DEBUG
-            printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
+                printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
 #endif
-
-            if ( gEvent.IsForcedTrg() || gFirstEvt ||
-                (etms>gConf.GetEvtThrtlPeriodMs()) ) {
                 
                 led2=1;
-                
+                /*
                 gRecentCountTime = static_cast<uint32_t>(time(0));
                 gRecentEvtNum    = gEvtNum;
                 // do start time second so that if we get only one event,
@@ -623,6 +670,7 @@
                     gLastEventReset = gEvtNum;
                     gDoResetLastCount = false;
                 }
+                */
                 
                 PIN_lockRegisters = 0; // done reading, unlock so we can talk to SD card.
                 
@@ -631,6 +679,7 @@
 #endif
 
                 SaveEvent(etms);
+                AddToRate(etms, false);
                 etms=0;
                 
 #ifdef EVT_TIME_PROFILE
@@ -665,6 +714,9 @@
 #endif
             OpenCommWin();
             gOpenCommWin=false;
+            gFirstEvt = true;
+            gTrgTimer.reset();
+            etms=0;
         } else {
 #ifdef DEBUG
             printf("gOpenCommWin=false\r\n");
@@ -680,6 +732,9 @@
             printf("seq complete. sngseq=%d\r\n",gConf.IsSingleSeqRunMode());
 #endif
             MakeOutputFile(gConf.IsSingleSeqRunMode());
+            gFirstEvt = true;
+            gTrgTimer.reset();
+            etms=0;
         }
 #ifdef EVT_TIME_PROFILE
         prof.stop(); aftNewSeq=prof.read_us(); prof.start();
@@ -696,15 +751,33 @@
         // get ready to trigger
         PIN_spi.format( 16, 1 ); // change to data readout format
         PIN_spi.frequency( 10000000 );  // Max is 12.5 MHz
-
+        
         // reset event
-        gEvent.ClearEvent();
+        // clear after comm win, so full event can be sent with status
+        // but don't clear counters or trigger bits, as
+        gEvent.ClearEvent(true);
     
     }
 
 }
 
 //
+// save a heartbeat tag
+//
+void SaveHeartbeat() {
+    if (gHrtbtNum>0) {
+#ifdef DEBUG
+        printf("save heartbeat #%u, time %u\r\n",
+            gHrtbtNum-1, gLastHrtbt);
+#endif
+        // save to SD
+        PIN_lockRegisters = 0; // unlock so we can talk to SD card.
+        SnSDUtils::WriteHeartbeatTo(SnSDUtils::GetCurFile(),
+            gLastHrtbt, gHrtbtNum-1); // -1 so it counts from 0
+    }
+}
+
+//
 // save the event
 //
 void SaveEvent(const int32_t etms) {
@@ -883,6 +956,9 @@
     PIN_heartbeat             = 0;
     wait_ms(20);
     
+    gCommWinChecks  = 0;
+    gNcommWinChecks = gConf.GetCommWinPeriod() / kCommWinLongPrdTk;
+    
     if (AreCardsPowered(true)) {
         // Set PLA value(s)
         PIN_spi.format( 16, 0 ); // change mode for DAC & PLA value setting
@@ -1131,6 +1207,9 @@
     // get the trigger rates
     float thmrate=0, evtrate=0;
     GetRates(thmrate, evtrate);
+#ifdef DEBUG
+    printf("thmrate=%g, evtrate=%g\r\n",thmrate,evtrate);
+#endif
 
     StopAllTickers();
 
@@ -1276,12 +1355,11 @@
     // (probably) power down comms and power up cards,amps
     SetPower(false);
 
-    gFirstEvt = true;
-
     // reset config with system powered (for DAC/PLA setting)
 #ifdef DEBUG
     printf("calling SetConfigAndMakeOutputFile\r\n");
 #endif
+    
     SetConfigAndMakeOutputFile();
 
 #ifdef DEBUG