Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
SnEventFrame.cpp@8:95a325df1f6b, 2012-08-08 (annotated)
- Committer:
- uci1
- Date:
- Wed Aug 08 23:27:37 2012 +0000
- Revision:
- 8:95a325df1f6b
- Parent:
- 3:24c5f0f50bf1
- Child:
- 21:ce51bb0ba4a5
Check power for low pow running. Average power over 500 readings. Use RTOS timers instead of tickers. Allow data taking of events, power readings or both, even if cards are off. Bug in EthernetInterface prevents IPs being reset. Lots of debug output.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
uci1 | 0:664899e0b988 | 1 | #include "SnEventFrame.h" |
uci1 | 0:664899e0b988 | 2 | |
uci1 | 0:664899e0b988 | 3 | #include "SnCRCUtils.h" |
uci1 | 0:664899e0b988 | 4 | |
uci1 | 1:e392595b4b76 | 5 | const uint8_t SnEventFrame::kIOVers = 1; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) |
uci1 | 1:e392595b4b76 | 6 | |
uci1 | 3:24c5f0f50bf1 | 7 | const char* SnEventFrame::ReadFrom(const char* const buf, |
uci1 | 3:24c5f0f50bf1 | 8 | const uint8_t loseLSB, const uint8_t loseMSB, |
uci1 | 3:24c5f0f50bf1 | 9 | const uint16_t wvBaseline) { |
uci1 | 0:664899e0b988 | 10 | // no check on the length of buf is done here |
uci1 | 0:664899e0b988 | 11 | // that should be been done already |
uci1 | 0:664899e0b988 | 12 | // |
uci1 | 0:664899e0b988 | 13 | // must match ::WriteToBuf |
uci1 | 0:664899e0b988 | 14 | |
uci1 | 3:24c5f0f50bf1 | 15 | // NOTE: on the mbed, this is reduntant (char is unsigned) |
uci1 | 3:24c5f0f50bf1 | 16 | // but this way, the block can be copied to other computers |
uci1 | 3:24c5f0f50bf1 | 17 | // and still work. |
uci1 | 0:664899e0b988 | 18 | union Usub { |
uci1 | 0:664899e0b988 | 19 | const char* s; |
uci1 | 0:664899e0b988 | 20 | const uint8_t* u; |
uci1 | 0:664899e0b988 | 21 | } b; |
uci1 | 0:664899e0b988 | 22 | b.s = buf; |
uci1 | 0:664899e0b988 | 23 | |
uci1 | 1:e392595b4b76 | 24 | uint8_t Rv=0; |
uci1 | 0:664899e0b988 | 25 | b.s = SnBitUtils::ReadFrom(b.s, Rv); // i/o version |
uci1 | 0:664899e0b988 | 26 | if (Rv>0) { |
uci1 | 0:664899e0b988 | 27 | b.s = SnBitUtils::ReadFrom(b.s, fMbedTime); |
uci1 | 0:664899e0b988 | 28 | b.s = SnBitUtils::ReadFrom(b.s, fEvtNum); |
uci1 | 0:664899e0b988 | 29 | b.s = SnBitUtils::ReadFrom(b.s, fDTms); |
uci1 | 0:664899e0b988 | 30 | b.s = SnBitUtils::ReadFrom(b.s, fTrgNum); |
uci1 | 0:664899e0b988 | 31 | b.s = SnBitUtils::ReadFrom(b.s, fTrgBits); |
uci1 | 0:664899e0b988 | 32 | b.u = UnpackWavef(b.u, fData, loseLSB, loseMSB, wvBaseline); |
uci1 | 0:664899e0b988 | 33 | b.s = SnBitUtils::ReadFrom(b.s, fCRC); |
uci1 | 0:664899e0b988 | 34 | } |
uci1 | 0:664899e0b988 | 35 | |
uci1 | 3:24c5f0f50bf1 | 36 | return b.s; |
uci1 | 0:664899e0b988 | 37 | } |
uci1 | 0:664899e0b988 | 38 | |
uci1 | 3:24c5f0f50bf1 | 39 | char* SnEventFrame::WriteTo(char* const buf, |
uci1 | 3:24c5f0f50bf1 | 40 | const uint8_t loseLSB, const uint8_t loseMSB, |
uci1 | 3:24c5f0f50bf1 | 41 | const uint16_t wvBaseline) const { |
uci1 | 0:664899e0b988 | 42 | // no check on the length of the buf is done here |
uci1 | 0:664899e0b988 | 43 | // that should be done already |
uci1 | 0:664899e0b988 | 44 | // |
uci1 | 0:664899e0b988 | 45 | // must match ReadFromBuf |
uci1 | 0:664899e0b988 | 46 | |
uci1 | 3:24c5f0f50bf1 | 47 | // NOTE: on the mbed, this is reduntant (char is unsigned) |
uci1 | 3:24c5f0f50bf1 | 48 | // but this way, the block can be copied to other computers |
uci1 | 3:24c5f0f50bf1 | 49 | // and still work. |
uci1 | 0:664899e0b988 | 50 | union { |
uci1 | 0:664899e0b988 | 51 | char* s; |
uci1 | 0:664899e0b988 | 52 | uint8_t* u; |
uci1 | 0:664899e0b988 | 53 | } b; |
uci1 | 0:664899e0b988 | 54 | b.s = buf; |
uci1 | 0:664899e0b988 | 55 | |
uci1 | 0:664899e0b988 | 56 | b.s = SnBitUtils::WriteTo(b.s, kIOVers); // i/o version |
uci1 | 0:664899e0b988 | 57 | |
uci1 | 0:664899e0b988 | 58 | b.s = SnBitUtils::WriteTo(b.s, fMbedTime); |
uci1 | 0:664899e0b988 | 59 | b.s = SnBitUtils::WriteTo(b.s, fEvtNum); |
uci1 | 0:664899e0b988 | 60 | b.s = SnBitUtils::WriteTo(b.s, fDTms); |
uci1 | 0:664899e0b988 | 61 | b.s = SnBitUtils::WriteTo(b.s, fTrgNum); |
uci1 | 0:664899e0b988 | 62 | b.s = SnBitUtils::WriteTo(b.s, fTrgBits); |
uci1 | 0:664899e0b988 | 63 | b.u = PackWavef(b.u, fData, loseLSB, loseMSB, wvBaseline); |
uci1 | 0:664899e0b988 | 64 | b.s = SnBitUtils::WriteTo(b.s, fCRC); |
uci1 | 3:24c5f0f50bf1 | 65 | |
uci1 | 3:24c5f0f50bf1 | 66 | return b.s; |
uci1 | 0:664899e0b988 | 67 | } |
uci1 | 0:664899e0b988 | 68 | |
uci1 | 0:664899e0b988 | 69 | void SnEventFrame::CalcCRC() { |
uci1 | 0:664899e0b988 | 70 | // CRC made using union on a little endian (mbed) processor |
uci1 | 0:664899e0b988 | 71 | fCRC = 0u; |
uci1 | 0:664899e0b988 | 72 | const uint16_t* dev = fData; |
uci1 | 1:e392595b4b76 | 73 | for (uint16_t i=0; i<kTotSamps; i++, dev++) { |
uci1 | 0:664899e0b988 | 74 | fCRC = update_crc32_xfer_short(fCRC, *dev); |
uci1 | 0:664899e0b988 | 75 | } |
uci1 | 0:664899e0b988 | 76 | } |
uci1 | 0:664899e0b988 | 77 | |
uci1 | 0:664899e0b988 | 78 | bool SnEventFrame::ReadFromFileToBuf(FILE* f, |
uci1 | 0:664899e0b988 | 79 | char* const evtBuf, |
uci1 | 0:664899e0b988 | 80 | const uint8_t loseLSB, |
uci1 | 0:664899e0b988 | 81 | const uint8_t loseMSB) { |
uci1 | 0:664899e0b988 | 82 | // file position expected to be at this event frame already |
uci1 | 0:664899e0b988 | 83 | bool ret = false; |
uci1 | 0:664899e0b988 | 84 | if (f!=0) { |
uci1 | 8:95a325df1f6b | 85 | if (fread(evtBuf, SizeOf(kIOVers, loseLSB, loseMSB), 1u, f)!=NULL) { |
uci1 | 0:664899e0b988 | 86 | ret = true; |
uci1 | 0:664899e0b988 | 87 | } |
uci1 | 0:664899e0b988 | 88 | } |
uci1 | 0:664899e0b988 | 89 | return ret; |
uci1 | 0:664899e0b988 | 90 | } |
uci1 | 0:664899e0b988 | 91 | |
uci1 | 0:664899e0b988 | 92 | bool SnEventFrame::ReadFrom(FILE* f, |
uci1 | 0:664899e0b988 | 93 | char* const evtBuf, |
uci1 | 0:664899e0b988 | 94 | const uint8_t loseLSB, const uint8_t loseMSB, |
uci1 | 0:664899e0b988 | 95 | const uint16_t wvBaseline) { |
uci1 | 0:664899e0b988 | 96 | // file position expected to be at this event frame already |
uci1 | 0:664899e0b988 | 97 | const bool ret = ReadFromFileToBuf(f, evtBuf, loseLSB, loseMSB); |
uci1 | 0:664899e0b988 | 98 | if (ret) { |
uci1 | 0:664899e0b988 | 99 | ReadFrom(evtBuf, loseLSB, loseMSB, wvBaseline); |
uci1 | 0:664899e0b988 | 100 | } |
uci1 | 0:664899e0b988 | 101 | return ret; |
uci1 | 0:664899e0b988 | 102 | } |
uci1 | 0:664899e0b988 | 103 | |
uci1 | 0:664899e0b988 | 104 | bool SnEventFrame::WriteTo(FILE* f, char* const evtBuf, |
uci1 | 0:664899e0b988 | 105 | const uint8_t loseLSB, const uint8_t loseMSB, |
uci1 | 0:664899e0b988 | 106 | const uint16_t wvBaseline) const { |
uci1 | 0:664899e0b988 | 107 | // file pointer should be in correct location |
uci1 | 0:664899e0b988 | 108 | |
uci1 | 0:664899e0b988 | 109 | WriteTo(evtBuf, loseLSB, loseMSB, wvBaseline); |
uci1 | 0:664899e0b988 | 110 | return WriteToFileFromBuf(f, evtBuf, loseLSB, loseMSB); |
uci1 | 0:664899e0b988 | 111 | } |
uci1 | 0:664899e0b988 | 112 | |
uci1 | 0:664899e0b988 | 113 | bool SnEventFrame::WriteToFileFromBuf(FILE* f, char* const evtBuf, |
uci1 | 0:664899e0b988 | 114 | const uint8_t loseLSB, const uint8_t loseMSB) { |
uci1 | 0:664899e0b988 | 115 | // file pointer should be in correct location |
uci1 | 0:664899e0b988 | 116 | |
uci1 | 0:664899e0b988 | 117 | bool ret = false; |
uci1 | 0:664899e0b988 | 118 | if (f!=0) { |
uci1 | 8:95a325df1f6b | 119 | fwrite(evtBuf, SizeOf(kIOVers, loseLSB, loseMSB), 1u, f); |
uci1 | 0:664899e0b988 | 120 | ret = (ferror(f)==false); |
uci1 | 0:664899e0b988 | 121 | } |
uci1 | 0:664899e0b988 | 122 | return ret; |
uci1 | 0:664899e0b988 | 123 | |
uci1 | 0:664899e0b988 | 124 | } |
uci1 | 0:664899e0b988 | 125 | |
uci1 | 0:664899e0b988 | 126 | |
uci1 | 0:664899e0b988 | 127 | uint8_t* SnEventFrame::PackWavef(uint8_t* const buf, const uint16_t* const data, |
uci1 | 0:664899e0b988 | 128 | const uint8_t loseLSB, const uint8_t loseMSB, |
uci1 | 0:664899e0b988 | 129 | const uint16_t wvBaseline) { |
uci1 | 0:664899e0b988 | 130 | // Compress the data. This is potentially LOSSY; it depends |
uci1 | 0:664899e0b988 | 131 | // on the dynamic range and on the options. |
uci1 | 0:664899e0b988 | 132 | // See SnConfigFrame::fWvLoseLSB and SnConfigFrame::fWvLoseMSB. |
uci1 | 0:664899e0b988 | 133 | // If the number of least signficant bits to lose is not 0, the |
uci1 | 0:664899e0b988 | 134 | // compression will be lossy (decreased resolution -- this is ok |
uci1 | 0:664899e0b988 | 135 | // if the noise of the signal is much greater than the resolution). |
uci1 | 0:664899e0b988 | 136 | // Losing the most significant bits will only be lossy if the |
uci1 | 0:664899e0b988 | 137 | // signal-SnConfigFrame::fWvBaseline cannot fit in the reduced |
uci1 | 0:664899e0b988 | 138 | // dynamic range (each MSB bit reducing the DR by a factor of 2). |
uci1 | 0:664899e0b988 | 139 | // |
uci1 | 0:664899e0b988 | 140 | // Note that the mbed uses little endian. Behavior should be the |
uci1 | 0:664899e0b988 | 141 | // same on big endian, but this has not been tested. |
uci1 | 0:664899e0b988 | 142 | // |
uci1 | 0:664899e0b988 | 143 | // Use an unsigned buffer to prevent bits being changed during |
uci1 | 0:664899e0b988 | 144 | // an implicit unsigned -> signed cast. |
uci1 | 0:664899e0b988 | 145 | // |
uci1 | 0:664899e0b988 | 146 | // buf = the byte array into which the data should be packed |
uci1 | 0:664899e0b988 | 147 | // data = the data to pack |
uci1 | 0:664899e0b988 | 148 | // loseLSB = number of least significant bits to throw away |
uci1 | 0:664899e0b988 | 149 | // loseMSB = number of most significant bits to throw away |
uci1 | 0:664899e0b988 | 150 | // wvBaseline = baseline to subtract to from ADC before packing |
uci1 | 0:664899e0b988 | 151 | |
uci1 | 0:664899e0b988 | 152 | const uint32_t blen = SizeOfPackedWavef(loseLSB, loseMSB); |
uci1 | 0:664899e0b988 | 153 | const uint8_t packSmpBits = BITS_IN_SHORT-loseLSB-loseMSB; |
uci1 | 0:664899e0b988 | 154 | |
uci1 | 0:664899e0b988 | 155 | // make sure this buffer space is all 0's to start |
uci1 | 0:664899e0b988 | 156 | memset(buf, 0, blen*sizeof(uint8_t)); |
uci1 | 0:664899e0b988 | 157 | |
uci1 | 0:664899e0b988 | 158 | const uint16_t clipHi = uint16_t( |
uci1 | 0:664899e0b988 | 159 | uint16_t(uint16_t(0xFFFFu >> loseLSB) << (loseLSB+loseMSB)) |
uci1 | 0:664899e0b988 | 160 | >> loseMSB); |
uci1 | 0:664899e0b988 | 161 | |
uci1 | 0:664899e0b988 | 162 | uint8_t* b = buf; |
uci1 | 0:664899e0b988 | 163 | const uint16_t* dev = data; |
uci1 | 0:664899e0b988 | 164 | uint16_t dum; |
uci1 | 0:664899e0b988 | 165 | int8_t sbit=0; |
uci1 | 0:664899e0b988 | 166 | for (uint16_t i=0; i<kTotSamps; i++, dev++) { |
uci1 | 0:664899e0b988 | 167 | // dump the bits we don't want |
uci1 | 0:664899e0b988 | 168 | dum = (*dev) - wvBaseline; |
uci1 | 0:664899e0b988 | 169 | if (dum<clipHi) { |
uci1 | 0:664899e0b988 | 170 | dum >>= loseLSB; |
uci1 | 0:664899e0b988 | 171 | dum <<= (loseLSB+loseMSB); |
uci1 | 0:664899e0b988 | 172 | } else { |
uci1 | 0:664899e0b988 | 173 | dum = clipHi << loseMSB; |
uci1 | 0:664899e0b988 | 174 | } |
uci1 | 0:664899e0b988 | 175 | if (sbit<=0) { |
uci1 | 0:664899e0b988 | 176 | // lose MSB's put in previous short (or none if sbit==0) |
uci1 | 0:664899e0b988 | 177 | dum <<= -sbit; |
uci1 | 0:664899e0b988 | 178 | *b |= dum >> 8u; // "first" byte of the short |
uci1 | 0:664899e0b988 | 179 | dum <<= 8u; |
uci1 | 0:664899e0b988 | 180 | *(b+1) |= dum >> 8u; // "second" |
uci1 | 0:664899e0b988 | 181 | // move to next number (dev++ in the for loop) |
uci1 | 0:664899e0b988 | 182 | // move starting bit up |
uci1 | 0:664899e0b988 | 183 | // but stay in this byte of the buf (do not increment b) |
uci1 | 0:664899e0b988 | 184 | // since kPackSmpBits <= kBitsInShort, sbit can't |
uci1 | 0:664899e0b988 | 185 | // move past the end of the current two bytes |
uci1 | 0:664899e0b988 | 186 | sbit += packSmpBits; |
uci1 | 0:664899e0b988 | 187 | } else { |
uci1 | 0:664899e0b988 | 188 | // first few bits towards the end of this short |
uci1 | 0:664899e0b988 | 189 | dum >>= sbit; |
uci1 | 0:664899e0b988 | 190 | *b |= dum >> 8u; // "first" byte of the short |
uci1 | 0:664899e0b988 | 191 | dum <<= 8u; |
uci1 | 0:664899e0b988 | 192 | *(b+1) |= dum >> 8u; // "second" |
uci1 | 0:664899e0b988 | 193 | if ( (sbit+packSmpBits) >= BITS_IN_SHORT ) { |
uci1 | 0:664899e0b988 | 194 | b+=2; // move to next short in the buf |
uci1 | 0:664899e0b988 | 195 | i--; dev--; // but stay on this number |
uci1 | 0:664899e0b988 | 196 | // move starting bit back into the short we just filled |
uci1 | 0:664899e0b988 | 197 | sbit -= BITS_IN_SHORT; |
uci1 | 0:664899e0b988 | 198 | } else { |
uci1 | 0:664899e0b988 | 199 | // stay in this buffer and move to the next number |
uci1 | 0:664899e0b988 | 200 | // move starting bit up |
uci1 | 0:664899e0b988 | 201 | sbit += packSmpBits; |
uci1 | 0:664899e0b988 | 202 | } |
uci1 | 0:664899e0b988 | 203 | } |
uci1 | 0:664899e0b988 | 204 | } |
uci1 | 0:664899e0b988 | 205 | |
uci1 | 0:664899e0b988 | 206 | return buf+blen; |
uci1 | 0:664899e0b988 | 207 | } |
uci1 | 0:664899e0b988 | 208 | |
uci1 | 0:664899e0b988 | 209 | const uint8_t* SnEventFrame::UnpackWavef(const uint8_t* const buf, |
uci1 | 0:664899e0b988 | 210 | uint16_t* const data, |
uci1 | 0:664899e0b988 | 211 | const uint8_t loseLSB, |
uci1 | 0:664899e0b988 | 212 | const uint8_t loseMSB, |
uci1 | 0:664899e0b988 | 213 | const uint16_t wvBaseline) { |
uci1 | 0:664899e0b988 | 214 | if (loseLSB==0 && loseMSB==0 && wvBaseline==0) { |
uci1 | 0:664899e0b988 | 215 | memcpy(data, buf, kTotSamps*sizeof(uint16_t)); |
uci1 | 0:664899e0b988 | 216 | } else { |
uci1 | 0:664899e0b988 | 217 | |
uci1 | 0:664899e0b988 | 218 | const uint8_t packSmpBits = BITS_IN_SHORT-loseLSB-loseMSB; |
uci1 | 0:664899e0b988 | 219 | |
uci1 | 0:664899e0b988 | 220 | // make sure data is all 0's to start |
uci1 | 0:664899e0b988 | 221 | memset(data, 0, kTotSamps*sizeof(uint16_t)); |
uci1 | 0:664899e0b988 | 222 | |
uci1 | 0:664899e0b988 | 223 | const uint8_t* b = buf; |
uci1 | 0:664899e0b988 | 224 | uint16_t* dev = data; |
uci1 | 0:664899e0b988 | 225 | uint16_t dum; |
uci1 | 0:664899e0b988 | 226 | int8_t sbit=0; |
uci1 | 0:664899e0b988 | 227 | for (uint16_t i=0; i<kTotSamps; i++, dev++) { |
uci1 | 0:664899e0b988 | 228 | dum = (*b) << 8u; |
uci1 | 0:664899e0b988 | 229 | dum |= *(b+1); |
uci1 | 0:664899e0b988 | 230 | if (sbit<=0) { |
uci1 | 0:664899e0b988 | 231 | dum >>= (-sbit+loseLSB+loseMSB); |
uci1 | 0:664899e0b988 | 232 | dum <<= loseLSB; |
uci1 | 0:664899e0b988 | 233 | *dev |= dum; |
uci1 | 0:664899e0b988 | 234 | // add baseline and move to next number (dev++ in the for loop) |
uci1 | 0:664899e0b988 | 235 | *dev += wvBaseline; |
uci1 | 0:664899e0b988 | 236 | // but stay in this short of the buf (do not increment b) |
uci1 | 0:664899e0b988 | 237 | // move starting bit up |
uci1 | 0:664899e0b988 | 238 | sbit += packSmpBits; |
uci1 | 0:664899e0b988 | 239 | } else { |
uci1 | 0:664899e0b988 | 240 | dum <<= sbit; |
uci1 | 0:664899e0b988 | 241 | dum >>= loseMSB+loseLSB; |
uci1 | 0:664899e0b988 | 242 | dum <<= loseLSB; |
uci1 | 0:664899e0b988 | 243 | *dev = dum; |
uci1 | 0:664899e0b988 | 244 | if ( (sbit+packSmpBits) >= BITS_IN_SHORT ) { |
uci1 | 0:664899e0b988 | 245 | b+=2; // move to next short in the buf |
uci1 | 0:664899e0b988 | 246 | i--; dev--; // but stay on this number |
uci1 | 0:664899e0b988 | 247 | // move starting bit back into the short we just read from |
uci1 | 0:664899e0b988 | 248 | sbit -= BITS_IN_SHORT; |
uci1 | 0:664899e0b988 | 249 | } else { |
uci1 | 0:664899e0b988 | 250 | // add baseline and move to next number (dev++ in the for loop) |
uci1 | 0:664899e0b988 | 251 | *dev += wvBaseline; |
uci1 | 0:664899e0b988 | 252 | sbit += packSmpBits; |
uci1 | 0:664899e0b988 | 253 | } |
uci1 | 0:664899e0b988 | 254 | } |
uci1 | 0:664899e0b988 | 255 | } |
uci1 | 0:664899e0b988 | 256 | } |
uci1 | 0:664899e0b988 | 257 | |
uci1 | 0:664899e0b988 | 258 | return buf+SizeOfPackedWavef(loseLSB, loseMSB); |
uci1 | 0:664899e0b988 | 259 | } |
uci1 | 0:664899e0b988 | 260 |