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