Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

SnSDUtils.cpp

Committer:
uci1
Date:
2012-06-30
Revision:
0:664899e0b988
Child:
1:e392595b4b76

File content as of revision 0:664899e0b988:

#include "SnSDUtils.h"

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

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


const char*   SnSDUtils::kSDsubDir  = "/sd";
char          SnSDUtils::fgCurFileName[kFNBufSize];
const uint8_t SnSDUtils::kIOvers    = 1;

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++;
            }
        }
        closedir(d);
    }
    
    return seq;
}

FILE* SnSDUtils::OpenExistingFile(const char* name) {
    FILE* f = 0;
    if (name!=NULL) {
        f = fopen(name, "wb");
    }
    return f;
}

FILE* SnSDUtils::OpenNewOutputFile(const uint64_t macadr,
                                   const uint32_t run) {
    // 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);
    strcpy(fgCurFileName,GetOutFileName(macadr, run, seq));
    //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,seq);
    FILE* f = 0;
    if (fgCurFileName!=NULL) {
        f = fopen(fgCurFileName, "wb");
    }
    return f;
}

bool SnSDUtils::WriteFileHeader(FILE* f, const uint64_t macadr) {
    // MUST INCREMENT kIOvers if these writes are altered
    fwrite(&kIOvers, sizeof(uint8_t), 1, f);
    fwrite(&macadr, sizeof(uint64_t), 1, f);
    return ferror(f);
}

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) {
    
    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) {
                f = SnSDUtils::OpenExistingFile(dent->d_name);
                rs = comm->SendData(f);
                if (rs<SnCommWin::kAllFails) {
                    break;
                } else if (doDelete) {
                    DeleteFile(f, dent->d_name);
                }
            }
        }
        closedir(d);
    }
    
    return rs;
}