Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
main.cpp
- Committer:
- uci1
- Date:
- 2012-11-24
- Revision:
- 28:484943132bb0
- Parent:
- 27:efc4d654b139
- Child:
- 30:f869ed4bcc08
File content as of revision 28:484943132bb0:
#include "mbed.h"
// start a watchdog as soon as possible
#include "Watchdog.h"
Watchdog::SnKickStarter gKickStarter(WDFAILSAFE);
#define ENABLE_AFAR_COMM
#define ENABLE_SBD_COMM
//#define ENABLE_USB_COMM
#define ENABLE_AFAR_TWITTER
//#define USE_RTOS_TIMER
//#define USE_ETH_INTERFACE
//#define EVT_TIME_PROFILE
//#define DEBUG
//#define SSNOTIFY
#define USE_MODSERIAL
#include <stdint.h>
#include "SDFileSystem.h"
#ifdef USE_MODSERIAL
#include "MODSERIAL.h"
#define MODSERIAL_RX_BUF_SIZE 512
#define MODSERIAL_TX_BUF_SIZE 512
#endif
#include "FATDirHandle.h"
#include "EthernetPowerControl.h"
#include "SnConstants.h"
#include "SnBitUtils.h"
#include "SnSDUtils.h"
#include "SnConfigFrame.h"
#include "SnEventFrame.h"
#include "SnStatusFrame.h"
#include "SnHeaderFrame.h"
#include "SnHeartbeatFrame.h"
#include "SnCommWin.h"
#ifdef USE_ETH_INTERFACE
#include "SnCommAfarTCP.h"
#else
#include "SnCommAfarNetIf.h"
#ifdef ENABLE_AFAR_TWITTER
#include "SnCommAfarNetIfTwitter.h"
#endif
#endif
#include "SnCommUsb.h"
#include "SnCommSBD.h"
#include "SnBase64.h"
#ifdef USE_RTOS_TIMER
#include "RtosTimer.h"
#endif
//
// 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);
// SD card select
DigitalOut PIN_SD_CS(p8);
// Activate/select chip by falling edge
DigitalOut PIN_ADC_CS( p9 );
// clock signal to activate PLA setting
DigitalOut PIN_PLA_cs(p10);
// To force a trigger
DigitalOut PIN_forceTrigger(p11); //modification
// To suppress thermal triggers
DigitalOut PIN_enableThermTrig(p12);
// Restart clock on all FPGAs.
DigitalOut PIN_DoNotRestartAllClocks( p13 );
// This tells the DFPGAs to store the data on motherboard FPGA and
// read it out.
DigitalIn PIN_a_sf_clk( p14 );
DigitalIn PIN_rst_a_sf(p15);
// afar power
DigitalOut PIN_afar_power(p16);
// batter voltage/current measurement
AnalogIn PIN_vADC1(p19);
AnalogIn PIN_vADC2(p18);
// 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);
// Tell FPGA to be ready to accept DAC values
DigitalOut PIN_start_fpga(p26);
// 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);
// Setup SPI pins
SPI PIN_spi( p5, p6, p7 );
// The SD card
// this needs to be first in case some other global uses a print statement
#ifdef USE_MODSERIAL
#define SERIAL_TYPE MODSERIAL
#else
#define SERIAL_TYPE Serial
#endif
static SERIAL_TYPE gCpu( USBTX, USBRX // defined here so it might be used for debugging output
#ifdef USE_MODSERIAL
,MODSERIAL_TX_BUF_SIZE,
MODSERIAL_RX_BUF_SIZE
#endif
);
static SERIAL_TYPE gSBDport(p28, p27, "sbd");
static SDFileSystem sd(p5, p6, p7, p8, SnSDUtils::kSDdir+1); // no leading '/'
static LocalFileSystem local((SnCommWin::kLocalDir)+1); // no leading '/'
//
// fwd declare fcns
//
void ReadAllRegisters();
void ReadRegister(const uint8_t chan, int16_t* dev);
void SaveHeartbeat();
void SaveEvent(const int32_t etms);
void WaitTrigAndSendClock();
void SetConfigAndMakeOutputFile();
SnCommWin::ECommWinResult OpenCommWin(const bool forceReconfig=false);
void MakeOutputFile(const bool stopRunning=false);
void SetPower(const bool isCommWin);
void procForceTrigger();
void procHeartbeat();
void procPowerCheck();
void procCommWin();
#ifdef USE_RTOS_TIMER
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
//
// globals
//
// readout objs
// TODO: use RtosTimer instead of Ticker?
#ifdef USE_RTOS_TIMER
static rtos::RtosTimer* gForceTicker;
static rtos::RtosTimer* gHeartbeatTicker;
static rtos::RtosTimer* gCommWinTicker;
static rtos::RtosTimer* gPowerCheckTicker;
#else
static Ticker gForceTicker;
static Ticker gHeartbeatTicker;
static Ticker gCommWinTicker;
static Ticker gPowerCheckTicker;
#endif
static Timer gTrgTimer;
static Timer gAdcToMBtimer;
static SnConfigFrame gConf;
static SnEventFrame gEvent;
static SnPowerFrame gPower;
// parameters
static bool gCardsPowered = false;
static bool gFirstEvt = true;
static volatile bool gReadingOut = false;
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 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
// i/o
static time_t gLastCommWin = 0; // time
static uint32_t gCommWinChecks = 0;
static uint32_t gNcommWinChecks = 0;
// heartbeat
static time_t gLastHrtbt = 0;
static volatile bool gHrtbtFired = false;
static uint32_t gHrtbtNum = 0;
// rates
static double gThmDtSum = 0; // sum of all time diffs between thermal trigs
static double gEvtDtSum = 0; // sum of all time diffs between events
static uint32_t gThmNumDt = 0; // number of thermal trig time diffs added up
static uint32_t gEvtNumDt = 0; // number of event time diffs added up
// this should be bigger than anything that will actually be used
static const uint32_t gBufSize=SnStatusFrame::kMaxSizeOf + (2u*SnHeaderFrame::kMaxSizeOf) + SnPowerFrame::kMaxSizeOf;
//static const uint32_t gB64Bsize=BASE64ENC_LEN(gBufSize)+1;
//static char gB64Buf[gB64Bsize];
static char gGenBuf[gBufSize]; // must be big enough for event or status or config!
static SnCommWin* gComms[kNcomms] = { 0 }; // order => priority. afar uses RTOS, and must be made inside main
#if defined(ENABLE_AFAR_TWITTER) && defined(ENABLE_AFAR_COMM)
static SnCommAfarNetIfTwitter* gTwit = 0;
#endif
void procForceTrigger() {
if (gReadingOut==false && gCommWinOpen==false) {
led3=!led3;
#ifdef DEBUG
printf("proc force\r\n");
#endif
gEvent.SetTrgBit(kFrcTrg);
gEvent.SetTrgNum(++(gTrgNum[kFrcTrg]));
//PIN_forceTrigger = 0;
PIN_forceTrigger = 1; // force a trigger
PIN_forceTrigger = 0;
#ifdef DEBUG
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());
#endif
}
}
void procHeartbeat() {
if (gReadingOut==false && gCommWinOpen==false) {
#ifdef DEBUG
printf("proc heartbeat\r\n");
#endif
//PIN_heartbeat = 0;
PIN_heartbeat = 1; // heartbeat pulse
PIN_heartbeat = 0;
gLastHrtbt = time(0);
gHrtbtFired = true;
++gHrtbtNum;
}
}
void procPowerCheck() {
#ifdef DEBUG
printf("proc power\r\n");
#endif
gCheckPower=true;
}
void procCommWin() {
++gCommWinChecks;
//if ( (time(0) - gLastCommWin) > gConf.GetCommWinPeriod() ) {
#ifdef DEBUG
printf("<><><><><><> gCommWinChecks=%u, gNcommWinChecks=%u\r\n",
gCommWinChecks, gNcommWinChecks);
#endif
if ( gCommWinChecks >= gNcommWinChecks ) {
#ifdef DEBUG
printf("proc comm win.\r\n");
#endif
led3=!led3;
gOpenCommWin = true;
}
}
bool AreCardsPowered(const bool checkPin) {
#ifdef DEBUG
printf("acp: PIN_turn_on_system=%d, gCardsPowered=%d\r\n",
PIN_turn_on_system.read(), gCardsPowered);
#endif
if (checkPin) {
gCardsPowered = (PIN_turn_on_system.read()==0);
}
return gCardsPowered;
}
void GetAvePowerReading() {
// use one measurement as the assumed average
// in order to reduce computational errors
int32_t v1, v2;
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++) {
v1 = PIN_vADC1.read_u16() - aaveV1;
v2 = PIN_vADC2.read_u16() - aaveV2;
n += 1;
ave1 += v1;
rms1 += v1*v1;
ave2 += v2;
rms2 += v2*v2;
}
rms1 -= (ave1*ave1)/n;
rms2 -= (ave2*ave2)/n;
rms1 /= n-1;
rms2 /= n-1;
rms1 = sqrt(rms1);
rms2 = sqrt(rms2);
ave1 /= n;
ave2 /= n;
ave1 += aaveV1;
ave2 += aaveV2;
gPower.Set(ave1, ave2, rms1, rms2, time(0));
}
void CheckPower(const bool isCommWin) {
#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.
#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);
#endif
SnSDUtils::WritePowerTo(cf, gPower, gPowNum);
}
// do we need to change modes?
bool changed = false;
if (gConf.IsLowPowerMode()) {
if (gPower.GetAveV1() > gConf.GetBatVoltLowPwr()) {
#ifdef DEBUG
printf("chaing to normal power!\r\n");
#endif
gConf.ChangeToNormPower();
changed = true;
}
} else {
if (gPower.GetAveV1() < gConf.GetBatVoltLowPwr()) {
#ifdef DEBUG
printf("chaing to low power!\r\n");
#endif
gConf.ChangeToLowPower();
changed = true;
}
}
if (changed) {
SetPower(isCommWin);
#ifdef DEBUG
printf("Using config %s\r\n",gConf.GetLabel());
#endif
SetConfigAndMakeOutputFile(); // setup defaults in case no communication
}
// checking done
gCheckPower = false;
}
void ResetCountersClearEvt() {
const uint32_t evtStartCurSeq = (SnSDUtils::GetCurSeqNum()) // no -1; start with seq=0
* gConf.GetEvtsPerFile();
gEvent.ClearEvent();
gEvtNum = gConf.GetFirstEvt() + evtStartCurSeq;
gPowNum = evtStartCurSeq;
memset(gTrgNum, 0, sizeof(uint32_t)*kNumTrgs);
// reset rate counters
gThmDtSum = 0;
gThmNumDt = 0;
gEvtDtSum = 0;
gEvtNumDt = 0;
// reset heartbeat counters
gLastHrtbt = 0;
gHrtbtFired = false;
gHrtbtNum = 0;
#ifdef DEBUG
printf("Reset: gEvtNum=%u, gPowNum=%u, evtStartCS=%u\r\n",
gEvtNum, gPowNum, evtStartCurSeq);
#endif
}
void GetRates(float& thmrate, float& evtrate) {
thmrate = evtrate = 0;
#ifdef DEBUG
printf("** Getting rates: gThmNumDt=%d, gThmDtSum=%g, "
"gEvtNumDt=%d, gEvtDtSum=%g\r\n",
gThmNumDt, gThmDtSum, gEvtNumDt, gEvtDtSum);
#endif
thmrate = (gThmDtSum>0.0) ? static_cast<float>(gThmNumDt) / (gThmDtSum/1e3)
: 0;
evtrate = (gEvtDtSum>0.0) ? static_cast<float>(gEvtNumDt) / (gEvtDtSum/1e3)
: 0;
}
void AddToRate(const float dt, const bool isThm) {
if (isThm) {
gThmDtSum += dt;
gThmNumDt += 1u;
} else {
gEvtDtSum += dt;
gEvtNumDt += 1u;
}
#ifdef DEBUG
printf("** AddToRate: dt=%g, isThm=%d\r\n",dt,(int)isThm);
printf("** AddToRate: gThmNumDt=%d, gThmDtSum=%g, "
"gEvtNumDt=%d, gEvtDtSum=%g\r\n",
gThmNumDt, gThmDtSum, gEvtNumDt, gEvtDtSum);
#endif
}
bool IsSeqComplete() {
#ifdef DEBUG
printf("IsSeqComplete: eps=%u, cntpow=%d, fe=%u, pow=%u, evt=%u, seq=%hu\r\n",
gConf.GetEvtsPerFile(), (int)gConf.IsCountingPowerReadings(),
gConf.GetFirstEvt(), gPowNum, gEvtNum, SnSDUtils::GetCurSeqNum());
#endif
if (gConf.GetEvtsPerFile()>0) {
const uint32_t evtEndCurSeq = (SnSDUtils::GetCurSeqNum()+1) // account for seq=0
* gConf.GetEvtsPerFile();
#ifdef DEBUG
printf("evtEndCurSeq=%u\r\n",evtEndCurSeq);
#endif
if (gConf.IsCountingPowerReadings()) {
return (gPowNum>=evtEndCurSeq);
} else {
// first event num is a one-time per run offset, not one per sequence
return (gEvtNum>=(gConf.GetFirstEvt()+evtEndCurSeq));
}
} else {
return false;
}
}
#ifdef USE_RTOS_TIMER
void stopTicker(rtos::RtosTimer* tik) {
if (tik!=0) {
tik->stop();
}
}
#else
void stopTicker(Ticker& tik) {
tik.detach();
}
#endif
#ifdef USE_RTOS_TIMER
float resetTicker(rtos::RtosTimer* tik, const float timSec,
const float maxTimSec) {
if (tik!=0) {
tik->stop();
if (timSec>0) {
float tp = timSec > maxTimSec ? maxTimSec : timSec;
tp *= 1000u; // ms
tik->start(tp);
return tp;
}
}
return 0;
}
#else
float resetTicker(Ticker& tik, const float timSec,
const float maxTimSec, void (*fptr)(void)) {
tik.detach();
if (timSec>0) {
const float tp = timSec > maxTimSec ? maxTimSec : timSec;
tik.attach(fptr, tp);
return tp;
}
return 0;
}
#endif
void StopAllTickers() {
stopTicker(gForceTicker);
stopTicker(gHeartbeatTicker);
stopTicker(gCommWinTicker);
stopTicker(gPowerCheckTicker);
}
void ResetAllTickers() {
#ifdef USE_RTOS_TIMER
const float ftp = resetTicker(gForceTicker, gConf.GetForceTrigPeriod(),
kAbsMaxTimer);
wait_ms(131); // make it less likely for multiple triggers to fire too close together
const float hbp = resetTicker(gHeartbeatTicker, gConf.GetHeartbeatPeriod(),
kAbsMaxTimer);
wait_ms(173); // make it less likely for multiple triggers to fire too close together
const float cwp = resetTicker(gCommWinTicker, gConf.GetCommWinPeriod(),
kCommWinLongPrdTk);
wait_ms(169); // make it less likely for multiple triggers to fire too close together
const float pcp = resetTicker(gPowerCheckTicker, gConf.GetVoltCheckPeriod(),
kAbsMaxTimer);
#else
const float ftp = resetTicker(gForceTicker, gConf.GetForceTrigPeriod(),
kAbsMaxTimer, &procForceTrigger);
wait_ms(131); // make it less likely for multiple triggers to fire too close together
const float hbp = resetTicker(gHeartbeatTicker, gConf.GetHeartbeatPeriod(),
kAbsMaxTimer, &procHeartbeat);
wait_ms(173); // make it less likely for multiple triggers to fire too close together
const float cwp = resetTicker(gCommWinTicker, gConf.GetCommWinPeriod(),
kCommWinLongPrdTk, &procCommWin);
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
#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);
#endif
}
void StopRunning() {
#if defined(DEBUG) || defined(SSNOTIFY)
printf("stop running\r\n");
#endif
StopAllTickers();
OpenCommWin();
while (true) {
led3 = 1; led4=1;
wait(0.5);
led3 = 0; led4=0;
wait(0.5);
// don't kick the watchdog
// if we do, the station is unrecoverable without physical access
}
}
int main() {
// a failsafe
Watchdog::kick(WDFAILSAFE);
{
gCpu.baud(CPUBAUD_SN);
#if defined(SSNOTIFY) || defined(DEBUG)
printf("main: start\r\n");
#endif
led1=1; wait(0.2);
led1=0; led2=1; wait(0.2);
led2=0; led3=1; wait(0.2);
led3=0; led4=1; wait(0.2);
led4=0;
}
#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();
#ifdef DEBUG
printf("making comm objects\r\n");
#endif
uint8_t comi(0);
#ifdef ENABLE_AFAR_COMM
// RTOS stuff must be made inside main for some reason
#ifdef USE_ETH_INTERFACE
gComms[comi++] = new SnCommAfarTCP(gConf);
#else
gComms[comi++] = new SnCommAfarNetIf(gConf);
#ifdef ENABLE_AFAR_TWITTER
gTwit = new SnCommAfarNetIfTwitter(gConf);
#endif
#endif
#endif
#ifdef ENABLE_SBD_COMM
gComms[comi++] = new SnCommSBD(&gSBDport, &gCpu);
#endif
#ifdef ENABLE_USB_COMM
gComms[comi++] = new SnCommUsb(&gCpu);
#endif
#ifdef DEBUG
printf("made comm objects\r\n");
#endif
#ifdef USE_RTOS_TIMER
gForceTicker = new rtos::RtosTimer(&procForceTrigger);
gHeartbeatTicker = new rtos::RtosTimer(&procHeartbeat);
gCommWinTicker = new rtos::RtosTimer(&procCommWin);
gPowerCheckTicker = new rtos::RtosTimer(&procPowerCheck);
#endif
led2=1;
//wait_ms(100);
#ifdef DEBUG
printf("\n\n\n\n\n\nstarting\r\n");
#endif
// set the clock to the BS time, if it's not set
if ( (static_cast<int32_t>(time(0)))<0 ) {
set_time(kBStime);
}
#ifdef DEBUG
printf("time = %d\r\n",(int32_t)time(0));
#endif
gLastCommWin = time(0); // prevent comm win proc
#ifdef USE_RTOS_TIMER
gForceTicker->stop();
#else
gForceTicker.detach();
#endif
gFirstEvt = true;
// (probably) power down comms and power up cards,amps
SetPower(false);
//
// get config
//
#ifdef DEBUG
printf("call OpenCommWin\r\n");
#endif
OpenCommWin(true); // alwasy configure, even if no new config
// get ready to trigger
PIN_spi.format( 16, 1 ); // change to data readout format
PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
led2=0;
// the main event loop. wait for triggers in SendClock
AreCardsPowered(true);
gTrgTimer.start();
register int32_t etms=0; // time between written events
while( true )
{
// in here, we wait for triggers from the MB-FPGA
Watchdog::kick(); // don't reset!
led1 = !led1;
#ifdef DEBUG
printf("calling wait trig\r\n");
printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
printf("readingout=%d\r\n",(int)gReadingOut);
#endif
PIN_lockRegisters = 0; // allow data to come from DFPGA
WaitTrigAndSendClock();
PIN_lockRegisters = 1; // block registers during readout
#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
if (gReadingOut) {
const int32_t ttms = gTrgTimer.read_ms(); // time since last trigger
gTrgTimer.reset(); gTrgTimer.start(); // restart trigger timer
etms += ttms;
Watchdog::kick(); // don't reset!
//
// got trigger. read registers to mbed and build the event
//
led4=1;
if ( gEvent.IsForcedTrg() || gFirstEvt ||
(etms>gConf.GetEvtThrtlPeriodMs()) ) {
// read data & calc CRC
#ifdef EVT_TIME_PROFILE
prof.stop(); befReadWv=prof.read_us(); prof.start();
#endif
// get the data to the MBED
gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit);
#ifdef EVT_TIME_PROFILE
prof.stop(); aftReadWv=prof.read_us(); prof.start();
#endif
gEvent.SetCurMbedTime();
// TODO: no way to check for external trigger?
if (gEvent.IsForcedTrg()==false) {
gEvent.SetTrgBit(kThmTrg);
gEvent.SetTrgNum(++(gTrgNum[kThmTrg]));
AddToRate(ttms, true);
} // else already set by procForceTrigger
// (no need to calc if we throw this event away)
Watchdog::kick(); // don't reset!
#ifdef DEBUG
printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
#endif
led2=1;
/*
gRecentCountTime = static_cast<uint32_t>(time(0));
gRecentEvtNum = gEvtNum;
// do start time second so that if we get only one event,
// the delta(t) will be less than 0 and the rates not calculated
if (gDoResetLastCount) {
gLastCountReset = static_cast<uint32_t>(time(0)); // to calc rates
gLastEventReset = gEvtNum;
gDoResetLastCount = false;
}
*/
PIN_lockRegisters = 0; // done reading, unlock so we can talk to SD card.
#ifdef EVT_TIME_PROFILE
prof.stop(); befSaveEvt=prof.read_us(); prof.start();
#endif
SaveEvent(etms);
AddToRate(etms, false);
etms=0;
#ifdef EVT_TIME_PROFILE
prof.stop(); aftSaveEvt=prof.read_us(); prof.start();
#endif
}
}
#ifdef DEBUG
printf("past reading out\r\n");
#endif
if (gHrtbtFired) {
SaveHeartbeat();
gHrtbtFired=false;
}
led4=0; led2=0;
#ifdef EVT_TIME_PROFILE
prof.stop(); befChkPow=prof.read_us(); prof.start();
#endif
// check the power?
if (gCheckPower) {
#ifdef DEBUG
printf("call check power\r\n");
#endif
CheckPower(false);
}
#ifdef EVT_TIME_PROFILE
prof.stop(); aftChkPow=prof.read_us(); prof.start();
#endif
// open comm win?
if (gOpenCommWin) {
#ifdef DEBUG
printf("gOpenComWin=%s, opening\r\n",gOpenCommWin?"true":"false");
#endif
OpenCommWin();
gOpenCommWin=false;
gFirstEvt = true;
gTrgTimer.reset();
etms=0;
} else {
#ifdef DEBUG
printf("gOpenCommWin=false, gCommWinChecks=%u, gNcommWinChecks=%u\r\n",
gCommWinChecks, gNcommWinChecks);
#endif
}
#ifdef EVT_TIME_PROFILE
prof.stop(); befNewSeq=prof.read_us(); prof.start();
#endif
// make new seq?
if (IsSeqComplete()) {
#ifdef DEBUG
printf("seq complete. sngseq=%d\r\n",gConf.IsSingleSeqRunMode());
#endif
MakeOutputFile(gConf.IsSingleSeqRunMode());
gFirstEvt = true;
gTrgTimer.reset();
etms=0;
}
#ifdef EVT_TIME_PROFILE
prof.stop(); aftNewSeq=prof.read_us(); prof.start();
#endif
#ifdef EVT_TIME_PROFILE
prof.stop(); endOfLoop=prof.read_us(); prof.start();
printf("befReadWv=%d, aftReadWv=%d, befSaveEvt=%d, aftSaveEvt=%d, "
"befChkPow=%d, aftChkPow=%d, befNewSeq=%d, aftNewSeq=%d, endOfLoop=%d\r\n",
befReadWv, aftReadWv, befSaveEvt, aftSaveEvt,
befChkPow, aftChkPow, befNewSeq, aftNewSeq, endOfLoop);
#endif
// get ready to trigger
PIN_spi.format( 16, 1 ); // change to data readout format
PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
// reset event
// clear after comm win, so full event can be sent with status
// but don't clear counters or trigger bits, as
gEvent.ClearEvent(true);
}
}
//
// save a heartbeat tag
//
void SaveHeartbeat() {
if (gHrtbtNum>0) {
#ifdef DEBUG
printf("save heartbeat #%u, time %u\r\n",
gHrtbtNum-1, gLastHrtbt);
#endif
// save to SD
PIN_lockRegisters = 0; // unlock so we can talk to SD card.
SnSDUtils::WriteHeartbeatTo(SnSDUtils::GetCurFile(),
gLastHrtbt, gHrtbtNum-1); // -1 so it counts from 0
}
}
//
// save the event
//
void SaveEvent(const int32_t etms) {
// write the event
#ifdef DEBUG
printf("save event\r\n");
#endif
// set the event number & dt
gEvent.SetEvtNum(gEvtNum);
gEvent.SetDTms(etms);
// save to SD
PIN_lockRegisters = 0; // unlock so we can talk to SD card.
SnSDUtils::WriteEventTo(SnSDUtils::GetCurFile(), gGenBuf, gEvent, gConf);
// increment event number
++gEvtNum;
#ifdef DEBUG
printf("gEvtNum=%u\r\n",gEvtNum);
#endif
}
void MakeOutputFile(const bool stopRunning) {
PIN_lockRegisters = 0; // unlock so we can talk to SD card.
#ifdef DEBUG
printf("closing output file. gEvtNum=%u, gPowNum=%u, stop=%d\r\n",
gEvtNum,gPowNum,(int)stopRunning);
#endif
SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
#ifdef DEBUG
printf("file closed\r\n");
#endif
if (stopRunning) {
StopRunning();
}
FILE* cf = SnSDUtils::OpenNewOutputFile(gConf.GetMacAddress(),
gConf.GetRun());
// reset event, timers, trigger counters
ResetCountersClearEvt();
if (cf!=0) {
wait_ms(200);
GetAvePowerReading();
#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);
#endif
SnSDUtils::WritePowerTo(cf, gPower, gPowNum);
}
#ifdef DEBUG
printf("made output file with run %u\r\n",gConf.GetRun());
printf("filename=%s\r\n",SnSDUtils::GetCurFileName());
#endif
SnSDUtils::WriteConfig(SnSDUtils::GetCurFile(), gConf);
#ifdef DEBUG
printf("write config to file\r\n");
#endif
}
//
// power stuff
//
void SetPower(const bool isCommWin) {
#ifdef DEBUG
printf("bef: pconp=%u (%08x), pcenet=%u (%08x)\r\n",
LPC_SC->PCONP, LPC_SC->PCONP, LPC1768_PCONP_PCENET, LPC1768_PCONP_PCENET);
printf("pcenet bef power: status=%d\r\n",Peripheral_GetStatus(LPC1768_PCONP_PCENET));
#endif
// TODO: turn on amps individually, when that's possible
if (isCommWin) {
PIN_turn_on_system = gConf.GetPowPinSetting(SnConfigFrame::kCardComWin);
wait_ms(10);
PIN_turn_on_amps = gConf.GetPowPinSetting(SnConfigFrame::kAmpsComWin);
wait_ms(10);
PIN_iridSbd_power = gConf.GetPowPinSetting(SnConfigFrame::kIridComWin);
wait_ms(10);
#ifdef DEBUG
printf("afar pin=%d, com powsetting=%d\r\n",PIN_afar_power.read(),
gConf.GetPowPinSetting(SnConfigFrame::kAfarComWin));
#endif
if (gConf.IsPoweredFor(SnConfigFrame::kAfarComWin)) {
#ifdef DEBUG
printf("PHY cowin powering up\r\n");
#endif
PHY_PowerUp(); wait(1);
#ifdef DEBUG
printf("PHY cowin powered up\r\n");
#endif
} else {
#ifdef DEBUG
printf("PHY cowin powering down\r\n");
#endif
PHY_PowerDown(); wait(1);
#ifdef DEBUG
printf("PHY cowin powered down\r\n");
#endif
}
#ifdef DEBUG
printf("PHY done\r\n");
#endif
wait_ms(100);
PIN_afar_power = gConf.GetPowPinSetting(SnConfigFrame::kAfarComWin);
wait_ms(10);
} else {
PIN_turn_on_system = gConf.GetPowPinSetting(SnConfigFrame::kCardDatTak);
wait_ms(10);
PIN_turn_on_amps = gConf.GetPowPinSetting(SnConfigFrame::kAmpsDatTak);
wait_ms(10);
PIN_iridSbd_power = gConf.GetPowPinSetting(SnConfigFrame::kIridDatTak);
wait_ms(10);
#ifdef DEBUG
printf("afar pin=%d, dat powsetting=%d, ispow=%d\r\n",PIN_afar_power.read(),
gConf.GetPowPinSetting(SnConfigFrame::kAfarDatTak),
(int)(gConf.IsPoweredFor(SnConfigFrame::kAfarDatTak)));
#endif
if (gConf.IsPoweredFor(SnConfigFrame::kAfarDatTak)) {
#ifdef DEBUG
printf("PHY dattak powering up\r\n");
#endif
PHY_PowerUp(); wait(1);
#ifdef DEBUG
printf("PHY dattak powered up\r\n");
#endif
} else {
#ifdef DEBUG
printf("PHY dattak powering down\r\n");
#endif
PHY_PowerDown(); wait(1);
#ifdef DEBUG
printf("PHY dattak powered down\r\n");
#endif
}
#ifdef DEBUG
printf("PHY done\r\n");
#endif
wait_ms(100);
PIN_afar_power = gConf.GetPowPinSetting(SnConfigFrame::kAfarDatTak);
wait_ms(10);
}
wait(1.5); // let things power up
#ifdef DEBUG
printf("aft: pconp=%u (%08x), pcenet=%u (%08x)\r\n",
LPC_SC->PCONP, LPC_SC->PCONP, LPC1768_PCONP_PCENET, LPC1768_PCONP_PCENET);
#endif
#ifdef DEBUG
printf("power word (%hhu): ",gConf.GetPowerMode()); SnBitUtils::printBits(gConf.GetPowerMode(),true);
printf("set power (iscom %d, pw %hhu): cards %d, amps %d, irid %d, afar %d\r\n",
isCommWin, gConf.GetPowerMode(), PIN_turn_on_system.read(), PIN_turn_on_amps.read(),
PIN_iridSbd_power.read(), PIN_afar_power.read());
printf("pcenet aft power: status=%d\r\n",Peripheral_GetStatus(LPC1768_PCONP_PCENET));
#endif
}
//
// set configuration
//
void SetConfigAndMakeOutputFile() {
#ifdef DEBUG
printf("SetConfigAndMakeOutputFile\r\n");
#endif
// restart watchdog
Watchdog::kick(gConf.GetWatchdogPeriod());
// block (thermal) triggers during configuration
PIN_enableThermTrig = 0;
PIN_ADC_CS = 1;
PIN_DoNotRestartAllClocks = 1;
PIN_forceTrigger = 0;
PIN_heartbeat = 0;
wait_ms(20);
gCommWinChecks = 0;
gNcommWinChecks = gConf.GetCommWinPeriod() / kCommWinLongPrdTk;
if (AreCardsPowered(true)) {
// Set PLA value(s)
PIN_spi.format( 16, 0 ); // change mode for DAC & PLA value setting
PIN_spi.frequency(1000000);
PIN_MajLogHiBit=1;
PIN_MajLogLoBit=1;
PIN_enableThermTrig=0;
uint16_t hi, lo;
PIN_PLA_cs=1;
wait(4);
for (uint8_t pi=0; pi<kNplas; pi++) {
if (pi < gConf.GetNumPlas()) {
SnConfigFrame::GetHiLoPlas(gConf.GetPla(pi), hi, lo);
PIN_spi.write(hi);
PIN_spi.write(lo);
#ifdef DEBUG
printf("pla hi %hu, lo %hu\r\n",hi,lo);
#endif
} else {
PIN_spi.write(kNoTrigPla); // hi
PIN_spi.write(kNoTrigPla); // lo
#ifdef DEBUG
printf("pla hi %hu, lo %hu\r\n",kNoTrigPla,kNoTrigPla);
#endif
}
Watchdog::kick();
}
wait(3);
PIN_PLA_cs=0;
wait(3);
// DAC values
//
// first 12 bits = DAC value
// next 2 bits = DAC ID
// last 2 bits = dFPGA ID
//
// But FPGA uses "gray encoding" which means only 1 bit
// can change at a time (of the last 4 bits). So even tho
// 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.
#ifdef DEBUG
printf("setting dacs\r\n");
#endif
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);
// build bit word
dv = static_cast<int>(gConf.GetDac(gri & 0x0003u, gri >> 2u));
dv <<= 4u;
dv |= gri;
#ifdef DEBUG
printf("dac %04x\r\n",dv);
#endif
// send to FPGA
PIN_start_fpga=1;
PIN_spi.write(dv);
PIN_start_fpga=0;
Watchdog::kick();
}
#ifdef DEBUG
printf("dacs set\r\n");
#endif
wait_ms(20);
} else {
#ifdef DEBUG
printf("cards off. skipping PLA and DAC setting\r\n");
#endif
}
// Majority Logic Trigger selection (# of cards)
SnBitUtils::SetChanNumBits(gConf.GetNumCardsMajLog() - 1u,
PIN_MajLogHiBit, PIN_MajLogLoBit);
// Enable thermal trigger?
PIN_enableThermTrig = gConf.IsThermTrigEnabled();
PIN_spi.format( 16, 1 ); // back to trigger mode
PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
// make new output file
// put after PLA/DAC, in case they affect the power readings
wait_ms(200);
MakeOutputFile();
// reset tickers
ResetAllTickers();
Watchdog::kick(); // don't reset!
#ifdef DEBUG
printf("set config done\r\n");
#endif
}
//
// readout functions
//
void WaitTrigAndSendClock() {
#ifdef DEBUG
printf("WaitTrigAndSendClock\r\n");
printf("wait trig: (pw %hhu): cards %d, amps %d, irid %d, afar %d\r\n",
gConf.GetPowerMode(), PIN_turn_on_system.read(), PIN_turn_on_amps.read(),
PIN_iridSbd_power.read(), PIN_afar_power.read());
printf("cards powered=%d\r\n",(int)AreCardsPowered(true));
#endif
PIN_spi.format( 16, 1 ); // back to trigger mode
PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
if (AreCardsPowered(false)) {
#ifdef DEBUG
printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
#endif
if (gFirstEvt==false) {
PIN_DoNotRestartAllClocks = 0;
wait_us(1);
PIN_DoNotRestartAllClocks = 1;
//led3 = !led3; // toggle send clock led
} else {
gFirstEvt = false;
}
//
// wait for a trigger here.
//
#ifdef DEBUG
printf("starting wait for trig\r\n");
#endif
gReadingOut = false; // this will allow forced triggers (see procForceTrigger())
while ( PIN_a_sf_clk == 1 ) {
if (gOpenCommWin || gCheckPower) {
#ifdef DEBUG
printf("break com=%d, pow=%d\r\n",gOpenCommWin,gCheckPower);
#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);
//
// 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)
gAdcToMBtimer.start();
for( uint8_t i = 0; i < 128; ++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
printf("total time = %d us\r\n", gAdcToMBtimer.read_us());
#endif
if ( kAdcToMBtimeCut < gAdcToMBtimer.read_us() ) {
gEvent.SetTrgBit(kAdcToMBflag);
}
gAdcToMBtimer.reset();
// restart the timers
//ResetAllTickers();
} else {
// cards have no power. don't try reading out
gReadingOut=false;
}
}
SnCommWin::ECommWinResult OpenCommWin(const bool forceReconfig) {
// loop through each comm mode:
// a) try to connect
// b) if connected, listen for config
// c) if config requests data, send it
/*
for (int i=0; i<5; i++) {
led4=1;
led3=1;
wait(0.5);
led4=0;
led3=0;
wait(0.5);
}
*/
gLastCommWin = time(0);
SnCommWin::ECommWinResult res = SnCommWin::kUndefFail;
// get the trigger rates
float thmrate=0, evtrate=0;
GetRates(thmrate, evtrate);
#ifdef DEBUG
printf("thmrate=%g, evtrate=%g\r\n",thmrate,evtrate);
#endif
StopAllTickers();
if (gConf.GetCommWinDuration()==0) {
// TODO: set min so this is not possible
res = SnCommWin::kOkNoMsg;
} else {
gCommWinOpen = true;
Watchdog::kick(); // don't reset!
#ifdef DEBUG
printf("opening comm window at %d\r\n", (int32_t)gLastCommWin);
printf("duration=%u\r\n",gConf.GetCommWinDuration());
#endif
// close the file so that the data is all written out.
// and open it back up at the beginning (for reading)
#ifdef DEBUG
printf("close & open file. gEvtNum=%u, gPowNum=%u\r\n",gEvtNum,gPowNum);
printf("curfile=%p, filename=%s\r\n",SnSDUtils::GetCurFile(),
SnSDUtils::GetCurFileName());
#endif
PIN_lockRegisters = 0; // unlock so we can talk to SD card.
#ifdef DEBUG
printf("closing output file\r\n");
#endif
SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
#ifdef DEBUG
printf("open existing file (%d)\r\n",strlen(SnSDUtils::GetCurFileName()));
#endif
SnSDUtils::OpenExistingFile(SnSDUtils::GetCurFileName(), true, false);
#ifdef DEBUG
printf("setting power\r\n");
#endif
// (probably) power down cards,amps and power up comms
SetPower(true);
// time to recount files for the status update
SnStatusFrame::fgRecalcFiles = true;
#if defined(ENABLE_AFAR_TWITTER) && defined(ENABLE_AFAR_COMM)
bool doTwitter = false;
#endif
#ifdef DEBUG
printf("start loop over comms\r\n");
#endif
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; ((time(0)-gLastCommWin)<gConf.GetCommWinDuration()); i++, cw++, ss++) {
Watchdog::kick(); // don't reset!
if (i==kNcomms) {
i=0;
cw = gComms;
ss = sendStat;
}
// skip if no comm object
if ((*cw)==0) {
continue;
}
// skip if no power for this comm
// THIS IS VITAL! For example, if the ethernet
// port is powered down, making an Ethernet obejct
// (done in netif) will stall forever waiting for the clock.
// Do it here to keep all PIN usage in main.cpp
bool havePower=false;
switch ((*cw)->GetCommType()) {
case SnConfigFrame::kIrid:
havePower = gConf.IsPoweredFor(SnConfigFrame::kIridComWin)
&& (PIN_iridSbd_power.read() ==
gConf.GetPowPinSetting(SnConfigFrame::kIridComWin));
break;
case SnConfigFrame::kAfar:
havePower = gConf.IsPoweredFor(SnConfigFrame::kAfarComWin)
&& (PIN_afar_power.read() ==
gConf.GetPowPinSetting(SnConfigFrame::kAfarComWin));
break;
case SnConfigFrame::kUSB:
havePower = true; // USB always on (for now)
break;
case SnConfigFrame::kSDcard: // shouldn't happen. skip it
default: // unknown.. skip it
break;
};
if (havePower==false) {
continue;
}
const uint32_t conto =
(gConf.GetCommWinDuration() < (*cw)->GetConnectTimeout()) ?
gConf.GetCommWinDuration() : (*cw)->GetConnectTimeout();
const uint32_t listo =
(gConf.GetCommWinDuration() < (*cw)->GetListenTimeout()) ?
gConf.GetCommWinDuration() : (*cw)->GetListenTimeout();
// update power reading in case we want to send it in status
GetAvePowerReading();
// open window and (mabye) send status update
#ifdef DEBUG
printf("calling OpenWindow. ss=%d\r\n",(int)(*ss));
printf("gtt=%u, ct=%d, lcw=%d, dur=%u\r\n",gConf.GetTimeoutTime(gLastCommWin,conto),
time(0), gLastCommWin, gConf.GetCommWinDuration());
#endif
const SnCommWin::ECommWinResult conres = (*cw)->OpenWindow(
gConf.GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gEvent, gPower,
SnSDUtils::GetCurSeqNum(), thmrate, evtrate,
gGenBuf);
if (conres>=SnCommWin::kConnected) {
Watchdog::kick(); // don't reset!
// connected. listen for config
*ss = false; // don't send status next time
#if defined(ENABLE_AFAR_TWITTER) && defined(ENABLE_AFAR_COMM)
if ((*cw)->GetCommType()==SnConfigFrame::kAfar) {
// if we connected by Afar
doTwitter = true;
}
#endif
#ifdef DEBUG
printf("get conf gtt=%u\r\n",gConf.GetTimeoutTime(gLastCommWin, listo));
#endif
const SnCommWin::ECommWinResult cfgres = (*cw)->GetConfig(
gConf, gConf.GetTimeoutTime(gLastCommWin, listo), gGenBuf, gBufSize);
if (cfgres>=SnCommWin::kOkWithMsg) {
Watchdog::kick(); // don't reset!
#ifdef DEBUG
printf("received config!\r\n");
printf("send data = %d\r\n", gConf.GetCommSendData());
#endif
// send data if need be (files, some events, etc)
const uint32_t winto = gConf.GetTimeoutTime(gLastCommWin,
gConf.GetCommWinDuration());
const uint32_t gtt = gConf.IsObeyingTimeout() ? winto : 0;
if (gConf.GetCommSendData()!=0) {
#ifdef DEBUG
printf("sending data, gtt=%u. lcw=%u, dur=%u, obey=%s\r\n",
gConf.GetTimeoutTime(gLastCommWin, gConf.GetCommWinDuration()),
gLastCommWin, gConf.GetCommWinDuration(),
gConf.IsObeyingTimeout() ? "true" : "false");
#endif
res = (*cw)->SendData(gConf, gEvent, gPower, gGenBuf, gBufSize,
gtt, gConf.GetCommWinDuration());
} else {
// don't send anything
res = cfgres;
}
#ifdef DEBUG
printf("Got config!\r\n");
#endif
Watchdog::kick(); // don't reset!
break;
}
} else {
(*cw)->CloseConn(gConf.GetTimeoutTime(gLastCommWin, listo));
} // if connected
Watchdog::kick(); // don't reset!
} // end loop over comms
// check Iridium time & close the connection(s)
cw = gComms;
for (uint8_t i=0; i<kNcomms; i++, cw++) {
if ((*cw)==0) {
continue;
}
// check Iridium time
if ((*cw)->GetCommType()==SnConfigFrame::kIrid) {
#ifdef DEBUG
printf("try to set iridium time\r\n");
#endif
// set the clock before closing connection
const bool con =
(*cw)->Connect(gConf.GetTimeoutTime(gLastCommWin,
gConf.GetCommWinDuration()));
if (con) {
const uint32_t nt = (*cw)->TrySetSysTimeUnix(
gConf.GetTimeoutTime(gLastCommWin,gConf.GetCommWinDuration()));
}
}
// close the connection
(*cw)->CloseConn(gConf.GetTimeoutTime(gLastCommWin,gConf.GetCommWinDuration()));
Watchdog::kick(); // don't reset!
// after normal Afar connection closed, try to tweet
if ((*cw)->GetCommType()==SnConfigFrame::kAfar) {
// tweet
#if defined(ENABLE_AFAR_TWITTER) && defined(ENABLE_AFAR_COMM)
#ifdef DEBUG
printf("for twitter: gTwit=%p, doTwitter=%d\r\n",gTwit,(int)doTwitter);
#endif
// send a twitter update
if ( (gTwit!=0) && doTwitter ) {
const uint32_t conto =
(gConf.GetCommWinDuration() < gTwit->GetConnectTimeout()) ?
gConf.GetCommWinDuration() : gTwit->GetConnectTimeout();
const uint32_t listo =
(gConf.GetCommWinDuration() < gTwit->GetListenTimeout()) ?
gConf.GetCommWinDuration() : gTwit->GetListenTimeout();
#ifdef DEBUG
printf("open twit window. conto=%u, listo=%u\r\n",
conto, listo);
#endif
const SnCommWin::ECommWinResult conres = gTwit->OpenWindow(
gConf.GetTimeoutTime(gLastCommWin, conto), false, gConf,
gEvent, gPower,
SnSDUtils::GetCurSeqNum(), thmrate, evtrate,
gGenBuf);
if (conres>=SnCommWin::kConnected) {
Watchdog::kick(); // don't reset!
gTwit->Tweet(gConf, thmrate, evtrate, gGenBuf,
gConf.GetTimeoutTime(time(0), listo));
}
}
}
#endif
}
} // if duration >0
/* not working. must use DEFCONF.DAT to change IP's.
// change comm parameters (IP addresses)
#ifdef DEBUG
printf("set comm params\r\n");
#endif
for (uint8_t cc=0; cc<kNcomms; cc++) {
if (gComms[cc]!=0) {
gComms[cc]->Set(gConf);
}
}
*/
// (probably) power down comms and power up cards,amps
SetPower(false);
// reset config with system powered (for DAC/PLA setting)
#ifdef DEBUG
printf("calling SetConfigAndMakeOutputFile\r\n");
#endif
SetConfigAndMakeOutputFile();
#ifdef DEBUG
printf("closing comm win at %d\r\n",(int32_t)time(0));
#endif
gCommWinOpen = false;
return res;
}