Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
Diff: SnEventFrame.cpp
- Revision:
- 0:664899e0b988
- Child:
- 1:e392595b4b76
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SnEventFrame.cpp Sat Jun 30 02:03:51 2012 +0000 @@ -0,0 +1,250 @@ +#include "SnEventFrame.h" + +#include "SnCRCUtils.h" + +void 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 + + union Usub { + const char* s; + const uint8_t* u; + } b; + b.s = buf; + + int8_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); + } + +} + +void 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 + + 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); + +} + +void SnEventFrame::CalcCRC() { + // CRC made using union on a little endian (mbed) processor + fCRC = 0u; + const uint16_t* dev = fData; + for (int16_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(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(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); +} +