Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Fri Aug 10 18:35:43 2012 +0000
Revision:
10:3c93db1cfb12
Parent:
9:a1a39573dd43
Child:
11:de443350ec4a
Ensure that lockRegisters (p20) is 0 before accessing the SD card, for example when closing the file. This fixes an issue seen when running in power count mode. Communications still under dev. Many debug outputs.

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