Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Revision:
56:0bba0ef15697
Parent:
47:fbe956b10a91
Child:
63:4820a4460f00
--- a/SnSDUtils.cpp	Fri Jan 03 13:03:01 2014 +0000
+++ b/SnSDUtils.cpp	Thu Oct 30 06:42:17 2014 +0000
@@ -19,6 +19,9 @@
 
 const char* const SnSDUtils::kSDdir     = "/sd";
 const char* const SnSDUtils::kSDsubDir  = "/sd/data";
+const char* const SnSDUtils::kRunSeqListFilenm = "/sd/RunSeqLC.txt";
+const uint16_t    SnSDUtils::kMaxSeqNum = 64000; // max "normal" seq
+const uint16_t    SnSDUtils::kBadSeqNum = 65000; // should be larger than kMaxSeqNum to separate "normal" and "bad" seqs
 char              SnSDUtils::fgCurFileName[kFNBufSize]={0};
 FILE*             SnSDUtils::fgCurFile  = 0;
 uint16_t          SnSDUtils::fgCurSeq   = 0;
@@ -29,14 +32,18 @@
     +(sizeof(uint8_t)+(2u*sizeof(uint16_t))); // power frame v1
 
 SnSDUtils::InitSDFcn SnSDUtils::fgDoInit = 0;
+bool                 SnSDUtils::fgInitOk = false;
 
 static const uint16_t __kMaxUShort = ~0;
 
-void SnSDUtils::InitSDCard(const bool force) {
+bool SnSDUtils::InitSDCard(const bool force) {
     if ((fgNeedToInit || force) && (fgDoInit!=0)) {
-        (*fgDoInit)();
-        fgNeedToInit = false;
+        fgInitOk = (*fgDoInit)() == 0;
+        if (IsInitOk()) {
+            fgNeedToInit = false;
+        }
     }
+    return fgInitOk;
 }
 
 const char* SnSDUtils::GetSubDirFor(const uint32_t run, const uint16_t seq,
@@ -155,113 +162,130 @@
 #ifdef DEBUG
     printf("open dir %s\r\n",dirname);
 #endif
-    InitSDCard();
+    if (InitSDCard()) {
 
-    DIR* rd( opendir(dirname) );
-    if (rd==NULL) {
-        // try making the directory
+        DIR* rd( opendir(dirname) );
+        if (rd==NULL) {
+            // try making the directory
 #ifdef DEBUG
-        printf("making dir %s\r\n",dirname);
+            printf("making dir %s\r\n",dirname);
 #endif
-        mkdir(dirname, 0777);
+            mkdir(dirname, 0777);
 #ifdef DEBUG
-        printf("opening dir %s\r\n",dirname);
+            printf("opening dir %s\r\n",dirname);
 #endif
-        rd = opendir(dirname);
-    }
+            rd = opendir(dirname);
+        }
 #ifdef DEBUG
-        printf("returning rd=%p\r\n",(void*)rd);
+            printf("returning rd=%p\r\n",(void*)rd);
 #endif
-    return rd;
+        return rd;
+    } else {
+        return 0;
+    }
 }
 
 uint16_t SnSDUtils::GetSeqNum(const uint64_t macadr,
                               const uint32_t run) {
     // count the files having expected filename format
-    InitSDCard();
+
+    uint16_t maxs(kBadSeqNum);
     
-    // get the run dir
-    uint32_t rdlen(0);
-    std::string rdnms ( GetSubDirFor(run, 0, rdlen, false) );
-    const char* rdnm = rdnms.c_str();
-    // open/make the run directory
-    FATDirHandle* rd(static_cast<FATDirHandle*>( OpenOrMakeAllDirs(rdnm) ));
-    struct dirent* rdent;
-    uint16_t dseq(0), maxs(0);
+    if (InitSDCard()) {
+        
+        maxs = 0; // change back from kBadSeqNum!
+        
+        // get the run dir
+        uint32_t rdlen(0);
+        std::string rdnms ( GetSubDirFor(run, 0, rdlen, false) );
+        const char* rdnm = rdnms.c_str();
+        // open/make the run directory
+        FATDirHandle* rd(static_cast<FATDirHandle*>( OpenOrMakeAllDirs(rdnm) ));
+        struct dirent* rdent;
+        uint16_t dseq(0);
 #ifdef DEBUG
-        printf("starting readdir loop over %p\r\n",(void*)rd);
+            printf("starting readdir loop over %p\r\n",(void*)rd);
 #endif    
-    while ( (rdent = readdir(rd))!=NULL ) {
+        while ( (rdent = readdir(rd))!=NULL ) {
 #ifdef DEBUG
-        printf("rdent = %p\r\n",(void*)rdent);
+            printf("rdent = %p\r\n",(void*)rdent);
 #endif    
-        if ((rd->filinfo()->fattrib & AM_DIR)!=0) {
+            if ((rd->filinfo()->fattrib & AM_DIR)!=0) {
 #ifdef DEBUG
-            printf("is a dir\r\n");
+                printf("is a dir\r\n");
 #endif    
-            // is a directory
-            const int ncm = sscanf(rdent->d_name, "s%hu", &dseq);
-            if (ncm==1) {
-                if (dseq>maxs) {
-                    maxs = dseq;
+                // is a directory
+                const int ncm = sscanf(rdent->d_name, "s%hu", &dseq);
+                if (ncm==1) {
+#ifdef DEBUG
+                    printf("dseq=%hu, maxs=%hu\r\n",dseq,maxs);
+#endif                    
+                    if ( (dseq>maxs) && (dseq<kMaxSeqNum) ) {
+                        maxs = dseq;
+                    }
                 }
             }
+#ifdef DEBUG
+             else {
+                printf("not a dir\r\n");
+            }
+#endif    
         }
 #ifdef DEBUG
-         else {
-            printf("not a dir\r\n");
-        }
+        printf("closing directory %p\r\n",(void*)rd);
 #endif    
-    }
+        closedir(rd);
 #ifdef DEBUG
-    printf("closing directory %p\r\n",(void*)rd);
-#endif    
-    closedir(rd);
-#ifdef DEBUG
-    printf("Found max seq dir num %hu for run %u\r\n",maxs,run);
+        printf("Found max seq dir num %hu for run %u\r\n",maxs,run);
 #endif
-    // open up the seq dir
-    rdnms = GetSubDirFor(run, maxs, rdlen, true);
-    rdnm = rdnms.c_str();
-    // runXseq0 filename (fn points to a static buffer)
-    const char* fn = GetOutFileName(macadr, run, maxs)
-        + rdlen + 1; // take out dir and '/'s
-    // don't compare seq#. don't use num of chars in case seq is >999
-    const int32_t ncomp = strrchr(fn, 's') - fn;
-    // open (or make) the run/seq dir
-    rd = static_cast<FATDirHandle*>( OpenOrMakeAllDirs(rdnm) );
-    // get the new sequence number (ok if it overflows this seq "bin")
-    maxs=0;
-    while ( (rdent = readdir(rd))!=NULL ) {
-        Watchdog::kick(); // don't reset
-        if ((rd->filinfo()->fattrib & AM_DIR)==0) {
-            // is a file.
-            // don't just count files, in case one seq was
-            // transferred and erased in the middle of a run
-            if (strncmp(rdent->d_name, fn, ncomp)==0) {
-                // allow for deleted files to make gaps.
-                // search for highest seq number and increase that
-                if (sscanf((rdent->d_name)+ncomp,"s%hu.dat",&dseq)==1) {
+        // open up the seq dir
+        rdnms = GetSubDirFor(run, maxs, rdlen, true);
+        rdnm = rdnms.c_str();
+        // runXseq0 filename (fn points to a static buffer)
+        const char* fn = GetOutFileName(macadr, run, maxs)
+            + rdlen + 1; // take out dir and '/'s
+        // don't compare seq#. don't use num of chars in case seq is >999
+        const int32_t ncomp = strrchr(fn, 's') - fn;
+        // open (or make) the run/seq dir
+        rd = static_cast<FATDirHandle*>( OpenOrMakeAllDirs(rdnm) );
+        // get the new sequence number (ok if it overflows this seq "bin")
+        maxs=0;
+        while ( (rdent = readdir(rd))!=NULL ) {
+            Watchdog::kick(); // don't reset
+            if ((rd->filinfo()->fattrib & AM_DIR)==0) {
+                // is a file.
+                // don't just count files, in case one seq was
+                // transferred and erased in the middle of a run
+                if (strncmp(rdent->d_name, fn, ncomp)==0) {
+                    // allow for deleted files to make gaps.
+                    // search for highest seq number and increase that
+                    if (sscanf((rdent->d_name)+ncomp,"s%hu.dat",&dseq)==1) {
 #ifdef DEBUG
-                    printf("dn=%s, seq=%hu, __kMaxUShort=%hu\r\n",
-                        rdent->d_name, dseq, __kMaxUShort);
+                        printf("dn=%s, seq=%hu, __kMaxUShort=%hu\r\n",
+                            rdent->d_name, dseq, __kMaxUShort);
 #endif
-                    if (dseq==__kMaxUShort) {
-                        maxs = dseq;
-                        break;
-                    }
-                    if (dseq>=maxs) {
-                        maxs=dseq+1;
-                    }
-                    if (maxs==__kMaxUShort) {
-                        break;
+                        if (dseq==__kMaxUShort) {
+                            maxs = dseq;
+                            break;
+                        }
+#ifdef DEBUG
+                        printf("dseq=%hu, maxs=%hu\r\n",dseq,maxs);
+#endif                    
+                        if ( (dseq>=maxs) && (dseq<kMaxSeqNum)) {
+                            maxs=dseq+1;
+                        }
+                        if (maxs==__kMaxUShort) {
+                            break;
+                        }
                     }
                 }
             }
         }
+        closedir(rd);
+    } else {
+        // no SD card
+        
     }
-    closedir(rd);
-
 #ifdef DEBUG
     printf("return maxs=%hu\r\n",maxs);
 #endif
@@ -270,21 +294,22 @@
 
 FILE* SnSDUtils::OpenExistingFile(const char* name, const bool setcurrent,
                                   const bool redoDir) {
-    InitSDCard();
     FILE* f = 0;
-    //if ((name!=NULL) && ((*name)!=0) ) { // simple check if filename not set
-    if (name!=NULL) { // simple check if filename not set
+    if (InitSDCard()) {
+        //if ((name!=NULL) && ((*name)!=0) ) { // simple check if filename not set
+        if (name!=NULL) { // simple check if filename not set
 #ifdef DEBUG
-        printf("opening SD file. name=[%s]\r\n",name);
+            printf("opening SD file. name=[%s]\r\n",name);
 #endif
-        f = OpenSDFile(name, "rb", redoDir);
-        /*
-        if (setcurrent) {
-            fgCurFile = f;
-            strncpy(fgCurFileName, name, kFNBufSize-1);
-            fgCurSeq = GetSeqNumFromFileName(fgCurFileName);
+            f = OpenSDFile(name, "rb", redoDir);
+            /*
+            if (setcurrent) {
+                fgCurFile = f;
+                strncpy(fgCurFileName, name, kFNBufSize-1);
+                fgCurSeq = GetSeqNumFromFileName(fgCurFileName);
+            }
+            */
         }
-        */
     }
     return f;
 }
@@ -333,57 +358,58 @@
 #ifdef DEBUG
     printf("OpenSDFile: Trying to open %s.\r\n",name);
 #endif
-    InitSDCard();
+    FILE* f = 0;
+    if (InitSDCard()) {
 
-    std::string ffn;
-    FILE* f = 0;
-    bool ok = true;
+        std::string ffn;
+        bool ok = true;
+#ifdef DEBUG
+        printf("redoDir=%d\r\n",(int)redoDir);
+#endif
+        if (redoDir) {
+#ifdef DEBUG
+            printf("calling GetFullFilename\r\n");
+#endif
+            ok = GetFullFilename(name, ffn);
+#ifdef DEBUG
+            printf("ffn=%s\r\n",ffn.c_str());
+#endif
+        } else {
+#ifdef DEBUG
+            printf("looking for /\r\n");
+#endif
+            // make sure the directory exists
+            const char* ld = strrchr(name, '/');
 #ifdef DEBUG
-    printf("redoDir=%d\r\n",(int)redoDir);
+            printf("ld=%p, ld-name = %d\r\n",ld,(int)(ld-name));
 #endif
-    if (redoDir) {
+            if ((ld!=0) && (ld>name)) {
+                std::string dn(name, ld-name);
+                DIR* d = OpenOrMakeAllDirs(dn.c_str());
 #ifdef DEBUG
-        printf("calling GetFullFilename\r\n");
+            printf("d=%p\r\n",d);
 #endif
-        ok = GetFullFilename(name, ffn);
+                if (d!=NULL) {
+                    closedir(d);
+                }
+            }
+            // now just copy the (already-) full name
+            ffn = name;
+        }
+        if ( ok && ffn.size()>0 ) {
+#ifdef DEBUG
+            printf("OpenSDFile: %s, mode %s\r\n",ffn.c_str(),mode);
+#endif
+            f = fopen(ffn.c_str(), mode);
+            //setvbuf(f, 0, _IONBF, 0); // no buffering
+#ifdef DEBUG
+            printf("OpenSDFile: f=%p\r\n",(void*)f);
+#endif
+        }
 #ifdef DEBUG
         printf("ffn=%s\r\n",ffn.c_str());
 #endif
-    } else {
-#ifdef DEBUG
-        printf("looking for /\r\n");
-#endif
-        // make sure the directory exists
-        const char* ld = strrchr(name, '/');
-#ifdef DEBUG
-        printf("ld=%p, ld-name = %d\r\n",ld,(int)(ld-name));
-#endif
-        if ((ld!=0) && (ld>name)) {
-            std::string dn(name, ld-name);
-            DIR* d = OpenOrMakeAllDirs(dn.c_str());
-#ifdef DEBUG
-        printf("d=%p\r\n",d);
-#endif
-            if (d!=NULL) {
-                closedir(d);
-            }
-        }
-        // now just copy the (already-) full name
-        ffn = name;
     }
-    if ( ok && ffn.size()>0 ) {
-#ifdef DEBUG
-        printf("OpenSDFile: %s, mode %s\r\n",ffn.c_str(),mode);
-#endif
-        f = fopen(ffn.c_str(), mode);
-        //setvbuf(f, 0, _IONBF, 0); // no buffering
-#ifdef DEBUG
-        printf("OpenSDFile: f=%p\r\n",(void*)f);
-#endif
-    }
-#ifdef DEBUG
-    printf("ffn=%s\r\n",ffn.c_str());
-#endif
     return f;
 }
 
@@ -397,115 +423,123 @@
     printf("getting seq num for run %u, minseq %hu\r\n",
         run, minseq);
 #endif
-    InitSDCard();
-
+    fgCurFile = 0;
     fgCurSeq = GetSeqNum(macadr, run);
-    if (fgCurSeq<minseq) {
-        fgCurSeq=minseq;
-    }
 #ifdef DEBUG
     printf("fgCurSeq=%hu\r\n",fgCurSeq);
-    printf("getting output file name\r\n");
+#endif
+    if (InitSDCard()) {
+        if (fgCurSeq<minseq) {
+            fgCurSeq=minseq;
+        }
+#ifdef DEBUG
+        printf("getting output file name\r\n");
 #endif
-    memset(fgCurFileName, 0, sizeof(char)*kFNBufSize);
-    strncpy(fgCurFileName,GetOutFileName(macadr, run, fgCurSeq),kFNBufSize-1);
-    //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,fgCurSeq);
+        memset(fgCurFileName, 0, sizeof(char)*kFNBufSize);
+        strncpy(fgCurFileName,GetOutFileName(macadr, run, fgCurSeq),kFNBufSize-1);
+        //fprintf(stderr,"cur file = %s (%hu)\n\r",fgCurFileName,fgCurSeq);
 #ifdef DEBUG
-    printf("fgCurFileName=%s\r\n",fgCurFileName);
+        printf("fgCurFileName=%s\r\n",fgCurFileName);
 #endif
-    fgCurFile = 0;
-    if (fgCurFileName!=NULL) {
+        fgCurFile = 0;
+        if (fgCurFileName!=NULL) {
 #ifdef DEBUG
-        printf("opening SD file\r\n");
+            printf("opening SD file\r\n");
 #endif
-        fgCurFile = OpenSDFile(fgCurFileName, "wb", false);
-        if (fgCurFile!=NULL && ferror(fgCurFile)==0) {
+            fgCurFile = OpenSDFile(fgCurFileName, "wb", false);
+            if (fgCurFile!=NULL && ferror(fgCurFile)==0) {
 #ifdef DEBUG
-            printf("Writing file header\r\n");
+                printf("Writing file header\r\n");
 #endif
-            WriteFileHeader(fgCurFile, macadr, run, fgCurSeq);
+                WriteFileHeader(fgCurFile, macadr, run, fgCurSeq);
+                
+                AddToRunSeqList(run, fgCurSeq);
+            }
         }
+#ifdef DEBUG
+        printf("fgCurFile=%p\r\n",(void*)fgCurFile);
+#endif
     }
-#ifdef DEBUG
-    printf("fgCurFile=%p\r\n",(void*)fgCurFile);
-#endif
     return fgCurFile;
 }
 
 void SnSDUtils::PrintFilesInDirs(const char* dirname) {
-    InitSDCard();
+    if (InitSDCard()) {
 
-    DIR* d;
-    struct dirent* dent;
-    Watchdog::kick(); // don't reset
-    if ( (d = opendir( dirname ))!=NULL ) {
-        FATDirHandle* dir = static_cast<FATDirHandle*>(d);
-        while ( (dent = readdir(d))!=NULL ) {
-            printf("dn=%s. datr=%02x. dir=%d\r\n",
-                dent->d_name,
-                dir->filinfo()->fattrib,
-                dir->filinfo()->fattrib & AM_DIR);
-            if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) {
-                std::string dnm(dirname);
-                dnm += "/";
-                dnm += dent->d_name;
-                PrintFilesInDirs(dnm.c_str());
+        DIR* d;
+        struct dirent* dent;
+        Watchdog::kick(); // don't reset
+        if ( (d = opendir( dirname ))!=NULL ) {
+            FATDirHandle* dir = static_cast<FATDirHandle*>(d);
+            while ( (dent = readdir(d))!=NULL ) {
+                printf("dn=%s. datr=%02x. dir=%d\r\n",
+                    dent->d_name,
+                    dir->filinfo()->fattrib,
+                    dir->filinfo()->fattrib & AM_DIR);
+                if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) {
+                    std::string dnm(dirname);
+                    dnm += "/";
+                    dnm += dent->d_name;
+                    PrintFilesInDirs(dnm.c_str());
+                }
             }
+            closedir(d);
         }
-        closedir(d);
     }
-
 }
 
 float SnSDUtils::GetFreeBytes() {
-    InitSDCard();
+    float frs(0);
+    if (InitSDCard()) {
 
-    FATFS* fs;
-    DWORD fre_clust;
-    f_getfree("0:",&fre_clust,&fs);
-    const float frs = static_cast<float>(fs->csize)
-        *static_cast<float>(fs->free_clust)
+        FATFS* fs;
+        DWORD fre_clust;
+        f_getfree("0:",&fre_clust,&fs);
+        frs = static_cast<float>(fs->csize)
+            *static_cast<float>(fs->free_clust)
 #if _MAX_SS != 512
-        *(fs->ssize);
+            *(fs->ssize);
 #else
-        *512;
+            *512;
 #endif
 #ifdef DEBUG
-    printf("free space = %g b (%g GB, %g MB, %g KB)\r\n",
-        frs, frs/1073741824.0, frs/1048576.0, frs/1024.0);
+        printf("free space = %g b (%g GB, %g MB, %g KB)\r\n",
+            frs, frs/1073741824.0, frs/1048576.0, frs/1024.0);
 #endif
+    }
     return frs;
 }
 
 void SnSDUtils::GetDirProps(const char* dirname,
                             uint32_t& nfiles,
                             float& totbytes) {
-    InitSDCard();
-
     nfiles = 0;
     totbytes = 0;
-    struct dirent* dent;
-    FATDirHandle* d = static_cast<FATDirHandle*>( opendir(dirname) );
-    if (d!=0) {
-        while ( (dent = readdir(d))!=NULL ) {
-            Watchdog::kick(); // don't reset
-            if ( (d->filinfo()->fattrib & AM_DIR)!=0 ) {
-                // a subdirectory
-                std::string dnm(dirname);
-                dnm += "/";
-                dnm += dent->d_name;
-                uint32_t sdnf;
-                float    sdtb;
-                GetDirProps(dnm.c_str(), sdnf, sdtb);
-                nfiles += sdnf;
-                totbytes += sdtb;
-             } else {
-                // a file
-                ++nfiles;
-                totbytes += d->filinfo()->fsize;
-             }
+    if (InitSDCard()) {
+
+        struct dirent* dent;
+        FATDirHandle* d = static_cast<FATDirHandle*>( opendir(dirname) );
+        if (d!=0) {
+            while ( (dent = readdir(d))!=NULL ) {
+                Watchdog::kick(); // don't reset
+                if ( (d->filinfo()->fattrib & AM_DIR)!=0 ) {
+                    // a subdirectory
+                    std::string dnm(dirname);
+                    dnm += "/";
+                    dnm += dent->d_name;
+                    uint32_t sdnf;
+                    float    sdtb;
+                    GetDirProps(dnm.c_str(), sdnf, sdtb);
+                    nfiles += sdnf;
+                    totbytes += sdtb;
+                 } else {
+                    // a file
+                    ++nfiles;
+                    totbytes += d->filinfo()->fsize;
+                 }
+            }
+            closedir(d);
         }
-        closedir(d);
     }
 #ifdef DEBUG
     printf("GetDirProps: %s :: nf=%u, tb=%g\r\n",
@@ -517,87 +551,87 @@
                                  const uint32_t time,
                                  const uint32_t num) {
     if (file!=0) {
-        InitSDCard();
-    
-        const bool r1 =
-            SnHeaderFrame::WriteTo(file, SnHeaderFrame::kHeartbeatCode,
-                         SnHeartbeatFrame::SizeOf(SnHeartbeatFrame::kIOVers));
-        const bool r2 = 
-            SnHeartbeatFrame::WriteTo(file, time, num);
-        return (r1 && r2);
-    } else {
-        return false;
+        if (InitSDCard()) {
+        
+            const bool r1 =
+                SnHeaderFrame::WriteTo(file, SnHeaderFrame::kHeartbeatCode,
+                             SnHeartbeatFrame::SizeOf(SnHeartbeatFrame::kIOVers));
+            const bool r2 = 
+                SnHeartbeatFrame::WriteTo(file, time, num);
+            return (r1 && r2);
+        }
     }
+    return false;
 }
 
 bool SnSDUtils::WriteTrigWaitWinTime(FILE* file,
                                      SnClockSetFrame& clkset,
                                      const bool isStart) {
     if (file!=0) {
-        InitSDCard();
-    
-        bool ok = SnHeaderFrame::WriteTo(file,
-                (isStart) ? (SnHeaderFrame::kFileTrgStrtCode)
-                          : (SnHeaderFrame::kFileTrgStopCode),
-                clkset.SizeOf());
-        ok &= (SnCommWin::kOkMsgSent == clkset.WriteTo(file));
-        return ok;
-    } else {
-        return false;
+        if (InitSDCard()) {
+        
+            bool ok = SnHeaderFrame::WriteTo(file,
+                    (isStart) ? (SnHeaderFrame::kFileTrgStrtCode)
+                              : (SnHeaderFrame::kFileTrgStopCode),
+                    clkset.SizeOf());
+            ok &= (SnCommWin::kOkMsgSent == clkset.WriteTo(file));
+            return ok;
+        }
     }
+    return false;
 }
 
 bool SnSDUtils::WriteEventTo(FILE* efile, char* const evtBuf,
                              const SnEventFrame& evt,
                              const SnConfigFrame& conf) {
     // write event to SD card
-        
+    bool ret = false;
     if (efile!=0) {
-        InitSDCard();
-        
-        uint8_t sLoseLSB=0, sLoseMSB=0;
-        uint16_t sWvBase=0;
-        conf.GetPackParsFor(SnConfigFrame::kSDcard, sLoseLSB, sLoseMSB, sWvBase);
-        SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kEventCode, 
-                               evt.SizeOf(SnEventFrame::kIOVers, sLoseLSB, sLoseMSB));
-        const bool ret = evt.WriteTo(efile, evtBuf, sLoseLSB, sLoseMSB, sWvBase);
-        fflush(efile);
-        return ret;
-    } else {
-        return false;
+        if (InitSDCard()) {
+            
+            uint8_t sLoseLSB=0, sLoseMSB=0;
+            uint16_t sWvBase=0;
+            conf.GetPackParsFor(SnConfigFrame::kSDcard, sLoseLSB, sLoseMSB, sWvBase);
+            SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kEventCode, 
+                                   evt.SizeOf(SnEventFrame::kIOVers, sLoseLSB, sLoseMSB));
+            ret = evt.WriteTo(efile, evtBuf, sLoseLSB, sLoseMSB, sWvBase);
+            fflush(efile);
+        }
     }
+    return ret;
 }
 
 bool SnSDUtils::WriteConfig(FILE* efile,
                             const SnConfigFrame& conf) {
     if (efile!=0) {
-        InitSDCard();
+        if (InitSDCard()) {
 
-        SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kConfigCode, 
-                           conf.SizeOf(SnConfigFrame::kIOVers));
-        conf.WriteTo(efile);
-        return true;
-    } else {
-        return false;
+            SnHeaderFrame::WriteTo(efile, SnHeaderFrame::kConfigCode, 
+                               conf.SizeOf(SnConfigFrame::kIOVers));
+            conf.WriteTo(efile);
+            return true;
+        }
     }
+    return false;
 }
 
 void SnSDUtils::DeleteFile(FILE*& f, const char* fname) {
 #ifdef DEBUG
     printf("try to delete %s at %p\r\n",fname,f);
 #endif
-    InitSDCard();
+    if (InitSDCard()) {
 
-    if (f!=0) {
-        fclose(f);
-        f=0;
-    }
-    std::string fn("");
-    if (GetFullFilename(fname, fn)) {
+        if (f!=0) {
+            fclose(f);
+            f=0;
+        }
+        std::string fn("");
+        if (GetFullFilename(fname, fn)) {
 #ifdef DEBUG
-        printf("calling remove [%s]\r\n",fn.c_str());
+            printf("calling remove [%s]\r\n",fn.c_str());
 #endif
-        remove(fn.c_str());
+            remove(fn.c_str());
+        }
     }
 }
 
@@ -614,69 +648,326 @@
 #ifdef DEBUG
     printf("deleting ALL files in %s\r\n",dirname);
 #endif
-    InitSDCard();
+    if (InitSDCard()) {
 
-    DIR* d;
-    struct dirent* dent;
-    if ( (d = opendir( dirname ))!=NULL ) {
-        FATDirHandle* dir = static_cast<FATDirHandle*>(d);
-        while ( (dent = readdir(d))!=NULL ) {
-            Watchdog::kick(); // don't reset
-            if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) {
-                // a subdirectory
-                std::string dnm(dirname);
-                dnm += "/";
-                dnm += dent->d_name;
-                // delete all the files in this new subdir
+        DIR* d;
+        struct dirent* dent;
+        if ( (d = opendir( dirname ))!=NULL ) {
+            FATDirHandle* dir = static_cast<FATDirHandle*>(d);
+            while ( (dent = readdir(d))!=NULL ) {
+                Watchdog::kick(); // don't reset
+                if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) {
+                    // a subdirectory
+                    std::string dnm(dirname);
+                    dnm += "/";
+                    dnm += dent->d_name;
+                    // delete all the files in this new subdir
 #ifdef DEBUG
-                printf("call DeleteAllFiles(%s)\r\n",dnm.c_str());
+                    printf("call DeleteAllFiles(%s)\r\n",dnm.c_str());
 #endif
-                DeleteAllFiles(dnm.c_str());
-            } else if (strncmp(dent->d_name, "SnEvts", 6)==0) {
-                // a data file (delete it)
-                const bool isCurFile = 
-                    (strcmp(dent->d_name, GetCurFileName())==0);
-                if (isCurFile==false) { // don't delete the current file
-                    FILE* f(0); // dummy
-                    DeleteFile(f, dent->d_name);
+                    DeleteAllFiles(dnm.c_str());
+                } else if (strncmp(dent->d_name, "SnEvts", 6)==0) {
+                    // a data file (delete it)
+                    const bool isCurFile = 
+                        (strcmp(dent->d_name, GetCurFileName())==0);
+                    if (isCurFile==false) { // don't delete the current file
+                        FILE* f(0); // dummy
+                        DeleteFile(f, dent->d_name);
+                    }
                 }
-            }
-        } // loop over stuff in this dir
-        closedir(d);
-        DeleteDirIfEmpty(dirname);
+            } // loop over stuff in this dir
+            closedir(d);
+            DeleteDirIfEmpty(dirname);
+        }
     }
 }
 
-void SnSDUtils::DeleteDirIfEmpty(const char* dirname) {
+bool SnSDUtils::DeleteDirIfEmpty(const char* dirname) {
 #ifdef DEBUG
     printf("DeleteDirIfEmpty(%s)\r\n",dirname);
 #endif
-    InitSDCard();
+    bool doDel = false;
+    if (InitSDCard()) {
 
-    DIR* d;
-    struct dirent* dent;
-    if ( (d = opendir(dirname))!=NULL ) {
-        dent = readdir(d);
-        bool doDel = false;
-        if ( dent==NULL ) {
-            // then this directory is empty
-            static const size_t subdsz = strlen(kSDsubDir);
-            // just double check that this directory is
-            // a subdirectory of the data dir
-            if (strlen(dirname)>subdsz) {
-                doDel = true;
+        DIR* d;
+        struct dirent* dent;
+        if ( (d = opendir(dirname))!=NULL ) {
+            dent = readdir(d);
+            if ( dent==NULL ) {
+                // then this directory is empty
+                static const size_t subdsz = strlen(kSDsubDir);
+                // just double check that this directory is
+                // a subdirectory of the data dir
+                if (strlen(dirname)>subdsz) {
+                    doDel = true;
+                }
+            } // else this dir isn't empty
+            closedir(d);
+            if (doDel) {
+#ifdef DEBUG
+                printf("removing directory [%s]\r\n",dirname);
+#endif
+                remove(dirname);
             }
-        } // else this dir isn't empty
-        closedir(d);
-        if (doDel) {
-#ifdef DEBUG
-            printf("removing directory [%s]\r\n",dirname);
-#endif
-            remove(dirname);
         }
     }
+    return doDel;
 }
 
+SnCommWin::ECommWinResult
+SnSDUtils::SendOneFile(const char* dfn,
+                       SnCommWin* comm,
+                       const uint32_t timeout,
+                       char* const buf,
+                       const uint32_t bsize,
+                       const SnConfigFrame& curConf,
+                       SnEventFrame& evt,
+                       SnPowerFrame& pow) {
+
+#ifdef DEBUG
+    printf("SendOneFile (%s)\r\n",dfn);
+#endif
+
+    SnCommWin::ECommWinResult res = SnCommWin::kOkMsgSent;
+    
+    // open the file
+    const bool isCurFile = (strcmp(dfn, GetCurFileName())==0);
+    FILE* f(0);
+    if (isCurFile) {
+        // file must already be written out!
+        f = GetCurFile();
+    } else {
+        f = OpenExistingFile(dfn, false, false);
+    }
+
+#ifdef DEBUG
+    printf("SendOneFile: isCurFile=%d, f=%p, fn=%s\r\n",
+        (int)isCurFile, (void*)f, dfn);
+#endif
+
+    uint8_t hndres = SnHeaderFrame::kHnShFailNonCode;
+    if (f!=0) {
+#ifdef DEBUG
+        printf("SendOneFile: calling SendDataFromFile\r\n");
+#endif
+        res = comm->SendDataFromFile(f, dfn,
+                             curConf, evt, pow, buf, bsize,
+                             0, timeout,
+                             &hndres);
+
+        if (isCurFile) {
+            // move (back) to the end of the file
+            // altho hopefully no writing will happen after this
+            fseek(fgCurFile, 0, SEEK_END);
+        }
+    }                
+#ifdef DEBUG
+    printf("isCurFile=%d, res=%d, deleting=%d, hndres=%02x\r\n",
+        (int)isCurFile, (int)res, (int)(curConf.IsDeletingFiles()),
+        hndres);
+#endif
+    
+    return res;
+}
+
+bool SnSDUtils::ClearRunSeqList() {
+    if (InitSDCard()) {
+        FILE* rslistf = fopen(kRunSeqListFilenm,"w");
+        const bool ok = rslistf!=0;
+        fclose(rslistf);
+#ifdef DEBUG
+        printf("ClearRunSeqList. ok=%s\r\n",(ok?"true":"false"));
+#endif
+        return ok;
+    }
+    return false;
+}
+
+bool SnSDUtils::AddToRunSeqList(const uint32_t run,
+                                const uint16_t seq) {
+    if (InitSDCard()) {
+        FILE* rslistf = fopen(kRunSeqListFilenm,"a");
+        bool ok = false;
+        if (rslistf!=0) {
+            ok  = fprintf(rslistf, "%u %hu\n", run, seq) > 0;
+            ok &= 0==ferror(rslistf);
+#ifdef DEBUG
+            printf("AddToRunSeqList: run=%u, seq=%hu, ok=%s\r\n",
+                run, seq, (ok?"true":"false"));
+#endif
+        }
+        fclose(rslistf);
+        return ok;    
+    }
+    return false;
+}
+
+SnCommWin::ECommWinResult
+SnSDUtils::SendFileWithRunSeq(SnCommWin* comm,
+                              const uint32_t timeout,
+                              char* const buf,
+                              const uint32_t bsize,
+                              const SnConfigFrame& curConf,
+                              SnEventFrame& evt,
+                              SnPowerFrame& pow,
+                              const uint32_t run,
+                              const uint16_t seq) {
+
+#ifdef DEBUG
+    printf("SendFileWithRunSeq\r\n");
+#endif
+
+    // get the file name
+    std::string dfn = 
+        GetOutFileName(SnConfigFrame::GetMacAddress(), run, seq);
+    
+    // send it
+    const SnCommWin::ECommWinResult res = 
+        SendOneFile(dfn.c_str(), comm, timeout, buf, bsize,
+                    curConf, evt, pow);
+    
+    // see if we need to remove this directory now
+    if (curConf.IsDeletingFiles()) {
+        // get run/seq directory name
+        uint32_t rdlen(0);
+        std::string rdnm( GetSubDirFor(run, seq, rdlen, true) );
+#ifdef DEBUG
+        printf("Checking removal of dir [%s]\r\n",rdnm.c_str());
+#endif
+        if ( DeleteDirIfEmpty(rdnm.c_str()) ) {
+            // removed the seq dir. do we need to remove
+            // the run dir too?
+            rdnm = GetSubDirFor(run, seq, rdlen, false);
+#ifdef DEBUG
+            printf("Checking removal of dir [%s]\r\n",rdnm.c_str());
+#endif
+            DeleteDirIfEmpty(rdnm.c_str());
+        }
+    }
+    
+    return res;
+}
+
+SnCommWin::ECommWinResult
+SnSDUtils::SendFilesInRunSeqList(SnCommWin* comm,
+                                 const uint32_t timeout,
+                                 char* const buf,
+                                 const uint32_t bsize,
+                                 const SnConfigFrame& curConf,
+                                 SnEventFrame& evt,
+                                 SnPowerFrame& pow) {
+#ifdef DEBUG
+    printf("SendFilesInRunSeqList\r\n");
+#endif
+
+    SnCommWin::ECommWinResult rs = SnCommWin::kOkMsgSent;
+
+    if (InitSDCard()) {
+
+        // open up the run/seq list file and send each corresponding file
+        FILE* rslistf = fopen(kRunSeqListFilenm,"r");
+#ifdef DEBUG
+        printf("fslistf=%p\r\n",(void*)rslistf);
+#endif
+        if (rslistf!=0) {
+            uint32_t run(0);
+            uint16_t seq(0);
+            while (    (feof(rslistf)==0)
+                    && (ferror(rslistf)==0) ) {
+#ifdef DEBUG
+                printf("feof=%d, ferror=%d\r\n",
+                    (int)(feof(rslistf)), (int)(ferror(rslistf)));
+#endif            
+                const int nfilled = fscanf(rslistf, "%u %hu\n", &run ,&seq);
+    
+#ifdef DEBUG
+                printf("nfilled=%d\r\n", nfilled);
+#endif            
+    
+                if ( 2==nfilled ) {
+    
+#ifdef DEBUG
+                    printf("run=%u, seq=%hu\r\n",run,seq);
+#endif            
+                    
+                    SnCommWin::ECommWinResult res =
+                        SendFileWithRunSeq(comm, timeout, buf, bsize,
+                                           curConf, evt, pow,
+                                           run, seq);
+                        
+                    if ((res<rs) || (res==SnCommWin::kOkStopComm)) {
+                        rs = res;
+                    }
+                    // don't necessarily stop if rs is bad. don't want one bad file to
+                    // prevent sending the others
+                    if (rs<=SnCommWin::kFailTimeout) {
+                        break;
+                    } else if (rs==SnCommWin::kOkStopComm) {
+                        break;
+                    }
+                    
+                }
+                
+            }
+            
+            // do we need to clear the list?
+            if (curConf.IsRunSeqListOneCommWinOnly()==false) {
+                if (rs >= SnCommWin::kOkMsgSent) {
+                    // all sent ok
+                    ClearRunSeqList();
+                }
+            }
+    
+        }
+        fclose(rslistf);
+    }
+    return rs;
+}
+
+SnCommWin::ECommWinResult
+SnSDUtils::SendPartOfRun(SnCommWin* comm,
+                         const uint32_t timeout,
+                         char* const buf,
+                         const uint32_t bsize,
+                         const SnConfigFrame& curConf,
+                         SnEventFrame& evt,
+                         SnPowerFrame& pow,
+                         const uint32_t run,
+                         const uint16_t minseq,
+                         const uint16_t maxseq) {
+    // send files with run number 'run'
+    // and seq number in [minseq,maxseq] (min/max inclusive)
+    
+#ifdef DEBUG
+    printf("SendPartOfRun\r\n");
+#endif
+
+    SnCommWin::ECommWinResult rs = SnCommWin::kOkMsgSent;
+
+    for (uint16_t seq=minseq; seq<=maxseq; ++seq) {
+        SnCommWin::ECommWinResult res =
+            SendFileWithRunSeq(comm,
+                               timeout, buf, bsize,
+                               curConf, evt, pow,
+                               run, seq);
+            
+        if ((res<rs) || (res==SnCommWin::kOkStopComm)) {
+            rs = res;
+        }
+        // don't necessarily stop if rs is bad. don't want one bad file to
+        // prevent sending the others
+        if (rs<=SnCommWin::kFailTimeout) {
+            break;
+        } else if (rs==SnCommWin::kOkStopComm) {
+            break;
+        }
+        
+    }
+    
+    return rs;
+}
+
+
 SnCommWin::ECommWinResult SnSDUtils::SendAllOfRun(SnCommWin* comm,
                                                   const uint32_t timeout,
                                                   char* const buf,
@@ -703,83 +994,52 @@
                                                   SnPowerFrame& pow,
                                                   const char* dirname) {
     // send all files in the specified directory
+
+    SnCommWin::ECommWinResult rs  = SnCommWin::kUndefFail;
     
-    InitSDCard();
-
-    SnCommWin::ECommWinResult rs  = SnCommWin::kOkMsgSent;
+    if (InitSDCard()) {
 
-    DIR* d;
-    struct dirent* dent;
-    if ( (d = opendir( dirname ))!=NULL ) {
-        FATDirHandle* dir = static_cast<FATDirHandle*>(d);
-        while ( (dent = readdir(d))!=NULL ) {
-            Watchdog::kick(); // don't reset
-            SnCommWin::ECommWinResult res = rs;
-            if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) {
-                // a subdirectory
-                std::string dnm(dirname);
-                dnm += "/";
-                dnm += dent->d_name;
-                // send all the files in this new subdir
-                res = SendAllFiles(comm, timeout, buf, bsize, 
-                             curConf, evt, pow,
-                             dnm.c_str());
-            } else if (strncmp(dent->d_name, "SnEvts", 6)==0) {
-                // a data file (send it)
-                const bool isCurFile = 
-                    (strcmp(dent->d_name, GetCurFileName())==0);
-                FILE* f(0);
-                if (isCurFile) {
-                    // file must already be written out!
-                    f = GetCurFile();
-                } else {
-                    std::string ffn(dirname);
-                    ffn += "/";
-                    ffn += dent->d_name;
-                    f = OpenExistingFile(ffn.c_str(), false, false);
+        rs  = SnCommWin::kOkMsgSent;
+    
+        DIR* d;
+        struct dirent* dent;
+        if ( (d = opendir( dirname ))!=NULL ) {
+            FATDirHandle* dir = static_cast<FATDirHandle*>(d);
+            while ( (dent = readdir(d))!=NULL ) {
+                Watchdog::kick(); // don't reset
+                SnCommWin::ECommWinResult res = rs;
+                if ( (dir->filinfo()->fattrib & AM_DIR)!=0 ) {
+                    // a subdirectory
+                    std::string dnm(dirname);
+                    dnm += "/";
+                    dnm += dent->d_name;
+                    // send all the files in this new subdir
+                    res = SendAllFiles(comm, timeout, buf, bsize, 
+                                 curConf, evt, pow,
+                                 dnm.c_str());
+                } else if (strncmp(dent->d_name, "SnEvts", 6)==0) {
+                    // a data file (send it)
+                    res = SendOneFile(dent->d_name, comm, timeout, buf, bsize,
+                                      curConf, evt, pow);
                 }
-#ifdef DEBUG
-                printf("calling senddata: f=%p (cur %p), fn=%s\r\n",
-                    f, GetCurFile(), dent->d_name);
-#endif
-                uint8_t hndres = SnHeaderFrame::kHnShFailNonCode;
-                if (f!=0) {
-                    res = comm->SendDataFromFile(f, dent->d_name,
-                                         curConf, evt, pow, buf, bsize,
-                                         0, timeout,
-                                         &hndres);
-
-                    if (isCurFile) {
-                        // move (back) to the end of the file
-                        // altho hopefully no writing will happen after this
-                        fseek(fgCurFile, 0, SEEK_END);
-                    }
-                }                
-#ifdef DEBUG
-                printf("isCurFile=%d, res=%d, deleting=%d, hndres=%02x\r\n",
-                    (int)isCurFile, (int)res, (int)(curConf.IsDeletingFiles()),
-                    hndres);
-#endif
-                
+                if ((res<rs) || (res==SnCommWin::kOkStopComm)) {
+                    rs = res;
+                }
+                // don't necessarily stop if rs is bad. don't want one bad file to
+                // prevent sending the others
+                if (rs<=SnCommWin::kFailTimeout) {
+                    break;
+                } else if (rs==SnCommWin::kOkStopComm) {
+                    break;
+                }
+            } // loop over stuff in this directory
+            closedir(d);
+            // see if we need to remove this directory now
+            if (curConf.IsDeletingFiles()) {
+                DeleteDirIfEmpty(dirname);
             }
-            if ((res<rs) || (res==SnCommWin::kOkStopComm)) {
-                rs = res;
-            }
-            // don't necessarily stop if rs is bad. don't want one bad file to
-            // prevent sending the others
-            if (rs<=SnCommWin::kFailTimeout) {
-                break;
-            } else if (rs==SnCommWin::kOkStopComm) {
-                break;
-            }
-        } // loop over stuff in this directory
-        closedir(d);
-        // see if we need to remove this directory now
-        if (curConf.IsDeletingFiles()) {
-            DeleteDirIfEmpty(dirname);
         }
     }
-    
     return rs;
 }