Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
Diff: SnEventFrame.cpp
- Revision:
- 21:ce51bb0ba4a5
- Parent:
- 8:95a325df1f6b
- Child:
- 25:57b2627fe756
--- a/SnEventFrame.cpp Wed Oct 03 00:22:27 2012 +0000 +++ b/SnEventFrame.cpp Wed Oct 10 05:54:12 2012 +0000 @@ -1,260 +1,270 @@ -#include "SnEventFrame.h" - -#include "SnCRCUtils.h" - -const uint8_t SnEventFrame::kIOVers = 1; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) - -const char* SnEventFrame::ReadFrom(const char* const buf, - const uint8_t loseLSB, const uint8_t loseMSB, - const uint16_t wvBaseline) { - // no check on the length of buf is done here - // that should be been done already - // - // must match ::WriteToBuf - - // NOTE: on the mbed, this is reduntant (char is unsigned) - // but this way, the block can be copied to other computers - // and still work. - union Usub { - const char* s; - const uint8_t* u; - } b; - b.s = buf; - - uint8_t Rv=0; - b.s = SnBitUtils::ReadFrom(b.s, Rv); // i/o version - if (Rv>0) { - b.s = SnBitUtils::ReadFrom(b.s, fMbedTime); - b.s = SnBitUtils::ReadFrom(b.s, fEvtNum); - b.s = SnBitUtils::ReadFrom(b.s, fDTms); - b.s = SnBitUtils::ReadFrom(b.s, fTrgNum); - b.s = SnBitUtils::ReadFrom(b.s, fTrgBits); - b.u = UnpackWavef(b.u, fData, loseLSB, loseMSB, wvBaseline); - b.s = SnBitUtils::ReadFrom(b.s, fCRC); - } - - return b.s; -} - -char* SnEventFrame::WriteTo(char* const buf, - const uint8_t loseLSB, const uint8_t loseMSB, - const uint16_t wvBaseline) const { - // no check on the length of the buf is done here - // that should be done already - // - // must match ReadFromBuf - - // NOTE: on the mbed, this is reduntant (char is unsigned) - // but this way, the block can be copied to other computers - // and still work. - union { - char* s; - uint8_t* u; - } b; - b.s = buf; - - b.s = SnBitUtils::WriteTo(b.s, kIOVers); // i/o version - - b.s = SnBitUtils::WriteTo(b.s, fMbedTime); - b.s = SnBitUtils::WriteTo(b.s, fEvtNum); - b.s = SnBitUtils::WriteTo(b.s, fDTms); - b.s = SnBitUtils::WriteTo(b.s, fTrgNum); - b.s = SnBitUtils::WriteTo(b.s, fTrgBits); - b.u = PackWavef(b.u, fData, loseLSB, loseMSB, wvBaseline); - b.s = SnBitUtils::WriteTo(b.s, fCRC); - - return b.s; -} - -void SnEventFrame::CalcCRC() { - // CRC made using union on a little endian (mbed) processor - fCRC = 0u; - const uint16_t* dev = fData; - for (uint16_t i=0; i<kTotSamps; i++, dev++) { - fCRC = update_crc32_xfer_short(fCRC, *dev); - } -} - -bool SnEventFrame::ReadFromFileToBuf(FILE* f, - char* const evtBuf, - const uint8_t loseLSB, - const uint8_t loseMSB) { - // file position expected to be at this event frame already - bool ret = false; - if (f!=0) { - if (fread(evtBuf, SizeOf(kIOVers, loseLSB, loseMSB), 1u, f)!=NULL) { - ret = true; - } - } - return ret; -} - -bool SnEventFrame::ReadFrom(FILE* f, - char* const evtBuf, - const uint8_t loseLSB, const uint8_t loseMSB, - const uint16_t wvBaseline) { - // file position expected to be at this event frame already - const bool ret = ReadFromFileToBuf(f, evtBuf, loseLSB, loseMSB); - if (ret) { - ReadFrom(evtBuf, loseLSB, loseMSB, wvBaseline); - } - return ret; -} - -bool SnEventFrame::WriteTo(FILE* f, char* const evtBuf, - const uint8_t loseLSB, const uint8_t loseMSB, - const uint16_t wvBaseline) const { - // file pointer should be in correct location - - WriteTo(evtBuf, loseLSB, loseMSB, wvBaseline); - return WriteToFileFromBuf(f, evtBuf, loseLSB, loseMSB); -} - -bool SnEventFrame::WriteToFileFromBuf(FILE* f, char* const evtBuf, - const uint8_t loseLSB, const uint8_t loseMSB) { - // file pointer should be in correct location - - bool ret = false; - if (f!=0) { - fwrite(evtBuf, SizeOf(kIOVers, loseLSB, loseMSB), 1u, f); - ret = (ferror(f)==false); - } - return ret; - -} - - -uint8_t* SnEventFrame::PackWavef(uint8_t* const buf, const uint16_t* const data, - const uint8_t loseLSB, const uint8_t loseMSB, - const uint16_t wvBaseline) { - // Compress the data. This is potentially LOSSY; it depends - // on the dynamic range and on the options. - // See SnConfigFrame::fWvLoseLSB and SnConfigFrame::fWvLoseMSB. - // If the number of least signficant bits to lose is not 0, the - // compression will be lossy (decreased resolution -- this is ok - // if the noise of the signal is much greater than the resolution). - // Losing the most significant bits will only be lossy if the - // signal-SnConfigFrame::fWvBaseline cannot fit in the reduced - // dynamic range (each MSB bit reducing the DR by a factor of 2). - // - // Note that the mbed uses little endian. Behavior should be the - // same on big endian, but this has not been tested. - // - // Use an unsigned buffer to prevent bits being changed during - // an implicit unsigned -> signed cast. - // - // buf = the byte array into which the data should be packed - // data = the data to pack - // loseLSB = number of least significant bits to throw away - // loseMSB = number of most significant bits to throw away - // wvBaseline = baseline to subtract to from ADC before packing - - const uint32_t blen = SizeOfPackedWavef(loseLSB, loseMSB); - const uint8_t packSmpBits = BITS_IN_SHORT-loseLSB-loseMSB; - - // make sure this buffer space is all 0's to start - memset(buf, 0, blen*sizeof(uint8_t)); - - const uint16_t clipHi = uint16_t( - uint16_t(uint16_t(0xFFFFu >> loseLSB) << (loseLSB+loseMSB)) - >> loseMSB); - - uint8_t* b = buf; - const uint16_t* dev = data; - uint16_t dum; - int8_t sbit=0; - for (uint16_t i=0; i<kTotSamps; i++, dev++) { - // dump the bits we don't want - dum = (*dev) - wvBaseline; - if (dum<clipHi) { - dum >>= loseLSB; - dum <<= (loseLSB+loseMSB); - } else { - dum = clipHi << loseMSB; - } - if (sbit<=0) { - // lose MSB's put in previous short (or none if sbit==0) - dum <<= -sbit; - *b |= dum >> 8u; // "first" byte of the short - dum <<= 8u; - *(b+1) |= dum >> 8u; // "second" - // move to next number (dev++ in the for loop) - // move starting bit up - // but stay in this byte of the buf (do not increment b) - // since kPackSmpBits <= kBitsInShort, sbit can't - // move past the end of the current two bytes - sbit += packSmpBits; - } else { - // first few bits towards the end of this short - dum >>= sbit; - *b |= dum >> 8u; // "first" byte of the short - dum <<= 8u; - *(b+1) |= dum >> 8u; // "second" - if ( (sbit+packSmpBits) >= BITS_IN_SHORT ) { - b+=2; // move to next short in the buf - i--; dev--; // but stay on this number - // move starting bit back into the short we just filled - sbit -= BITS_IN_SHORT; - } else { - // stay in this buffer and move to the next number - // move starting bit up - sbit += packSmpBits; - } - } - } - - return buf+blen; -} - -const uint8_t* SnEventFrame::UnpackWavef(const uint8_t* const buf, - uint16_t* const data, - const uint8_t loseLSB, - const uint8_t loseMSB, - const uint16_t wvBaseline) { - if (loseLSB==0 && loseMSB==0 && wvBaseline==0) { - memcpy(data, buf, kTotSamps*sizeof(uint16_t)); - } else { - - const uint8_t packSmpBits = BITS_IN_SHORT-loseLSB-loseMSB; - - // make sure data is all 0's to start - memset(data, 0, kTotSamps*sizeof(uint16_t)); - - const uint8_t* b = buf; - uint16_t* dev = data; - uint16_t dum; - int8_t sbit=0; - for (uint16_t i=0; i<kTotSamps; i++, dev++) { - dum = (*b) << 8u; - dum |= *(b+1); - if (sbit<=0) { - dum >>= (-sbit+loseLSB+loseMSB); - dum <<= loseLSB; - *dev |= dum; - // add baseline and move to next number (dev++ in the for loop) - *dev += wvBaseline; - // but stay in this short of the buf (do not increment b) - // move starting bit up - sbit += packSmpBits; - } else { - dum <<= sbit; - dum >>= loseMSB+loseLSB; - dum <<= loseLSB; - *dev = dum; - if ( (sbit+packSmpBits) >= BITS_IN_SHORT ) { - b+=2; // move to next short in the buf - i--; dev--; // but stay on this number - // move starting bit back into the short we just read from - sbit -= BITS_IN_SHORT; - } else { - // add baseline and move to next number (dev++ in the for loop) - *dev += wvBaseline; - sbit += packSmpBits; - } - } - } - } - - return buf+SizeOfPackedWavef(loseLSB, loseMSB); -} - +#include "SnEventFrame.h" + +#include "SnCRCUtils.h" + +//#define DEBUG + +const uint8_t SnEventFrame::kIOVers = 1; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) + +const char* SnEventFrame::ReadFrom(const char* const buf, + const uint8_t loseLSB, const uint8_t loseMSB, + const uint16_t wvBaseline) { + // no check on the length of buf is done here + // that should be been done already + // + // must match ::WriteToBuf + + // NOTE: on the mbed, this is reduntant (char is unsigned) + // but this way, the block can be copied to other computers + // and still work. + union Usub { + const char* s; + const uint8_t* u; + } b; + b.s = buf; + + uint8_t Rv=0; + b.s = SnBitUtils::ReadFrom(b.s, Rv); // i/o version + if (Rv>0) { + b.s = SnBitUtils::ReadFrom(b.s, fMbedTime); + b.s = SnBitUtils::ReadFrom(b.s, fEvtNum); + b.s = SnBitUtils::ReadFrom(b.s, fDTms); + b.s = SnBitUtils::ReadFrom(b.s, fTrgNum); + b.s = SnBitUtils::ReadFrom(b.s, fTrgBits); + b.u = UnpackWavef(b.u, fData, loseLSB, loseMSB, wvBaseline); + b.s = SnBitUtils::ReadFrom(b.s, fCRC); + } + + return b.s; +} + +char* SnEventFrame::WriteTo(char* const buf, + const uint8_t loseLSB, const uint8_t loseMSB, + const uint16_t wvBaseline) const { + // no check on the length of the buf is done here + // that should be done already + // + // must match ReadFromBuf + + // NOTE: on the mbed, this is reduntant (char is unsigned) + // but this way, the block can be copied to other computers + // and still work. + union { + char* s; + uint8_t* u; + } b; + b.s = buf; + + b.s = SnBitUtils::WriteTo(b.s, kIOVers); // i/o version + + b.s = SnBitUtils::WriteTo(b.s, fMbedTime); + b.s = SnBitUtils::WriteTo(b.s, fEvtNum); + b.s = SnBitUtils::WriteTo(b.s, fDTms); + b.s = SnBitUtils::WriteTo(b.s, fTrgNum); + b.s = SnBitUtils::WriteTo(b.s, fTrgBits); + b.u = PackWavef(b.u, fData, loseLSB, loseMSB, wvBaseline); + b.s = SnBitUtils::WriteTo(b.s, fCRC); + +#ifdef DEBUG + printf("SnEventFrame::WriteTo:\r\n"); + for (uint32_t i=0; i<b.s-buf; i++) { + printf("%02X ",buf[i]); + } + printf("\r\n"); +#endif + + return b.s; +} + +void SnEventFrame::CalcCRC() { + // CRC made using union on a little endian (mbed) processor + fCRC = 0u; + const uint16_t* dev = fData; + for (uint16_t i=0; i<kTotSamps; ++i, ++dev) { + fCRC = update_crc32_xfer_short(fCRC, *dev); + } +} + +bool SnEventFrame::ReadFromFileToBuf(FILE* f, + char* const evtBuf, + const uint8_t loseLSB, + const uint8_t loseMSB) { + // file position expected to be at this event frame already + bool ret = false; + if (f!=0) { + if (fread(evtBuf, SizeOf(kIOVers, loseLSB, loseMSB), 1u, f)!=NULL) { + ret = true; + } + } + return ret; +} + +bool SnEventFrame::ReadFrom(FILE* f, + char* const evtBuf, + const uint8_t loseLSB, const uint8_t loseMSB, + const uint16_t wvBaseline) { + // file position expected to be at this event frame already + const bool ret = ReadFromFileToBuf(f, evtBuf, loseLSB, loseMSB); + if (ret) { + ReadFrom(evtBuf, loseLSB, loseMSB, wvBaseline); + } + return ret; +} + +bool SnEventFrame::WriteTo(FILE* f, char* const evtBuf, + const uint8_t loseLSB, const uint8_t loseMSB, + const uint16_t wvBaseline) const { + // file pointer should be in correct location + + WriteTo(evtBuf, loseLSB, loseMSB, wvBaseline); + return WriteToFileFromBuf(f, evtBuf, loseLSB, loseMSB); +} + +bool SnEventFrame::WriteToFileFromBuf(FILE* f, char* const evtBuf, + const uint8_t loseLSB, const uint8_t loseMSB) { + // file pointer should be in correct location + + bool ret = false; + if (f!=0) { + fwrite(evtBuf, SizeOf(kIOVers, loseLSB, loseMSB), 1u, f); + ret = (ferror(f)==false); + } + return ret; + +} + + +uint8_t* SnEventFrame::PackWavef(uint8_t* const buf, const uint16_t* const data, + const uint8_t loseLSB, const uint8_t loseMSB, + const uint16_t wvBaseline) { + // Compress the data. This is potentially LOSSY; it depends + // on the dynamic range and on the options. + // See SnConfigFrame::fWvLoseLSB and SnConfigFrame::fWvLoseMSB. + // If the number of least signficant bits to lose is not 0, the + // compression will be lossy (decreased resolution -- this is ok + // if the noise of the signal is much greater than the resolution). + // Losing the most significant bits will only be lossy if the + // signal-SnConfigFrame::fWvBaseline cannot fit in the reduced + // dynamic range (each MSB bit reducing the DR by a factor of 2). + // + // Note that the mbed uses little endian. Behavior should be the + // same on big endian, but this has not been tested. + // + // Use an unsigned buffer to prevent bits being changed during + // an implicit unsigned -> signed cast. + // + // buf = the byte array into which the data should be packed + // data = the data to pack + // loseLSB = number of least significant bits to throw away + // loseMSB = number of most significant bits to throw away + // wvBaseline = baseline to subtract to from ADC before packing + + const uint32_t blen = SizeOfPackedWavef(loseLSB, loseMSB); + const uint8_t packSmpBits = BITS_IN_SHORT-loseLSB-loseMSB; + + // make sure this buffer space is all 0's to start + memset(buf, 0, blen*sizeof(uint8_t)); + + const uint16_t clipHi = uint16_t( + uint16_t(uint16_t(0xFFFFu >> loseLSB) << (loseLSB+loseMSB)) + >> loseMSB); + + uint8_t* b = buf; + const uint16_t* dev = data; + uint16_t dum; + int8_t sbit=0; + for (uint16_t i=0; i<kTotSamps; ++i, ++dev) { + // dump the bits we don't want + dum = (*dev) - wvBaseline; + if (dum<clipHi) { + dum >>= loseLSB; + dum <<= (loseLSB+loseMSB); + } else { + dum = clipHi << loseMSB; + } + if (sbit<=0) { + // lose MSB's put in previous short (or none if sbit==0) + dum <<= -sbit; + *b |= dum >> 8u; // "first" byte of the short + dum <<= 8u; + *(b+1) |= dum >> 8u; // "second" + // move to next number (dev++ in the for loop) + // move starting bit up + // but stay in this byte of the buf (do not increment b) + // since kPackSmpBits <= kBitsInShort, sbit can't + // move past the end of the current two bytes + sbit += packSmpBits; + } else { + // first few bits towards the end of this short + dum >>= sbit; + *b |= dum >> 8u; // "first" byte of the short + dum <<= 8u; + *(b+1) |= dum >> 8u; // "second" + if ( (sbit+packSmpBits) >= BITS_IN_SHORT ) { + b+=2; // move to next short in the buf + i--; dev--; // but stay on this number + // move starting bit back into the short we just filled + sbit -= BITS_IN_SHORT; + } else { + // stay in this buffer and move to the next number + // move starting bit up + sbit += packSmpBits; + } + } + } + + return buf+blen; +} + +const uint8_t* SnEventFrame::UnpackWavef(const uint8_t* const buf, + uint16_t* const data, + const uint8_t loseLSB, + const uint8_t loseMSB, + const uint16_t wvBaseline) { + if (loseLSB==0 && loseMSB==0 && wvBaseline==0) { + memcpy(data, buf, kTotSamps*sizeof(uint16_t)); + } else { + + const uint8_t packSmpBits = BITS_IN_SHORT-loseLSB-loseMSB; + + // make sure data is all 0's to start + memset(data, 0, kTotSamps*sizeof(uint16_t)); + + const uint8_t* b = buf; + uint16_t* dev = data; + uint16_t dum; + int8_t sbit=0; + for (uint16_t i=0; i<kTotSamps; ++i, ++dev) { + dum = (*b) << 8u; + dum |= *(b+1); + if (sbit<=0) { + dum >>= (-sbit+loseLSB+loseMSB); + dum <<= loseLSB; + *dev |= dum; + // add baseline and move to next number (dev++ in the for loop) + *dev += wvBaseline; + // but stay in this short of the buf (do not increment b) + // move starting bit up + sbit += packSmpBits; + } else { + dum <<= sbit; + dum >>= loseMSB+loseLSB; + dum <<= loseLSB; + *dev = dum; + if ( (sbit+packSmpBits) >= BITS_IN_SHORT ) { + b+=2; // move to next short in the buf + i--; dev--; // but stay on this number + // move starting bit back into the short we just read from + sbit -= BITS_IN_SHORT; + } else { + // add baseline and move to next number (dev++ in the for loop) + *dev += wvBaseline; + sbit += packSmpBits; + } + } + } + } + + return buf+SizeOfPackedWavef(loseLSB, loseMSB); +} +