Arianna autonomous DAQ firmware

Dependencies:   mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW

Revision:
12:d472f9811262
Parent:
10:3c93db1cfb12
Child:
13:7a1fb885a8e4
--- a/SnCommWin.cpp	Mon Aug 13 20:44:06 2012 +0000
+++ b/SnCommWin.cpp	Sat Aug 18 05:00:32 2012 +0000
@@ -7,30 +7,51 @@
 #include "SnStatusFrame.h"
 #include "SnSDUtils.h"
 
+bool SnCommWin::IsTimedOut(const uint32_t timeout_clock) const {
+    if ( timeout_clock > 0 ) {
+        if (time(0)>timeout_clock) {
+            return true;
+        }
+    }
+    return false;
+}
+
 SnCommWin::ECommWinResult SnCommWin::SendData(SnConfigFrame& conf,
                                               SnEventFrame& evt,
                                               SnPowerFrame& pow,
                                               char* const genBuf,
                                               const uint32_t bsize,
-                                              const uint32_t timeout) {
+                                              const uint32_t timeout,
+                                              const uint32_t handshakeTimeout) {
+#ifdef DEBUG
     printf("SnCommWin::SendData\r\n");
+#endif
     ECommWinResult res = kUndefFail;
-    const uint32_t to = (conf.IsObeyingTimeout()) ? timeout : kSecsPerYear;
     if (conf.IsSendingAllFiles()) {
+#ifdef DEBUG
         printf("sending all files\r\n");
-        res = SnSDUtils::SendAllFiles(this, conf.IsDeletingFiles(), to, 
-                                      genBuf, bsize, conf, evt, pow);
+#endif
+        res = SnSDUtils::SendAllFiles(this, timeout, 
+                                      genBuf, bsize, conf, evt, pow,
+                                      handshakeTimeout);
     } else {
         if (conf.GetCommSendData()==0) {
+#ifdef DEBUG
             printf("no data to send\r\n");
+#endif
             res = kOkNoMsg;
         } else {
             const uint32_t nev = (conf.GetCommSendData()>0) ?
                                   conf.GetCommSendData() // send N events
                                   : 0u; // send all events in last file
+#ifdef DEBUG
+            printf("calling SendData. f=%x, nev=%u\r\n",SnSDUtils::GetCurFile(), nev);
+#endif
             res = SendData(SnSDUtils::GetCurFile(), SnSDUtils::GetCurFileName(),
-                           conf, evt, pow, genBuf, bsize, nev, to);
+                           conf, evt, pow, genBuf, bsize, nev, timeout, handshakeTimeout);
+#ifdef DEBUG
             printf("after send data cur file, res=%d\r\n",(int)res);
+#endif
         }
     }
     return res;
@@ -44,34 +65,57 @@
                                               const uint32_t bsize,
                                               const uint32_t nevts,
                                               const uint32_t timeout_clock,
-                                              const uint32_t firstEvt) {
+                                              const uint32_t handshakeTimeout) {
     // nevts==0 ==> send all events
     
-    printf("SnCommWin::SendData cur file\r\n");
+#ifdef DEBUG
+    printf("SnCommWin::SendData file (%p), fn=%s\r\n",inf,infn);
+#endif
     ECommWinResult res = kUndefFail;
+    bool didDel = false;
     if (inf!=0) {
+#ifdef DEBUG
+        printf("sending file name %s\r\n",infn);
+#endif
         // send the file name
         res = SendFilename(infn, genBuf, timeout_clock);
         if (res>kAllFails) {
             if (genBuf!=0) {
+#ifdef DEBUG
+                printf("calling send file contents\r\n");
+#endif
                 // send the contents
                 res = SendFileContents(inf, curConf, evt, pow, genBuf,
-                                       nevts, timeout_clock, firstEvt);
-                if (res>SnCommWin::kAllFails) {
+                                       nevts, timeout_clock);
+#ifdef DEBUG
+                printf("res=%d (fails=%d)\r\n",(int)res,(int)kAllFails);
+#endif
+                if (res>kAllFails) {
+#ifdef DEBUG
+                    printf("calling wait handshake\r\n");
+#endif
                     // wait for handshake
                     uint8_t hndshk=0;
-                    res = WaitHandshake(timeout_clock, genBuf, bsize, hndshk);
+                    res = WaitHandshake(handshakeTimeout, genBuf, bsize, hndshk);
                     if (    (res==SnCommWin::kOkWithMsg) // got handshake
                          && (nevts==0)                   // sent whole file
                          &&  curConf.IsDeletingFiles()   // want to delete
-                         //&& (strcmp(infn, SnSDUtils::GetCurFileName()!=0) // not current file (TODO?)
+                         && (inf!=SnSDUtils::GetCurFile()) // not current file
                          && (hndshk==SnHeaderFrame::kHnShOkComplCode)) {  // whole file received
                         // delete it
                         SnSDUtilsWhisperer::DeleteFile(inf, infn);
+                        didDel=true;
                     }
                 }
             }
         }
+    } else {
+#ifdef DEBUG
+        printf("inf=0!\r\n");
+#endif
+    }
+    if ( (inf!=SnSDUtils::GetCurFile()) && (didDel==false) ) {
+        SnSDUtils::CloseOutputFile(inf);
     }
     return res;
 }
@@ -80,13 +124,20 @@
                                                    char* const buf,
                                                    const uint32_t bsize,
                                                    uint8_t& hndShkCode) {
-    printf("WaitHandshake, to=%u\r\n",timeout);
+    // ensure we don't wait forever
+    const uint32_t to = (timeout>0) ? timeout : kListenTimeout;
+#ifdef DEBUG
+    printf("WaitHandshake, to=%u\r\n",to);
+#endif
     
-    const int mlen = ReceiveAll(buf, SnHeaderFrame::SizeOf(), timeout);
+    const int mlen = ReceiveAll(buf, SnHeaderFrame::SizeOf(), to);
     if (mlen>0 && static_cast<uint32_t>(mlen) == SnHeaderFrame::SizeOf()) {
         uint32_t msgLen=0;
         const char* b = buf;
         SnHeaderFrame::ReadFrom(b, hndShkCode, msgLen);
+#ifdef DEBUG
+        printf("got handshake code=%02x, len=%u\r\n",hndShkCode,msgLen);
+#endif
         if ((hndShkCode & SnHeaderFrame::kHndShkBits)!=0) {
             return SnCommWin::kOkWithMsg;
         } else {
@@ -103,7 +154,9 @@
                                                const uint32_t bsize) {
     // confBuf assumed to alread be of allocated size
     
+#ifdef DEBUG
     printf("GetConfig, to=%u\r\n",timeOut);
+#endif
     
     SnCommWin::ECommWinResult res = SnCommWin::kUndefFail;
     if (bsize<SnHeaderFrame::kMaxSizeOf || bsize<SnConfigFrame::kMaxSizeOf) {
@@ -115,8 +168,13 @@
             uint8_t mcode=0; uint32_t mlen=0;
             const char* b = confBuf;
             SnHeaderFrame::ReadFrom(b, mcode, mlen);
+#ifdef DEBUG
             printf("mcode=%02x, mlen=%u\r\n", mcode, mlen);
-            if (mcode!=SnHeaderFrame::kConfigCode) {
+#endif
+            if (mcode==SnHeaderFrame::kNoConfigCode) {
+                // no config to get
+                res = SnCommWin::kOkWithMsg;
+            } else if (mcode!=SnHeaderFrame::kConfigCode) {
                 res = SnCommWin::kUnexpectedRec;
             } else {
                 // get config
@@ -124,7 +182,7 @@
                 if (clen>0 && static_cast<uint32_t>(clen)==mlen) {
                     b = confBuf;
                     conf.ReadFrom(b);
-                    res = SnCommWin::kOkWithMsg;
+                    res = SnCommWin::kOkWthMsgNoConf;
                 } else {
                     res = SnCommWin::kUnexpectedRec;
                 }
@@ -145,6 +203,9 @@
                                                 char* const genBuf,
                                                 const uint32_t timeout_clock) {
     // TODO: check if connected?
+#ifdef DEBUG
+    printf("########### Send Status\r\n");
+#endif
     const uint32_t ssize = SnStatusFrame::SizeOf(SnStatusFrame::kIOVers, conf);
     char* b = genBuf;
     SnHeaderFrame::WriteTo(b, SnHeaderFrame::kStatusCode, ssize);
@@ -164,7 +225,9 @@
     msiz = b-genBuf;
     mlen = SendAll(genBuf, msiz, timeout_clock);
     if (mlen==msiz) {
+#ifdef DEBUG
         printf("status+power sent\r\n");
+#endif
         b = genBuf;
         SnHeaderFrame::WriteTo(b, SnHeaderFrame::kEventCode,
             evt.SizeOf(SnEventFrame::kIOVers,
@@ -176,19 +239,185 @@
     return SnCommWin::kFailPartSent;
 }
 
-SnCommWin::ECommWinResult SnCommWin::SendFilename(const char* fn,
+SnCommWin::ECommWinResult SnCommWin::SendFilename(const char* inf,
                                                   char* const genBuf,
                                                   const uint32_t timeout_clock) {
-    printf("afar send filename %s\r\n",fn);
+#ifdef DEBUG
+    printf("SnCommWin::SendFilename %s\r\n",inf);
+#endif
+    // remove the directory
+    const char* fn = strrchr(inf, '/');
+    if (fn==0) {
+        // no directory
+        fn = inf;
+    } else if (fn!=inf) {
+        ++fn; // move past the '/' if it was found
+    }
+#ifdef DEBUG
+    printf("send %s\r\n",fn);
+#endif
     const size_t flen = strlen(fn);
     char* b = genBuf;
     SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFilenameCode, flen);
-    sprintf(b, "%s", fn);
-    const int msiz = SnHeaderFrame::SizeOf()+flen;
+    b = SnBitUtils::WriteTo(b, fn, flen);
+    const int msiz = b-genBuf;
     const int mlen = SendAll(genBuf, msiz, timeout_clock);
+#ifdef DEBUG
+    printf("time = %u, timeout = %u\r\n",time(0), timeout_clock);
+#endif
     return (msiz==mlen) ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent;
 }
 
+int SnCommWin::SendFileBlock(FILE* inf, 
+                             const uint8_t blockHeaderCode,
+                             const uint32_t blockSize,
+                             char* const genBuf,
+                             const uint32_t timeout) {
+    // sends the block from the file. does not check if the file has sufficient bytes
+    // this should be done before calling this function
+    // (where the number of bytes in the file can be cached)
+    char* b = genBuf;
+    SnHeaderFrame::WriteTo(b, blockHeaderCode, blockSize);
+    SnBitUtils::ReadFrom(inf, b, blockSize);
+#ifdef DEBUG
+    printf("Sending block hc %02x, len=%u\r\n",blockHeaderCode,blockSize+SnHeaderFrame::SizeOf());
+#endif
+    return SendAll(genBuf, blockSize+SnHeaderFrame::SizeOf(), timeout);
+}                             
+
+SnCommWin::ECommWinResult SnCommWin::SendFileContents(FILE* inf,
+                                                    const SnConfigFrame& curConf,
+                                                    SnEventFrame& evt,
+                                                    SnPowerFrame& pow,
+                                                    char* const genBuf,
+                                                    uint32_t nevts,
+                                                    const uint32_t timeout_clock) {
+    // firstEvt==0 ==> start at beginning
+    // nevts==0 ==> all events
+    
+#ifdef DEBUG
+    printf("SendFileContents (byte streaming)\r\n");
+#endif
+    
+    // store position in file so we can go back to it afterwards
+    // this is probably not necessary, because if this file is open
+    // in write-only mode, we're screwed..
+    const int fpos = ftell(inf);
+    if (fpos>0) {
+        fseek(inf, 0, SEEK_SET);
+    }
+    // how many bytes?
+    fseek(inf, 0, SEEK_END); // go to end
+    const int fend = ftell(inf);
+    fseek(inf, 0, SEEK_SET); // go to start
+#ifdef DEBUG
+    printf("fend=%d\r\n",fend);
+    printf("fpos=%d\r\n",fpos);
+#endif
+    
+    // variables used when sending data
+    char* b = genBuf;
+    int msiz, mlen;
+    
+    // first is the file header, which has no SnHeaderFrame
+    msiz = SnSDUtils::SizeOfFileHeader(SnSDUtils::kIOvers);
+    bool ok = (ftell(inf)+msiz)<=fend;
+    if (ok) {
+        mlen = SendFileBlock(inf, SnHeaderFrame::kFileHeadrCode, 
+                             msiz, genBuf, timeout_clock);
+        ok &= (msiz+SnHeaderFrame::SizeOf())==mlen;
+        
+#ifdef DEBUG
+        printf("sent file header. ok=%d\r\n",(int)ok);
+#endif
+        
+        // the header info for each block
+        uint8_t hcode;
+        uint32_t hlen;
+        
+        // count number of events / power readings sent
+        uint32_t evtsSent=0, powsSent=0;
+
+        // now just loop through file and send each block
+        while (    ok
+                && (feof(inf)==0)
+                && (ferror(inf)==0)
+                && ((ftell(inf)+SnHeaderFrame::SizeOf())<=fend) ) {
+            // read the header for the block
+            SnSDUtils::ReadBlockHeader(inf, hcode, hlen);
+#ifdef DEBUG
+            printf("new block: hc=%02x, hl=%u, ftell=%d, fend=%d\r\n",
+                hcode, hlen, ftell(inf), fend);
+#endif
+            ok &= (ftell(inf)+hlen)<=fend;
+            if (ok) {
+                // send the block
+                // TODO: repack events?
+                msiz = hlen + SnHeaderFrame::SizeOf();
+                mlen = SendFileBlock(inf, hcode, hlen, genBuf, timeout_clock);
+                ok &= msiz==mlen;
+                if (ok) {
+                    if (hcode==SnHeaderFrame::kEventCode) {
+                        ++evtsSent;
+                        if (nevts>0) {
+                            if (evtsSent>=nevts) {
+#ifdef DEBUG
+                                printf("send %u events. stop\r\n",evtsSent);
+#endif
+                                break;
+                            }
+                        }
+                    } else if (hcode==SnHeaderFrame::kPowerCode) {
+                        ++powsSent;
+                    }
+                } else {
+#ifdef DEBUG
+                    printf("not ok when sending hcode=%02x\r\n",hcode);
+#endif
+                }
+            }
+        }
+        
+#ifdef DEBUG
+        printf("loop done. ok=%d\r\n",(int)ok);
+#endif
+        
+        // send number of events sent
+#ifdef DEBUG
+        printf("sending evtsSent (%u)\r\n",evtsSent);
+#endif
+        b = genBuf;
+        SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNevtsCode, sizeof(uint32_t));
+        b = SnBitUtils::WriteTo(b, evtsSent);
+        msiz = b - genBuf;
+        mlen = SendAll(genBuf, msiz, timeout_clock);
+        ok &= msiz==mlen;
+        
+        // send number of power readings sent
+#ifdef DEBUG
+        printf("sending powsSent (%u)\r\n",powsSent);
+#endif
+        b = genBuf;
+        SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNpwrsCode, sizeof(uint32_t));
+        b = SnBitUtils::WriteTo(b, powsSent);
+        msiz = b - genBuf;
+        mlen = SendAll(genBuf, msiz, timeout_clock);
+        ok &= msiz==mlen;
+        
+    }
+
+
+    // put file position back
+    fseek(inf, fpos, SEEK_SET);
+    
+#ifdef DEBUG
+    printf("end contents: ok=%d\r\n",(int)ok);
+#endif
+    
+    return ok ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent;
+}
+
+/*
 SnCommWin::ECommWinResult SnCommWin::SendFileContents(FILE* inf,
                                                     const SnConfigFrame& curConf,
                                                     SnEventFrame& evt,
@@ -197,7 +426,7 @@
                                                     uint32_t nevts,
                                                     const uint32_t timeout_clock,
                                                     const uint32_t firstEvt) {
-    printf("comm win send conf and events\r\n");
+    printf("comm win send file contents\r\n");
     // firstEvt==0 ==> start at beginning
     // nevts==0 ==> all events
     
@@ -205,162 +434,232 @@
     if (fpos>0) {
         fseek(inf, 0, SEEK_SET);
     }
-    
+    // how many bytes?
+    fseek(inf, 0, SEEK_END); // go to end
+    const int fend = ftell(inf);
+    fseek(inf, 0, SEEK_SET); // go to start
+    printf("fend=%d\r\n",fend);
     printf("fpos=%d\r\n",fpos);
-    
     // get file header
     uint64_t macadr;
     uint32_t run;
     uint16_t seq;
-    SnSDUtils::ReadFileHeader(inf, macadr, run, seq, &pow);
+    bool ok = (ftell(inf)+SnSDUtils::SizeOfFileHeader(SnSDUtils::kIOvers))<=fend;
+    if (ok) {
+        SnSDUtils::ReadFileHeader(inf, macadr, run, seq, &pow);
+        printf("read file header: run %u, seq %hu\r\n",run,seq);
+    }
+    
+    printf(">>> file hdr read ftell(inf)=%d\r\n",ftell(inf));
     
     // check block
     uint8_t hcode;
     uint32_t hlen;
-    SnSDUtils::ReadBlockHeader(inf, hcode, hlen);
-    if (hcode==SnHeaderFrame::kPowerCode) {
-        pow.ReadFrom(inf);
+    ok &= (ftell(inf)+SnHeaderFrame::SizeOf())<=fend;
+    if (ok) {
+        SnSDUtils::ReadBlockHeader(inf, hcode, hlen);
+        printf("read block hd %02x, len %u\r\n",hcode,hlen);
+        if (hcode==SnHeaderFrame::kPowerCode) {
+            ok &= (ftell(inf)+SnPowerFrame::SizeOf(SnPowerFrame::kIOvers))<=fend;
+            if (ok) {
+                pow.ReadFrom(inf);
+                printf("read power: v1=%g, v2=%g\r\n",pow.GetAveV1(), pow.GetAveV2());
+                // now read the next header
+                ok &= (ftell(inf)+SnHeaderFrame::SizeOf())<=fend;
+                if (ok) {
+                    SnSDUtils::ReadBlockHeader(inf, hcode, hlen);
+                    printf("read new header: hc %02x, hlen=%u\r\n",hcode,hlen);
+                }
+            }
+        }
     }
     
+    printf(">>> power tried ftell(inf)=%d\r\n",ftell(inf));
+    
+    printf("hcode=%02x\r\n",hcode);
+    printf("ok=%d\r\n",(int)ok);
+    printf("feof=%d\r\n",feof(inf));
+    printf("ferror=%d\r\n",ferror(inf));
+    printf("%d+%u <= %d ? %d\r\n",ftell(inf),hlen,fend,
+        (int)((ftell(inf)+hlen)<=fend));
+    
     // TODO: check memory for temporary config/event frames?
     // get config
     while ((hcode!=SnHeaderFrame::kConfigCode)
+            && ok
             && (feof(inf)==0)
-            && (ferror(inf)==0) ) {
+            && (ferror(inf)==0)
+            && ((ftell(inf)+hlen) <= fend) ) {
+        printf("skip: ftell=%d, hlen=%u\r\n",ftell(inf),hlen);
         fseek(inf, hlen, SEEK_CUR); // skip this block
-        SnSDUtils::ReadBlockHeader(inf, hcode, hlen);
+        ok = (ftell(inf)+SnHeaderFrame::SizeOf())<=fend;
+        if (ok) {
+            SnSDUtils::ReadBlockHeader(inf, hcode, hlen);
+            printf("hcs >>> ftell(inf)=%d, hcode=%02x, hlen=%u\r\n",ftell(inf),hcode,hlen);
+            printf("feof=%d, ferror=%d\r\n",feof(inf),ferror(inf));
+        }
     }
-    SnConfigFrame conf;
-    conf.ReadFrom(inf);
-    
-    // get event size
-    uint8_t sLoseLSB=0, sLoseMSB=0;
-    uint16_t sWvBase=0;
-    curConf.GetPackParsFor(GetCommType(), sLoseLSB, sLoseMSB, sWvBase);
-    
-    // size of event in file
-    const uint32_t esize = SnEventFrame::SizeOf(SnEventFrame::kIOVers,
-                                                conf.GetWvLoseLSB(),
-                                                conf.GetWvLoseMSB());
-    
-    printf("esize=%u\r\n",esize);
     
-    // how many more bytes?
-    const int fcur = ftell(inf);
-    fseek(inf, 0, SEEK_END); // go to end
-    const int fend = ftell(inf);
-    fseek(inf, fcur, SEEK_SET); // go back
+    printf("checking ftell\r\n");
+    bool gotConf = false;
+    ok = (ftell(inf)+hlen) <= fend;
+    printf("making temp config\r\n");
+    SnConfigFrame conf; // TODO: SOMETIMES STALLS HERE!
+    printf("trying to read\r\n");
+    if (ok && (hcode==SnHeaderFrame::kConfigCode)) {
+        printf("reading config from ftell=%d, hcode=%02x, hlen=%u, ok=%d\r\n",
+            ftell(inf), hcode, hlen, (int)ok);
+        conf.ReadFrom(inf);
+        gotConf = (ftell(inf) <= fend) && (feof(inf)==0) && (ferror(inf)==0);
+    }
+    printf(">>> conf. ftell(inf)=%d, gotconf=%d\r\n",ftell(inf),(int)gotConf);
     
-    bool ok = false;
     char* b = genBuf;
-    // send the file header
-    SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileHeadrCode,
-                           SnSDUtils::SizeOfFileHeader(SnSDUtils::kIOvers));
-    SnSDUtils::WriteFileHeader(b, macadr, run, seq);
-    int msiz = b-genBuf;
-    int mlen = SendAll(genBuf, msiz, timeout_clock);
-    if (mlen==msiz) {
-        // send power header
+    int msiz, mlen;
+    if (ok && gotConf) {
+        // get event size
+        uint8_t sLoseLSB=0, sLoseMSB=0;
+        uint16_t sWvBase=0;
+        curConf.GetPackParsFor(GetCommType(), sLoseLSB, sLoseMSB, sWvBase);
+        
+        // size of event in file
+        const uint32_t esize = SnEventFrame::SizeOf(SnEventFrame::kIOVers,
+                                                    conf.GetWvLoseLSB(),
+                                                    conf.GetWvLoseMSB());
+        
+        printf("esize=%u\r\n",esize);
+            
+        // number of events / power readings we will send
+        uint32_t evtsSent=0, powsSent=0;
         b = genBuf;
-        SnHeaderFrame::WriteTo(b, SnHeaderFrame::kPowerCode, 
-                               pow.SizeOf(SnPowerFrame::kIOvers));
-        pow.WriteTo(b);
+        // send the file header
+        SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileHeadrCode,
+                               SnSDUtils::SizeOfFileHeader(SnSDUtils::kIOvers));
+        SnSDUtils::WriteFileHeader(b, macadr, run, seq);
         msiz = b-genBuf;
         mlen = SendAll(genBuf, msiz, timeout_clock);
         if (mlen==msiz) {
-            // send the config
+            // send power header
             b = genBuf;
-            SnHeaderFrame::WriteTo(b, SnHeaderFrame::kConfigCode, 
-                                   conf.SizeOf(SnConfigFrame::kIOVers));
-            conf.WriteTo(b);
+            SnHeaderFrame::WriteTo(b, SnHeaderFrame::kPowerCode, 
+                                   pow.SizeOf(SnPowerFrame::kIOvers));
+            pow.WriteTo(b);
             msiz = b-genBuf;
             mlen = SendAll(genBuf, msiz, timeout_clock);
+            ++powsSent;
             if (mlen==msiz) {
-                ok = true;
+                // send the config
+                b = genBuf;
+                SnHeaderFrame::WriteTo(b, SnHeaderFrame::kConfigCode, 
+                                       conf.SizeOf(SnConfigFrame::kIOVers));
+                conf.WriteTo(b);
+                msiz = b-genBuf;
+                mlen = SendAll(genBuf, msiz, timeout_clock);
+                if (mlen==msiz) {
+                    ok = true;
+                }
             }
         }
-    }
-        
-    printf("ok=%d, nevts=%u\r\n",(int)ok,nevts);
-    
-    if (ok) {
-        // size of event sent over afar
-        const uint32_t ssize = SnEventFrame::SizeOf(SnEventFrame::kIOVers,
-                                                    sLoseLSB, sLoseMSB);
+            
+        printf("ok=%d, nevts=%u\r\n",(int)ok,nevts);
         
-        // loop over blocks. send event & power frames
-        // until EOF or nevets have been sent
-        uint32_t evtsSent=0, powsSent=0;
-        uint8_t hc; uint32_t hl;
-        while (ok && (feof(inf)==0) 
-                  && (ferror(inf)==0) ) {
-            SnSDUtils::ReadBlockHeader(inf, hc, hl);
-            if (hc==SnHeaderFrame::kEventCode) {
-                if ((ftell(inf)+ssize)<=fend) {
-                    evt.ReadFrom(inf, genBuf,
-                        conf.GetWvLoseLSB(), conf.GetWvLoseMSB(),
-                        conf.GetWvBaseline());
-                    if (evt.GetEvtNum()>=firstEvt) {
-                        ++evtsSent;
-                        printf("sending evt %u\r\n",evtsSent);
-                        // must be after evt.Read, since that uses the buffer
-                        b = genBuf;
-                        SnHeaderFrame::WriteTo(b, SnHeaderFrame::kEventCode, ssize);
-                        evt.WriteTo(b, sLoseLSB, sLoseMSB, sWvBase); // will repack if necessary
-                        msiz = b-genBuf; //SnHeaderFrame::SizeOf()+ssize;
-                        mlen = SendAll(genBuf, msiz, timeout_clock);
-                        ok &= mlen==msiz;
+        if (ok) {
+            // size of event sent over afar
+            const uint32_t ssize = SnEventFrame::SizeOf(SnEventFrame::kIOVers,
+                                                        sLoseLSB, sLoseMSB);
+            
+            // loop over blocks. send event & power frames
+            // until EOF or nevets have been sent
+            uint8_t hc; uint32_t hl;
+            while (ok && (feof(inf)==0) 
+                      && (ferror(inf)==0)
+                      && (ftell(inf)<fend) ) { // feof doesn't seem to work
+                printf(">>> ftell(inf)=%d\r\n",ftell(inf));
+                if ((ftell(inf)+SnHeaderFrame::SizeOf())<=fend) {
+                    SnSDUtils::ReadBlockHeader(inf, hc, hl);
+                    if (hc==SnHeaderFrame::kEventCode) {
+                        if ((ftell(inf)+ssize)<=fend) {
+                            evt.ReadFrom(inf, genBuf,
+                                conf.GetWvLoseLSB(), conf.GetWvLoseMSB(),
+                                conf.GetWvBaseline());
+                            if (evt.GetEvtNum()>=firstEvt) {
+                                ++evtsSent;
+                                printf("sending evt %u\r\n",evtsSent);
+                                // must be after evt.Read, since that uses the buffer
+                                b = genBuf;
+                                SnHeaderFrame::WriteTo(b, SnHeaderFrame::kEventCode, ssize);
+                                evt.WriteTo(b, sLoseLSB, sLoseMSB, sWvBase); // will repack if necessary
+                                msiz = b-genBuf; //SnHeaderFrame::SizeOf()+ssize;
+                                mlen = SendAll(genBuf, msiz, timeout_clock);
+                                ok &= mlen==msiz;
+                            }
+                        } else {
+                            printf("event header, but not enough bytes in file\r\n");
+                            ok = false;
+                        }
+                    } else if (hc==SnHeaderFrame::kPowerCode) {
+                        if ((ftell(inf)+SnPowerFrame::SizeOf(SnPowerFrame::kIOvers))<=fend) {
+                            ++powsSent;
+                            pow.ReadFrom(inf);
+                            printf("sending power frame %u, v1=%g, v2=%g, t=%u\r\n",
+                                powsSent, pow.GetAveV1(), pow.GetAveV2(), pow.GetTime());
+                            b = genBuf;
+                            SnHeaderFrame::WriteTo(b, SnHeaderFrame::kPowerCode, 
+                                SnPowerFrame::SizeOf(SnPowerFrame::kIOvers));
+                            pow.WriteTo(b);
+                            msiz = b-genBuf;
+                            mlen = SendAll(genBuf, msiz, timeout_clock);
+                            ok &= mlen==msiz;
+                        } else {
+                            printf("power header, but not enough bytes in file\r\n");
+                            ok = false;
+                        }
+                    } else {
+                        printf("unhandled block. hc=%hhu, hl=%u\r\n",
+                            hc, hl);
+                        if ((ftell(inf)+hl)<=fend) {
+                            fseek(inf, hl, SEEK_CUR); // skip this block
+                        } else {
+                            printf("not enough bytes in file to skip block\r\n");
+                            ok = false;
+                        }
                     }
                 } else {
-                    printf("event header, but not enough bytes in file\r\n");
-                    ok = false;
-                }
-            } else if (hc==SnHeaderFrame::kPowerCode) {
-                if ((ftell(inf)+SnPowerFrame::SizeOf(SnPowerFrame::kIOvers))<=fend) {
-                    ++powsSent;
-                    pow.ReadFrom(inf);
-                    printf("sending power frame %u, v1=%g, v2=%g, t=%u\r\n",
-                        powsSent, pow.GetAveV1(), pow.GetAveV2(), pow.GetTime());
-                    b = genBuf;
-                    SnHeaderFrame::WriteTo(b, SnHeaderFrame::kPowerCode, 
-                        SnPowerFrame::SizeOf(SnPowerFrame::kIOvers));
-                    pow.WriteTo(b);
-                    msiz = b-genBuf;
-                    mlen = SendAll(genBuf, msiz, timeout_clock);
-                    ok &= mlen==msiz;
-                } else {
-                    printf("power header, but not enough bytes in file\r\n");
-                    ok = false;
-                }
-            } else {
-                printf("unhandled block. hc=%hhu, hl=%u\r\n",
-                    hc, hl);
-                if ((ftell(inf)+hl)<=fend) {
-                    fseek(inf, hl, SEEK_CUR); // skip this block
-                } else {
-                    printf("not enough bytes in file to skip block\r\n");
+                    printf("not enough bytes in file to read header\r\n");
+                    printf("feof=%d\r\n",feof(inf));
+                    printf("ftell(inf)=%d, hdr size=%u, fend=%u\r\n",
+                        (ftell(inf)), SnHeaderFrame::SizeOf(), fend);
                     ok = false;
                 }
             }
+            // send number of events sent
+            b = genBuf;
+            SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNevtsCode, sizeof(uint32_t));
+            b = SnBitUtils::WriteTo(b, evtsSent);
+            msiz = b - genBuf;
+            mlen = SendAll(genBuf, msiz, timeout_clock);
+            ok &= msiz==mlen;
+            // send number of power readings sent
+            b = genBuf;
+            SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNpwrsCode, sizeof(uint32_t));
+            b = SnBitUtils::WriteTo(b, powsSent);
+            msiz = b - genBuf;
+            mlen = SendAll(genBuf, msiz, timeout_clock);
+            ok &= msiz==mlen;
         }
-        // send number of events sent
+    } else {
+        printf("failed to get config from file\r\n");
+        // send corrupted file handshake
         b = genBuf;
-        SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNevtsCode, sizeof(uint32_t));
-        b = SnBitUtils::WriteTo(b, evtsSent);
-        msiz = b - genBuf;
-        mlen = SendAll(genBuf, msiz, timeout_clock);
-        ok &= msiz==mlen;
-        // send number of power readings sent
-        b = genBuf;
-        SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileNpwrsCode, sizeof(uint32_t));
-        b = SnBitUtils::WriteTo(b, powsSent);
-        msiz = b -genBuf;
+        SnHeaderFrame::WriteTo(b, SnHeaderFrame::kFileReadFailCode, 0u);
+        msiz = b-genBuf;
         mlen = SendAll(genBuf, msiz, timeout_clock);
         ok &= msiz==mlen;
     }
-        
+    
     // put file position back
     fseek(inf, fpos, SEEK_SET);
     
     return ok ? SnCommWin::kOkMsgSent : SnCommWin::kFailPartSent;
 }
+*/