IM920 (920MHz wireless module) protocol parser
Revision 0:ee7d2910f5ea, committed 2016-04-11
- Comitter:
- hideakitai
- Date:
- Mon Apr 11 12:41:10 2016 +0000
- Commit message:
- IM920 (920MHz wireless module) protocol parser
Changed in this revision
IM920.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IM920.h Mon Apr 11 12:41:10 2016 +0000 @@ -0,0 +1,242 @@ +#pragma once +#include "mbed.h" +#include <queue> + + #define kAsciiCR 0x0D + #define kAsciiLF 0x0A + +class IM920 : public Serial +{ + typedef enum StateIm920 { + kStateNode = 0, + kStateParentId, + kStateRssi, + kStateData, + kStateCRLF + } StateIm920; + + typedef struct Im920Packet { + int node; + int parent_id; + int rssi; + int data[8]; + } Im920Packet; + + typedef struct Im920PacketAscii { + char node[3]; + char parent_id[5]; + char rssi[3]; + char data[8][3]; + } Im920PacketAscii; + +public: + + IM920(PinName tx, PinName rx, int baudrate) + : mbed::Serial(tx, rx) + , pc(NULL) + { + this->baud(baudrate); + this->attach(this, &IM920::push_byte); + } + virtual ~IM920() + { + if (pc) delete pc; + } + + void push_byte() { byte_buff.push(this->getc()); } + void pop_byte() { byte_buff.pop(); } + + void pop() { readBuffer_.pop(); } + + int available() { return (int)readBuffer_.size(); } + + void dump() + { + while(byte_buff.size()) + { + if(pc) pc->printf("%c", (char)byte_buff.front()); + byte_buff.pop(); + } + } + + virtual void setDebugSerial(Serial* s) { pc = s; } + + void send(const char* format) + { this->Serial::printf(format); } + template <typename A> + void send(const char* format, A &a) + { this->Serial::printf(format, a); } + template <typename A, typename B> + void send(const char* format, A &a, B &b) + { this->Serial::printf(format, a, b); } + template <typename A, typename B, typename C> + void send(const char* format, A &a, B &b, C &c) + { this->Serial::printf(format, a, b, c); } + + const Im920Packet& getPacket() { return readBuffer_.front(); } + const int& getNwNode() { return readBuffer_.front().node; } + const int& getNwParentId() { return readBuffer_.front().parent_id; } + const int& getNwRssi() { return readBuffer_.front().rssi; } + const int* getDataPtr() { return (int*)readBuffer_.front().data; } + uint8_t getData(int idx) { return readBuffer_.front().data[idx]; } + + void enableWriteFlash() { send("ENWR\r\n"); } + void disableWriteFlash() { send("DSWR\r\n"); } + void deleteParentId() { send("ERID\r\n"); } + void writeParentId(int id) { send("SRID %04x\r\n", id); } + void requestParentId() { send("RRID\r\n"); } + void writeWirelessPower(int n) { send("STPO %1d\r\n", n); } + void writeWirelessSpeed(int n) { send("STRT %1d\r\n", n); } + void writeBaudrate(int n) { send("SBRT %1d\r\n", n); } + void writeChannel(int n) { send("STCH %02d\r\n", n); } + void reset() { send("SRST\r\n"); } + + void dumpPacket() + { + if(available()) + { + if(pc) + { + Im920Packet& p = readBuffer_.front(); + pc->printf("packet dump >> %02x,%04x,%02x:", p.node, p.parent_id, p.rssi); + for (int i=0; i<7; i++) pc->printf("%02x,", p.data[i]); + pc->printf("%02x\r\n", p.data[7]); + } + readBuffer_.pop(); + } + else + if(pc) pc->printf("[Error] No Packet Available!!\n"); + } + + void parse() + { + if (byte_buff.size() <= 0) return; + + static bool bUnderParsing = false; + static int cnt = 0; + static int dcnt = 0; + static Im920PacketAscii pa; + static StateIm920 state = kStateNode; + + while (byte_buff.size() > 0) + { + char data = (char)byte_buff.front(); + + if (isCorrupted((int)data)) { + state = kStateNode; + bUnderParsing = false; + return; + } + + if (!bUnderParsing) + { + for (int i=0; i<5; i++) pa.parent_id[i] = (char)0; + for (int i=0; i<3; i++) { + pa.node[i] = pa.rssi[i] = (char)0; + for (int j=0; j<8; j++) pa.data[j][i] = (char)0; + } + dcnt = cnt = 0; + bUnderParsing = true; + } + + switch(state) + { + case kStateNode: + { + if (data == ',') { + state = kStateParentId; + dcnt = cnt = 0; + } else { + pa.node[cnt++] = data; + } + break; + } + case kStateParentId: + { + if (data == ',') { + state = kStateRssi; + dcnt = cnt = 0; + } else { + pa.parent_id[cnt++] = data; + } + break; + } + case kStateRssi: + { + if (data == ':') { + state = kStateData; + dcnt = cnt = 0; + } else { + pa.rssi[cnt++] = data; + } + break; + } + case kStateData: + { + if (data == ',') { + ++dcnt; + cnt = 0; + } else if (data == (char)kAsciiCR) { + state = kStateCRLF; + } else { + pa.data[dcnt][cnt++] = data; + } + break; + } + case kStateCRLF: + { + if (data == (char)kAsciiLF) + { + Im920Packet p; + p.node = (int)strtol(pa.node, NULL, 16); + p.parent_id = (int)strtol(pa.parent_id, NULL, 16); + p.rssi = (int)strtol(pa.rssi, NULL, 16); + for (int i = 0; i < 8; i++) { + p.data[i] = (int)strtol(pa.data[i], NULL, 16); + } + readBuffer_.push(p); +// std::queue<int>().swap(q) + } + else + { + if(pc) pc->printf("invalid data order!!!\n"); + } + state = kStateNode; + bUnderParsing = false; + dcnt = cnt = 0; + + break; + } + default: + { + state = kStateNode; + bUnderParsing = false; + dcnt = cnt = 0; + break; + } + } + pop_byte(); + } + } + + +private: + bool isCorrupted(int ascii) + { + bool isCRLF = ((ascii == 13) || (ascii == 10)) ? true : false; + bool isPunctuation = ((ascii == 44) || (ascii == 58)) ? true : false; + bool is0to9 = ((ascii >= 48) && (ascii <= 57)) ? true : false; + bool isAtoF = ((ascii >= 65) && (ascii <= 70)) ? true : false; + if (!(isCRLF || isPunctuation || is0to9 || isAtoF)) { + if(pc) pc->printf("Invalid Ascii!\r\n"); + return true; + } + return false; + } + + queue<uint8_t> byte_buff; + queue<Im920Packet> readBuffer_; + Serial* pc; +}; + +