Arianna autonomous DAQ firmware
Dependencies: mbed SDFileSystemFilinfo AriSnProtocol NetServicesMin AriSnComm MODSERIAL PowerControlClkPatch DS1820OW
SnCommWin.cpp
- Committer:
- uci1
- Date:
- 2012-08-18
- Revision:
- 12:d472f9811262
- Parent:
- 10:3c93db1cfb12
- Child:
- 13:7a1fb885a8e4
File content as of revision 12:d472f9811262:
#include "SnCommWin.h" #include "SnHeaderFrame.h" #include "SnConfigFrame.h" #include "SnEventFrame.h" #include "SnPowerFrame.h" #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 handshakeTimeout) { #ifdef DEBUG printf("SnCommWin::SendData\r\n"); #endif ECommWinResult res = kUndefFail; if (conf.IsSendingAllFiles()) { #ifdef DEBUG printf("sending all files\r\n"); #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, timeout, handshakeTimeout); #ifdef DEBUG printf("after send data cur file, res=%d\r\n",(int)res); #endif } } return res; } SnCommWin::ECommWinResult SnCommWin::SendData(FILE* inf, const char* infn, const SnConfigFrame& curConf, SnEventFrame& evt, SnPowerFrame& pow, char* const genBuf, const uint32_t bsize, const uint32_t nevts, const uint32_t timeout_clock, const uint32_t handshakeTimeout) { // nevts==0 ==> send all events #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); #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(handshakeTimeout, genBuf, bsize, hndshk); if ( (res==SnCommWin::kOkWithMsg) // got handshake && (nevts==0) // sent whole file && curConf.IsDeletingFiles() // want to delete && (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; } SnCommWin::ECommWinResult SnCommWin::WaitHandshake(const uint32_t timeout, char* const buf, const uint32_t bsize, uint8_t& hndShkCode) { // 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(), 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 { // TODO: somehow handle unexpected message? return SnCommWin::kUnexpectedRec; } } return SnCommWin::kOkNoMsg; } SnCommWin::ECommWinResult SnCommWin::GetConfig(SnConfigFrame& conf, const uint32_t timeOut, char* const confBuf, 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) { res = SnCommWin::kUndefFail; } else { // get header const int hlen = ReceiveAll(confBuf, SnHeaderFrame::SizeOf(), timeOut); if (hlen>0 && static_cast<uint32_t>(hlen)==SnHeaderFrame::SizeOf()) { 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); #endif if (mcode==SnHeaderFrame::kNoConfigCode) { // no config to get res = SnCommWin::kOkWithMsg; } else if (mcode!=SnHeaderFrame::kConfigCode) { res = SnCommWin::kUnexpectedRec; } else { // get config const int clen = ReceiveAll(confBuf, mlen, timeOut); if (clen>0 && static_cast<uint32_t>(clen)==mlen) { b = confBuf; conf.ReadFrom(b); res = SnCommWin::kOkWthMsgNoConf; } else { res = SnCommWin::kUnexpectedRec; } } } else { res = SnCommWin::kUnexpectedRec; } } return res; } SnCommWin::ECommWinResult SnCommWin::SendStatus(const SnConfigFrame& conf, const SnEventFrame& evt, const SnPowerFrame& pow, const uint16_t seq, const float thmrate, const float evtrate, 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); SnStatusFrame::WriteTo(b, GetCommType(), conf, evt, genBuf, seq, thmrate, evtrate); SnHeaderFrame::WriteTo(b, SnHeaderFrame::kPowerCode, pow.SizeOf(SnPowerFrame::kIOvers)); pow.WriteTo(b); int msiz = b-genBuf; int mlen = SendAll(genBuf, msiz, timeout_clock); #ifdef DEBUG printf("status frame:\r\n"); for (uint32_t i=0; i<msize; i++) { printf("%02X ",genBuf[i]); } printf("\r\n"); #endif 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, conf.GetWvLoseLSB(), conf.GetWvLoseMSB())); evt.WriteTo(b, conf.GetWvLoseLSB(), conf.GetWvLoseMSB(), conf.GetWvBaseline()); return SnCommWin::kOkMsgSent; } return SnCommWin::kFailPartSent; } SnCommWin::ECommWinResult SnCommWin::SendFilename(const char* inf, char* const genBuf, const uint32_t timeout_clock) { #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); 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, SnPowerFrame& pow, char* const genBuf, uint32_t nevts, const uint32_t timeout_clock, const uint32_t firstEvt) { printf("comm win send file contents\r\n"); // firstEvt==0 ==> start at beginning // nevts==0 ==> all events 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 printf("fend=%d\r\n",fend); printf("fpos=%d\r\n",fpos); // get file header uint64_t macadr; uint32_t run; uint16_t seq; 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; 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) && ((ftell(inf)+hlen) <= fend) ) { printf("skip: ftell=%d, hlen=%u\r\n",ftell(inf),hlen); fseek(inf, hlen, SEEK_CUR); // skip this block 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)); } } 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); char* b = genBuf; 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; // 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 power header b = genBuf; 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) { // 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); // 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("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; } } else { printf("failed to get config from file\r\n"); // send corrupted file handshake 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; } */