Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Thu Aug 02 05:42:47 2012 +0000
Revision:
4:a91682e19d6b
Parent:
3:24c5f0f50bf1
Child:
5:9cea89700c66
Add power reading, once per file. Prevent seq number from wrapping around. Still many debugging messages. Communications not finished.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
uci1 0:664899e0b988 1 #include "mbed.h"
uci1 0:664899e0b988 2
uci1 0:664899e0b988 3 #include <stdint.h>
uci1 0:664899e0b988 4 #include "SDFileSystem.h"
uci1 0:664899e0b988 5 #include "MODSERIAL.h"
uci1 0:664899e0b988 6 #include "Watchdog.h"
uci1 0:664899e0b988 7 #include "SnConstants.h"
uci1 0:664899e0b988 8 #include "SnBitUtils.h"
uci1 0:664899e0b988 9 #include "SnSDUtils.h"
uci1 0:664899e0b988 10 #include "SnConfigFrame.h"
uci1 0:664899e0b988 11 #include "SnEventFrame.h"
uci1 0:664899e0b988 12 #include "SnStatusFrame.h"
uci1 2:e67f7c158087 13 #include "SnHeaderFrame.h"
uci1 0:664899e0b988 14 #include "SnCommWin.h"
uci1 0:664899e0b988 15 #include "SnCommAfar.h"
uci1 0:664899e0b988 16 #include "SnCommUsb.h"
uci1 1:e392595b4b76 17 #include "SnBase64.h"
uci1 0:664899e0b988 18
uci1 0:664899e0b988 19 //
uci1 0:664899e0b988 20 // MBED PINS (ordered by number)
uci1 0:664899e0b988 21 //
uci1 0:664899e0b988 22 // leds (for debugging)
uci1 0:664899e0b988 23 DigitalOut led1(LED1);
uci1 0:664899e0b988 24 DigitalOut led2(LED2);
uci1 0:664899e0b988 25 DigitalOut led3(LED3);
uci1 0:664899e0b988 26 DigitalOut led4(LED4);
uci1 0:664899e0b988 27 // Set up power pins - Note that it's Zero for "on"
uci1 1:e392595b4b76 28 DigitalOut PIN_turn_on_system(p17); // this turns on system
uci1 0:664899e0b988 29 DigitalOut PIN_turn_on_amps(p25);
uci1 0:664899e0b988 30 // Activate/select chip by falling edge
uci1 0:664899e0b988 31 DigitalOut PIN_ADC_CS( p9 );
uci1 0:664899e0b988 32 // clock signal to activate PLA setting
uci1 0:664899e0b988 33 DigitalOut PIN_PLA_cs(p10);
uci1 0:664899e0b988 34 // To force a trigger
uci1 0:664899e0b988 35 DigitalOut PIN_forceTrigger(p11); //modification
uci1 0:664899e0b988 36 // To suppress thermal triggers
uci1 0:664899e0b988 37 DigitalOut PIN_enableThermTrig(p12);
uci1 0:664899e0b988 38 // Restart clock on all FPGAs.
uci1 0:664899e0b988 39 DigitalOut PIN_DoNotRestartAllClocks( p13 );
uci1 0:664899e0b988 40 // This tells the DFPGAs to store the data on motherboard FPGA and
uci1 0:664899e0b988 41 // read it out.
uci1 0:664899e0b988 42 DigitalIn PIN_a_sf_clk( p14 );
uci1 0:664899e0b988 43 DigitalIn PIN_rst_a_sf(p15);
uci1 1:e392595b4b76 44 // afar power
uci1 1:e392595b4b76 45 DigitalOut PIN_afar_power(p16);
uci1 4:a91682e19d6b 46 // batter voltage/current measurement
uci1 4:a91682e19d6b 47 AnalogIn PIN_vADC1(p19);
uci1 4:a91682e19d6b 48 AnalogIn PIN_vADC2(p18);
uci1 0:664899e0b988 49 // Lock daughter card registeres (during data readout).
uci1 0:664899e0b988 50 DigitalOut PIN_lockRegisters( p20 );
uci1 1:e392595b4b76 51 // iridium (SBD) power
uci1 1:e392595b4b76 52 DigitalOut PIN_iridSbd_power(p21);
uci1 0:664899e0b988 53 // Majority logic pins
uci1 0:664899e0b988 54 DigitalOut PIN_MajLogHiBit(p22);
uci1 0:664899e0b988 55 DigitalOut PIN_MajLogLoBit(p23);
uci1 0:664899e0b988 56 // Tell FPGA to be ready to accept DAC values
uci1 0:664899e0b988 57 DigitalOut PIN_start_fpga(p26);
uci1 0:664899e0b988 58 // Two bits to the select the daughter card for readout
uci1 0:664899e0b988 59 DigitalOut PIN_selCardHiBit( p29 );
uci1 0:664899e0b988 60 DigitalOut PIN_selCardLoBit( p30 );
uci1 0:664899e0b988 61 // To launch a heartbeat pulse
uci1 0:664899e0b988 62 DigitalOut PIN_heartbeat(p24);
uci1 0:664899e0b988 63 // Setup SPI pins
uci1 0:664899e0b988 64 SPI PIN_spi( p5, p6, p7 );
uci1 0:664899e0b988 65 // The SD card
uci1 3:24c5f0f50bf1 66
uci1 3:24c5f0f50bf1 67 // this needs to be first in case some other global uses a print statement
uci1 3:24c5f0f50bf1 68 static MODSERIAL gCpu( USBTX, USBRX ); // defined here so it might be used for debugging output
uci1 3:24c5f0f50bf1 69
uci1 0:664899e0b988 70 SDFileSystem sd(p5, p6, p7, p8, SnSDUtils::kSDsubDir+1);
uci1 0:664899e0b988 71 LocalFileSystem local("local");
uci1 0:664899e0b988 72
uci1 0:664899e0b988 73 //
uci1 0:664899e0b988 74 // fwd declare fcns
uci1 0:664899e0b988 75 //
uci1 0:664899e0b988 76 void ReadAllRegisters();
uci1 0:664899e0b988 77 void ReadRegister(const uint8_t chan, int16_t* dev);
uci1 0:664899e0b988 78 void SaveEvent(const int32_t etms);
uci1 0:664899e0b988 79 void WaitTrigAndSendClock();
uci1 1:e392595b4b76 80 void SetConfigAndMakeOutputFile();
uci1 0:664899e0b988 81 SnCommWin::ECommWinResult OpenCommWin();
uci1 3:24c5f0f50bf1 82 void MakeOutputFile(const bool stopRunning=false);
uci1 4:a91682e19d6b 83 void SetPower(const bool isCommWin);
uci1 0:664899e0b988 84
uci1 0:664899e0b988 85 //
uci1 0:664899e0b988 86 // globals
uci1 0:664899e0b988 87 //
uci1 0:664899e0b988 88 // readout objs
uci1 0:664899e0b988 89 static Ticker gForceTicker;
uci1 3:24c5f0f50bf1 90 static Ticker gHeartbeatTicker;
uci1 1:e392595b4b76 91 static Ticker gCommWinTicker;
uci1 0:664899e0b988 92 static Timer gEvtTimer;
uci1 0:664899e0b988 93 static SnConfigFrame gConf;
uci1 0:664899e0b988 94 static SnEventFrame gEvent;
uci1 0:664899e0b988 95 // parameters
uci1 0:664899e0b988 96 static bool gFirstEvt = true;
uci1 0:664899e0b988 97 static bool gReadingOut = false;
uci1 0:664899e0b988 98 static bool gCommWinOpen = false; // if it's open
uci1 1:e392595b4b76 99 static volatile bool gOpenCommWin = false; // if it should be opened
uci1 0:664899e0b988 100 static int32_t gEvtNum = 0; // num of evt written
uci1 0:664899e0b988 101 static int32_t gTrgNum[kNumTrgs] = {0}; // num of this type of trg received
uci1 0:664899e0b988 102 // i/o
uci1 1:e392595b4b76 103 static time_t gLastCommWin = 0;
uci1 3:24c5f0f50bf1 104 static const uint32_t gBufSize=SnStatusFrame::kMaxSizeOf + SnHeaderFrame::kMaxSizeOf;
uci1 3:24c5f0f50bf1 105 static const uint32_t gB64Bsize=BASE64ENC_LEN(gBufSize)+1;
uci1 3:24c5f0f50bf1 106 static char gB64Buf[gB64Bsize];
uci1 3:24c5f0f50bf1 107 static char gGenBuf[gBufSize]; // must be big enough for event or status or config!
uci1 1:e392595b4b76 108 //static SnCommWin* gComms[kNcomms] = { new SnCommAfar, new SnCommUsb(&gCpu) }; // order => priority
uci1 1:e392595b4b76 109 //static SnCommWin* gComms[kNcomms] = { new SnCommUsb(&gCpu) }; // order => priority
uci1 3:24c5f0f50bf1 110 static SnCommWin* gComms[kNcomms] = { new SnCommAfar(gB64Buf, gB64Bsize) }; // order => priority
uci1 0:664899e0b988 111
uci1 0:664899e0b988 112 void procForceTrigger() {
uci1 3:24c5f0f50bf1 113 led3=!led3;
uci1 0:664899e0b988 114 if (gReadingOut==false && gCommWinOpen==false) {
uci1 0:664899e0b988 115 gEvent.SetTrgBit(kFrcTrg);
uci1 0:664899e0b988 116 gEvent.SetTrgNum((gTrgNum[kFrcTrg])++);
uci1 0:664899e0b988 117 PIN_forceTrigger = 1; // force a trigger
uci1 0:664899e0b988 118 }
uci1 0:664899e0b988 119 }
uci1 0:664899e0b988 120
uci1 3:24c5f0f50bf1 121 void procHeartbeat() {
uci1 3:24c5f0f50bf1 122 if (gReadingOut==false && gCommWinOpen==false) {
uci1 3:24c5f0f50bf1 123 PIN_heartbeat = 1; // heartbeat pulse
uci1 3:24c5f0f50bf1 124 PIN_heartbeat = 0;
uci1 3:24c5f0f50bf1 125 }
uci1 3:24c5f0f50bf1 126 }
uci1 3:24c5f0f50bf1 127
uci1 0:664899e0b988 128 void procCommWin() {
uci1 0:664899e0b988 129 if (gReadingOut==false && gCommWinOpen==false) {
uci1 1:e392595b4b76 130 if ( (time(0) - gLastCommWin) > gConf.GetCommWinPeriod() ) {
uci1 1:e392595b4b76 131 led3=!led3;
uci1 1:e392595b4b76 132 gOpenCommWin = true;
uci1 1:e392595b4b76 133 }
uci1 0:664899e0b988 134 }
uci1 0:664899e0b988 135 }
uci1 0:664899e0b988 136
uci1 1:e392595b4b76 137 uint32_t GetTimeoutTime(const uint32_t startTime,
uci1 1:e392595b4b76 138 const uint32_t delta) {
uci1 1:e392595b4b76 139 const uint32_t lst = time(0)-startTime;
uci1 1:e392595b4b76 140 const uint32_t lio =
uci1 1:e392595b4b76 141 ((lst+delta) < gConf.GetCommWinDuration()) ?
uci1 1:e392595b4b76 142 lst+delta : gConf.GetCommWinDuration();
uci1 1:e392595b4b76 143 return lio+startTime;
uci1 1:e392595b4b76 144 }
uci1 1:e392595b4b76 145
uci1 0:664899e0b988 146
uci1 0:664899e0b988 147 // TODO: add block-id's to output file? (config block, event block, file header block, etc.)
uci1 0:664899e0b988 148
uci1 1:e392595b4b76 149 // TODO: HEARTBEAT!
uci1 1:e392595b4b76 150
uci1 1:e392595b4b76 151 // TODO: make websocket URL settable in the config (i.e. via SBD?)
uci1 1:e392595b4b76 152
uci1 0:664899e0b988 153 int main() {
uci1 1:e392595b4b76 154 {
uci1 2:e67f7c158087 155 led1=1; wait(0.2);
uci1 2:e67f7c158087 156 led1=0; led2=1; wait(0.2);
uci1 2:e67f7c158087 157 led2=0; led3=1; wait(0.2);
uci1 2:e67f7c158087 158 led3=0; led4=1; wait(0.2);
uci1 1:e392595b4b76 159 led4=0;
uci1 1:e392595b4b76 160 }
uci1 1:e392595b4b76 161
uci1 0:664899e0b988 162 led2=1;
uci1 0:664899e0b988 163 //wait_ms(100);
uci1 1:e392595b4b76 164
uci1 3:24c5f0f50bf1 165 printf("\n\n\n\n\n\nstarting\r\n");
uci1 1:e392595b4b76 166
uci1 0:664899e0b988 167 // a failsafe
uci1 0:664899e0b988 168 Watchdog::kick(kWDFailsafe);
uci1 0:664899e0b988 169
uci1 1:e392595b4b76 170 // set the clock to the BS time, if it's not set
uci1 1:e392595b4b76 171 if ( (static_cast<int32_t>(time(0)))<0 ) {
uci1 1:e392595b4b76 172 set_time(kBStime);
uci1 1:e392595b4b76 173 }
uci1 1:e392595b4b76 174 printf("time = %d\r\n",(int32_t)time(0));
uci1 1:e392595b4b76 175 gLastCommWin = time(0); // prevent comm win proc
uci1 0:664899e0b988 176
uci1 0:664899e0b988 177 gForceTicker.detach();
uci1 0:664899e0b988 178 gFirstEvt = true;
uci1 0:664899e0b988 179
uci1 4:a91682e19d6b 180 // (probably) power down comms and power up cards,amps
uci1 4:a91682e19d6b 181 SetPower(false);
uci1 4:a91682e19d6b 182
uci1 3:24c5f0f50bf1 183 printf("Using config %s\r\n",gConf.GetLabel());
uci1 1:e392595b4b76 184 SetConfigAndMakeOutputFile(); // setup defaults in case no communication
uci1 4:a91682e19d6b 185
uci1 0:664899e0b988 186 //
uci1 0:664899e0b988 187 // get config
uci1 0:664899e0b988 188 //
uci1 3:24c5f0f50bf1 189 //printf("open window\r\n");
uci1 2:e67f7c158087 190 OpenCommWin();
uci1 3:24c5f0f50bf1 191
uci1 0:664899e0b988 192 // get ready to trigger
uci1 0:664899e0b988 193 PIN_spi.format( 16, 1 ); // change to data readout format
uci1 0:664899e0b988 194
uci1 0:664899e0b988 195 led2=0;
uci1 0:664899e0b988 196
uci1 0:664899e0b988 197 // the main event loop. wait for triggers in SendClock
uci1 3:24c5f0f50bf1 198 gEvtTimer.start();
uci1 0:664899e0b988 199 while( true )
uci1 0:664899e0b988 200 {
uci1 0:664899e0b988 201 // in here, we wait for triggers from the MB-FPGA
uci1 0:664899e0b988 202 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 203
uci1 1:e392595b4b76 204 led1 = !led1;
uci1 1:e392595b4b76 205
uci1 1:e392595b4b76 206 printf("calling wait trig\r\n");
uci1 1:e392595b4b76 207 printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
uci1 1:e392595b4b76 208
uci1 0:664899e0b988 209 PIN_lockRegisters = 0; // allow data to come from DFPGA
uci1 0:664899e0b988 210 WaitTrigAndSendClock();
uci1 0:664899e0b988 211 PIN_lockRegisters = 1; // block registers during readout
uci1 1:e392595b4b76 212
uci1 3:24c5f0f50bf1 213 const int32_t etms = gEvtTimer.read_ms(); // time since last trigger
uci1 3:24c5f0f50bf1 214 gEvtTimer.reset(); gEvtTimer.start(); // start counter from this trigger
uci1 1:e392595b4b76 215
uci1 1:e392595b4b76 216 printf("wait trig send clock exited\r\n");
uci1 1:e392595b4b76 217
uci1 0:664899e0b988 218 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 219
uci1 1:e392595b4b76 220 if (gReadingOut) {
uci1 1:e392595b4b76 221 //
uci1 1:e392595b4b76 222 // got trigger. read registers to mbed and build the event
uci1 1:e392595b4b76 223 //
uci1 1:e392595b4b76 224
uci1 1:e392595b4b76 225 led4=1;
uci1 1:e392595b4b76 226 printf("readout\r\n");
uci1 1:e392595b4b76 227
uci1 1:e392595b4b76 228 // read data & calc CRC
uci1 1:e392595b4b76 229 gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit);
uci1 1:e392595b4b76 230 gEvent.SetCurMbedTime();
uci1 1:e392595b4b76 231 // TODO: no way to check for external trigger?
uci1 1:e392595b4b76 232 if (gEvent.IsForcedTrg()==false) {
uci1 1:e392595b4b76 233 gEvent.SetTrgBit(kThmTrg);
uci1 1:e392595b4b76 234 gEvent.SetTrgNum((gTrgNum[kThmTrg])++);
uci1 1:e392595b4b76 235 } // else already set by procForceTrigger
uci1 1:e392595b4b76 236 // (no need to calc if we throw this event away)
uci1 1:e392595b4b76 237
uci1 1:e392595b4b76 238 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 239
uci1 1:e392595b4b76 240 printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
uci1 1:e392595b4b76 241
uci1 1:e392595b4b76 242 if ( gEvent.IsForcedTrg() || gFirstEvt ||
uci1 1:e392595b4b76 243 (etms>gConf.GetEvtThrtlPeriodMs()) ) {
uci1 1:e392595b4b76 244
uci1 1:e392595b4b76 245 led2=1;
uci1 1:e392595b4b76 246
uci1 1:e392595b4b76 247 PIN_lockRegisters = 0; // done reading, unlock so we can talk to SD card.
uci1 1:e392595b4b76 248
uci1 1:e392595b4b76 249 SaveEvent(etms);
uci1 3:24c5f0f50bf1 250
uci1 3:24c5f0f50bf1 251 if (gEvtNum>=(gConf.GetFirstEvt()+gConf.GetEvtsPerFile())) {
uci1 3:24c5f0f50bf1 252 MakeOutputFile(gConf.IsSingleSeqRunMode());
uci1 3:24c5f0f50bf1 253 }
uci1 3:24c5f0f50bf1 254 /*
uci1 1:e392595b4b76 255 } else {
uci1 1:e392595b4b76 256 printf("forced=%s, gFirstEvt=%s, e>t %d>%hu %s\r\n",
uci1 1:e392595b4b76 257 gEvent.IsForcedTrg()?"true":"false", gFirstEvt?"true":"false",
uci1 1:e392595b4b76 258 etms, gConf.GetEvtThrtlPeriodMs(),
uci1 1:e392595b4b76 259 etms>gConf.GetEvtThrtlPeriodMs() ? "true":"false");
uci1 3:24c5f0f50bf1 260 */
uci1 1:e392595b4b76 261 }
uci1 1:e392595b4b76 262 }
uci1 1:e392595b4b76 263 printf("past reading out\r\n");
uci1 1:e392595b4b76 264
uci1 1:e392595b4b76 265 led4=0; led2=0;
uci1 1:e392595b4b76 266
uci1 0:664899e0b988 267 if (gOpenCommWin) {
uci1 1:e392595b4b76 268 printf("gOpenComWin=%s, opening\r\n",gOpenCommWin?"true":"false");
uci1 0:664899e0b988 269 OpenCommWin();
uci1 0:664899e0b988 270 gOpenCommWin=false;
uci1 1:e392595b4b76 271 } else {
uci1 1:e392595b4b76 272 printf("gOpenCommWin=false\r\n");
uci1 0:664899e0b988 273 }
uci1 0:664899e0b988 274 }
uci1 0:664899e0b988 275
uci1 0:664899e0b988 276 }
uci1 0:664899e0b988 277
uci1 0:664899e0b988 278 //
uci1 0:664899e0b988 279 // save the event
uci1 0:664899e0b988 280 //
uci1 0:664899e0b988 281 void SaveEvent(const int32_t etms) {
uci1 0:664899e0b988 282 // write the event
uci1 0:664899e0b988 283
uci1 3:24c5f0f50bf1 284 printf("save event\r\n");
uci1 3:24c5f0f50bf1 285
uci1 0:664899e0b988 286 // set the event number & dt
uci1 3:24c5f0f50bf1 287 gEvent.SetEvtNum(gEvtNum);
uci1 0:664899e0b988 288 gEvent.SetDTms(etms);
uci1 0:664899e0b988 289
uci1 0:664899e0b988 290 // save to SD
uci1 1:e392595b4b76 291 SnSDUtils::WriteEventTo(SnSDUtils::GetCurFile(), gGenBuf, gEvent, gConf);
uci1 0:664899e0b988 292
uci1 0:664899e0b988 293 // reset
uci1 0:664899e0b988 294 gEvent.ClearEvent();
uci1 0:664899e0b988 295
uci1 3:24c5f0f50bf1 296 // increment event number
uci1 3:24c5f0f50bf1 297 ++gEvtNum;
uci1 3:24c5f0f50bf1 298
uci1 1:e392595b4b76 299 printf("gEvtNum=%d\r\n",gEvtNum);
uci1 3:24c5f0f50bf1 300 }
uci1 3:24c5f0f50bf1 301
uci1 3:24c5f0f50bf1 302 void MakeOutputFile(const bool stopRunning) {
uci1 3:24c5f0f50bf1 303 SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
uci1 3:24c5f0f50bf1 304 if (stopRunning) {
uci1 2:e67f7c158087 305 while (true) {
uci1 1:e392595b4b76 306 led3 = 1; led4=1;
uci1 0:664899e0b988 307 wait(0.5);
uci1 1:e392595b4b76 308 led3 = 0; led4=0;
uci1 0:664899e0b988 309 wait(0.5);
uci1 1:e392595b4b76 310 Watchdog::kick();
uci1 0:664899e0b988 311 }
uci1 0:664899e0b988 312 }
uci1 3:24c5f0f50bf1 313 SnSDUtils::OpenNewOutputFile(gConf.GetMacAddress(),
uci1 4:a91682e19d6b 314 gConf.GetRun(),
uci1 4:a91682e19d6b 315 PIN_vADC1.read_u16(),
uci1 4:a91682e19d6b 316 PIN_vADC2.read_u16());
uci1 3:24c5f0f50bf1 317 printf("made output file with run %u\r\n",gConf.GetRun());
uci1 3:24c5f0f50bf1 318 printf("filename=%s\r\n",SnSDUtils::GetCurFileName());
uci1 3:24c5f0f50bf1 319 SnSDUtils::WriteConfig(SnSDUtils::GetCurFile(), gConf);
uci1 0:664899e0b988 320 }
uci1 0:664899e0b988 321
uci1 0:664899e0b988 322 //
uci1 4:a91682e19d6b 323 // power stuff
uci1 4:a91682e19d6b 324 //
uci1 4:a91682e19d6b 325 void SetPower(const bool isCommWin) {
uci1 4:a91682e19d6b 326 if (isCommWin) {
uci1 4:a91682e19d6b 327 PIN_turn_on_system = gConf.IsPoweredFor(SnConfigFrame::kCardComWin);
uci1 4:a91682e19d6b 328 wait_ms(10);
uci1 4:a91682e19d6b 329 PIN_turn_on_amps = gConf.IsPoweredFor(SnConfigFrame::kAmpsComWin);
uci1 4:a91682e19d6b 330 wait_ms(10);
uci1 4:a91682e19d6b 331 PIN_iridSbd_power = gConf.IsPoweredFor(SnConfigFrame::kIridComWin);
uci1 4:a91682e19d6b 332 wait_ms(10);
uci1 4:a91682e19d6b 333 PIN_afar_power = gConf.IsPoweredFor(SnConfigFrame::kAfarComWin);
uci1 4:a91682e19d6b 334 wait_ms(10);
uci1 4:a91682e19d6b 335 } else {
uci1 4:a91682e19d6b 336 PIN_turn_on_system = gConf.IsPoweredFor(SnConfigFrame::kCardDatTak);
uci1 4:a91682e19d6b 337 wait_ms(10);
uci1 4:a91682e19d6b 338 PIN_turn_on_amps = gConf.IsPoweredFor(SnConfigFrame::kAmpsDatTak);
uci1 4:a91682e19d6b 339 wait_ms(10);
uci1 4:a91682e19d6b 340 PIN_iridSbd_power = gConf.IsPoweredFor(SnConfigFrame::kIridDatTak);
uci1 4:a91682e19d6b 341 wait_ms(10);
uci1 4:a91682e19d6b 342 PIN_afar_power = gConf.IsPoweredFor(SnConfigFrame::kAfarDatTak);
uci1 4:a91682e19d6b 343 wait_ms(10);
uci1 4:a91682e19d6b 344 }
uci1 4:a91682e19d6b 345 }
uci1 4:a91682e19d6b 346
uci1 4:a91682e19d6b 347 //
uci1 0:664899e0b988 348 // set configuration
uci1 0:664899e0b988 349 //
uci1 1:e392595b4b76 350 void SetConfigAndMakeOutputFile() {
uci1 1:e392595b4b76 351 printf("SetConfigAndMakeOutputFile\r\n");
uci1 1:e392595b4b76 352
uci1 0:664899e0b988 353 // restart watchdog
uci1 0:664899e0b988 354 Watchdog::kick(gConf.GetWatchdogPeriod());
uci1 0:664899e0b988 355
uci1 1:e392595b4b76 356 // block (thermal) triggers during configuration
uci1 1:e392595b4b76 357 PIN_enableThermTrig = 0;
uci1 1:e392595b4b76 358 PIN_ADC_CS = 1;
uci1 1:e392595b4b76 359 PIN_DoNotRestartAllClocks = 1;
uci1 1:e392595b4b76 360 PIN_forceTrigger = 0;
uci1 3:24c5f0f50bf1 361 PIN_heartbeat = 0;
uci1 1:e392595b4b76 362 wait_ms(20);
uci1 1:e392595b4b76 363
uci1 0:664899e0b988 364 // reset event, timers, trigger counters
uci1 0:664899e0b988 365 gEvent.ClearEvent();
uci1 0:664899e0b988 366 gEvtNum = gConf.GetFirstEvt();
uci1 0:664899e0b988 367 memset(gTrgNum, 0, sizeof(int32_t)*kNumTrgs);
uci1 0:664899e0b988 368
uci1 0:664899e0b988 369 // make new output file
uci1 3:24c5f0f50bf1 370 MakeOutputFile();
uci1 0:664899e0b988 371
uci1 0:664899e0b988 372 // TODO: turn on amps individually, when that's possible
uci1 1:e392595b4b76 373 PIN_turn_on_amps = gConf.IsEachAmpOn() ? 0 : 1;
uci1 0:664899e0b988 374
uci1 0:664899e0b988 375 // Set PLA value(s)
uci1 0:664899e0b988 376 PIN_spi.format( 16, 0 ); // change mode for DAC & PLA value setting
uci1 1:e392595b4b76 377 PIN_spi.frequency(1000000);
uci1 0:664899e0b988 378 PIN_MajLogHiBit=1;
uci1 0:664899e0b988 379 PIN_MajLogLoBit=1;
uci1 0:664899e0b988 380 PIN_enableThermTrig=0;
uci1 0:664899e0b988 381
uci1 0:664899e0b988 382 uint16_t hi, lo;
uci1 0:664899e0b988 383 PIN_PLA_cs=1;
uci1 1:e392595b4b76 384 wait(4);
uci1 0:664899e0b988 385 for (uint8_t pi=0; pi<kNplas; pi++) {
uci1 0:664899e0b988 386 if (pi < gConf.GetNumPlas()) {
uci1 0:664899e0b988 387 SnConfigFrame::GetHiLoPlas(gConf.GetPla(pi), hi, lo);
uci1 0:664899e0b988 388 PIN_spi.write(hi);
uci1 0:664899e0b988 389 PIN_spi.write(lo);
uci1 3:24c5f0f50bf1 390 printf("pla hi %hu, lo %hu\r\n",hi,lo);
uci1 0:664899e0b988 391 } else {
uci1 0:664899e0b988 392 PIN_spi.write(kNoTrigPla); // hi
uci1 0:664899e0b988 393 PIN_spi.write(kNoTrigPla); // lo
uci1 3:24c5f0f50bf1 394 printf("pla hi %hu, lo %hu\r\n",kNoTrigPla,kNoTrigPla);
uci1 0:664899e0b988 395 }
uci1 1:e392595b4b76 396 Watchdog::kick();
uci1 0:664899e0b988 397 }
uci1 0:664899e0b988 398 wait(3);
uci1 0:664899e0b988 399 PIN_PLA_cs=0;
uci1 0:664899e0b988 400 wait(3);
uci1 0:664899e0b988 401
uci1 0:664899e0b988 402 // DAC values
uci1 0:664899e0b988 403 //
uci1 0:664899e0b988 404 // first 12 bits = DAC value
uci1 0:664899e0b988 405 // next 2 bits = DAC ID
uci1 0:664899e0b988 406 // last 2 bits = dFPGA ID
uci1 0:664899e0b988 407 //
uci1 0:664899e0b988 408 // But FPGA uses "gray encoding" which means only 1 bit
uci1 0:664899e0b988 409 // can change at a time (of the last 4 bits). So even tho
uci1 0:664899e0b988 410 // the card/dac# is encoded, the order is also important
uci1 0:664899e0b988 411 // 0000 (dac0,card0), 0001 (dac0,card1), 0011 (dac0,card3), 0010 (dac0,card2),
uci1 0:664899e0b988 412 // 0110 (dac1,card2), 0111 (dac1,card3), 0101 (dac1,card1), etc.
uci1 1:e392595b4b76 413 printf("setting dacs\r\n");
uci1 1:e392595b4b76 414 uint16_t dv=0;
uci1 0:664899e0b988 415 for (uint8_t i=0, gri=0; i<kTotDacs; i++) {
uci1 0:664899e0b988 416 // get the gray-codes for this iteration
uci1 0:664899e0b988 417 gri = SnBitUtils::binToGray(i);
uci1 0:664899e0b988 418
uci1 0:664899e0b988 419 // build bit word
uci1 0:664899e0b988 420 dv = static_cast<int>(gConf.GetDac(gri & 0x0003u, gri >> 2u));
uci1 0:664899e0b988 421 dv <<= 4u;
uci1 0:664899e0b988 422 dv |= gri;
uci1 0:664899e0b988 423
uci1 1:e392595b4b76 424 printf("dac %04x\r\n",dv);
uci1 1:e392595b4b76 425
uci1 0:664899e0b988 426 // send to FPGA
uci1 0:664899e0b988 427 PIN_start_fpga=1;
uci1 0:664899e0b988 428 PIN_spi.write(dv);
uci1 0:664899e0b988 429 PIN_start_fpga=0;
uci1 1:e392595b4b76 430
uci1 1:e392595b4b76 431 Watchdog::kick();
uci1 1:e392595b4b76 432
uci1 0:664899e0b988 433 }
uci1 1:e392595b4b76 434 printf("dacs set\r\n");
uci1 0:664899e0b988 435 wait_ms(20);
uci1 0:664899e0b988 436
uci1 0:664899e0b988 437 // Majority Logic Trigger selection (# of cards)
uci1 0:664899e0b988 438 SnBitUtils::SetChanNumBits(gConf.GetNumCardsMajLog() - 1u,
uci1 0:664899e0b988 439 PIN_MajLogHiBit, PIN_MajLogLoBit);
uci1 0:664899e0b988 440
uci1 0:664899e0b988 441 // Enable thermal trigger?
uci1 0:664899e0b988 442 PIN_enableThermTrig = gConf.IsThermTrigEnabled();
uci1 0:664899e0b988 443
uci1 0:664899e0b988 444 PIN_spi.format( 16, 1 ); // back to trigger mode
uci1 1:e392595b4b76 445 PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
uci1 1:e392595b4b76 446
uci1 1:e392595b4b76 447 // force a trigger every...
uci1 1:e392595b4b76 448 gForceTicker.detach();
uci1 3:24c5f0f50bf1 449 if (gConf.GetForceTrigPeriod()>0) {
uci1 3:24c5f0f50bf1 450 gForceTicker.attach(&procForceTrigger,
uci1 3:24c5f0f50bf1 451 gConf.GetForceTrigPeriod() > kAbsMaxTimer ?
uci1 3:24c5f0f50bf1 452 kAbsMaxTimer : gConf.GetForceTrigPeriod()); // force period has a maximum
uci1 3:24c5f0f50bf1 453 }
uci1 3:24c5f0f50bf1 454 // heartbeat every ...
uci1 3:24c5f0f50bf1 455 gHeartbeatTicker.detach();
uci1 3:24c5f0f50bf1 456 if (gConf.GetHeartbeatPeriod()>0) {
uci1 3:24c5f0f50bf1 457 gHeartbeatTicker.attach(&procHeartbeat,
uci1 3:24c5f0f50bf1 458 gConf.GetHeartbeatPeriod() > kAbsMaxTimer ?
uci1 3:24c5f0f50bf1 459 kAbsMaxTimer : gConf.GetHeartbeatPeriod());
uci1 3:24c5f0f50bf1 460 }
uci1 1:e392595b4b76 461 // proc a comm win every...
uci1 1:e392595b4b76 462 gCommWinTicker.detach();
uci1 1:e392595b4b76 463 gCommWinTicker.attach(&procCommWin,
uci1 1:e392595b4b76 464 gConf.GetCommWinPeriod() > kAbsMaxTimer ?
uci1 1:e392595b4b76 465 kCommWinLongPrdTk : gConf.GetCommWinPeriod()); // periodic check if above max
uci1 1:e392595b4b76 466 printf("attach comm win ticker %u\r\n",
uci1 1:e392595b4b76 467 gConf.GetCommWinPeriod() > kAbsMaxTimer ?
uci1 1:e392595b4b76 468 kCommWinLongPrdTk : gConf.GetCommWinPeriod());
uci1 0:664899e0b988 469
uci1 0:664899e0b988 470 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 471
uci1 0:664899e0b988 472 }
uci1 0:664899e0b988 473
uci1 0:664899e0b988 474 //
uci1 0:664899e0b988 475 // readout functions
uci1 0:664899e0b988 476 //
uci1 0:664899e0b988 477 void WaitTrigAndSendClock() {
uci1 1:e392595b4b76 478
uci1 1:e392595b4b76 479 printf("WaitTrigAndSendClock\r\n");
uci1 1:e392595b4b76 480
uci1 0:664899e0b988 481 if (gFirstEvt==false) {
uci1 0:664899e0b988 482 PIN_DoNotRestartAllClocks = 0;
uci1 0:664899e0b988 483 wait_us(1);
uci1 0:664899e0b988 484 PIN_DoNotRestartAllClocks = 1;
uci1 0:664899e0b988 485 //led3 = !led3; // toggle send clock led
uci1 0:664899e0b988 486 } else {
uci1 0:664899e0b988 487 gFirstEvt = false;
uci1 0:664899e0b988 488 }
uci1 0:664899e0b988 489
uci1 0:664899e0b988 490 //
uci1 0:664899e0b988 491 // wait for a trigger here.
uci1 0:664899e0b988 492 //
uci1 0:664899e0b988 493 gReadingOut = false; // this will allow forced triggers (see procForceTrigger())
uci1 0:664899e0b988 494 while ( PIN_a_sf_clk == 1 ) {
uci1 0:664899e0b988 495 if (gOpenCommWin) {
uci1 1:e392595b4b76 496 return; // break out to open comms
uci1 0:664899e0b988 497 }
uci1 0:664899e0b988 498 }
uci1 0:664899e0b988 499 PIN_forceTrigger=0; // necessary for forced triggers, harmless for other triggers
uci1 0:664899e0b988 500 gReadingOut = true; // disallow new forced triggers
uci1 0:664899e0b988 501 //
uci1 0:664899e0b988 502 // collect data from daughter cards
uci1 0:664899e0b988 503 //
uci1 0:664899e0b988 504 // TODO: what if some card (set of channels) doesn't respond?
uci1 0:664899e0b988 505 // currently, will wait forever?
uci1 0:664899e0b988 506 // also, if ch1 is dead, will wait forever (due to FPGA code)
uci1 0:664899e0b988 507
uci1 0:664899e0b988 508 for( uint8_t i = 0; i < kNsamps; i++ ) {
uci1 0:664899e0b988 509 if( PIN_a_sf_clk == 1 ) {
uci1 0:664899e0b988 510 if( i == 0 )
uci1 0:664899e0b988 511 wait_us( 1 );
uci1 0:664899e0b988 512
uci1 0:664899e0b988 513 PIN_ADC_CS = 0;
uci1 0:664899e0b988 514 PIN_spi.write( 0x00 );
uci1 0:664899e0b988 515 PIN_ADC_CS = 1;
uci1 0:664899e0b988 516 } else {
uci1 0:664899e0b988 517 i--;
uci1 0:664899e0b988 518 }
uci1 0:664899e0b988 519 }
uci1 0:664899e0b988 520
uci1 0:664899e0b988 521 }
uci1 0:664899e0b988 522
uci1 0:664899e0b988 523 SnCommWin::ECommWinResult OpenCommWin() {
uci1 0:664899e0b988 524 // loop through each comm mode:
uci1 0:664899e0b988 525 // a) try to connect
uci1 0:664899e0b988 526 // b) if connected, listen for config
uci1 0:664899e0b988 527 // c) if config requests data, send it
uci1 3:24c5f0f50bf1 528
uci1 3:24c5f0f50bf1 529 gLastCommWin = time(0);
uci1 3:24c5f0f50bf1 530 if (gConf.GetCommWinDuration()==0) {
uci1 3:24c5f0f50bf1 531 // TODO: set min so this is not possible
uci1 3:24c5f0f50bf1 532 return SnCommWin::kOkNoMsg;
uci1 3:24c5f0f50bf1 533 }
uci1 0:664899e0b988 534
uci1 0:664899e0b988 535 gCommWinOpen = true;
uci1 0:664899e0b988 536 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 537
uci1 3:24c5f0f50bf1 538 printf("opening comm window at %d\r\n", (int32_t)gLastCommWin);
uci1 3:24c5f0f50bf1 539
uci1 3:24c5f0f50bf1 540 // close the file so that the data is all written out.
uci1 3:24c5f0f50bf1 541 // and open it back up at the beginning (for reading)
uci1 3:24c5f0f50bf1 542 SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
uci1 3:24c5f0f50bf1 543 SnSDUtils::OpenExistingFile(SnSDUtils::GetCurFileName(), true);
uci1 0:664899e0b988 544
uci1 4:a91682e19d6b 545 // (probably) power down cards,amps and power up comms
uci1 4:a91682e19d6b 546 SetPower(true);
uci1 0:664899e0b988 547
uci1 0:664899e0b988 548 const uint32_t conto = (gConf.GetCommWinDuration() < kConnectTimeout) ?
uci1 0:664899e0b988 549 gConf.GetCommWinDuration() : kConnectTimeout;
uci1 0:664899e0b988 550 const uint32_t listo = (gConf.GetCommWinDuration() < kListenTimeout) ?
uci1 0:664899e0b988 551 gConf.GetCommWinDuration() : kListenTimeout;
uci1 0:664899e0b988 552
uci1 0:664899e0b988 553 SnCommWin::ECommWinResult res = SnCommWin::kUndefFail;
uci1 0:664899e0b988 554
uci1 1:e392595b4b76 555 bool gotNewConfig=false;
uci1 1:e392595b4b76 556 bool sendStat[kNcomms];
uci1 1:e392595b4b76 557 for (uint8_t i=0; i<kNcomms; i++) {
uci1 1:e392595b4b76 558 sendStat[i]=true;
uci1 1:e392595b4b76 559 }
uci1 1:e392595b4b76 560 bool* ss = sendStat;
uci1 0:664899e0b988 561 SnCommWin** cw = gComms;
uci1 1:e392595b4b76 562 for (uint8_t i=0; ((time(0)-gLastCommWin)<gConf.GetCommWinDuration()); i++, cw++, ss++) {
uci1 1:e392595b4b76 563 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 564 if (i==kNcomms) {
uci1 1:e392595b4b76 565 i=0;
uci1 1:e392595b4b76 566 cw = gComms;
uci1 1:e392595b4b76 567 ss = sendStat;
uci1 1:e392595b4b76 568 }
uci1 0:664899e0b988 569 // open window and (mabye) send status update
uci1 1:e392595b4b76 570 printf("calling OpenWindow. ss=%d\r\n",(int)(*ss));
uci1 1:e392595b4b76 571 printf("gtt=%u, ct=%d, lcw=%d, dur=%u\r\n",GetTimeoutTime(gLastCommWin,conto),
uci1 1:e392595b4b76 572 time(0), gLastCommWin, gConf.GetCommWinDuration());
uci1 0:664899e0b988 573 const SnCommWin::ECommWinResult conres = (*cw)->OpenWindow(
uci1 2:e67f7c158087 574 GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gEvent, gGenBuf);
uci1 0:664899e0b988 575 if (conres>=SnCommWin::kConnected) {
uci1 1:e392595b4b76 576 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 577 // connected. listen for config
uci1 1:e392595b4b76 578 *ss = false; // don't send status next time
uci1 0:664899e0b988 579 const SnCommWin::ECommWinResult cfgres = (*cw)->GetConfig(
uci1 3:24c5f0f50bf1 580 gConf, GetTimeoutTime(gLastCommWin, listo), gGenBuf, gBufSize);
uci1 0:664899e0b988 581 if (cfgres>=SnCommWin::kOkWithMsg) {
uci1 1:e392595b4b76 582 Watchdog::kick(); // don't reset!
uci1 3:24c5f0f50bf1 583 printf("received config (%u)!\r\n",gConf.SizeOf());
uci1 1:e392595b4b76 584 char* b = gGenBuf;
uci1 1:e392595b4b76 585 gConf.WriteTo(b);
uci1 3:24c5f0f50bf1 586 const uint32_t csz = gConf.SizeOf();
uci1 3:24c5f0f50bf1 587 for (uint32_t i=0; i<csz; i++) {
uci1 1:e392595b4b76 588 printf("%02x ",gGenBuf[i]);
uci1 1:e392595b4b76 589 }
uci1 1:e392595b4b76 590 printf("\r\n");
uci1 0:664899e0b988 591 // send data if need be (files, some events, etc)
uci1 3:24c5f0f50bf1 592 printf("send data = %d\r\n", gConf.GetCommSendData());
uci1 0:664899e0b988 593 if (gConf.GetCommSendData()!=0) {
uci1 3:24c5f0f50bf1 594 printf("sending data\r\n");
uci1 3:24c5f0f50bf1 595 res = (*cw)->SendData(gConf, gEvent, gGenBuf, gBufSize,
uci1 1:e392595b4b76 596 GetTimeoutTime(gLastCommWin, gConf.GetCommWinDuration()));
uci1 0:664899e0b988 597 } else {
uci1 0:664899e0b988 598 // don't send anything
uci1 0:664899e0b988 599 res = cfgres;
uci1 0:664899e0b988 600 }
uci1 1:e392595b4b76 601 printf("Got config!\r\n");
uci1 1:e392595b4b76 602 gotNewConfig=true;
uci1 1:e392595b4b76 603 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 604 break;
uci1 0:664899e0b988 605 }
uci1 0:664899e0b988 606 }
uci1 0:664899e0b988 607
uci1 0:664899e0b988 608 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 609
uci1 0:664899e0b988 610 }
uci1 0:664899e0b988 611
uci1 4:a91682e19d6b 612 // (probably) power down comms and power up cards,amps
uci1 4:a91682e19d6b 613 SetPower(false);
uci1 4:a91682e19d6b 614
uci1 1:e392595b4b76 615 gFirstEvt = true;
uci1 4:a91682e19d6b 616
uci1 1:e392595b4b76 617 // reset config with system powered (for DAC/PLA setting)
uci1 1:e392595b4b76 618 if (gotNewConfig) {
uci1 1:e392595b4b76 619 printf("calling SetConfigAndMakeOutputFile\r\n");
uci1 1:e392595b4b76 620 SetConfigAndMakeOutputFile();
uci1 1:e392595b4b76 621 // TODO: remove
uci1 1:e392595b4b76 622 }
uci1 1:e392595b4b76 623 printf("closing comm win at %d\r\n",(int32_t)time(0));
uci1 1:e392595b4b76 624
uci1 0:664899e0b988 625 gCommWinOpen = false;
uci1 0:664899e0b988 626 return res;
uci1 0:664899e0b988 627 }