Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
SnEventFrame.cpp
- Committer:
- uci1
- Date:
- 2012-07-31
- Revision:
- 3:24c5f0f50bf1
- Parent:
- 1:e392595b4b76
- Child:
- 8:95a325df1f6b
File content as of revision 3:24c5f0f50bf1:
#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(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);
}