Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
Diff: main.cpp
- 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; }