WizziLab's serial protocol library

Dependents:   modem_ref_helper_for_v5_3_217 modem_ref_helper

Committer:
Jeej
Date:
Tue Aug 20 13:48:15 2019 +0000
Revision:
8:42e00820df36
Parent:
7:45fe755f52bc
Child:
9:0140247bab90
Implemented DMA instead of interrupts.

Who changed what in which revision?

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