Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

SnEventFrame.h

Committer:
uci1
Date:
2019-06-05
Revision:
125:ce4045184366
Parent:
119:b3d7699d0eb0

File content as of revision 125:ce4045184366:

#ifndef SN_SnEventFrame
#define SN_SnEventFrame

#include <stdint.h>
#include "SnConstants.h"

//#define EVDEBUG

class SnEventFrame {
    
 public:
    // i/o version
    static const uint8_t    kIOVers;   // MUST BE INCREASED if any member var changes (==> also if kNchans, etc. change!)
    static const uint32_t   kMaxSizeOfV1 =  
            ((sizeof(uint32_t)*4u)+sizeof(int32_t)+sizeof(uint16_t)
            +(kTotSampsAtwd4ch*sizeof(uint16_t))+1u);
    static const uint32_t   kMaxSizeOfV2 = kMaxSizeOfV1
            - (kTotSampsAtwd4ch*sizeof(uint16_t)) 
            + (kTotSampsSst4ch*sizeof(uint16_t))
            + (kNstopBytesSst4ch*sizeof(uint8_t));
    static const uint32_t   kMaxSizeOfV3 = kMaxSizeOfV2; // same as V2 (just 1GHz clock)
    static const uint32_t   kMaxSizeOfV4 = kMaxSizeOfV1
            - (kTotSampsAtwd4ch*sizeof(uint16_t)) 
            + (kTotSampsSst4ch512*sizeof(uint16_t))
            + (kNstopBytesSst4ch512*sizeof(uint8_t));
    static const uint32_t   kMaxSizeOfV5 = kMaxSizeOfV4; // same as V4 (just 1GHz clock)
    static const uint32_t   kMaxSizeOfV6 = kMaxSizeOfV1
            - (kTotSampsAtwd4ch*sizeof(uint16_t)) 
            + (kTotSampsSst8ch*sizeof(uint16_t))
            + (kNstopBytesSst8ch*sizeof(uint8_t));
    static const uint32_t   kMaxSizeOfV7 = kMaxSizeOfV6; // same as V6 (just 1GHz clock)
    static const uint32_t   kMaxSizeOf   = kMaxSizeOfV5; // biggest one

 private:
    // !!
    // !! If any member variables change, update: SizeOf function and kIOVers value! (also if kNchans, etc. change!)
    // !!
    
    uint16_t            fData[kTotSamps];  // the (uncompressed) waveform data
    uint32_t            fMbedTime;         // mbed time in seconds since epoch
    // TODO: time since last event?
    uint32_t            fEvtNum;           // written event number ...
     int32_t            fDTms;             // time since last written event (ms)
    uint32_t            fTrgNum;           // this event is trigger number ...
    uint16_t            fTrgBits;          // trigger bit word
    mutable uint32_t    fCRC;              // CRC on the uncompressed waveform data
#if CHIPBOARD!=ATWD4CH
    uint8_t             fStop[kNstopBytes];// the stop bit word (one bit per sample)
#endif
    // TODO: check if other parameters should be added:
    // - stop position?
    // - card(s) producing trigger?
    
    void            CalcCRC();
    
    static
    bool ReadFromFileToBuf(FILE* f,
                           char* const evtBuf,
                           const uint8_t loseLSB, const uint8_t loseMSB);

    static
    bool WriteToFileFromBuf(FILE* f, char* const evtBuf,
                            const uint8_t loseLSB, const uint8_t loseMSB);
    
 public:
    SnEventFrame() { ClearEvent(true, true); }
    virtual ~SnEventFrame() {}

    virtual void CopyTo(SnEventFrame& evt) const {
        if (&evt!=this) {
            evt.fMbedTime = fMbedTime;
            evt.fEvtNum   = fEvtNum;
            evt.fDTms     = fDTms;
            evt.fTrgNum   = fTrgNum;
            evt.fTrgBits  = fTrgBits;
            evt.fCRC      = fCRC;
            memcpy(evt.fData, fData, kTotSamps*sizeof(uint16_t));
#if CHIPBOARD!=ATWD4CH
            memcpy(evt.fStop, fStop, kNstopBytes*sizeof(uint8_t));
#endif
        }
    }
    
    const uint16_t* GetData() const { return fData; }
          uint16_t* GetData()       { return fData; }
    const uint16_t* GetData(const uint8_t ch) const { return fData + (ch*kNsamps); }
          uint16_t* GetData(const uint8_t ch)       { return fData + (ch*kNsamps); }
          uint16_t  GetData(const uint8_t ch, const uint16_t sm) const
        { return fData[(ch*kNsamps)+sm]; }
          uint16_t& GetData(const uint8_t ch, const uint16_t sm)
        { return fData[(ch*kNsamps)+sm]; }
    
#if CHIPBOARD!=ATWD4CH
    const uint8_t*  GetStop() const { return fStop; }
          uint8_t*  GetStop()       { return fStop; }
#endif
        
    uint32_t GetMbedTime() const { return fMbedTime; }
    uint32_t GetEvtNum() const { return fEvtNum; }
    int32_t  GetDTms() const { return fDTms; }
    uint32_t GetTrgNum() const { return fTrgNum; }
    uint16_t GetTrgBits() const { return fTrgBits; }
    uint32_t GetCRC() const { return fCRC; }
    
    void ClearEvent(const bool clearTrigs,
                    const bool clearWaveData) {
#ifdef EVDEBUG
        printf("CLEARING EVENT!\r\n");
#endif
        fMbedTime = 0;
        
        if (clearWaveData) {
            memset(fData, 0, kTotSamps*sizeof(int16_t));
#if CHIPBOARD!=ATWD4CH
            memset(fStop, 0, kNstopBytes*sizeof(uint8_t));
#endif
            fCRC = 0;
        }
        if (clearTrigs) {
            fEvtNum = fTrgNum = 0;
            fTrgBits = 0;
        }
    }
    
    void SetTrgBit(const ETrgBit_t t)   { fTrgBits |= t; }
    void DisableTrgBit(const ETrgBit_t b) { fTrgBits &= ~b; }
    void SetTrgNum(const uint32_t t)    { fTrgNum = t; }
    void SetEvtNum(const uint32_t n)    { fEvtNum = n; }
    void SetDTms(const int32_t dtms)    { fDTms = dtms; }
    void SetCurMbedTime()               { fMbedTime = time(0); }
    
//    bool IsForcedTrg() const { return (fTrgBits & kFrcTrg)!=0; }
    
#if CHIPBOARD!=ATWD4CH
    void ReadWaveformsSST(SPI& spi, DigitalOut& readingData) {
        readingData   = 1;  // start reading

        // first get waveform data
        uint16_t* d = fData;
        for (uint8_t ch=0; ch<kNchans; ++ch) {
#ifdef EVDEBUG
            printf("new channel %hhu\r\n",ch);
#endif

            spi.format( 5, 1 ); // throw away leading bits (1 meaningless + 4 MSB 0's bits before 12 bit ADC value)
            spi.write(0);       // get the throw away bits
            spi.format( 12, 1); // read remaining

            for (uint16_t i=0; i<kNsamps; ++i, ++d) {
                *d = spi.write(0x00)/* >> 1*/; // get rid of stop bit (TODO: is this right?)
                if (i==0) {
                    spi.format( 16, 1); // back to normal
                }
#ifdef EVDEBUG
                if (i==0 || i==1) {
                    printf("d: spi gave (%hu) ",*d);
                    SnBitUtils::printBits(*d, false);
                }
#endif
            }
        }
        // now get stop data
        uint8_t* s = fStop;
        uint16_t sd(0);
        for (uint16_t i=0; i<kNstopBytes; i+=2, s+=2) {
            if (i==0) {
                // need to throw away the very first bit
                // but we can't ask spi to send only 1 bit
                spi.format( 5, 1 );
                sd = spi.write(0x00);
                // toss the first bit totally
                // move the other 4 bits to the front
                sd <<= 12;
                spi.format( 12, 1); // read the rest of the real 16 bits
                sd |= spi.write(0x00);
                spi.format( 16, 1); // normal after this
            } else {
                sd = spi.write(0x00);
            }
#ifdef EVDEBUG
            /*
            printf("s: spi gave (%hu) ",sd);
            SnBitUtils::printBits(sd, false);
            */
#endif
            *s     = (sd & 0xFF00) >> BITS_IN_CHAR;
            *(s+1) =  sd & 0x00FF;
        }
        readingData   = 0;  // done reading
        /*
        // get rid of stop bit (TODO: is this right?)
        *s >>= 1;
        *s <<= 1;
        */
#ifdef EVDEBUG
        /*
        d = fData;
        for (uint8_t ch=0; ch<kNchans; ch++) {
            for (uint16_t i=0; i<kNsamps; i++, d++) {
                printf("(%hhu,%03hhu,%hu) ",ch,i,*d);
            }
            printf("\r\n");
        }
        s = fStop;
        for (uint16_t i=0; i<kNstopBytes; ++i, ++s) {
            for (int16_t j=(sizeof(uint8_t)*BITS_IN_CHAR)-1; j>-1; --j) {
                if ( (*s&(1<<j))!=0 ) {
                    printf("stop bit at %hu\r\n",
                        j+(BITS_IN_CHAR*sizeof(uint8_t)*i));
                }
            }
        }
        */
#endif
        CalcCRC();
    }
#endif
    
    void ReadWaveformsATWD(SPI& spi,
                           DigitalOut& cardHiBit, DigitalOut& cardLoBit) {
        uint16_t* dev=fData;
        for( uint8_t ch = 0; ch < kNchans; ch++ ) {
            // Pick which register to read.
            SnBitUtils::SetChanNumBits(ch, cardHiBit, cardLoBit);
            for( uint16_t i = 0; i < kNsamps; i++, dev++ ) {        
                *dev = spi.write(0x00) >> 1;
            }
        }
#ifdef EVDEBUG
        dev = fData;
        for (uint8_t ch=0; ch<kNchans; ch++) {
            for (uint16_t i=0; i<kNsamps; i++, dev++) {
                printf("(%hhu,%03hhu,%hu) ",ch,i,*dev);
            }
            printf("\r\n");
        }
#endif
        CalcCRC();
    }
    
        
    static
    uint16_t GetTotSamplesForIOVers(const uint8_t rv) {
        if (rv<2) {
            return kTotSampsAtwd4ch;
        } else if ((rv==2)||(rv==3)) {
            return kTotSampsSst4ch;
        } else if ((rv==4)||(rv==5)) {
            return kTotSampsSst4ch512;
        } else if ((rv==6)||(rv==7)) {
            return kTotSampsSst8ch;
        } else {
            // ???
            return kTotSampsSst4ch;
        }
    }
    
    static
    uint16_t GetStopBytesForIOVers(const uint8_t rv) {
        if (rv<2) {
            return 0;
        } else if ((rv==2)||(rv==3)) {
            return kNstopBytesSst4ch;
        } else if ((rv==4)||(rv==5)) {
            return kNstopBytesSst4ch512;
        } else if ((rv==6)||(rv==7)) {
            return kNstopBytesSst8ch;
        } else {
            // ???
            return kNstopBytesSst4ch;
        }
    }

    static
    uint16_t GetStopBytesForIOVersBufferSafe(const uint8_t rv) {
        // get the max number of stop bytes that will fit in an fStop buffer
        const uint16_t nsb = GetStopBytesForIOVers(rv);
        return (nsb>kNstopBytes) ? kNstopBytes : nsb; // prevent buffer overflow
    }
    
    static
    uint32_t SizeOf(const uint8_t rv, const uint8_t loseLSB, const uint8_t loseMSB) {
        // size of member vars + size of packed waveform + 1 for i/o version
#ifdef EVDEBUG
        printf("event: rv=%hhu, loseLBS=%hhu, loseMSB=%hhu\r\n", rv, loseLSB, loseMSB);
#endif
        uint32_t sz(0);
        const uint16_t ntotsamps = GetTotSamplesForIOVers(rv);
        if (rv==1) {
            sz = kMaxSizeOfV1;
        } else if (rv==2) {
            sz = kMaxSizeOfV2;
        } else if (rv==3) {
            sz = kMaxSizeOfV3;
        } else if (rv==4) {
            sz = kMaxSizeOfV4;
        } else if (rv==5) {
            sz = kMaxSizeOfV5;
        } else if (rv==6) {
            sz = kMaxSizeOfV6;
        } else if (rv==7) {
            sz = kMaxSizeOfV7;
        } else {
            sz = kMaxSizeOf;
        }
#ifdef EVDEBUG
        printf("event: ntotsamps=%hu, sz=%u\r\n", ntotsamps, sz);
#endif
        if ((loseLSB==0) && (loseMSB==0)) {
            return sz;
        } else {
#ifdef EVDEBUG
            printf("event packed size=%u\r\n",
                (sz-(ntotsamps*sizeof(uint16_t))
                      +SizeOfPackedWavef(loseLSB, loseMSB, ntotsamps)));
#endif
            return (sz-(ntotsamps*sizeof(uint16_t))
                      +SizeOfPackedWavef(loseLSB, loseMSB, ntotsamps));
        }
    }
    
    static
    uint32_t SizeOfPackedWavef(const uint8_t loseLSB,
                               const uint8_t loseMSB,
                               const uint16_t totsamps=kTotSamps) {
        const uint8_t p = BITS_IN_SHORT-loseLSB-loseMSB;
        return ((p*totsamps)/8u) + (((p*totsamps)%8u)!=0 ? 1u : 0u);
    }
    
    const char* ReadFrom(const char* const buf,
                         const uint8_t loseLSB, const uint8_t loseMSB,
                         const uint16_t wvBaseline);
    
    char* WriteTo(char* const buf,
                  const uint8_t loseLSB, const uint8_t loseMSB,
                  const uint16_t wvBaseline) const;
    
    bool ReadFrom(FILE* f, char* const evtBuf,
                  const uint8_t loseLSB, const uint8_t loseMSB,
                  const uint16_t wvBaseline);
    bool WriteTo(FILE* f, char* const evtBuf,
                 const uint8_t loseLSB, const uint8_t loseMSB,
                 const uint16_t wvBaseline) const;
        
    static
    const uint8_t* 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);
    
    static
    uint8_t* 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);
};


#endif // SN_SnEventFrame