![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
SnEventFrame.cpp
- Committer:
- uci1
- Date:
- 2019-06-05
- Revision:
- 125:ce4045184366
- Parent:
- 119:b3d7699d0eb0
File content as of revision 125:ce4045184366:
#include "SnEventFrame.h" #include "SnCRCUtils.h" //#define DEBUG #if CHIPBOARD==ATWD4CH const uint8_t SnEventFrame::kIOVers = 1; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) #elif CHIPBOARD==SST4CH const uint8_t SnEventFrame::kIOVers = 2; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) #elif CHIPBOARD==SST4CH_1GHz const uint8_t SnEventFrame::kIOVers = 3; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) #elif CHIPBOARD==SST4CH512 const uint8_t SnEventFrame::kIOVers = 4; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) #elif CHIPBOARD==SST4CH512_1GHz const uint8_t SnEventFrame::kIOVers = 5; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) #elif CHIPBOARD==SST8CH const uint8_t SnEventFrame::kIOVers = 6; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) #elif CHIPBOARD==SST8CH_1GHz const uint8_t SnEventFrame::kIOVers = 7; // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!) #else #error CHIPBOARD value not accounted for in event frame i/o version. #endif 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) { const uint16_t nsamps = GetTotSamplesForIOVers(Rv); 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, nsamps); b.s = SnBitUtils::ReadFrom(b.s, fCRC); #if CHIPBOARD!=ATWD4CH const uint16_t nstopBytes = GetStopBytesForIOVersBufferSafe(Rv); if (Rv>1) { b.s = SnBitUtils::ReadFrom(b.s, fStop, nstopBytes); } #endif } 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 const uint16_t nsamps = GetTotSamplesForIOVers(kIOVers); 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, nsamps); b.s = SnBitUtils::WriteTo(b.s, fCRC); #if CHIPBOARD!=ATWD4CH const uint16_t nstopBytes = GetStopBytesForIOVersBufferSafe(kIOVers); if (kIOVers>1) { // we test kIOVers rather than the CHIPBOARD #define in order // to ensure that the i/o version is the ONLY variable that determines // what the event looks like in a file or communication. // this is the only way to ensure readability going forward. #ifdef DEBUG printf("kNstopBytes=%hu, nstopBytes=%hu, kIOVers=%hhu\r\n", kNstopBytes, nstopBytes, kIOVers); char* x = b.s; #endif b.s = SnBitUtils::WriteTo(b.s, fStop, nstopBytes); #ifdef DEBUG printf("wrote %d stop bytes\r\n", b.s - x); #endif } #endif #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 = SnCRCUtils::GetCRC32for(fData, kTotSamps); #if CHIPBOARD!=ATWD4CH fCRC = SnCRCUtils::GetUpdatedCRC32for(fCRC, fStop, kNstopBytes); #endif #ifdef DEBUG printf("SnEventFrame::CalcCRC crc=%u\r\n",fCRC); #endif } 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)!=0) { 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, const uint16_t nsamps) { // 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<nsamps; ++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, const uint16_t nsamps) { if (loseLSB==0 && loseMSB==0 && wvBaseline==0) { memcpy(data, buf, nsamps*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, nsamps*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<nsamps; ++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); }