Arianna station communication peripherals.
Dependents: AutonomousDAQ AutonomousDAQ
SnCommSBD.h@10:29301aaa8c33, 2018-08-08 (annotated)
- Committer:
- uci1
- Date:
- Wed Aug 08 21:00:41 2018 +0000
- Revision:
- 10:29301aaa8c33
- Parent:
- 7:ba4bc9266f9c
Fixed EOL termination for SBD comms, replacing \r\n with \r (or something like that)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
uci1 | 0:26c9189e5924 | 1 | #ifndef SN_SnCommSBD |
uci1 | 0:26c9189e5924 | 2 | #define SN_SnCommSBD |
uci1 | 0:26c9189e5924 | 3 | |
uci1 | 0:26c9189e5924 | 4 | #include "SnCommPeripheral.h" |
uci1 | 0:26c9189e5924 | 5 | |
uci1 | 0:26c9189e5924 | 6 | #ifdef ENABLE_SBD |
uci1 | 0:26c9189e5924 | 7 | |
uci1 | 0:26c9189e5924 | 8 | #include "SnHeaderFrame.h" |
uci1 | 0:26c9189e5924 | 9 | #include "string" |
uci1 | 0:26c9189e5924 | 10 | |
uci1 | 0:26c9189e5924 | 11 | #define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) |
uci1 | 0:26c9189e5924 | 12 | |
uci1 | 0:26c9189e5924 | 13 | class SnCommSBD : public SnCommPeripheral { |
uci1 | 0:26c9189e5924 | 14 | public: |
uci1 | 0:26c9189e5924 | 15 | static const uint16_t kMaxSend = 340-SnHeaderFrame::kMaxSizeOf; // max bytes sendable by SBD |
uci1 | 0:26c9189e5924 | 16 | static const uint16_t kMaxRecv = 270-SnHeaderFrame::kMaxSizeOf; // max bytes readable by SBD |
uci1 | 3:a7f72492f19e | 17 | static const uint16_t kWaitOnGSS = 30; // seconds |
uci1 | 3:a7f72492f19e | 18 | static const uint16_t kRxBufSz = 5*kMaxRecv; // size of read buffer in bytes |
uci1 | 3:a7f72492f19e | 19 | static const uint16_t kTxBufSz = kMaxSend; // size of send buffer in bytes |
uci1 | 0:26c9189e5924 | 20 | |
uci1 | 0:26c9189e5924 | 21 | //typedef int32_t (SnCommSBD::*SBDSendRecv)(char* const, const uint32_t, const uint32_t); |
uci1 | 0:26c9189e5924 | 22 | typedef bool (SnCommSBD::*SerialReadWriteable)(); |
uci1 | 0:26c9189e5924 | 23 | |
uci1 | 0:26c9189e5924 | 24 | private: |
uci1 | 5:2ee6cbb948c0 | 25 | COMM_SERIALTYPE* fSBD; // serial connection to the SBD modem. maybe a MODSERIAL (which inherits from Serial) |
uci1 | 3:a7f72492f19e | 26 | char fRxBuf[kRxBufSz]; // store the incoming SBD msg in case it's not read all at once |
uci1 | 3:a7f72492f19e | 27 | char fTxBuf[kTxBufSz]; // store the incoming SBD msg in case it's not read all at once |
uci1 | 3:a7f72492f19e | 28 | uint16_t fTxPos; // current position in tx buffer |
uci1 | 3:a7f72492f19e | 29 | uint16_t fRxPos; // position in rx buffer |
uci1 | 3:a7f72492f19e | 30 | uint16_t fRxSiz; // size of message stored in rx buffer |
uci1 | 0:26c9189e5924 | 31 | uint16_t fRMsgNum; // recv SBD message number |
uci1 | 0:26c9189e5924 | 32 | uint16_t fRMsgTot; // recv total SBD messages |
uci1 | 0:26c9189e5924 | 33 | uint16_t fSMsgNum; // send SBD message number |
uci1 | 0:26c9189e5924 | 34 | uint16_t fSMsgTot; // send total SBD messages. separate from the read num/tot to allow (a) read 1/2, (b) send msg, (c) read 2/2 |
uci1 | 7:ba4bc9266f9c | 35 | // TODO: with outgoing buffering, the total number of messages to be sent cannot be known ahead of time! |
uci1 | 0:26c9189e5924 | 36 | |
uci1 | 0:26c9189e5924 | 37 | template<class DATA, class SENDRECV> |
uci1 | 0:26c9189e5924 | 38 | int DoIO(DATA data, |
uci1 | 0:26c9189e5924 | 39 | const uint32_t length, |
uci1 | 0:26c9189e5924 | 40 | const uint32_t timeout_clock, |
uci1 | 0:26c9189e5924 | 41 | SENDRECV fcn, |
uci1 | 0:26c9189e5924 | 42 | SerialReadWriteable able=0) { |
uci1 | 0:26c9189e5924 | 43 | // TODO: if B64, must return number of bytes of raw (non encoded) message |
uci1 | 0:26c9189e5924 | 44 | int res=0; |
uci1 | 0:26c9189e5924 | 45 | uint32_t b=0; |
uci1 | 0:26c9189e5924 | 46 | while ( (length>b) ) { |
uci1 | 0:26c9189e5924 | 47 | if (IsTimedOut(timeout_clock)) { |
uci1 | 0:26c9189e5924 | 48 | break; |
uci1 | 0:26c9189e5924 | 49 | } |
uci1 | 0:26c9189e5924 | 50 | if ( (able==0) || |
uci1 | 0:26c9189e5924 | 51 | ((able!=0) && (CALL_MEMBER_FN(*this, able)())) ) { |
uci1 | 0:26c9189e5924 | 52 | res = CALL_MEMBER_FN(*this, fcn)(data+b, length-b, timeout_clock); |
uci1 | 0:26c9189e5924 | 53 | if (res<0) { |
uci1 | 0:26c9189e5924 | 54 | return b; |
uci1 | 0:26c9189e5924 | 55 | } else { |
uci1 | 0:26c9189e5924 | 56 | b += res; |
uci1 | 0:26c9189e5924 | 57 | } |
uci1 | 0:26c9189e5924 | 58 | } else if (able!=0) { |
uci1 | 4:8328c2972290 | 59 | #ifdef USE_RTOS |
uci1 | 4:8328c2972290 | 60 | Thread::wait(10); |
uci1 | 4:8328c2972290 | 61 | #else |
uci1 | 0:26c9189e5924 | 62 | wait_ms(10); // wait for readable/writeable |
uci1 | 4:8328c2972290 | 63 | #endif |
uci1 | 0:26c9189e5924 | 64 | } |
uci1 | 0:26c9189e5924 | 65 | } |
uci1 | 0:26c9189e5924 | 66 | return b; // timeout |
uci1 | 0:26c9189e5924 | 67 | } |
uci1 | 3:a7f72492f19e | 68 | /* |
uci1 | 0:26c9189e5924 | 69 | template<class DATA, class SENDRECV> |
uci1 | 0:26c9189e5924 | 70 | int32_t DoIOInChunks(DATA data, const uint32_t length, |
uci1 | 0:26c9189e5924 | 71 | const uint32_t timeout_clock, |
uci1 | 0:26c9189e5924 | 72 | const uint16_t maxBufLen, |
uci1 | 0:26c9189e5924 | 73 | SENDRECV fcn) { |
uci1 | 0:26c9189e5924 | 74 | // get/ship the data in chunks (since SBD limits incoming/outgoing messages) |
uci1 | 0:26c9189e5924 | 75 | int32_t b=0, cl=0; |
uci1 | 0:26c9189e5924 | 76 | while ( length>b ) { |
uci1 | 0:26c9189e5924 | 77 | if (IsTimedOut(timeout_clock)) { |
uci1 | 0:26c9189e5924 | 78 | break; |
uci1 | 0:26c9189e5924 | 79 | } |
uci1 | 0:26c9189e5924 | 80 | cl = (length-b); |
uci1 | 0:26c9189e5924 | 81 | if (cl>maxBufLen) { |
uci1 | 0:26c9189e5924 | 82 | cl = maxBufLen; |
uci1 | 0:26c9189e5924 | 83 | } |
uci1 | 3:a7f72492f19e | 84 | #ifdef DEBUG |
uci1 | 0:26c9189e5924 | 85 | printf("DoIOInChunks: call DoIO with b=%d, cl=%d\r\n",b,cl); |
uci1 | 3:a7f72492f19e | 86 | #endif |
uci1 | 0:26c9189e5924 | 87 | b += DoIO<DATA>(data+b, cl, timeout_clock, fcn); |
uci1 | 3:a7f72492f19e | 88 | #ifdef DEBUG |
uci1 | 0:26c9189e5924 | 89 | printf("DoIOInChunks: b=%d, length=%u\r\n",b,length); |
uci1 | 3:a7f72492f19e | 90 | #endif |
uci1 | 0:26c9189e5924 | 91 | } |
uci1 | 3:a7f72492f19e | 92 | #ifdef DEBUG |
uci1 | 0:26c9189e5924 | 93 | printf("DoIOInChunks: return %d\r\n",b); |
uci1 | 3:a7f72492f19e | 94 | #endif |
uci1 | 0:26c9189e5924 | 95 | return b; |
uci1 | 0:26c9189e5924 | 96 | } |
uci1 | 0:26c9189e5924 | 97 | */ |
uci1 | 0:26c9189e5924 | 98 | bool SerialReadable(); |
uci1 | 0:26c9189e5924 | 99 | bool SerialWriteable(); |
uci1 | 0:26c9189e5924 | 100 | int32_t PutC(const char* const data, const uint32_t, const uint32_t); |
uci1 | 0:26c9189e5924 | 101 | int32_t GetC(char* const data, const uint32_t, const uint32_t); |
uci1 | 3:a7f72492f19e | 102 | int32_t SendBufferedSBD(const char* const data, |
uci1 | 3:a7f72492f19e | 103 | const uint32_t length, |
uci1 | 3:a7f72492f19e | 104 | const uint32_t timeout_clock); |
uci1 | 0:26c9189e5924 | 105 | int32_t SendSBD(const char* const data, const uint32_t length, |
uci1 | 0:26c9189e5924 | 106 | const uint32_t timeout_clock); |
uci1 | 0:26c9189e5924 | 107 | int32_t RecvSBD(char* const data, const uint32_t length, |
uci1 | 0:26c9189e5924 | 108 | const uint32_t timeout_clock); |
uci1 | 0:26c9189e5924 | 109 | int32_t AtCmd(const char* const cmd, |
uci1 | 0:26c9189e5924 | 110 | const uint32_t timeout); |
uci1 | 0:26c9189e5924 | 111 | int32_t AtResp(char* const res, const uint32_t rlen, |
uci1 | 0:26c9189e5924 | 112 | const uint32_t timeout); |
uci1 | 0:26c9189e5924 | 113 | void AppendRespTxt(std::string& str, |
uci1 | 0:26c9189e5924 | 114 | const uint32_t timeout, |
uci1 | 0:26c9189e5924 | 115 | const uint32_t maxslen); |
uci1 | 0:26c9189e5924 | 116 | bool AtRespContainsTxt(const char* const desired, |
uci1 | 0:26c9189e5924 | 117 | const uint32_t timeout, |
uci1 | 0:26c9189e5924 | 118 | std::string& str, |
uci1 | 0:26c9189e5924 | 119 | const char* until="\r\n", |
uci1 | 0:26c9189e5924 | 120 | const uint32_t maxslen=1024); |
uci1 | 0:26c9189e5924 | 121 | bool WaitForAtResponse(const char* const desired, |
uci1 | 0:26c9189e5924 | 122 | const uint32_t timeout, |
uci1 | 0:26c9189e5924 | 123 | const char* until="\r\n"); |
uci1 | 0:26c9189e5924 | 124 | bool WaitForAtResponse(const char* const desired, |
uci1 | 0:26c9189e5924 | 125 | const uint32_t timeout, |
uci1 | 0:26c9189e5924 | 126 | std::string& str, |
uci1 | 0:26c9189e5924 | 127 | const char* until="\r\n"); |
uci1 | 0:26c9189e5924 | 128 | bool WaitForAtResponses(const char* const desired, |
uci1 | 0:26c9189e5924 | 129 | const uint32_t timeout, |
uci1 | 0:26c9189e5924 | 130 | const char* until="\r\n"); |
uci1 | 0:26c9189e5924 | 131 | bool WaitForAtResponses(const char* const desired, |
uci1 | 0:26c9189e5924 | 132 | const uint32_t timeout, |
uci1 | 0:26c9189e5924 | 133 | std::string& str, |
uci1 | 0:26c9189e5924 | 134 | const char* until="\r\n"); |
uci1 | 0:26c9189e5924 | 135 | void EmptyRxBuffer(const uint32_t timeout); |
uci1 | 0:26c9189e5924 | 136 | static |
uci1 | 0:26c9189e5924 | 137 | uint16_t GetMsgNumFromHeader(const uint32_t hlen) { |
uci1 | 0:26c9189e5924 | 138 | return (hlen>>16u); |
uci1 | 0:26c9189e5924 | 139 | } |
uci1 | 0:26c9189e5924 | 140 | static |
uci1 | 0:26c9189e5924 | 141 | uint16_t GetMsgTotFromHeader(const uint32_t hlen) { |
uci1 | 0:26c9189e5924 | 142 | return (hlen&0xFFFF); |
uci1 | 0:26c9189e5924 | 143 | } |
uci1 | 0:26c9189e5924 | 144 | static |
uci1 | 0:26c9189e5924 | 145 | void GetMsgNumTotFromHeader(const uint32_t hlen, |
uci1 | 0:26c9189e5924 | 146 | uint16_t& mnum, |
uci1 | 0:26c9189e5924 | 147 | uint16_t& mtot) { |
uci1 | 0:26c9189e5924 | 148 | mnum = GetMsgNumFromHeader(hlen); |
uci1 | 0:26c9189e5924 | 149 | mtot = GetMsgTotFromHeader(hlen); |
uci1 | 0:26c9189e5924 | 150 | } |
uci1 | 0:26c9189e5924 | 151 | uint32_t GetHeaderFromMsgNumTot(const bool isSending) const { |
uci1 | 0:26c9189e5924 | 152 | uint32_t h = (isSending ? fSMsgNum : fRMsgNum); |
uci1 | 0:26c9189e5924 | 153 | h <<= 16u; |
uci1 | 0:26c9189e5924 | 154 | h |= (isSending ? fSMsgTot : fRMsgTot); |
uci1 | 0:26c9189e5924 | 155 | return h; |
uci1 | 0:26c9189e5924 | 156 | } |
uci1 | 0:26c9189e5924 | 157 | |
uci1 | 0:26c9189e5924 | 158 | protected: |
uci1 | 0:26c9189e5924 | 159 | virtual int32_t ReceiveAll(char* const buf, const uint32_t mlen, |
uci1 | 0:26c9189e5924 | 160 | const uint32_t timeout_clock); |
uci1 | 0:26c9189e5924 | 161 | virtual int32_t SendAll(const char* const data, const uint32_t length, |
uci1 | 0:26c9189e5924 | 162 | const uint32_t timeout_clock); |
uci1 | 3:a7f72492f19e | 163 | virtual int32_t FinishSending(const uint32_t timeout_clock); |
uci1 | 0:26c9189e5924 | 164 | |
uci1 | 0:26c9189e5924 | 165 | public: |
uci1 | 5:2ee6cbb948c0 | 166 | // Serial and MODSERIAL don't share virtual functions, so we MUST obtain |
uci1 | 5:2ee6cbb948c0 | 167 | // a pointer of type MODSERIAL if that's what we're using |
uci1 | 5:2ee6cbb948c0 | 168 | SnCommSBD(COMM_SERIALTYPE* sbdPort=0) : |
uci1 | 3:a7f72492f19e | 169 | fSBD(sbdPort), fTxPos(0), fRxPos(0), fRxSiz(0), |
uci1 | 0:26c9189e5924 | 170 | fRMsgNum(0), fRMsgTot(0), // essential that these start at 0! |
uci1 | 0:26c9189e5924 | 171 | fSMsgNum(0), fSMsgTot(0) { |
uci1 | 0:26c9189e5924 | 172 | |
uci1 | 3:a7f72492f19e | 173 | memset(fRxBuf, 0, kRxBufSz*sizeof(char)); |
uci1 | 3:a7f72492f19e | 174 | memset(fTxBuf, 0, kTxBufSz*sizeof(char)); |
uci1 | 0:26c9189e5924 | 175 | } |
uci1 | 0:26c9189e5924 | 176 | virtual ~SnCommSBD() {} |
uci1 | 0:26c9189e5924 | 177 | |
uci1 | 4:8328c2972290 | 178 | virtual bool TrySetSysTimeUnix(const uint32_t timeout, |
uci1 | 4:8328c2972290 | 179 | uint32_t& prvTime, |
uci1 | 4:8328c2972290 | 180 | uint32_t& setTime); |
uci1 | 0:26c9189e5924 | 181 | |
uci1 | 5:2ee6cbb948c0 | 182 | virtual bool CheckSignalStrength(const uint32_t timeout, |
uci1 | 5:2ee6cbb948c0 | 183 | float& sigstr); |
uci1 | 5:2ee6cbb948c0 | 184 | |
uci1 | 0:26c9189e5924 | 185 | virtual bool Connect(const uint32_t timeout); |
uci1 | 0:26c9189e5924 | 186 | |
uci1 | 3:a7f72492f19e | 187 | virtual bool CloseConn(const uint32_t timeout) { |
uci1 | 3:a7f72492f19e | 188 | ClearSendReceiveBuffers(); |
uci1 | 3:a7f72492f19e | 189 | return true; |
uci1 | 3:a7f72492f19e | 190 | } |
uci1 | 3:a7f72492f19e | 191 | |
uci1 | 3:a7f72492f19e | 192 | virtual bool PowerDown(const uint32_t); |
uci1 | 0:26c9189e5924 | 193 | |
uci1 | 3:a7f72492f19e | 194 | void ClearSendReceiveBuffers() { |
uci1 | 3:a7f72492f19e | 195 | fRxPos=0; |
uci1 | 3:a7f72492f19e | 196 | fRxSiz=0; |
uci1 | 3:a7f72492f19e | 197 | fRMsgNum=0; |
uci1 | 3:a7f72492f19e | 198 | fRMsgTot=0; |
uci1 | 3:a7f72492f19e | 199 | fSMsgNum=0; |
uci1 | 3:a7f72492f19e | 200 | fSMsgTot=0; |
uci1 | 3:a7f72492f19e | 201 | memset(fRxBuf, 0, kMaxRecv*sizeof(char)); |
uci1 | 3:a7f72492f19e | 202 | } |
uci1 | 0:26c9189e5924 | 203 | |
uci1 | 0:26c9189e5924 | 204 | static |
uci1 | 0:26c9189e5924 | 205 | bool ParseSBDSresp(const std::string& sr, |
uci1 | 0:26c9189e5924 | 206 | int32_t& mo, int32_t& momsn, |
uci1 | 0:26c9189e5924 | 207 | int32_t& mt, int32_t& mtmsn); |
uci1 | 0:26c9189e5924 | 208 | |
uci1 | 0:26c9189e5924 | 209 | static |
uci1 | 0:26c9189e5924 | 210 | bool ParseSBDIXresp(const std::string& ixr, |
uci1 | 0:26c9189e5924 | 211 | int32_t& mo, int32_t& momsn, |
uci1 | 0:26c9189e5924 | 212 | int32_t& mt, int32_t& mtmsn, |
uci1 | 0:26c9189e5924 | 213 | int32_t& mtlen, int32_t& mtq); |
uci1 | 0:26c9189e5924 | 214 | |
uci1 | 0:26c9189e5924 | 215 | |
uci1 | 0:26c9189e5924 | 216 | }; |
uci1 | 0:26c9189e5924 | 217 | |
uci1 | 0:26c9189e5924 | 218 | #endif // ENABLE_SBD |
uci1 | 0:26c9189e5924 | 219 | |
uci1 | 0:26c9189e5924 | 220 | #endif // SN_SnCommSBD |