Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Sat Sep 29 04:54:15 2012 +0000
Revision:
18:55f1581f2ee4
Parent:
17:4687bf932b8c
Child:
19:74155d652c37
This version uses USB communication only. Changed forced trigger period to be a float, so subsecond trigs are possible. Changed from EthernetInterface to NetServicesMin. This allows slow (2KBps) transfer over TCP, but at least it's robust.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
uci1 0:664899e0b988 1 #include "mbed.h"
uci1 0:664899e0b988 2
uci1 18:55f1581f2ee4 3 //#define USE_RTOS_TIMER
uci1 18:55f1581f2ee4 4 //#define USE_ETH_INTERFACE
uci1 8:95a325df1f6b 5
uci1 12:d472f9811262 6 //#define EVT_TIME_PROFILE
uci1 14:2736b57bbbed 7 //#define DEBUG
uci1 16:744ce85aede2 8 //#define SSNOTIFY
uci1 15:f2569d8e4176 9 #define USE_MODSERIAL
uci1 12:d472f9811262 10
uci1 0:664899e0b988 11 #include <stdint.h>
uci1 0:664899e0b988 12 #include "SDFileSystem.h"
uci1 15:f2569d8e4176 13 #ifdef USE_MODSERIAL
uci1 0:664899e0b988 14 #include "MODSERIAL.h"
uci1 18:55f1581f2ee4 15 #define MODSERIAL_RX_BUF_SIZE 512
uci1 18:55f1581f2ee4 16 #define MODSERIAL_TX_BUF_SIZE 512
uci1 15:f2569d8e4176 17 #endif
uci1 0:664899e0b988 18 #include "Watchdog.h"
uci1 0:664899e0b988 19 #include "SnConstants.h"
uci1 0:664899e0b988 20 #include "SnBitUtils.h"
uci1 0:664899e0b988 21 #include "SnSDUtils.h"
uci1 0:664899e0b988 22 #include "SnConfigFrame.h"
uci1 0:664899e0b988 23 #include "SnEventFrame.h"
uci1 0:664899e0b988 24 #include "SnStatusFrame.h"
uci1 2:e67f7c158087 25 #include "SnHeaderFrame.h"
uci1 0:664899e0b988 26 #include "SnCommWin.h"
uci1 18:55f1581f2ee4 27 #ifdef USE_ETH_INTERFACE
uci1 7:079617408fec 28 #include "SnCommAfarTCP.h"
uci1 18:55f1581f2ee4 29 #else
uci1 18:55f1581f2ee4 30 #include "SnCommAfarNetIf.h"
uci1 18:55f1581f2ee4 31 #endif
uci1 0:664899e0b988 32 #include "SnCommUsb.h"
uci1 15:f2569d8e4176 33 #include "SnCommSBD.h"
uci1 1:e392595b4b76 34 #include "SnBase64.h"
uci1 8:95a325df1f6b 35 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 36 #include "RtosTimer.h"
uci1 8:95a325df1f6b 37 #endif
uci1 0:664899e0b988 38
uci1 0:664899e0b988 39 //
uci1 0:664899e0b988 40 // MBED PINS (ordered by number)
uci1 0:664899e0b988 41 //
uci1 0:664899e0b988 42 // leds (for debugging)
uci1 0:664899e0b988 43 DigitalOut led1(LED1);
uci1 0:664899e0b988 44 DigitalOut led2(LED2);
uci1 0:664899e0b988 45 DigitalOut led3(LED3);
uci1 0:664899e0b988 46 DigitalOut led4(LED4);
uci1 0:664899e0b988 47 // Set up power pins - Note that it's Zero for "on"
uci1 1:e392595b4b76 48 DigitalOut PIN_turn_on_system(p17); // this turns on system
uci1 0:664899e0b988 49 DigitalOut PIN_turn_on_amps(p25);
uci1 15:f2569d8e4176 50 // SD card select
uci1 15:f2569d8e4176 51 DigitalOut PIN_SD_CS(p8);
uci1 0:664899e0b988 52 // Activate/select chip by falling edge
uci1 0:664899e0b988 53 DigitalOut PIN_ADC_CS( p9 );
uci1 0:664899e0b988 54 // clock signal to activate PLA setting
uci1 0:664899e0b988 55 DigitalOut PIN_PLA_cs(p10);
uci1 0:664899e0b988 56 // To force a trigger
uci1 0:664899e0b988 57 DigitalOut PIN_forceTrigger(p11); //modification
uci1 0:664899e0b988 58 // To suppress thermal triggers
uci1 0:664899e0b988 59 DigitalOut PIN_enableThermTrig(p12);
uci1 0:664899e0b988 60 // Restart clock on all FPGAs.
uci1 0:664899e0b988 61 DigitalOut PIN_DoNotRestartAllClocks( p13 );
uci1 0:664899e0b988 62 // This tells the DFPGAs to store the data on motherboard FPGA and
uci1 0:664899e0b988 63 // read it out.
uci1 0:664899e0b988 64 DigitalIn PIN_a_sf_clk( p14 );
uci1 0:664899e0b988 65 DigitalIn PIN_rst_a_sf(p15);
uci1 1:e392595b4b76 66 // afar power
uci1 1:e392595b4b76 67 DigitalOut PIN_afar_power(p16);
uci1 4:a91682e19d6b 68 // batter voltage/current measurement
uci1 4:a91682e19d6b 69 AnalogIn PIN_vADC1(p19);
uci1 4:a91682e19d6b 70 AnalogIn PIN_vADC2(p18);
uci1 0:664899e0b988 71 // Lock daughter card registeres (during data readout).
uci1 0:664899e0b988 72 DigitalOut PIN_lockRegisters( p20 );
uci1 1:e392595b4b76 73 // iridium (SBD) power
uci1 1:e392595b4b76 74 DigitalOut PIN_iridSbd_power(p21);
uci1 0:664899e0b988 75 // Majority logic pins
uci1 0:664899e0b988 76 DigitalOut PIN_MajLogHiBit(p22);
uci1 0:664899e0b988 77 DigitalOut PIN_MajLogLoBit(p23);
uci1 0:664899e0b988 78 // Tell FPGA to be ready to accept DAC values
uci1 0:664899e0b988 79 DigitalOut PIN_start_fpga(p26);
uci1 0:664899e0b988 80 // Two bits to the select the daughter card for readout
uci1 0:664899e0b988 81 DigitalOut PIN_selCardHiBit( p29 );
uci1 0:664899e0b988 82 DigitalOut PIN_selCardLoBit( p30 );
uci1 0:664899e0b988 83 // To launch a heartbeat pulse
uci1 0:664899e0b988 84 DigitalOut PIN_heartbeat(p24);
uci1 0:664899e0b988 85 // Setup SPI pins
uci1 0:664899e0b988 86 SPI PIN_spi( p5, p6, p7 );
uci1 0:664899e0b988 87 // The SD card
uci1 3:24c5f0f50bf1 88
uci1 3:24c5f0f50bf1 89 // this needs to be first in case some other global uses a print statement
uci1 15:f2569d8e4176 90 #ifdef USE_MODSERIAL
uci1 16:744ce85aede2 91 #define SERIAL_TYPE MODSERIAL
uci1 15:f2569d8e4176 92 #else
uci1 16:744ce85aede2 93 #define SERIAL_TYPE Serial
uci1 15:f2569d8e4176 94 #endif
uci1 16:744ce85aede2 95 static SERIAL_TYPE gCpu( USBTX, USBRX // defined here so it might be used for debugging output
uci1 16:744ce85aede2 96 #ifdef USE_MODSERIAL
uci1 16:744ce85aede2 97 ,MODSERIAL_TX_BUF_SIZE,
uci1 16:744ce85aede2 98 MODSERIAL_RX_BUF_SIZE
uci1 16:744ce85aede2 99 #endif
uci1 16:744ce85aede2 100 );
uci1 16:744ce85aede2 101 static SERIAL_TYPE gSBDport(p28, p27, "sbd");
uci1 13:7a1fb885a8e4 102 static SDFileSystem sd(p5, p6, p7, p8, SnSDUtils::kSDsubDir+1);
uci1 13:7a1fb885a8e4 103 static LocalFileSystem local("local");
uci1 0:664899e0b988 104
uci1 0:664899e0b988 105 //
uci1 0:664899e0b988 106 // fwd declare fcns
uci1 0:664899e0b988 107 //
uci1 0:664899e0b988 108 void ReadAllRegisters();
uci1 0:664899e0b988 109 void ReadRegister(const uint8_t chan, int16_t* dev);
uci1 0:664899e0b988 110 void SaveEvent(const int32_t etms);
uci1 0:664899e0b988 111 void WaitTrigAndSendClock();
uci1 1:e392595b4b76 112 void SetConfigAndMakeOutputFile();
uci1 13:7a1fb885a8e4 113 SnCommWin::ECommWinResult OpenCommWin(const bool forceReconfig=false);
uci1 3:24c5f0f50bf1 114 void MakeOutputFile(const bool stopRunning=false);
uci1 4:a91682e19d6b 115 void SetPower(const bool isCommWin);
uci1 8:95a325df1f6b 116 void procForceTrigger();
uci1 8:95a325df1f6b 117 void procHeartbeat();
uci1 8:95a325df1f6b 118 void procPowerCheck();
uci1 8:95a325df1f6b 119 void procCommWin();
uci1 8:95a325df1f6b 120 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 121 void procForceTrigger(void const *) { return procForceTrigger(); }
uci1 8:95a325df1f6b 122 void procHeartbeat(void const *) { return procHeartbeat(); }
uci1 8:95a325df1f6b 123 void procPowerCheck(void const *) { return procPowerCheck(); }
uci1 8:95a325df1f6b 124 void procCommWin(void const *) { return procCommWin(); }
uci1 8:95a325df1f6b 125 #endif
uci1 0:664899e0b988 126
uci1 0:664899e0b988 127 //
uci1 0:664899e0b988 128 // globals
uci1 0:664899e0b988 129 //
uci1 0:664899e0b988 130 // readout objs
uci1 8:95a325df1f6b 131 // TODO: use RtosTimer instead of Ticker?
uci1 8:95a325df1f6b 132 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 133 static rtos::RtosTimer* gForceTicker;
uci1 8:95a325df1f6b 134 static rtos::RtosTimer* gHeartbeatTicker;
uci1 8:95a325df1f6b 135 static rtos::RtosTimer* gCommWinTicker;
uci1 8:95a325df1f6b 136 static rtos::RtosTimer* gPowerCheckTicker;
uci1 8:95a325df1f6b 137 #else
uci1 0:664899e0b988 138 static Ticker gForceTicker;
uci1 3:24c5f0f50bf1 139 static Ticker gHeartbeatTicker;
uci1 1:e392595b4b76 140 static Ticker gCommWinTicker;
uci1 8:95a325df1f6b 141 static Ticker gPowerCheckTicker;
uci1 8:95a325df1f6b 142 #endif
uci1 12:d472f9811262 143 static Timer gTrgTimer;
uci1 16:744ce85aede2 144 static Timer gAdcToMBtimer;
uci1 0:664899e0b988 145 static SnConfigFrame gConf;
uci1 0:664899e0b988 146 static SnEventFrame gEvent;
uci1 8:95a325df1f6b 147 static SnPowerFrame gPower;
uci1 0:664899e0b988 148 // parameters
uci1 0:664899e0b988 149 static bool gFirstEvt = true;
uci1 15:f2569d8e4176 150 static volatile bool gReadingOut = false;
uci1 15:f2569d8e4176 151 static volatile bool gCommWinOpen = false; // if it's open
uci1 1:e392595b4b76 152 static volatile bool gOpenCommWin = false; // if it should be opened
uci1 8:95a325df1f6b 153 static volatile bool gCheckPower = false; // if it should be checked
uci1 8:95a325df1f6b 154 static uint32_t gPowNum = 0;
uci1 8:95a325df1f6b 155 static uint32_t gEvtNum = 0; // num of evt written
uci1 8:95a325df1f6b 156 static uint32_t gTrgNum[kNumTrgs] = {0}; // num of this type of trg received
uci1 0:664899e0b988 157 // i/o
uci1 1:e392595b4b76 158 static time_t gLastCommWin = 0;
uci1 10:3c93db1cfb12 159 static uint32_t gLastCountReset = 0;
uci1 10:3c93db1cfb12 160 // this should be bigger than anything that will actually be used
uci1 10:3c93db1cfb12 161 static const uint32_t gBufSize=SnStatusFrame::kMaxSizeOf + (2u*SnHeaderFrame::kMaxSizeOf) + SnPowerFrame::kMaxSizeOf;
uci1 6:6f002d202f59 162 //static const uint32_t gB64Bsize=BASE64ENC_LEN(gBufSize)+1;
uci1 6:6f002d202f59 163 //static char gB64Buf[gB64Bsize];
uci1 3:24c5f0f50bf1 164 static char gGenBuf[gBufSize]; // must be big enough for event or status or config!
uci1 11:de443350ec4a 165 static SnCommWin* gComms[kNcomms] = { 0 }; // order => priority. afar uses RTOS, and must be made inside main
uci1 0:664899e0b988 166
uci1 0:664899e0b988 167 void procForceTrigger() {
uci1 0:664899e0b988 168 if (gReadingOut==false && gCommWinOpen==false) {
uci1 15:f2569d8e4176 169 led3=!led3;
uci1 12:d472f9811262 170 #ifdef DEBUG
uci1 8:95a325df1f6b 171 printf("proc force\r\n");
uci1 12:d472f9811262 172 #endif
uci1 0:664899e0b988 173 gEvent.SetTrgBit(kFrcTrg);
uci1 0:664899e0b988 174 gEvent.SetTrgNum((gTrgNum[kFrcTrg])++);
uci1 0:664899e0b988 175 PIN_forceTrigger = 1; // force a trigger
uci1 0:664899e0b988 176 }
uci1 0:664899e0b988 177 }
uci1 0:664899e0b988 178
uci1 3:24c5f0f50bf1 179 void procHeartbeat() {
uci1 3:24c5f0f50bf1 180 if (gReadingOut==false && gCommWinOpen==false) {
uci1 12:d472f9811262 181 #ifdef DEBUG
uci1 8:95a325df1f6b 182 printf("proc heartbeat\r\n");
uci1 12:d472f9811262 183 #endif
uci1 3:24c5f0f50bf1 184 PIN_heartbeat = 1; // heartbeat pulse
uci1 3:24c5f0f50bf1 185 PIN_heartbeat = 0;
uci1 3:24c5f0f50bf1 186 }
uci1 3:24c5f0f50bf1 187 }
uci1 3:24c5f0f50bf1 188
uci1 8:95a325df1f6b 189 void procPowerCheck() {
uci1 12:d472f9811262 190 #ifdef DEBUG
uci1 8:95a325df1f6b 191 printf("proc power\r\n");
uci1 12:d472f9811262 192 #endif
uci1 8:95a325df1f6b 193 gCheckPower=true;
uci1 8:95a325df1f6b 194 }
uci1 8:95a325df1f6b 195
uci1 0:664899e0b988 196 void procCommWin() {
uci1 0:664899e0b988 197 if (gReadingOut==false && gCommWinOpen==false) {
uci1 1:e392595b4b76 198 if ( (time(0) - gLastCommWin) > gConf.GetCommWinPeriod() ) {
uci1 12:d472f9811262 199 #ifdef DEBUG
uci1 8:95a325df1f6b 200 printf("proc comm win\r\n");
uci1 12:d472f9811262 201 #endif
uci1 1:e392595b4b76 202 led3=!led3;
uci1 1:e392595b4b76 203 gOpenCommWin = true;
uci1 1:e392595b4b76 204 }
uci1 0:664899e0b988 205 }
uci1 0:664899e0b988 206 }
uci1 0:664899e0b988 207
uci1 1:e392595b4b76 208 uint32_t GetTimeoutTime(const uint32_t startTime,
uci1 1:e392595b4b76 209 const uint32_t delta) {
uci1 16:744ce85aede2 210 const uint32_t ct = time(0);
uci1 16:744ce85aede2 211 uint32_t lst = time(0)-startTime;
uci1 16:744ce85aede2 212 if ( (ct<startTime) || (ct==0) ||
uci1 16:744ce85aede2 213 (lst>kSecsPerDay) ) {
uci1 16:744ce85aede2 214 // possible clock problems
uci1 16:744ce85aede2 215 lst = kDefTimeout;
uci1 16:744ce85aede2 216 }
uci1 1:e392595b4b76 217 const uint32_t lio =
uci1 1:e392595b4b76 218 ((lst+delta) < gConf.GetCommWinDuration()) ?
uci1 1:e392595b4b76 219 lst+delta : gConf.GetCommWinDuration();
uci1 1:e392595b4b76 220 return lio+startTime;
uci1 1:e392595b4b76 221 }
uci1 1:e392595b4b76 222
uci1 8:95a325df1f6b 223 bool AreCardsPowered() {
uci1 12:d472f9811262 224 #ifdef DEBUG
uci1 8:95a325df1f6b 225 printf("acp: PIN_turn_on_system=%d\r\n",PIN_turn_on_system.read());
uci1 12:d472f9811262 226 #endif
uci1 8:95a325df1f6b 227 return (PIN_turn_on_system.read()==0);
uci1 8:95a325df1f6b 228 }
uci1 0:664899e0b988 229
uci1 8:95a325df1f6b 230 void GetAvePowerReading() {
uci1 8:95a325df1f6b 231 // use one measurement as the assumed average
uci1 8:95a325df1f6b 232 // in order to reduce computational errors
uci1 8:95a325df1f6b 233 int32_t v1, v2;
uci1 8:95a325df1f6b 234 const uint16_t aaveV1 = PIN_vADC1.read_u16();
uci1 8:95a325df1f6b 235 const uint16_t aaveV2 = PIN_vADC2.read_u16();
uci1 8:95a325df1f6b 236 float n=0, ave1=0, ave2=0, rms1=0, rms2=0;
uci1 8:95a325df1f6b 237 for (uint16_t i=0; i<kNvoltsAve; i++) {
uci1 8:95a325df1f6b 238 v1 = PIN_vADC1.read_u16() - aaveV1;
uci1 8:95a325df1f6b 239 v2 = PIN_vADC2.read_u16() - aaveV2;
uci1 8:95a325df1f6b 240 n += 1;
uci1 8:95a325df1f6b 241 ave1 += v1;
uci1 8:95a325df1f6b 242 rms1 += v1*v1;
uci1 8:95a325df1f6b 243 ave2 += v2;
uci1 8:95a325df1f6b 244 rms2 += v2*v2;
uci1 8:95a325df1f6b 245 }
uci1 8:95a325df1f6b 246 rms1 -= (ave1*ave1)/n;
uci1 8:95a325df1f6b 247 rms2 -= (ave2*ave2)/n;
uci1 8:95a325df1f6b 248 rms1 /= n-1;
uci1 8:95a325df1f6b 249 rms2 /= n-1;
uci1 9:a1a39573dd43 250 rms1 = sqrt(rms1);
uci1 9:a1a39573dd43 251 rms2 = sqrt(rms2);
uci1 8:95a325df1f6b 252 ave1 /= n;
uci1 8:95a325df1f6b 253 ave2 /= n;
uci1 8:95a325df1f6b 254 ave1 += aaveV1;
uci1 8:95a325df1f6b 255 ave2 += aaveV2;
uci1 8:95a325df1f6b 256 gPower.Set(ave1, ave2, rms1, rms2, time(0));
uci1 8:95a325df1f6b 257 }
uci1 0:664899e0b988 258
uci1 8:95a325df1f6b 259 void CheckPower(const bool isCommWin) {
uci1 12:d472f9811262 260 #ifdef DEBUG
uci1 8:95a325df1f6b 261 printf("CheckPower\r\n");
uci1 12:d472f9811262 262 #endif
uci1 8:95a325df1f6b 263 // read power
uci1 8:95a325df1f6b 264 GetAvePowerReading();
uci1 8:95a325df1f6b 265 // save to disk
uci1 8:95a325df1f6b 266 FILE* cf = SnSDUtils::GetCurFile();
uci1 8:95a325df1f6b 267 if (cf!=0) {
uci1 11:de443350ec4a 268 PIN_lockRegisters = 0; // unlock so we can talk to SD card.
uci1 12:d472f9811262 269 #ifdef DEBUG
uci1 8:95a325df1f6b 270 printf("writing power. v1=%g, v2=%g, r1=%g, r2=%g, t=%u, pownum=%u\r\n",
uci1 8:95a325df1f6b 271 gPower.GetAveV1(), gPower.GetAveV2(),
uci1 8:95a325df1f6b 272 gPower.GetRmsV1(), gPower.GetRmsV2(), gPower.GetTime(),
uci1 8:95a325df1f6b 273 gPowNum);
uci1 12:d472f9811262 274 #endif
uci1 8:95a325df1f6b 275 SnSDUtils::WritePowerTo(cf, gPower, gPowNum);
uci1 8:95a325df1f6b 276 }
uci1 8:95a325df1f6b 277 // do we need to change modes?
uci1 8:95a325df1f6b 278 bool changed = false;
uci1 8:95a325df1f6b 279 if (gConf.IsLowPowerMode()) {
uci1 8:95a325df1f6b 280 if (gPower.GetAveV1() > gConf.GetBatVoltLowPwr()) {
uci1 12:d472f9811262 281 #ifdef DEBUG
uci1 8:95a325df1f6b 282 printf("chaing to normal power!\r\n");
uci1 12:d472f9811262 283 #endif
uci1 8:95a325df1f6b 284 gConf.ChangeToNormPower();
uci1 8:95a325df1f6b 285 changed = true;
uci1 8:95a325df1f6b 286 }
uci1 8:95a325df1f6b 287 } else {
uci1 8:95a325df1f6b 288 if (gPower.GetAveV1() < gConf.GetBatVoltLowPwr()) {
uci1 12:d472f9811262 289 #ifdef DEBUG
uci1 8:95a325df1f6b 290 printf("chaing to low power!\r\n");
uci1 12:d472f9811262 291 #endif
uci1 8:95a325df1f6b 292 gConf.ChangeToLowPower();
uci1 8:95a325df1f6b 293 changed = true;
uci1 8:95a325df1f6b 294 }
uci1 8:95a325df1f6b 295 }
uci1 8:95a325df1f6b 296 if (changed) {
uci1 8:95a325df1f6b 297 SetPower(isCommWin);
uci1 12:d472f9811262 298 #ifdef DEBUG
uci1 8:95a325df1f6b 299 printf("Using config %s\r\n",gConf.GetLabel());
uci1 12:d472f9811262 300 #endif
uci1 8:95a325df1f6b 301 SetConfigAndMakeOutputFile(); // setup defaults in case no communication
uci1 8:95a325df1f6b 302 }
uci1 8:95a325df1f6b 303 // checking done
uci1 8:95a325df1f6b 304 gCheckPower = false;
uci1 8:95a325df1f6b 305 }
uci1 8:95a325df1f6b 306
uci1 10:3c93db1cfb12 307 void ResetCountersClearEvt() {
uci1 12:d472f9811262 308 const uint32_t evtStartCurSeq = (SnSDUtils::GetCurSeqNum()) // no -1; start with seq=0
uci1 12:d472f9811262 309 * gConf.GetEvtsPerFile();
uci1 10:3c93db1cfb12 310 gEvent.ClearEvent();
uci1 12:d472f9811262 311 gEvtNum = gConf.GetFirstEvt() + evtStartCurSeq;
uci1 12:d472f9811262 312 gPowNum = evtStartCurSeq;
uci1 10:3c93db1cfb12 313 memset(gTrgNum, 0, sizeof(uint32_t)*kNumTrgs);
uci1 13:7a1fb885a8e4 314 gLastCountReset = static_cast<uint32_t>(time(0)); // to calc rates
uci1 13:7a1fb885a8e4 315 #ifdef DEBUG
uci1 13:7a1fb885a8e4 316 printf("Reset: gEvtNum=%u, gPowNum=%u, evtStartCS=%u\r\n",
uci1 13:7a1fb885a8e4 317 gEvtNum, gPowNum, evtStartCurSeq);
uci1 13:7a1fb885a8e4 318 #endif
uci1 10:3c93db1cfb12 319 }
uci1 10:3c93db1cfb12 320
uci1 10:3c93db1cfb12 321 void GetRates(float& thmrate, float& evtrate) {
uci1 10:3c93db1cfb12 322 thmrate = evtrate = 0;
uci1 10:3c93db1cfb12 323 const uint32_t dt = static_cast<uint32_t>(time(0)) - gLastCountReset;
uci1 10:3c93db1cfb12 324 if (dt>0) {
uci1 10:3c93db1cfb12 325 thmrate = gTrgNum[kThmTrg] / dt;
uci1 10:3c93db1cfb12 326 evtrate = (gEvtNum + gConf.GetFirstEvt()) / dt;
uci1 10:3c93db1cfb12 327 }
uci1 10:3c93db1cfb12 328 }
uci1 10:3c93db1cfb12 329
uci1 8:95a325df1f6b 330 bool IsSeqComplete() {
uci1 12:d472f9811262 331 #ifdef DEBUG
uci1 12:d472f9811262 332 printf("IsSeqComplete: eps=%u, cntpow=%d, fe=%u, pow=%u, evt=%u, seq=%hu\r\n",
uci1 10:3c93db1cfb12 333 gConf.GetEvtsPerFile(), (int)gConf.IsCountingPowerReadings(),
uci1 12:d472f9811262 334 gConf.GetFirstEvt(), gPowNum, gEvtNum, SnSDUtils::GetCurSeqNum());
uci1 12:d472f9811262 335 #endif
uci1 8:95a325df1f6b 336 if (gConf.GetEvtsPerFile()>0) {
uci1 12:d472f9811262 337 const uint32_t evtEndCurSeq = (SnSDUtils::GetCurSeqNum()+1) // account for seq=0
uci1 12:d472f9811262 338 * gConf.GetEvtsPerFile();
uci1 12:d472f9811262 339 #ifdef DEBUG
uci1 12:d472f9811262 340 printf("evtEndCurSeq=%u\r\n",evtEndCurSeq);
uci1 12:d472f9811262 341 #endif
uci1 8:95a325df1f6b 342 if (gConf.IsCountingPowerReadings()) {
uci1 12:d472f9811262 343 return (gPowNum>=evtEndCurSeq);
uci1 8:95a325df1f6b 344 } else {
uci1 12:d472f9811262 345 // first event num is a one-time per run offset, not one per sequence
uci1 12:d472f9811262 346 return (gEvtNum>=(gConf.GetFirstEvt()+evtEndCurSeq));
uci1 8:95a325df1f6b 347 }
uci1 12:d472f9811262 348 } else {
uci1 12:d472f9811262 349 return false;
uci1 8:95a325df1f6b 350 }
uci1 8:95a325df1f6b 351 }
uci1 1:e392595b4b76 352
uci1 8:95a325df1f6b 353 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 354 void stopTicker(rtos::RtosTimer* tik) {
uci1 8:95a325df1f6b 355 if (tik!=0) {
uci1 8:95a325df1f6b 356 tik->stop();
uci1 8:95a325df1f6b 357 }
uci1 8:95a325df1f6b 358 }
uci1 8:95a325df1f6b 359 #else
uci1 8:95a325df1f6b 360 void stopTicker(Ticker& tik) {
uci1 8:95a325df1f6b 361 tik.detach();
uci1 8:95a325df1f6b 362 }
uci1 8:95a325df1f6b 363 #endif
uci1 8:95a325df1f6b 364
uci1 8:95a325df1f6b 365 #ifdef USE_RTOS_TIMER
uci1 18:55f1581f2ee4 366 float resetTicker(rtos::RtosTimer* tik, const float timSec,
uci1 18:55f1581f2ee4 367 const float maxTimSec) {
uci1 8:95a325df1f6b 368 if (tik!=0) {
uci1 8:95a325df1f6b 369 tik->stop();
uci1 8:95a325df1f6b 370 if (timSec>0) {
uci1 18:55f1581f2ee4 371 float tp = timSec > maxTimSec ? maxTimSec : timSec;
uci1 8:95a325df1f6b 372 tp *= 1000u; // ms
uci1 16:744ce85aede2 373 /*
uci1 16:744ce85aede2 374 if (tik==gForceTicker) {
uci1 16:744ce85aede2 375 tik->start((1./10.)*1e3);
uci1 16:744ce85aede2 376 return ((1./10.)*1e3);
uci1 16:744ce85aede2 377 } else
uci1 16:744ce85aede2 378 */
uci1 8:95a325df1f6b 379 tik->start(tp);
uci1 8:95a325df1f6b 380 return tp;
uci1 8:95a325df1f6b 381 }
uci1 8:95a325df1f6b 382 }
uci1 8:95a325df1f6b 383 return 0;
uci1 8:95a325df1f6b 384 }
uci1 8:95a325df1f6b 385 #else
uci1 18:55f1581f2ee4 386 float resetTicker(Ticker& tik, const float timSec,
uci1 18:55f1581f2ee4 387 const float maxTimSec, void (*fptr)(void)) {
uci1 8:95a325df1f6b 388 tik.detach();
uci1 8:95a325df1f6b 389 if (timSec>0) {
uci1 18:55f1581f2ee4 390 const float tp = timSec > maxTimSec ? maxTimSec : timSec;
uci1 8:95a325df1f6b 391 tik.attach(fptr, tp);
uci1 8:95a325df1f6b 392 return tp;
uci1 8:95a325df1f6b 393 }
uci1 8:95a325df1f6b 394 return 0;
uci1 8:95a325df1f6b 395 }
uci1 8:95a325df1f6b 396 #endif
uci1 8:95a325df1f6b 397
uci1 15:f2569d8e4176 398 void StopAllTickers() {
uci1 8:95a325df1f6b 399 stopTicker(gForceTicker);
uci1 8:95a325df1f6b 400 stopTicker(gHeartbeatTicker);
uci1 8:95a325df1f6b 401 stopTicker(gCommWinTicker);
uci1 8:95a325df1f6b 402 stopTicker(gPowerCheckTicker);
uci1 15:f2569d8e4176 403 }
uci1 15:f2569d8e4176 404
uci1 15:f2569d8e4176 405 void ResetAllTickers() {
uci1 15:f2569d8e4176 406 #ifdef USE_RTOS_TIMER
uci1 18:55f1581f2ee4 407 const float ftp = resetTicker(gForceTicker, gConf.GetForceTrigPeriod(),
uci1 18:55f1581f2ee4 408 kAbsMaxTimer);
uci1 18:55f1581f2ee4 409 const float hbp = resetTicker(gHeartbeatTicker, gConf.GetHeartbeatPeriod(),
uci1 18:55f1581f2ee4 410 kAbsMaxTimer);
uci1 18:55f1581f2ee4 411 const float cwp = resetTicker(gCommWinTicker, gConf.GetCommWinPeriod(),
uci1 18:55f1581f2ee4 412 kCommWinLongPrdTk);
uci1 18:55f1581f2ee4 413 const float pcp = resetTicker(gPowerCheckTicker, gConf.GetVoltCheckPeriod(),
uci1 18:55f1581f2ee4 414 kAbsMaxTimer);
uci1 15:f2569d8e4176 415 #else
uci1 18:55f1581f2ee4 416 const float ftp = resetTicker(gForceTicker, gConf.GetForceTrigPeriod(),
uci1 18:55f1581f2ee4 417 kAbsMaxTimer, &procForceTrigger);
uci1 18:55f1581f2ee4 418 const float hbp = resetTicker(gHeartbeatTicker, gConf.GetHeartbeatPeriod(),
uci1 18:55f1581f2ee4 419 kAbsMaxTimer, &procHeartbeat);
uci1 18:55f1581f2ee4 420 const float cwp = resetTicker(gCommWinTicker, gConf.GetCommWinPeriod(),
uci1 18:55f1581f2ee4 421 kCommWinLongPrdTk, &procCommWin);
uci1 18:55f1581f2ee4 422 const float pcp = resetTicker(gPowerCheckTicker, gConf.GetVoltCheckPeriod(),
uci1 18:55f1581f2ee4 423 kAbsMaxTimer, &procPowerCheck);
uci1 15:f2569d8e4176 424 #endif
uci1 15:f2569d8e4176 425 #ifdef DEBUG
uci1 18:55f1581f2ee4 426 printf("attach force trig %g\r\n",ftp);
uci1 18:55f1581f2ee4 427 printf("attach heart beat %g\r\n",hbp);
uci1 18:55f1581f2ee4 428 printf("attach comm win %g\r\n",cwp);
uci1 18:55f1581f2ee4 429 printf("attach power chk %g\r\n",pcp);
uci1 15:f2569d8e4176 430 #endif
uci1 15:f2569d8e4176 431 }
uci1 15:f2569d8e4176 432
uci1 15:f2569d8e4176 433 void StopRunning() {
uci1 15:f2569d8e4176 434 #if defined(DEBUG) || defined(SSNOTIFY)
uci1 15:f2569d8e4176 435 printf("stop running\r\n");
uci1 15:f2569d8e4176 436 #endif
uci1 15:f2569d8e4176 437 StopAllTickers();
uci1 17:4687bf932b8c 438 OpenCommWin();
uci1 8:95a325df1f6b 439 while (true) {
uci1 8:95a325df1f6b 440 led3 = 1; led4=1;
uci1 8:95a325df1f6b 441 wait(0.5);
uci1 8:95a325df1f6b 442 led3 = 0; led4=0;
uci1 8:95a325df1f6b 443 wait(0.5);
uci1 8:95a325df1f6b 444 //Watchdog::kick(); - if we kick the watchdog, the station is unrecoverable without physical access
uci1 8:95a325df1f6b 445 }
uci1 8:95a325df1f6b 446 }
uci1 1:e392595b4b76 447
uci1 0:664899e0b988 448 int main() {
uci1 1:e392595b4b76 449 {
uci1 18:55f1581f2ee4 450 gCpu.baud(115200);
uci1 18:55f1581f2ee4 451 #if defined(SSNOTIFY) || defined(DEBUG)
uci1 15:f2569d8e4176 452 printf("main: start\r\n");
uci1 15:f2569d8e4176 453 #endif
uci1 2:e67f7c158087 454 led1=1; wait(0.2);
uci1 2:e67f7c158087 455 led1=0; led2=1; wait(0.2);
uci1 2:e67f7c158087 456 led2=0; led3=1; wait(0.2);
uci1 2:e67f7c158087 457 led3=0; led4=1; wait(0.2);
uci1 1:e392595b4b76 458 led4=0;
uci1 1:e392595b4b76 459 }
uci1 18:55f1581f2ee4 460
uci1 18:55f1581f2ee4 461 #ifdef DEBUG
uci1 18:55f1581f2ee4 462 printf("making comm objects\r\n");
uci1 18:55f1581f2ee4 463 #endif
uci1 16:744ce85aede2 464
uci1 8:95a325df1f6b 465 // RTOS stuff must be made inside main for some reason
uci1 18:55f1581f2ee4 466 /*
uci1 18:55f1581f2ee4 467 #ifdef USE_ETH_INTERFACE
uci1 18:55f1581f2ee4 468 gComms[0] = new SnCommAfarTCP(gConf);
uci1 18:55f1581f2ee4 469 #else
uci1 18:55f1581f2ee4 470 gComms[0] = new SnCommAfarNetIf(gConf);
uci1 18:55f1581f2ee4 471 #endif
uci1 18:55f1581f2ee4 472 */
uci1 16:744ce85aede2 473 //gComms[0] = new SnCommSBD(&gSBDport, &gCpu);
uci1 16:744ce85aede2 474 gComms[0] = new SnCommUsb(&gCpu);
uci1 18:55f1581f2ee4 475
uci1 18:55f1581f2ee4 476 #ifdef DEBUG
uci1 18:55f1581f2ee4 477 printf("make comm objects\r\n");
uci1 18:55f1581f2ee4 478 #endif
uci1 13:7a1fb885a8e4 479
uci1 8:95a325df1f6b 480 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 481 gForceTicker = new rtos::RtosTimer(&procForceTrigger);
uci1 8:95a325df1f6b 482 gHeartbeatTicker = new rtos::RtosTimer(&procHeartbeat);
uci1 8:95a325df1f6b 483 gCommWinTicker = new rtos::RtosTimer(&procCommWin);
uci1 8:95a325df1f6b 484 gPowerCheckTicker = new rtos::RtosTimer(&procPowerCheck);
uci1 8:95a325df1f6b 485 #endif
uci1 8:95a325df1f6b 486
uci1 0:664899e0b988 487 led2=1;
uci1 0:664899e0b988 488 //wait_ms(100);
uci1 1:e392595b4b76 489
uci1 12:d472f9811262 490 #ifdef DEBUG
uci1 3:24c5f0f50bf1 491 printf("\n\n\n\n\n\nstarting\r\n");
uci1 12:d472f9811262 492 #endif
uci1 1:e392595b4b76 493
uci1 0:664899e0b988 494 // a failsafe
uci1 0:664899e0b988 495 Watchdog::kick(kWDFailsafe);
uci1 0:664899e0b988 496
uci1 1:e392595b4b76 497 // set the clock to the BS time, if it's not set
uci1 1:e392595b4b76 498 if ( (static_cast<int32_t>(time(0)))<0 ) {
uci1 1:e392595b4b76 499 set_time(kBStime);
uci1 1:e392595b4b76 500 }
uci1 12:d472f9811262 501 #ifdef DEBUG
uci1 1:e392595b4b76 502 printf("time = %d\r\n",(int32_t)time(0));
uci1 12:d472f9811262 503 #endif
uci1 1:e392595b4b76 504 gLastCommWin = time(0); // prevent comm win proc
uci1 0:664899e0b988 505
uci1 8:95a325df1f6b 506 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 507 gForceTicker->stop();
uci1 8:95a325df1f6b 508 #else
uci1 0:664899e0b988 509 gForceTicker.detach();
uci1 8:95a325df1f6b 510 #endif
uci1 0:664899e0b988 511 gFirstEvt = true;
uci1 0:664899e0b988 512
uci1 4:a91682e19d6b 513 // (probably) power down comms and power up cards,amps
uci1 4:a91682e19d6b 514 SetPower(false);
uci1 4:a91682e19d6b 515
uci1 0:664899e0b988 516 //
uci1 0:664899e0b988 517 // get config
uci1 0:664899e0b988 518 //
uci1 12:d472f9811262 519 #ifdef DEBUG
uci1 8:95a325df1f6b 520 printf("call OpenCommWin\r\n");
uci1 12:d472f9811262 521 #endif
uci1 13:7a1fb885a8e4 522 OpenCommWin(true); // alwasy configure, even if no new config
uci1 3:24c5f0f50bf1 523
uci1 0:664899e0b988 524 // get ready to trigger
uci1 0:664899e0b988 525 PIN_spi.format( 16, 1 ); // change to data readout format
uci1 15:f2569d8e4176 526 PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
uci1 0:664899e0b988 527
uci1 0:664899e0b988 528 led2=0;
uci1 0:664899e0b988 529
uci1 0:664899e0b988 530 // the main event loop. wait for triggers in SendClock
uci1 12:d472f9811262 531 gTrgTimer.start();
uci1 12:d472f9811262 532 register int32_t etms=0; // time between written events
uci1 0:664899e0b988 533 while( true )
uci1 0:664899e0b988 534 {
uci1 0:664899e0b988 535 // in here, we wait for triggers from the MB-FPGA
uci1 0:664899e0b988 536 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 537
uci1 1:e392595b4b76 538 led1 = !led1;
uci1 1:e392595b4b76 539
uci1 12:d472f9811262 540 #ifdef DEBUG
uci1 1:e392595b4b76 541 printf("calling wait trig\r\n");
uci1 1:e392595b4b76 542 printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
uci1 5:9cea89700c66 543 printf("readingout=%d\r\n",(int)gReadingOut);
uci1 12:d472f9811262 544 #endif
uci1 1:e392595b4b76 545
uci1 0:664899e0b988 546 PIN_lockRegisters = 0; // allow data to come from DFPGA
uci1 0:664899e0b988 547 WaitTrigAndSendClock();
uci1 0:664899e0b988 548 PIN_lockRegisters = 1; // block registers during readout
uci1 1:e392595b4b76 549
uci1 12:d472f9811262 550 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 551 Timer prof;
uci1 12:d472f9811262 552 prof.start();
uci1 12:d472f9811262 553 int befReadWv=0, aftReadWv=0, befSaveEvt=0, aftSaveEvt=0,
uci1 12:d472f9811262 554 befChkPow=0, aftChkPow=0, befNewSeq=0, aftNewSeq=0, endOfLoop=0;
uci1 12:d472f9811262 555 #endif
uci1 12:d472f9811262 556
uci1 1:e392595b4b76 557 if (gReadingOut) {
uci1 12:d472f9811262 558
uci1 12:d472f9811262 559 const int32_t ttms = gTrgTimer.read_ms(); // time since last trigger
uci1 12:d472f9811262 560 gTrgTimer.reset(); gTrgTimer.start(); // restart trigger timer
uci1 12:d472f9811262 561 etms += ttms;
uci1 8:95a325df1f6b 562
uci1 8:95a325df1f6b 563 Watchdog::kick(); // don't reset!
uci1 15:f2569d8e4176 564
uci1 1:e392595b4b76 565 //
uci1 1:e392595b4b76 566 // got trigger. read registers to mbed and build the event
uci1 1:e392595b4b76 567 //
uci1 1:e392595b4b76 568
uci1 1:e392595b4b76 569 led4=1;
uci1 1:e392595b4b76 570
uci1 1:e392595b4b76 571 // read data & calc CRC
uci1 12:d472f9811262 572 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 573 prof.stop(); befReadWv=prof.read_us(); prof.start();
uci1 12:d472f9811262 574 #endif
uci1 12:d472f9811262 575
uci1 1:e392595b4b76 576 gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit);
uci1 15:f2569d8e4176 577
uci1 12:d472f9811262 578 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 579 prof.stop(); aftReadWv=prof.read_us(); prof.start();
uci1 12:d472f9811262 580 #endif
uci1 12:d472f9811262 581
uci1 1:e392595b4b76 582 gEvent.SetCurMbedTime();
uci1 1:e392595b4b76 583 // TODO: no way to check for external trigger?
uci1 1:e392595b4b76 584 if (gEvent.IsForcedTrg()==false) {
uci1 1:e392595b4b76 585 gEvent.SetTrgBit(kThmTrg);
uci1 1:e392595b4b76 586 gEvent.SetTrgNum((gTrgNum[kThmTrg])++);
uci1 1:e392595b4b76 587 } // else already set by procForceTrigger
uci1 1:e392595b4b76 588 // (no need to calc if we throw this event away)
uci1 1:e392595b4b76 589
uci1 1:e392595b4b76 590 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 591
uci1 12:d472f9811262 592 #ifdef DEBUG
uci1 1:e392595b4b76 593 printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
uci1 12:d472f9811262 594 #endif
uci1 1:e392595b4b76 595
uci1 1:e392595b4b76 596 if ( gEvent.IsForcedTrg() || gFirstEvt ||
uci1 1:e392595b4b76 597 (etms>gConf.GetEvtThrtlPeriodMs()) ) {
uci1 1:e392595b4b76 598
uci1 1:e392595b4b76 599 led2=1;
uci1 1:e392595b4b76 600
uci1 1:e392595b4b76 601 PIN_lockRegisters = 0; // done reading, unlock so we can talk to SD card.
uci1 1:e392595b4b76 602
uci1 12:d472f9811262 603 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 604 prof.stop(); befSaveEvt=prof.read_us(); prof.start();
uci1 12:d472f9811262 605 #endif
uci1 12:d472f9811262 606
uci1 1:e392595b4b76 607 SaveEvent(etms);
uci1 12:d472f9811262 608 etms=0;
uci1 8:95a325df1f6b 609
uci1 12:d472f9811262 610 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 611 prof.stop(); aftSaveEvt=prof.read_us(); prof.start();
uci1 12:d472f9811262 612 #endif
uci1 1:e392595b4b76 613 }
uci1 1:e392595b4b76 614 }
uci1 12:d472f9811262 615 #ifdef DEBUG
uci1 1:e392595b4b76 616 printf("past reading out\r\n");
uci1 12:d472f9811262 617 #endif
uci1 1:e392595b4b76 618
uci1 1:e392595b4b76 619 led4=0; led2=0;
uci1 12:d472f9811262 620
uci1 12:d472f9811262 621 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 622 prof.stop(); befChkPow=prof.read_us(); prof.start();
uci1 12:d472f9811262 623 #endif
uci1 8:95a325df1f6b 624 // check the power?
uci1 8:95a325df1f6b 625 if (gCheckPower) {
uci1 12:d472f9811262 626 #ifdef DEBUG
uci1 8:95a325df1f6b 627 printf("call check power\r\n");
uci1 12:d472f9811262 628 #endif
uci1 8:95a325df1f6b 629 CheckPower(false);
uci1 8:95a325df1f6b 630 }
uci1 12:d472f9811262 631 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 632 prof.stop(); aftChkPow=prof.read_us(); prof.start();
uci1 12:d472f9811262 633 #endif
uci1 8:95a325df1f6b 634
uci1 12:d472f9811262 635 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 636 prof.stop(); befNewSeq=prof.read_us(); prof.start();
uci1 12:d472f9811262 637 #endif
uci1 8:95a325df1f6b 638 // make new seq?
uci1 8:95a325df1f6b 639 if (IsSeqComplete()) {
uci1 12:d472f9811262 640 #ifdef DEBUG
uci1 10:3c93db1cfb12 641 printf("seq complete. sngseq=%d\r\n",gConf.IsSingleSeqRunMode());
uci1 12:d472f9811262 642 #endif
uci1 8:95a325df1f6b 643 MakeOutputFile(gConf.IsSingleSeqRunMode());
uci1 8:95a325df1f6b 644 }
uci1 12:d472f9811262 645 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 646 prof.stop(); aftNewSeq=prof.read_us(); prof.start();
uci1 12:d472f9811262 647 #endif
uci1 12:d472f9811262 648
uci1 8:95a325df1f6b 649 // open comm win?
uci1 0:664899e0b988 650 if (gOpenCommWin) {
uci1 12:d472f9811262 651 #ifdef DEBUG
uci1 1:e392595b4b76 652 printf("gOpenComWin=%s, opening\r\n",gOpenCommWin?"true":"false");
uci1 12:d472f9811262 653 #endif
uci1 0:664899e0b988 654 OpenCommWin();
uci1 0:664899e0b988 655 gOpenCommWin=false;
uci1 1:e392595b4b76 656 } else {
uci1 12:d472f9811262 657 #ifdef DEBUG
uci1 1:e392595b4b76 658 printf("gOpenCommWin=false\r\n");
uci1 12:d472f9811262 659 #endif
uci1 0:664899e0b988 660 }
uci1 12:d472f9811262 661
uci1 12:d472f9811262 662 #ifdef EVT_TIME_PROFILE
uci1 12:d472f9811262 663 prof.stop(); endOfLoop=prof.read_us(); prof.start();
uci1 12:d472f9811262 664 printf("befReadWv=%d, aftReadWv=%d, befSaveEvt=%d, aftSaveEvt=%d, "
uci1 12:d472f9811262 665 "befChkPow=%d, aftChkPow=%d, befNewSeq=%d, aftNewSeq=%d, endOfLoop=%d\r\n",
uci1 12:d472f9811262 666 befReadWv, aftReadWv, befSaveEvt, aftSaveEvt,
uci1 12:d472f9811262 667 befChkPow, aftChkPow, befNewSeq, aftNewSeq, endOfLoop);
uci1 12:d472f9811262 668 #endif
uci1 15:f2569d8e4176 669
uci1 15:f2569d8e4176 670 // get ready to trigger
uci1 15:f2569d8e4176 671 PIN_spi.format( 16, 1 ); // change to data readout format
uci1 15:f2569d8e4176 672 PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
uci1 0:664899e0b988 673 }
uci1 0:664899e0b988 674
uci1 0:664899e0b988 675 }
uci1 0:664899e0b988 676
uci1 0:664899e0b988 677 //
uci1 0:664899e0b988 678 // save the event
uci1 0:664899e0b988 679 //
uci1 0:664899e0b988 680 void SaveEvent(const int32_t etms) {
uci1 0:664899e0b988 681 // write the event
uci1 12:d472f9811262 682
uci1 12:d472f9811262 683 #ifdef DEBUG
uci1 3:24c5f0f50bf1 684 printf("save event\r\n");
uci1 12:d472f9811262 685 #endif
uci1 3:24c5f0f50bf1 686
uci1 0:664899e0b988 687 // set the event number & dt
uci1 3:24c5f0f50bf1 688 gEvent.SetEvtNum(gEvtNum);
uci1 0:664899e0b988 689 gEvent.SetDTms(etms);
uci1 0:664899e0b988 690
uci1 0:664899e0b988 691 // save to SD
uci1 11:de443350ec4a 692 PIN_lockRegisters = 0; // unlock so we can talk to SD card.
uci1 1:e392595b4b76 693 SnSDUtils::WriteEventTo(SnSDUtils::GetCurFile(), gGenBuf, gEvent, gConf);
uci1 0:664899e0b988 694
uci1 0:664899e0b988 695 // reset
uci1 0:664899e0b988 696 gEvent.ClearEvent();
uci1 0:664899e0b988 697
uci1 3:24c5f0f50bf1 698 // increment event number
uci1 3:24c5f0f50bf1 699 ++gEvtNum;
uci1 3:24c5f0f50bf1 700
uci1 12:d472f9811262 701 #ifdef DEBUG
uci1 8:95a325df1f6b 702 printf("gEvtNum=%u\r\n",gEvtNum);
uci1 12:d472f9811262 703 #endif
uci1 3:24c5f0f50bf1 704 }
uci1 3:24c5f0f50bf1 705
uci1 3:24c5f0f50bf1 706 void MakeOutputFile(const bool stopRunning) {
uci1 10:3c93db1cfb12 707 PIN_lockRegisters = 0; // unlock so we can talk to SD card.
uci1 12:d472f9811262 708 #ifdef DEBUG
uci1 10:3c93db1cfb12 709 printf("closing output file. gEvtNum=%u, gPowNum=%u, stop=%d\r\n",
uci1 10:3c93db1cfb12 710 gEvtNum,gPowNum,(int)stopRunning);
uci1 12:d472f9811262 711 #endif
uci1 13:7a1fb885a8e4 712
uci1 3:24c5f0f50bf1 713 SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
uci1 13:7a1fb885a8e4 714
uci1 12:d472f9811262 715 #ifdef DEBUG
uci1 10:3c93db1cfb12 716 printf("file closed\r\n");
uci1 12:d472f9811262 717 #endif
uci1 3:24c5f0f50bf1 718 if (stopRunning) {
uci1 8:95a325df1f6b 719 StopRunning();
uci1 0:664899e0b988 720 }
uci1 8:95a325df1f6b 721 FILE* cf = SnSDUtils::OpenNewOutputFile(gConf.GetMacAddress(),
uci1 8:95a325df1f6b 722 gConf.GetRun());
uci1 13:7a1fb885a8e4 723 // reset event, timers, trigger counters
uci1 13:7a1fb885a8e4 724 ResetCountersClearEvt();
uci1 8:95a325df1f6b 725 if (cf!=0) {
uci1 8:95a325df1f6b 726 wait_ms(200);
uci1 8:95a325df1f6b 727 GetAvePowerReading();
uci1 12:d472f9811262 728 #ifdef DEBUG
uci1 8:95a325df1f6b 729 printf("writing power. v1=%g, v2=%g, r1=%g, r2=%g, t=%u, pownum=%u\r\n",
uci1 8:95a325df1f6b 730 gPower.GetAveV1(), gPower.GetAveV2(),
uci1 8:95a325df1f6b 731 gPower.GetRmsV1(), gPower.GetRmsV2(), gPower.GetTime(),
uci1 8:95a325df1f6b 732 gPowNum);
uci1 12:d472f9811262 733 #endif
uci1 8:95a325df1f6b 734 SnSDUtils::WritePowerTo(cf, gPower, gPowNum);
uci1 8:95a325df1f6b 735 }
uci1 12:d472f9811262 736 #ifdef DEBUG
uci1 3:24c5f0f50bf1 737 printf("made output file with run %u\r\n",gConf.GetRun());
uci1 3:24c5f0f50bf1 738 printf("filename=%s\r\n",SnSDUtils::GetCurFileName());
uci1 12:d472f9811262 739 #endif
uci1 3:24c5f0f50bf1 740 SnSDUtils::WriteConfig(SnSDUtils::GetCurFile(), gConf);
uci1 0:664899e0b988 741 }
uci1 0:664899e0b988 742
uci1 0:664899e0b988 743 //
uci1 4:a91682e19d6b 744 // power stuff
uci1 4:a91682e19d6b 745 //
uci1 4:a91682e19d6b 746 void SetPower(const bool isCommWin) {
uci1 8:95a325df1f6b 747 // TODO: turn on amps individually, when that's possible
uci1 4:a91682e19d6b 748 if (isCommWin) {
uci1 5:9cea89700c66 749 PIN_turn_on_system = gConf.GetPowPinSetting(SnConfigFrame::kCardComWin);
uci1 4:a91682e19d6b 750 wait_ms(10);
uci1 5:9cea89700c66 751 PIN_turn_on_amps = gConf.GetPowPinSetting(SnConfigFrame::kAmpsComWin);
uci1 4:a91682e19d6b 752 wait_ms(10);
uci1 5:9cea89700c66 753 PIN_iridSbd_power = gConf.GetPowPinSetting(SnConfigFrame::kIridComWin);
uci1 4:a91682e19d6b 754 wait_ms(10);
uci1 5:9cea89700c66 755 PIN_afar_power = gConf.GetPowPinSetting(SnConfigFrame::kAfarComWin);
uci1 4:a91682e19d6b 756 wait_ms(10);
uci1 4:a91682e19d6b 757 } else {
uci1 5:9cea89700c66 758 PIN_turn_on_system = gConf.GetPowPinSetting(SnConfigFrame::kCardDatTak);
uci1 4:a91682e19d6b 759 wait_ms(10);
uci1 5:9cea89700c66 760 PIN_turn_on_amps = gConf.GetPowPinSetting(SnConfigFrame::kAmpsDatTak);
uci1 4:a91682e19d6b 761 wait_ms(10);
uci1 5:9cea89700c66 762 PIN_iridSbd_power = gConf.GetPowPinSetting(SnConfigFrame::kIridDatTak);
uci1 4:a91682e19d6b 763 wait_ms(10);
uci1 5:9cea89700c66 764 PIN_afar_power = gConf.GetPowPinSetting(SnConfigFrame::kAfarDatTak);
uci1 4:a91682e19d6b 765 wait_ms(10);
uci1 4:a91682e19d6b 766 }
uci1 16:744ce85aede2 767 wait(1.5); // let things power up
uci1 12:d472f9811262 768 #ifdef DEBUG
uci1 16:744ce85aede2 769 printf("power word (%hhu): ",gConf.GetPowerMode()); SnBitUtils::printBits(gConf.GetPowerMode(),true);
uci1 6:6f002d202f59 770 printf("set power (iscom %d, pw %hhu): cards %d, amps %d, irid %d, afar %d\r\n",
uci1 6:6f002d202f59 771 isCommWin, gConf.GetPowerMode(), PIN_turn_on_system.read(), PIN_turn_on_amps.read(),
uci1 6:6f002d202f59 772 PIN_iridSbd_power.read(), PIN_afar_power.read());
uci1 12:d472f9811262 773 #endif
uci1 4:a91682e19d6b 774 }
uci1 4:a91682e19d6b 775
uci1 4:a91682e19d6b 776 //
uci1 0:664899e0b988 777 // set configuration
uci1 0:664899e0b988 778 //
uci1 1:e392595b4b76 779 void SetConfigAndMakeOutputFile() {
uci1 12:d472f9811262 780 #ifdef DEBUG
uci1 1:e392595b4b76 781 printf("SetConfigAndMakeOutputFile\r\n");
uci1 12:d472f9811262 782 #endif
uci1 1:e392595b4b76 783
uci1 0:664899e0b988 784 // restart watchdog
uci1 0:664899e0b988 785 Watchdog::kick(gConf.GetWatchdogPeriod());
uci1 0:664899e0b988 786
uci1 1:e392595b4b76 787 // block (thermal) triggers during configuration
uci1 1:e392595b4b76 788 PIN_enableThermTrig = 0;
uci1 1:e392595b4b76 789 PIN_ADC_CS = 1;
uci1 1:e392595b4b76 790 PIN_DoNotRestartAllClocks = 1;
uci1 1:e392595b4b76 791 PIN_forceTrigger = 0;
uci1 3:24c5f0f50bf1 792 PIN_heartbeat = 0;
uci1 1:e392595b4b76 793 wait_ms(20);
uci1 1:e392595b4b76 794
uci1 8:95a325df1f6b 795 if (AreCardsPowered()) {
uci1 8:95a325df1f6b 796 // Set PLA value(s)
uci1 8:95a325df1f6b 797 PIN_spi.format( 16, 0 ); // change mode for DAC & PLA value setting
uci1 8:95a325df1f6b 798 PIN_spi.frequency(1000000);
uci1 8:95a325df1f6b 799 PIN_MajLogHiBit=1;
uci1 8:95a325df1f6b 800 PIN_MajLogLoBit=1;
uci1 8:95a325df1f6b 801 PIN_enableThermTrig=0;
uci1 0:664899e0b988 802
uci1 8:95a325df1f6b 803 uint16_t hi, lo;
uci1 8:95a325df1f6b 804 PIN_PLA_cs=1;
uci1 8:95a325df1f6b 805 wait(4);
uci1 8:95a325df1f6b 806 for (uint8_t pi=0; pi<kNplas; pi++) {
uci1 8:95a325df1f6b 807 if (pi < gConf.GetNumPlas()) {
uci1 8:95a325df1f6b 808 SnConfigFrame::GetHiLoPlas(gConf.GetPla(pi), hi, lo);
uci1 8:95a325df1f6b 809 PIN_spi.write(hi);
uci1 8:95a325df1f6b 810 PIN_spi.write(lo);
uci1 12:d472f9811262 811 #ifdef DEBUG
uci1 8:95a325df1f6b 812 printf("pla hi %hu, lo %hu\r\n",hi,lo);
uci1 12:d472f9811262 813 #endif
uci1 8:95a325df1f6b 814 } else {
uci1 8:95a325df1f6b 815 PIN_spi.write(kNoTrigPla); // hi
uci1 8:95a325df1f6b 816 PIN_spi.write(kNoTrigPla); // lo
uci1 12:d472f9811262 817 #ifdef DEBUG
uci1 8:95a325df1f6b 818 printf("pla hi %hu, lo %hu\r\n",kNoTrigPla,kNoTrigPla);
uci1 12:d472f9811262 819 #endif
uci1 8:95a325df1f6b 820 }
uci1 8:95a325df1f6b 821 Watchdog::kick();
uci1 0:664899e0b988 822 }
uci1 8:95a325df1f6b 823 wait(3);
uci1 8:95a325df1f6b 824 PIN_PLA_cs=0;
uci1 8:95a325df1f6b 825 wait(3);
uci1 0:664899e0b988 826
uci1 8:95a325df1f6b 827 // DAC values
uci1 8:95a325df1f6b 828 //
uci1 8:95a325df1f6b 829 // first 12 bits = DAC value
uci1 8:95a325df1f6b 830 // next 2 bits = DAC ID
uci1 8:95a325df1f6b 831 // last 2 bits = dFPGA ID
uci1 8:95a325df1f6b 832 //
uci1 8:95a325df1f6b 833 // But FPGA uses "gray encoding" which means only 1 bit
uci1 8:95a325df1f6b 834 // can change at a time (of the last 4 bits). So even tho
uci1 8:95a325df1f6b 835 // the card/dac# is encoded, the order is also important
uci1 8:95a325df1f6b 836 // 0000 (dac0,card0), 0001 (dac0,card1), 0011 (dac0,card3), 0010 (dac0,card2),
uci1 8:95a325df1f6b 837 // 0110 (dac1,card2), 0111 (dac1,card3), 0101 (dac1,card1), etc.
uci1 12:d472f9811262 838 #ifdef DEBUG
uci1 8:95a325df1f6b 839 printf("setting dacs\r\n");
uci1 12:d472f9811262 840 #endif
uci1 8:95a325df1f6b 841 uint16_t dv=0;
uci1 8:95a325df1f6b 842 for (uint8_t i=0, gri=0; i<kTotDacs; i++) {
uci1 8:95a325df1f6b 843 // get the gray-codes for this iteration
uci1 8:95a325df1f6b 844 gri = SnBitUtils::binToGray(i);
uci1 8:95a325df1f6b 845
uci1 8:95a325df1f6b 846 // build bit word
uci1 8:95a325df1f6b 847 dv = static_cast<int>(gConf.GetDac(gri & 0x0003u, gri >> 2u));
uci1 8:95a325df1f6b 848 dv <<= 4u;
uci1 8:95a325df1f6b 849 dv |= gri;
uci1 8:95a325df1f6b 850
uci1 12:d472f9811262 851 #ifdef DEBUG
uci1 8:95a325df1f6b 852 printf("dac %04x\r\n",dv);
uci1 12:d472f9811262 853 #endif
uci1 8:95a325df1f6b 854
uci1 8:95a325df1f6b 855 // send to FPGA
uci1 8:95a325df1f6b 856 PIN_start_fpga=1;
uci1 8:95a325df1f6b 857 PIN_spi.write(dv);
uci1 8:95a325df1f6b 858 PIN_start_fpga=0;
uci1 8:95a325df1f6b 859
uci1 8:95a325df1f6b 860 Watchdog::kick();
uci1 8:95a325df1f6b 861
uci1 8:95a325df1f6b 862 }
uci1 12:d472f9811262 863 #ifdef DEBUG
uci1 8:95a325df1f6b 864 printf("dacs set\r\n");
uci1 12:d472f9811262 865 #endif
uci1 8:95a325df1f6b 866 wait_ms(20);
uci1 8:95a325df1f6b 867 } else {
uci1 12:d472f9811262 868 #ifdef DEBUG
uci1 8:95a325df1f6b 869 printf("cards off. skipping PLA and DAC setting\r\n");
uci1 12:d472f9811262 870 #endif
uci1 0:664899e0b988 871 }
uci1 0:664899e0b988 872
uci1 0:664899e0b988 873 // Majority Logic Trigger selection (# of cards)
uci1 0:664899e0b988 874 SnBitUtils::SetChanNumBits(gConf.GetNumCardsMajLog() - 1u,
uci1 0:664899e0b988 875 PIN_MajLogHiBit, PIN_MajLogLoBit);
uci1 0:664899e0b988 876
uci1 0:664899e0b988 877 // Enable thermal trigger?
uci1 0:664899e0b988 878 PIN_enableThermTrig = gConf.IsThermTrigEnabled();
uci1 0:664899e0b988 879
uci1 0:664899e0b988 880 PIN_spi.format( 16, 1 ); // back to trigger mode
uci1 1:e392595b4b76 881 PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
uci1 1:e392595b4b76 882
uci1 8:95a325df1f6b 883 // make new output file
uci1 8:95a325df1f6b 884 // put after PLA/DAC, in case they affect the power readings
uci1 8:95a325df1f6b 885 wait_ms(200);
uci1 8:95a325df1f6b 886 MakeOutputFile();
uci1 8:95a325df1f6b 887
uci1 15:f2569d8e4176 888 // reset tickers
uci1 15:f2569d8e4176 889 ResetAllTickers();
uci1 8:95a325df1f6b 890
uci1 8:95a325df1f6b 891 // TODO: change comm parameters
uci1 8:95a325df1f6b 892 /*
uci1 8:95a325df1f6b 893 printf("set comm params\r\n");
uci1 8:95a325df1f6b 894 for (uint8_t cc=0; cc<kNcomms; cc++) {
uci1 8:95a325df1f6b 895 if (gComms[cc]!=0) {
uci1 8:95a325df1f6b 896 gComms[cc]->Set(gConf);
uci1 8:95a325df1f6b 897 }
uci1 3:24c5f0f50bf1 898 }
uci1 8:95a325df1f6b 899 */
uci1 0:664899e0b988 900
uci1 0:664899e0b988 901 Watchdog::kick(); // don't reset!
uci1 8:95a325df1f6b 902
uci1 12:d472f9811262 903 #ifdef DEBUG
uci1 8:95a325df1f6b 904 printf("set config done\r\n");
uci1 12:d472f9811262 905 #endif
uci1 0:664899e0b988 906 }
uci1 0:664899e0b988 907
uci1 0:664899e0b988 908 //
uci1 0:664899e0b988 909 // readout functions
uci1 0:664899e0b988 910 //
uci1 0:664899e0b988 911 void WaitTrigAndSendClock() {
uci1 1:e392595b4b76 912
uci1 12:d472f9811262 913 #ifdef DEBUG
uci1 1:e392595b4b76 914 printf("WaitTrigAndSendClock\r\n");
uci1 6:6f002d202f59 915 printf("wait trig: (pw %hhu): cards %d, amps %d, irid %d, afar %d\r\n",
uci1 6:6f002d202f59 916 gConf.GetPowerMode(), PIN_turn_on_system.read(), PIN_turn_on_amps.read(),
uci1 6:6f002d202f59 917 PIN_iridSbd_power.read(), PIN_afar_power.read());
uci1 8:95a325df1f6b 918 printf("cards powered=%d\r\n",(int)AreCardsPowered());
uci1 12:d472f9811262 919 #endif
uci1 0:664899e0b988 920
uci1 15:f2569d8e4176 921 PIN_spi.format( 16, 1 ); // back to trigger mode
uci1 15:f2569d8e4176 922 PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
uci1 15:f2569d8e4176 923
uci1 8:95a325df1f6b 924 if (AreCardsPowered()) {
uci1 8:95a325df1f6b 925
uci1 8:95a325df1f6b 926 if (gFirstEvt==false) {
uci1 8:95a325df1f6b 927 PIN_DoNotRestartAllClocks = 0;
uci1 8:95a325df1f6b 928 wait_us(1);
uci1 8:95a325df1f6b 929 PIN_DoNotRestartAllClocks = 1;
uci1 8:95a325df1f6b 930 //led3 = !led3; // toggle send clock led
uci1 8:95a325df1f6b 931 } else {
uci1 8:95a325df1f6b 932 gFirstEvt = false;
uci1 8:95a325df1f6b 933 }
uci1 8:95a325df1f6b 934
uci1 8:95a325df1f6b 935 //
uci1 8:95a325df1f6b 936 // wait for a trigger here.
uci1 8:95a325df1f6b 937 //
uci1 12:d472f9811262 938 #ifdef DEBUG
uci1 8:95a325df1f6b 939 printf("starting wait for trig\r\n");
uci1 12:d472f9811262 940 #endif
uci1 16:744ce85aede2 941
uci1 8:95a325df1f6b 942 gReadingOut = false; // this will allow forced triggers (see procForceTrigger())
uci1 8:95a325df1f6b 943 while ( PIN_a_sf_clk == 1 ) {
uci1 8:95a325df1f6b 944 if (gOpenCommWin || gCheckPower) {
uci1 12:d472f9811262 945 #ifdef DEBUG
uci1 8:95a325df1f6b 946 printf("break com=%d, pow=%d\r\n",gOpenCommWin,gCheckPower);
uci1 12:d472f9811262 947 #endif
uci1 8:95a325df1f6b 948 return; // break out to open comms or check power
uci1 8:95a325df1f6b 949 }
uci1 0:664899e0b988 950 }
uci1 8:95a325df1f6b 951 PIN_forceTrigger=0; // necessary for forced triggers, harmless for other triggers
uci1 8:95a325df1f6b 952 gReadingOut = true; // disallow new forced triggers
uci1 15:f2569d8e4176 953
uci1 15:f2569d8e4176 954 // we can't be interrupted before data arrives at the MB FPGA
uci1 15:f2569d8e4176 955 //StopAllTickers();
uci1 15:f2569d8e4176 956 /*
uci1 15:f2569d8e4176 957 procForceTrigger();
uci1 15:f2569d8e4176 958 procHeartbeat();
uci1 15:f2569d8e4176 959 procPowerCheck();
uci1 15:f2569d8e4176 960 procCommWin();
uci1 15:f2569d8e4176 961 */
uci1 16:744ce85aede2 962
uci1 16:744ce85aede2 963 //wait_us(6);
uci1 16:744ce85aede2 964
uci1 8:95a325df1f6b 965 //
uci1 8:95a325df1f6b 966 // collect data from daughter cards
uci1 8:95a325df1f6b 967 //
uci1 8:95a325df1f6b 968 // TODO: what if some card (set of channels) doesn't respond?
uci1 8:95a325df1f6b 969 // currently, will wait forever?
uci1 8:95a325df1f6b 970 // also, if ch1 is dead, will wait forever (due to FPGA code)
uci1 16:744ce85aede2 971 gAdcToMBtimer.start();
uci1 16:744ce85aede2 972 for( uint8_t i = 0; i < 128; ++i ) {
uci1 16:744ce85aede2 973 while (PIN_a_sf_clk==1) {}
uci1 16:744ce85aede2 974 while (PIN_a_sf_clk==0) {}
uci1 16:744ce85aede2 975 /*
uci1 16:744ce85aede2 976 if ((i == 10)&&(gEvtNum % 20)) {
uci1 16:744ce85aede2 977 wait_us(8);
uci1 16:744ce85aede2 978 }
uci1 16:744ce85aede2 979 */
uci1 16:744ce85aede2 980 PIN_ADC_CS = 0;
uci1 16:744ce85aede2 981 PIN_spi.write( 0x00 );
uci1 16:744ce85aede2 982 PIN_ADC_CS = 1;
uci1 16:744ce85aede2 983 /*
uci1 8:95a325df1f6b 984 if( PIN_a_sf_clk == 1 ) {
uci1 8:95a325df1f6b 985 if( i == 0 )
uci1 8:95a325df1f6b 986 wait_us( 1 );
uci1 8:95a325df1f6b 987
uci1 8:95a325df1f6b 988 PIN_ADC_CS = 0;
uci1 8:95a325df1f6b 989 PIN_spi.write( 0x00 );
uci1 8:95a325df1f6b 990 PIN_ADC_CS = 1;
uci1 8:95a325df1f6b 991 } else {
uci1 8:95a325df1f6b 992 i--;
uci1 8:95a325df1f6b 993 }
uci1 16:744ce85aede2 994 */
uci1 0:664899e0b988 995 }
uci1 16:744ce85aede2 996 gAdcToMBtimer.stop();
uci1 16:744ce85aede2 997 #ifdef DEBUG
uci1 16:744ce85aede2 998 printf("total time = %d us\r\n", gAdcToMBtimer.read_us());
uci1 16:744ce85aede2 999 #endif
uci1 16:744ce85aede2 1000 if ( kAdcToMBtimeCut < gAdcToMBtimer.read_us() ) {
uci1 16:744ce85aede2 1001 gEvent.SetTrgBit(kAdcToMBflag);
uci1 16:744ce85aede2 1002 }
uci1 16:744ce85aede2 1003 gAdcToMBtimer.reset();
uci1 15:f2569d8e4176 1004
uci1 15:f2569d8e4176 1005 // restart the timers
uci1 15:f2569d8e4176 1006 //ResetAllTickers();
uci1 8:95a325df1f6b 1007 } else {
uci1 8:95a325df1f6b 1008 // cards have no power. don't try reading out
uci1 8:95a325df1f6b 1009 gReadingOut=false;
uci1 0:664899e0b988 1010 }
uci1 0:664899e0b988 1011 }
uci1 0:664899e0b988 1012
uci1 13:7a1fb885a8e4 1013 SnCommWin::ECommWinResult OpenCommWin(const bool forceReconfig) {
uci1 0:664899e0b988 1014 // loop through each comm mode:
uci1 0:664899e0b988 1015 // a) try to connect
uci1 0:664899e0b988 1016 // b) if connected, listen for config
uci1 0:664899e0b988 1017 // c) if config requests data, send it
uci1 16:744ce85aede2 1018 /*
uci1 16:744ce85aede2 1019 for (int i=0; i<5; i++) {
uci1 16:744ce85aede2 1020 led4=1;
uci1 16:744ce85aede2 1021 led3=1;
uci1 16:744ce85aede2 1022 wait(0.5);
uci1 16:744ce85aede2 1023 led4=0;
uci1 16:744ce85aede2 1024 led3=0;
uci1 16:744ce85aede2 1025 wait(0.5);
uci1 16:744ce85aede2 1026 }
uci1 16:744ce85aede2 1027 */
uci1 3:24c5f0f50bf1 1028 gLastCommWin = time(0);
uci1 13:7a1fb885a8e4 1029
uci1 0:664899e0b988 1030 SnCommWin::ECommWinResult res = SnCommWin::kUndefFail;
uci1 0:664899e0b988 1031
uci1 1:e392595b4b76 1032 bool gotNewConfig=false;
uci1 13:7a1fb885a8e4 1033
uci1 13:7a1fb885a8e4 1034 if (gConf.GetCommWinDuration()==0) {
uci1 13:7a1fb885a8e4 1035 // TODO: set min so this is not possible
uci1 13:7a1fb885a8e4 1036 res = SnCommWin::kOkNoMsg;
uci1 13:7a1fb885a8e4 1037 } else {
uci1 13:7a1fb885a8e4 1038
uci1 13:7a1fb885a8e4 1039 gCommWinOpen = true;
uci1 1:e392595b4b76 1040 Watchdog::kick(); // don't reset!
uci1 13:7a1fb885a8e4 1041
uci1 13:7a1fb885a8e4 1042 #ifdef DEBUG
uci1 13:7a1fb885a8e4 1043 printf("opening comm window at %d\r\n", (int32_t)gLastCommWin);
uci1 16:744ce85aede2 1044 printf("duration=%u\r\n",gConf.GetCommWinDuration());
uci1 13:7a1fb885a8e4 1045 #endif
uci1 13:7a1fb885a8e4 1046
uci1 13:7a1fb885a8e4 1047 // close the file so that the data is all written out.
uci1 13:7a1fb885a8e4 1048 // and open it back up at the beginning (for reading)
uci1 12:d472f9811262 1049 #ifdef DEBUG
uci1 13:7a1fb885a8e4 1050 printf("close & open file. gEvtNum=%u, gPowNum=%u\r\n",gEvtNum,gPowNum);
uci1 12:d472f9811262 1051 #endif
uci1 13:7a1fb885a8e4 1052 PIN_lockRegisters = 0; // unlock so we can talk to SD card.
uci1 13:7a1fb885a8e4 1053 SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
uci1 13:7a1fb885a8e4 1054 SnSDUtils::OpenExistingFile(SnSDUtils::GetCurFileName(), true);
uci1 13:7a1fb885a8e4 1055
uci1 13:7a1fb885a8e4 1056 // (probably) power down cards,amps and power up comms
uci1 13:7a1fb885a8e4 1057 SetPower(true);
uci1 13:7a1fb885a8e4 1058
uci1 15:f2569d8e4176 1059
uci1 13:7a1fb885a8e4 1060 bool sendStat[kNcomms];
uci1 13:7a1fb885a8e4 1061 for (uint8_t i=0; i<kNcomms; i++) {
uci1 13:7a1fb885a8e4 1062 sendStat[i]=true;
uci1 13:7a1fb885a8e4 1063 }
uci1 13:7a1fb885a8e4 1064 bool* ss = sendStat;
uci1 13:7a1fb885a8e4 1065 SnCommWin** cw = gComms;
uci1 13:7a1fb885a8e4 1066 for (uint8_t i=0; ((time(0)-gLastCommWin)<gConf.GetCommWinDuration()); i++, cw++, ss++) {
uci1 1:e392595b4b76 1067 Watchdog::kick(); // don't reset!
uci1 13:7a1fb885a8e4 1068 if (i==kNcomms) {
uci1 13:7a1fb885a8e4 1069 i=0;
uci1 13:7a1fb885a8e4 1070 cw = gComms;
uci1 13:7a1fb885a8e4 1071 ss = sendStat;
uci1 13:7a1fb885a8e4 1072 }
uci1 13:7a1fb885a8e4 1073 if ((*cw)==0) {
uci1 13:7a1fb885a8e4 1074 continue;
uci1 13:7a1fb885a8e4 1075 }
uci1 16:744ce85aede2 1076
uci1 16:744ce85aede2 1077 const uint32_t conto =
uci1 16:744ce85aede2 1078 (gConf.GetCommWinDuration() < (*cw)->GetConnectTimeout()) ?
uci1 16:744ce85aede2 1079 gConf.GetCommWinDuration() : (*cw)->GetConnectTimeout();
uci1 16:744ce85aede2 1080 const uint32_t listo =
uci1 16:744ce85aede2 1081 (gConf.GetCommWinDuration() < (*cw)->GetListenTimeout()) ?
uci1 16:744ce85aede2 1082 gConf.GetCommWinDuration() : (*cw)->GetListenTimeout();
uci1 16:744ce85aede2 1083
uci1 16:744ce85aede2 1084 // update power reading in case we want to send it in status
uci1 16:744ce85aede2 1085 GetAvePowerReading();
uci1 16:744ce85aede2 1086 // get the trigger rates
uci1 16:744ce85aede2 1087 float thmrate=0, evtrate=0;
uci1 16:744ce85aede2 1088 GetRates(thmrate, evtrate);
uci1 13:7a1fb885a8e4 1089 // open window and (mabye) send status update
uci1 12:d472f9811262 1090 #ifdef DEBUG
uci1 13:7a1fb885a8e4 1091 printf("calling OpenWindow. ss=%d\r\n",(int)(*ss));
uci1 13:7a1fb885a8e4 1092 printf("gtt=%u, ct=%d, lcw=%d, dur=%u\r\n",GetTimeoutTime(gLastCommWin,conto),
uci1 13:7a1fb885a8e4 1093 time(0), gLastCommWin, gConf.GetCommWinDuration());
uci1 12:d472f9811262 1094 #endif
uci1 13:7a1fb885a8e4 1095 const SnCommWin::ECommWinResult conres = (*cw)->OpenWindow(
uci1 13:7a1fb885a8e4 1096 GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gEvent, gPower,
uci1 13:7a1fb885a8e4 1097 SnSDUtils::GetCurSeqNum(), thmrate, evtrate,
uci1 13:7a1fb885a8e4 1098 gGenBuf);
uci1 13:7a1fb885a8e4 1099 if (conres>=SnCommWin::kConnected) {
uci1 1:e392595b4b76 1100 Watchdog::kick(); // don't reset!
uci1 13:7a1fb885a8e4 1101 // connected. listen for config
uci1 13:7a1fb885a8e4 1102 *ss = false; // don't send status next time
uci1 12:d472f9811262 1103 #ifdef DEBUG
uci1 13:7a1fb885a8e4 1104 printf("get conf gtt=%u\r\n",GetTimeoutTime(gLastCommWin, listo));
uci1 12:d472f9811262 1105 #endif
uci1 13:7a1fb885a8e4 1106 const SnCommWin::ECommWinResult cfgres = (*cw)->GetConfig(
uci1 13:7a1fb885a8e4 1107 gConf, GetTimeoutTime(gLastCommWin, listo), gGenBuf, gBufSize);
uci1 16:744ce85aede2 1108
uci1 13:7a1fb885a8e4 1109 if (cfgres>=SnCommWin::kOkWithMsg) {
uci1 13:7a1fb885a8e4 1110 Watchdog::kick(); // don't reset!
uci1 16:744ce85aede2 1111
uci1 12:d472f9811262 1112 #ifdef DEBUG
uci1 13:7a1fb885a8e4 1113 printf("received config!\r\n");
uci1 13:7a1fb885a8e4 1114 printf("send data = %d\r\n", gConf.GetCommSendData());
uci1 12:d472f9811262 1115 #endif
uci1 13:7a1fb885a8e4 1116 // send data if need be (files, some events, etc)
uci1 13:7a1fb885a8e4 1117 const uint32_t winto = GetTimeoutTime(gLastCommWin,
uci1 13:7a1fb885a8e4 1118 gConf.GetCommWinDuration());
uci1 13:7a1fb885a8e4 1119 const uint32_t gtt = gConf.IsObeyingTimeout() ? winto : 0;
uci1 13:7a1fb885a8e4 1120 if (gConf.GetCommSendData()!=0) {
uci1 12:d472f9811262 1121 #ifdef DEBUG
uci1 13:7a1fb885a8e4 1122 printf("sending data, gtt=%u. lcw=%u, dur=%u, obey=%s\r\n",
uci1 13:7a1fb885a8e4 1123 GetTimeoutTime(gLastCommWin, gConf.GetCommWinDuration()),
uci1 13:7a1fb885a8e4 1124 gLastCommWin, gConf.GetCommWinDuration(),
uci1 13:7a1fb885a8e4 1125 gConf.IsObeyingTimeout() ? "true" : "false");
uci1 12:d472f9811262 1126 #endif
uci1 16:744ce85aede2 1127
uci1 13:7a1fb885a8e4 1128 res = (*cw)->SendData(gConf, gEvent, gPower, gGenBuf, gBufSize,
uci1 13:7a1fb885a8e4 1129 gtt, winto);
uci1 13:7a1fb885a8e4 1130 } else {
uci1 13:7a1fb885a8e4 1131 // don't send anything
uci1 13:7a1fb885a8e4 1132 res = cfgres;
uci1 13:7a1fb885a8e4 1133 }
uci1 13:7a1fb885a8e4 1134 #ifdef DEBUG
uci1 13:7a1fb885a8e4 1135 printf("Got config!\r\n");
uci1 13:7a1fb885a8e4 1136 #endif
uci1 13:7a1fb885a8e4 1137 gotNewConfig = (cfgres!=SnCommWin::kOkWthMsgNoConf);
uci1 13:7a1fb885a8e4 1138 Watchdog::kick(); // don't reset!
uci1 13:7a1fb885a8e4 1139 break;
uci1 13:7a1fb885a8e4 1140 }
uci1 0:664899e0b988 1141 }
uci1 13:7a1fb885a8e4 1142
uci1 13:7a1fb885a8e4 1143 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 1144 }
uci1 15:f2569d8e4176 1145 // close the connection(s)
uci1 15:f2569d8e4176 1146 cw = gComms;
uci1 15:f2569d8e4176 1147 for (uint8_t i=0; i<kNcomms; i++, cw++) {
uci1 15:f2569d8e4176 1148 if ((*cw)==0) {
uci1 15:f2569d8e4176 1149 continue;
uci1 15:f2569d8e4176 1150 }
uci1 16:744ce85aede2 1151 if ((*cw)->GetCommType()==SnConfigFrame::kIrid) {
uci1 16:744ce85aede2 1152 #ifdef DEBUG
uci1 16:744ce85aede2 1153 printf("try to set iridium time\r\n");
uci1 16:744ce85aede2 1154 #endif
uci1 16:744ce85aede2 1155 // set the clock before closing connection
uci1 16:744ce85aede2 1156 const bool con =
uci1 16:744ce85aede2 1157 (*cw)->Connect(GetTimeoutTime(gLastCommWin,
uci1 16:744ce85aede2 1158 gConf.GetCommWinDuration()));
uci1 16:744ce85aede2 1159 if (con) {
uci1 16:744ce85aede2 1160 const uint32_t nt = (*cw)->TrySetSysTimeUnix(
uci1 16:744ce85aede2 1161 GetTimeoutTime(gLastCommWin,gConf.GetCommWinDuration()));
uci1 16:744ce85aede2 1162 }
uci1 16:744ce85aede2 1163 }
uci1 15:f2569d8e4176 1164 (*cw)->CloseConn(GetTimeoutTime(gLastCommWin,gConf.GetCommWinDuration()));
uci1 15:f2569d8e4176 1165 Watchdog::kick(); // don't reset!
uci1 15:f2569d8e4176 1166 }
uci1 0:664899e0b988 1167 }
uci1 12:d472f9811262 1168
uci1 4:a91682e19d6b 1169 // (probably) power down comms and power up cards,amps
uci1 4:a91682e19d6b 1170 SetPower(false);
uci1 4:a91682e19d6b 1171
uci1 1:e392595b4b76 1172 gFirstEvt = true;
uci1 4:a91682e19d6b 1173
uci1 1:e392595b4b76 1174 // reset config with system powered (for DAC/PLA setting)
uci1 13:7a1fb885a8e4 1175 if (gotNewConfig || forceReconfig) {
uci1 12:d472f9811262 1176 #ifdef DEBUG
uci1 1:e392595b4b76 1177 printf("calling SetConfigAndMakeOutputFile\r\n");
uci1 12:d472f9811262 1178 #endif
uci1 1:e392595b4b76 1179 SetConfigAndMakeOutputFile();
uci1 12:d472f9811262 1180 } else {
uci1 12:d472f9811262 1181 MakeOutputFile();
uci1 1:e392595b4b76 1182 }
uci1 12:d472f9811262 1183 #ifdef DEBUG
uci1 1:e392595b4b76 1184 printf("closing comm win at %d\r\n",(int32_t)time(0));
uci1 12:d472f9811262 1185 #endif
uci1 1:e392595b4b76 1186
uci1 0:664899e0b988 1187 gCommWinOpen = false;
uci1 0:664899e0b988 1188 return res;
uci1 0:664899e0b988 1189 }