Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
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
Generated on Fri Jul 15 2022 00:05:33 by 1.7.2