Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Tue Jul 31 04:59:16 2012 +0000
Revision:
3:24c5f0f50bf1
Parent:
2:e67f7c158087
Child:
4:a91682e19d6b
Test bench version. Communications not completed. Debugging output present. But will read the local config file and save events that can be used for testing.

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