Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
SnSDUtils.cpp@4:a91682e19d6b, 2012-08-02 (annotated)
- Committer:
- uci1
- Date:
- Thu Aug 02 05:42:47 2012 +0000
- Revision:
- 4:a91682e19d6b
- Parent:
- 3:24c5f0f50bf1
- Child:
- 5:9cea89700c66
Add power reading, once per file. Prevent seq number from wrapping around. Still many debugging messages. Communications not finished.
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 | 0:664899e0b988 | 6 | |
uci1 | 0:664899e0b988 | 7 | #include "SnConfigFrame.h" |
uci1 | 0:664899e0b988 | 8 | #include "SnEventFrame.h" |
uci1 | 4:a91682e19d6b | 9 | #include "SnPowerFrame.h" |
uci1 | 0:664899e0b988 | 10 | |
uci1 | 0:664899e0b988 | 11 | |
uci1 | 1:e392595b4b76 | 12 | const char* const SnSDUtils::kSDsubDir = "/sd"; |
uci1 | 2:e67f7c158087 | 13 | char SnSDUtils::fgCurFileName[kFNBufSize]={0}; |
uci1 | 1:e392595b4b76 | 14 | FILE* SnSDUtils::fgCurFile = 0; |
uci1 | 4:a91682e19d6b | 15 | const uint8_t SnSDUtils::kIOvers = 2; |
uci1 | 4:a91682e19d6b | 16 | |
uci1 | 4:a91682e19d6b | 17 | static const uint16_t __kMaxUShort = ~0; |
uci1 | 0:664899e0b988 | 18 | |
uci1 | 0:664899e0b988 | 19 | const char* SnSDUtils::GetOutFileName(const uint64_t macadr, |
uci1 | 0:664899e0b988 | 20 | const uint32_t run, |
uci1 | 0:664899e0b988 | 21 | const uint16_t seq) { |
uci1 | 0:664899e0b988 | 22 | // returns the formatted file name, or NULL if the directory is too long |
uci1 | 0:664899e0b988 | 23 | // and the full name cannot fit in the buffer |
uci1 | 0:664899e0b988 | 24 | // NOTE: this fcn uses a static buffer, and so should not be called |
uci1 | 0:664899e0b988 | 25 | // multiple times in the same line (that includes the calling of functions |
uci1 | 0:664899e0b988 | 26 | // that call this function!) |
uci1 | 0:664899e0b988 | 27 | // |
uci1 | 0:664899e0b988 | 28 | // filename = SnEvtsM[6-byte hex mac adr]r[6-digit run num]s[5-digit seq num].dat |
uci1 | 0:664899e0b988 | 29 | // 35 chars 7 + 12 +1+ 5 +1+ 5 + 4 |
uci1 | 0:664899e0b988 | 30 | |
uci1 | 0:664899e0b988 | 31 | if (strlen(kSDsubDir)<(kFNBufSize-37)) { |
uci1 | 0:664899e0b988 | 32 | static char tbuf[kFNBufSize]; |
uci1 | 0:664899e0b988 | 33 | memset(tbuf, 0, sizeof(char)*kFNBufSize); |
uci1 | 0:664899e0b988 | 34 | // if file name format changes, GetSeqNum must be changed too |
uci1 | 0:664899e0b988 | 35 | sprintf(tbuf, "%s/SnEvtsM%012llXr%05ds%05d.dat", |
uci1 | 0:664899e0b988 | 36 | kSDsubDir, |
uci1 | 0:664899e0b988 | 37 | macadr>>16, // 64 -> 48 bits |
uci1 | 0:664899e0b988 | 38 | run, seq); |
uci1 | 0:664899e0b988 | 39 | return tbuf; |
uci1 | 0:664899e0b988 | 40 | } else { |
uci1 | 0:664899e0b988 | 41 | return NULL; |
uci1 | 0:664899e0b988 | 42 | } |
uci1 | 0:664899e0b988 | 43 | } |
uci1 | 0:664899e0b988 | 44 | |
uci1 | 0:664899e0b988 | 45 | uint16_t SnSDUtils::GetSeqNum(const uint64_t macadr, |
uci1 | 0:664899e0b988 | 46 | const uint32_t run) { |
uci1 | 0:664899e0b988 | 47 | // count the files having expected filename format |
uci1 | 0:664899e0b988 | 48 | |
uci1 | 0:664899e0b988 | 49 | const char* fn = GetOutFileName(macadr, run, 0) |
uci1 | 0:664899e0b988 | 50 | + strlen(kSDsubDir) + 1; // take out dir and '/'s |
uci1 | 0:664899e0b988 | 51 | |
uci1 | 0:664899e0b988 | 52 | DIR* d; |
uci1 | 0:664899e0b988 | 53 | struct dirent* dent; |
uci1 | 0:664899e0b988 | 54 | |
uci1 | 0:664899e0b988 | 55 | uint16_t seq=0; |
uci1 | 0:664899e0b988 | 56 | if ( (d = opendir( kSDsubDir ))!=NULL ) { |
uci1 | 0:664899e0b988 | 57 | // don't compare seq#. don't use num of chars in case seq is >999 |
uci1 | 0:664899e0b988 | 58 | const uint32_t ncomp = strrchr(fn, 's') - fn; |
uci1 | 0:664899e0b988 | 59 | while ( (dent = readdir(d))!=NULL ) { |
uci1 | 0:664899e0b988 | 60 | if (strncmp(dent->d_name, fn, ncomp)==0) { |
uci1 | 0:664899e0b988 | 61 | seq++; |
uci1 | 4:a91682e19d6b | 62 | if (seq==__kMaxUShort) { |
uci1 | 4:a91682e19d6b | 63 | break; |
uci1 | 4:a91682e19d6b | 64 | } |
uci1 | 0:664899e0b988 | 65 | } |
uci1 | 0:664899e0b988 | 66 | } |
uci1 | 0:664899e0b988 | 67 | closedir(d); |
uci1 | 0:664899e0b988 | 68 | } |
uci1 | 0:664899e0b988 | 69 | |
uci1 | 0:664899e0b988 | 70 | return seq; |
uci1 | 0:664899e0b988 | 71 | } |
uci1 | 0:664899e0b988 | 72 | |
uci1 | 3:24c5f0f50bf1 | 73 | FILE* SnSDUtils::OpenExistingFile(const char* name, const bool setcurrent) { |
uci1 | 0:664899e0b988 | 74 | FILE* f = 0; |
uci1 | 0:664899e0b988 | 75 | if (name!=NULL) { |
uci1 | 3:24c5f0f50bf1 | 76 | f = OpenSDFile(name, "rb"); |
uci1 | 3:24c5f0f50bf1 | 77 | if (setcurrent) { |
uci1 | 3:24c5f0f50bf1 | 78 | fgCurFile = f; |
uci1 | 3:24c5f0f50bf1 | 79 | } |
uci1 | 0:664899e0b988 | 80 | } |
uci1 | 0:664899e0b988 | 81 | return f; |
uci1 | 0:664899e0b988 | 82 | } |
uci1 | 0:664899e0b988 | 83 | |
uci1 | 3:24c5f0f50bf1 | 84 | FILE* SnSDUtils::OpenSDFile(const char* name, const char* mode) { |
uci1 | 3:24c5f0f50bf1 | 85 | FILE* f = fopen(name, mode); |
uci1 | 1:e392595b4b76 | 86 | //setvbuf(f, 0, _IONBF, 0); // no buffering |
uci1 | 1:e392595b4b76 | 87 | return f; |
uci1 | 1:e392595b4b76 | 88 | } |
uci1 | 1:e392595b4b76 | 89 | |
uci1 | 0:664899e0b988 | 90 | FILE* SnSDUtils::OpenNewOutputFile(const uint64_t macadr, |
uci1 | 4:a91682e19d6b | 91 | const uint32_t run, |
uci1 | 4:a91682e19d6b | 92 | const uint16_t v1, const uint16_t v2) { |
uci1 | 0:664899e0b988 | 93 | // opens a new file in the specified directory and writes this |
uci1 | 0:664899e0b988 | 94 | // this mbed's mac address as the first sizeof(uint64_t) bytes (i.e. 4 bytes) |
uci1 | 0:664899e0b988 | 95 | // |
uci1 | 0:664899e0b988 | 96 | const uint16_t seq = GetSeqNum(macadr, run); |
uci1 | 0:664899e0b988 | 97 | memset(fgCurFileName, 0, sizeof(char)*kFNBufSize); |
uci1 | 2:e67f7c158087 | 98 | strncpy(fgCurFileName,GetOutFileName(macadr, run, seq),kFNBufSize-1); |
uci1 | 0:664899e0b988 | 99 | //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,seq); |
uci1 | 1:e392595b4b76 | 100 | fgCurFile = 0; |
uci1 | 0:664899e0b988 | 101 | if (fgCurFileName!=NULL) { |
uci1 | 3:24c5f0f50bf1 | 102 | fgCurFile = OpenSDFile(fgCurFileName, "wb"); |
uci1 | 2:e67f7c158087 | 103 | if (fgCurFile!=NULL && ferror(fgCurFile)==0) { |
uci1 | 4:a91682e19d6b | 104 | WriteFileHeader(fgCurFile, macadr, run, seq, v1, v2); |
uci1 | 2:e67f7c158087 | 105 | } |
uci1 | 0:664899e0b988 | 106 | } |
uci1 | 1:e392595b4b76 | 107 | return fgCurFile; |
uci1 | 0:664899e0b988 | 108 | } |
uci1 | 0:664899e0b988 | 109 | |
uci1 | 2:e67f7c158087 | 110 | bool SnSDUtils::WriteFileHeader(FILE* f, const uint64_t macadr, |
uci1 | 4:a91682e19d6b | 111 | const uint32_t run, const uint16_t seq, |
uci1 | 4:a91682e19d6b | 112 | const uint16_t v1, const uint16_t v2) { |
uci1 | 0:664899e0b988 | 113 | // MUST INCREMENT kIOvers if these writes are altered |
uci1 | 0:664899e0b988 | 114 | fwrite(&kIOvers, sizeof(uint8_t), 1, f); |
uci1 | 0:664899e0b988 | 115 | fwrite(&macadr, sizeof(uint64_t), 1, f); |
uci1 | 2:e67f7c158087 | 116 | fwrite(&run, sizeof(uint32_t), 1, f); |
uci1 | 2:e67f7c158087 | 117 | fwrite(&seq, sizeof(uint16_t), 1, f); |
uci1 | 4:a91682e19d6b | 118 | SnPowerFrame::WriteTo(f, v1, v2); |
uci1 | 1:e392595b4b76 | 119 | fflush(f); |
uci1 | 0:664899e0b988 | 120 | return ferror(f); |
uci1 | 0:664899e0b988 | 121 | } |
uci1 | 0:664899e0b988 | 122 | |
uci1 | 2:e67f7c158087 | 123 | bool SnSDUtils::ReadFileHeader(FILE* f, uint64_t& macadr, |
uci1 | 4:a91682e19d6b | 124 | uint32_t& run, uint16_t& seq, |
uci1 | 4:a91682e19d6b | 125 | uint16_t& v1, uint16_t& v2) { |
uci1 | 2:e67f7c158087 | 126 | uint8_t Rv=0; |
uci1 | 2:e67f7c158087 | 127 | fread(&Rv, sizeof(uint8_t), 1, f); |
uci1 | 2:e67f7c158087 | 128 | fread(&macadr, sizeof(uint64_t), 1, f); |
uci1 | 2:e67f7c158087 | 129 | fread(&run, sizeof(uint32_t), 1, f); |
uci1 | 2:e67f7c158087 | 130 | fread(&seq, sizeof(uint16_t), 1, f); |
uci1 | 4:a91682e19d6b | 131 | if (Rv>1) { |
uci1 | 4:a91682e19d6b | 132 | SnPowerFrame::ReadFrom(f, v1, v2); |
uci1 | 4:a91682e19d6b | 133 | } |
uci1 | 2:e67f7c158087 | 134 | return ferror(f); |
uci1 | 2:e67f7c158087 | 135 | } |
uci1 | 2:e67f7c158087 | 136 | |
uci1 | 0:664899e0b988 | 137 | bool SnSDUtils::WriteEventTo(FILE* efile, char* const evtBuf, |
uci1 | 0:664899e0b988 | 138 | const SnEventFrame& evt, |
uci1 | 0:664899e0b988 | 139 | const SnConfigFrame& conf) { |
uci1 | 0:664899e0b988 | 140 | // write event to SD card |
uci1 | 0:664899e0b988 | 141 | |
uci1 | 0:664899e0b988 | 142 | uint8_t sLoseLSB=0, sLoseMSB=0; |
uci1 | 0:664899e0b988 | 143 | uint16_t sWvBase=0; |
uci1 | 0:664899e0b988 | 144 | conf.GetPackParsFor(SnConfigFrame::kSDcard, sLoseLSB, sLoseMSB, sWvBase); |
uci1 | 0:664899e0b988 | 145 | const bool ret = evt.WriteTo(efile, evtBuf, sLoseLSB, sLoseMSB, sWvBase); |
uci1 | 0:664899e0b988 | 146 | fflush(efile); |
uci1 | 0:664899e0b988 | 147 | return ret; |
uci1 | 0:664899e0b988 | 148 | } |
uci1 | 0:664899e0b988 | 149 | |
uci1 | 0:664899e0b988 | 150 | bool SnSDUtils::WriteConfig(FILE* efile, |
uci1 | 0:664899e0b988 | 151 | const SnConfigFrame& conf) { |
uci1 | 0:664899e0b988 | 152 | conf.WriteTo(efile); |
uci1 | 0:664899e0b988 | 153 | return true; |
uci1 | 0:664899e0b988 | 154 | } |
uci1 | 0:664899e0b988 | 155 | |
uci1 | 0:664899e0b988 | 156 | void SnSDUtils::DeleteFile(FILE*& f, const char* fname) { |
uci1 | 0:664899e0b988 | 157 | fclose(f); |
uci1 | 0:664899e0b988 | 158 | f=0; |
uci1 | 0:664899e0b988 | 159 | remove(fname); |
uci1 | 0:664899e0b988 | 160 | } |
uci1 | 0:664899e0b988 | 161 | |
uci1 | 0:664899e0b988 | 162 | SnCommWin::ECommWinResult SnSDUtils::SendAllFiles(SnCommWin* comm, |
uci1 | 3:24c5f0f50bf1 | 163 | const bool doDelete, |
uci1 | 3:24c5f0f50bf1 | 164 | const uint32_t timeout, |
uci1 | 3:24c5f0f50bf1 | 165 | char* const buf, |
uci1 | 3:24c5f0f50bf1 | 166 | const uint32_t bsize) { |
uci1 | 0:664899e0b988 | 167 | |
uci1 | 0:664899e0b988 | 168 | DIR* d; |
uci1 | 0:664899e0b988 | 169 | struct dirent* dent; |
uci1 | 0:664899e0b988 | 170 | |
uci1 | 0:664899e0b988 | 171 | SnCommWin::ECommWinResult rs = SnCommWin::kUndefFail; |
uci1 | 0:664899e0b988 | 172 | |
uci1 | 0:664899e0b988 | 173 | if ( (d = opendir( kSDsubDir ))!=NULL ) { |
uci1 | 0:664899e0b988 | 174 | FILE* f; |
uci1 | 0:664899e0b988 | 175 | while ( (dent = readdir(d))!=NULL ) { |
uci1 | 0:664899e0b988 | 176 | if (strncmp(dent->d_name, "SnEvts", 6)==0) { |
uci1 | 1:e392595b4b76 | 177 | const bool isCurFile = |
uci1 | 1:e392595b4b76 | 178 | (strcmp(dent->d_name, GetCurFileName())==0); |
uci1 | 1:e392595b4b76 | 179 | if (isCurFile) { |
uci1 | 3:24c5f0f50bf1 | 180 | // file must already be written out! |
uci1 | 1:e392595b4b76 | 181 | f = GetCurFile(); |
uci1 | 1:e392595b4b76 | 182 | } else { |
uci1 | 3:24c5f0f50bf1 | 183 | f = OpenExistingFile(dent->d_name, false); |
uci1 | 1:e392595b4b76 | 184 | } |
uci1 | 3:24c5f0f50bf1 | 185 | // send the filename |
uci1 | 3:24c5f0f50bf1 | 186 | rs = comm->SendFilename(dent->d_name, buf); |
uci1 | 0:664899e0b988 | 187 | if (rs<SnCommWin::kAllFails) { |
uci1 | 3:24c5f0f50bf1 | 188 | // send the data from the file |
uci1 | 3:24c5f0f50bf1 | 189 | rs = comm->SendData(f); |
uci1 | 3:24c5f0f50bf1 | 190 | if (rs<SnCommWin::kAllFails) { |
uci1 | 3:24c5f0f50bf1 | 191 | break; |
uci1 | 3:24c5f0f50bf1 | 192 | } else { |
uci1 | 3:24c5f0f50bf1 | 193 | // wait for handshake before next file |
uci1 | 3:24c5f0f50bf1 | 194 | rs = comm->WaitHandshake(timeout, buf, bsize); |
uci1 | 3:24c5f0f50bf1 | 195 | if ((rs==SnCommWin::kOkWithMsg) |
uci1 | 3:24c5f0f50bf1 | 196 | && doDelete && (isCurFile==false)) { |
uci1 | 3:24c5f0f50bf1 | 197 | DeleteFile(f, dent->d_name); |
uci1 | 3:24c5f0f50bf1 | 198 | } |
uci1 | 3:24c5f0f50bf1 | 199 | } |
uci1 | 3:24c5f0f50bf1 | 200 | } |
uci1 | 3:24c5f0f50bf1 | 201 | if (isCurFile) { |
uci1 | 3:24c5f0f50bf1 | 202 | // move (back) to the end of the file |
uci1 | 3:24c5f0f50bf1 | 203 | // altho hopefully no writing will happen after this |
uci1 | 3:24c5f0f50bf1 | 204 | fseek(fgCurFile, 0, SEEK_END); |
uci1 | 0:664899e0b988 | 205 | } |
uci1 | 0:664899e0b988 | 206 | } |
uci1 | 0:664899e0b988 | 207 | } |
uci1 | 0:664899e0b988 | 208 | closedir(d); |
uci1 | 0:664899e0b988 | 209 | } |
uci1 | 0:664899e0b988 | 210 | |
uci1 | 0:664899e0b988 | 211 | return rs; |
uci1 | 0:664899e0b988 | 212 | } |
uci1 | 0:664899e0b988 | 213 |