Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Committer:
uci1
Date:
Tue Oct 16 04:47:44 2012 +0000
Revision:
22:f957c4f840ad
Parent:
21:ce51bb0ba4a5
Child:
25:57b2627fe756
USB comm only. Make firing of comm window independent of real time clock. Add heartbeat firing time to the data stream.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
uci1 0:664899e0b988 1 #include "SnSDUtils.h"
uci1 0:664899e0b988 2
uci1 0:664899e0b988 3 #include "mbed.h"
uci1 0:664899e0b988 4 #include "SDFileSystem.h"
uci1 21:ce51bb0ba4a5 5 #include "FATDirHandle.h"
uci1 0:664899e0b988 6 #include <string.h>
uci1 12:d472f9811262 7 #include <string>
uci1 0:664899e0b988 8
uci1 0:664899e0b988 9 #include "SnConfigFrame.h"
uci1 0:664899e0b988 10 #include "SnEventFrame.h"
uci1 22:f957c4f840ad 11 #include "SnHeartbeatFrame.h"
uci1 0:664899e0b988 12
uci1 15:f2569d8e4176 13 //#define DEBUG
uci1 0:664899e0b988 14
uci1 19:74155d652c37 15 const char* const SnSDUtils::kSDdir = "/sd";
uci1 19:74155d652c37 16 const char* const SnSDUtils::kSDsubDir = "/sd/data";
uci1 2:e67f7c158087 17 char SnSDUtils::fgCurFileName[kFNBufSize]={0};
uci1 1:e392595b4b76 18 FILE* SnSDUtils::fgCurFile = 0;
uci1 12:d472f9811262 19 uint16_t SnSDUtils::fgCurSeq = 0;
uci1 8:95a325df1f6b 20 const uint8_t SnSDUtils::kIOvers = 3;
uci1 5:9cea89700c66 21 const uint32_t SnSDUtils::kMaxSizeOfFileHdr =
uci1 5:9cea89700c66 22 sizeof(uint8_t)+sizeof(uint64_t)+sizeof(uint32_t)+sizeof(uint16_t)
uci1 8:95a325df1f6b 23 +(sizeof(uint8_t)+(2u*sizeof(uint16_t))); // power frame v1
uci1 4:a91682e19d6b 24
uci1 4:a91682e19d6b 25 static const uint16_t __kMaxUShort = ~0;
uci1 0:664899e0b988 26
uci1 0:664899e0b988 27 const char* SnSDUtils::GetOutFileName(const uint64_t macadr,
uci1 0:664899e0b988 28 const uint32_t run,
uci1 0:664899e0b988 29 const uint16_t seq) {
uci1 0:664899e0b988 30 // returns the formatted file name, or NULL if the directory is too long
uci1 0:664899e0b988 31 // and the full name cannot fit in the buffer
uci1 0:664899e0b988 32 // NOTE: this fcn uses a static buffer, and so should not be called
uci1 0:664899e0b988 33 // multiple times in the same line (that includes the calling of functions
uci1 0:664899e0b988 34 // that call this function!)
uci1 0:664899e0b988 35 //
uci1 0:664899e0b988 36 // filename = SnEvtsM[6-byte hex mac adr]r[6-digit run num]s[5-digit seq num].dat
uci1 0:664899e0b988 37 // 35 chars 7 + 12 +1+ 5 +1+ 5 + 4
uci1 0:664899e0b988 38
uci1 0:664899e0b988 39 if (strlen(kSDsubDir)<(kFNBufSize-37)) {
uci1 0:664899e0b988 40 static char tbuf[kFNBufSize];
uci1 0:664899e0b988 41 memset(tbuf, 0, sizeof(char)*kFNBufSize);
uci1 0:664899e0b988 42 // if file name format changes, GetSeqNum must be changed too
uci1 0:664899e0b988 43 sprintf(tbuf, "%s/SnEvtsM%012llXr%05ds%05d.dat",
uci1 0:664899e0b988 44 kSDsubDir,
uci1 0:664899e0b988 45 macadr>>16, // 64 -> 48 bits
uci1 0:664899e0b988 46 run, seq);
uci1 0:664899e0b988 47 return tbuf;
uci1 0:664899e0b988 48 } else {
uci1 0:664899e0b988 49 return NULL;
uci1 0:664899e0b988 50 }
uci1 0:664899e0b988 51 }
uci1 12:d472f9811262 52 /*
uci1 10:3c93db1cfb12 53 uint16_t SnSDUtils::GetCurSeqNum() {
uci1 10:3c93db1cfb12 54 return GetSeqNumFromFileName(fgCurFileName);
uci1 10:3c93db1cfb12 55 }
uci1 12:d472f9811262 56 */
uci1 10:3c93db1cfb12 57 uint16_t SnSDUtils::GetSeqNumFromFileName(const char* fn) {
uci1 10:3c93db1cfb12 58 uint16_t seq=0;
uci1 10:3c93db1cfb12 59 const uint32_t ncomp = strrchr(fn, 's') - fn;
uci1 10:3c93db1cfb12 60 if (ncomp<strlen(fn)) {
uci1 10:3c93db1cfb12 61 sscanf(fn+ncomp,"s%hu.dat",&seq);
uci1 10:3c93db1cfb12 62 }
uci1 10:3c93db1cfb12 63 return seq;
uci1 10:3c93db1cfb12 64 }
uci1 10:3c93db1cfb12 65
uci1 0:664899e0b988 66 uint16_t SnSDUtils::GetSeqNum(const uint64_t macadr,
uci1 0:664899e0b988 67 const uint32_t run) {
uci1 0:664899e0b988 68 // count the files having expected filename format
uci1 0:664899e0b988 69
uci1 21:ce51bb0ba4a5 70 // fn points to a static buffer
uci1 0:664899e0b988 71 const char* fn = GetOutFileName(macadr, run, 0)
uci1 0:664899e0b988 72 + strlen(kSDsubDir) + 1; // take out dir and '/'s
uci1 0:664899e0b988 73
uci1 20:e5857b287b3b 74 DIR* d( opendir(kSDsubDir) );
uci1 20:e5857b287b3b 75 if (d==NULL) {
uci1 20:e5857b287b3b 76 // try making the directory
uci1 20:e5857b287b3b 77 mkdir(kSDsubDir, 0777);
uci1 20:e5857b287b3b 78 d = opendir( kSDsubDir );
uci1 20:e5857b287b3b 79 }
uci1 0:664899e0b988 80 struct dirent* dent;
uci1 0:664899e0b988 81
uci1 6:6f002d202f59 82 uint16_t seq=0, newseq=0;
uci1 20:e5857b287b3b 83 if ( d!=NULL ) {
uci1 0:664899e0b988 84 // don't compare seq#. don't use num of chars in case seq is >999
uci1 0:664899e0b988 85 const uint32_t ncomp = strrchr(fn, 's') - fn;
uci1 0:664899e0b988 86 while ( (dent = readdir(d))!=NULL ) {
uci1 0:664899e0b988 87 if (strncmp(dent->d_name, fn, ncomp)==0) {
uci1 6:6f002d202f59 88 // allow for deleted files to make gaps.
uci1 6:6f002d202f59 89 // search for highest seq number and increase that
uci1 7:079617408fec 90 sscanf((dent->d_name)+ncomp,"s%hu.dat",&seq);
uci1 12:d472f9811262 91 #ifdef DEBUG
uci1 7:079617408fec 92 printf("dn=%s, seq=%hu, __kMaxUShort=%hu\r\n",
uci1 7:079617408fec 93 dent->d_name, seq, __kMaxUShort);
uci1 12:d472f9811262 94 #endif
uci1 4:a91682e19d6b 95 if (seq==__kMaxUShort) {
uci1 6:6f002d202f59 96 newseq = seq;
uci1 6:6f002d202f59 97 break;
uci1 6:6f002d202f59 98 }
uci1 6:6f002d202f59 99 if (seq>=newseq) {
uci1 6:6f002d202f59 100 newseq=seq+1;
uci1 6:6f002d202f59 101 }
uci1 6:6f002d202f59 102 if (newseq==__kMaxUShort) {
uci1 4:a91682e19d6b 103 break;
uci1 4:a91682e19d6b 104 }
uci1 0:664899e0b988 105 }
uci1 0:664899e0b988 106 }
uci1 0:664899e0b988 107 closedir(d);
uci1 0:664899e0b988 108 }
uci1 7:079617408fec 109
uci1 21:ce51bb0ba4a5 110 #ifdef DEBUG
uci1 21:ce51bb0ba4a5 111 printf("return newseq=%hu\r\n",newseq);
uci1 21:ce51bb0ba4a5 112 #endif
uci1 6:6f002d202f59 113 return newseq;
uci1 0:664899e0b988 114 }
uci1 0:664899e0b988 115
uci1 3:24c5f0f50bf1 116 FILE* SnSDUtils::OpenExistingFile(const char* name, const bool setcurrent) {
uci1 0:664899e0b988 117 FILE* f = 0;
uci1 0:664899e0b988 118 if (name!=NULL) {
uci1 3:24c5f0f50bf1 119 f = OpenSDFile(name, "rb");
uci1 12:d472f9811262 120 /*
uci1 3:24c5f0f50bf1 121 if (setcurrent) {
uci1 3:24c5f0f50bf1 122 fgCurFile = f;
uci1 12:d472f9811262 123 strncpy(fgCurFileName, name, kFNBufSize-1);
uci1 12:d472f9811262 124 fgCurSeq = GetSeqNumFromFileName(fgCurFileName);
uci1 3:24c5f0f50bf1 125 }
uci1 12:d472f9811262 126 */
uci1 0:664899e0b988 127 }
uci1 0:664899e0b988 128 return f;
uci1 0:664899e0b988 129 }
uci1 0:664899e0b988 130
uci1 3:24c5f0f50bf1 131 FILE* SnSDUtils::OpenSDFile(const char* name, const char* mode) {
uci1 12:d472f9811262 132 // TODO: check if we have memory?
uci1 12:d472f9811262 133 std::string fn(name);
uci1 12:d472f9811262 134 if (strncmp(name, kSDsubDir, strlen(kSDsubDir))!=0) {
uci1 12:d472f9811262 135 // filename lacks directory
uci1 12:d472f9811262 136 fn = kSDsubDir;
uci1 12:d472f9811262 137 fn += "/";
uci1 12:d472f9811262 138 fn += name;
uci1 12:d472f9811262 139 }
uci1 12:d472f9811262 140 #ifdef DEBUG
uci1 12:d472f9811262 141 printf("OpenSDFile: %s, mode %s\r\n",fn.c_str(),mode);
uci1 12:d472f9811262 142 #endif
uci1 12:d472f9811262 143 FILE* f = fopen(fn.c_str(), mode);
uci1 1:e392595b4b76 144 //setvbuf(f, 0, _IONBF, 0); // no buffering
uci1 19:74155d652c37 145 #ifdef DEBUG
uci1 19:74155d652c37 146 printf("OpenSDFile: f=%p\r\n",(void*)f);
uci1 19:74155d652c37 147 #endif
uci1 1:e392595b4b76 148 return f;
uci1 1:e392595b4b76 149 }
uci1 1:e392595b4b76 150
uci1 0:664899e0b988 151 FILE* SnSDUtils::OpenNewOutputFile(const uint64_t macadr,
uci1 8:95a325df1f6b 152 const uint32_t run) {
uci1 0:664899e0b988 153 // opens a new file in the specified directory and writes this
uci1 0:664899e0b988 154 // this mbed's mac address as the first sizeof(uint64_t) bytes (i.e. 4 bytes)
uci1 0:664899e0b988 155 //
uci1 22:f957c4f840ad 156 #ifdef DEBUG
uci1 22:f957c4f840ad 157 printf("getting seq num\r\n");
uci1 22:f957c4f840ad 158 #endif
uci1 12:d472f9811262 159 fgCurSeq = GetSeqNum(macadr, run);
uci1 22:f957c4f840ad 160 #ifdef DEBUG
uci1 22:f957c4f840ad 161 printf("getting output file name\r\n");
uci1 22:f957c4f840ad 162 #endif
uci1 0:664899e0b988 163 memset(fgCurFileName, 0, sizeof(char)*kFNBufSize);
uci1 12:d472f9811262 164 strncpy(fgCurFileName,GetOutFileName(macadr, run, fgCurSeq),kFNBufSize-1);
uci1 12:d472f9811262 165 //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,fgCurSeq);
uci1 1:e392595b4b76 166 fgCurFile = 0;
uci1 0:664899e0b988 167 if (fgCurFileName!=NULL) {
uci1 22:f957c4f840ad 168 #ifdef DEBUG
uci1 22:f957c4f840ad 169 printf("opening SD file\r\n");
uci1 22:f957c4f840ad 170 #endif
uci1 3:24c5f0f50bf1 171 fgCurFile = OpenSDFile(fgCurFileName, "wb");
uci1 2:e67f7c158087 172 if (fgCurFile!=NULL && ferror(fgCurFile)==0) {
uci1 19:74155d652c37 173 #ifdef DEBUG
uci1 19:74155d652c37 174 printf("Writing file header\r\n");
uci1 19:74155d652c37 175 #endif
uci1 12:d472f9811262 176 WriteFileHeader(fgCurFile, macadr, run, fgCurSeq);
uci1 2:e67f7c158087 177 }
uci1 0:664899e0b988 178 }
uci1 19:74155d652c37 179 #ifdef DEBUG
uci1 19:74155d652c37 180 printf("fgCurFile=%p\r\n",(void*)fgCurFile);
uci1 19:74155d652c37 181 #endif
uci1 1:e392595b4b76 182 return fgCurFile;
uci1 0:664899e0b988 183 }
uci1 0:664899e0b988 184
uci1 21:ce51bb0ba4a5 185 void SnSDUtils::GetDirProps(const char* dirname,
uci1 21:ce51bb0ba4a5 186 uint32_t& nfiles,
uci1 21:ce51bb0ba4a5 187 float& totbytes) {
uci1 21:ce51bb0ba4a5 188 nfiles = 0;
uci1 21:ce51bb0ba4a5 189 totbytes = 0;
uci1 21:ce51bb0ba4a5 190 FATDirHandle* d = dynamic_cast<FATDirHandle*>( opendir(dirname) );
uci1 21:ce51bb0ba4a5 191 if (d!=0) {
uci1 21:ce51bb0ba4a5 192 while ( (readdir(d))!=NULL ) {
uci1 21:ce51bb0ba4a5 193 ++nfiles;
uci1 21:ce51bb0ba4a5 194 totbytes += d->filinfo()->fsize;
uci1 21:ce51bb0ba4a5 195 }
uci1 21:ce51bb0ba4a5 196 closedir(d);
uci1 21:ce51bb0ba4a5 197 }
uci1 21:ce51bb0ba4a5 198 #ifdef DEBUG
uci1 22:f957c4f840ad 199 printf("GetDirProps: %s :: nf=%u, tb=%g\r\n",
uci1 21:ce51bb0ba4a5 200 dirname, nfiles, totbytes);
uci1 21:ce51bb0ba4a5 201 #endif
uci1 21:ce51bb0ba4a5 202 }
uci1 21:ce51bb0ba4a5 203
uci1 22:f957c4f840ad 204 bool SnSDUtils::WriteHeartbeatTo(FILE* file,
uci1 22:f957c4f840ad 205 const uint32_t time,
uci1 22:f957c4f840ad 206 const uint32_t num) {
uci1 22:f957c4f840ad 207 const SnCommWin::ECommWinResult r1 =
uci1 22:f957c4f840ad 208 SnHeaderFrame::WriteTo(file, SnHeaderFrame::kHeartbeatCode,
uci1 22:f957c4f840ad 209 SnHeartbeatFrame::SizeOf(SnHeartbeatFrame::kIOVers));
uci1 22:f957c4f840ad 210 const SnCommWin::ECommWinResult r2 =
uci1 22:f957c4f840ad 211 SnHeartbeatFrame::WriteTo(file, time, num);
uci1 22:f957c4f840ad 212 return ((r1==SnCommWin::kOkMsgSent)
uci1 22:f957c4f840ad 213 && (r2==SnCommWin::kOkMsgSent));
uci1 22:f957c4f840ad 214 }
uci1 22:f957c4f840ad 215
uci1 0:664899e0b988 216 bool SnSDUtils::WriteEventTo(FILE* efile, char* const evtBuf,
uci1 0:664899e0b988 217 const SnEventFrame& evt,
uci1 0:664899e0b988 218 const SnConfigFrame& conf) {
uci1 0:664899e0b988 219 // write event to SD card
uci1 0:664899e0b988 220
uci1 0:664899e0b988 221 uint8_t sLoseLSB=0, sLoseMSB=0;
uci1 0:664899e0b988 222 uint16_t sWvBase=0;
uci1 0:664899e0b988 223 conf.GetPackParsFor(SnConfigFrame::kSDcard, sLoseLSB, sLoseMSB, sWvBase);
uci1 8:95a325df1f6b 224 SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kEventCode,
uci1 8:95a325df1f6b 225 evt.SizeOf(SnEventFrame::kIOVers, sLoseLSB, sLoseMSB));
uci1 0:664899e0b988 226 const bool ret = evt.WriteTo(efile, evtBuf, sLoseLSB, sLoseMSB, sWvBase);
uci1 0:664899e0b988 227 fflush(efile);
uci1 0:664899e0b988 228 return ret;
uci1 0:664899e0b988 229 }
uci1 0:664899e0b988 230
uci1 0:664899e0b988 231 bool SnSDUtils::WriteConfig(FILE* efile,
uci1 0:664899e0b988 232 const SnConfigFrame& conf) {
uci1 8:95a325df1f6b 233 SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kConfigCode,
uci1 8:95a325df1f6b 234 conf.SizeOf(SnConfigFrame::kIOVers));
uci1 0:664899e0b988 235 conf.WriteTo(efile);
uci1 0:664899e0b988 236 return true;
uci1 0:664899e0b988 237 }
uci1 0:664899e0b988 238
uci1 0:664899e0b988 239 void SnSDUtils::DeleteFile(FILE*& f, const char* fname) {
uci1 0:664899e0b988 240 fclose(f);
uci1 0:664899e0b988 241 f=0;
uci1 21:ce51bb0ba4a5 242 // make sure we're trying to delete a file off the SD card
uci1 21:ce51bb0ba4a5 243 std::string fn(fname);
uci1 21:ce51bb0ba4a5 244 if (strncmp(fname,kSDsubDir,strlen(kSDsubDir))!=0) {
uci1 21:ce51bb0ba4a5 245 fn = kSDsubDir;
uci1 21:ce51bb0ba4a5 246 fn += "/";
uci1 21:ce51bb0ba4a5 247 fn += fname;
uci1 21:ce51bb0ba4a5 248 }
uci1 21:ce51bb0ba4a5 249 remove(fn.c_str());
uci1 0:664899e0b988 250 }
uci1 0:664899e0b988 251
uci1 0:664899e0b988 252 SnCommWin::ECommWinResult SnSDUtils::SendAllFiles(SnCommWin* comm,
uci1 3:24c5f0f50bf1 253 const uint32_t timeout,
uci1 3:24c5f0f50bf1 254 char* const buf,
uci1 6:6f002d202f59 255 const uint32_t bsize,
uci1 6:6f002d202f59 256 const SnConfigFrame& curConf,
uci1 8:95a325df1f6b 257 SnEventFrame& evt,
uci1 12:d472f9811262 258 SnPowerFrame& pow,
uci1 12:d472f9811262 259 const uint32_t handshakeTimeout) {
uci1 16:744ce85aede2 260
uci1 0:664899e0b988 261 DIR* d;
uci1 0:664899e0b988 262 struct dirent* dent;
uci1 0:664899e0b988 263
uci1 16:744ce85aede2 264 SnCommWin::ECommWinResult rs = SnCommWin::kOkMsgSent;
uci1 0:664899e0b988 265
uci1 0:664899e0b988 266 if ( (d = opendir( kSDsubDir ))!=NULL ) {
uci1 0:664899e0b988 267 FILE* f;
uci1 0:664899e0b988 268 while ( (dent = readdir(d))!=NULL ) {
uci1 0:664899e0b988 269 if (strncmp(dent->d_name, "SnEvts", 6)==0) {
uci1 1:e392595b4b76 270 const bool isCurFile =
uci1 1:e392595b4b76 271 (strcmp(dent->d_name, GetCurFileName())==0);
uci1 1:e392595b4b76 272 if (isCurFile) {
uci1 3:24c5f0f50bf1 273 // file must already be written out!
uci1 1:e392595b4b76 274 f = GetCurFile();
uci1 1:e392595b4b76 275 } else {
uci1 3:24c5f0f50bf1 276 f = OpenExistingFile(dent->d_name, false);
uci1 1:e392595b4b76 277 }
uci1 12:d472f9811262 278 #ifdef DEBUG
uci1 12:d472f9811262 279 printf("calling senddata: f=%p (cur %p), fn=%s\r\n",
uci1 12:d472f9811262 280 f, GetCurFile(), dent->d_name);
uci1 12:d472f9811262 281 #endif
uci1 16:744ce85aede2 282 const SnCommWin::ECommWinResult res =
uci1 16:744ce85aede2 283 comm->SendData(f, dent->d_name,
uci1 16:744ce85aede2 284 curConf, evt, pow, buf, bsize,
uci1 16:744ce85aede2 285 0, timeout, handshakeTimeout);
uci1 16:744ce85aede2 286 if (res<rs) {
uci1 16:744ce85aede2 287 rs = res;
uci1 16:744ce85aede2 288 }
uci1 16:744ce85aede2 289 // don't stop if res is bad. don't want one bad file to
uci1 16:744ce85aede2 290 // prevent sending the others
uci1 16:744ce85aede2 291
uci1 12:d472f9811262 292 // send data should close or delete the file (if appropriate)
uci1 12:d472f9811262 293 // unless it's the current file
uci1 3:24c5f0f50bf1 294 if (isCurFile) {
uci1 3:24c5f0f50bf1 295 // move (back) to the end of the file
uci1 3:24c5f0f50bf1 296 // altho hopefully no writing will happen after this
uci1 3:24c5f0f50bf1 297 fseek(fgCurFile, 0, SEEK_END);
uci1 0:664899e0b988 298 }
uci1 0:664899e0b988 299 }
uci1 0:664899e0b988 300 }
uci1 0:664899e0b988 301 closedir(d);
uci1 0:664899e0b988 302 }
uci1 0:664899e0b988 303
uci1 0:664899e0b988 304 return rs;
uci1 0:664899e0b988 305 }
uci1 0:664899e0b988 306