Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SnEventFrame.cpp Source File

SnEventFrame.cpp

00001 #include "SnEventFrame.h"
00002 
00003 #include "SnCRCUtils.h"
00004 
00005 //#define DEBUG
00006 
00007 #if CHIPBOARD==ATWD4CH
00008 const uint8_t     SnEventFrame::kIOVers = 1;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
00009 #elif CHIPBOARD==SST4CH
00010 const uint8_t     SnEventFrame::kIOVers = 2;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
00011 #elif CHIPBOARD==SST4CH_1GHz
00012 const uint8_t     SnEventFrame::kIOVers = 3;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
00013 #elif CHIPBOARD==SST4CH512
00014 const uint8_t     SnEventFrame::kIOVers = 4;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
00015 #elif CHIPBOARD==SST4CH512_1GHz
00016 const uint8_t     SnEventFrame::kIOVers = 5;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
00017 #elif CHIPBOARD==SST8CH
00018 const uint8_t     SnEventFrame::kIOVers = 6;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
00019 #elif CHIPBOARD==SST8CH_1GHz
00020 const uint8_t     SnEventFrame::kIOVers = 7;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
00021 #else
00022 #error CHIPBOARD value not accounted for in event frame i/o version.
00023 #endif
00024 
00025 const char* SnEventFrame::ReadFrom(const char* const buf,
00026                                    const uint8_t loseLSB, const uint8_t loseMSB,
00027                                    const uint16_t wvBaseline) {
00028     // no check on the length of buf is done here
00029     // that should be been done already
00030     //
00031     // must match ::WriteToBuf
00032     
00033     // NOTE: on the mbed, this is reduntant (char is unsigned)
00034     // but this way, the block can be copied to other computers
00035     // and still work.
00036     union Usub {
00037         const char* s;
00038         const uint8_t* u;
00039     } b;
00040     b.s = buf;
00041    
00042     uint8_t Rv=0;
00043     b.s           = SnBitUtils::ReadFrom(b.s, Rv); // i/o version
00044     if (Rv>0) {
00045 
00046         const uint16_t nsamps = GetTotSamplesForIOVers(Rv);
00047 
00048         b.s       = SnBitUtils::ReadFrom(b.s, fMbedTime);
00049         b.s       = SnBitUtils::ReadFrom(b.s, fEvtNum);
00050         b.s       = SnBitUtils::ReadFrom(b.s, fDTms);
00051         b.s       = SnBitUtils::ReadFrom(b.s, fTrgNum);
00052         b.s       = SnBitUtils::ReadFrom(b.s, fTrgBits);
00053         b.u       = UnpackWavef(b.u, fData, loseLSB, loseMSB, wvBaseline, nsamps);
00054         b.s       = SnBitUtils::ReadFrom(b.s, fCRC);
00055 
00056 #if CHIPBOARD!=ATWD4CH
00057         const uint16_t nstopBytes = GetStopBytesForIOVersBufferSafe(Rv);
00058         if (Rv>1) {
00059             b.s   = SnBitUtils::ReadFrom(b.s, fStop, nstopBytes);
00060         }
00061 #endif
00062     }
00063     
00064     return b.s;
00065 }
00066 
00067 char* SnEventFrame::WriteTo(char* const buf,
00068                             const uint8_t loseLSB, const uint8_t loseMSB,
00069                             const uint16_t wvBaseline) const {
00070     // no check on the length of the buf is done here
00071     // that should be done already
00072     //
00073     // must match ReadFromBuf
00074     
00075     // NOTE: on the mbed, this is reduntant (char is unsigned)
00076     // but this way, the block can be copied to other computers
00077     // and still work.
00078     union {
00079         char* s;
00080         uint8_t* u;
00081     } b;
00082     b.s = buf;
00083     
00084     b.s           = SnBitUtils::WriteTo(b.s, kIOVers); // i/o version
00085 
00086     const uint16_t nsamps = GetTotSamplesForIOVers(kIOVers);
00087     
00088     b.s           = SnBitUtils::WriteTo(b.s, fMbedTime);
00089     b.s           = SnBitUtils::WriteTo(b.s, fEvtNum);
00090     b.s           = SnBitUtils::WriteTo(b.s, fDTms);
00091     b.s           = SnBitUtils::WriteTo(b.s, fTrgNum);
00092     b.s           = SnBitUtils::WriteTo(b.s, fTrgBits);
00093     b.u           = PackWavef(b.u, fData, loseLSB, loseMSB, wvBaseline, nsamps);
00094     b.s           = SnBitUtils::WriteTo(b.s, fCRC);
00095 
00096 #if CHIPBOARD!=ATWD4CH
00097     const uint16_t nstopBytes = GetStopBytesForIOVersBufferSafe(kIOVers);
00098     if (kIOVers>1) {
00099         // we test kIOVers rather than the CHIPBOARD #define in order
00100         // to ensure that the i/o version is the ONLY variable that determines
00101         // what the event looks like in a file or communication.
00102         // this is the only way to ensure readability going forward.
00103 #ifdef DEBUG
00104         printf("kNstopBytes=%hu, nstopBytes=%hu, kIOVers=%hhu\r\n",
00105             kNstopBytes, nstopBytes, kIOVers);
00106         char* x = b.s;
00107 #endif
00108         b.s       = SnBitUtils::WriteTo(b.s, fStop, nstopBytes);
00109 #ifdef DEBUG
00110         printf("wrote %d stop bytes\r\n", b.s - x);
00111 #endif
00112     }
00113 #endif
00114 
00115 #ifdef DEBUG
00116     printf("SnEventFrame::WriteTo:\r\n");
00117     for (uint32_t i=0; i<b.s-buf; i++) {
00118         printf("%02X ",buf[i]);
00119     }
00120     printf("\r\n");
00121 #endif
00122     
00123     return b.s;
00124 }
00125 
00126 void SnEventFrame::CalcCRC() {
00127     // CRC made using union on a little endian (mbed) processor
00128     fCRC = SnCRCUtils::GetCRC32for(fData, kTotSamps);
00129 #if CHIPBOARD!=ATWD4CH
00130     fCRC = SnCRCUtils::GetUpdatedCRC32for(fCRC, fStop, kNstopBytes);
00131 #endif
00132 #ifdef DEBUG
00133     printf("SnEventFrame::CalcCRC  crc=%u\r\n",fCRC);
00134 #endif
00135 }
00136 
00137 bool SnEventFrame::ReadFromFileToBuf(FILE* f,
00138                                      char* const evtBuf,
00139                                      const uint8_t loseLSB,
00140                                      const uint8_t loseMSB) {
00141     // file position expected to be at this event frame already
00142     bool ret = false;
00143     if (f!=0) {
00144         if (fread(evtBuf, SizeOf(kIOVers, loseLSB, loseMSB), 1u, f)!=0) {
00145             ret = true;
00146         }
00147     }
00148     return ret;
00149 }
00150 
00151 bool SnEventFrame::ReadFrom(FILE* f,
00152                             char* const evtBuf,
00153                             const uint8_t loseLSB, const uint8_t loseMSB,
00154                             const uint16_t wvBaseline) {
00155     // file position expected to be at this event frame already
00156     const bool ret = ReadFromFileToBuf(f, evtBuf, loseLSB, loseMSB);
00157     if (ret) {
00158         ReadFrom(evtBuf, loseLSB, loseMSB, wvBaseline);
00159     }
00160     return ret;
00161 }
00162 
00163 bool SnEventFrame::WriteTo(FILE* f, char* const evtBuf,
00164                            const uint8_t loseLSB, const uint8_t loseMSB,
00165                            const uint16_t wvBaseline) const {
00166     // file pointer should be in correct location
00167     
00168     WriteTo(evtBuf, loseLSB, loseMSB, wvBaseline);
00169     return WriteToFileFromBuf(f, evtBuf, loseLSB, loseMSB);
00170 }
00171 
00172 bool SnEventFrame::WriteToFileFromBuf(FILE* f, char* const evtBuf,
00173                                const uint8_t loseLSB, const uint8_t loseMSB) {
00174     // file pointer should be in correct location
00175     
00176     bool ret = false;
00177     if (f!=0) {
00178         fwrite(evtBuf, SizeOf(kIOVers, loseLSB, loseMSB), 1u, f);
00179         ret = (ferror(f)==false);
00180     }
00181     return ret;
00182 
00183 }
00184 
00185 
00186 uint8_t* SnEventFrame::PackWavef(uint8_t* const buf, const uint16_t* const data,
00187                                  const uint8_t loseLSB, const uint8_t loseMSB,
00188                                  const uint16_t wvBaseline,
00189                                  const uint16_t nsamps) {
00190     // Compress the data. This is potentially LOSSY; it depends
00191     // on the dynamic range and on the options.
00192     // See SnConfigFrame::fWvLoseLSB and SnConfigFrame::fWvLoseMSB.
00193     // If the number of least signficant bits to lose is not 0, the
00194     // compression will be lossy (decreased resolution -- this is ok
00195     // if the noise of the signal is much greater than the resolution).
00196     // Losing the most significant bits will only be lossy if the
00197     // signal-SnConfigFrame::fWvBaseline cannot fit in the reduced
00198     // dynamic range (each MSB bit reducing the DR by a factor of 2).
00199     //
00200     // Note that the mbed uses little endian. Behavior should be the
00201     // same on big endian, but this has not been tested.
00202     //
00203     // Use an unsigned buffer to prevent bits being changed during
00204     // an implicit unsigned -> signed cast.
00205     //
00206     // buf = the byte array into which the data should be packed
00207     // data = the data to pack
00208     // loseLSB = number of least significant bits to throw away
00209     // loseMSB = number of most significant bits to throw away
00210     // wvBaseline = baseline to subtract to from ADC before packing
00211     
00212     const uint32_t blen = SizeOfPackedWavef(loseLSB, loseMSB);
00213     const uint8_t packSmpBits = BITS_IN_SHORT-loseLSB-loseMSB;
00214 
00215     // make sure this buffer space is all 0's to start
00216     memset(buf, 0, blen*sizeof(uint8_t));
00217     
00218     const uint16_t clipHi = uint16_t(
00219        uint16_t(uint16_t(0xFFFFu >> loseLSB) << (loseLSB+loseMSB))
00220                 >> loseMSB);
00221     
00222     uint8_t* b = buf;
00223     const uint16_t* dev = data;
00224     uint16_t dum;
00225     int8_t sbit=0;
00226     for (uint16_t i=0; i<nsamps; ++i, ++dev) {
00227         // dump the bits we don't want
00228         dum = (*dev) - wvBaseline;
00229         if (dum<clipHi) {
00230           dum >>= loseLSB;
00231           dum <<= (loseLSB+loseMSB);
00232         } else {
00233           dum = clipHi << loseMSB;
00234         }
00235         if (sbit<=0) {
00236             // lose MSB's put in previous short (or none if sbit==0)
00237             dum   <<= -sbit;
00238             *b     |= dum >> 8u;         // "first" byte of the short
00239             dum   <<= 8u;
00240             *(b+1) |= dum >> 8u;   // "second"
00241             // move to next number (dev++ in the for loop)
00242             // move starting bit up
00243             // but stay in this byte of the buf (do not increment b)
00244             // since kPackSmpBits <= kBitsInShort, sbit can't
00245             // move past the end of the current two bytes
00246             sbit += packSmpBits;
00247         } else {
00248             // first few bits towards the end of this short
00249             dum   >>= sbit;
00250             *b     |= dum >> 8u;         // "first" byte of the short
00251             dum   <<= 8u;
00252             *(b+1) |= dum >> 8u;   // "second"
00253             if ( (sbit+packSmpBits) >= BITS_IN_SHORT ) {
00254                b+=2;       // move to next short in the buf
00255                i--; dev--; // but stay on this number
00256                // move starting bit back into the short we just filled
00257                sbit -= BITS_IN_SHORT;
00258             } else {
00259                // stay in this buffer and move to the next number
00260                // move starting bit up
00261                sbit += packSmpBits;
00262             }
00263         }
00264     }
00265     
00266     return buf+blen;
00267 }
00268 
00269 const uint8_t* SnEventFrame::UnpackWavef(const uint8_t* const buf,
00270                                          uint16_t* const data,
00271                                          const uint8_t loseLSB,
00272                                          const uint8_t loseMSB,
00273                                          const uint16_t wvBaseline,
00274                                          const uint16_t nsamps) {
00275     if (loseLSB==0 && loseMSB==0 && wvBaseline==0) {
00276         memcpy(data, buf, nsamps*sizeof(uint16_t));
00277     } else {
00278 
00279         const uint8_t packSmpBits = BITS_IN_SHORT-loseLSB-loseMSB;
00280     
00281         // make sure data is all 0's to start
00282         memset(data, 0, nsamps*sizeof(uint16_t));
00283         
00284         const uint8_t* b = buf;
00285         uint16_t* dev = data;
00286         uint16_t dum;
00287         int8_t sbit=0;
00288         for (uint16_t i=0; i<nsamps; ++i, ++dev) {
00289             dum  = (*b) << 8u;
00290             dum |= *(b+1);
00291             if (sbit<=0) {
00292                 dum >>= (-sbit+loseLSB+loseMSB);
00293                 dum <<= loseLSB;
00294                 *dev |= dum;
00295                 // add baseline and move to next number (dev++ in the for loop)
00296                 *dev += wvBaseline;
00297                 // but stay in this short of the buf (do not increment b)
00298                 // move starting bit up
00299                 sbit += packSmpBits;
00300             } else {
00301                 dum <<= sbit;
00302                 dum >>= loseMSB+loseLSB;
00303                 dum <<= loseLSB;
00304                 *dev = dum;
00305                 if ( (sbit+packSmpBits) >= BITS_IN_SHORT ) {
00306                    b+=2;       // move to next short in the buf
00307                    i--; dev--; // but stay on this number
00308                    // move starting bit back into the short we just read from
00309                    sbit -= BITS_IN_SHORT;
00310                 } else {
00311                    // add baseline and move to next number (dev++ in the for loop)
00312                    *dev += wvBaseline;
00313                    sbit += packSmpBits;
00314                 }
00315             } 
00316         }
00317     }
00318     
00319     return buf+SizeOfPackedWavef(loseLSB, loseMSB);
00320 }
00321