Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
SnSDUtils.cpp@16:744ce85aede2, 2012-09-12 (annotated)
- Committer:
- uci1
- Date:
- Wed Sep 12 04:47:22 2012 +0000
- Revision:
- 16:744ce85aede2
- Parent:
- 15:f2569d8e4176
- Child:
- 19:74155d652c37
SBD comm seems to be working. USB comm seems to be working (at 115200 baud). AFAR comm seems to be working. This version is set for USB communication and has zero text output.
Who changed what in which revision?
User | Revision | Line number | New 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 | 0:664899e0b988 | 5 | #include <string.h> |
uci1 | 12:d472f9811262 | 6 | #include <string> |
uci1 | 0:664899e0b988 | 7 | |
uci1 | 0:664899e0b988 | 8 | #include "SnConfigFrame.h" |
uci1 | 0:664899e0b988 | 9 | #include "SnEventFrame.h" |
uci1 | 0:664899e0b988 | 10 | |
uci1 | 15:f2569d8e4176 | 11 | //#define DEBUG |
uci1 | 0:664899e0b988 | 12 | |
uci1 | 1:e392595b4b76 | 13 | const char* const SnSDUtils::kSDsubDir = "/sd"; |
uci1 | 2:e67f7c158087 | 14 | char SnSDUtils::fgCurFileName[kFNBufSize]={0}; |
uci1 | 1:e392595b4b76 | 15 | FILE* SnSDUtils::fgCurFile = 0; |
uci1 | 12:d472f9811262 | 16 | uint16_t SnSDUtils::fgCurSeq = 0; |
uci1 | 8:95a325df1f6b | 17 | const uint8_t SnSDUtils::kIOvers = 3; |
uci1 | 5:9cea89700c66 | 18 | const uint32_t SnSDUtils::kMaxSizeOfFileHdr = |
uci1 | 5:9cea89700c66 | 19 | sizeof(uint8_t)+sizeof(uint64_t)+sizeof(uint32_t)+sizeof(uint16_t) |
uci1 | 8:95a325df1f6b | 20 | +(sizeof(uint8_t)+(2u*sizeof(uint16_t))); // power frame v1 |
uci1 | 4:a91682e19d6b | 21 | |
uci1 | 4:a91682e19d6b | 22 | static const uint16_t __kMaxUShort = ~0; |
uci1 | 0:664899e0b988 | 23 | |
uci1 | 0:664899e0b988 | 24 | const char* SnSDUtils::GetOutFileName(const uint64_t macadr, |
uci1 | 0:664899e0b988 | 25 | const uint32_t run, |
uci1 | 0:664899e0b988 | 26 | const uint16_t seq) { |
uci1 | 0:664899e0b988 | 27 | // returns the formatted file name, or NULL if the directory is too long |
uci1 | 0:664899e0b988 | 28 | // and the full name cannot fit in the buffer |
uci1 | 0:664899e0b988 | 29 | // NOTE: this fcn uses a static buffer, and so should not be called |
uci1 | 0:664899e0b988 | 30 | // multiple times in the same line (that includes the calling of functions |
uci1 | 0:664899e0b988 | 31 | // that call this function!) |
uci1 | 0:664899e0b988 | 32 | // |
uci1 | 0:664899e0b988 | 33 | // filename = SnEvtsM[6-byte hex mac adr]r[6-digit run num]s[5-digit seq num].dat |
uci1 | 0:664899e0b988 | 34 | // 35 chars 7 + 12 +1+ 5 +1+ 5 + 4 |
uci1 | 0:664899e0b988 | 35 | |
uci1 | 0:664899e0b988 | 36 | if (strlen(kSDsubDir)<(kFNBufSize-37)) { |
uci1 | 0:664899e0b988 | 37 | static char tbuf[kFNBufSize]; |
uci1 | 0:664899e0b988 | 38 | memset(tbuf, 0, sizeof(char)*kFNBufSize); |
uci1 | 0:664899e0b988 | 39 | // if file name format changes, GetSeqNum must be changed too |
uci1 | 0:664899e0b988 | 40 | sprintf(tbuf, "%s/SnEvtsM%012llXr%05ds%05d.dat", |
uci1 | 0:664899e0b988 | 41 | kSDsubDir, |
uci1 | 0:664899e0b988 | 42 | macadr>>16, // 64 -> 48 bits |
uci1 | 0:664899e0b988 | 43 | run, seq); |
uci1 | 0:664899e0b988 | 44 | return tbuf; |
uci1 | 0:664899e0b988 | 45 | } else { |
uci1 | 0:664899e0b988 | 46 | return NULL; |
uci1 | 0:664899e0b988 | 47 | } |
uci1 | 0:664899e0b988 | 48 | } |
uci1 | 12:d472f9811262 | 49 | /* |
uci1 | 10:3c93db1cfb12 | 50 | uint16_t SnSDUtils::GetCurSeqNum() { |
uci1 | 10:3c93db1cfb12 | 51 | return GetSeqNumFromFileName(fgCurFileName); |
uci1 | 10:3c93db1cfb12 | 52 | } |
uci1 | 12:d472f9811262 | 53 | */ |
uci1 | 10:3c93db1cfb12 | 54 | uint16_t SnSDUtils::GetSeqNumFromFileName(const char* fn) { |
uci1 | 10:3c93db1cfb12 | 55 | uint16_t seq=0; |
uci1 | 10:3c93db1cfb12 | 56 | const uint32_t ncomp = strrchr(fn, 's') - fn; |
uci1 | 10:3c93db1cfb12 | 57 | if (ncomp<strlen(fn)) { |
uci1 | 10:3c93db1cfb12 | 58 | sscanf(fn+ncomp,"s%hu.dat",&seq); |
uci1 | 10:3c93db1cfb12 | 59 | } |
uci1 | 10:3c93db1cfb12 | 60 | return seq; |
uci1 | 10:3c93db1cfb12 | 61 | } |
uci1 | 10:3c93db1cfb12 | 62 | |
uci1 | 0:664899e0b988 | 63 | uint16_t SnSDUtils::GetSeqNum(const uint64_t macadr, |
uci1 | 0:664899e0b988 | 64 | const uint32_t run) { |
uci1 | 0:664899e0b988 | 65 | // count the files having expected filename format |
uci1 | 0:664899e0b988 | 66 | |
uci1 | 0:664899e0b988 | 67 | const char* fn = GetOutFileName(macadr, run, 0) |
uci1 | 0:664899e0b988 | 68 | + strlen(kSDsubDir) + 1; // take out dir and '/'s |
uci1 | 0:664899e0b988 | 69 | |
uci1 | 0:664899e0b988 | 70 | DIR* d; |
uci1 | 0:664899e0b988 | 71 | struct dirent* dent; |
uci1 | 0:664899e0b988 | 72 | |
uci1 | 6:6f002d202f59 | 73 | uint16_t seq=0, newseq=0; |
uci1 | 0:664899e0b988 | 74 | if ( (d = opendir( kSDsubDir ))!=NULL ) { |
uci1 | 0:664899e0b988 | 75 | // don't compare seq#. don't use num of chars in case seq is >999 |
uci1 | 0:664899e0b988 | 76 | const uint32_t ncomp = strrchr(fn, 's') - fn; |
uci1 | 0:664899e0b988 | 77 | while ( (dent = readdir(d))!=NULL ) { |
uci1 | 0:664899e0b988 | 78 | if (strncmp(dent->d_name, fn, ncomp)==0) { |
uci1 | 6:6f002d202f59 | 79 | // allow for deleted files to make gaps. |
uci1 | 6:6f002d202f59 | 80 | // search for highest seq number and increase that |
uci1 | 7:079617408fec | 81 | sscanf((dent->d_name)+ncomp,"s%hu.dat",&seq); |
uci1 | 12:d472f9811262 | 82 | #ifdef DEBUG |
uci1 | 7:079617408fec | 83 | /* |
uci1 | 7:079617408fec | 84 | printf("dn=%s, seq=%hu, __kMaxUShort=%hu\r\n", |
uci1 | 7:079617408fec | 85 | dent->d_name, seq, __kMaxUShort); |
uci1 | 7:079617408fec | 86 | */ |
uci1 | 12:d472f9811262 | 87 | #endif |
uci1 | 4:a91682e19d6b | 88 | if (seq==__kMaxUShort) { |
uci1 | 6:6f002d202f59 | 89 | newseq = seq; |
uci1 | 6:6f002d202f59 | 90 | break; |
uci1 | 6:6f002d202f59 | 91 | } |
uci1 | 6:6f002d202f59 | 92 | if (seq>=newseq) { |
uci1 | 6:6f002d202f59 | 93 | newseq=seq+1; |
uci1 | 6:6f002d202f59 | 94 | } |
uci1 | 6:6f002d202f59 | 95 | if (newseq==__kMaxUShort) { |
uci1 | 4:a91682e19d6b | 96 | break; |
uci1 | 4:a91682e19d6b | 97 | } |
uci1 | 0:664899e0b988 | 98 | } |
uci1 | 0:664899e0b988 | 99 | } |
uci1 | 0:664899e0b988 | 100 | closedir(d); |
uci1 | 0:664899e0b988 | 101 | } |
uci1 | 7:079617408fec | 102 | |
uci1 | 6:6f002d202f59 | 103 | return newseq; |
uci1 | 0:664899e0b988 | 104 | } |
uci1 | 0:664899e0b988 | 105 | |
uci1 | 3:24c5f0f50bf1 | 106 | FILE* SnSDUtils::OpenExistingFile(const char* name, const bool setcurrent) { |
uci1 | 0:664899e0b988 | 107 | FILE* f = 0; |
uci1 | 0:664899e0b988 | 108 | if (name!=NULL) { |
uci1 | 3:24c5f0f50bf1 | 109 | f = OpenSDFile(name, "rb"); |
uci1 | 12:d472f9811262 | 110 | /* |
uci1 | 3:24c5f0f50bf1 | 111 | if (setcurrent) { |
uci1 | 3:24c5f0f50bf1 | 112 | fgCurFile = f; |
uci1 | 12:d472f9811262 | 113 | strncpy(fgCurFileName, name, kFNBufSize-1); |
uci1 | 12:d472f9811262 | 114 | fgCurSeq = GetSeqNumFromFileName(fgCurFileName); |
uci1 | 3:24c5f0f50bf1 | 115 | } |
uci1 | 12:d472f9811262 | 116 | */ |
uci1 | 0:664899e0b988 | 117 | } |
uci1 | 0:664899e0b988 | 118 | return f; |
uci1 | 0:664899e0b988 | 119 | } |
uci1 | 0:664899e0b988 | 120 | |
uci1 | 3:24c5f0f50bf1 | 121 | FILE* SnSDUtils::OpenSDFile(const char* name, const char* mode) { |
uci1 | 12:d472f9811262 | 122 | // TODO: check if we have memory? |
uci1 | 12:d472f9811262 | 123 | std::string fn(name); |
uci1 | 12:d472f9811262 | 124 | if (strncmp(name, kSDsubDir, strlen(kSDsubDir))!=0) { |
uci1 | 12:d472f9811262 | 125 | // filename lacks directory |
uci1 | 12:d472f9811262 | 126 | fn = kSDsubDir; |
uci1 | 12:d472f9811262 | 127 | fn += "/"; |
uci1 | 12:d472f9811262 | 128 | fn += name; |
uci1 | 12:d472f9811262 | 129 | } |
uci1 | 12:d472f9811262 | 130 | #ifdef DEBUG |
uci1 | 12:d472f9811262 | 131 | printf("OpenSDFile: %s, mode %s\r\n",fn.c_str(),mode); |
uci1 | 12:d472f9811262 | 132 | #endif |
uci1 | 12:d472f9811262 | 133 | FILE* f = fopen(fn.c_str(), mode); |
uci1 | 1:e392595b4b76 | 134 | //setvbuf(f, 0, _IONBF, 0); // no buffering |
uci1 | 1:e392595b4b76 | 135 | return f; |
uci1 | 1:e392595b4b76 | 136 | } |
uci1 | 1:e392595b4b76 | 137 | |
uci1 | 0:664899e0b988 | 138 | FILE* SnSDUtils::OpenNewOutputFile(const uint64_t macadr, |
uci1 | 8:95a325df1f6b | 139 | const uint32_t run) { |
uci1 | 0:664899e0b988 | 140 | // opens a new file in the specified directory and writes this |
uci1 | 0:664899e0b988 | 141 | // this mbed's mac address as the first sizeof(uint64_t) bytes (i.e. 4 bytes) |
uci1 | 0:664899e0b988 | 142 | // |
uci1 | 12:d472f9811262 | 143 | fgCurSeq = GetSeqNum(macadr, run); |
uci1 | 0:664899e0b988 | 144 | memset(fgCurFileName, 0, sizeof(char)*kFNBufSize); |
uci1 | 12:d472f9811262 | 145 | strncpy(fgCurFileName,GetOutFileName(macadr, run, fgCurSeq),kFNBufSize-1); |
uci1 | 12:d472f9811262 | 146 | //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,fgCurSeq); |
uci1 | 1:e392595b4b76 | 147 | fgCurFile = 0; |
uci1 | 0:664899e0b988 | 148 | if (fgCurFileName!=NULL) { |
uci1 | 3:24c5f0f50bf1 | 149 | fgCurFile = OpenSDFile(fgCurFileName, "wb"); |
uci1 | 2:e67f7c158087 | 150 | if (fgCurFile!=NULL && ferror(fgCurFile)==0) { |
uci1 | 12:d472f9811262 | 151 | WriteFileHeader(fgCurFile, macadr, run, fgCurSeq); |
uci1 | 2:e67f7c158087 | 152 | } |
uci1 | 0:664899e0b988 | 153 | } |
uci1 | 1:e392595b4b76 | 154 | return fgCurFile; |
uci1 | 0:664899e0b988 | 155 | } |
uci1 | 0:664899e0b988 | 156 | |
uci1 | 0:664899e0b988 | 157 | bool SnSDUtils::WriteEventTo(FILE* efile, char* const evtBuf, |
uci1 | 0:664899e0b988 | 158 | const SnEventFrame& evt, |
uci1 | 0:664899e0b988 | 159 | const SnConfigFrame& conf) { |
uci1 | 0:664899e0b988 | 160 | // write event to SD card |
uci1 | 0:664899e0b988 | 161 | |
uci1 | 0:664899e0b988 | 162 | uint8_t sLoseLSB=0, sLoseMSB=0; |
uci1 | 0:664899e0b988 | 163 | uint16_t sWvBase=0; |
uci1 | 0:664899e0b988 | 164 | conf.GetPackParsFor(SnConfigFrame::kSDcard, sLoseLSB, sLoseMSB, sWvBase); |
uci1 | 8:95a325df1f6b | 165 | SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kEventCode, |
uci1 | 8:95a325df1f6b | 166 | evt.SizeOf(SnEventFrame::kIOVers, sLoseLSB, sLoseMSB)); |
uci1 | 0:664899e0b988 | 167 | const bool ret = evt.WriteTo(efile, evtBuf, sLoseLSB, sLoseMSB, sWvBase); |
uci1 | 0:664899e0b988 | 168 | fflush(efile); |
uci1 | 0:664899e0b988 | 169 | return ret; |
uci1 | 0:664899e0b988 | 170 | } |
uci1 | 0:664899e0b988 | 171 | |
uci1 | 0:664899e0b988 | 172 | bool SnSDUtils::WriteConfig(FILE* efile, |
uci1 | 0:664899e0b988 | 173 | const SnConfigFrame& conf) { |
uci1 | 8:95a325df1f6b | 174 | SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kConfigCode, |
uci1 | 8:95a325df1f6b | 175 | conf.SizeOf(SnConfigFrame::kIOVers)); |
uci1 | 0:664899e0b988 | 176 | conf.WriteTo(efile); |
uci1 | 0:664899e0b988 | 177 | return true; |
uci1 | 0:664899e0b988 | 178 | } |
uci1 | 0:664899e0b988 | 179 | |
uci1 | 0:664899e0b988 | 180 | void SnSDUtils::DeleteFile(FILE*& f, const char* fname) { |
uci1 | 0:664899e0b988 | 181 | fclose(f); |
uci1 | 0:664899e0b988 | 182 | f=0; |
uci1 | 0:664899e0b988 | 183 | remove(fname); |
uci1 | 0:664899e0b988 | 184 | } |
uci1 | 0:664899e0b988 | 185 | |
uci1 | 0:664899e0b988 | 186 | SnCommWin::ECommWinResult SnSDUtils::SendAllFiles(SnCommWin* comm, |
uci1 | 3:24c5f0f50bf1 | 187 | const uint32_t timeout, |
uci1 | 3:24c5f0f50bf1 | 188 | char* const buf, |
uci1 | 6:6f002d202f59 | 189 | const uint32_t bsize, |
uci1 | 6:6f002d202f59 | 190 | const SnConfigFrame& curConf, |
uci1 | 8:95a325df1f6b | 191 | SnEventFrame& evt, |
uci1 | 12:d472f9811262 | 192 | SnPowerFrame& pow, |
uci1 | 12:d472f9811262 | 193 | const uint32_t handshakeTimeout) { |
uci1 | 16:744ce85aede2 | 194 | |
uci1 | 0:664899e0b988 | 195 | DIR* d; |
uci1 | 0:664899e0b988 | 196 | struct dirent* dent; |
uci1 | 0:664899e0b988 | 197 | |
uci1 | 16:744ce85aede2 | 198 | SnCommWin::ECommWinResult rs = SnCommWin::kOkMsgSent; |
uci1 | 0:664899e0b988 | 199 | |
uci1 | 12:d472f9811262 | 200 | const bool doDelete = curConf.IsDeletingFiles(); |
uci1 | 12:d472f9811262 | 201 | |
uci1 | 0:664899e0b988 | 202 | if ( (d = opendir( kSDsubDir ))!=NULL ) { |
uci1 | 0:664899e0b988 | 203 | FILE* f; |
uci1 | 0:664899e0b988 | 204 | while ( (dent = readdir(d))!=NULL ) { |
uci1 | 0:664899e0b988 | 205 | if (strncmp(dent->d_name, "SnEvts", 6)==0) { |
uci1 | 1:e392595b4b76 | 206 | const bool isCurFile = |
uci1 | 1:e392595b4b76 | 207 | (strcmp(dent->d_name, GetCurFileName())==0); |
uci1 | 1:e392595b4b76 | 208 | if (isCurFile) { |
uci1 | 3:24c5f0f50bf1 | 209 | // file must already be written out! |
uci1 | 1:e392595b4b76 | 210 | f = GetCurFile(); |
uci1 | 1:e392595b4b76 | 211 | } else { |
uci1 | 3:24c5f0f50bf1 | 212 | f = OpenExistingFile(dent->d_name, false); |
uci1 | 1:e392595b4b76 | 213 | } |
uci1 | 12:d472f9811262 | 214 | #ifdef DEBUG |
uci1 | 12:d472f9811262 | 215 | printf("calling senddata: f=%p (cur %p), fn=%s\r\n", |
uci1 | 12:d472f9811262 | 216 | f, GetCurFile(), dent->d_name); |
uci1 | 12:d472f9811262 | 217 | #endif |
uci1 | 16:744ce85aede2 | 218 | const SnCommWin::ECommWinResult res = |
uci1 | 16:744ce85aede2 | 219 | comm->SendData(f, dent->d_name, |
uci1 | 16:744ce85aede2 | 220 | curConf, evt, pow, buf, bsize, |
uci1 | 16:744ce85aede2 | 221 | 0, timeout, handshakeTimeout); |
uci1 | 16:744ce85aede2 | 222 | if (res<rs) { |
uci1 | 16:744ce85aede2 | 223 | rs = res; |
uci1 | 16:744ce85aede2 | 224 | } |
uci1 | 16:744ce85aede2 | 225 | // don't stop if res is bad. don't want one bad file to |
uci1 | 16:744ce85aede2 | 226 | // prevent sending the others |
uci1 | 16:744ce85aede2 | 227 | |
uci1 | 12:d472f9811262 | 228 | // send data should close or delete the file (if appropriate) |
uci1 | 12:d472f9811262 | 229 | // unless it's the current file |
uci1 | 3:24c5f0f50bf1 | 230 | if (isCurFile) { |
uci1 | 3:24c5f0f50bf1 | 231 | // move (back) to the end of the file |
uci1 | 3:24c5f0f50bf1 | 232 | // altho hopefully no writing will happen after this |
uci1 | 3:24c5f0f50bf1 | 233 | fseek(fgCurFile, 0, SEEK_END); |
uci1 | 0:664899e0b988 | 234 | } |
uci1 | 0:664899e0b988 | 235 | } |
uci1 | 0:664899e0b988 | 236 | } |
uci1 | 0:664899e0b988 | 237 | closedir(d); |
uci1 | 0:664899e0b988 | 238 | } |
uci1 | 0:664899e0b988 | 239 | |
uci1 | 0:664899e0b988 | 240 | return rs; |
uci1 | 0:664899e0b988 | 241 | } |
uci1 | 0:664899e0b988 | 242 |