Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

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