Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Fri Aug 03 00:04:34 2012 +0000
Revision:
5:9cea89700c66
Parent:
4:a91682e19d6b
Child:
6:6f002d202f59
Bug fix to power: set 0 for cards and amps if on. Still working on communications. Many debug printouts.

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 5:9cea89700c66 208 printf("readingout=%d\r\n",(int)gReadingOut);
uci1 1:e392595b4b76 209
uci1 0:664899e0b988 210 PIN_lockRegisters = 0; // allow data to come from DFPGA
uci1 0:664899e0b988 211 WaitTrigAndSendClock();
uci1 0:664899e0b988 212 PIN_lockRegisters = 1; // block registers during readout
uci1 1:e392595b4b76 213
uci1 3:24c5f0f50bf1 214 const int32_t etms = gEvtTimer.read_ms(); // time since last trigger
uci1 3:24c5f0f50bf1 215 gEvtTimer.reset(); gEvtTimer.start(); // start counter from this trigger
uci1 1:e392595b4b76 216
uci1 1:e392595b4b76 217 printf("wait trig send clock exited\r\n");
uci1 1:e392595b4b76 218
uci1 0:664899e0b988 219 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 220
uci1 1:e392595b4b76 221 if (gReadingOut) {
uci1 1:e392595b4b76 222 //
uci1 1:e392595b4b76 223 // got trigger. read registers to mbed and build the event
uci1 1:e392595b4b76 224 //
uci1 1:e392595b4b76 225
uci1 1:e392595b4b76 226 led4=1;
uci1 1:e392595b4b76 227 printf("readout\r\n");
uci1 1:e392595b4b76 228
uci1 1:e392595b4b76 229 // read data & calc CRC
uci1 1:e392595b4b76 230 gEvent.ReadWaveforms(PIN_spi, PIN_selCardHiBit, PIN_selCardLoBit);
uci1 1:e392595b4b76 231 gEvent.SetCurMbedTime();
uci1 1:e392595b4b76 232 // TODO: no way to check for external trigger?
uci1 1:e392595b4b76 233 if (gEvent.IsForcedTrg()==false) {
uci1 1:e392595b4b76 234 gEvent.SetTrgBit(kThmTrg);
uci1 1:e392595b4b76 235 gEvent.SetTrgNum((gTrgNum[kThmTrg])++);
uci1 1:e392595b4b76 236 } // else already set by procForceTrigger
uci1 1:e392595b4b76 237 // (no need to calc if we throw this event away)
uci1 1:e392595b4b76 238
uci1 1:e392595b4b76 239 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 240
uci1 1:e392595b4b76 241 printf("gFirstEvt=%s\r\n",gFirstEvt?"true":"false");
uci1 1:e392595b4b76 242
uci1 1:e392595b4b76 243 if ( gEvent.IsForcedTrg() || gFirstEvt ||
uci1 1:e392595b4b76 244 (etms>gConf.GetEvtThrtlPeriodMs()) ) {
uci1 1:e392595b4b76 245
uci1 1:e392595b4b76 246 led2=1;
uci1 1:e392595b4b76 247
uci1 1:e392595b4b76 248 PIN_lockRegisters = 0; // done reading, unlock so we can talk to SD card.
uci1 1:e392595b4b76 249
uci1 1:e392595b4b76 250 SaveEvent(etms);
uci1 3:24c5f0f50bf1 251
uci1 3:24c5f0f50bf1 252 if (gEvtNum>=(gConf.GetFirstEvt()+gConf.GetEvtsPerFile())) {
uci1 3:24c5f0f50bf1 253 MakeOutputFile(gConf.IsSingleSeqRunMode());
uci1 3:24c5f0f50bf1 254 }
uci1 3:24c5f0f50bf1 255 /*
uci1 1:e392595b4b76 256 } else {
uci1 1:e392595b4b76 257 printf("forced=%s, gFirstEvt=%s, e>t %d>%hu %s\r\n",
uci1 1:e392595b4b76 258 gEvent.IsForcedTrg()?"true":"false", gFirstEvt?"true":"false",
uci1 1:e392595b4b76 259 etms, gConf.GetEvtThrtlPeriodMs(),
uci1 1:e392595b4b76 260 etms>gConf.GetEvtThrtlPeriodMs() ? "true":"false");
uci1 3:24c5f0f50bf1 261 */
uci1 1:e392595b4b76 262 }
uci1 1:e392595b4b76 263 }
uci1 1:e392595b4b76 264 printf("past reading out\r\n");
uci1 1:e392595b4b76 265
uci1 1:e392595b4b76 266 led4=0; led2=0;
uci1 1:e392595b4b76 267
uci1 0:664899e0b988 268 if (gOpenCommWin) {
uci1 1:e392595b4b76 269 printf("gOpenComWin=%s, opening\r\n",gOpenCommWin?"true":"false");
uci1 0:664899e0b988 270 OpenCommWin();
uci1 0:664899e0b988 271 gOpenCommWin=false;
uci1 1:e392595b4b76 272 } else {
uci1 1:e392595b4b76 273 printf("gOpenCommWin=false\r\n");
uci1 0:664899e0b988 274 }
uci1 0:664899e0b988 275 }
uci1 0:664899e0b988 276
uci1 0:664899e0b988 277 }
uci1 0:664899e0b988 278
uci1 0:664899e0b988 279 //
uci1 0:664899e0b988 280 // save the event
uci1 0:664899e0b988 281 //
uci1 0:664899e0b988 282 void SaveEvent(const int32_t etms) {
uci1 0:664899e0b988 283 // write the event
uci1 0:664899e0b988 284
uci1 3:24c5f0f50bf1 285 printf("save event\r\n");
uci1 3:24c5f0f50bf1 286
uci1 0:664899e0b988 287 // set the event number & dt
uci1 3:24c5f0f50bf1 288 gEvent.SetEvtNum(gEvtNum);
uci1 0:664899e0b988 289 gEvent.SetDTms(etms);
uci1 0:664899e0b988 290
uci1 0:664899e0b988 291 // save to SD
uci1 1:e392595b4b76 292 SnSDUtils::WriteEventTo(SnSDUtils::GetCurFile(), gGenBuf, gEvent, gConf);
uci1 0:664899e0b988 293
uci1 0:664899e0b988 294 // reset
uci1 0:664899e0b988 295 gEvent.ClearEvent();
uci1 0:664899e0b988 296
uci1 3:24c5f0f50bf1 297 // increment event number
uci1 3:24c5f0f50bf1 298 ++gEvtNum;
uci1 3:24c5f0f50bf1 299
uci1 1:e392595b4b76 300 printf("gEvtNum=%d\r\n",gEvtNum);
uci1 3:24c5f0f50bf1 301 }
uci1 3:24c5f0f50bf1 302
uci1 3:24c5f0f50bf1 303 void MakeOutputFile(const bool stopRunning) {
uci1 3:24c5f0f50bf1 304 SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
uci1 3:24c5f0f50bf1 305 if (stopRunning) {
uci1 2:e67f7c158087 306 while (true) {
uci1 1:e392595b4b76 307 led3 = 1; led4=1;
uci1 0:664899e0b988 308 wait(0.5);
uci1 1:e392595b4b76 309 led3 = 0; led4=0;
uci1 0:664899e0b988 310 wait(0.5);
uci1 1:e392595b4b76 311 Watchdog::kick();
uci1 0:664899e0b988 312 }
uci1 0:664899e0b988 313 }
uci1 3:24c5f0f50bf1 314 SnSDUtils::OpenNewOutputFile(gConf.GetMacAddress(),
uci1 4:a91682e19d6b 315 gConf.GetRun(),
uci1 4:a91682e19d6b 316 PIN_vADC1.read_u16(),
uci1 4:a91682e19d6b 317 PIN_vADC2.read_u16());
uci1 3:24c5f0f50bf1 318 printf("made output file with run %u\r\n",gConf.GetRun());
uci1 3:24c5f0f50bf1 319 printf("filename=%s\r\n",SnSDUtils::GetCurFileName());
uci1 3:24c5f0f50bf1 320 SnSDUtils::WriteConfig(SnSDUtils::GetCurFile(), gConf);
uci1 0:664899e0b988 321 }
uci1 0:664899e0b988 322
uci1 0:664899e0b988 323 //
uci1 4:a91682e19d6b 324 // power stuff
uci1 4:a91682e19d6b 325 //
uci1 4:a91682e19d6b 326 void SetPower(const bool isCommWin) {
uci1 4:a91682e19d6b 327 if (isCommWin) {
uci1 5:9cea89700c66 328 PIN_turn_on_system = gConf.GetPowPinSetting(SnConfigFrame::kCardComWin);
uci1 4:a91682e19d6b 329 wait_ms(10);
uci1 5:9cea89700c66 330 PIN_turn_on_amps = gConf.GetPowPinSetting(SnConfigFrame::kAmpsComWin);
uci1 4:a91682e19d6b 331 wait_ms(10);
uci1 5:9cea89700c66 332 PIN_iridSbd_power = gConf.GetPowPinSetting(SnConfigFrame::kIridComWin);
uci1 4:a91682e19d6b 333 wait_ms(10);
uci1 5:9cea89700c66 334 PIN_afar_power = gConf.GetPowPinSetting(SnConfigFrame::kAfarComWin);
uci1 4:a91682e19d6b 335 wait_ms(10);
uci1 4:a91682e19d6b 336 } else {
uci1 5:9cea89700c66 337 PIN_turn_on_system = gConf.GetPowPinSetting(SnConfigFrame::kCardDatTak);
uci1 4:a91682e19d6b 338 wait_ms(10);
uci1 5:9cea89700c66 339 PIN_turn_on_amps = gConf.GetPowPinSetting(SnConfigFrame::kAmpsDatTak);
uci1 4:a91682e19d6b 340 wait_ms(10);
uci1 5:9cea89700c66 341 PIN_iridSbd_power = gConf.GetPowPinSetting(SnConfigFrame::kIridDatTak);
uci1 4:a91682e19d6b 342 wait_ms(10);
uci1 5:9cea89700c66 343 PIN_afar_power = gConf.GetPowPinSetting(SnConfigFrame::kAfarDatTak);
uci1 4:a91682e19d6b 344 wait_ms(10);
uci1 4:a91682e19d6b 345 }
uci1 4:a91682e19d6b 346 }
uci1 4:a91682e19d6b 347
uci1 4:a91682e19d6b 348 //
uci1 0:664899e0b988 349 // set configuration
uci1 0:664899e0b988 350 //
uci1 1:e392595b4b76 351 void SetConfigAndMakeOutputFile() {
uci1 1:e392595b4b76 352 printf("SetConfigAndMakeOutputFile\r\n");
uci1 1:e392595b4b76 353
uci1 0:664899e0b988 354 // restart watchdog
uci1 0:664899e0b988 355 Watchdog::kick(gConf.GetWatchdogPeriod());
uci1 0:664899e0b988 356
uci1 1:e392595b4b76 357 // block (thermal) triggers during configuration
uci1 1:e392595b4b76 358 PIN_enableThermTrig = 0;
uci1 1:e392595b4b76 359 PIN_ADC_CS = 1;
uci1 1:e392595b4b76 360 PIN_DoNotRestartAllClocks = 1;
uci1 1:e392595b4b76 361 PIN_forceTrigger = 0;
uci1 3:24c5f0f50bf1 362 PIN_heartbeat = 0;
uci1 1:e392595b4b76 363 wait_ms(20);
uci1 1:e392595b4b76 364
uci1 0:664899e0b988 365 // reset event, timers, trigger counters
uci1 0:664899e0b988 366 gEvent.ClearEvent();
uci1 0:664899e0b988 367 gEvtNum = gConf.GetFirstEvt();
uci1 0:664899e0b988 368 memset(gTrgNum, 0, sizeof(int32_t)*kNumTrgs);
uci1 0:664899e0b988 369
uci1 0:664899e0b988 370 // make new output file
uci1 3:24c5f0f50bf1 371 MakeOutputFile();
uci1 0:664899e0b988 372
uci1 0:664899e0b988 373 // TODO: turn on amps individually, when that's possible
uci1 1:e392595b4b76 374 PIN_turn_on_amps = gConf.IsEachAmpOn() ? 0 : 1;
uci1 0:664899e0b988 375
uci1 0:664899e0b988 376 // Set PLA value(s)
uci1 0:664899e0b988 377 PIN_spi.format( 16, 0 ); // change mode for DAC & PLA value setting
uci1 1:e392595b4b76 378 PIN_spi.frequency(1000000);
uci1 0:664899e0b988 379 PIN_MajLogHiBit=1;
uci1 0:664899e0b988 380 PIN_MajLogLoBit=1;
uci1 0:664899e0b988 381 PIN_enableThermTrig=0;
uci1 0:664899e0b988 382
uci1 0:664899e0b988 383 uint16_t hi, lo;
uci1 0:664899e0b988 384 PIN_PLA_cs=1;
uci1 1:e392595b4b76 385 wait(4);
uci1 0:664899e0b988 386 for (uint8_t pi=0; pi<kNplas; pi++) {
uci1 0:664899e0b988 387 if (pi < gConf.GetNumPlas()) {
uci1 0:664899e0b988 388 SnConfigFrame::GetHiLoPlas(gConf.GetPla(pi), hi, lo);
uci1 0:664899e0b988 389 PIN_spi.write(hi);
uci1 0:664899e0b988 390 PIN_spi.write(lo);
uci1 3:24c5f0f50bf1 391 printf("pla hi %hu, lo %hu\r\n",hi,lo);
uci1 0:664899e0b988 392 } else {
uci1 0:664899e0b988 393 PIN_spi.write(kNoTrigPla); // hi
uci1 0:664899e0b988 394 PIN_spi.write(kNoTrigPla); // lo
uci1 3:24c5f0f50bf1 395 printf("pla hi %hu, lo %hu\r\n",kNoTrigPla,kNoTrigPla);
uci1 0:664899e0b988 396 }
uci1 1:e392595b4b76 397 Watchdog::kick();
uci1 0:664899e0b988 398 }
uci1 0:664899e0b988 399 wait(3);
uci1 0:664899e0b988 400 PIN_PLA_cs=0;
uci1 0:664899e0b988 401 wait(3);
uci1 0:664899e0b988 402
uci1 0:664899e0b988 403 // DAC values
uci1 0:664899e0b988 404 //
uci1 0:664899e0b988 405 // first 12 bits = DAC value
uci1 0:664899e0b988 406 // next 2 bits = DAC ID
uci1 0:664899e0b988 407 // last 2 bits = dFPGA ID
uci1 0:664899e0b988 408 //
uci1 0:664899e0b988 409 // But FPGA uses "gray encoding" which means only 1 bit
uci1 0:664899e0b988 410 // can change at a time (of the last 4 bits). So even tho
uci1 0:664899e0b988 411 // the card/dac# is encoded, the order is also important
uci1 0:664899e0b988 412 // 0000 (dac0,card0), 0001 (dac0,card1), 0011 (dac0,card3), 0010 (dac0,card2),
uci1 0:664899e0b988 413 // 0110 (dac1,card2), 0111 (dac1,card3), 0101 (dac1,card1), etc.
uci1 1:e392595b4b76 414 printf("setting dacs\r\n");
uci1 1:e392595b4b76 415 uint16_t dv=0;
uci1 0:664899e0b988 416 for (uint8_t i=0, gri=0; i<kTotDacs; i++) {
uci1 0:664899e0b988 417 // get the gray-codes for this iteration
uci1 0:664899e0b988 418 gri = SnBitUtils::binToGray(i);
uci1 0:664899e0b988 419
uci1 0:664899e0b988 420 // build bit word
uci1 0:664899e0b988 421 dv = static_cast<int>(gConf.GetDac(gri & 0x0003u, gri >> 2u));
uci1 0:664899e0b988 422 dv <<= 4u;
uci1 0:664899e0b988 423 dv |= gri;
uci1 0:664899e0b988 424
uci1 1:e392595b4b76 425 printf("dac %04x\r\n",dv);
uci1 1:e392595b4b76 426
uci1 0:664899e0b988 427 // send to FPGA
uci1 0:664899e0b988 428 PIN_start_fpga=1;
uci1 0:664899e0b988 429 PIN_spi.write(dv);
uci1 0:664899e0b988 430 PIN_start_fpga=0;
uci1 1:e392595b4b76 431
uci1 1:e392595b4b76 432 Watchdog::kick();
uci1 1:e392595b4b76 433
uci1 0:664899e0b988 434 }
uci1 1:e392595b4b76 435 printf("dacs set\r\n");
uci1 0:664899e0b988 436 wait_ms(20);
uci1 0:664899e0b988 437
uci1 0:664899e0b988 438 // Majority Logic Trigger selection (# of cards)
uci1 0:664899e0b988 439 SnBitUtils::SetChanNumBits(gConf.GetNumCardsMajLog() - 1u,
uci1 0:664899e0b988 440 PIN_MajLogHiBit, PIN_MajLogLoBit);
uci1 0:664899e0b988 441
uci1 0:664899e0b988 442 // Enable thermal trigger?
uci1 0:664899e0b988 443 PIN_enableThermTrig = gConf.IsThermTrigEnabled();
uci1 0:664899e0b988 444
uci1 0:664899e0b988 445 PIN_spi.format( 16, 1 ); // back to trigger mode
uci1 1:e392595b4b76 446 PIN_spi.frequency( 10000000 ); // Max is 12.5 MHz
uci1 1:e392595b4b76 447
uci1 1:e392595b4b76 448 // force a trigger every...
uci1 1:e392595b4b76 449 gForceTicker.detach();
uci1 3:24c5f0f50bf1 450 if (gConf.GetForceTrigPeriod()>0) {
uci1 3:24c5f0f50bf1 451 gForceTicker.attach(&procForceTrigger,
uci1 3:24c5f0f50bf1 452 gConf.GetForceTrigPeriod() > kAbsMaxTimer ?
uci1 3:24c5f0f50bf1 453 kAbsMaxTimer : gConf.GetForceTrigPeriod()); // force period has a maximum
uci1 3:24c5f0f50bf1 454 }
uci1 3:24c5f0f50bf1 455 // heartbeat every ...
uci1 3:24c5f0f50bf1 456 gHeartbeatTicker.detach();
uci1 3:24c5f0f50bf1 457 if (gConf.GetHeartbeatPeriod()>0) {
uci1 3:24c5f0f50bf1 458 gHeartbeatTicker.attach(&procHeartbeat,
uci1 3:24c5f0f50bf1 459 gConf.GetHeartbeatPeriod() > kAbsMaxTimer ?
uci1 3:24c5f0f50bf1 460 kAbsMaxTimer : gConf.GetHeartbeatPeriod());
uci1 3:24c5f0f50bf1 461 }
uci1 1:e392595b4b76 462 // proc a comm win every...
uci1 1:e392595b4b76 463 gCommWinTicker.detach();
uci1 1:e392595b4b76 464 gCommWinTicker.attach(&procCommWin,
uci1 1:e392595b4b76 465 gConf.GetCommWinPeriod() > kAbsMaxTimer ?
uci1 1:e392595b4b76 466 kCommWinLongPrdTk : gConf.GetCommWinPeriod()); // periodic check if above max
uci1 1:e392595b4b76 467 printf("attach comm win ticker %u\r\n",
uci1 1:e392595b4b76 468 gConf.GetCommWinPeriod() > kAbsMaxTimer ?
uci1 1:e392595b4b76 469 kCommWinLongPrdTk : gConf.GetCommWinPeriod());
uci1 0:664899e0b988 470
uci1 0:664899e0b988 471 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 472
uci1 0:664899e0b988 473 }
uci1 0:664899e0b988 474
uci1 0:664899e0b988 475 //
uci1 0:664899e0b988 476 // readout functions
uci1 0:664899e0b988 477 //
uci1 0:664899e0b988 478 void WaitTrigAndSendClock() {
uci1 1:e392595b4b76 479
uci1 1:e392595b4b76 480 printf("WaitTrigAndSendClock\r\n");
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 for( uint8_t i = 0; i < kNsamps; i++ ) {
uci1 0:664899e0b988 508 if( PIN_a_sf_clk == 1 ) {
uci1 0:664899e0b988 509 if( i == 0 )
uci1 0:664899e0b988 510 wait_us( 1 );
uci1 0:664899e0b988 511
uci1 0:664899e0b988 512 PIN_ADC_CS = 0;
uci1 0:664899e0b988 513 PIN_spi.write( 0x00 );
uci1 0:664899e0b988 514 PIN_ADC_CS = 1;
uci1 0:664899e0b988 515 } else {
uci1 0:664899e0b988 516 i--;
uci1 0:664899e0b988 517 }
uci1 0:664899e0b988 518 }
uci1 0:664899e0b988 519 }
uci1 0:664899e0b988 520
uci1 0:664899e0b988 521 SnCommWin::ECommWinResult OpenCommWin() {
uci1 0:664899e0b988 522 // loop through each comm mode:
uci1 0:664899e0b988 523 // a) try to connect
uci1 0:664899e0b988 524 // b) if connected, listen for config
uci1 0:664899e0b988 525 // c) if config requests data, send it
uci1 3:24c5f0f50bf1 526
uci1 3:24c5f0f50bf1 527 gLastCommWin = time(0);
uci1 3:24c5f0f50bf1 528 if (gConf.GetCommWinDuration()==0) {
uci1 3:24c5f0f50bf1 529 // TODO: set min so this is not possible
uci1 3:24c5f0f50bf1 530 return SnCommWin::kOkNoMsg;
uci1 3:24c5f0f50bf1 531 }
uci1 0:664899e0b988 532
uci1 0:664899e0b988 533 gCommWinOpen = true;
uci1 0:664899e0b988 534 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 535
uci1 3:24c5f0f50bf1 536 printf("opening comm window at %d\r\n", (int32_t)gLastCommWin);
uci1 3:24c5f0f50bf1 537
uci1 3:24c5f0f50bf1 538 // close the file so that the data is all written out.
uci1 3:24c5f0f50bf1 539 // and open it back up at the beginning (for reading)
uci1 3:24c5f0f50bf1 540 SnSDUtils::CloseOutputFile(SnSDUtils::GetCurFile());
uci1 3:24c5f0f50bf1 541 SnSDUtils::OpenExistingFile(SnSDUtils::GetCurFileName(), true);
uci1 0:664899e0b988 542
uci1 4:a91682e19d6b 543 // (probably) power down cards,amps and power up comms
uci1 4:a91682e19d6b 544 SetPower(true);
uci1 0:664899e0b988 545
uci1 0:664899e0b988 546 const uint32_t conto = (gConf.GetCommWinDuration() < kConnectTimeout) ?
uci1 0:664899e0b988 547 gConf.GetCommWinDuration() : kConnectTimeout;
uci1 0:664899e0b988 548 const uint32_t listo = (gConf.GetCommWinDuration() < kListenTimeout) ?
uci1 0:664899e0b988 549 gConf.GetCommWinDuration() : kListenTimeout;
uci1 0:664899e0b988 550
uci1 0:664899e0b988 551 SnCommWin::ECommWinResult res = SnCommWin::kUndefFail;
uci1 0:664899e0b988 552
uci1 1:e392595b4b76 553 bool gotNewConfig=false;
uci1 1:e392595b4b76 554 bool sendStat[kNcomms];
uci1 1:e392595b4b76 555 for (uint8_t i=0; i<kNcomms; i++) {
uci1 1:e392595b4b76 556 sendStat[i]=true;
uci1 1:e392595b4b76 557 }
uci1 1:e392595b4b76 558 bool* ss = sendStat;
uci1 0:664899e0b988 559 SnCommWin** cw = gComms;
uci1 1:e392595b4b76 560 for (uint8_t i=0; ((time(0)-gLastCommWin)<gConf.GetCommWinDuration()); i++, cw++, ss++) {
uci1 1:e392595b4b76 561 Watchdog::kick(); // don't reset!
uci1 1:e392595b4b76 562 if (i==kNcomms) {
uci1 1:e392595b4b76 563 i=0;
uci1 1:e392595b4b76 564 cw = gComms;
uci1 1:e392595b4b76 565 ss = sendStat;
uci1 1:e392595b4b76 566 }
uci1 0:664899e0b988 567 // open window and (mabye) send status update
uci1 1:e392595b4b76 568 printf("calling OpenWindow. ss=%d\r\n",(int)(*ss));
uci1 1:e392595b4b76 569 printf("gtt=%u, ct=%d, lcw=%d, dur=%u\r\n",GetTimeoutTime(gLastCommWin,conto),
uci1 1:e392595b4b76 570 time(0), gLastCommWin, gConf.GetCommWinDuration());
uci1 0:664899e0b988 571 const SnCommWin::ECommWinResult conres = (*cw)->OpenWindow(
uci1 2:e67f7c158087 572 GetTimeoutTime(gLastCommWin, conto), *ss, gConf, gEvent, gGenBuf);
uci1 0:664899e0b988 573 if (conres>=SnCommWin::kConnected) {
uci1 1:e392595b4b76 574 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 575 // connected. listen for config
uci1 1:e392595b4b76 576 *ss = false; // don't send status next time
uci1 0:664899e0b988 577 const SnCommWin::ECommWinResult cfgres = (*cw)->GetConfig(
uci1 3:24c5f0f50bf1 578 gConf, GetTimeoutTime(gLastCommWin, listo), gGenBuf, gBufSize);
uci1 0:664899e0b988 579 if (cfgres>=SnCommWin::kOkWithMsg) {
uci1 1:e392595b4b76 580 Watchdog::kick(); // don't reset!
uci1 3:24c5f0f50bf1 581 printf("received config (%u)!\r\n",gConf.SizeOf());
uci1 1:e392595b4b76 582 char* b = gGenBuf;
uci1 1:e392595b4b76 583 gConf.WriteTo(b);
uci1 3:24c5f0f50bf1 584 const uint32_t csz = gConf.SizeOf();
uci1 3:24c5f0f50bf1 585 for (uint32_t i=0; i<csz; i++) {
uci1 1:e392595b4b76 586 printf("%02x ",gGenBuf[i]);
uci1 1:e392595b4b76 587 }
uci1 1:e392595b4b76 588 printf("\r\n");
uci1 0:664899e0b988 589 // send data if need be (files, some events, etc)
uci1 3:24c5f0f50bf1 590 printf("send data = %d\r\n", gConf.GetCommSendData());
uci1 0:664899e0b988 591 if (gConf.GetCommSendData()!=0) {
uci1 3:24c5f0f50bf1 592 printf("sending data\r\n");
uci1 3:24c5f0f50bf1 593 res = (*cw)->SendData(gConf, gEvent, gGenBuf, gBufSize,
uci1 1:e392595b4b76 594 GetTimeoutTime(gLastCommWin, gConf.GetCommWinDuration()));
uci1 0:664899e0b988 595 } else {
uci1 0:664899e0b988 596 // don't send anything
uci1 0:664899e0b988 597 res = cfgres;
uci1 0:664899e0b988 598 }
uci1 1:e392595b4b76 599 printf("Got config!\r\n");
uci1 1:e392595b4b76 600 gotNewConfig=true;
uci1 1:e392595b4b76 601 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 602 break;
uci1 0:664899e0b988 603 }
uci1 0:664899e0b988 604 }
uci1 0:664899e0b988 605
uci1 0:664899e0b988 606 Watchdog::kick(); // don't reset!
uci1 0:664899e0b988 607
uci1 0:664899e0b988 608 }
uci1 0:664899e0b988 609
uci1 4:a91682e19d6b 610 // (probably) power down comms and power up cards,amps
uci1 4:a91682e19d6b 611 SetPower(false);
uci1 4:a91682e19d6b 612
uci1 1:e392595b4b76 613 gFirstEvt = true;
uci1 4:a91682e19d6b 614
uci1 1:e392595b4b76 615 // reset config with system powered (for DAC/PLA setting)
uci1 1:e392595b4b76 616 if (gotNewConfig) {
uci1 1:e392595b4b76 617 printf("calling SetConfigAndMakeOutputFile\r\n");
uci1 1:e392595b4b76 618 SetConfigAndMakeOutputFile();
uci1 1:e392595b4b76 619 // TODO: remove
uci1 1:e392595b4b76 620 }
uci1 1:e392595b4b76 621 printf("closing comm win at %d\r\n",(int32_t)time(0));
uci1 1:e392595b4b76 622
uci1 0:664899e0b988 623 gCommWinOpen = false;
uci1 0:664899e0b988 624 return res;
uci1 0:664899e0b988 625 }