IM920 (920MHz wireless module) protocol parser
IM920.h@0:ee7d2910f5ea, 2016-04-11 (annotated)
- Committer:
- hideakitai
- Date:
- Mon Apr 11 12:41:10 2016 +0000
- Revision:
- 0:ee7d2910f5ea
IM920 (920MHz wireless module) protocol parser
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hideakitai | 0:ee7d2910f5ea | 1 | #pragma once |
hideakitai | 0:ee7d2910f5ea | 2 | #include "mbed.h" |
hideakitai | 0:ee7d2910f5ea | 3 | #include <queue> |
hideakitai | 0:ee7d2910f5ea | 4 | |
hideakitai | 0:ee7d2910f5ea | 5 | #define kAsciiCR 0x0D |
hideakitai | 0:ee7d2910f5ea | 6 | #define kAsciiLF 0x0A |
hideakitai | 0:ee7d2910f5ea | 7 | |
hideakitai | 0:ee7d2910f5ea | 8 | class IM920 : public Serial |
hideakitai | 0:ee7d2910f5ea | 9 | { |
hideakitai | 0:ee7d2910f5ea | 10 | typedef enum StateIm920 { |
hideakitai | 0:ee7d2910f5ea | 11 | kStateNode = 0, |
hideakitai | 0:ee7d2910f5ea | 12 | kStateParentId, |
hideakitai | 0:ee7d2910f5ea | 13 | kStateRssi, |
hideakitai | 0:ee7d2910f5ea | 14 | kStateData, |
hideakitai | 0:ee7d2910f5ea | 15 | kStateCRLF |
hideakitai | 0:ee7d2910f5ea | 16 | } StateIm920; |
hideakitai | 0:ee7d2910f5ea | 17 | |
hideakitai | 0:ee7d2910f5ea | 18 | typedef struct Im920Packet { |
hideakitai | 0:ee7d2910f5ea | 19 | int node; |
hideakitai | 0:ee7d2910f5ea | 20 | int parent_id; |
hideakitai | 0:ee7d2910f5ea | 21 | int rssi; |
hideakitai | 0:ee7d2910f5ea | 22 | int data[8]; |
hideakitai | 0:ee7d2910f5ea | 23 | } Im920Packet; |
hideakitai | 0:ee7d2910f5ea | 24 | |
hideakitai | 0:ee7d2910f5ea | 25 | typedef struct Im920PacketAscii { |
hideakitai | 0:ee7d2910f5ea | 26 | char node[3]; |
hideakitai | 0:ee7d2910f5ea | 27 | char parent_id[5]; |
hideakitai | 0:ee7d2910f5ea | 28 | char rssi[3]; |
hideakitai | 0:ee7d2910f5ea | 29 | char data[8][3]; |
hideakitai | 0:ee7d2910f5ea | 30 | } Im920PacketAscii; |
hideakitai | 0:ee7d2910f5ea | 31 | |
hideakitai | 0:ee7d2910f5ea | 32 | public: |
hideakitai | 0:ee7d2910f5ea | 33 | |
hideakitai | 0:ee7d2910f5ea | 34 | IM920(PinName tx, PinName rx, int baudrate) |
hideakitai | 0:ee7d2910f5ea | 35 | : mbed::Serial(tx, rx) |
hideakitai | 0:ee7d2910f5ea | 36 | , pc(NULL) |
hideakitai | 0:ee7d2910f5ea | 37 | { |
hideakitai | 0:ee7d2910f5ea | 38 | this->baud(baudrate); |
hideakitai | 0:ee7d2910f5ea | 39 | this->attach(this, &IM920::push_byte); |
hideakitai | 0:ee7d2910f5ea | 40 | } |
hideakitai | 0:ee7d2910f5ea | 41 | virtual ~IM920() |
hideakitai | 0:ee7d2910f5ea | 42 | { |
hideakitai | 0:ee7d2910f5ea | 43 | if (pc) delete pc; |
hideakitai | 0:ee7d2910f5ea | 44 | } |
hideakitai | 0:ee7d2910f5ea | 45 | |
hideakitai | 0:ee7d2910f5ea | 46 | void push_byte() { byte_buff.push(this->getc()); } |
hideakitai | 0:ee7d2910f5ea | 47 | void pop_byte() { byte_buff.pop(); } |
hideakitai | 0:ee7d2910f5ea | 48 | |
hideakitai | 0:ee7d2910f5ea | 49 | void pop() { readBuffer_.pop(); } |
hideakitai | 0:ee7d2910f5ea | 50 | |
hideakitai | 0:ee7d2910f5ea | 51 | int available() { return (int)readBuffer_.size(); } |
hideakitai | 0:ee7d2910f5ea | 52 | |
hideakitai | 0:ee7d2910f5ea | 53 | void dump() |
hideakitai | 0:ee7d2910f5ea | 54 | { |
hideakitai | 0:ee7d2910f5ea | 55 | while(byte_buff.size()) |
hideakitai | 0:ee7d2910f5ea | 56 | { |
hideakitai | 0:ee7d2910f5ea | 57 | if(pc) pc->printf("%c", (char)byte_buff.front()); |
hideakitai | 0:ee7d2910f5ea | 58 | byte_buff.pop(); |
hideakitai | 0:ee7d2910f5ea | 59 | } |
hideakitai | 0:ee7d2910f5ea | 60 | } |
hideakitai | 0:ee7d2910f5ea | 61 | |
hideakitai | 0:ee7d2910f5ea | 62 | virtual void setDebugSerial(Serial* s) { pc = s; } |
hideakitai | 0:ee7d2910f5ea | 63 | |
hideakitai | 0:ee7d2910f5ea | 64 | void send(const char* format) |
hideakitai | 0:ee7d2910f5ea | 65 | { this->Serial::printf(format); } |
hideakitai | 0:ee7d2910f5ea | 66 | template <typename A> |
hideakitai | 0:ee7d2910f5ea | 67 | void send(const char* format, A &a) |
hideakitai | 0:ee7d2910f5ea | 68 | { this->Serial::printf(format, a); } |
hideakitai | 0:ee7d2910f5ea | 69 | template <typename A, typename B> |
hideakitai | 0:ee7d2910f5ea | 70 | void send(const char* format, A &a, B &b) |
hideakitai | 0:ee7d2910f5ea | 71 | { this->Serial::printf(format, a, b); } |
hideakitai | 0:ee7d2910f5ea | 72 | template <typename A, typename B, typename C> |
hideakitai | 0:ee7d2910f5ea | 73 | void send(const char* format, A &a, B &b, C &c) |
hideakitai | 0:ee7d2910f5ea | 74 | { this->Serial::printf(format, a, b, c); } |
hideakitai | 0:ee7d2910f5ea | 75 | |
hideakitai | 0:ee7d2910f5ea | 76 | const Im920Packet& getPacket() { return readBuffer_.front(); } |
hideakitai | 0:ee7d2910f5ea | 77 | const int& getNwNode() { return readBuffer_.front().node; } |
hideakitai | 0:ee7d2910f5ea | 78 | const int& getNwParentId() { return readBuffer_.front().parent_id; } |
hideakitai | 0:ee7d2910f5ea | 79 | const int& getNwRssi() { return readBuffer_.front().rssi; } |
hideakitai | 0:ee7d2910f5ea | 80 | const int* getDataPtr() { return (int*)readBuffer_.front().data; } |
hideakitai | 0:ee7d2910f5ea | 81 | uint8_t getData(int idx) { return readBuffer_.front().data[idx]; } |
hideakitai | 0:ee7d2910f5ea | 82 | |
hideakitai | 0:ee7d2910f5ea | 83 | void enableWriteFlash() { send("ENWR\r\n"); } |
hideakitai | 0:ee7d2910f5ea | 84 | void disableWriteFlash() { send("DSWR\r\n"); } |
hideakitai | 0:ee7d2910f5ea | 85 | void deleteParentId() { send("ERID\r\n"); } |
hideakitai | 0:ee7d2910f5ea | 86 | void writeParentId(int id) { send("SRID %04x\r\n", id); } |
hideakitai | 0:ee7d2910f5ea | 87 | void requestParentId() { send("RRID\r\n"); } |
hideakitai | 0:ee7d2910f5ea | 88 | void writeWirelessPower(int n) { send("STPO %1d\r\n", n); } |
hideakitai | 0:ee7d2910f5ea | 89 | void writeWirelessSpeed(int n) { send("STRT %1d\r\n", n); } |
hideakitai | 0:ee7d2910f5ea | 90 | void writeBaudrate(int n) { send("SBRT %1d\r\n", n); } |
hideakitai | 0:ee7d2910f5ea | 91 | void writeChannel(int n) { send("STCH %02d\r\n", n); } |
hideakitai | 0:ee7d2910f5ea | 92 | void reset() { send("SRST\r\n"); } |
hideakitai | 0:ee7d2910f5ea | 93 | |
hideakitai | 0:ee7d2910f5ea | 94 | void dumpPacket() |
hideakitai | 0:ee7d2910f5ea | 95 | { |
hideakitai | 0:ee7d2910f5ea | 96 | if(available()) |
hideakitai | 0:ee7d2910f5ea | 97 | { |
hideakitai | 0:ee7d2910f5ea | 98 | if(pc) |
hideakitai | 0:ee7d2910f5ea | 99 | { |
hideakitai | 0:ee7d2910f5ea | 100 | Im920Packet& p = readBuffer_.front(); |
hideakitai | 0:ee7d2910f5ea | 101 | pc->printf("packet dump >> %02x,%04x,%02x:", p.node, p.parent_id, p.rssi); |
hideakitai | 0:ee7d2910f5ea | 102 | for (int i=0; i<7; i++) pc->printf("%02x,", p.data[i]); |
hideakitai | 0:ee7d2910f5ea | 103 | pc->printf("%02x\r\n", p.data[7]); |
hideakitai | 0:ee7d2910f5ea | 104 | } |
hideakitai | 0:ee7d2910f5ea | 105 | readBuffer_.pop(); |
hideakitai | 0:ee7d2910f5ea | 106 | } |
hideakitai | 0:ee7d2910f5ea | 107 | else |
hideakitai | 0:ee7d2910f5ea | 108 | if(pc) pc->printf("[Error] No Packet Available!!\n"); |
hideakitai | 0:ee7d2910f5ea | 109 | } |
hideakitai | 0:ee7d2910f5ea | 110 | |
hideakitai | 0:ee7d2910f5ea | 111 | void parse() |
hideakitai | 0:ee7d2910f5ea | 112 | { |
hideakitai | 0:ee7d2910f5ea | 113 | if (byte_buff.size() <= 0) return; |
hideakitai | 0:ee7d2910f5ea | 114 | |
hideakitai | 0:ee7d2910f5ea | 115 | static bool bUnderParsing = false; |
hideakitai | 0:ee7d2910f5ea | 116 | static int cnt = 0; |
hideakitai | 0:ee7d2910f5ea | 117 | static int dcnt = 0; |
hideakitai | 0:ee7d2910f5ea | 118 | static Im920PacketAscii pa; |
hideakitai | 0:ee7d2910f5ea | 119 | static StateIm920 state = kStateNode; |
hideakitai | 0:ee7d2910f5ea | 120 | |
hideakitai | 0:ee7d2910f5ea | 121 | while (byte_buff.size() > 0) |
hideakitai | 0:ee7d2910f5ea | 122 | { |
hideakitai | 0:ee7d2910f5ea | 123 | char data = (char)byte_buff.front(); |
hideakitai | 0:ee7d2910f5ea | 124 | |
hideakitai | 0:ee7d2910f5ea | 125 | if (isCorrupted((int)data)) { |
hideakitai | 0:ee7d2910f5ea | 126 | state = kStateNode; |
hideakitai | 0:ee7d2910f5ea | 127 | bUnderParsing = false; |
hideakitai | 0:ee7d2910f5ea | 128 | return; |
hideakitai | 0:ee7d2910f5ea | 129 | } |
hideakitai | 0:ee7d2910f5ea | 130 | |
hideakitai | 0:ee7d2910f5ea | 131 | if (!bUnderParsing) |
hideakitai | 0:ee7d2910f5ea | 132 | { |
hideakitai | 0:ee7d2910f5ea | 133 | for (int i=0; i<5; i++) pa.parent_id[i] = (char)0; |
hideakitai | 0:ee7d2910f5ea | 134 | for (int i=0; i<3; i++) { |
hideakitai | 0:ee7d2910f5ea | 135 | pa.node[i] = pa.rssi[i] = (char)0; |
hideakitai | 0:ee7d2910f5ea | 136 | for (int j=0; j<8; j++) pa.data[j][i] = (char)0; |
hideakitai | 0:ee7d2910f5ea | 137 | } |
hideakitai | 0:ee7d2910f5ea | 138 | dcnt = cnt = 0; |
hideakitai | 0:ee7d2910f5ea | 139 | bUnderParsing = true; |
hideakitai | 0:ee7d2910f5ea | 140 | } |
hideakitai | 0:ee7d2910f5ea | 141 | |
hideakitai | 0:ee7d2910f5ea | 142 | switch(state) |
hideakitai | 0:ee7d2910f5ea | 143 | { |
hideakitai | 0:ee7d2910f5ea | 144 | case kStateNode: |
hideakitai | 0:ee7d2910f5ea | 145 | { |
hideakitai | 0:ee7d2910f5ea | 146 | if (data == ',') { |
hideakitai | 0:ee7d2910f5ea | 147 | state = kStateParentId; |
hideakitai | 0:ee7d2910f5ea | 148 | dcnt = cnt = 0; |
hideakitai | 0:ee7d2910f5ea | 149 | } else { |
hideakitai | 0:ee7d2910f5ea | 150 | pa.node[cnt++] = data; |
hideakitai | 0:ee7d2910f5ea | 151 | } |
hideakitai | 0:ee7d2910f5ea | 152 | break; |
hideakitai | 0:ee7d2910f5ea | 153 | } |
hideakitai | 0:ee7d2910f5ea | 154 | case kStateParentId: |
hideakitai | 0:ee7d2910f5ea | 155 | { |
hideakitai | 0:ee7d2910f5ea | 156 | if (data == ',') { |
hideakitai | 0:ee7d2910f5ea | 157 | state = kStateRssi; |
hideakitai | 0:ee7d2910f5ea | 158 | dcnt = cnt = 0; |
hideakitai | 0:ee7d2910f5ea | 159 | } else { |
hideakitai | 0:ee7d2910f5ea | 160 | pa.parent_id[cnt++] = data; |
hideakitai | 0:ee7d2910f5ea | 161 | } |
hideakitai | 0:ee7d2910f5ea | 162 | break; |
hideakitai | 0:ee7d2910f5ea | 163 | } |
hideakitai | 0:ee7d2910f5ea | 164 | case kStateRssi: |
hideakitai | 0:ee7d2910f5ea | 165 | { |
hideakitai | 0:ee7d2910f5ea | 166 | if (data == ':') { |
hideakitai | 0:ee7d2910f5ea | 167 | state = kStateData; |
hideakitai | 0:ee7d2910f5ea | 168 | dcnt = cnt = 0; |
hideakitai | 0:ee7d2910f5ea | 169 | } else { |
hideakitai | 0:ee7d2910f5ea | 170 | pa.rssi[cnt++] = data; |
hideakitai | 0:ee7d2910f5ea | 171 | } |
hideakitai | 0:ee7d2910f5ea | 172 | break; |
hideakitai | 0:ee7d2910f5ea | 173 | } |
hideakitai | 0:ee7d2910f5ea | 174 | case kStateData: |
hideakitai | 0:ee7d2910f5ea | 175 | { |
hideakitai | 0:ee7d2910f5ea | 176 | if (data == ',') { |
hideakitai | 0:ee7d2910f5ea | 177 | ++dcnt; |
hideakitai | 0:ee7d2910f5ea | 178 | cnt = 0; |
hideakitai | 0:ee7d2910f5ea | 179 | } else if (data == (char)kAsciiCR) { |
hideakitai | 0:ee7d2910f5ea | 180 | state = kStateCRLF; |
hideakitai | 0:ee7d2910f5ea | 181 | } else { |
hideakitai | 0:ee7d2910f5ea | 182 | pa.data[dcnt][cnt++] = data; |
hideakitai | 0:ee7d2910f5ea | 183 | } |
hideakitai | 0:ee7d2910f5ea | 184 | break; |
hideakitai | 0:ee7d2910f5ea | 185 | } |
hideakitai | 0:ee7d2910f5ea | 186 | case kStateCRLF: |
hideakitai | 0:ee7d2910f5ea | 187 | { |
hideakitai | 0:ee7d2910f5ea | 188 | if (data == (char)kAsciiLF) |
hideakitai | 0:ee7d2910f5ea | 189 | { |
hideakitai | 0:ee7d2910f5ea | 190 | Im920Packet p; |
hideakitai | 0:ee7d2910f5ea | 191 | p.node = (int)strtol(pa.node, NULL, 16); |
hideakitai | 0:ee7d2910f5ea | 192 | p.parent_id = (int)strtol(pa.parent_id, NULL, 16); |
hideakitai | 0:ee7d2910f5ea | 193 | p.rssi = (int)strtol(pa.rssi, NULL, 16); |
hideakitai | 0:ee7d2910f5ea | 194 | for (int i = 0; i < 8; i++) { |
hideakitai | 0:ee7d2910f5ea | 195 | p.data[i] = (int)strtol(pa.data[i], NULL, 16); |
hideakitai | 0:ee7d2910f5ea | 196 | } |
hideakitai | 0:ee7d2910f5ea | 197 | readBuffer_.push(p); |
hideakitai | 0:ee7d2910f5ea | 198 | // std::queue<int>().swap(q) |
hideakitai | 0:ee7d2910f5ea | 199 | } |
hideakitai | 0:ee7d2910f5ea | 200 | else |
hideakitai | 0:ee7d2910f5ea | 201 | { |
hideakitai | 0:ee7d2910f5ea | 202 | if(pc) pc->printf("invalid data order!!!\n"); |
hideakitai | 0:ee7d2910f5ea | 203 | } |
hideakitai | 0:ee7d2910f5ea | 204 | state = kStateNode; |
hideakitai | 0:ee7d2910f5ea | 205 | bUnderParsing = false; |
hideakitai | 0:ee7d2910f5ea | 206 | dcnt = cnt = 0; |
hideakitai | 0:ee7d2910f5ea | 207 | |
hideakitai | 0:ee7d2910f5ea | 208 | break; |
hideakitai | 0:ee7d2910f5ea | 209 | } |
hideakitai | 0:ee7d2910f5ea | 210 | default: |
hideakitai | 0:ee7d2910f5ea | 211 | { |
hideakitai | 0:ee7d2910f5ea | 212 | state = kStateNode; |
hideakitai | 0:ee7d2910f5ea | 213 | bUnderParsing = false; |
hideakitai | 0:ee7d2910f5ea | 214 | dcnt = cnt = 0; |
hideakitai | 0:ee7d2910f5ea | 215 | break; |
hideakitai | 0:ee7d2910f5ea | 216 | } |
hideakitai | 0:ee7d2910f5ea | 217 | } |
hideakitai | 0:ee7d2910f5ea | 218 | pop_byte(); |
hideakitai | 0:ee7d2910f5ea | 219 | } |
hideakitai | 0:ee7d2910f5ea | 220 | } |
hideakitai | 0:ee7d2910f5ea | 221 | |
hideakitai | 0:ee7d2910f5ea | 222 | |
hideakitai | 0:ee7d2910f5ea | 223 | private: |
hideakitai | 0:ee7d2910f5ea | 224 | bool isCorrupted(int ascii) |
hideakitai | 0:ee7d2910f5ea | 225 | { |
hideakitai | 0:ee7d2910f5ea | 226 | bool isCRLF = ((ascii == 13) || (ascii == 10)) ? true : false; |
hideakitai | 0:ee7d2910f5ea | 227 | bool isPunctuation = ((ascii == 44) || (ascii == 58)) ? true : false; |
hideakitai | 0:ee7d2910f5ea | 228 | bool is0to9 = ((ascii >= 48) && (ascii <= 57)) ? true : false; |
hideakitai | 0:ee7d2910f5ea | 229 | bool isAtoF = ((ascii >= 65) && (ascii <= 70)) ? true : false; |
hideakitai | 0:ee7d2910f5ea | 230 | if (!(isCRLF || isPunctuation || is0to9 || isAtoF)) { |
hideakitai | 0:ee7d2910f5ea | 231 | if(pc) pc->printf("Invalid Ascii!\r\n"); |
hideakitai | 0:ee7d2910f5ea | 232 | return true; |
hideakitai | 0:ee7d2910f5ea | 233 | } |
hideakitai | 0:ee7d2910f5ea | 234 | return false; |
hideakitai | 0:ee7d2910f5ea | 235 | } |
hideakitai | 0:ee7d2910f5ea | 236 | |
hideakitai | 0:ee7d2910f5ea | 237 | queue<uint8_t> byte_buff; |
hideakitai | 0:ee7d2910f5ea | 238 | queue<Im920Packet> readBuffer_; |
hideakitai | 0:ee7d2910f5ea | 239 | Serial* pc; |
hideakitai | 0:ee7d2910f5ea | 240 | }; |
hideakitai | 0:ee7d2910f5ea | 241 | |
hideakitai | 0:ee7d2910f5ea | 242 |