Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Thu Aug 09 02:16:08 2012 +0000
Revision:
9:a1a39573dd43
Parent:
8:95a325df1f6b
Child:
10:3c93db1cfb12
Same as Rev8, but the rms values in power readings are actually the square root of the variance

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