WizziLab's serial protocol library

Dependents:   modem_ref_helper_for_v5_3_217 modem_ref_helper

Committer:
Jeej
Date:
Wed Apr 26 12:29:35 2017 +0000
Revision:
0:95b73d0b37b7
Child:
1:ca1c9bfb1cf4
Initial version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jeej 0:95b73d0b37b7 1 #include "WizziCom.h"
Jeej 0:95b73d0b37b7 2
Jeej 0:95b73d0b37b7 3 #if 1
Jeej 0:95b73d0b37b7 4 #define COM_DPRINT(...) DPRINT(__VA_ARGS__)
Jeej 0:95b73d0b37b7 5 #define COM_DPRINT_DATA(...) DPRINT_DATA(__VA_ARGS__)
Jeej 0:95b73d0b37b7 6 #define COM_FPRINT(...) FPRINT(__VA_ARGS__)
Jeej 0:95b73d0b37b7 7 #else
Jeej 0:95b73d0b37b7 8 #define COM_DPRINT(...);
Jeej 0:95b73d0b37b7 9 #define COM_DPRINT_DATA(...);
Jeej 0:95b73d0b37b7 10 #define COM_FPRINT(...);
Jeej 0:95b73d0b37b7 11 #endif
Jeej 0:95b73d0b37b7 12
Jeej 0:95b73d0b37b7 13 #define XON_SIGNAL (0x0001 << 0)
Jeej 0:95b73d0b37b7 14 #define START_SIGNAL (0x0001 << 1)
Jeej 0:95b73d0b37b7 15
Jeej 0:95b73d0b37b7 16 // +--------------+--------+--------+--------+---- - - - - - - - - - - --------+
Jeej 0:95b73d0b37b7 17 // | SYNC | LEN | SEQ | ID | PAYLOAD |
Jeej 0:95b73d0b37b7 18 // +--------------+--------+--------+--------+---- - - - - - - - - - - --------+
Jeej 0:95b73d0b37b7 19 //
Jeej 0:95b73d0b37b7 20 // 2 bytes 1 byte 1 byte 1 byte LEN bytes
Jeej 0:95b73d0b37b7 21 // |<------------>|<------>|<------>|<------>|<--- - - - - - - - - - - ------->|
Jeej 0:95b73d0b37b7 22
Jeej 0:95b73d0b37b7 23
Jeej 0:95b73d0b37b7 24 // first byte of the sync word
Jeej 0:95b73d0b37b7 25 // (ASCII start of heading)
Jeej 0:95b73d0b37b7 26 #define KAL_COM_SYNC_BYTE_0 0x01
Jeej 0:95b73d0b37b7 27
Jeej 0:95b73d0b37b7 28 // second byte of the sync word
Jeej 0:95b73d0b37b7 29 // (ASCII group separator)
Jeej 0:95b73d0b37b7 30 #define KAL_COM_SYNC_BYTE_1 0x1F
Jeej 0:95b73d0b37b7 31
Jeej 0:95b73d0b37b7 32 // message header length in byte
Jeej 0:95b73d0b37b7 33 #define KAL_COM_HEADER_LEN 5
Jeej 0:95b73d0b37b7 34
Jeej 0:95b73d0b37b7 35
Jeej 0:95b73d0b37b7 36 //======================================================================
Jeej 0:95b73d0b37b7 37 // wizzi_com_fid_t
Jeej 0:95b73d0b37b7 38 //----------------------------------------------------------------------
Jeej 0:95b73d0b37b7 39 // Enumerator of serial Flow-ids
Jeej 0:95b73d0b37b7 40 //======================================================================
Jeej 0:95b73d0b37b7 41 typedef enum
Jeej 0:95b73d0b37b7 42 {
Jeej 0:95b73d0b37b7 43 // Trace channel
Jeej 0:95b73d0b37b7 44 KAL_COM_FLOWID_TRC = 0,
Jeej 0:95b73d0b37b7 45 // General purpose Command channel
Jeej 0:95b73d0b37b7 46 KAL_COM_FLOWID_CMD,
Jeej 0:95b73d0b37b7 47 // ALP channel
Jeej 0:95b73d0b37b7 48 KAL_COM_FLOWID_ALP,
Jeej 0:95b73d0b37b7 49 // System notifications
Jeej 0:95b73d0b37b7 50 KAL_COM_FLOWID_SYS,
Jeej 0:95b73d0b37b7 51 // File System channel
Jeej 0:95b73d0b37b7 52 KAL_COM_FLOWID_FS,
Jeej 0:95b73d0b37b7 53
Jeej 0:95b73d0b37b7 54 KAL_COM_FLOWID_QTY
Jeej 0:95b73d0b37b7 55
Jeej 0:95b73d0b37b7 56 } wizzi_com_fid_t;
Jeej 0:95b73d0b37b7 57
Jeej 0:95b73d0b37b7 58 #define KAL_COM_FLOW(fid,type) ((((fid)&0x7)<<4) | ((type)&0xF))
Jeej 0:95b73d0b37b7 59 #define KAL_COM_FLOWID(id) (((id)>>4)&0x7)
Jeej 0:95b73d0b37b7 60 #define KAL_COM_FLOWID_REDIRECT 0x80
Jeej 0:95b73d0b37b7 61
Jeej 0:95b73d0b37b7 62 //======================================================================
Jeej 0:95b73d0b37b7 63 // wizzi_com_flow_t
Jeej 0:95b73d0b37b7 64 //----------------------------------------------------------------------
Jeej 0:95b73d0b37b7 65 // Enumerator of serial flows
Jeej 0:95b73d0b37b7 66 //======================================================================
Jeej 0:95b73d0b37b7 67 typedef enum
Jeej 0:95b73d0b37b7 68 {
Jeej 0:95b73d0b37b7 69 // Default printf type
Jeej 0:95b73d0b37b7 70 KAL_COM_FLOW_PRINTF = KAL_COM_FLOW(KAL_COM_FLOWID_TRC,0),
Jeej 0:95b73d0b37b7 71 // Substitute the string by a codeword
Jeej 0:95b73d0b37b7 72 // interpreted by the PC com tool
Jeej 0:95b73d0b37b7 73 KAL_COM_FLOW_PRINTF_COMPRESSED = KAL_COM_FLOW(KAL_COM_FLOWID_TRC,1),
Jeej 0:95b73d0b37b7 74 // Display the payload as hex data
Jeej 0:95b73d0b37b7 75 KAL_COM_FLOW_PRINT_HEX = KAL_COM_FLOW(KAL_COM_FLOWID_TRC,2),
Jeej 0:95b73d0b37b7 76
Jeej 0:95b73d0b37b7 77 // AT command
Jeej 0:95b73d0b37b7 78 KAL_COM_FLOW_AT_CMD = KAL_COM_FLOW(KAL_COM_FLOWID_ALP,0),
Jeej 0:95b73d0b37b7 79 // AT command response
Jeej 0:95b73d0b37b7 80 KAL_COM_FLOW_AT_RESP = KAL_COM_FLOW(KAL_COM_FLOWID_ALP,1),
Jeej 0:95b73d0b37b7 81 // AT unsolicited message
Jeej 0:95b73d0b37b7 82 KAL_COM_FLOW_AT_UNS = KAL_COM_FLOW(KAL_COM_FLOWID_ALP,2),
Jeej 0:95b73d0b37b7 83 // AT unsolicited error
Jeej 0:95b73d0b37b7 84 KAL_COM_FLOW_AT_ERR = KAL_COM_FLOW(KAL_COM_FLOWID_ALP,3),
Jeej 0:95b73d0b37b7 85
Jeej 0:95b73d0b37b7 86 // Remote Commands
Jeej 0:95b73d0b37b7 87 KAL_COM_FLOW_CMD = KAL_COM_FLOW(KAL_COM_FLOWID_CMD,0),
Jeej 0:95b73d0b37b7 88
Jeej 0:95b73d0b37b7 89 // Remote System reset
Jeej 0:95b73d0b37b7 90 KAL_COM_FLOW_SYS_RST = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,0),
Jeej 0:95b73d0b37b7 91 // Button Emulator
Jeej 0:95b73d0b37b7 92 KAL_COM_FLOW_SYS_BUTTON = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,1),
Jeej 0:95b73d0b37b7 93 // Dump Debug parameters
Jeej 0:95b73d0b37b7 94 KAL_COM_FLOW_SYS_INFO = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,2),
Jeej 0:95b73d0b37b7 95 // CUP signalisation
Jeej 0:95b73d0b37b7 96 KAL_COM_FLOW_SYS_CUP = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,3),
Jeej 0:95b73d0b37b7 97 // Ping distant COM
Jeej 0:95b73d0b37b7 98 KAL_COM_FLOW_SYS_PING = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,4),
Jeej 0:95b73d0b37b7 99 // Pong from distant COM
Jeej 0:95b73d0b37b7 100 KAL_COM_FLOW_SYS_PONG = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,5),
Jeej 0:95b73d0b37b7 101 // Enable system config from distant COM
Jeej 0:95b73d0b37b7 102 KAL_COM_FLOW_SYS_CFG = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,6),
Jeej 0:95b73d0b37b7 103 // Configure Output Trace level from distant COM
Jeej 0:95b73d0b37b7 104 KAL_COM_FLOW_SYS_TLEV = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,7),
Jeej 0:95b73d0b37b7 105 // Configure COM port redirection
Jeej 0:95b73d0b37b7 106 KAL_COM_FLOW_SYS_REDIR = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,8),
Jeej 0:95b73d0b37b7 107 // Flow control signalling
Jeej 0:95b73d0b37b7 108 KAL_COM_FLOW_SYS_XON = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,9),
Jeej 0:95b73d0b37b7 109 KAL_COM_FLOW_SYS_XOFF = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,10),
Jeej 0:95b73d0b37b7 110 KAL_COM_FLOW_SYS_XACK = KAL_COM_FLOW(KAL_COM_FLOWID_SYS,11),
Jeej 0:95b73d0b37b7 111
Jeej 0:95b73d0b37b7 112 // File System Command/Response
Jeej 0:95b73d0b37b7 113 KAL_COM_FLOW_FS_CMD = KAL_COM_FLOW(KAL_COM_FLOWID_FS,0),
Jeej 0:95b73d0b37b7 114 KAL_COM_FLOW_FS_RESP = KAL_COM_FLOW(KAL_COM_FLOWID_FS,1),
Jeej 0:95b73d0b37b7 115
Jeej 0:95b73d0b37b7 116 } wizzi_com_flow_t;
Jeej 0:95b73d0b37b7 117
Jeej 0:95b73d0b37b7 118
Jeej 0:95b73d0b37b7 119
Jeej 0:95b73d0b37b7 120
Jeej 0:95b73d0b37b7 121 enum {
Jeej 0:95b73d0b37b7 122 SEARCH_HEADER,
Jeej 0:95b73d0b37b7 123 PARSE_HEADER,
Jeej 0:95b73d0b37b7 124 SEARCH_BODY,
Jeej 0:95b73d0b37b7 125 PARSE_BODY,
Jeej 0:95b73d0b37b7 126 };
Jeej 0:95b73d0b37b7 127
Jeej 0:95b73d0b37b7 128 void wizzi_com_rx_thread();
Jeej 0:95b73d0b37b7 129 void wizzi_com_tx_thread();
Jeej 0:95b73d0b37b7 130
Jeej 0:95b73d0b37b7 131 const uint8_t g_type_to_flow[WIZZICOM_PKT_QTY] = {
Jeej 0:95b73d0b37b7 132 // Default printf type
Jeej 0:95b73d0b37b7 133 KAL_COM_FLOW_PRINTF,
Jeej 0:95b73d0b37b7 134 // Substitute the string by a codeword
Jeej 0:95b73d0b37b7 135 // interpreted by the PC com tool
Jeej 0:95b73d0b37b7 136 KAL_COM_FLOW_PRINTF_COMPRESSED,
Jeej 0:95b73d0b37b7 137 // Display the payload as hex data
Jeej 0:95b73d0b37b7 138 KAL_COM_FLOW_PRINT_HEX,
Jeej 0:95b73d0b37b7 139
Jeej 0:95b73d0b37b7 140 // AT command
Jeej 0:95b73d0b37b7 141 KAL_COM_FLOW_AT_CMD,
Jeej 0:95b73d0b37b7 142 // AT command response
Jeej 0:95b73d0b37b7 143 KAL_COM_FLOW_AT_RESP,
Jeej 0:95b73d0b37b7 144 // AT unsolicited message
Jeej 0:95b73d0b37b7 145 KAL_COM_FLOW_AT_UNS,
Jeej 0:95b73d0b37b7 146 // AT unsolicited error
Jeej 0:95b73d0b37b7 147 KAL_COM_FLOW_AT_ERR,
Jeej 0:95b73d0b37b7 148
Jeej 0:95b73d0b37b7 149 // Remote Commands
Jeej 0:95b73d0b37b7 150 KAL_COM_FLOW_CMD,
Jeej 0:95b73d0b37b7 151
Jeej 0:95b73d0b37b7 152 // Remote System reset
Jeej 0:95b73d0b37b7 153 KAL_COM_FLOW_SYS_RST,
Jeej 0:95b73d0b37b7 154 // Button Emulator
Jeej 0:95b73d0b37b7 155 KAL_COM_FLOW_SYS_BUTTON,
Jeej 0:95b73d0b37b7 156 // Dump Debug parameters
Jeej 0:95b73d0b37b7 157 KAL_COM_FLOW_SYS_INFO,
Jeej 0:95b73d0b37b7 158 // CUP signalisation
Jeej 0:95b73d0b37b7 159 KAL_COM_FLOW_SYS_CUP,
Jeej 0:95b73d0b37b7 160 // Ping distant COM
Jeej 0:95b73d0b37b7 161 KAL_COM_FLOW_SYS_PING,
Jeej 0:95b73d0b37b7 162 // Pong from distant COM
Jeej 0:95b73d0b37b7 163 KAL_COM_FLOW_SYS_PONG,
Jeej 0:95b73d0b37b7 164 // Enable system config from distant COM
Jeej 0:95b73d0b37b7 165 KAL_COM_FLOW_SYS_CFG,
Jeej 0:95b73d0b37b7 166 // Configure Output Trace level from distant COM
Jeej 0:95b73d0b37b7 167 KAL_COM_FLOW_SYS_TLEV,
Jeej 0:95b73d0b37b7 168 // Configure COM port redirection
Jeej 0:95b73d0b37b7 169 KAL_COM_FLOW_SYS_REDIR,
Jeej 0:95b73d0b37b7 170 // Flow control signalling
Jeej 0:95b73d0b37b7 171 KAL_COM_FLOW_SYS_XON,
Jeej 0:95b73d0b37b7 172 KAL_COM_FLOW_SYS_XOFF,
Jeej 0:95b73d0b37b7 173 KAL_COM_FLOW_SYS_XACK,
Jeej 0:95b73d0b37b7 174
Jeej 0:95b73d0b37b7 175 // File System Command/Response
Jeej 0:95b73d0b37b7 176 KAL_COM_FLOW_FS_CMD,
Jeej 0:95b73d0b37b7 177 KAL_COM_FLOW_FS_RESP
Jeej 0:95b73d0b37b7 178 };
Jeej 0:95b73d0b37b7 179
Jeej 0:95b73d0b37b7 180 WizziCom::WizziCom(PinName tx, PinName rx, PinName irq_out, PinName irq_in) :
Jeej 0:95b73d0b37b7 181 _data_parsing(0),
Jeej 0:95b73d0b37b7 182 _irq_in_int(0),
Jeej 0:95b73d0b37b7 183 _rx_thread(osPriorityRealtime, 512, NULL),
Jeej 0:95b73d0b37b7 184 _tx_thread(osPriorityHigh, 512, NULL),
Jeej 0:95b73d0b37b7 185 _callback_thread(osPriorityLow, 512, NULL)
Jeej 0:95b73d0b37b7 186 {
Jeej 0:95b73d0b37b7 187 _state = SEARCH_HEADER;
Jeej 0:95b73d0b37b7 188 _skipped_bytes = 0;
Jeej 0:95b73d0b37b7 189 _tx_seq = 0;
Jeej 0:95b73d0b37b7 190 _rx_seq = 0;
Jeej 0:95b73d0b37b7 191
Jeej 0:95b73d0b37b7 192 memset(_callback, 0, sizeof(_callback));
Jeej 0:95b73d0b37b7 193
Jeej 0:95b73d0b37b7 194 _serial = new RawSerial(tx, rx, 115200);
Jeej 0:95b73d0b37b7 195 _serial->format(8, SerialBase::None, 1);
Jeej 0:95b73d0b37b7 196 _serial->attach(callback(this, &WizziCom::_rx_isr), Serial::RxIrq);
Jeej 0:95b73d0b37b7 197
Jeej 0:95b73d0b37b7 198 _irq_out = (irq_out != NC)? new DigitalOut(irq_out) : NULL;
Jeej 0:95b73d0b37b7 199
Jeej 0:95b73d0b37b7 200 if (irq_in != NC)
Jeej 0:95b73d0b37b7 201 {
Jeej 0:95b73d0b37b7 202 _irq_in = new InterruptIn(irq_in);
Jeej 0:95b73d0b37b7 203 _irq_in->rise(callback(this, &WizziCom::_irq_in_isr));
Jeej 0:95b73d0b37b7 204 }
Jeej 0:95b73d0b37b7 205 else
Jeej 0:95b73d0b37b7 206 {
Jeej 0:95b73d0b37b7 207 _irq_in = NULL;
Jeej 0:95b73d0b37b7 208 }
Jeej 0:95b73d0b37b7 209
Jeej 0:95b73d0b37b7 210 osStatus err = _rx_thread.start(callback(this, &WizziCom::_thread_rx));
Jeej 0:95b73d0b37b7 211 ASSERT(err == osOK, "Failed to start WizziCom _thread_rx (err: %d)\r\n", err);
Jeej 0:95b73d0b37b7 212
Jeej 0:95b73d0b37b7 213 err = _tx_thread.start(callback(this, &WizziCom::_thread_tx));
Jeej 0:95b73d0b37b7 214 ASSERT(err == osOK, "Failed to start WizziCom _thread_tx (err: %d)\r\n", err);
Jeej 0:95b73d0b37b7 215
Jeej 0:95b73d0b37b7 216 err = _callback_thread.start(callback(this, &WizziCom::_thread_callback));
Jeej 0:95b73d0b37b7 217 ASSERT(err == osOK, "Failed to start WizziCom _thread_callback (err: %d)\r\n", err);
Jeej 0:95b73d0b37b7 218 }
Jeej 0:95b73d0b37b7 219
Jeej 0:95b73d0b37b7 220 WizziCom::~WizziCom()
Jeej 0:95b73d0b37b7 221 {
Jeej 0:95b73d0b37b7 222 _rx_thread.terminate();
Jeej 0:95b73d0b37b7 223 _tx_thread.terminate();
Jeej 0:95b73d0b37b7 224 _callback_thread.terminate();
Jeej 0:95b73d0b37b7 225 delete _serial;
Jeej 0:95b73d0b37b7 226 delete _irq_out;
Jeej 0:95b73d0b37b7 227 delete _irq_in;
Jeej 0:95b73d0b37b7 228 }
Jeej 0:95b73d0b37b7 229
Jeej 0:95b73d0b37b7 230 void WizziCom::attach(WizziComCallback function, WizziComPacketType packet_type)
Jeej 0:95b73d0b37b7 231 {
Jeej 0:95b73d0b37b7 232 _callback[packet_type] = callback(function);
Jeej 0:95b73d0b37b7 233 }
Jeej 0:95b73d0b37b7 234
Jeej 0:95b73d0b37b7 235 void WizziCom::reset(void)
Jeej 0:95b73d0b37b7 236 {
Jeej 0:95b73d0b37b7 237 COM_FPRINT("\r\n");
Jeej 0:95b73d0b37b7 238
Jeej 0:95b73d0b37b7 239 _serial->attach(NULL, Serial::RxIrq);
Jeej 0:95b73d0b37b7 240
Jeej 0:95b73d0b37b7 241 _state = SEARCH_HEADER;
Jeej 0:95b73d0b37b7 242 _skipped_bytes = 0;
Jeej 0:95b73d0b37b7 243 _tx_seq = 0;
Jeej 0:95b73d0b37b7 244 _rx_seq = 0;
Jeej 0:95b73d0b37b7 245
Jeej 0:95b73d0b37b7 246 _rx_buf.reset();
Jeej 0:95b73d0b37b7 247
Jeej 0:95b73d0b37b7 248 _serial->attach(callback(this, &WizziCom::_rx_isr), Serial::RxIrq);
Jeej 0:95b73d0b37b7 249 }
Jeej 0:95b73d0b37b7 250
Jeej 0:95b73d0b37b7 251 void WizziCom::send(WizziComPacketType type, uint8_t length, uint8_t* data)
Jeej 0:95b73d0b37b7 252 {
Jeej 0:95b73d0b37b7 253 wizzi_com_tx_msg_t msg;
Jeej 0:95b73d0b37b7 254
Jeej 0:95b73d0b37b7 255 msg.id = g_type_to_flow[type];
Jeej 0:95b73d0b37b7 256 msg.pbuf = data;
Jeej 0:95b73d0b37b7 257 msg.plen = length;
Jeej 0:95b73d0b37b7 258 msg.alen = 0;
Jeej 0:95b73d0b37b7 259
Jeej 0:95b73d0b37b7 260 _post_msg(&msg);
Jeej 0:95b73d0b37b7 261 }
Jeej 0:95b73d0b37b7 262
Jeej 0:95b73d0b37b7 263 void WizziCom::send(WizziComPacket_t* packet)
Jeej 0:95b73d0b37b7 264 {
Jeej 0:95b73d0b37b7 265 wizzi_com_tx_msg_t msg;
Jeej 0:95b73d0b37b7 266
Jeej 0:95b73d0b37b7 267 msg.id = g_type_to_flow[packet->type];
Jeej 0:95b73d0b37b7 268 msg.pbuf = packet->data;
Jeej 0:95b73d0b37b7 269 msg.plen = packet->length;
Jeej 0:95b73d0b37b7 270 msg.alen = 0;
Jeej 0:95b73d0b37b7 271
Jeej 0:95b73d0b37b7 272 _post_msg(&msg);
Jeej 0:95b73d0b37b7 273
Jeej 0:95b73d0b37b7 274 FREE(packet);
Jeej 0:95b73d0b37b7 275 }
Jeej 0:95b73d0b37b7 276
Jeej 0:95b73d0b37b7 277
Jeej 0:95b73d0b37b7 278 /**
Jeej 0:95b73d0b37b7 279 Serial Rx Interrupt Service Routine.
Jeej 0:95b73d0b37b7 280 Add recevied bytes to the RX buffer.
Jeej 0:95b73d0b37b7 281
Jeej 0:95b73d0b37b7 282 @param void
Jeej 0:95b73d0b37b7 283 @return void
Jeej 0:95b73d0b37b7 284 */
Jeej 0:95b73d0b37b7 285 void WizziCom::_rx_isr()
Jeej 0:95b73d0b37b7 286 {
Jeej 0:95b73d0b37b7 287 // Loop just in case more than one character is in UART's receive FIFO buffer
Jeej 0:95b73d0b37b7 288 while (_serial->readable())
Jeej 0:95b73d0b37b7 289 {
Jeej 0:95b73d0b37b7 290 _rx_buf.push(_serial->getc());
Jeej 0:95b73d0b37b7 291 //PRINT("-");
Jeej 0:95b73d0b37b7 292 }
Jeej 0:95b73d0b37b7 293
Jeej 0:95b73d0b37b7 294 // unlock data parsing thread
Jeej 0:95b73d0b37b7 295 if (_state == SEARCH_HEADER && _rx_buf.available_data() >= KAL_COM_HEADER_LEN)
Jeej 0:95b73d0b37b7 296 {
Jeej 0:95b73d0b37b7 297 _state = PARSE_HEADER;
Jeej 0:95b73d0b37b7 298 _data_parsing.release();
Jeej 0:95b73d0b37b7 299 }
Jeej 0:95b73d0b37b7 300 else if (_state == SEARCH_BODY && _rx_buf.available_data() >= _msg.blen)
Jeej 0:95b73d0b37b7 301 {
Jeej 0:95b73d0b37b7 302 _state = PARSE_BODY;
Jeej 0:95b73d0b37b7 303 _data_parsing.release();
Jeej 0:95b73d0b37b7 304 }
Jeej 0:95b73d0b37b7 305 }
Jeej 0:95b73d0b37b7 306
Jeej 0:95b73d0b37b7 307 /**
Jeej 0:95b73d0b37b7 308 CTS pin Interrupt Service Routine.
Jeej 0:95b73d0b37b7 309 For flow control (not yet inplemented)
Jeej 0:95b73d0b37b7 310
Jeej 0:95b73d0b37b7 311 @param void
Jeej 0:95b73d0b37b7 312 @return void
Jeej 0:95b73d0b37b7 313 */
Jeej 0:95b73d0b37b7 314 void WizziCom::_irq_in_isr()
Jeej 0:95b73d0b37b7 315 {
Jeej 0:95b73d0b37b7 316 //PRINT("IRQ_IN_ISR\r\n");
Jeej 0:95b73d0b37b7 317 //_irq_in_int->release();
Jeej 0:95b73d0b37b7 318 }
Jeej 0:95b73d0b37b7 319
Jeej 0:95b73d0b37b7 320 /**
Jeej 0:95b73d0b37b7 321 Wakes-up modem and send data throught Serial.
Jeej 0:95b73d0b37b7 322
Jeej 0:95b73d0b37b7 323 @param const uint8_t* Pointer to data buffer
Jeej 0:95b73d0b37b7 324 @param int Data length
Jeej 0:95b73d0b37b7 325 @return void
Jeej 0:95b73d0b37b7 326 */
Jeej 0:95b73d0b37b7 327 void WizziCom::_send_raw(wizzi_com_tx_buf_t* tx_buf)
Jeej 0:95b73d0b37b7 328 {
Jeej 0:95b73d0b37b7 329 COM_FPRINT("\r\n");
Jeej 0:95b73d0b37b7 330
Jeej 0:95b73d0b37b7 331 COM_DPRINT("<-- (%02d) %d\r\n", _flow_to_type(tx_buf->buf[4]), (tx_buf->len - KAL_COM_HEADER_LEN));
Jeej 0:95b73d0b37b7 332
Jeej 0:95b73d0b37b7 333 if (_irq_out)
Jeej 0:95b73d0b37b7 334 {
Jeej 0:95b73d0b37b7 335 *(_irq_out) = 1;
Jeej 0:95b73d0b37b7 336 Thread::wait(3);
Jeej 0:95b73d0b37b7 337 }
Jeej 0:95b73d0b37b7 338
Jeej 0:95b73d0b37b7 339 for (uint32_t i=0 ; i<tx_buf->len ; i++)
Jeej 0:95b73d0b37b7 340 {
Jeej 0:95b73d0b37b7 341 _serial->putc(tx_buf->buf[i]);
Jeej 0:95b73d0b37b7 342 }
Jeej 0:95b73d0b37b7 343
Jeej 0:95b73d0b37b7 344 if (_irq_out)
Jeej 0:95b73d0b37b7 345 {
Jeej 0:95b73d0b37b7 346 // Important to not release the ressource too soon
Jeej 0:95b73d0b37b7 347 Thread::wait(2);
Jeej 0:95b73d0b37b7 348 *(_irq_out) = 0;
Jeej 0:95b73d0b37b7 349 }
Jeej 0:95b73d0b37b7 350 }
Jeej 0:95b73d0b37b7 351
Jeej 0:95b73d0b37b7 352 void WizziCom::_sys_xack(void)
Jeej 0:95b73d0b37b7 353 {
Jeej 0:95b73d0b37b7 354 send(WizziComPacketSysXack, 0, NULL);
Jeej 0:95b73d0b37b7 355 }
Jeej 0:95b73d0b37b7 356
Jeej 0:95b73d0b37b7 357 // Formats to send packet throught Serial.
Jeej 0:95b73d0b37b7 358 wizzi_com_tx_buf_t* WizziCom::_new_msg(wizzi_com_tx_msg_t* msg)
Jeej 0:95b73d0b37b7 359 {
Jeej 0:95b73d0b37b7 360 uint8_t len = KAL_COM_HEADER_LEN + msg->alen + msg->plen;
Jeej 0:95b73d0b37b7 361 COM_FPRINT("(len:%d)\r\n", len);
Jeej 0:95b73d0b37b7 362
Jeej 0:95b73d0b37b7 363 wizzi_com_tx_buf_t* tx_buf = (wizzi_com_tx_buf_t*)MALLOC(sizeof(wizzi_com_tx_buf_t) - 1 + len);
Jeej 0:95b73d0b37b7 364
Jeej 0:95b73d0b37b7 365 // construct serial header
Jeej 0:95b73d0b37b7 366 // concatenate and update tx_seq ID
Jeej 0:95b73d0b37b7 367 uint8_t* p = tx_buf->buf;
Jeej 0:95b73d0b37b7 368 uint8_t* t = p;
Jeej 0:95b73d0b37b7 369 *p++ = (uint8_t)KAL_COM_SYNC_BYTE_0;
Jeej 0:95b73d0b37b7 370 *p++ = (uint8_t)KAL_COM_SYNC_BYTE_1;
Jeej 0:95b73d0b37b7 371 *p++ = (uint8_t)msg->alen + msg->plen;
Jeej 0:95b73d0b37b7 372 *p++ = (uint8_t)_tx_seq++;
Jeej 0:95b73d0b37b7 373 *p++ = (uint8_t)msg->id;
Jeej 0:95b73d0b37b7 374
Jeej 0:95b73d0b37b7 375 // copy payload and parameters
Jeej 0:95b73d0b37b7 376 memcpy(p, msg->pbuf, msg->plen);
Jeej 0:95b73d0b37b7 377 p += msg->plen;
Jeej 0:95b73d0b37b7 378 memcpy(p, msg->abuf, msg->alen);
Jeej 0:95b73d0b37b7 379 p += msg->alen;
Jeej 0:95b73d0b37b7 380
Jeej 0:95b73d0b37b7 381 tx_buf->len = (uint32_t)(p - t);
Jeej 0:95b73d0b37b7 382
Jeej 0:95b73d0b37b7 383 ASSERT(tx_buf->len == len, "New msg wrong length %d expected %d\r\n", tx_buf->len, len);
Jeej 0:95b73d0b37b7 384
Jeej 0:95b73d0b37b7 385 return tx_buf;
Jeej 0:95b73d0b37b7 386 }
Jeej 0:95b73d0b37b7 387
Jeej 0:95b73d0b37b7 388 void WizziCom::_post_msg(wizzi_com_tx_msg_t* msg)
Jeej 0:95b73d0b37b7 389 {
Jeej 0:95b73d0b37b7 390 COM_FPRINT("\r\n");
Jeej 0:95b73d0b37b7 391
Jeej 0:95b73d0b37b7 392 ASSERT(_tx_queue.put(_new_msg(msg)) == osOK, "WizziCom TX queue full!\r\n");
Jeej 0:95b73d0b37b7 393 }
Jeej 0:95b73d0b37b7 394
Jeej 0:95b73d0b37b7 395 uint8_t WizziCom::_flow_to_type(uint8_t flow_id)
Jeej 0:95b73d0b37b7 396 {
Jeej 0:95b73d0b37b7 397 // Get packet type from flow_id
Jeej 0:95b73d0b37b7 398 uint8_t packet_type = 0;
Jeej 0:95b73d0b37b7 399 while ((g_type_to_flow[packet_type] != flow_id) && (packet_type < WIZZICOM_PKT_QTY))
Jeej 0:95b73d0b37b7 400 {
Jeej 0:95b73d0b37b7 401 packet_type++;
Jeej 0:95b73d0b37b7 402 }
Jeej 0:95b73d0b37b7 403 return packet_type;
Jeej 0:95b73d0b37b7 404 }
Jeej 0:95b73d0b37b7 405
Jeej 0:95b73d0b37b7 406 void WizziCom::_new_pkt(WizziComPacket_t* packet)
Jeej 0:95b73d0b37b7 407 {
Jeej 0:95b73d0b37b7 408 //COM_COM_FPRINT("\r\n");
Jeej 0:95b73d0b37b7 409
Jeej 0:95b73d0b37b7 410 COM_DPRINT("--> (%02d) %d\r\n", packet->type, packet->length);
Jeej 0:95b73d0b37b7 411
Jeej 0:95b73d0b37b7 412 // Distribute packet types to callbacks
Jeej 0:95b73d0b37b7 413 switch (packet->type)
Jeej 0:95b73d0b37b7 414 {
Jeej 0:95b73d0b37b7 415 case WizziComPacketSysXon:
Jeej 0:95b73d0b37b7 416 FREE(packet);
Jeej 0:95b73d0b37b7 417 COM_DPRINT("XON\r\n");
Jeej 0:95b73d0b37b7 418 _tx_thread.signal_set(XON_SIGNAL);
Jeej 0:95b73d0b37b7 419 break;
Jeej 0:95b73d0b37b7 420 case WizziComPacketSysXoff:
Jeej 0:95b73d0b37b7 421 FREE(packet);
Jeej 0:95b73d0b37b7 422 COM_DPRINT("XOFF\r\n");
Jeej 0:95b73d0b37b7 423 _sys_xack();
Jeej 0:95b73d0b37b7 424 break;
Jeej 0:95b73d0b37b7 425 default:
Jeej 0:95b73d0b37b7 426 ASSERT(_rx_queue.put(packet) == osOK, "WizziCom RX queue full!\r\n");
Jeej 0:95b73d0b37b7 427 break;
Jeej 0:95b73d0b37b7 428 }
Jeej 0:95b73d0b37b7 429 }
Jeej 0:95b73d0b37b7 430
Jeej 0:95b73d0b37b7 431
Jeej 0:95b73d0b37b7 432 /**
Jeej 0:95b73d0b37b7 433 Reads the Rx buffer, parses the packets
Jeej 0:95b73d0b37b7 434
Jeej 0:95b73d0b37b7 435 @param void
Jeej 0:95b73d0b37b7 436 @return void
Jeej 0:95b73d0b37b7 437 */
Jeej 0:95b73d0b37b7 438 void WizziCom::_parse_packet_header(void)
Jeej 0:95b73d0b37b7 439 {
Jeej 0:95b73d0b37b7 440 COM_FPRINT("\r\n");
Jeej 0:95b73d0b37b7 441
Jeej 0:95b73d0b37b7 442 uint8_t header[KAL_COM_HEADER_LEN];
Jeej 0:95b73d0b37b7 443 uint8_t seqnum;
Jeej 0:95b73d0b37b7 444
Jeej 0:95b73d0b37b7 445 ASSERT(_rx_buf.available_data() >= KAL_COM_HEADER_LEN, "Not enough data for header\r\n");
Jeej 0:95b73d0b37b7 446
Jeej 0:95b73d0b37b7 447 _skipped_bytes = 0;
Jeej 0:95b73d0b37b7 448
Jeej 0:95b73d0b37b7 449 header[0] = _rx_buf.pop();
Jeej 0:95b73d0b37b7 450
Jeej 0:95b73d0b37b7 451 while (_rx_buf.available_data() >= KAL_COM_HEADER_LEN - 1)
Jeej 0:95b73d0b37b7 452 {
Jeej 0:95b73d0b37b7 453 header[1] = _rx_buf.pop();
Jeej 0:95b73d0b37b7 454
Jeej 0:95b73d0b37b7 455 // Check sync bytes
Jeej 0:95b73d0b37b7 456 if(KAL_COM_SYNC_BYTE_0 == header[0] && KAL_COM_SYNC_BYTE_1 == header[1])
Jeej 0:95b73d0b37b7 457 {
Jeej 0:95b73d0b37b7 458 // Copy header
Jeej 0:95b73d0b37b7 459 _rx_buf.get(&header[2], KAL_COM_HEADER_LEN - 2);
Jeej 0:95b73d0b37b7 460
Jeej 0:95b73d0b37b7 461 // Fill temp header
Jeej 0:95b73d0b37b7 462 _msg.blen = header[2];
Jeej 0:95b73d0b37b7 463 seqnum = header[3];
Jeej 0:95b73d0b37b7 464 _msg.id = _flow_to_type(header[4]);
Jeej 0:95b73d0b37b7 465
Jeej 0:95b73d0b37b7 466 // Update seqnum
Jeej 0:95b73d0b37b7 467 WARNING(_rx_seq == seqnum, "COM Bad seqnum expected:%d got:%d\r\n", _rx_seq, seqnum);
Jeej 0:95b73d0b37b7 468 _rx_seq = seqnum + 1;
Jeej 0:95b73d0b37b7 469
Jeej 0:95b73d0b37b7 470 // search for body
Jeej 0:95b73d0b37b7 471 _state = SEARCH_BODY;
Jeej 0:95b73d0b37b7 472
Jeej 0:95b73d0b37b7 473 // Start parsing if data is already available
Jeej 0:95b73d0b37b7 474 if (_rx_buf.available_data() >= _msg.blen)
Jeej 0:95b73d0b37b7 475 {
Jeej 0:95b73d0b37b7 476 _state = PARSE_BODY;
Jeej 0:95b73d0b37b7 477 _data_parsing.release();
Jeej 0:95b73d0b37b7 478 }
Jeej 0:95b73d0b37b7 479
Jeej 0:95b73d0b37b7 480 //COM_DPRINT("COM header found (id: %02X seq: %d body: %d/%d bytes)\r\n", _msg.id, seqnum, _rx_buf.available_data(), _msg.blen);
Jeej 0:95b73d0b37b7 481 break;
Jeej 0:95b73d0b37b7 482 }
Jeej 0:95b73d0b37b7 483 else
Jeej 0:95b73d0b37b7 484 {
Jeej 0:95b73d0b37b7 485 // Shift by 1 byte
Jeej 0:95b73d0b37b7 486 //WARNING(false, "COM Skipped byte 0x%02X.\r\n", header[0]);
Jeej 0:95b73d0b37b7 487 _skipped_bytes++;
Jeej 0:95b73d0b37b7 488 header[0] = header[1];
Jeej 0:95b73d0b37b7 489 }
Jeej 0:95b73d0b37b7 490 }
Jeej 0:95b73d0b37b7 491
Jeej 0:95b73d0b37b7 492 WARNING(!_skipped_bytes, "COM Skipped %d bytes.\r\n", _skipped_bytes);
Jeej 0:95b73d0b37b7 493 }
Jeej 0:95b73d0b37b7 494
Jeej 0:95b73d0b37b7 495 /**
Jeej 0:95b73d0b37b7 496 Reads the Rx buffer, parses the packets
Jeej 0:95b73d0b37b7 497
Jeej 0:95b73d0b37b7 498 @param void
Jeej 0:95b73d0b37b7 499 @return void
Jeej 0:95b73d0b37b7 500 */
Jeej 0:95b73d0b37b7 501 void WizziCom::_parse_packet_body(void)
Jeej 0:95b73d0b37b7 502 {
Jeej 0:95b73d0b37b7 503 ASSERT(_rx_buf.available_data() >= _msg.blen, "Not enough data for body\r\n");
Jeej 0:95b73d0b37b7 504
Jeej 0:95b73d0b37b7 505 if (_callback[_msg.id] || _callback[WizziComPacketOther])
Jeej 0:95b73d0b37b7 506 {
Jeej 0:95b73d0b37b7 507 //COM_DPRINT("COM body found (%d bytes)\r\n", _msg.blen);
Jeej 0:95b73d0b37b7 508
Jeej 0:95b73d0b37b7 509 WizziComPacket_t* pkt = (WizziComPacket_t*)MALLOC(sizeof(WizziComPacket_t) - 1 + _msg.blen);
Jeej 0:95b73d0b37b7 510
Jeej 0:95b73d0b37b7 511 // copy data to buffer
Jeej 0:95b73d0b37b7 512 pkt->length = _msg.blen;
Jeej 0:95b73d0b37b7 513 pkt->type = _msg.id;
Jeej 0:95b73d0b37b7 514
Jeej 0:95b73d0b37b7 515 if (_msg.blen)
Jeej 0:95b73d0b37b7 516 {
Jeej 0:95b73d0b37b7 517 _rx_buf.get(pkt->data, _msg.blen);
Jeej 0:95b73d0b37b7 518 }
Jeej 0:95b73d0b37b7 519
Jeej 0:95b73d0b37b7 520 // add packet to queue
Jeej 0:95b73d0b37b7 521 _new_pkt(pkt);
Jeej 0:95b73d0b37b7 522 }
Jeej 0:95b73d0b37b7 523 else
Jeej 0:95b73d0b37b7 524 {
Jeej 0:95b73d0b37b7 525 // Ignore packet
Jeej 0:95b73d0b37b7 526 //COM_DPRINT("Ignore pkt id %02X\r\n", _msg.id);
Jeej 0:95b73d0b37b7 527 if (_msg.blen)
Jeej 0:95b73d0b37b7 528 {
Jeej 0:95b73d0b37b7 529 _rx_buf.get(NULL, _msg.blen);
Jeej 0:95b73d0b37b7 530 }
Jeej 0:95b73d0b37b7 531 }
Jeej 0:95b73d0b37b7 532
Jeej 0:95b73d0b37b7 533 // Seach for next header
Jeej 0:95b73d0b37b7 534 _state = SEARCH_HEADER;
Jeej 0:95b73d0b37b7 535
Jeej 0:95b73d0b37b7 536 // Start parsing if data is already available
Jeej 0:95b73d0b37b7 537 if (_rx_buf.available_data() >= KAL_COM_HEADER_LEN)
Jeej 0:95b73d0b37b7 538 {
Jeej 0:95b73d0b37b7 539 _state = PARSE_HEADER;
Jeej 0:95b73d0b37b7 540 _data_parsing.release();
Jeej 0:95b73d0b37b7 541 }
Jeej 0:95b73d0b37b7 542 }
Jeej 0:95b73d0b37b7 543
Jeej 0:95b73d0b37b7 544 // Thread for calling callbacks
Jeej 0:95b73d0b37b7 545 // Like arg, arg thread is stalled by callbacks but not the parsing thread.
Jeej 0:95b73d0b37b7 546 void WizziCom::_thread_callback(void)
Jeej 0:95b73d0b37b7 547 {
Jeej 0:95b73d0b37b7 548 osEvent evt;
Jeej 0:95b73d0b37b7 549 WizziComPacket_t* packet;
Jeej 0:95b73d0b37b7 550
Jeej 0:95b73d0b37b7 551 COM_FPRINT("(id:0x%08x)\r\n", osThreadGetId());
Jeej 0:95b73d0b37b7 552 while (true)
Jeej 0:95b73d0b37b7 553 {
Jeej 0:95b73d0b37b7 554 // wait for available packet
Jeej 0:95b73d0b37b7 555 evt = _rx_queue.get();
Jeej 0:95b73d0b37b7 556 packet = (evt.status == osEventMessage)? (WizziComPacket_t*)evt.value.p : NULL;
Jeej 0:95b73d0b37b7 557
Jeej 0:95b73d0b37b7 558 if (packet != NULL)
Jeej 0:95b73d0b37b7 559 {
Jeej 0:95b73d0b37b7 560 if (_callback[packet->type])
Jeej 0:95b73d0b37b7 561 {
Jeej 0:95b73d0b37b7 562 _callback[packet->type].call(this, packet);
Jeej 0:95b73d0b37b7 563 }
Jeej 0:95b73d0b37b7 564 else if (_callback[WizziComPacketOther])
Jeej 0:95b73d0b37b7 565 {
Jeej 0:95b73d0b37b7 566 _callback[WizziComPacketOther].call(this, packet);
Jeej 0:95b73d0b37b7 567 }
Jeej 0:95b73d0b37b7 568 else
Jeej 0:95b73d0b37b7 569 {
Jeej 0:95b73d0b37b7 570 EPRINT("Untreated pkt type %d in queue!\r\n", packet->type);
Jeej 0:95b73d0b37b7 571 FREE(packet);
Jeej 0:95b73d0b37b7 572 }
Jeej 0:95b73d0b37b7 573 }
Jeej 0:95b73d0b37b7 574 }
Jeej 0:95b73d0b37b7 575 }
Jeej 0:95b73d0b37b7 576
Jeej 0:95b73d0b37b7 577
Jeej 0:95b73d0b37b7 578 // Thread for parsing packets from RX buffer.
Jeej 0:95b73d0b37b7 579 void WizziCom::_thread_rx(void)
Jeej 0:95b73d0b37b7 580 {
Jeej 0:95b73d0b37b7 581 COM_FPRINT("(id:0x%08x)\r\n", osThreadGetId());
Jeej 0:95b73d0b37b7 582 while (true)
Jeej 0:95b73d0b37b7 583 {
Jeej 0:95b73d0b37b7 584 // wait for data available
Jeej 0:95b73d0b37b7 585 _data_parsing.wait();
Jeej 0:95b73d0b37b7 586
Jeej 0:95b73d0b37b7 587 if (_state == PARSE_HEADER)
Jeej 0:95b73d0b37b7 588 {
Jeej 0:95b73d0b37b7 589 _parse_packet_header();
Jeej 0:95b73d0b37b7 590 }
Jeej 0:95b73d0b37b7 591 else if (_state == PARSE_BODY)
Jeej 0:95b73d0b37b7 592 {
Jeej 0:95b73d0b37b7 593 _parse_packet_body();
Jeej 0:95b73d0b37b7 594 }
Jeej 0:95b73d0b37b7 595 }
Jeej 0:95b73d0b37b7 596 }
Jeej 0:95b73d0b37b7 597
Jeej 0:95b73d0b37b7 598 void WizziCom::_thread_tx(void)
Jeej 0:95b73d0b37b7 599 {
Jeej 0:95b73d0b37b7 600 COM_FPRINT("(id:0x%08x)\r\n", osThreadGetId());
Jeej 0:95b73d0b37b7 601
Jeej 0:95b73d0b37b7 602 wizzi_com_tx_buf_t* msg;
Jeej 0:95b73d0b37b7 603 osEvent evt;
Jeej 0:95b73d0b37b7 604 uint8_t flow_id;
Jeej 0:95b73d0b37b7 605
Jeej 0:95b73d0b37b7 606 while (true)
Jeej 0:95b73d0b37b7 607 {
Jeej 0:95b73d0b37b7 608 // wait for data to send
Jeej 0:95b73d0b37b7 609 evt = _tx_queue.get();
Jeej 0:95b73d0b37b7 610 msg = (evt.status == osEventMessage)? (wizzi_com_tx_buf_t*)evt.value.p : NULL;
Jeej 0:95b73d0b37b7 611
Jeej 0:95b73d0b37b7 612
Jeej 0:95b73d0b37b7 613 // send message
Jeej 0:95b73d0b37b7 614 if (msg != NULL)
Jeej 0:95b73d0b37b7 615 {
Jeej 0:95b73d0b37b7 616 flow_id = msg->buf[4];
Jeej 0:95b73d0b37b7 617
Jeej 0:95b73d0b37b7 618 _send_raw(msg);
Jeej 0:95b73d0b37b7 619 FREE(msg);
Jeej 0:95b73d0b37b7 620
Jeej 0:95b73d0b37b7 621 if (KAL_COM_FLOW_SYS_XACK == flow_id)
Jeej 0:95b73d0b37b7 622 {
Jeej 0:95b73d0b37b7 623 COM_DPRINT("XACK\r\n");
Jeej 0:95b73d0b37b7 624 _tx_thread.signal_wait(XON_SIGNAL);
Jeej 0:95b73d0b37b7 625 }
Jeej 0:95b73d0b37b7 626 }
Jeej 0:95b73d0b37b7 627 }
Jeej 0:95b73d0b37b7 628 }