Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
Diff: main.cpp
- Revision:
- 56:0bba0ef15697
- Parent:
- 52:dc82c37ad234
- Child:
- 59:21128cc24b04
--- a/main.cpp Fri Jan 03 13:03:01 2014 +0000 +++ b/main.cpp Thu Oct 30 06:42:17 2014 +0000 @@ -1,22 +1,28 @@ #include "mbed.h" + +const uint32_t gPowerOnTime( time(0) ); + // start a watchdog as soon as possible #include "Watchdog.h" Watchdog::SnKickStarter gKickStarter(WDFAILSAFE); -//#define DISABLE_CONFIG_SAFETYNETS +#define DISABLE_CONFIG_SAFETYNETS + +// CHIPBOARD is defined in SnConstants.h #define ENABLE_AFAR_COMM #define ENABLE_SBD_COMM //#define ENABLE_USB_COMM //#define ENABLE_AFAR_TWITTER -//#define USE_RTOS // change in CommConstants and EthernetPower also +//#define USE_RTOS // change USE_RTOS in CommConstants and EthernetPower also //#define USE_ETH_INTERFACE //#define EVT_TIME_PROFILE //#define DEBUG //#define SSNOTIFY #define USE_MODSERIAL + #include <stdint.h> #include "SnConstants.h" @@ -25,7 +31,7 @@ #define MODSERIAL_RX_BUF_SIZE 512 #define MODSERIAL_TX_BUF_SIZE 512 #include "MODSERIAL.h" -#endif +#endif // USE_MODSERIAL #include "FATDirHandle.h" #include "EthernetPowerControl.h" #include "SnBitUtils.h" @@ -50,14 +56,15 @@ #endif // ENABLE_AFAR_COMM #ifdef ENABLE_USB_COMM #include "SnCommWinUsb.h" -#endif +#endif // ENABLE_USB_COMM #ifdef ENABLE_SBD_COMM #include "SnCommWinSBD.h" -#endif +#endif // ENABLE_SBD_COMM //#include "SnBase64.h" #ifdef USE_RTOS_TIMER #include "RtosTimer.h" -#endif +#endif // USE_RTOS_TIMER +#include "DS1820.h" extern "C" void mbed_reset(); @@ -65,52 +72,86 @@ // MBED PINS (ordered by number) // // leds (for debugging) -DigitalOut led1(LED1); -DigitalOut led2(LED2); -DigitalOut led3(LED3); -DigitalOut led4(LED4); -// Set up power pins - Note that it's Zero for "on" -DigitalOut PIN_turn_on_system(p17); // this turns on system -DigitalOut PIN_turn_on_amps(p25); +DigitalOut led1(LED1,0); +DigitalOut led2(LED2,0); +DigitalOut led3(LED3,0); +DigitalOut led4(LED4,0); + +// 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 +DigitalOut PIN_turn_on_amps(p25,1); // this turns off the amps +#else +DigitalOut PIN_turn_on_system(p17,0); // this turns off the system +DigitalOut PIN_turn_on_amps(p25,0); // this turns off the amps +#endif // ATWD4CH // SD card select -DigitalOut PIN_SD_CS(p8); +DigitalOut PIN_SD_CS(p8,0); +#if CHIPBOARD==ATWD4CH // Activate/select chip by falling edge -DigitalOut PIN_ADC_CS( p9 ); +DigitalOut PIN_ADC_CS(p9,0); // clock signal to activate PLA setting -DigitalOut PIN_PLA_cs(p10); +DigitalOut PIN_PLA_cs(p10,0); +#else +I2C PIN_i2c(p9, p10); +#endif // ATWD4CH // To force a trigger -DigitalOut PIN_forceTrigger(p11); //modification +DigitalOut PIN_forceTrigger(p11,0); //modification // To suppress thermal triggers -DigitalOut PIN_enableThermTrig(p12); +DigitalOut PIN_enableThermTrig(p12,0); +#if CHIPBOARD==ATWD4CH // Restart clock on all FPGAs. -DigitalOut PIN_DoNotRestartAllClocks( p13 ); +DigitalOut PIN_DoNotRestartAllClocks(p13,0); +#else +DigitalOut PIN_ResetChips(p13,0); +#endif // ATWD4CH +#if CHIPBOARD==ATWD4CH // This tells the DFPGAs to store the data on motherboard FPGA and // read it out. -DigitalIn PIN_a_sf_clk( p14 ); +DigitalIn PIN_a_sf_clk(p14); DigitalIn PIN_rst_a_sf(p15); +#else +DigitalIn PIN_dataReady(p14); // when triggered data is stored in the mb FPGA and ready for readout by mbed +#endif // ATWD4CH // afar power -DigitalOut PIN_afar_power(p16); +DigitalOut PIN_afar_power(p16,0); // batter voltage/current measurement AnalogIn PIN_vADC1(p19); AnalogIn PIN_vADC2(p18); +#if CHIPBOARD==ATWD4CH // Lock daughter card registeres (during data readout). -DigitalOut PIN_lockRegisters( p20 ); +DigitalOut PIN_lockRegisters(p20,0); +#else +DigitalOut PIN_readingData(p20,0); +#endif // ATWD4CH // iridium (SBD) power -DigitalOut PIN_iridSbd_power(p21); +DigitalOut PIN_iridSbd_power(p21,0); // Majority logic pins -DigitalOut PIN_MajLogHiBit(p22); -DigitalOut PIN_MajLogLoBit(p23); +DigitalOut PIN_MajLogHiBit(p22,0); +DigitalOut PIN_MajLogLoBit(p23,0); +// To launch a heartbeat pulse +DigitalOut PIN_heartbeat(p24,0); +#if CHIPBOARD==ATWD4CH // Tell FPGA to be ready to accept DAC values -DigitalOut PIN_start_fpga(p26); +DigitalOut PIN_start_fpga(p26,0); +#else +DigitalIn PIN_unused26(p26); +#endif // ATWD4CH +#if CHIPBOARD==ATWD4CH // Two bits to the select the daughter card for readout -DigitalOut PIN_selCardHiBit( p29 ); -DigitalOut PIN_selCardLoBit( p30 ); -// To launch a heartbeat pulse -DigitalOut PIN_heartbeat(p24); +DigitalOut PIN_selCardHiBit(p29,0); +DigitalOut PIN_selCardLoBit(p30,0); +#else +DigitalOut PIN_dualOrSingleThresholds(p29, 1); // 1 = dual (hi AND lo thresh crossings) +DigitalOut PIN_differentialTrigSignal(p30, 1); // 1 = chip sends one trigger signal per channel with reduced noise, 0 = chip sends each comparator signal separately +#endif // ATWD4CH // Setup SPI pins SPI PIN_spi( p5, p6, p7 ); -// The SD card +#if CHIPBOARD==SST4CH +PinName gThermPinName(p15); +DS1820 PIN_therm(gThermPinName, gThermPinName, false); // be default, on external power +#endif // we have to do this shit because Serial and MODSERIAL don't have virtual functions // so calling, e.g. readable from a Serial* will call Serial::readable instead of MODSERIAL::readable @@ -119,7 +160,7 @@ #define MAIN_SERIALTYPE AjK::MODSERIAL #else #define MAIN_SERIALTYPE Serial -#endif +#endif // USE_MODSERIAL // 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 @@ -127,9 +168,10 @@ static MAIN_SERIALTYPE gSBDport(p28, p27, #ifdef USE_MODSERIAL MODSERIAL_TX_BUF_SIZE, MODSERIAL_RX_BUF_SIZE, -#endif +#endif // USE_MODSERIAL "sbd"); +// The SD card static SDFileSystem sd(p5, p6, p7, p8, SnSDUtils::kSDdir+1); // no leading '/' static LocalFileSystem local((SnCommWin::kLocalDir)+1); // no leading '/' @@ -149,13 +191,15 @@ void procForceTrigger(); void procHeartbeat(); void procPowerCheck(); +void procTempCheck(); void procCommWin(); #ifdef USE_RTOS void procForceTrigger(void const *) { return procForceTrigger(); } void procHeartbeat(void const *) { return procHeartbeat(); } void procPowerCheck(void const *) { return procPowerCheck(); } void procCommWin(void const *) { return procCommWin(); } -#endif +void procTempCheck(void const *) { return procTempCheck(); } +#endif // USE_RTOS // // globals @@ -167,12 +211,14 @@ static rtos::RtosTimer* gHeartbeatTicker; static rtos::RtosTimer* gCommWinTicker; static rtos::RtosTimer* gPowerCheckTicker; +static rtos::RtosTimer* gTempCheckTicker; #else static Ticker gForceTicker; static Ticker gHeartbeatTicker; static Ticker gCommWinTicker; static Ticker gPowerCheckTicker; -#endif +static Ticker gTempCheckTicker; +#endif // USE_RTOS static Timer gAllTrgTimer; static Timer gThmTrgTimer; static Timer gAdcToMBtimer; @@ -182,17 +228,19 @@ static SnConfigFrame gConf(false); #else static SnConfigFrame gConf; -#endif +#endif // DISABLE_CONFIG_SAFETYNETS static SnEventFrame gEvent; static SnEventFrame gLastEvent; static SnPowerFrame gPower; +static SnTempFrame gTemperature; // parameters static bool gCardsPowered = false; static bool gFirstEvt = true; -static volatile bool gReadingOut = false; +static volatile bool gReadingOut = false; // if data is being read from the FPGA static volatile bool gCommWinOpen = false; // if it's open static volatile bool gOpenCommWin = false; // if it should be opened static volatile bool gCheckPower = false; // if it should be checked +static volatile bool gCheckTemp = false; // if it should be checked static uint32_t gPowNum = 0; static uint32_t gEvtNum = 0; // num of evt written static uint32_t gTrgNum[kNumTrgs] = {0}; // num of this type of trg received @@ -226,10 +274,17 @@ led3=!led3; #ifdef DEBUG printf("proc force\r\n"); +#if CHIPBOARD==ATWD4CH printf("PIN_forceTrigge=%d, PIN_turn_on_system=%d, " "PIN_a_sf_clk=%d\r\n", PIN_forceTrigger.read(), PIN_turn_on_system.read(), PIN_a_sf_clk.read()); +#else + printf("PIN_forceTrigge=%d, PIN_turn_on_system=%d, " + "PIN_dataReady=%d\r\n", + PIN_forceTrigger.read(), PIN_turn_on_system.read(), + PIN_dataReady.read()); +#endif // ATWD4CH #endif gEvent.SetTrgBit(kFrcTrg); gEvent.SetTrgNum(++(gTrgNum[kFrcTrg])); @@ -260,6 +315,13 @@ gCheckPower=true; } +void procTempCheck() { +#ifdef DEBUG + printf("proc temp check\r\n"); +#endif + gCheckTemp=true; +} + void procCommWin() { ++gCommWinChecks; //if ( (time(0) - gLastCommWin) > gConf.GetCommWinPeriod() ) { @@ -278,12 +340,20 @@ bool AreCardsPowered(const bool checkPin) { #ifdef DEBUG - printf("acp: PIN_turn_on_system=%d, gCardsPowered=%d\r\n", + printf("acp call: PIN_turn_on_system=%d, gCardsPowered=%d\r\n", PIN_turn_on_system.read(), gCardsPowered); #endif if (checkPin) { +#if CHIPBOARD==ATWD4CH gCardsPowered = (PIN_turn_on_system.read()==0); +#else + gCardsPowered = (PIN_turn_on_system.read()==1); +#endif // ATWD4CH } +#ifdef DEBUG + printf("acp return: PIN_turn_on_system=%d, gCardsPowered=%d\r\n", + PIN_turn_on_system.read(), gCardsPowered); +#endif return gCardsPowered; } @@ -294,7 +364,7 @@ const uint16_t aaveV1 = PIN_vADC1.read_u16(); const uint16_t aaveV2 = PIN_vADC2.read_u16(); float n=0, ave1=0, ave2=0, rms1=0, rms2=0; - for (uint16_t i=0; i<kNvoltsAve; i++) { + for (uint16_t i=0; i<kNvoltsAve; ++i) { v1 = PIN_vADC1.read_u16() - aaveV1; v2 = PIN_vADC2.read_u16() - aaveV2; n += 1; @@ -314,29 +384,97 @@ ave1 += aaveV1; ave2 += aaveV2; gPower.Set(ave1, ave2, rms1, rms2, time(0)); +#ifdef DEBUG + printf("ave power. v1=%g, v2=%g, r1=%g, r2=%g, t=%u\r\n", + gPower.GetAveV1(), gPower.GetAveV2(), + gPower.GetRmsV1(), gPower.GetRmsV2(), gPower.GetTime()); +#endif } -void CheckPower(const bool isCommWin) { +#if CHIPBOARD==SST4CH +void InitTempProbe() { +#ifdef DEBUG + printf("setting temp probe power mode\r\n"); +#endif + // set power style for temperature probe + PIN_therm.set_use_parasite_power( gConf.IsTempUsingParasitePower() ); + // setup the probe +#ifdef DEBUG + printf("calling therm probe search_ROM_setup\r\n"); +#endif + PIN_therm.search_ROM_setup(); + const int tsr = PIN_therm.search_ROM(); // this is necessary for some reason +#ifdef DEBUG + printf("search ROM = %d\r\n", tsr); +#endif +} +#endif + +void UpdateTemperature() { + // ask chip to convert temperature + PIN_therm.convert_temperature(true, DS1820::all_devices); + gTemperature.SetTempAndTime( PIN_therm.temperature('c'), time(0) ); +#ifdef DEBUG + printf("TTTTTTTT temp = %g at %u\r\n", gTemperature.GetTemperature(), + gTemperature.GetTime()); +#endif +} + +void CheckTemp() { +#ifdef DEBUG + printf("CheckTemp\r\n"); +#endif + UpdateTemperature(); + // save to disk + FILE* cf = SnSDUtils::GetCurFile(); + if (cf!=0) { +#if CHIPBOARD==ATWD4CH + PIN_lockRegisters = 0; // unlock so we can talk to the SD card +#else + PIN_readingData = 0; // unlock so we can talk to the SD card +#endif // ATWD4CH +#ifdef DEBUG + printf("writing temp. temp = %g at %u\r\n", + gTemperature.GetTemperature(), + gTemperature.GetTime()); +#endif + SnSDUtils::WriteTempTo(cf, gTemperature); + } + gCheckTemp = false; +} + +void CheckPower(const bool isCommWin, + const bool saveReading=true) { #ifdef DEBUG printf("CheckPower\r\n"); #endif // read power GetAvePowerReading(); - // save to disk - FILE* cf = SnSDUtils::GetCurFile(); - if (cf!=0) { - PIN_lockRegisters = 0; // unlock so we can talk to SD card. + if (saveReading) { + // save to disk + FILE* cf = SnSDUtils::GetCurFile(); + if (cf!=0) { +#if CHIPBOARD==ATWD4CH + PIN_lockRegisters = 0; // unlock so we can talk to the SD card +#else + PIN_readingData = 0; // unlock so we can talk to the SD card +#endif // ATWD4CH #ifdef DEBUG - printf("writing power. v1=%g, v2=%g, r1=%g, r2=%g, t=%u, pownum=%u\r\n", - gPower.GetAveV1(), gPower.GetAveV2(), - gPower.GetRmsV1(), gPower.GetRmsV2(), gPower.GetTime(), - gPowNum); + printf("writing power. v1=%g, v2=%g, r1=%g, r2=%g, t=%u, pownum=%u\r\n", + gPower.GetAveV1(), gPower.GetAveV2(), + gPower.GetRmsV1(), gPower.GetRmsV2(), gPower.GetTime(), + gPowNum); #endif - SnSDUtils::WritePowerTo(cf, gPower, gPowNum); + SnSDUtils::WritePowerTo(cf, gPower, gPowNum); + } } // do we need to change modes? bool changed = false; if (gConf.IsLowPowerMode()) { +#ifdef DEBUG + printf("in low pwr. v1=%g, fromLP=%hu\r\n", + gPower.GetAveV1(), gConf.GetBatVoltFromLowPwr()); +#endif if (gPower.GetAveV1() > gConf.GetBatVoltFromLowPwr()) { #ifdef DEBUG printf("chaing to normal power!\r\n"); @@ -345,6 +483,10 @@ changed = true; } } else { +#ifdef DEBUG + printf("in normal pwr. v1=%g, toLP=%hu\r\n", + gPower.GetAveV1(), gConf.GetBatVoltToLowPwr()); +#endif if (gPower.GetAveV1() < gConf.GetBatVoltToLowPwr()) { #ifdef DEBUG printf("chaing to low power!\r\n"); @@ -386,6 +528,21 @@ #endif } +void CalcRate(const uint32_t numtrgs, + const double tottime_ms, + float& rate) { + rate = 0; + if (numtrgs>1) { + if (tottime_ms>0.0) { + rate = static_cast<float>(numtrgs) + / (tottime_ms/1e3); + } else { + // lots of triggers in 0 time + rate = 1e6; + } + } +} + void GetRates(float& thmrate, float& evtrate) { thmrate = evtrate = 0; #ifdef DEBUG @@ -394,13 +551,11 @@ gThmNumDt, gThmDtSum, gEvtNumDt, gEvtDtSum); #endif - thmrate = (gThmDtSum>0.0 && gThmNumDt>1) ? - static_cast<float>(gThmNumDt) / (gThmDtSum/1e3) : 0; - evtrate = (gEvtDtSum>0.0 && gEvtNumDt>1) ? - static_cast<float>(gEvtNumDt) / (gEvtDtSum/1e3) :0; + CalcRate(gThmNumDt, gThmDtSum, thmrate); + CalcRate(gEvtNumDt, gEvtDtSum, evtrate); } -void AddToRate(const float dt, const bool isThm) { +void AddToRate(const double dt, const bool isThm) { if (isThm) { gThmDtSum += dt; gThmNumDt += 1u; @@ -449,7 +604,7 @@ void stopTicker(Ticker& tik) { tik.detach(); } -#endif +#endif // USE_RTOS #ifdef USE_RTOS float resetTicker(rtos::RtosTimer* tik, const float timSec, @@ -476,13 +631,14 @@ } return 0; } -#endif +#endif // USE_RTOS void StopAllTickers() { stopTicker(gForceTicker); stopTicker(gHeartbeatTicker); stopTicker(gCommWinTicker); stopTicker(gPowerCheckTicker); + stopTicker(gTempCheckTicker); } void ResetAllTickers() { @@ -498,6 +654,9 @@ Thread::wait(169); // make it less likely for multiple triggers to fire too close together const float pcp = resetTicker(gPowerCheckTicker, gConf.GetVoltCheckPeriod(), kAbsMaxTimer); + Thread::wait(143); // make it less likely for multiple triggers to fire too close together + const float ctp = resetTicker(gTempCheckTicker, gConf.GetTempCheckPeriod(), + kAbsMaxTimer); #else const float ftp = resetTicker(gForceTicker, gConf.GetForceTrigPeriod(), kAbsMaxTimer, &procForceTrigger); @@ -510,15 +669,45 @@ wait_ms(169); // make it less likely for multiple triggers to fire too close together const float pcp = resetTicker(gPowerCheckTicker, gConf.GetVoltCheckPeriod(), kAbsMaxTimer, &procPowerCheck); -#endif + wait_ms(143); // make it less likely for multiple triggers to fire too close together + const float ctp = resetTicker(gTempCheckTicker, gConf.GetTempCheckPeriod(), + kAbsMaxTimer, &procTempCheck); +#endif // USE_RTOS #ifdef DEBUG printf("attach force trig %g\r\n",ftp); printf("attach heart beat %g\r\n",hbp); printf("attach comm win %g\r\n",cwp); printf("attach power chk %g\r\n",pcp); + printf("attach temp chk %g\r\n",ctp); #endif } +void UponBrownout() { + // signal brownout by all LEDs off + led1 = led2 = led3 = led4 = 0; + // note that debug printing here is pointless, + // since power over USB will prevent brownout + + // close the current file +#if CHIPBOARD==ATWD4CH + PIN_lockRegisters = 0; // unlock so we can talk to the SD card +#else + PIN_readingData = 0; // unlock so we can talk to the SD card +#endif + SnSDUtils::WriteTrigWaitWinTime(SnSDUtils::GetCurFile(), + gClkSet, + false); + SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile()); + + // change to low power settings + gConf.ChangeToLowPower(); + // actually power stuff down + SetPower(gCommWinOpen); + + // goodnight + Sleep(); +} + void StopRunning() { #if defined(DEBUG) || defined(SSNOTIFY) printf("stop running\r\n"); @@ -531,35 +720,49 @@ Thread::wait(500); #else wait(0.5); -#endif +#endif // USE_RTOS led3 = 0; led4=0; #ifdef USE_RTOS Thread::wait(500); #else wait(0.5); -#endif +#endif // USE_RTOS // don't kick the watchdog // if we do, the station is unrecoverable without physical access } } -void InitSDCard() { +int InitSDCard() { #ifdef DEBUG printf("initializing SD card..\r\n"); #endif // initialize the SD card. this should prevent the issue with // seq 0 being overwritten upon power up or the SD card first // being insterted - sd.disk_initialize(); + const int ret = sd.disk_initialize(); +#ifdef DEBUG + printf("called disk_initialize (ret=%d)\r\n",ret); +#endif + return ret; } int main() { // a failsafe Watchdog::kick(WDFAILSAFE); + + gCpu.baud(CPUBAUD_SN); + + // check in case we need to go to low power + //wait(4); // TODO: the vADCs read high for first ~4-5sec + CheckPower(false, false); +#ifdef DEBUG + printf("startup power: cards %d, amps %d, irid %d, afar %d\r\n", + PIN_turn_on_system.read(), PIN_turn_on_amps.read(), + PIN_iridSbd_power.read(), PIN_afar_power.read()); +#endif { - gCpu.baud(CPUBAUD_SN); #if defined(SSNOTIFY) || defined(DEBUG) printf("\n\n\n\n\nmain: start\r\n"); #endif @@ -573,12 +776,20 @@ led1=0; led2=1; wait(0.2); led2=0; led3=1; wait(0.2); led3=0; led4=1; wait(0.2); -#endif +#endif // USE_RTOS led4=0; } + // don't initialize yet, but give SnSDUtils a pointer to + // the function that initializes it, so it can call the fcn later SnSDUtils::fgDoInit = &InitSDCard; - + + // Note: the brownout isn't useful since it sees either 5V or nothing on our board + // set up the brownout interrupt + NVIC_SetVector(BOD_IRQn, (uint32_t)&UponBrownout); + // Enable Brown Out Detect Interrupt + NVIC_EnableIRQ(BOD_IRQn); + #ifdef DEBUG printf("making comm objects\r\n"); #endif @@ -602,27 +813,27 @@ printf("making SnCommAfarNetIfTwitter\r\n"); #endif gTwit = new SnCommAfarNetIfTwitter(gConf); -#endif -#endif -#endif +#endif // ENABLE_AFAR_TWITTER +#endif // USE_ETH_INTERFACE +#endif // ENABLE_AFAR_COMM #ifdef ENABLE_SBD_COMM #ifdef DEBUG printf("making SnCommWinSBD\r\n"); #endif gComms[comi++] = new SnCommWinSBD(&gSBDport); -#endif +#endif // ENABLE_SBD_COMM #ifdef ENABLE_USB_COMM #ifdef DEBUG printf("makin SnCommWinUsb\r\n"); #endif gComms[comi++] = new SnCommWinUsb(&gCpu); -#endif +#endif // ENABLE_USB_COMM #ifdef DEBUG printf("made comm objects\r\n"); #ifdef USE_MODSERIAL printf("using MODSERIAL\r\n"); -#endif +#endif // USE_MODSERIAL #endif if (comi!=kNcomms) { @@ -636,7 +847,8 @@ gHeartbeatTicker = new rtos::RtosTimer(&procHeartbeat); gCommWinTicker = new rtos::RtosTimer(&procCommWin); gPowerCheckTicker = new rtos::RtosTimer(&procPowerCheck); -#endif + gTempCheckTicker = new rtos::RtosTimer(&procTempCheck); +#endif // USE_RTOS led2=1; @@ -653,11 +865,13 @@ gForceTicker->stop(); #else gForceTicker.detach(); -#endif +#endif // USE_RTOS gFirstEvt = true; - + // (probably) power down comms and power up cards,amps SetPower(false); + // check power again to see if voltages drooped + CheckPower(false, false); // // get config @@ -676,7 +890,7 @@ // read and cache the dCard power pin setting, // so we can use the cached value later AreCardsPowered(true); // TODO: should this be an if? - register int32_t etms=0; // time between written events + register double etms=0; // time between written events // the main event loop. wait for triggers in SendClock while ( true ) { @@ -699,22 +913,33 @@ true); gThmTrgTimer.reset(); gThmTrgTimer.start(); gAllTrgTimer.reset(); gAllTrgTimer.start(); +#if CHIPBOARD==SST4CH + // 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; +#endif } - PIN_lockRegisters = 0; // allow data to come from DFPGA - WaitTrigAndSendClock(); // wiat for trigger and move data to MB. this returns immediately if cards are powered off - PIN_lockRegisters = 1; // block registers during readout - +#if CHIPBOARD==ATWD4CH + PIN_lockRegisters = 0; // allow data to come from DFPGA + WaitTrigAndSendClock(); // wait for trigger and move data to MB. this returns immediately if cards are powered off + PIN_lockRegisters = 1; // block registers during readout +#else + PIN_readingData = 0; // not reading yet + WaitTrigAndSendClock(); // wait for trigger. this returns immediately if cards are powered off + // PIN_readingData will be set high by SnEventFrame::ReadWaveformsSST +#endif // ATWD4CH #ifdef EVT_TIME_PROFILE Timer prof; prof.start(); int befReadWv=0, aftReadWv=0, befSaveEvt=0, aftSaveEvt=0, befChkPow=0, aftChkPow=0, befNewSeq=0, aftNewSeq=0, endOfLoop=0; -#endif +#endif // EVT_TIME_PROFILE if (gReadingOut) { - - const int32_t ttms = gThmTrgTimer.read_ms(); // for rate calculation - const int32_t atms = gAllTrgTimer.read_ms(); // for throttle + const double ttms = gThmTrgTimer.read_us() / 1e3; // for rate calculation + const double atms = gAllTrgTimer.read_us() / 1e3; // for throttle if (gEvent.IsForcedTrg()==false) { // don't reset if not a thermal trigger gThmTrgTimer.reset(); gThmTrgTimer.start(); @@ -738,19 +963,27 @@ } // else already set by procForceTrigger if ( gEvent.IsForcedTrg() || gFirstEvt || - (etms>gConf.GetEvtThrtlPeriodMs()) ) { + (etms>=gConf.GetEvtThrtlPeriodMs()) ) { // read data & calc CRC #ifdef EVT_TIME_PROFILE prof.stop(); befReadWv=prof.read_us(); prof.start(); -#endif +#endif // EVT_TIME_PROFILE +#if CHIPBOARD==ATWD4CH // get the data to the MBED - gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit); - + 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 + PIN_ResetChips = 1; +// wait_us(1); + PIN_ResetChips = 0; +#endif //ATWD4CH + #ifdef EVT_TIME_PROFILE prof.stop(); aftReadWv=prof.read_us(); prof.start(); -#endif +#endif // EVT_TIME_PROFILE gEvent.SetCurMbedTime(); @@ -773,11 +1006,16 @@ } */ - PIN_lockRegisters = 0; // done reading, unlock so we can talk to SD card. +#if CHIPBOARD==ATWD4CH + PIN_lockRegisters = 0; // done reading, unlock so we can talk to the SD card +#else + // (this is redundant; it's already set low by SnEventFrame) + PIN_readingData = 0; // done reading, unlock so we can talk to the SD card +#endif // ATWD4CH #ifdef EVT_TIME_PROFILE prof.stop(); befSaveEvt=prof.read_us(); prof.start(); -#endif +#endif // EVT_TIME_PROFILE SaveEvent(etms); AddToRate(etms, false); @@ -785,6 +1023,12 @@ #ifdef EVT_TIME_PROFILE prof.stop(); aftSaveEvt=prof.read_us(); prof.start(); +#endif // EVT_TIME_PROFILE + } else { +#if CHIPBOARD==SST4CH + // reset in case a trigger arrived before we were ready + PIN_ResetChips = 1; + PIN_ResetChips = 0; #endif } } @@ -801,7 +1045,7 @@ #ifdef EVT_TIME_PROFILE prof.stop(); befChkPow=prof.read_us(); prof.start(); -#endif +#endif // EVT_TIME_PROFILE // check the power? if (gCheckPower) { #ifdef DEBUG @@ -811,7 +1055,14 @@ } #ifdef EVT_TIME_PROFILE prof.stop(); aftChkPow=prof.read_us(); prof.start(); +#endif // EVT_TIME_PROFILE + + if (gCheckTemp) { +#ifdef DEBUG + printf("call check temp\r\n"); #endif + CheckTemp(); + } // open comm win? if (gOpenCommWin) { @@ -837,7 +1088,7 @@ #ifdef EVT_TIME_PROFILE prof.stop(); befNewSeq=prof.read_us(); prof.start(); -#endif +#endif // EVT_TIME_PROFILE // make new seq? if (IsSeqComplete()) { #ifdef DEBUG @@ -855,7 +1106,7 @@ } #ifdef EVT_TIME_PROFILE prof.stop(); aftNewSeq=prof.read_us(); prof.start(); -#endif +#endif // EVT_TIME_PROFILE #ifdef EVT_TIME_PROFILE prof.stop(); endOfLoop=prof.read_us(); prof.start(); @@ -863,7 +1114,7 @@ "befChkPow=%d, aftChkPow=%d, befNewSeq=%d, aftNewSeq=%d, endOfLoop=%d\r\n", befReadWv, aftReadWv, befSaveEvt, aftSaveEvt, befChkPow, aftChkPow, befNewSeq, aftNewSeq, endOfLoop); -#endif +#endif // EVT_TIME_PROFILE /* // get ready to trigger @@ -890,7 +1141,11 @@ gHrtbtNum-1, gLastHrtbt); #endif // save to SD - PIN_lockRegisters = 0; // unlock so we can talk to SD card. +#if CHIPBOARD==ATWD4CH + PIN_lockRegisters = 0; // unlock so we can talk to the SD card +#else + PIN_readingData = 0; // unlock so we can talk to the SD card +#endif SnSDUtils::WriteHeartbeatTo(SnSDUtils::GetCurFile(), gLastHrtbt, gHrtbtNum-1); // -1 so it counts from 0 } @@ -903,7 +1158,7 @@ // write the event #ifdef DEBUG - printf("save event\r\n"); + printf("save event (%u)\r\n", gEvtNum); #endif // set the event number & dt @@ -911,7 +1166,11 @@ gEvent.SetDTms(etms); // save to SD - PIN_lockRegisters = 0; // unlock so we can talk to SD card. +#if CHIPBOARD==ATWD4CH + PIN_lockRegisters = 0; // unlock so we can talk to the SD card +#else + PIN_readingData = 0; // unlock so we can talk to the SD card +#endif SnSDUtils::WriteEventTo(SnSDUtils::GetCurFile(), gGenBuf, gEvent, gConf); // make a copy in case we need to send it with the status @@ -928,7 +1187,11 @@ } void MakeOutputFile(const bool stopRunning) { - PIN_lockRegisters = 0; // unlock so we can talk to SD card. +#if CHIPBOARD==ATWD4CH + PIN_lockRegisters = 0; // unlock so we can talk to the SD card +#else + PIN_readingData = 0; // unlock so we can talk to the SD card +#endif #ifdef DEBUG printf("closing output file. gEvtNum=%u, gPowNum=%u, stop=%d\r\n", gEvtNum,gPowNum,(int)stopRunning); @@ -942,7 +1205,7 @@ if (stopRunning) { StopRunning(); } - FILE* cf = SnSDUtils::OpenNewOutputFile(gConf.GetMacAddress(), + FILE* cf = SnSDUtils::OpenNewOutputFile(SnConfigFrame::GetMacAddress(), gConf.GetRun(), gConf.GetFirstSeq()); // reset event, timers, trigger counters @@ -975,7 +1238,7 @@ bool PowerDownCommPeriph(const SnConfigFrame::EDatPackBit type) { SnCommWin** cw = gComms; - for (uint8_t i=0; i<kNcomms; i++, cw++) { + for (uint8_t i=0; i<kNcomms; ++i, ++cw) { if ((*cw)==0) { continue; } else if ((*cw)->GetCommType()==type) { @@ -1147,8 +1410,10 @@ // block (thermal) triggers during configuration PIN_enableThermTrig = 0; +#if CHIPBOARD==ATWD4CH PIN_ADC_CS = 1; PIN_DoNotRestartAllClocks = 1; +#endif PIN_forceTrigger = 0; PIN_heartbeat = 0; #ifdef USE_RTOS @@ -1162,12 +1427,13 @@ if (AreCardsPowered(true)) { // Set PLA value(s) - PIN_spi.format( 16, 0 ); // change mode for DAC & PLA value setting + PIN_spi.format( 16, 0 ); // change mode for DAC & PLA value setting (with ATWD4CH) PIN_spi.frequency(1000000); PIN_MajLogHiBit=1; PIN_MajLogLoBit=1; PIN_enableThermTrig=0; +#if CHIPBOARD==ATWD4CH uint16_t hi, lo; PIN_PLA_cs=1; #ifdef USE_RTOS @@ -1175,7 +1441,7 @@ #else wait(4); #endif - for (uint8_t pi=0; pi<kNplas; pi++) { + for (uint8_t pi=0; pi<kNplas; ++pi) { if (pi < gConf.GetNumPlas()) { SnConfigFrame::GetHiLoPlas(gConf.GetPla(pi), hi, lo); PIN_spi.write(hi); @@ -1204,6 +1470,7 @@ wait(3); #endif + // DAC values // // first 12 bits = DAC value @@ -1219,7 +1486,7 @@ printf("setting dacs\r\n"); #endif uint16_t dv=0; - for (uint8_t i=0, gri=0; i<kTotDacs; i++) { + for (uint8_t i=0, gri=0; i<kTotDacs; ++i) { // get the gray-codes for this iteration gri = SnBitUtils::binToGray(i); @@ -1240,6 +1507,67 @@ Watchdog::kick(); } +#else // SST + + // set and/or & differential pins + + // set DACs via I2C + + uint16_t dv=0; + uint8_t dn=0; + uint8_t cmdAndDac[3]; + for (uint8_t ch=0; ch<kNchans; ++ch) { + for (uint8_t dc=0; dc<kNchanDacs; ++dc) { +// for (uint16_t dc=kNchanDacs-1; dc>=0; --dc) { // first all the highs, then the lows +// for (int16_t ch=kNchans-1; ch>=0; --ch) { // chans in reverse order + bool dok = false; + for (uint8_t tries = 0; (tries<kMaxDacSetTries) && (dok==false); ++tries) { +#ifdef DEBUG + printf("start i2c for dc=%hhu, ch=%hhu, try=%hhu, dok=%s\r\n", + dc, ch, tries, (dok ? "true" : "false")); + printf("address 0x%hhx (%hhd) ", kAllLTC2657, kAllLTC2657); + SnBitUtils::printBits(kAllLTC2657, true); +#endif + // build data to send + // blame the engineers for this bizzare mapping from + // chan, threshold -> DAC number + dn = (kTotDacs-1)-(dc*kNchans)-ch; + if (dn>7) { // invalid code for LTC2657 dac chip + error("chan/dac combination too big for 3 bits!"); + } + dn |= (kUpdateDacCmd<<4); // prefix with update DAC value command +#ifdef DEBUG + printf("dn=%hhu ", dn); + SnBitUtils::printBits(dn, true); +#endif + dv = (gConf.GetDac(ch, dc)) << 4; // put 0's at the end (12 bits of num then 4 zero bits) +#ifdef DEBUG + printf("dv=%hu\r\n",dv); + printf("ch=%hhu, dc=%hhu, dac=%hu\r\n",ch,dc,gConf.GetDac(ch,dc)); +#endif + // mbed i2c.write seems to send it "backwards" from a (low endian) bit + // point of view.. i guess it's forwards from an intuitive pov? + cmdAndDac[0] = dn; + cmdAndDac[1] = (dv & 0xFF00u) >> 8; // 8 MSBs of 12 bit num first + cmdAndDac[2] = (dv & 0x00FFu); // 4 LSBs of 12 bit num followed by 4 zeros + +#ifdef DEBUG + printf("cmdAndDac[0]="); SnBitUtils::printBits(cmdAndDac[2],true); + printf("cmdAndDac[1]="); SnBitUtils::printBits(cmdAndDac[1],true); + printf("cmdAndDac[2]="); SnBitUtils::printBits(cmdAndDac[0],true); +#endif + // try to send it + // TODO: if no ACK, is just re-trying the whole thing good enough? + // TODO: assign correct slave address for the DAC chip (this is a global address) + dok = PIN_i2c.write(kAllLTC2657, + reinterpret_cast<char*>(cmdAndDac), + 3*sizeof(uint8_t))==0; + } // end try loop + } + } + +#endif // CHIPBOARD + #ifdef DEBUG printf("dacs set\r\n"); #endif @@ -1253,6 +1581,12 @@ printf("cards off. skipping PLA and DAC setting\r\n"); #endif } + +#if CHIPBOARD==SST4CH + // set the SST triggering run mode + PIN_dualOrSingleThresholds = gConf.IsDualThresholdMode(); + PIN_differentialTrigSignal = gConf.IsDifferentialTrigMode(); +#endif // Majority Logic Trigger selection (# of cards) SnBitUtils::SetChanNumBits(gConf.GetNumCardsMajLog() - 1u, @@ -1261,6 +1595,10 @@ // Enable thermal trigger? PIN_enableThermTrig = gConf.IsThermTrigEnabled(); +#if CHIPBOARD==SST4CH + InitTempProbe(); +#endif + PIN_spi.format( 16, 1 ); // back to trigger mode PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz @@ -1305,9 +1643,11 @@ PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz if (gFirstEvt==false) { +#if CHIPBOARD==ATWD4CH PIN_DoNotRestartAllClocks = 0; wait_us(1); PIN_DoNotRestartAllClocks = 1; +#endif //led3 = !led3; // toggle send clock led } else { gFirstEvt = false; @@ -1321,33 +1661,28 @@ #endif gReadingOut = false; // this will allow forced triggers (see procForceTrigger()) - while ( PIN_a_sf_clk == 1 ) { - if (gOpenCommWin || gCheckPower) { +#if CHIPBOARD==ATWD4CH + while ( PIN_a_sf_clk == 1 ) { // wait for trigger +#else + while ( PIN_dataReady==0 ) { // wait for data in mb fpga +#endif + if (gOpenCommWin || gCheckPower || gCheckTemp) { #ifdef DEBUG - printf("break com=%d, pow=%d\r\n",gOpenCommWin,gCheckPower); + printf("break com=%d, pow=%d, tmp=%d\r\n", + gOpenCommWin,gCheckPower,gCheckTemp); #endif return; // break out to open comms or check power } } - //PIN_forceTrigger=0; // necessary for forced triggers, harmless for other triggers gReadingOut = true; // disallow new forced triggers -/* -#ifdef DEBUG - printf("after wait for trig. PIN_a_sf_clk=%d\r\n", - PIN_a_sf_clk.read()); -#endif -*/ + // we can't be interrupted before data arrives at the MB FPGA //StopAllTickers(); -/* - procForceTrigger(); - procHeartbeat(); - procPowerCheck(); - procCommWin(); -*/ //wait_us(5); - + +#if CHIPBOARD==ATWD4CH + // ATWD // // collect data from daughter cards // @@ -1355,29 +1690,13 @@ // currently, will wait forever? // also, if ch1 is dead, will wait forever (due to FPGA code) gAdcToMBtimer.start(); - for( uint8_t i = 0; i < 128; ++i ) { + for( uint16_t i = 0; i < kNsamps; ++i ) { while (PIN_a_sf_clk==1) {} while (PIN_a_sf_clk==0) {} - /* - if ((i == 10)&&(gEvtNum % 20)) { - wait_us(8); - } - */ + PIN_ADC_CS = 0; PIN_spi.write( 0x00 ); PIN_ADC_CS = 1; - /* - if( PIN_a_sf_clk == 1 ) { - if( i == 0 ) - wait_us( 1 ); - - PIN_ADC_CS = 0; - PIN_spi.write( 0x00 ); - PIN_ADC_CS = 1; - } else { - i--; - } - */ } gAdcToMBtimer.stop(); #ifdef DEBUG @@ -1388,8 +1707,10 @@ } gAdcToMBtimer.reset(); - // restart the timers - //ResetAllTickers(); +#else + // For SST, data is already in the mb FPGA, so no need to do anything here +#endif + } else { // cards have no power. don't try reading out gReadingOut=false; @@ -1398,6 +1719,7 @@ // true and the "start trigger" clock will be written continuously gFirstEvt = false; } + } bool IsPinPowered(const SnCommWin* cw) { @@ -1450,6 +1772,7 @@ float thmrate=0, evtrate=0; GetRates(thmrate, evtrate); #ifdef DEBUG + printf("config=%s\r\n", gConf.GetLabel()); printf("thmrate=%g, evtrate=%g\r\n",thmrate,evtrate); #endif @@ -1477,7 +1800,11 @@ #endif if (isStartupWin==false) { - PIN_lockRegisters = 0; // unlock so we can talk to SD card. +#if CHIPBOARD==ATWD4CH + PIN_lockRegisters = 0; // unlock so we can talk to the SD card +#else + PIN_readingData = 0; // unlock so we can talk to the SD card +#endif #ifdef DEBUG printf("closing output file\r\n"); #endif @@ -1507,12 +1834,12 @@ printf("start loop over comms\r\n"); #endif bool sendStat[kNcomms]; - for (uint8_t i=0; i<kNcomms; i++) { + for (uint8_t i=0; i<kNcomms; ++i) { sendStat[i]=true; } bool* ss = sendStat; SnCommWin** cw = gComms; - for (uint8_t i=0; ((time(0)-gLastCommWin)<gConf.GetCommWinDuration()); i++, cw++, ss++) { + for (uint8_t i=0; ((time(0)-gLastCommWin)<gConf.GetCommWinDuration()); ++i, ++cw, ++ss) { Watchdog::kick(); // don't reset! if (i==kNcomms) { i=0; @@ -1546,6 +1873,14 @@ // update power reading in case we want to send it in status GetAvePowerReading(); + + // update temperature in case we want to send it in status + if (isStartupWin) { +#if CHIPBOARD==SST4CH + InitTempProbe(); +#endif + } + UpdateTemperature(); // open window and (mabye) send status update #ifdef DEBUG @@ -1559,8 +1894,11 @@ const SnCommWin::ECommWinResult conres = (*cw)->OpenWindow( // gConf.GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gEvent, gPower, gConf.GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gLastEvent, gPower, - SnSDUtils::GetCurSeqNum(), thmrate, evtrate, + SnSDUtils::GetCurSeqNum(), thmrate, evtrate, gPowerOnTime, gTemperature, gGenBuf); +#ifdef DEBUG + printf("conres = %d\r\n",static_cast<int>(conres)); +#endif if (conres>=SnCommWin::kConnected) { Watchdog::kick(); // don't reset! // connected. listen for config @@ -1581,7 +1919,9 @@ #endif const SnCommWin::ECommWinResult cfgres = (*cw)->GetConfig( gConf, gConf.GetTimeoutTime(gLastCommWin, listo), gGenBuf, gBufSize); - +#ifdef DEBUG + printf("cfgres = %d\r\n",static_cast<int>(cfgres)); +#endif if (cfgres>=SnCommWin::kOkWithMsg) { Watchdog::kick(); // don't reset! @@ -1602,12 +1942,18 @@ uint8_t hndshk(0); uint32_t hndshkLen(0); res = (*cw)->WaitHandshake(gConf, winto, gGenBuf, gBufSize, hndshk, &hndshkLen); +#ifdef DEBUG + printf("WaitHandshake res = %d\r\n",static_cast<int>(res)); +#endif // handle response if (SnCommWin::kOkWithMsg==res) { res = (*cw)->HandleHandshake(SnSDUtils::GetCurFile(), SnSDUtils::GetCurFileName(), gConf, gLastEvent, gPower, gGenBuf, gBufSize, winto, hndshk, hndshkLen); +#ifdef DEBUG + printf("HandleHandshake res = %d\r\n",static_cast<int>(res)); +#endif } } if (gConf.GetCommSendData()!=0) { @@ -1620,6 +1966,10 @@ res = (*cw)->SendData(gConf, gLastEvent, gPower, gGenBuf, gBufSize, winto); +#ifdef DEBUG + printf("SendData res = %d\r\n",static_cast<int>(res)); +#endif + } else { // don't send anything res = cfgres; @@ -1640,7 +1990,7 @@ // check Iridium time, send Iridium signal strength, and close the connection(s) cw = gComms; - for (uint8_t i=0; i<kNcomms; i++, cw++) { + for (uint8_t i=0; i<kNcomms; ++i, ++cw) { if ((*cw)==0) { continue; } @@ -1716,7 +2066,7 @@ // close connections const uint32_t extraDiscTime = gLastCommWin + gConf.GetCommWinConnectTO(); cw = gComms; - for (uint8_t i=0; i<kNcomms; i++, cw++) { + for (uint8_t i=0; i<kNcomms; ++i, ++cw) { if ((*cw)==0) { continue; } else { @@ -1743,8 +2093,8 @@ if (res<=SnCommWin::kAllFails) { ++gConsecCommFails; #ifdef DEBUG - printf("gConsecCommFails=%hu, kMaxConsecCommFails=%hu\r\n", - gConsecCommFails,kMaxConsecCommFails); + printf("res=%d, gConsecCommFails=%hu, kMaxConsecCommFails=%hu\r\n", + static_cast<int>(res), gConsecCommFails,kMaxConsecCommFails); #endif if (gConsecCommFails>kMaxConsecCommFails) { #ifdef DEBUG @@ -1767,6 +2117,15 @@ SetConfigAndMakeOutputFile(); + if (gConf.IsRunSeqListOneCommWinOnly()) { + SnSDUtils::ClearRunSeqList(); + } + + // check power in case we should be in low power mode + // but don't save this reading to the file + // (there's already one near the beginning) + CheckPower(false, false); + #ifdef DEBUG printf("closing comm win at %d\r\n",(int32_t)time(0)); #endif