Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Revision:
1:e392595b4b76
Parent:
0:664899e0b988
Child:
2:e67f7c158087
--- a/main.cpp	Sat Jun 30 02:03:51 2012 +0000
+++ b/main.cpp	Fri Jul 20 19:04:02 2012 +0000
@@ -13,6 +13,7 @@
 #include "SnCommWin.h"
 #include "SnCommAfar.h"
 #include "SnCommUsb.h"
+#include "SnBase64.h"
 
 //
 // MBED PINS (ordered by number)
@@ -23,7 +24,7 @@
 DigitalOut led3(LED3);
 DigitalOut led4(LED4);
 // Set up power pins - Note that it's Zero for "on"
-DigitalOut PIN_turn_on_system(p17);
+DigitalOut PIN_turn_on_system(p17); // this turns on system
 DigitalOut PIN_turn_on_amps(p25);
 // Activate/select chip by falling edge
 DigitalOut PIN_ADC_CS( p9 );
@@ -39,8 +40,12 @@
 // read it out.
 DigitalIn PIN_a_sf_clk( p14 );
 DigitalIn PIN_rst_a_sf(p15);
+// afar power
+DigitalOut PIN_afar_power(p16);
 // Lock daughter card registeres (during data readout).
 DigitalOut PIN_lockRegisters( p20 );
+// iridium (SBD) power
+DigitalOut PIN_iridSbd_power(p21);
 // Majority logic pins
 DigitalOut PIN_MajLogHiBit(p22);
 DigitalOut PIN_MajLogLoBit(p23);
@@ -65,7 +70,7 @@
 void                      ReadRegister(const uint8_t chan, int16_t* dev);
 void                      SaveEvent(const int32_t etms);
 void                      WaitTrigAndSendClock();
-void                      SetConfig();
+void                      SetConfigAndMakeOutputFile();
 SnCommWin::ECommWinResult OpenCommWin();
 
 //
@@ -73,7 +78,7 @@
 //
 // readout objs
 static Ticker         gForceTicker;
-static Ticker         gIOticker;
+static Ticker         gCommWinTicker;
 static Timer          gEvtTimer;
 static SnConfigFrame  gConf;
 static SnEventFrame   gEvent;
@@ -81,21 +86,22 @@
 static bool           gFirstEvt         = true;
 static bool           gReadingOut       = false;
 static bool           gCommWinOpen      = false; // if it's open
-static bool           gOpenCommWin      = false; // if it should be opened
+static volatile bool  gOpenCommWin      = false; // if it should be opened
 static int32_t        gEvtNum           = 0;   // num of evt written
 static int32_t        gTrgNum[kNumTrgs] = {0}; // num of this type of trg received
 // i/o
-static Timer          gIOtimer;
+static time_t         gLastCommWin      = 0;
 static MODSERIAL      gCpu( USBTX, USBRX ); // defined here so it might be used for debugging output
-static SnCommWin*     gComms[kNcomms]   = { new SnCommAfar, new SnCommUsb(&gCpu) }; // order => priority
-static FILE*          gCurFile          = 0;
+//static SnCommWin*     gComms[kNcomms]   = { new SnCommAfar, new SnCommUsb(&gCpu) }; // order => priority
+//static SnCommWin*     gComms[kNcomms]   = { new SnCommUsb(&gCpu) }; // order => priority
+static SnCommWin*     gComms[kNcomms]   = { new SnCommAfar }; // order => priority
 //static char           gEvtBuf[SnEventFrame::kMaxSizeOf];
 //static char           gConfBuf[SnConfigFrame::kMaxSizeOf];
 //static char           gStatBuf[SnStatusFrame::kMaxSizeOf];
 static char           gGenBuf[SnStatusFrame::kMaxSizeOf]; // must be big enough for event or status or config!
 
 void procForceTrigger() {
-    led1=!led1;
+    //led1=!led1;
     if (gReadingOut==false && gCommWinOpen==false) {
         gEvent.SetTrgBit(kFrcTrg);
         gEvent.SetTrgNum((gTrgNum[kFrcTrg])++);
@@ -105,100 +111,147 @@
 
 void procCommWin() {
     if (gReadingOut==false && gCommWinOpen==false) {
-        gOpenCommWin = true;
+        if ( (time(0) - gLastCommWin) > gConf.GetCommWinPeriod() ) {
+            led3=!led3;
+            gOpenCommWin = true;
+        }
     }
 }
 
+uint32_t GetTimeoutTime(const uint32_t startTime,
+                        const uint32_t delta) {
+    const uint32_t lst = time(0)-startTime;
+    const uint32_t lio = 
+        ((lst+delta) < gConf.GetCommWinDuration()) ?
+          lst+delta  : gConf.GetCommWinDuration();
+    return lio+startTime;
+}
+
 
 // TODO: add block-id's to output file? (config block, event block, file header block, etc.)
 
+// TODO: HEARTBEAT!
+
+// TODO: make websocket URL settable in the config (i.e. via SBD?)
+
 int main() {
+    {
+        led1=1; wait(0.3);
+        led1=0; led2=1; wait(0.3);
+        led2=0; led3=1; wait(0.3);
+        led3=0; led4=1; wait(0.3);
+        led4=0;
+    }
+    
     led2=1;
     //wait_ms(100);
-
+    
+    printf("starting\r\n");
+        
     // a failsafe
     Watchdog::kick(kWDFailsafe);
-
-    // Turn on all power
-    // Note that zero means "on"
-    PIN_turn_on_system=0;
-
-    // block (thermal) triggers during configuration
-    PIN_enableThermTrig       = 0;
-    PIN_ADC_CS                = 1;
-    PIN_DoNotRestartAllClocks = 1;
-    PIN_forceTrigger          = 0;
-    wait_ms(20);
     
-    // setup SPI
-    PIN_spi.frequency( 10000000 );  // Max is 12.5 MHz
+    // set the clock to the BS time, if it's not set
+    if ( (static_cast<int32_t>(time(0)))<0 ) {
+        set_time(kBStime);
+    }
+    printf("time = %d\r\n",(int32_t)time(0));
+    gLastCommWin = time(0); // prevent comm win proc
     
     gForceTicker.detach();
     gFirstEvt = true;
     
     gConf.Reset();
+    SetConfigAndMakeOutputFile(); // setup defaults in case no communication
     
     //
     // get config
     //
-    
-    // TODO: communication window
-    // TODO: call usb port setup
-    //OpenCommWin();
-    // TODO: get config
-    SetConfig();
-    
+    printf("open window\r\n");
+    //gOpenCommWin();
+
     // get ready to trigger
     PIN_spi.format( 16, 1 ); // change to data readout format
 
-    // force a trigger every dForceTrigPeriod seconds
-    gForceTicker.attach(&procForceTrigger, gConf.GetForceTrigPeriod());
-        
     led2=0;
     
+    bool restartEvtTimer=true;
     // the main event loop. wait for triggers in SendClock
     while( true )
     {
         // in here, we wait for triggers from the MB-FPGA
-        led4 = !led4;
         Watchdog::kick(); // don't reset!
-        gEvtTimer.reset();
-        gEvtTimer.start();
+        
+        led1 = !led1;
+        
+        printf("calling wait trig\r\n");
+        printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
+
+        if (restartEvtTimer) {
+            gEvtTimer.reset();
+            gEvtTimer.start();
+            restartEvtTimer=false;
+        }
         PIN_lockRegisters = 0; // allow data to come from DFPGA
         WaitTrigAndSendClock();
         PIN_lockRegisters = 1; // block registers during readout
-        gEvtTimer.stop();
+        
+        const int32_t etms = gEvtTimer.read_ms(); // but don't stop the timer!
+        
+        printf("wait trig send clock exited\r\n");
+                
         Watchdog::kick(); // don't reset!
         
+        if (gReadingOut) {
+            //
+            // got trigger. read registers to mbed and build the event
+            //
+            
+            led4=1;
+            printf("readout\r\n");
+            
+            // read data & calc CRC
+            gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit);
+            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!
+    
+            printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
+
+            if ( gEvent.IsForcedTrg() || gFirstEvt ||
+                (etms>gConf.GetEvtThrtlPeriodMs()) ) {
+                
+                led2=1;
+                
+                PIN_lockRegisters = 0; // done reading, unlock so we can talk to SD card.
+                
+                printf("save event\r\n");
+                wait(5);
+                SaveEvent(etms);
+                restartEvtTimer=true;
+            } else {
+                printf("forced=%s, gFirstEvt=%s, e>t %d>%hu %s\r\n",
+                    gEvent.IsForcedTrg()?"true":"false", gFirstEvt?"true":"false",
+                    etms, gConf.GetEvtThrtlPeriodMs(),
+                    etms>gConf.GetEvtThrtlPeriodMs() ? "true":"false");
+            }
+        }
+        printf("past reading out\r\n");
+        
+        led4=0; led2=0;
+        
         if (gOpenCommWin) {
+            printf("gOpenComWin=%s, opening\r\n",gOpenCommWin?"true":"false");
             OpenCommWin();
             gOpenCommWin=false;
-            continue;
-        }
-        
-        //
-        // got trigger. read registers to mbed and build the event
-        //
-
-        // read data & calc CRC
-        gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit);
-        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!
-
-        const int32_t etms = gEvtTimer.read_ms();
-        if ( gEvent.IsForcedTrg() || 
-            (etms>gConf.GetEvtThrtlPeriodMs()) ) {
-            
-            PIN_lockRegisters = 0; // done reading, unlock so we can talk to SD card.
-            SaveEvent(etms);
-
+        } else {
+            printf("gOpenCommWin=false\r\n");
         }
     }
 
@@ -215,18 +268,20 @@
     gEvent.SetDTms(etms);
     
     // save to SD
-    SnSDUtils::WriteEventTo(gCurFile, gGenBuf, gEvent, gConf);
+    SnSDUtils::WriteEventTo(SnSDUtils::GetCurFile(), gGenBuf, gEvent, gConf);
     
     // reset
     gEvent.ClearEvent();
     
-    if (gEvtNum==5) {
-        fclose(gCurFile);
+    printf("gEvtNum=%d\r\n",gEvtNum);
+    if (gEvtNum==10) {
+        fclose(SnSDUtils::GetCurFile());
         while (1) {
-            led3 = 1;
+            led3 = 1; led4=1;
             wait(0.5);
-            led3 = 0;
+            led3 = 0; led4=0;
             wait(0.5);
+            Watchdog::kick();
         }
     }
     
@@ -235,40 +290,47 @@
 //
 // set configuration
 //
-void SetConfig() {
+void SetConfigAndMakeOutputFile() {
+    printf("SetConfigAndMakeOutputFile\r\n");
+    
     // restart watchdog
     Watchdog::kick(gConf.GetWatchdogPeriod());
     
+    // block (thermal) triggers during configuration
+    PIN_enableThermTrig       = 0;
+    PIN_ADC_CS                = 1;
+    PIN_DoNotRestartAllClocks = 1;
+    PIN_forceTrigger          = 0;
+    wait_ms(20);
+    
     // reset event, timers, trigger counters
     gEvent.ClearEvent();
     gEvtNum = gConf.GetFirstEvt();
-    gEvtTimer.reset();
     memset(gTrgNum, 0, sizeof(int32_t)*kNumTrgs);
     
     // make new output file
-    SnSDUtils::CloseOutputFile(gCurFile);
-    
-    gCurFile = SnSDUtils::OpenNewOutputFile(gConf.GetMacAddress(),
-                                            gConf.GetRun());
-    SnSDUtils::WriteFileHeader(gCurFile, gConf.GetMacAddress());
-    SnSDUtils::WriteConfig(gCurFile, gConf);
+    SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
+    SnSDUtils::OpenNewOutputFile(gConf.GetMacAddress(),
+                                 gConf.GetRun());
+    printf("made output file with run %u\r\n",gConf.GetRun());
+    printf("filename=%s\r\n",SnSDUtils::GetCurFileName());
+    SnSDUtils::WriteFileHeader(SnSDUtils::GetCurFile(),
+                               gConf.GetMacAddress());
+    SnSDUtils::WriteConfig(SnSDUtils::GetCurFile(), gConf);
     
     // TODO: turn on amps individually, when that's possible
-    if (gConf.IsEachAmpOn()) {
-        PIN_turn_on_amps=0;
-    }
+    PIN_turn_on_amps = gConf.IsEachAmpOn() ? 0 : 1;
     
     // Set PLA value(s)
-    // TODO: send multiple values when FPGA code is ready for it
-    // TODO: uncomment when using new version of FPGA code
     PIN_spi.format( 16, 0 ); // change mode for DAC & PLA value setting
+    PIN_spi.frequency(1000000);
     PIN_MajLogHiBit=1;
     PIN_MajLogLoBit=1;
     PIN_enableThermTrig=0;
 
     uint16_t hi, lo;
     PIN_PLA_cs=1;
-    wait(3);
+    wait(4);
     for (uint8_t pi=0; pi<kNplas; pi++) {
         if (pi < gConf.GetNumPlas()) {
             SnConfigFrame::GetHiLoPlas(gConf.GetPla(pi), hi, lo);
@@ -278,6 +340,7 @@
             PIN_spi.write(kNoTrigPla); // hi
             PIN_spi.write(kNoTrigPla); // lo
         }
+        Watchdog::kick();
     }
     wait(3);
     PIN_PLA_cs=0;
@@ -294,7 +357,8 @@
     // the card/dac# is encoded, the order is also important
     // 0000 (dac0,card0), 0001 (dac0,card1), 0011 (dac0,card3), 0010 (dac0,card2),
     // 0110 (dac1,card2), 0111 (dac1,card3), 0101 (dac1,card1), etc.
-    int dv=0;
+    printf("setting dacs\r\n");
+    uint16_t dv=0;
     for (uint8_t i=0, gri=0; i<kTotDacs; i++) {
         // get the gray-codes for this iteration
         gri = SnBitUtils::binToGray(i);
@@ -304,12 +368,17 @@
         dv <<= 4u;
         dv  |= gri;
         
+        printf("dac %04x\r\n",dv);
+        
         // send to FPGA
         PIN_start_fpga=1;
         PIN_spi.write(dv);
         PIN_start_fpga=0;
+
+        Watchdog::kick();
+        
     }
-        
+    printf("dacs set\r\n");
     wait_ms(20);
     
     // Majority Logic Trigger selection (# of cards)
@@ -320,6 +389,21 @@
     PIN_enableThermTrig = gConf.IsThermTrigEnabled();
 
     PIN_spi.format( 16, 1 ); // back to trigger mode
+    PIN_spi.frequency( 10000000 );  // Max is 12.5 MHz
+
+    // force a trigger every...
+    gForceTicker.detach();
+    gForceTicker.attach(&procForceTrigger, 
+        gConf.GetForceTrigPeriod() > kAbsMaxTimer ?
+        kAbsMaxTimer : gConf.GetForceTrigPeriod()); // force period has a maximum
+    // proc a comm win every...
+    gCommWinTicker.detach();
+    gCommWinTicker.attach(&procCommWin,
+        gConf.GetCommWinPeriod() > kAbsMaxTimer ?
+        kCommWinLongPrdTk : gConf.GetCommWinPeriod()); // periodic check if above max
+    printf("attach comm win ticker %u\r\n",
+        gConf.GetCommWinPeriod() > kAbsMaxTimer ?
+        kCommWinLongPrdTk : gConf.GetCommWinPeriod());
     
     Watchdog::kick(); // don't reset!
 
@@ -329,7 +413,9 @@
 // readout functions
 //
 void WaitTrigAndSendClock() {
-
+    
+    printf("WaitTrigAndSendClock\r\n");
+        
     if (gFirstEvt==false) {
         PIN_DoNotRestartAllClocks    = 0;
         wait_us(1);
@@ -345,17 +431,14 @@
     gReadingOut = false;  // this will allow forced triggers (see procForceTrigger())
     while ( PIN_a_sf_clk == 1 ) {
         if (gOpenCommWin) {
-            // break out to open comms
-            return;
+            return; // break out to open comms
         }
     }
     PIN_forceTrigger=0;   // necessary for forced triggers, harmless for other triggers
     gReadingOut = true;   // disallow new forced triggers
-    
     //
     // collect data from daughter cards
     //
-    
     // TODO: what if some card (set of channels) doesn't respond?
     // currently, will wait forever?
     // also, if ch1 is dead, will wait forever (due to FPGA code)
@@ -384,39 +467,74 @@
     gCommWinOpen = true;
     Watchdog::kick(); // don't reset!
     
-    // TODO: power up comm systems
+    printf("opening comm window at %d\r\n", (int32_t)time(0));
     
-    gIOtimer.reset();
-    gIOtimer.start();
+    // power system down
+    PIN_turn_on_system = 1;
+    PIN_turn_on_amps = 1;
+    wait_ms(20);
+    // power up the comm systems
+    PIN_iridSbd_power = 1;
+    wait_ms(10);
+    PIN_afar_power = 1;
+    wait_ms(10);
     
     const uint32_t conto = (gConf.GetCommWinDuration() < kConnectTimeout) ?
         gConf.GetCommWinDuration() : kConnectTimeout;
     const uint32_t listo = (gConf.GetCommWinDuration() < kListenTimeout) ?
         gConf.GetCommWinDuration() : kListenTimeout;
     
+    gLastCommWin = time(0);
+    
     SnCommWin::ECommWinResult res = SnCommWin::kUndefFail;
     
+    bool gotNewConfig=false;
+    bool sendStat[kNcomms];
+    for (uint8_t i=0; i<kNcomms; i++) {
+        sendStat[i]=true;
+    }
+    bool* ss = sendStat;
     SnCommWin** cw = gComms;
-    for (uint8_t i=0; (i<kNcomms) && 
-                     (gIOtimer.read()<gConf.GetCommWinDuration()); i++, cw++) {
-        
+    for (uint8_t i=0; ((time(0)-gLastCommWin)<gConf.GetCommWinDuration()); i++, cw++, ss++) {
+        Watchdog::kick(); // don't reset!
+        if (i==kNcomms) {
+            i=0;
+            cw = gComms;
+            ss = sendStat;
+        }
         // open window and (mabye) send status update
+        printf("calling OpenWindow. ss=%d\r\n",(int)(*ss));
+        printf("gtt=%u, ct=%d, lcw=%d, dur=%u\r\n",GetTimeoutTime(gLastCommWin,conto),
+            time(0), gLastCommWin, gConf.GetCommWinDuration());
         const SnCommWin::ECommWinResult conres = (*cw)->OpenWindow(
-            gIOtimer, conto, true, gConf, gEvent, gGenBuf, gGenBuf);
+            GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gEvent, gGenBuf, gGenBuf);
         if (conres>=SnCommWin::kConnected) {
+            Watchdog::kick(); // don't reset!
             // connected. listen for config
+            *ss = false; // don't send status next time
             const SnCommWin::ECommWinResult cfgres = (*cw)->GetConfig(
-                gConf, gIOtimer, listo, gGenBuf);
+                gConf, GetTimeoutTime(gLastCommWin, listo), gGenBuf);
             if (cfgres>=SnCommWin::kOkWithMsg) {
-                // got config. set it up.
-                SetConfig();
+                Watchdog::kick(); // don't reset!
+                printf("received config!\r\n");
+                char* b = gGenBuf;
+                gConf.WriteTo(b);
+                for (uint32_t i=0; i<gConf.SizeOf(); i++) {
+                    printf("%02x ",gGenBuf[i]);
+                }
+                printf("\r\n");
                 // send data if need be (files, some events, etc)
                 if (gConf.GetCommSendData()!=0) {
-                    res = (*cw)->SendData(gConf, gEvent, gGenBuf, gGenBuf);
+                    
+                    res = (*cw)->SendData(gConf, gEvent, gGenBuf, gGenBuf,
+                        GetTimeoutTime(gLastCommWin, gConf.GetCommWinDuration()));
                 } else {
                     // don't send anything
                     res = cfgres;
                 }
+                printf("Got config!\r\n");
+                gotNewConfig=true;
+                Watchdog::kick(); // don't reset!
                 break;
             }
         }
@@ -425,6 +543,25 @@
 
     }
     
+    // power down the comm systems
+    PIN_iridSbd_power = 0;
+    wait_ms(10);
+    PIN_afar_power = 0;
+    wait_ms(10);
+    // power system back up
+    gFirstEvt = true;
+    PIN_turn_on_system = 0;
+    wait_ms(10);
+    PIN_turn_on_amps = 0;
+    wait_ms(10);
+    // reset config with system powered (for DAC/PLA setting)
+    if (gotNewConfig) {
+        printf("calling SetConfigAndMakeOutputFile\r\n");
+        SetConfigAndMakeOutputFile();
+        // TODO: remove
+    }
+    printf("closing comm win at %d\r\n",(int32_t)time(0));
+    
     gCommWinOpen = false;
     return res;
 }