Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

SnSDUtils.cpp

Committer:
uci1
Date:
2012-08-03
Revision:
5:9cea89700c66
Parent:
4:a91682e19d6b
Child:
6:6f002d202f59

File content as of revision 5:9cea89700c66:

#include "SnSDUtils.h"

#include "mbed.h"
#include "SDFileSystem.h"
#include <string.h>

#include "SnConfigFrame.h"
#include "SnEventFrame.h"


const char* const SnSDUtils::kSDsubDir  = "/sd";
char              SnSDUtils::fgCurFileName[kFNBufSize]={0};
FILE*             SnSDUtils::fgCurFile  = 0;
const uint8_t     SnSDUtils::kIOvers    = 2;
const uint32_t    SnSDUtils::kMaxSizeOfFileHdr = 
    sizeof(uint8_t)+sizeof(uint64_t)+sizeof(uint32_t)+sizeof(uint16_t)
    +SnPowerFrame::kMaxSizeOf;

static const uint16_t __kMaxUShort = ~0;

const char* SnSDUtils::GetOutFileName(const uint64_t macadr,
                                      const uint32_t run,
                                      const uint16_t seq) {
    // returns the formatted file name, or NULL if the directory is too long
    // and the full name cannot fit in the buffer
    // NOTE: this fcn uses a static buffer, and so should not be called
    // multiple times in the same line (that includes the calling of functions
    // that call this function!)
    //
    // filename = SnEvtsM[6-byte hex mac adr]r[6-digit run num]s[5-digit seq num].dat
    //  35 chars      7     +    12         +1+         5     +1+     5         + 4
    
    if (strlen(kSDsubDir)<(kFNBufSize-37)) {
        static char tbuf[kFNBufSize];
        memset(tbuf, 0, sizeof(char)*kFNBufSize);
        // if file name format changes, GetSeqNum must be changed too
        sprintf(tbuf, "%s/SnEvtsM%012llXr%05ds%05d.dat",
            kSDsubDir,
            macadr>>16, // 64 -> 48 bits
            run, seq);
        return tbuf;
    } else {
        return NULL;
    }
}

uint16_t SnSDUtils::GetSeqNum(const uint64_t macadr,
                              const uint32_t run) {
    // count the files having expected filename format
    
    const char* fn = GetOutFileName(macadr, run, 0)
        + strlen(kSDsubDir) + 1; // take out dir and '/'s
    
    DIR* d;
    struct dirent* dent;
    
    uint16_t seq=0;
    if ( (d = opendir( kSDsubDir ))!=NULL ) {
        // don't compare seq#. don't use num of chars in case seq is >999
        const uint32_t ncomp = strrchr(fn, 's') - fn;
        while ( (dent = readdir(d))!=NULL ) {
            if (strncmp(dent->d_name, fn, ncomp)==0) {
                seq++;
                if (seq==__kMaxUShort) {
                    break;
                }
            }
        }
        closedir(d);
    }
    
    return seq;
}

FILE* SnSDUtils::OpenExistingFile(const char* name, const bool setcurrent) {
    FILE* f = 0;
    if (name!=NULL) {
        f = OpenSDFile(name, "rb");
        if (setcurrent) {
            fgCurFile = f;
        }
    }
    return f;
}

FILE* SnSDUtils::OpenSDFile(const char* name, const char* mode) {
    FILE* f = fopen(name, mode);
    //setvbuf(f, 0, _IONBF, 0); // no buffering
    return f;
}

FILE* SnSDUtils::OpenNewOutputFile(const uint64_t macadr,
                                   const uint32_t run,
                                   const uint16_t v1, const uint16_t v2) {
    // opens a new file in the specified directory and writes this
    // this mbed's mac address as the first sizeof(uint64_t) bytes (i.e. 4 bytes)
    //
    const uint16_t seq = GetSeqNum(macadr, run);
    memset(fgCurFileName, 0, sizeof(char)*kFNBufSize);
    strncpy(fgCurFileName,GetOutFileName(macadr, run, seq),kFNBufSize-1);
    //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,seq);
    fgCurFile = 0;
    if (fgCurFileName!=NULL) {
        fgCurFile = OpenSDFile(fgCurFileName, "wb");
        if (fgCurFile!=NULL && ferror(fgCurFile)==0) {
            WriteFileHeader(fgCurFile, macadr, run, seq, v1, v2);
        }
    }
    return fgCurFile;
}

bool SnSDUtils::WriteEventTo(FILE* efile, char* const evtBuf,
                             const SnEventFrame& evt,
                             const SnConfigFrame& conf) {
    // write event to SD card
        
    uint8_t sLoseLSB=0, sLoseMSB=0;
    uint16_t sWvBase=0;
    conf.GetPackParsFor(SnConfigFrame::kSDcard, sLoseLSB, sLoseMSB, sWvBase);
    const bool ret = evt.WriteTo(efile, evtBuf, sLoseLSB, sLoseMSB, sWvBase);
    fflush(efile);
    return ret;
}

bool SnSDUtils::WriteConfig(FILE* efile,
                            const SnConfigFrame& conf) {
    conf.WriteTo(efile);
    return true;
}

void SnSDUtils::DeleteFile(FILE*& f, const char* fname) {
    fclose(f);
    f=0;
    remove(fname);
}

SnCommWin::ECommWinResult SnSDUtils::SendAllFiles(SnCommWin* comm,
                                                  const bool doDelete,
                                                  const uint32_t timeout,
                                                  char* const buf,
                                                  const uint32_t bsize) {
    
    DIR* d;
    struct dirent* dent;
    
    SnCommWin::ECommWinResult rs = SnCommWin::kUndefFail;
    
    if ( (d = opendir( kSDsubDir ))!=NULL ) {
        FILE* f;
        while ( (dent = readdir(d))!=NULL ) {
            if (strncmp(dent->d_name, "SnEvts", 6)==0) {
                const bool isCurFile = 
                    (strcmp(dent->d_name, GetCurFileName())==0);
                if (isCurFile) {
                    // file must already be written out!
                    f = GetCurFile();
                } else {
                    f = OpenExistingFile(dent->d_name, false);
                }
                // send the filename
                rs = comm->SendFilename(dent->d_name, buf);
                if (rs<SnCommWin::kAllFails) {
                    // send the data from the file
                    rs = comm->SendData(f);
                    if (rs<SnCommWin::kAllFails) {
                        break;
                    } else {
                        // wait for handshake before next file
                        rs = comm->WaitHandshake(timeout, buf, bsize);
                        if ((rs==SnCommWin::kOkWithMsg) 
                             && doDelete && (isCurFile==false)) {
                            DeleteFile(f, dent->d_name);
                        }
                    }
                }
                if (isCurFile) {
                    // move (back) to the end of the file
                    // altho hopefully no writing will happen after this
                    fseek(fgCurFile, 0, SEEK_END);
                }
            }
        }
        closedir(d);
    }
    
    return rs;
}