Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Fri Jul 20 19:04:02 2012 +0000
Revision:
1:e392595b4b76
Parent:
0:664899e0b988
Child:
2:e67f7c158087
many features checked and working. afar implemented. sending of data not yet tested. contains many debug prints

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