IM920 (920MHz wireless module) protocol parser
IM920.h
- Committer:
- hideakitai
- Date:
- 2016-04-11
- Revision:
- 0:ee7d2910f5ea
File content as of revision 0:ee7d2910f5ea:
#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; };