Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Wed Aug 08 23:27:37 2012 +0000
Revision:
8:95a325df1f6b
Parent:
7:079617408fec
Child:
9:a1a39573dd43
Check power for low pow running. Average power over 500 readings. Use RTOS timers instead of tickers. Allow data taking of events, power readings or both, even if cards are off. Bug in EthernetInterface prevents IPs being reset. Lots of debug output.

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