Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Mon Aug 13 20:44:06 2012 +0000
Revision:
11:de443350ec4a
Parent:
10:3c93db1cfb12
Child:
12:d472f9811262
Added p20 being set to 0 before every write to the SD card, to protect against the writing causing the system to stall. Comms under dev. Many debug messages.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
uci1 0:664899e0b988 1 #include "mbed.h"
uci1 0:664899e0b988 2
uci1 8:95a325df1f6b 3 #define USE_RTOS_TIMER
uci1 8:95a325df1f6b 4
uci1 0:664899e0b988 5 #include <stdint.h>
uci1 0:664899e0b988 6 #include "SDFileSystem.h"
uci1 0:664899e0b988 7 #include "MODSERIAL.h"
uci1 0:664899e0b988 8 #include "Watchdog.h"
uci1 0:664899e0b988 9 #include "SnConstants.h"
uci1 0:664899e0b988 10 #include "SnBitUtils.h"
uci1 0:664899e0b988 11 #include "SnSDUtils.h"
uci1 0:664899e0b988 12 #include "SnConfigFrame.h"
uci1 0:664899e0b988 13 #include "SnEventFrame.h"
uci1 0:664899e0b988 14 #include "SnStatusFrame.h"
uci1 2:e67f7c158087 15 #include "SnHeaderFrame.h"
uci1 0:664899e0b988 16 #include "SnCommWin.h"
uci1 7:079617408fec 17 #include "SnCommAfarTCP.h"
uci1 0:664899e0b988 18 #include "SnCommUsb.h"
uci1 1:e392595b4b76 19 #include "SnBase64.h"
uci1 8:95a325df1f6b 20 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 21 #include "RtosTimer.h"
uci1 8:95a325df1f6b 22 #endif
uci1 0:664899e0b988 23
uci1 0:664899e0b988 24 //
uci1 0:664899e0b988 25 // MBED PINS (ordered by number)
uci1 0:664899e0b988 26 //
uci1 0:664899e0b988 27 // leds (for debugging)
uci1 0:664899e0b988 28 DigitalOut led1(LED1);
uci1 0:664899e0b988 29 DigitalOut led2(LED2);
uci1 0:664899e0b988 30 DigitalOut led3(LED3);
uci1 0:664899e0b988 31 DigitalOut led4(LED4);
uci1 0:664899e0b988 32 // Set up power pins - Note that it's Zero for "on"
uci1 1:e392595b4b76 33 DigitalOut PIN_turn_on_system(p17); // this turns on system
uci1 0:664899e0b988 34 DigitalOut PIN_turn_on_amps(p25);
uci1 0:664899e0b988 35 // Activate/select chip by falling edge
uci1 0:664899e0b988 36 DigitalOut PIN_ADC_CS( p9 );
uci1 0:664899e0b988 37 // clock signal to activate PLA setting
uci1 0:664899e0b988 38 DigitalOut PIN_PLA_cs(p10);
uci1 0:664899e0b988 39 // To force a trigger
uci1 0:664899e0b988 40 DigitalOut PIN_forceTrigger(p11); //modification
uci1 0:664899e0b988 41 // To suppress thermal triggers
uci1 0:664899e0b988 42 DigitalOut PIN_enableThermTrig(p12);
uci1 0:664899e0b988 43 // Restart clock on all FPGAs.
uci1 0:664899e0b988 44 DigitalOut PIN_DoNotRestartAllClocks( p13 );
uci1 0:664899e0b988 45 // This tells the DFPGAs to store the data on motherboard FPGA and
uci1 0:664899e0b988 46 // read it out.
uci1 0:664899e0b988 47 DigitalIn PIN_a_sf_clk( p14 );
uci1 0:664899e0b988 48 DigitalIn PIN_rst_a_sf(p15);
uci1 1:e392595b4b76 49 // afar power
uci1 1:e392595b4b76 50 DigitalOut PIN_afar_power(p16);
uci1 4:a91682e19d6b 51 // batter voltage/current measurement
uci1 4:a91682e19d6b 52 AnalogIn PIN_vADC1(p19);
uci1 4:a91682e19d6b 53 AnalogIn PIN_vADC2(p18);
uci1 0:664899e0b988 54 // Lock daughter card registeres (during data readout).
uci1 0:664899e0b988 55 DigitalOut PIN_lockRegisters( p20 );
uci1 1:e392595b4b76 56 // iridium (SBD) power
uci1 1:e392595b4b76 57 DigitalOut PIN_iridSbd_power(p21);
uci1 0:664899e0b988 58 // Majority logic pins
uci1 0:664899e0b988 59 DigitalOut PIN_MajLogHiBit(p22);
uci1 0:664899e0b988 60 DigitalOut PIN_MajLogLoBit(p23);
uci1 0:664899e0b988 61 // Tell FPGA to be ready to accept DAC values
uci1 0:664899e0b988 62 DigitalOut PIN_start_fpga(p26);
uci1 0:664899e0b988 63 // Two bits to the select the daughter card for readout
uci1 0:664899e0b988 64 DigitalOut PIN_selCardHiBit( p29 );
uci1 0:664899e0b988 65 DigitalOut PIN_selCardLoBit( p30 );
uci1 0:664899e0b988 66 // To launch a heartbeat pulse
uci1 0:664899e0b988 67 DigitalOut PIN_heartbeat(p24);
uci1 0:664899e0b988 68 // Setup SPI pins
uci1 0:664899e0b988 69 SPI PIN_spi( p5, p6, p7 );
uci1 0:664899e0b988 70 // The SD card
uci1 3:24c5f0f50bf1 71
uci1 3:24c5f0f50bf1 72 // this needs to be first in case some other global uses a print statement
uci1 3:24c5f0f50bf1 73 static MODSERIAL gCpu( USBTX, USBRX ); // defined here so it might be used for debugging output
uci1 3:24c5f0f50bf1 74
uci1 0:664899e0b988 75 SDFileSystem sd(p5, p6, p7, p8, SnSDUtils::kSDsubDir+1);
uci1 0:664899e0b988 76 LocalFileSystem local("local");
uci1 0:664899e0b988 77
uci1 0:664899e0b988 78 //
uci1 0:664899e0b988 79 // fwd declare fcns
uci1 0:664899e0b988 80 //
uci1 0:664899e0b988 81 void ReadAllRegisters();
uci1 0:664899e0b988 82 void ReadRegister(const uint8_t chan, int16_t* dev);
uci1 0:664899e0b988 83 void SaveEvent(const int32_t etms);
uci1 0:664899e0b988 84 void WaitTrigAndSendClock();
uci1 1:e392595b4b76 85 void SetConfigAndMakeOutputFile();
uci1 0:664899e0b988 86 SnCommWin::ECommWinResult OpenCommWin();
uci1 3:24c5f0f50bf1 87 void MakeOutputFile(const bool stopRunning=false);
uci1 4:a91682e19d6b 88 void SetPower(const bool isCommWin);
uci1 8:95a325df1f6b 89 void procForceTrigger();
uci1 8:95a325df1f6b 90 void procHeartbeat();
uci1 8:95a325df1f6b 91 void procPowerCheck();
uci1 8:95a325df1f6b 92 void procCommWin();
uci1 8:95a325df1f6b 93 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 94 void procForceTrigger(void const *) { return procForceTrigger(); }
uci1 8:95a325df1f6b 95 void procHeartbeat(void const *) { return procHeartbeat(); }
uci1 8:95a325df1f6b 96 void procPowerCheck(void const *) { return procPowerCheck(); }
uci1 8:95a325df1f6b 97 void procCommWin(void const *) { return procCommWin(); }
uci1 8:95a325df1f6b 98 #endif
uci1 0:664899e0b988 99
uci1 0:664899e0b988 100 //
uci1 0:664899e0b988 101 // globals
uci1 0:664899e0b988 102 //
uci1 0:664899e0b988 103 // readout objs
uci1 8:95a325df1f6b 104 // TODO: use RtosTimer instead of Ticker?
uci1 8:95a325df1f6b 105 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 106 static rtos::RtosTimer* gForceTicker;
uci1 8:95a325df1f6b 107 static rtos::RtosTimer* gHeartbeatTicker;
uci1 8:95a325df1f6b 108 static rtos::RtosTimer* gCommWinTicker;
uci1 8:95a325df1f6b 109 static rtos::RtosTimer* gPowerCheckTicker;
uci1 8:95a325df1f6b 110 #else
uci1 0:664899e0b988 111 static Ticker gForceTicker;
uci1 3:24c5f0f50bf1 112 static Ticker gHeartbeatTicker;
uci1 1:e392595b4b76 113 static Ticker gCommWinTicker;
uci1 8:95a325df1f6b 114 static Ticker gPowerCheckTicker;
uci1 8:95a325df1f6b 115 #endif
uci1 0:664899e0b988 116 static Timer gEvtTimer;
uci1 0:664899e0b988 117 static SnConfigFrame gConf;
uci1 0:664899e0b988 118 static SnEventFrame gEvent;
uci1 8:95a325df1f6b 119 static SnPowerFrame gPower;
uci1 0:664899e0b988 120 // parameters
uci1 0:664899e0b988 121 static bool gFirstEvt = true;
uci1 0:664899e0b988 122 static bool gReadingOut = false;
uci1 0:664899e0b988 123 static bool gCommWinOpen = false; // if it's open
uci1 1:e392595b4b76 124 static volatile bool gOpenCommWin = false; // if it should be opened
uci1 8:95a325df1f6b 125 static volatile bool gCheckPower = false; // if it should be checked
uci1 8:95a325df1f6b 126 static uint32_t gPowNum = 0;
uci1 8:95a325df1f6b 127 static uint32_t gEvtNum = 0; // num of evt written
uci1 8:95a325df1f6b 128 static uint32_t gTrgNum[kNumTrgs] = {0}; // num of this type of trg received
uci1 0:664899e0b988 129 // i/o
uci1 1:e392595b4b76 130 static time_t gLastCommWin = 0;
uci1 10:3c93db1cfb12 131 static uint32_t gLastCountReset = 0;
uci1 10:3c93db1cfb12 132 // this should be bigger than anything that will actually be used
uci1 10:3c93db1cfb12 133 static const uint32_t gBufSize=SnStatusFrame::kMaxSizeOf + (2u*SnHeaderFrame::kMaxSizeOf) + SnPowerFrame::kMaxSizeOf;
uci1 6:6f002d202f59 134 //static const uint32_t gB64Bsize=BASE64ENC_LEN(gBufSize)+1;
uci1 6:6f002d202f59 135 //static char gB64Buf[gB64Bsize];
uci1 3:24c5f0f50bf1 136 static char gGenBuf[gBufSize]; // must be big enough for event or status or config!
uci1 11:de443350ec4a 137 static SnCommWin* gComms[kNcomms] = { 0 }; // order => priority. afar uses RTOS, and must be made inside main
uci1 0:664899e0b988 138
uci1 0:664899e0b988 139 void procForceTrigger() {
uci1 3:24c5f0f50bf1 140 led3=!led3;
uci1 0:664899e0b988 141 if (gReadingOut==false && gCommWinOpen==false) {
uci1 8:95a325df1f6b 142 printf("proc force\r\n");
uci1 0:664899e0b988 143 gEvent.SetTrgBit(kFrcTrg);
uci1 0:664899e0b988 144 gEvent.SetTrgNum((gTrgNum[kFrcTrg])++);
uci1 0:664899e0b988 145 PIN_forceTrigger = 1; // force a trigger
uci1 0:664899e0b988 146 }
uci1 0:664899e0b988 147 }
uci1 0:664899e0b988 148
uci1 3:24c5f0f50bf1 149 void procHeartbeat() {
uci1 3:24c5f0f50bf1 150 if (gReadingOut==false && gCommWinOpen==false) {
uci1 8:95a325df1f6b 151 printf("proc heartbeat\r\n");
uci1 3:24c5f0f50bf1 152 PIN_heartbeat = 1; // heartbeat pulse
uci1 3:24c5f0f50bf1 153 PIN_heartbeat = 0;
uci1 3:24c5f0f50bf1 154 }
uci1 3:24c5f0f50bf1 155 }
uci1 3:24c5f0f50bf1 156
uci1 8:95a325df1f6b 157 void procPowerCheck() {
uci1 8:95a325df1f6b 158 printf("proc power\r\n");
uci1 8:95a325df1f6b 159 gCheckPower=true;
uci1 8:95a325df1f6b 160 }
uci1 8:95a325df1f6b 161
uci1 0:664899e0b988 162 void procCommWin() {
uci1 0:664899e0b988 163 if (gReadingOut==false && gCommWinOpen==false) {
uci1 1:e392595b4b76 164 if ( (time(0) - gLastCommWin) > gConf.GetCommWinPeriod() ) {
uci1 8:95a325df1f6b 165 printf("proc comm win\r\n");
uci1 1:e392595b4b76 166 led3=!led3;
uci1 1:e392595b4b76 167 gOpenCommWin = true;
uci1 1:e392595b4b76 168 }
uci1 0:664899e0b988 169 }
uci1 0:664899e0b988 170 }
uci1 0:664899e0b988 171
uci1 1:e392595b4b76 172 uint32_t GetTimeoutTime(const uint32_t startTime,
uci1 1:e392595b4b76 173 const uint32_t delta) {
uci1 1:e392595b4b76 174 const uint32_t lst = time(0)-startTime;
uci1 1:e392595b4b76 175 const uint32_t lio =
uci1 1:e392595b4b76 176 ((lst+delta) < gConf.GetCommWinDuration()) ?
uci1 1:e392595b4b76 177 lst+delta : gConf.GetCommWinDuration();
uci1 1:e392595b4b76 178 return lio+startTime;
uci1 1:e392595b4b76 179 }
uci1 1:e392595b4b76 180
uci1 8:95a325df1f6b 181 bool AreCardsPowered() {
uci1 8:95a325df1f6b 182 printf("acp: PIN_turn_on_system=%d\r\n",PIN_turn_on_system.read());
uci1 8:95a325df1f6b 183 return (PIN_turn_on_system.read()==0);
uci1 8:95a325df1f6b 184 }
uci1 0:664899e0b988 185
uci1 8:95a325df1f6b 186 void GetAvePowerReading() {
uci1 8:95a325df1f6b 187 // use one measurement as the assumed average
uci1 8:95a325df1f6b 188 // in order to reduce computational errors
uci1 8:95a325df1f6b 189 int32_t v1, v2;
uci1 8:95a325df1f6b 190 const uint16_t aaveV1 = PIN_vADC1.read_u16();
uci1 8:95a325df1f6b 191 const uint16_t aaveV2 = PIN_vADC2.read_u16();
uci1 8:95a325df1f6b 192 float n=0, ave1=0, ave2=0, rms1=0, rms2=0;
uci1 8:95a325df1f6b 193 for (uint16_t i=0; i<kNvoltsAve; i++) {
uci1 8:95a325df1f6b 194 v1 = PIN_vADC1.read_u16() - aaveV1;
uci1 8:95a325df1f6b 195 v2 = PIN_vADC2.read_u16() - aaveV2;
uci1 8:95a325df1f6b 196 n += 1;
uci1 8:95a325df1f6b 197 ave1 += v1;
uci1 8:95a325df1f6b 198 rms1 += v1*v1;
uci1 8:95a325df1f6b 199 ave2 += v2;
uci1 8:95a325df1f6b 200 rms2 += v2*v2;
uci1 8:95a325df1f6b 201 }
uci1 8:95a325df1f6b 202 rms1 -= (ave1*ave1)/n;
uci1 8:95a325df1f6b 203 rms2 -= (ave2*ave2)/n;
uci1 8:95a325df1f6b 204 rms1 /= n-1;
uci1 8:95a325df1f6b 205 rms2 /= n-1;
uci1 9:a1a39573dd43 206 rms1 = sqrt(rms1);
uci1 9:a1a39573dd43 207 rms2 = sqrt(rms2);
uci1 8:95a325df1f6b 208 ave1 /= n;
uci1 8:95a325df1f6b 209 ave2 /= n;
uci1 8:95a325df1f6b 210 ave1 += aaveV1;
uci1 8:95a325df1f6b 211 ave2 += aaveV2;
uci1 8:95a325df1f6b 212 gPower.Set(ave1, ave2, rms1, rms2, time(0));
uci1 8:95a325df1f6b 213 }
uci1 0:664899e0b988 214
uci1 8:95a325df1f6b 215 void CheckPower(const bool isCommWin) {
uci1 8:95a325df1f6b 216 printf("CheckPower\r\n");
uci1 8:95a325df1f6b 217 // read power
uci1 8:95a325df1f6b 218 GetAvePowerReading();
uci1 8:95a325df1f6b 219 // save to disk
uci1 8:95a325df1f6b 220 FILE* cf = SnSDUtils::GetCurFile();
uci1 8:95a325df1f6b 221 if (cf!=0) {
uci1 11:de443350ec4a 222 PIN_lockRegisters = 0; // unlock so we can talk to SD card.
uci1 8:95a325df1f6b 223 printf("writing power. v1=%g, v2=%g, r1=%g, r2=%g, t=%u, pownum=%u\r\n",
uci1 8:95a325df1f6b 224 gPower.GetAveV1(), gPower.GetAveV2(),
uci1 8:95a325df1f6b 225 gPower.GetRmsV1(), gPower.GetRmsV2(), gPower.GetTime(),
uci1 8:95a325df1f6b 226 gPowNum);
uci1 8:95a325df1f6b 227 SnSDUtils::WritePowerTo(cf, gPower, gPowNum);
uci1 8:95a325df1f6b 228 }
uci1 8:95a325df1f6b 229 // do we need to change modes?
uci1 8:95a325df1f6b 230 bool changed = false;
uci1 8:95a325df1f6b 231 if (gConf.IsLowPowerMode()) {
uci1 8:95a325df1f6b 232 if (gPower.GetAveV1() > gConf.GetBatVoltLowPwr()) {
uci1 8:95a325df1f6b 233 printf("chaing to normal power!\r\n");
uci1 8:95a325df1f6b 234 gConf.ChangeToNormPower();
uci1 8:95a325df1f6b 235 changed = true;
uci1 8:95a325df1f6b 236 }
uci1 8:95a325df1f6b 237 } else {
uci1 8:95a325df1f6b 238 if (gPower.GetAveV1() < gConf.GetBatVoltLowPwr()) {
uci1 8:95a325df1f6b 239 printf("chaing to low power!\r\n");
uci1 8:95a325df1f6b 240 gConf.ChangeToLowPower();
uci1 8:95a325df1f6b 241 changed = true;
uci1 8:95a325df1f6b 242 }
uci1 8:95a325df1f6b 243 }
uci1 8:95a325df1f6b 244 if (changed) {
uci1 8:95a325df1f6b 245 SetPower(isCommWin);
uci1 8:95a325df1f6b 246 printf("Using config %s\r\n",gConf.GetLabel());
uci1 8:95a325df1f6b 247 SetConfigAndMakeOutputFile(); // setup defaults in case no communication
uci1 8:95a325df1f6b 248 }
uci1 8:95a325df1f6b 249 // checking done
uci1 8:95a325df1f6b 250 gCheckPower = false;
uci1 8:95a325df1f6b 251 }
uci1 8:95a325df1f6b 252
uci1 10:3c93db1cfb12 253 void ResetCountersClearEvt() {
uci1 10:3c93db1cfb12 254 gEvent.ClearEvent();
uci1 10:3c93db1cfb12 255 gEvtNum = gConf.GetFirstEvt();
uci1 10:3c93db1cfb12 256 gPowNum = 0;
uci1 10:3c93db1cfb12 257 memset(gTrgNum, 0, sizeof(uint32_t)*kNumTrgs);
uci1 10:3c93db1cfb12 258 gLastCountReset = static_cast<uint32_t>(time(0));
uci1 10:3c93db1cfb12 259 }
uci1 10:3c93db1cfb12 260
uci1 10:3c93db1cfb12 261 void GetRates(float& thmrate, float& evtrate) {
uci1 10:3c93db1cfb12 262 thmrate = evtrate = 0;
uci1 10:3c93db1cfb12 263 const uint32_t dt = static_cast<uint32_t>(time(0)) - gLastCountReset;
uci1 10:3c93db1cfb12 264 if (dt>0) {
uci1 10:3c93db1cfb12 265 thmrate = gTrgNum[kThmTrg] / dt;
uci1 10:3c93db1cfb12 266 evtrate = (gEvtNum + gConf.GetFirstEvt()) / dt;
uci1 10:3c93db1cfb12 267 }
uci1 10:3c93db1cfb12 268 }
uci1 10:3c93db1cfb12 269
uci1 8:95a325df1f6b 270 bool IsSeqComplete() {
uci1 10:3c93db1cfb12 271 printf("IsSeqComplete: eps=%u, cntpow=%d, fe=%u, pow=%u, evt=%u\r\n",
uci1 10:3c93db1cfb12 272 gConf.GetEvtsPerFile(), (int)gConf.IsCountingPowerReadings(),
uci1 10:3c93db1cfb12 273 gConf.GetFirstEvt(), gPowNum, gEvtNum);
uci1 8:95a325df1f6b 274 if (gConf.GetEvtsPerFile()>0) {
uci1 8:95a325df1f6b 275 if (gConf.IsCountingPowerReadings()) {
uci1 8:95a325df1f6b 276 return (gPowNum>=gConf.GetEvtsPerFile());
uci1 8:95a325df1f6b 277 } else {
uci1 8:95a325df1f6b 278 return (gEvtNum>=(gConf.GetFirstEvt()+gConf.GetEvtsPerFile()));
uci1 8:95a325df1f6b 279 }
uci1 8:95a325df1f6b 280 }
uci1 8:95a325df1f6b 281 return false;
uci1 8:95a325df1f6b 282 }
uci1 1:e392595b4b76 283
uci1 8:95a325df1f6b 284 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 285 void stopTicker(rtos::RtosTimer* tik) {
uci1 8:95a325df1f6b 286 if (tik!=0) {
uci1 8:95a325df1f6b 287 tik->stop();
uci1 8:95a325df1f6b 288 }
uci1 8:95a325df1f6b 289 }
uci1 8:95a325df1f6b 290 #else
uci1 8:95a325df1f6b 291 void stopTicker(Ticker& tik) {
uci1 8:95a325df1f6b 292 tik.detach();
uci1 8:95a325df1f6b 293 }
uci1 8:95a325df1f6b 294 #endif
uci1 8:95a325df1f6b 295
uci1 8:95a325df1f6b 296 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 297 uint32_t resetTicker(rtos::RtosTimer* tik, const uint32_t timSec,
uci1 8:95a325df1f6b 298 const uint32_t maxTimSec) {
uci1 8:95a325df1f6b 299 if (tik!=0) {
uci1 8:95a325df1f6b 300 tik->stop();
uci1 8:95a325df1f6b 301 if (timSec>0) {
uci1 8:95a325df1f6b 302 uint32_t tp = timSec > maxTimSec ? maxTimSec : timSec;
uci1 8:95a325df1f6b 303 tp *= 1000u; // ms
uci1 8:95a325df1f6b 304 tik->start(tp);
uci1 8:95a325df1f6b 305 return tp;
uci1 8:95a325df1f6b 306 }
uci1 8:95a325df1f6b 307 }
uci1 8:95a325df1f6b 308 return 0;
uci1 8:95a325df1f6b 309 }
uci1 8:95a325df1f6b 310 #else
uci1 8:95a325df1f6b 311 uint32_t resetTicker(Ticker& tik, const uint32_t timSec,
uci1 8:95a325df1f6b 312 const uint32_t maxTimSec, void (*fptr)(void)) {
uci1 8:95a325df1f6b 313 tik.detach();
uci1 8:95a325df1f6b 314 if (timSec>0) {
uci1 8:95a325df1f6b 315 const uint32_t tp = timSec > maxTimSec ? maxTimSec : timSec;
uci1 8:95a325df1f6b 316 tik.attach(fptr, tp);
uci1 8:95a325df1f6b 317 return tp;
uci1 8:95a325df1f6b 318 }
uci1 8:95a325df1f6b 319 return 0;
uci1 8:95a325df1f6b 320 }
uci1 8:95a325df1f6b 321 #endif
uci1 8:95a325df1f6b 322
uci1 8:95a325df1f6b 323 void StopRunning() {
uci1 10:3c93db1cfb12 324 printf("stop running\r\n");
uci1 10:3c93db1cfb12 325 printf("stopping force\r\n");
uci1 8:95a325df1f6b 326 stopTicker(gForceTicker);
uci1 10:3c93db1cfb12 327 printf("stop heart\r\n");
uci1 8:95a325df1f6b 328 stopTicker(gHeartbeatTicker);
uci1 10:3c93db1cfb12 329 printf("stop comm win\r\n");
uci1 8:95a325df1f6b 330 stopTicker(gCommWinTicker);
uci1 10:3c93db1cfb12 331 printf("stop power check\r\n");
uci1 8:95a325df1f6b 332 stopTicker(gPowerCheckTicker);
uci1 8:95a325df1f6b 333 while (true) {
uci1 8:95a325df1f6b 334 led3 = 1; led4=1;
uci1 8:95a325df1f6b 335 wait(0.5);
uci1 8:95a325df1f6b 336 led3 = 0; led4=0;
uci1 8:95a325df1f6b 337 wait(0.5);
uci1 8:95a325df1f6b 338 //Watchdog::kick(); - if we kick the watchdog, the station is unrecoverable without physical access
uci1 8:95a325df1f6b 339 }
uci1 8:95a325df1f6b 340 }
uci1 1:e392595b4b76 341
uci1 0:664899e0b988 342 int main() {
uci1 1:e392595b4b76 343 {
uci1 2:e67f7c158087 344 led1=1; wait(0.2);
uci1 2:e67f7c158087 345 led1=0; led2=1; wait(0.2);
uci1 2:e67f7c158087 346 led2=0; led3=1; wait(0.2);
uci1 2:e67f7c158087 347 led3=0; led4=1; wait(0.2);
uci1 1:e392595b4b76 348 led4=0;
uci1 1:e392595b4b76 349 }
uci1 1:e392595b4b76 350
uci1 8:95a325df1f6b 351 // RTOS stuff must be made inside main for some reason
uci1 8:95a325df1f6b 352 gComms[0] = new SnCommAfarTCP(gConf);
uci1 8:95a325df1f6b 353 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 354 gForceTicker = new rtos::RtosTimer(&procForceTrigger);
uci1 8:95a325df1f6b 355 gHeartbeatTicker = new rtos::RtosTimer(&procHeartbeat);
uci1 8:95a325df1f6b 356 gCommWinTicker = new rtos::RtosTimer(&procCommWin);
uci1 8:95a325df1f6b 357 gPowerCheckTicker = new rtos::RtosTimer(&procPowerCheck);
uci1 8:95a325df1f6b 358 #endif
uci1 8:95a325df1f6b 359
uci1 0:664899e0b988 360 led2=1;
uci1 0:664899e0b988 361 //wait_ms(100);
uci1 1:e392595b4b76 362
uci1 3:24c5f0f50bf1 363 printf("\n\n\n\n\n\nstarting\r\n");
uci1 1:e392595b4b76 364
uci1 0:664899e0b988 365 // a failsafe
uci1 0:664899e0b988 366 Watchdog::kick(kWDFailsafe);
uci1 0:664899e0b988 367
uci1 1:e392595b4b76 368 // set the clock to the BS time, if it's not set
uci1 1:e392595b4b76 369 if ( (static_cast<int32_t>(time(0)))<0 ) {
uci1 1:e392595b4b76 370 set_time(kBStime);
uci1 1:e392595b4b76 371 }
uci1 1:e392595b4b76 372 printf("time = %d\r\n",(int32_t)time(0));
uci1 1:e392595b4b76 373 gLastCommWin = time(0); // prevent comm win proc
uci1 0:664899e0b988 374
uci1 8:95a325df1f6b 375 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 376 gForceTicker->stop();
uci1 8:95a325df1f6b 377 #else
uci1 0:664899e0b988 378 gForceTicker.detach();
uci1 8:95a325df1f6b 379 #endif
uci1 0:664899e0b988 380 gFirstEvt = true;
uci1 0:664899e0b988 381
uci1 4:a91682e19d6b 382 // (probably) power down comms and power up cards,amps
uci1 4:a91682e19d6b 383 SetPower(false);
uci1 4:a91682e19d6b 384
uci1 3:24c5f0f50bf1 385 printf("Using config %s\r\n",gConf.GetLabel());
uci1 1:e392595b4b76 386 SetConfigAndMakeOutputFile(); // setup defaults in case no communication
uci1 4:a91682e19d6b 387
uci1 0:664899e0b988 388 //
uci1 0:664899e0b988 389 // get config
uci1 0:664899e0b988 390 //
uci1 8:95a325df1f6b 391 printf("call OpenCommWin\r\n");
uci1 2:e67f7c158087 392 OpenCommWin();
uci1 3:24c5f0f50bf1 393
uci1 0:664899e0b988 394 // get ready to trigger
uci1 0:664899e0b988 395 PIN_spi.format( 16, 1 ); // change to data readout format
uci1 0:664899e0b988 396
uci1 0:664899e0b988 397 led2=0;
uci1 0:664899e0b988 398
uci1 0:664899e0b988 399 // the main event loop. wait for triggers in SendClock
uci1 3:24c5f0f50bf1 400 gEvtTimer.start();
uci1 0:664899e0b988 401 while( true )
uci1 0:664899e0b988 402 {
uci1 0:664899e0b988 403 // in here, we wait for triggers from the MB-FPGA
uci1 0:664899e0b988 404 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 405
uci1 1:e392595b4b76 406 led1 = !led1;
uci1 1:e392595b4b76 407
uci1 1:e392595b4b76 408 printf("calling wait trig\r\n");
uci1 1:e392595b4b76 409 printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
uci1 5:9cea89700c66 410 printf("readingout=%d\r\n",(int)gReadingOut);
uci1 1:e392595b4b76 411
uci1 0:664899e0b988 412 PIN_lockRegisters = 0; // allow data to come from DFPGA
uci1 0:664899e0b988 413 WaitTrigAndSendClock();
uci1 0:664899e0b988 414 PIN_lockRegisters = 1; // block registers during readout
uci1 1:e392595b4b76 415
uci1 1:e392595b4b76 416 if (gReadingOut) {
uci1 8:95a325df1f6b 417 const int32_t etms = gEvtTimer.read_ms(); // time since last trigger
uci1 8:95a325df1f6b 418 gEvtTimer.reset(); gEvtTimer.start(); // start counter from this trigger
uci1 8:95a325df1f6b 419
uci1 8:95a325df1f6b 420 Watchdog::kick(); // don't reset!
uci1 8:95a325df1f6b 421
uci1 1:e392595b4b76 422 //
uci1 1:e392595b4b76 423 // got trigger. read registers to mbed and build the event
uci1 1:e392595b4b76 424 //
uci1 1:e392595b4b76 425
uci1 1:e392595b4b76 426 led4=1;
uci1 1:e392595b4b76 427 printf("readout\r\n");
uci1 1:e392595b4b76 428
uci1 1:e392595b4b76 429 // read data & calc CRC
uci1 1:e392595b4b76 430 gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit);
uci1 1:e392595b4b76 431 gEvent.SetCurMbedTime();
uci1 1:e392595b4b76 432 // TODO: no way to check for external trigger?
uci1 1:e392595b4b76 433 if (gEvent.IsForcedTrg()==false) {
uci1 1:e392595b4b76 434 gEvent.SetTrgBit(kThmTrg);
uci1 1:e392595b4b76 435 gEvent.SetTrgNum((gTrgNum[kThmTrg])++);
uci1 1:e392595b4b76 436 } // else already set by procForceTrigger
uci1 1:e392595b4b76 437 // (no need to calc if we throw this event away)
uci1 1:e392595b4b76 438
uci1 1:e392595b4b76 439 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 440
uci1 1:e392595b4b76 441 printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
uci1 1:e392595b4b76 442
uci1 1:e392595b4b76 443 if ( gEvent.IsForcedTrg() || gFirstEvt ||
uci1 1:e392595b4b76 444 (etms>gConf.GetEvtThrtlPeriodMs()) ) {
uci1 1:e392595b4b76 445
uci1 1:e392595b4b76 446 led2=1;
uci1 1:e392595b4b76 447
uci1 1:e392595b4b76 448 PIN_lockRegisters = 0; // done reading, unlock so we can talk to SD card.
uci1 1:e392595b4b76 449
uci1 1:e392595b4b76 450 SaveEvent(etms);
uci1 8:95a325df1f6b 451
uci1 3:24c5f0f50bf1 452 /*
uci1 1:e392595b4b76 453 } else {
uci1 1:e392595b4b76 454 printf("forced=%s, gFirstEvt=%s, e>t %d>%hu %s\r\n",
uci1 1:e392595b4b76 455 gEvent.IsForcedTrg()?"true":"false", gFirstEvt?"true":"false",
uci1 1:e392595b4b76 456 etms, gConf.GetEvtThrtlPeriodMs(),
uci1 1:e392595b4b76 457 etms>gConf.GetEvtThrtlPeriodMs() ? "true":"false");
uci1 3:24c5f0f50bf1 458 */
uci1 1:e392595b4b76 459 }
uci1 1:e392595b4b76 460 }
uci1 1:e392595b4b76 461 printf("past reading out\r\n");
uci1 1:e392595b4b76 462
uci1 1:e392595b4b76 463 led4=0; led2=0;
uci1 1:e392595b4b76 464
uci1 8:95a325df1f6b 465 // check the power?
uci1 8:95a325df1f6b 466 if (gCheckPower) {
uci1 8:95a325df1f6b 467 printf("call check power\r\n");
uci1 8:95a325df1f6b 468 CheckPower(false);
uci1 8:95a325df1f6b 469 }
uci1 8:95a325df1f6b 470
uci1 8:95a325df1f6b 471 // make new seq?
uci1 8:95a325df1f6b 472 if (IsSeqComplete()) {
uci1 10:3c93db1cfb12 473 printf("seq complete. sngseq=%d\r\n",gConf.IsSingleSeqRunMode());
uci1 8:95a325df1f6b 474 MakeOutputFile(gConf.IsSingleSeqRunMode());
uci1 8:95a325df1f6b 475 }
uci1 8:95a325df1f6b 476
uci1 8:95a325df1f6b 477 // open comm win?
uci1 0:664899e0b988 478 if (gOpenCommWin) {
uci1 1:e392595b4b76 479 printf("gOpenComWin=%s, opening\r\n",gOpenCommWin?"true":"false");
uci1 0:664899e0b988 480 OpenCommWin();
uci1 0:664899e0b988 481 gOpenCommWin=false;
uci1 1:e392595b4b76 482 } else {
uci1 1:e392595b4b76 483 printf("gOpenCommWin=false\r\n");
uci1 0:664899e0b988 484 }
uci1 0:664899e0b988 485 }
uci1 0:664899e0b988 486
uci1 0:664899e0b988 487 }
uci1 0:664899e0b988 488
uci1 0:664899e0b988 489 //
uci1 0:664899e0b988 490 // save the event
uci1 0:664899e0b988 491 //
uci1 0:664899e0b988 492 void SaveEvent(const int32_t etms) {
uci1 0:664899e0b988 493 // write the event
uci1 0:664899e0b988 494
uci1 3:24c5f0f50bf1 495 printf("save event\r\n");
uci1 3:24c5f0f50bf1 496
uci1 0:664899e0b988 497 // set the event number & dt
uci1 3:24c5f0f50bf1 498 gEvent.SetEvtNum(gEvtNum);
uci1 0:664899e0b988 499 gEvent.SetDTms(etms);
uci1 0:664899e0b988 500
uci1 0:664899e0b988 501 // save to SD
uci1 11:de443350ec4a 502 PIN_lockRegisters = 0; // unlock so we can talk to SD card.
uci1 1:e392595b4b76 503 SnSDUtils::WriteEventTo(SnSDUtils::GetCurFile(), gGenBuf, gEvent, gConf);
uci1 0:664899e0b988 504
uci1 0:664899e0b988 505 // reset
uci1 0:664899e0b988 506 gEvent.ClearEvent();
uci1 0:664899e0b988 507
uci1 3:24c5f0f50bf1 508 // increment event number
uci1 3:24c5f0f50bf1 509 ++gEvtNum;
uci1 3:24c5f0f50bf1 510
uci1 8:95a325df1f6b 511 printf("gEvtNum=%u\r\n",gEvtNum);
uci1 3:24c5f0f50bf1 512 }
uci1 3:24c5f0f50bf1 513
uci1 3:24c5f0f50bf1 514 void MakeOutputFile(const bool stopRunning) {
uci1 10:3c93db1cfb12 515 PIN_lockRegisters = 0; // unlock so we can talk to SD card.
uci1 10:3c93db1cfb12 516 printf("closing output file. gEvtNum=%u, gPowNum=%u, stop=%d\r\n",
uci1 10:3c93db1cfb12 517 gEvtNum,gPowNum,(int)stopRunning);
uci1 3:24c5f0f50bf1 518 SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
uci1 10:3c93db1cfb12 519 printf("file closed\r\n");
uci1 3:24c5f0f50bf1 520 if (stopRunning) {
uci1 8:95a325df1f6b 521 StopRunning();
uci1 0:664899e0b988 522 }
uci1 8:95a325df1f6b 523 FILE* cf = SnSDUtils::OpenNewOutputFile(gConf.GetMacAddress(),
uci1 8:95a325df1f6b 524 gConf.GetRun());
uci1 8:95a325df1f6b 525 if (cf!=0) {
uci1 8:95a325df1f6b 526 wait_ms(200);
uci1 8:95a325df1f6b 527 GetAvePowerReading();
uci1 8:95a325df1f6b 528 printf("writing power. v1=%g, v2=%g, r1=%g, r2=%g, t=%u, pownum=%u\r\n",
uci1 8:95a325df1f6b 529 gPower.GetAveV1(), gPower.GetAveV2(),
uci1 8:95a325df1f6b 530 gPower.GetRmsV1(), gPower.GetRmsV2(), gPower.GetTime(),
uci1 8:95a325df1f6b 531 gPowNum);
uci1 8:95a325df1f6b 532 SnSDUtils::WritePowerTo(cf, gPower, gPowNum);
uci1 8:95a325df1f6b 533 }
uci1 3:24c5f0f50bf1 534 printf("made output file with run %u\r\n",gConf.GetRun());
uci1 3:24c5f0f50bf1 535 printf("filename=%s\r\n",SnSDUtils::GetCurFileName());
uci1 3:24c5f0f50bf1 536 SnSDUtils::WriteConfig(SnSDUtils::GetCurFile(), gConf);
uci1 0:664899e0b988 537 }
uci1 0:664899e0b988 538
uci1 0:664899e0b988 539 //
uci1 4:a91682e19d6b 540 // power stuff
uci1 4:a91682e19d6b 541 //
uci1 4:a91682e19d6b 542 void SetPower(const bool isCommWin) {
uci1 8:95a325df1f6b 543 // TODO: turn on amps individually, when that's possible
uci1 4:a91682e19d6b 544 if (isCommWin) {
uci1 5:9cea89700c66 545 PIN_turn_on_system = gConf.GetPowPinSetting(SnConfigFrame::kCardComWin);
uci1 4:a91682e19d6b 546 wait_ms(10);
uci1 5:9cea89700c66 547 PIN_turn_on_amps = gConf.GetPowPinSetting(SnConfigFrame::kAmpsComWin);
uci1 4:a91682e19d6b 548 wait_ms(10);
uci1 5:9cea89700c66 549 PIN_iridSbd_power = gConf.GetPowPinSetting(SnConfigFrame::kIridComWin);
uci1 4:a91682e19d6b 550 wait_ms(10);
uci1 5:9cea89700c66 551 PIN_afar_power = gConf.GetPowPinSetting(SnConfigFrame::kAfarComWin);
uci1 4:a91682e19d6b 552 wait_ms(10);
uci1 4:a91682e19d6b 553 } else {
uci1 5:9cea89700c66 554 PIN_turn_on_system = gConf.GetPowPinSetting(SnConfigFrame::kCardDatTak);
uci1 4:a91682e19d6b 555 wait_ms(10);
uci1 5:9cea89700c66 556 PIN_turn_on_amps = gConf.GetPowPinSetting(SnConfigFrame::kAmpsDatTak);
uci1 4:a91682e19d6b 557 wait_ms(10);
uci1 5:9cea89700c66 558 PIN_iridSbd_power = gConf.GetPowPinSetting(SnConfigFrame::kIridDatTak);
uci1 4:a91682e19d6b 559 wait_ms(10);
uci1 5:9cea89700c66 560 PIN_afar_power = gConf.GetPowPinSetting(SnConfigFrame::kAfarDatTak);
uci1 4:a91682e19d6b 561 wait_ms(10);
uci1 4:a91682e19d6b 562 }
uci1 8:95a325df1f6b 563 wait(1);
uci1 6:6f002d202f59 564 printf("set power (iscom %d, pw %hhu): cards %d, amps %d, irid %d, afar %d\r\n",
uci1 6:6f002d202f59 565 isCommWin, gConf.GetPowerMode(), PIN_turn_on_system.read(), PIN_turn_on_amps.read(),
uci1 6:6f002d202f59 566 PIN_iridSbd_power.read(), PIN_afar_power.read());
uci1 4:a91682e19d6b 567 }
uci1 4:a91682e19d6b 568
uci1 4:a91682e19d6b 569 //
uci1 0:664899e0b988 570 // set configuration
uci1 0:664899e0b988 571 //
uci1 1:e392595b4b76 572 void SetConfigAndMakeOutputFile() {
uci1 1:e392595b4b76 573 printf("SetConfigAndMakeOutputFile\r\n");
uci1 1:e392595b4b76 574
uci1 0:664899e0b988 575 // restart watchdog
uci1 0:664899e0b988 576 Watchdog::kick(gConf.GetWatchdogPeriod());
uci1 0:664899e0b988 577
uci1 1:e392595b4b76 578 // block (thermal) triggers during configuration
uci1 1:e392595b4b76 579 PIN_enableThermTrig = 0;
uci1 1:e392595b4b76 580 PIN_ADC_CS = 1;
uci1 1:e392595b4b76 581 PIN_DoNotRestartAllClocks = 1;
uci1 1:e392595b4b76 582 PIN_forceTrigger = 0;
uci1 3:24c5f0f50bf1 583 PIN_heartbeat = 0;
uci1 1:e392595b4b76 584 wait_ms(20);
uci1 1:e392595b4b76 585
uci1 0:664899e0b988 586 // reset event, timers, trigger counters
uci1 10:3c93db1cfb12 587 ResetCountersClearEvt();
uci1 0:664899e0b988 588
uci1 8:95a325df1f6b 589 if (AreCardsPowered()) {
uci1 8:95a325df1f6b 590 // Set PLA value(s)
uci1 8:95a325df1f6b 591 PIN_spi.format( 16, 0 ); // change mode for DAC & PLA value setting
uci1 8:95a325df1f6b 592 PIN_spi.frequency(1000000);
uci1 8:95a325df1f6b 593 PIN_MajLogHiBit=1;
uci1 8:95a325df1f6b 594 PIN_MajLogLoBit=1;
uci1 8:95a325df1f6b 595 PIN_enableThermTrig=0;
uci1 0:664899e0b988 596
uci1 8:95a325df1f6b 597 uint16_t hi, lo;
uci1 8:95a325df1f6b 598 PIN_PLA_cs=1;
uci1 8:95a325df1f6b 599 wait(4);
uci1 8:95a325df1f6b 600 for (uint8_t pi=0; pi<kNplas; pi++) {
uci1 8:95a325df1f6b 601 if (pi < gConf.GetNumPlas()) {
uci1 8:95a325df1f6b 602 SnConfigFrame::GetHiLoPlas(gConf.GetPla(pi), hi, lo);
uci1 8:95a325df1f6b 603 PIN_spi.write(hi);
uci1 8:95a325df1f6b 604 PIN_spi.write(lo);
uci1 8:95a325df1f6b 605 printf("pla hi %hu, lo %hu\r\n",hi,lo);
uci1 8:95a325df1f6b 606 } else {
uci1 8:95a325df1f6b 607 PIN_spi.write(kNoTrigPla); // hi
uci1 8:95a325df1f6b 608 PIN_spi.write(kNoTrigPla); // lo
uci1 8:95a325df1f6b 609 printf("pla hi %hu, lo %hu\r\n",kNoTrigPla,kNoTrigPla);
uci1 8:95a325df1f6b 610 }
uci1 8:95a325df1f6b 611 Watchdog::kick();
uci1 0:664899e0b988 612 }
uci1 8:95a325df1f6b 613 wait(3);
uci1 8:95a325df1f6b 614 PIN_PLA_cs=0;
uci1 8:95a325df1f6b 615 wait(3);
uci1 0:664899e0b988 616
uci1 8:95a325df1f6b 617 // DAC values
uci1 8:95a325df1f6b 618 //
uci1 8:95a325df1f6b 619 // first 12 bits = DAC value
uci1 8:95a325df1f6b 620 // next 2 bits = DAC ID
uci1 8:95a325df1f6b 621 // last 2 bits = dFPGA ID
uci1 8:95a325df1f6b 622 //
uci1 8:95a325df1f6b 623 // But FPGA uses "gray encoding" which means only 1 bit
uci1 8:95a325df1f6b 624 // can change at a time (of the last 4 bits). So even tho
uci1 8:95a325df1f6b 625 // the card/dac# is encoded, the order is also important
uci1 8:95a325df1f6b 626 // 0000 (dac0,card0), 0001 (dac0,card1), 0011 (dac0,card3), 0010 (dac0,card2),
uci1 8:95a325df1f6b 627 // 0110 (dac1,card2), 0111 (dac1,card3), 0101 (dac1,card1), etc.
uci1 8:95a325df1f6b 628 printf("setting dacs\r\n");
uci1 8:95a325df1f6b 629 uint16_t dv=0;
uci1 8:95a325df1f6b 630 for (uint8_t i=0, gri=0; i<kTotDacs; i++) {
uci1 8:95a325df1f6b 631 // get the gray-codes for this iteration
uci1 8:95a325df1f6b 632 gri = SnBitUtils::binToGray(i);
uci1 8:95a325df1f6b 633
uci1 8:95a325df1f6b 634 // build bit word
uci1 8:95a325df1f6b 635 dv = static_cast<int>(gConf.GetDac(gri & 0x0003u, gri >> 2u));
uci1 8:95a325df1f6b 636 dv <<= 4u;
uci1 8:95a325df1f6b 637 dv |= gri;
uci1 8:95a325df1f6b 638
uci1 8:95a325df1f6b 639 printf("dac %04x\r\n",dv);
uci1 8:95a325df1f6b 640
uci1 8:95a325df1f6b 641 // send to FPGA
uci1 8:95a325df1f6b 642 PIN_start_fpga=1;
uci1 8:95a325df1f6b 643 PIN_spi.write(dv);
uci1 8:95a325df1f6b 644 PIN_start_fpga=0;
uci1 8:95a325df1f6b 645
uci1 8:95a325df1f6b 646 Watchdog::kick();
uci1 8:95a325df1f6b 647
uci1 8:95a325df1f6b 648 }
uci1 8:95a325df1f6b 649 printf("dacs set\r\n");
uci1 8:95a325df1f6b 650 wait_ms(20);
uci1 8:95a325df1f6b 651 } else {
uci1 8:95a325df1f6b 652 printf("cards off. skipping PLA and DAC setting\r\n");
uci1 0:664899e0b988 653 }
uci1 0:664899e0b988 654
uci1 0:664899e0b988 655 // Majority Logic Trigger selection (# of cards)
uci1 0:664899e0b988 656 SnBitUtils::SetChanNumBits(gConf.GetNumCardsMajLog() - 1u,
uci1 0:664899e0b988 657 PIN_MajLogHiBit, PIN_MajLogLoBit);
uci1 0:664899e0b988 658
uci1 0:664899e0b988 659 // Enable thermal trigger?
uci1 0:664899e0b988 660 PIN_enableThermTrig = gConf.IsThermTrigEnabled();
uci1 0:664899e0b988 661
uci1 0:664899e0b988 662 PIN_spi.format( 16, 1 ); // back to trigger mode
uci1 1:e392595b4b76 663 PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
uci1 1:e392595b4b76 664
uci1 8:95a325df1f6b 665 // make new output file
uci1 8:95a325df1f6b 666 // put after PLA/DAC, in case they affect the power readings
uci1 8:95a325df1f6b 667 wait_ms(200);
uci1 8:95a325df1f6b 668 MakeOutputFile();
uci1 8:95a325df1f6b 669
uci1 1:e392595b4b76 670 // force a trigger every...
uci1 8:95a325df1f6b 671 #ifdef USE_RTOS_TIMER
uci1 8:95a325df1f6b 672 const uint32_t ftp = resetTicker(gForceTicker, gConf.GetForceTrigPeriod(),
uci1 8:95a325df1f6b 673 kAbsMaxTimer);
uci1 8:95a325df1f6b 674 const uint32_t hbp = resetTicker(gHeartbeatTicker, gConf.GetHeartbeatPeriod(),
uci1 8:95a325df1f6b 675 kAbsMaxTimer);
uci1 8:95a325df1f6b 676 const uint32_t cwp = resetTicker(gCommWinTicker, gConf.GetCommWinPeriod(),
uci1 8:95a325df1f6b 677 kCommWinLongPrdTk);
uci1 8:95a325df1f6b 678 const uint32_t pcp = resetTicker(gPowerCheckTicker, gConf.GetVoltCheckPeriod(),
uci1 8:95a325df1f6b 679 kAbsMaxTimer);
uci1 8:95a325df1f6b 680 #else
uci1 8:95a325df1f6b 681 const uint32_t ftp = resetTicker(gForceTicker, gConf.GetForceTrigPeriod(),
uci1 8:95a325df1f6b 682 kAbsMaxTimer, &procForceTrigger);
uci1 8:95a325df1f6b 683 const uint32_t hbp = resetTicker(gHeartbeatTicker, gConf.GetHeartbeatPeriod(),
uci1 8:95a325df1f6b 684 kAbsMaxTimer, &procHeartbeat);
uci1 8:95a325df1f6b 685 const uint32_t cwp = resetTicker(gCommWinTicker, gConf.GetCommWinPeriod(),
uci1 8:95a325df1f6b 686 kCommWinLongPrdTk, &procCommWin);
uci1 8:95a325df1f6b 687 const uint32_t pcp = resetTicker(gPowerCheckTicker, gConf.GetVoltCheckPeriod(),
uci1 8:95a325df1f6b 688 kAbsMaxTimer, &procPowerCheck);
uci1 8:95a325df1f6b 689 #endif
uci1 8:95a325df1f6b 690 printf("attach force trig %u\r\n",ftp);
uci1 8:95a325df1f6b 691 printf("attach heart beat %u\r\n",hbp);
uci1 8:95a325df1f6b 692 printf("attach comm win %u\r\n",cwp);
uci1 8:95a325df1f6b 693 printf("attach power chk %u\r\n",pcp);
uci1 8:95a325df1f6b 694
uci1 8:95a325df1f6b 695 // TODO: change comm parameters
uci1 8:95a325df1f6b 696 /*
uci1 8:95a325df1f6b 697 printf("set comm params\r\n");
uci1 8:95a325df1f6b 698 for (uint8_t cc=0; cc<kNcomms; cc++) {
uci1 8:95a325df1f6b 699 if (gComms[cc]!=0) {
uci1 8:95a325df1f6b 700 gComms[cc]->Set(gConf);
uci1 8:95a325df1f6b 701 }
uci1 3:24c5f0f50bf1 702 }
uci1 8:95a325df1f6b 703 */
uci1 0:664899e0b988 704
uci1 0:664899e0b988 705 Watchdog::kick(); // don't reset!
uci1 8:95a325df1f6b 706
uci1 8:95a325df1f6b 707 printf("set config done\r\n");
uci1 0:664899e0b988 708 }
uci1 0:664899e0b988 709
uci1 0:664899e0b988 710 //
uci1 0:664899e0b988 711 // readout functions
uci1 0:664899e0b988 712 //
uci1 0:664899e0b988 713 void WaitTrigAndSendClock() {
uci1 1:e392595b4b76 714
uci1 1:e392595b4b76 715 printf("WaitTrigAndSendClock\r\n");
uci1 6:6f002d202f59 716 printf("wait trig: (pw %hhu): cards %d, amps %d, irid %d, afar %d\r\n",
uci1 6:6f002d202f59 717 gConf.GetPowerMode(), PIN_turn_on_system.read(), PIN_turn_on_amps.read(),
uci1 6:6f002d202f59 718 PIN_iridSbd_power.read(), PIN_afar_power.read());
uci1 8:95a325df1f6b 719 printf("cards powered=%d\r\n",(int)AreCardsPowered());
uci1 0:664899e0b988 720
uci1 8:95a325df1f6b 721 if (AreCardsPowered()) {
uci1 8:95a325df1f6b 722
uci1 8:95a325df1f6b 723 if (gFirstEvt==false) {
uci1 8:95a325df1f6b 724 PIN_DoNotRestartAllClocks = 0;
uci1 8:95a325df1f6b 725 wait_us(1);
uci1 8:95a325df1f6b 726 PIN_DoNotRestartAllClocks = 1;
uci1 8:95a325df1f6b 727 //led3 = !led3; // toggle send clock led
uci1 8:95a325df1f6b 728 } else {
uci1 8:95a325df1f6b 729 gFirstEvt = false;
uci1 8:95a325df1f6b 730 }
uci1 8:95a325df1f6b 731
uci1 8:95a325df1f6b 732 //
uci1 8:95a325df1f6b 733 // wait for a trigger here.
uci1 8:95a325df1f6b 734 //
uci1 8:95a325df1f6b 735 printf("starting wait for trig\r\n");
uci1 8:95a325df1f6b 736 gReadingOut = false; // this will allow forced triggers (see procForceTrigger())
uci1 8:95a325df1f6b 737 while ( PIN_a_sf_clk == 1 ) {
uci1 8:95a325df1f6b 738 if (gOpenCommWin || gCheckPower) {
uci1 8:95a325df1f6b 739 printf("break com=%d, pow=%d\r\n",gOpenCommWin,gCheckPower);
uci1 8:95a325df1f6b 740 return; // break out to open comms or check power
uci1 8:95a325df1f6b 741 }
uci1 0:664899e0b988 742 }
uci1 8:95a325df1f6b 743 printf("starting readout. force=%d, clk=%d\r\n",
uci1 8:95a325df1f6b 744 PIN_forceTrigger.read(), PIN_a_sf_clk.read());
uci1 8:95a325df1f6b 745 PIN_forceTrigger=0; // necessary for forced triggers, harmless for other triggers
uci1 8:95a325df1f6b 746 gReadingOut = true; // disallow new forced triggers
uci1 8:95a325df1f6b 747 //
uci1 8:95a325df1f6b 748 // collect data from daughter cards
uci1 8:95a325df1f6b 749 //
uci1 8:95a325df1f6b 750 // TODO: what if some card (set of channels) doesn't respond?
uci1 8:95a325df1f6b 751 // currently, will wait forever?
uci1 8:95a325df1f6b 752 // also, if ch1 is dead, will wait forever (due to FPGA code)
uci1 8:95a325df1f6b 753 for( uint8_t i = 0; i < kNsamps; i++ ) {
uci1 8:95a325df1f6b 754 if( PIN_a_sf_clk == 1 ) {
uci1 8:95a325df1f6b 755 if( i == 0 )
uci1 8:95a325df1f6b 756 wait_us( 1 );
uci1 8:95a325df1f6b 757
uci1 8:95a325df1f6b 758 PIN_ADC_CS = 0;
uci1 8:95a325df1f6b 759 PIN_spi.write( 0x00 );
uci1 8:95a325df1f6b 760 PIN_ADC_CS = 1;
uci1 8:95a325df1f6b 761 } else {
uci1 8:95a325df1f6b 762 i--;
uci1 8:95a325df1f6b 763 }
uci1 0:664899e0b988 764 }
uci1 8:95a325df1f6b 765 } else {
uci1 8:95a325df1f6b 766 // cards have no power. don't try reading out
uci1 8:95a325df1f6b 767 gReadingOut=false;
uci1 0:664899e0b988 768 }
uci1 0:664899e0b988 769 }
uci1 0:664899e0b988 770
uci1 0:664899e0b988 771 SnCommWin::ECommWinResult OpenCommWin() {
uci1 0:664899e0b988 772 // loop through each comm mode:
uci1 0:664899e0b988 773 // a) try to connect
uci1 0:664899e0b988 774 // b) if connected, listen for config
uci1 0:664899e0b988 775 // c) if config requests data, send it
uci1 3:24c5f0f50bf1 776
uci1 3:24c5f0f50bf1 777 gLastCommWin = time(0);
uci1 3:24c5f0f50bf1 778 if (gConf.GetCommWinDuration()==0) {
uci1 3:24c5f0f50bf1 779 // TODO: set min so this is not possible
uci1 3:24c5f0f50bf1 780 return SnCommWin::kOkNoMsg;
uci1 3:24c5f0f50bf1 781 }
uci1 0:664899e0b988 782
uci1 0:664899e0b988 783 gCommWinOpen = true;
uci1 0:664899e0b988 784 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 785
uci1 3:24c5f0f50bf1 786 printf("opening comm window at %d\r\n", (int32_t)gLastCommWin);
uci1 3:24c5f0f50bf1 787
uci1 3:24c5f0f50bf1 788 // close the file so that the data is all written out.
uci1 3:24c5f0f50bf1 789 // and open it back up at the beginning (for reading)
uci1 8:95a325df1f6b 790 printf("close & open file. gEvtNum=%u, gPowNum=%u\r\n",gEvtNum,gPowNum);
uci1 10:3c93db1cfb12 791 PIN_lockRegisters = 0; // unlock so we can talk to SD card.
uci1 3:24c5f0f50bf1 792 SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
uci1 3:24c5f0f50bf1 793 SnSDUtils::OpenExistingFile(SnSDUtils::GetCurFileName(), true);
uci1 0:664899e0b988 794
uci1 4:a91682e19d6b 795 // (probably) power down cards,amps and power up comms
uci1 4:a91682e19d6b 796 SetPower(true);
uci1 0:664899e0b988 797
uci1 0:664899e0b988 798 const uint32_t conto = (gConf.GetCommWinDuration() < kConnectTimeout) ?
uci1 0:664899e0b988 799 gConf.GetCommWinDuration() : kConnectTimeout;
uci1 0:664899e0b988 800 const uint32_t listo = (gConf.GetCommWinDuration() < kListenTimeout) ?
uci1 0:664899e0b988 801 gConf.GetCommWinDuration() : kListenTimeout;
uci1 0:664899e0b988 802
uci1 0:664899e0b988 803 SnCommWin::ECommWinResult res = SnCommWin::kUndefFail;
uci1 0:664899e0b988 804
uci1 1:e392595b4b76 805 bool gotNewConfig=false;
uci1 1:e392595b4b76 806 bool sendStat[kNcomms];
uci1 1:e392595b4b76 807 for (uint8_t i=0; i<kNcomms; i++) {
uci1 1:e392595b4b76 808 sendStat[i]=true;
uci1 1:e392595b4b76 809 }
uci1 1:e392595b4b76 810 bool* ss = sendStat;
uci1 0:664899e0b988 811 SnCommWin** cw = gComms;
uci1 1:e392595b4b76 812 for (uint8_t i=0; ((time(0)-gLastCommWin)<gConf.GetCommWinDuration()); i++, cw++, ss++) {
uci1 1:e392595b4b76 813 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 814 if (i==kNcomms) {
uci1 1:e392595b4b76 815 i=0;
uci1 1:e392595b4b76 816 cw = gComms;
uci1 1:e392595b4b76 817 ss = sendStat;
uci1 1:e392595b4b76 818 }
uci1 7:079617408fec 819 if ((*cw)==0) {
uci1 7:079617408fec 820 continue;
uci1 7:079617408fec 821 }
uci1 0:664899e0b988 822 // open window and (mabye) send status update
uci1 1:e392595b4b76 823 printf("calling OpenWindow. ss=%d\r\n",(int)(*ss));
uci1 1:e392595b4b76 824 printf("gtt=%u, ct=%d, lcw=%d, dur=%u\r\n",GetTimeoutTime(gLastCommWin,conto),
uci1 1:e392595b4b76 825 time(0), gLastCommWin, gConf.GetCommWinDuration());
uci1 8:95a325df1f6b 826 // update power reading in case we want to send it in status
uci1 8:95a325df1f6b 827 GetAvePowerReading();
uci1 10:3c93db1cfb12 828 // get the trigger rates
uci1 10:3c93db1cfb12 829 float thmrate=0, evtrate=0;
uci1 10:3c93db1cfb12 830 GetRates(thmrate, evtrate);
uci1 0:664899e0b988 831 const SnCommWin::ECommWinResult conres = (*cw)->OpenWindow(
uci1 10:3c93db1cfb12 832 GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gEvent, gPower,
uci1 10:3c93db1cfb12 833 SnSDUtils::GetCurSeqNum(), thmrate, evtrate,
uci1 10:3c93db1cfb12 834 gGenBuf);
uci1 0:664899e0b988 835 if (conres>=SnCommWin::kConnected) {
uci1 1:e392595b4b76 836 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 837 // connected. listen for config
uci1 1:e392595b4b76 838 *ss = false; // don't send status next time
uci1 0:664899e0b988 839 const SnCommWin::ECommWinResult cfgres = (*cw)->GetConfig(
uci1 3:24c5f0f50bf1 840 gConf, GetTimeoutTime(gLastCommWin, listo), gGenBuf, gBufSize);
uci1 0:664899e0b988 841 if (cfgres>=SnCommWin::kOkWithMsg) {
uci1 1:e392595b4b76 842 Watchdog::kick(); // don't reset!
uci1 8:95a325df1f6b 843 printf("received config!\r\n");
uci1 0:664899e0b988 844 // send data if need be (files, some events, etc)
uci1 3:24c5f0f50bf1 845 printf("send data = %d\r\n", gConf.GetCommSendData());
uci1 0:664899e0b988 846 if (gConf.GetCommSendData()!=0) {
uci1 3:24c5f0f50bf1 847 printf("sending data\r\n");
uci1 8:95a325df1f6b 848 res = (*cw)->SendData(gConf, gEvent, gPower, gGenBuf, gBufSize,
uci1 1:e392595b4b76 849 GetTimeoutTime(gLastCommWin, gConf.GetCommWinDuration()));
uci1 0:664899e0b988 850 } else {
uci1 0:664899e0b988 851 // don't send anything
uci1 0:664899e0b988 852 res = cfgres;
uci1 0:664899e0b988 853 }
uci1 1:e392595b4b76 854 printf("Got config!\r\n");
uci1 1:e392595b4b76 855 gotNewConfig=true;
uci1 1:e392595b4b76 856 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 857 break;
uci1 0:664899e0b988 858 }
uci1 0:664899e0b988 859 }
uci1 0:664899e0b988 860
uci1 0:664899e0b988 861 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 862
uci1 0:664899e0b988 863 }
uci1 0:664899e0b988 864
uci1 4:a91682e19d6b 865 // (probably) power down comms and power up cards,amps
uci1 4:a91682e19d6b 866 SetPower(false);
uci1 4:a91682e19d6b 867
uci1 1:e392595b4b76 868 gFirstEvt = true;
uci1 4:a91682e19d6b 869
uci1 1:e392595b4b76 870 // reset config with system powered (for DAC/PLA setting)
uci1 1:e392595b4b76 871 if (gotNewConfig) {
uci1 1:e392595b4b76 872 printf("calling SetConfigAndMakeOutputFile\r\n");
uci1 1:e392595b4b76 873 SetConfigAndMakeOutputFile();
uci1 1:e392595b4b76 874 // TODO: remove
uci1 1:e392595b4b76 875 }
uci1 1:e392595b4b76 876 printf("closing comm win at %d\r\n",(int32_t)time(0));
uci1 1:e392595b4b76 877
uci1 0:664899e0b988 878 gCommWinOpen = false;
uci1 0:664899e0b988 879 return res;
uci1 0:664899e0b988 880 }