Trond Enger / d7a_1x

Fork of d7a_1x by WizziLab

Committer:
Jeej
Date:
Tue Aug 30 17:15:31 2016 +0000
Revision:
44:8ebe6b70f932
Parent:
43:28202405094d
Parent:
42:1578f0480dcb
Child:
45:b85384e7d825
Fuse branches.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jeej 24:a8433b091764 1 #include "mbed.h"
Jeej 24:a8433b091764 2 #include "rtos.h"
Jeej 24:a8433b091764 3 #include "dbg.h"
Jeej 24:a8433b091764 4 #include "d7a_com.h"
Jeej 25:aac250164497 5 #include "d7a_common.h"
Jeej 25:aac250164497 6 #include "d7a_fs.h"
Jeej 25:aac250164497 7 #include "d7a_modem.h"
Jeej 25:aac250164497 8 #include "d7a_sys.h"
Jeej 24:a8433b091764 9
Jeej 34:1311cc53201a 10
Jeej 37:e04613e021f2 11 #define XON_SIGNAL (0x0001 << 0)
Jeej 37:e04613e021f2 12 #define START_SIGNAL (0x0001 << 1)
Jeej 31:ab9bfdbc6b44 13
Jeej 31:ab9bfdbc6b44 14 typedef struct {
Jeej 31:ab9bfdbc6b44 15 uint32_t len;
Jeej 31:ab9bfdbc6b44 16 uint8_t* buf;
Jeej 31:ab9bfdbc6b44 17 } d7a_com_tx_buf_t;
Jeej 30:d775c1409849 18
Jeej 37:e04613e021f2 19 enum {
Jeej 37:e04613e021f2 20 SEARCH_HEADER,
Jeej 37:e04613e021f2 21 PARSE_HEADER,
Jeej 37:e04613e021f2 22 SEARCH_BODY,
Jeej 37:e04613e021f2 23 PARSE_BODY,
Jeej 37:e04613e021f2 24 };
Jeej 30:d775c1409849 25
Jeej 25:aac250164497 26 typedef struct {
Jeej 37:e04613e021f2 27 bool rx_started;
Jeej 37:e04613e021f2 28 bool tx_started;
Jeej 37:e04613e021f2 29
Jeej 37:e04613e021f2 30 uint8_t state;
Jeej 34:1311cc53201a 31
Jeej 25:aac250164497 32 DigitalOut* rts;
Jeej 25:aac250164497 33 InterruptIn* cts;
Jeej 25:aac250164497 34
Jeej 25:aac250164497 35 // RX buffer address
Jeej 25:aac250164497 36 uint8_t* rx_buffer;
Jeej 25:aac250164497 37 // RX buffer size
Jeej 25:aac250164497 38 uint16_t rx_buffer_size;
Jeej 25:aac250164497 39 // Write index in RX buffer
Jeej 25:aac250164497 40 volatile uint16_t write_idx;
Jeej 25:aac250164497 41 // Read index in RX buffer
Jeej 25:aac250164497 42 uint16_t read_idx;
Jeej 25:aac250164497 43 // Number of bytes available in RX buffer
Jeej 25:aac250164497 44 volatile uint16_t data_available;
Jeej 37:e04613e021f2 45 // min data in buffer before parsing body
Jeej 37:e04613e021f2 46 d7a_com_rx_msg_t msg;
Jeej 33:f9a542d3efaa 47 // Number of skipped bytes while parsing
Jeej 33:f9a542d3efaa 48 uint16_t skipped_bytes;
Jeej 33:f9a542d3efaa 49
Jeej 25:aac250164497 50 // Port TX sequence number
Jeej 25:aac250164497 51 uint8_t tx_seq;
Jeej 25:aac250164497 52 // Port RX sequence number
Jeej 25:aac250164497 53 uint8_t rx_seq;
Jeej 25:aac250164497 54 // Response to command maximum time
Jeej 25:aac250164497 55 uint32_t timeout;
Jeej 25:aac250164497 56
Jeej 25:aac250164497 57 // Waiting for data available in RX buffer
Jeej 25:aac250164497 58 Semaphore* data_parsing;
Jeej 25:aac250164497 59 // CTS management
Jeej 25:aac250164497 60 Semaphore* cts_int;
Jeej 25:aac250164497 61
Jeej 25:aac250164497 62 // Data treatment threads
Jeej 31:ab9bfdbc6b44 63 Thread* rx_thread;
Jeej 25:aac250164497 64 Serial* serial;
Jeej 25:aac250164497 65
Jeej 31:ab9bfdbc6b44 66 // Tx Thread
Jeej 31:ab9bfdbc6b44 67 Thread* tx_thread;
Jeej 31:ab9bfdbc6b44 68 Queue<d7a_com_tx_buf_t, 32> tx_queue;
Jeej 31:ab9bfdbc6b44 69
Jeej 34:1311cc53201a 70 Timer tim;
Jeej 34:1311cc53201a 71
Jeej 25:aac250164497 72 } d7a_com_ctx_t;
Jeej 24:a8433b091764 73
Jeej 31:ab9bfdbc6b44 74
Jeej 24:a8433b091764 75 static d7a_com_ctx_t g_com_ctx;
Jeej 24:a8433b091764 76
Jeej 24:a8433b091764 77 /**
Jeej 24:a8433b091764 78 Thread for parsing packets from RX buffer.
Jeej 24:a8433b091764 79
Jeej 24:a8433b091764 80 @param void
Jeej 24:a8433b091764 81 @return void
Jeej 24:a8433b091764 82 */
Jeej 31:ab9bfdbc6b44 83 void d7a_com_rx_thread( void const *p );
Jeej 31:ab9bfdbc6b44 84 void d7a_com_tx_thread( void const *p );
Jeej 31:ab9bfdbc6b44 85
Jeej 24:a8433b091764 86
Jeej 24:a8433b091764 87 /**
Jeej 24:a8433b091764 88 Serial Rx Interrupt Service Routine.
Jeej 24:a8433b091764 89 Add recevied bytes to the RX buffer.
Jeej 24:a8433b091764 90
Jeej 24:a8433b091764 91 @param void
Jeej 24:a8433b091764 92 @return void
Jeej 24:a8433b091764 93 */
Jeej 24:a8433b091764 94 void rx_isr()
Jeej 24:a8433b091764 95 {
Jeej 24:a8433b091764 96 // Loop just in case more than one character is in UART's receive FIFO buffer
Jeej 24:a8433b091764 97 // Stop if buffer full
Jeej 34:1311cc53201a 98 while (g_com_ctx.serial->readable())
Jeej 34:1311cc53201a 99 {
Jeej 34:1311cc53201a 100
Jeej 24:a8433b091764 101 g_com_ctx.rx_buffer[g_com_ctx.write_idx] = g_com_ctx.serial->getc();
Jeej 34:1311cc53201a 102 //PRINT("-");
Jeej 34:1311cc53201a 103
Jeej 42:1578f0480dcb 104 //if (g_com_ctx.rx_started)
Jeej 34:1311cc53201a 105 {
Jeej 34:1311cc53201a 106 g_com_ctx.data_available++;
Jeej 34:1311cc53201a 107
Jeej 34:1311cc53201a 108 g_com_ctx.write_idx = (g_com_ctx.write_idx >= (g_com_ctx.rx_buffer_size-1))? 0 : g_com_ctx.write_idx+1;
Jeej 34:1311cc53201a 109 //g_com_ctx.write_idx = (g_com_ctx.write_idx + 1) % g_com_ctx.rx_buffer_size;
Jeej 42:1578f0480dcb 110
Jeej 42:1578f0480dcb 111 // unlock data parsing thread
Jeej 42:1578f0480dcb 112 if (g_com_ctx.state == SEARCH_HEADER && g_com_ctx.data_available >= KAL_COM_HEADER_LEN)
Jeej 42:1578f0480dcb 113 {
Jeej 42:1578f0480dcb 114 g_com_ctx.state = PARSE_HEADER;
Jeej 42:1578f0480dcb 115 g_com_ctx.data_parsing->release();
Jeej 42:1578f0480dcb 116 }
Jeej 42:1578f0480dcb 117 else if (g_com_ctx.state == SEARCH_BODY && g_com_ctx.data_available >= g_com_ctx.msg.blen)
Jeej 42:1578f0480dcb 118 {
Jeej 42:1578f0480dcb 119 g_com_ctx.state = PARSE_BODY;
Jeej 42:1578f0480dcb 120 g_com_ctx.data_parsing->release();
Jeej 42:1578f0480dcb 121 }
Jeej 34:1311cc53201a 122 }
Jeej 24:a8433b091764 123 }
Jeej 33:f9a542d3efaa 124
Jeej 42:1578f0480dcb 125 ASSERT(g_com_ctx.data_available <= g_com_ctx.rx_buffer_size, "RX Buffer overflow! (%d/%d)\r\n", g_com_ctx.data_available, g_com_ctx.rx_buffer_size);
Jeej 24:a8433b091764 126 }
Jeej 24:a8433b091764 127
Jeej 24:a8433b091764 128 /**
Jeej 24:a8433b091764 129 CTS pin Interrupt Service Routine.
Jeej 24:a8433b091764 130 For flow control (not yet inplemented)
Jeej 24:a8433b091764 131
Jeej 24:a8433b091764 132 @param void
Jeej 24:a8433b091764 133 @return void
Jeej 24:a8433b091764 134 */
Jeej 24:a8433b091764 135 void cts_isr()
Jeej 24:a8433b091764 136 {
Jeej 34:1311cc53201a 137 //PRINT("CTS_INT\r\n");
Jeej 34:1311cc53201a 138 //g_com_ctx.cts_int->release();
Jeej 24:a8433b091764 139 }
Jeej 24:a8433b091764 140
Jeej 26:9f0b9833cac6 141 // D7a_com constructor.
Jeej 26:9f0b9833cac6 142 // Opens a serial port and monitors the input for ALP packets.
Jeej 26:9f0b9833cac6 143 // Pins are those of the host, not the modem:
Jeej 26:9f0b9833cac6 144 // TX-host -> RX-modem
Jeej 26:9f0b9833cac6 145 // RX-host <- TX-modem
Jeej 26:9f0b9833cac6 146 // RTS-host -> CTS-modem
Jeej 26:9f0b9833cac6 147 // CTS-host <- RTS-modem
Jeej 26:9f0b9833cac6 148 void d7a_com_open( const d7a_com_config_t* config )
Jeej 26:9f0b9833cac6 149 {
Jeej 26:9f0b9833cac6 150 FPRINT("\r\n");
Jeej 26:9f0b9833cac6 151
Jeej 37:e04613e021f2 152 g_com_ctx.rx_started = false;
Jeej 37:e04613e021f2 153 g_com_ctx.tx_started = false;
Jeej 37:e04613e021f2 154 g_com_ctx.state = SEARCH_HEADER;
Jeej 26:9f0b9833cac6 155 g_com_ctx.rx_buffer_size = config->rx_buffer_size;
Jeej 26:9f0b9833cac6 156 g_com_ctx.rx_buffer = (uint8_t*)MALLOC(g_com_ctx.rx_buffer_size);
Jeej 26:9f0b9833cac6 157 g_com_ctx.data_available = 0;
Jeej 33:f9a542d3efaa 158 g_com_ctx.skipped_bytes = 0;
Jeej 26:9f0b9833cac6 159 g_com_ctx.write_idx = 0;
Jeej 26:9f0b9833cac6 160 g_com_ctx.read_idx = 0;
Jeej 26:9f0b9833cac6 161 g_com_ctx.tx_seq = 0;
Jeej 26:9f0b9833cac6 162 g_com_ctx.rx_seq = 0;
Jeej 26:9f0b9833cac6 163
Jeej 26:9f0b9833cac6 164 g_com_ctx.serial = new Serial(config->tx, config->rx);
Jeej 26:9f0b9833cac6 165 g_com_ctx.rts = new DigitalOut(config->rts);
Jeej 26:9f0b9833cac6 166 g_com_ctx.cts = new InterruptIn(config->cts);
Jeej 34:1311cc53201a 167 g_com_ctx.data_parsing = new Semaphore(0);
Jeej 34:1311cc53201a 168 g_com_ctx.cts_int = new Semaphore(0);
Jeej 31:ab9bfdbc6b44 169
Jeej 34:1311cc53201a 170 g_com_ctx.cts->rise(&cts_isr);
Jeej 34:1311cc53201a 171
Jeej 26:9f0b9833cac6 172 /* XXX: Unknown bug:
Jeej 26:9f0b9833cac6 173 Baud rate can be found with high error rate (> 4%).
Jeej 26:9f0b9833cac6 174 It is here manualy corrected after an oscilloscope measure.
Jeej 26:9f0b9833cac6 175 Normal Baudrate should be 115200.
Jeej 26:9f0b9833cac6 176 */
Jeej 33:f9a542d3efaa 177 //g_com_ctx.serial->baud(117000); // XXX
Jeej 33:f9a542d3efaa 178 g_com_ctx.serial->baud(115200); // XXX
Jeej 34:1311cc53201a 179 //g_com_ctx.serial->baud(57600); // XXX
Jeej 26:9f0b9833cac6 180 g_com_ctx.serial->format(8, SerialBase::None, 1);
Jeej 26:9f0b9833cac6 181 g_com_ctx.serial->attach(&rx_isr, Serial::RxIrq);
Jeej 30:d775c1409849 182
Jeej 31:ab9bfdbc6b44 183 g_com_ctx.tx_thread = new Thread(d7a_com_tx_thread, NULL, osPriorityHigh, DEFAULT_STACK_SIZE);
Jeej 31:ab9bfdbc6b44 184 g_com_ctx.rx_thread = new Thread(d7a_com_rx_thread, NULL, osPriorityHigh, DEFAULT_STACK_SIZE);
Jeej 26:9f0b9833cac6 185 }
Jeej 26:9f0b9833cac6 186
Jeej 26:9f0b9833cac6 187 // Destructor
Jeej 26:9f0b9833cac6 188 void d7a_com_close()
Jeej 26:9f0b9833cac6 189 {
Jeej 26:9f0b9833cac6 190 FPRINT("\r\n");
Jeej 31:ab9bfdbc6b44 191 g_com_ctx.rx_thread->terminate();
Jeej 31:ab9bfdbc6b44 192 g_com_ctx.tx_thread->terminate();
Jeej 26:9f0b9833cac6 193 delete g_com_ctx.data_parsing;
Jeej 26:9f0b9833cac6 194 delete g_com_ctx.cts_int;
Jeej 26:9f0b9833cac6 195 delete g_com_ctx.serial;
Jeej 26:9f0b9833cac6 196 delete g_com_ctx.rts;
Jeej 26:9f0b9833cac6 197 delete g_com_ctx.cts;
Jeej 26:9f0b9833cac6 198 FREE(g_com_ctx.rx_buffer);
Jeej 26:9f0b9833cac6 199 }
Jeej 26:9f0b9833cac6 200
Jeej 37:e04613e021f2 201 void d7a_com_start_rx(void)
Jeej 37:e04613e021f2 202 {
Jeej 37:e04613e021f2 203 FPRINT("\r\n");
Jeej 37:e04613e021f2 204 g_com_ctx.rx_started = true;
Jeej 37:e04613e021f2 205 g_com_ctx.rx_thread->signal_set(START_SIGNAL);
Jeej 37:e04613e021f2 206 }
Jeej 37:e04613e021f2 207
Jeej 37:e04613e021f2 208 void d7a_com_stop_rx(void)
Jeej 34:1311cc53201a 209 {
Jeej 34:1311cc53201a 210 FPRINT("\r\n");
Jeej 37:e04613e021f2 211 g_com_ctx.rx_started = false;
Jeej 37:e04613e021f2 212 }
Jeej 37:e04613e021f2 213
Jeej 37:e04613e021f2 214 void d7a_com_start_tx(void)
Jeej 37:e04613e021f2 215 {
Jeej 37:e04613e021f2 216 FPRINT("\r\n");
Jeej 37:e04613e021f2 217 g_com_ctx.tx_started = true;
Jeej 37:e04613e021f2 218 g_com_ctx.tx_thread->signal_set(START_SIGNAL);
Jeej 37:e04613e021f2 219 }
Jeej 37:e04613e021f2 220
Jeej 37:e04613e021f2 221 void d7a_com_stop_tx(void)
Jeej 37:e04613e021f2 222 {
Jeej 37:e04613e021f2 223 FPRINT("\r\n");
Jeej 37:e04613e021f2 224 g_com_ctx.tx_started = false;
Jeej 34:1311cc53201a 225 }
Jeej 34:1311cc53201a 226
Jeej 34:1311cc53201a 227 void d7a_com_restart(void)
Jeej 34:1311cc53201a 228 {
Jeej 34:1311cc53201a 229 FPRINT("\r\n");
Jeej 37:e04613e021f2 230 d7a_com_stop_rx();
Jeej 37:e04613e021f2 231 d7a_com_stop_tx();
Jeej 42:1578f0480dcb 232
Jeej 42:1578f0480dcb 233 g_com_ctx.state = SEARCH_HEADER;
Jeej 34:1311cc53201a 234 g_com_ctx.data_available = 0;
Jeej 34:1311cc53201a 235 g_com_ctx.skipped_bytes = 0;
Jeej 34:1311cc53201a 236 g_com_ctx.write_idx = 0;
Jeej 34:1311cc53201a 237 g_com_ctx.read_idx = 0;
Jeej 34:1311cc53201a 238 g_com_ctx.tx_seq = 0;
Jeej 34:1311cc53201a 239 g_com_ctx.rx_seq = 0;
Jeej 34:1311cc53201a 240
Jeej 34:1311cc53201a 241 d7a_com_tx_buf_t* msg;
Jeej 34:1311cc53201a 242 d7a_com_rx_msg_t* pkt;
Jeej 34:1311cc53201a 243 osEvent evt;
Jeej 34:1311cc53201a 244
Jeej 34:1311cc53201a 245 // Flush TX queue
Jeej 34:1311cc53201a 246 do
Jeej 34:1311cc53201a 247 {
Jeej 34:1311cc53201a 248 // wait for data
Jeej 34:1311cc53201a 249 evt = g_com_ctx.tx_queue.get(1);
Jeej 34:1311cc53201a 250 msg = (evt.status == osEventMessage)? (d7a_com_tx_buf_t*)evt.value.p : NULL;
Jeej 34:1311cc53201a 251
Jeej 34:1311cc53201a 252 // free message
Jeej 34:1311cc53201a 253 if (msg != NULL)
Jeej 34:1311cc53201a 254 {
Jeej 34:1311cc53201a 255 FREE(msg->buf);
Jeej 34:1311cc53201a 256 FREE(msg);
Jeej 34:1311cc53201a 257 }
Jeej 34:1311cc53201a 258 } while (msg != NULL);
Jeej 34:1311cc53201a 259
Jeej 34:1311cc53201a 260 // Flush RX
Jeej 34:1311cc53201a 261 for (int i = 0 ; i < 3 ; i++)
Jeej 34:1311cc53201a 262 {
Jeej 34:1311cc53201a 263 do
Jeej 34:1311cc53201a 264 {
Jeej 34:1311cc53201a 265 // wait for data
Jeej 34:1311cc53201a 266 if (i == 0)
Jeej 34:1311cc53201a 267 {
Jeej 34:1311cc53201a 268 pkt = d7a_modem_wait_pkt(1);
Jeej 34:1311cc53201a 269 }
Jeej 34:1311cc53201a 270 else if (i == 1)
Jeej 34:1311cc53201a 271 {
Jeej 34:1311cc53201a 272 pkt = d7a_fs_wait_pkt(1);
Jeej 34:1311cc53201a 273 }
Jeej 34:1311cc53201a 274 else
Jeej 34:1311cc53201a 275 {
Jeej 34:1311cc53201a 276 pkt = d7a_sys_wait_pkt(1);
Jeej 34:1311cc53201a 277 }
Jeej 34:1311cc53201a 278
Jeej 34:1311cc53201a 279 // free message
Jeej 34:1311cc53201a 280 if (pkt != NULL)
Jeej 34:1311cc53201a 281 {
Jeej 34:1311cc53201a 282 FREE(pkt);
Jeej 34:1311cc53201a 283 }
Jeej 34:1311cc53201a 284 } while (pkt != NULL);
Jeej 34:1311cc53201a 285 }
Jeej 34:1311cc53201a 286
Jeej 37:e04613e021f2 287 d7a_com_start_rx();
Jeej 37:e04613e021f2 288 d7a_com_start_tx();
Jeej 34:1311cc53201a 289 }
Jeej 34:1311cc53201a 290
Jeej 42:1578f0480dcb 291
Jeej 34:1311cc53201a 292 static void d7a_com_copy_to_linear(uint8_t* linear_buffer, uint16_t read_start, uint16_t length)
Jeej 34:1311cc53201a 293 {
Jeej 34:1311cc53201a 294 uint16_t first_part_size;
Jeej 34:1311cc53201a 295 uint16_t second_part_size;
Jeej 34:1311cc53201a 296
Jeej 34:1311cc53201a 297 ASSERT(length <= g_com_ctx.rx_buffer_size, "Length too long (%d) for buffer size (%d)\r\n", length, g_com_ctx.rx_buffer_size);
Jeej 34:1311cc53201a 298
Jeej 34:1311cc53201a 299 read_start %= g_com_ctx.rx_buffer_size;
Jeej 34:1311cc53201a 300 first_part_size = (length > (g_com_ctx.rx_buffer_size - read_start))? g_com_ctx.rx_buffer_size - read_start : length;
Jeej 34:1311cc53201a 301
Jeej 34:1311cc53201a 302 memcpy((void*)&linear_buffer[0], (const void*)&g_com_ctx.rx_buffer[read_start], first_part_size);
Jeej 34:1311cc53201a 303
Jeej 34:1311cc53201a 304 // The circular buffer is wrapping
Jeej 34:1311cc53201a 305 if (length > first_part_size)
Jeej 34:1311cc53201a 306 {
Jeej 34:1311cc53201a 307 second_part_size = length - first_part_size;
Jeej 34:1311cc53201a 308 memcpy((void*)&linear_buffer[first_part_size], (const void*)&g_com_ctx.rx_buffer[0], second_part_size);
Jeej 34:1311cc53201a 309 }
Jeej 34:1311cc53201a 310 }
Jeej 24:a8433b091764 311
Jeej 42:1578f0480dcb 312
Jeej 42:1578f0480dcb 313 void d7a_com_print_stats(void)
Jeej 42:1578f0480dcb 314 {
Jeej 42:1578f0480dcb 315 PRINT("State: %d\r\n", g_com_ctx.state);
Jeej 42:1578f0480dcb 316 PRINT("Data: %d\r\n", g_com_ctx.data_available);
Jeej 42:1578f0480dcb 317
Jeej 42:1578f0480dcb 318 #if 0
Jeej 42:1578f0480dcb 319 if (g_com_ctx.data_available)
Jeej 42:1578f0480dcb 320 {
Jeej 42:1578f0480dcb 321 uint8_t* temp = (uint8_t*)MALLOC(g_com_ctx.data_available);
Jeej 42:1578f0480dcb 322 d7a_com_copy_to_linear(temp, g_com_ctx.read_idx, g_com_ctx.data_available);
Jeej 42:1578f0480dcb 323 PRINT_DATA("", "%02X ", temp, g_com_ctx.data_available, "\r\n");
Jeej 42:1578f0480dcb 324 FREE(temp);
Jeej 42:1578f0480dcb 325 }
Jeej 42:1578f0480dcb 326 #endif
Jeej 42:1578f0480dcb 327 }
Jeej 42:1578f0480dcb 328
Jeej 42:1578f0480dcb 329
Jeej 24:a8433b091764 330 /**
Jeej 24:a8433b091764 331 Wakes-up modem and send data throught Serial.
Jeej 24:a8433b091764 332
Jeej 24:a8433b091764 333 @param const uint8_t* Pointer to data buffer
Jeej 24:a8433b091764 334 @param int Data length
Jeej 24:a8433b091764 335 @return void
Jeej 24:a8433b091764 336 */
Jeej 26:9f0b9833cac6 337 static void d7a_com_send(const uint8_t* buffer, int length)
Jeej 24:a8433b091764 338 {
Jeej 31:ab9bfdbc6b44 339 FPRINT("(len:%d)\r\n", length);
Jeej 34:1311cc53201a 340
Jeej 24:a8433b091764 341 *(g_com_ctx.rts) = 1;
Jeej 24:a8433b091764 342
Jeej 31:ab9bfdbc6b44 343 //dbg_print_data("%02X ", (uint8_t*)buffer, length);
Jeej 31:ab9bfdbc6b44 344 //DPRINT("\r\n");
Jeej 39:2101208fafb6 345 Thread::wait(2);
Jeej 24:a8433b091764 346
Jeej 34:1311cc53201a 347 for (uint32_t i=0 ; i<length ; i++)
Jeej 24:a8433b091764 348 {
Jeej 24:a8433b091764 349 g_com_ctx.serial->putc(buffer[i]);
Jeej 24:a8433b091764 350 }
Jeej 24:a8433b091764 351
Jeej 42:1578f0480dcb 352 //Thread::wait(2);
Jeej 42:1578f0480dcb 353
Jeej 24:a8433b091764 354 *(g_com_ctx.rts) = 0;
Jeej 24:a8433b091764 355 }
Jeej 24:a8433b091764 356
Jeej 31:ab9bfdbc6b44 357
Jeej 31:ab9bfdbc6b44 358 static void d7a_com_post_tx(uint8_t* buffer, uint32_t length)
Jeej 31:ab9bfdbc6b44 359 {
Jeej 31:ab9bfdbc6b44 360 FPRINT("(len:%d)\r\n", length);
Jeej 34:1311cc53201a 361
Jeej 31:ab9bfdbc6b44 362 d7a_com_tx_buf_t* tx_buf = (d7a_com_tx_buf_t*)MALLOC(sizeof(d7a_com_tx_buf_t));
Jeej 31:ab9bfdbc6b44 363
Jeej 31:ab9bfdbc6b44 364 tx_buf->len = length;
Jeej 37:e04613e021f2 365 tx_buf->buf = buffer;
Jeej 31:ab9bfdbc6b44 366
Jeej 31:ab9bfdbc6b44 367 g_com_ctx.tx_queue.put(tx_buf);
Jeej 31:ab9bfdbc6b44 368 }
Jeej 31:ab9bfdbc6b44 369
Jeej 26:9f0b9833cac6 370 // Formats and send packet throught Serial.
Jeej 26:9f0b9833cac6 371 void d7a_com_send_msg(d7a_com_tx_msg_t* msg)
Jeej 34:1311cc53201a 372 {
Jeej 34:1311cc53201a 373 uint8_t* buf;
Jeej 34:1311cc53201a 374 uint16_t len = msg->alen + msg->plen;
Jeej 34:1311cc53201a 375 FPRINT("(len:%d)\r\n", len);
Jeej 34:1311cc53201a 376
Jeej 34:1311cc53201a 377 buf = (uint8_t*)MALLOC(KAL_COM_HEADER_LEN + len);
Jeej 34:1311cc53201a 378
Jeej 34:1311cc53201a 379 // construct serial header
Jeej 34:1311cc53201a 380 // concatenate and update tx_seq ID
Jeej 34:1311cc53201a 381 buf[0] = (uint8_t)KAL_COM_SYNC_BYTE_0;
Jeej 34:1311cc53201a 382 buf[1] = (uint8_t)KAL_COM_SYNC_BYTE_1;
Jeej 34:1311cc53201a 383 buf[2] = (uint8_t)len;
Jeej 34:1311cc53201a 384 buf[3] = (uint8_t)g_com_ctx.tx_seq++;
Jeej 34:1311cc53201a 385 buf[4] = (uint8_t)msg->id;
Jeej 34:1311cc53201a 386 len += KAL_COM_HEADER_LEN;
Jeej 34:1311cc53201a 387
Jeej 34:1311cc53201a 388 // copy payload and parameters
Jeej 34:1311cc53201a 389 memcpy(buf + KAL_COM_HEADER_LEN, msg->pbuf, msg->plen);
Jeej 34:1311cc53201a 390 memcpy(buf + KAL_COM_HEADER_LEN + msg->plen, msg->abuf, msg->alen);
Jeej 34:1311cc53201a 391
Jeej 34:1311cc53201a 392 DPRINT("<-- (0x%02X) %d\r\n", buf[4], (len - KAL_COM_HEADER_LEN));
Jeej 34:1311cc53201a 393
Jeej 34:1311cc53201a 394 d7a_com_send(buf, len);
Jeej 34:1311cc53201a 395 }
Jeej 34:1311cc53201a 396
Jeej 34:1311cc53201a 397 void d7a_com_post_msg(d7a_com_tx_msg_t* msg)
Jeej 34:1311cc53201a 398 {
Jeej 26:9f0b9833cac6 399 uint8_t* buf;
Jeej 26:9f0b9833cac6 400 uint16_t len = msg->alen + msg->plen;
Jeej 30:d775c1409849 401 FPRINT("(len:%d)\r\n", len);
Jeej 26:9f0b9833cac6 402
Jeej 26:9f0b9833cac6 403 buf = (uint8_t*)MALLOC(KAL_COM_HEADER_LEN + len);
Jeej 26:9f0b9833cac6 404
Jeej 26:9f0b9833cac6 405 // construct serial header
Jeej 26:9f0b9833cac6 406 // concatenate and update tx_seq ID
Jeej 26:9f0b9833cac6 407 buf[0] = (uint8_t)KAL_COM_SYNC_BYTE_0;
Jeej 26:9f0b9833cac6 408 buf[1] = (uint8_t)KAL_COM_SYNC_BYTE_1;
Jeej 26:9f0b9833cac6 409 buf[2] = (uint8_t)len;
Jeej 26:9f0b9833cac6 410 buf[3] = (uint8_t)g_com_ctx.tx_seq++;
Jeej 26:9f0b9833cac6 411 buf[4] = (uint8_t)msg->id;
Jeej 26:9f0b9833cac6 412 len += KAL_COM_HEADER_LEN;
Jeej 26:9f0b9833cac6 413
Jeej 26:9f0b9833cac6 414 // copy payload and parameters
Jeej 26:9f0b9833cac6 415 memcpy(buf + KAL_COM_HEADER_LEN, msg->pbuf, msg->plen);
Jeej 26:9f0b9833cac6 416 memcpy(buf + KAL_COM_HEADER_LEN + msg->plen, msg->abuf, msg->alen);
Jeej 26:9f0b9833cac6 417
Jeej 31:ab9bfdbc6b44 418 d7a_com_post_tx(buf, len);
Jeej 26:9f0b9833cac6 419 }
Jeej 26:9f0b9833cac6 420
Jeej 31:ab9bfdbc6b44 421
Jeej 30:d775c1409849 422 void d7a_com_dump(uint8_t* buf, uint8_t len, d7a_com_flow_t flow)
Jeej 30:d775c1409849 423 {
Jeej 30:d775c1409849 424 d7a_com_tx_msg_t msg;
Jeej 30:d775c1409849 425
Jeej 30:d775c1409849 426 msg.id = flow;
Jeej 30:d775c1409849 427 msg.pbuf = buf;
Jeej 30:d775c1409849 428 msg.plen = len;
Jeej 30:d775c1409849 429 msg.alen = 0;
Jeej 34:1311cc53201a 430 d7a_com_post_msg(&msg);
Jeej 30:d775c1409849 431 }
Jeej 30:d775c1409849 432
Jeej 34:1311cc53201a 433 void d7a_com_force_dump(uint8_t* buf, uint8_t len, d7a_com_flow_t flow)
Jeej 33:f9a542d3efaa 434 {
Jeej 34:1311cc53201a 435 d7a_com_tx_msg_t msg;
Jeej 34:1311cc53201a 436
Jeej 34:1311cc53201a 437 msg.id = flow;
Jeej 34:1311cc53201a 438 msg.pbuf = buf;
Jeej 34:1311cc53201a 439 msg.plen = len;
Jeej 34:1311cc53201a 440 msg.alen = 0;
Jeej 34:1311cc53201a 441 d7a_com_send_msg(&msg);
Jeej 33:f9a542d3efaa 442 }
Jeej 26:9f0b9833cac6 443
Jeej 25:aac250164497 444 static void d7a_com_new_pkt(d7a_com_rx_msg_t* pkt)
Jeej 25:aac250164497 445 {
Jeej 26:9f0b9833cac6 446 //FPRINT("\r\n");
Jeej 35:1fe2975c5a63 447
Jeej 35:1fe2975c5a63 448 DPRINT("--> (0x%02X) %d\r\n", pkt->id, pkt->blen);
Jeej 35:1fe2975c5a63 449
Jeej 25:aac250164497 450 // Distribute packet types to processes
Jeej 25:aac250164497 451 switch (KAL_COM_FLOWID(pkt->id))
Jeej 25:aac250164497 452 {
Jeej 25:aac250164497 453 case KAL_COM_FLOWID_FS:
Jeej 25:aac250164497 454 d7a_fs_new_pkt(pkt);
Jeej 25:aac250164497 455 break;
Jeej 25:aac250164497 456 case KAL_COM_FLOWID_CMD:
Jeej 25:aac250164497 457 d7a_modem_new_pkt(pkt);
Jeej 25:aac250164497 458 break;
Jeej 25:aac250164497 459 case KAL_COM_FLOWID_SYS:
Jeej 30:d775c1409849 460 // This has to be here to avoid going to another process
Jeej 30:d775c1409849 461 if (pkt->id == KAL_COM_FLOW_SYS_XON)
Jeej 30:d775c1409849 462 {
Jeej 42:1578f0480dcb 463 DPRINT("XON\r\n");
Jeej 34:1311cc53201a 464 g_com_ctx.tx_thread->signal_set(XON_SIGNAL);
Jeej 30:d775c1409849 465 FREE(pkt);
Jeej 30:d775c1409849 466 }
Jeej 30:d775c1409849 467 else if (pkt->id == KAL_COM_FLOW_SYS_XOFF)
Jeej 30:d775c1409849 468 {
Jeej 42:1578f0480dcb 469 DPRINT("XOFF\r\n");
Jeej 34:1311cc53201a 470 d7a_sys_xack();
Jeej 30:d775c1409849 471 FREE(pkt);
Jeej 30:d775c1409849 472 }
Jeej 30:d775c1409849 473 else
Jeej 30:d775c1409849 474 {
Jeej 34:1311cc53201a 475 if (KAL_COM_FLOW_SYS_PONG == pkt->id)
Jeej 34:1311cc53201a 476 {
Jeej 34:1311cc53201a 477 g_com_ctx.tim.stop();
Jeej 34:1311cc53201a 478 uint32_t time_us = g_com_ctx.tim.read_us();
Jeej 34:1311cc53201a 479 IPRINT("Ping in %d.%03dms\r\n", time_us/1000, time_us%1000);
Jeej 34:1311cc53201a 480 }
Jeej 30:d775c1409849 481 d7a_sys_new_pkt(pkt);
Jeej 30:d775c1409849 482 }
Jeej 30:d775c1409849 483 break;
Jeej 25:aac250164497 484 default:
Jeej 25:aac250164497 485 EPRINT("Untreated pkt type 0x%02X\r\n", pkt->id);
Jeej 25:aac250164497 486 FREE(pkt);
Jeej 25:aac250164497 487 break;
Jeej 25:aac250164497 488 }
Jeej 25:aac250164497 489 }
Jeej 24:a8433b091764 490
Jeej 37:e04613e021f2 491 void d7a_com_forward_buffer(uint8_t size)
Jeej 37:e04613e021f2 492 {
Jeej 37:e04613e021f2 493 g_com_ctx.read_idx = (g_com_ctx.read_idx + size) % g_com_ctx.rx_buffer_size;
Jeej 37:e04613e021f2 494 g_com_ctx.data_available -= size;
Jeej 37:e04613e021f2 495 }
Jeej 33:f9a542d3efaa 496
Jeej 24:a8433b091764 497 /**
Jeej 34:1311cc53201a 498 Reads the Rx buffer, parses the packets
Jeej 24:a8433b091764 499
Jeej 24:a8433b091764 500 @param void
Jeej 24:a8433b091764 501 @return void
Jeej 24:a8433b091764 502 */
Jeej 37:e04613e021f2 503 static void parse_packet_header(void)
Jeej 24:a8433b091764 504 {
Jeej 37:e04613e021f2 505 uint8_t header[KAL_COM_HEADER_LEN];
Jeej 37:e04613e021f2 506 uint8_t seqnum;
Jeej 33:f9a542d3efaa 507
Jeej 42:1578f0480dcb 508 ASSERT(g_com_ctx.data_available >= KAL_COM_HEADER_LEN, "Not enough data for header\r\n");
Jeej 42:1578f0480dcb 509
Jeej 37:e04613e021f2 510 g_com_ctx.skipped_bytes = 0;
Jeej 33:f9a542d3efaa 511
Jeej 37:e04613e021f2 512 // Lookup fist sync byte
Jeej 37:e04613e021f2 513 while (g_com_ctx.data_available >= KAL_COM_HEADER_LEN)
Jeej 24:a8433b091764 514 {
Jeej 37:e04613e021f2 515 if(KAL_COM_SYNC_BYTE_0 == g_com_ctx.rx_buffer[g_com_ctx.read_idx])
Jeej 24:a8433b091764 516 {
Jeej 37:e04613e021f2 517 // copy following data
Jeej 37:e04613e021f2 518 d7a_com_copy_to_linear(header, g_com_ctx.read_idx, KAL_COM_HEADER_LEN);
Jeej 37:e04613e021f2 519 if (KAL_COM_SYNC_BYTE_1 == header[1])
Jeej 33:f9a542d3efaa 520 {
Jeej 37:e04613e021f2 521 // Fill temp header
Jeej 37:e04613e021f2 522 g_com_ctx.msg.blen = header[2];
Jeej 37:e04613e021f2 523 seqnum = header[3];
Jeej 37:e04613e021f2 524 g_com_ctx.msg.id = header[4];
Jeej 37:e04613e021f2 525
Jeej 37:e04613e021f2 526 // Update seqnum
Jeej 37:e04613e021f2 527 WARNING(g_com_ctx.rx_seq == seqnum, "COM Bad seqnum expected:%d got:%d\r\n", g_com_ctx.rx_seq, seqnum);
Jeej 37:e04613e021f2 528 g_com_ctx.rx_seq = seqnum + 1;
Jeej 37:e04613e021f2 529
Jeej 37:e04613e021f2 530 // search for body
Jeej 37:e04613e021f2 531 d7a_com_forward_buffer(KAL_COM_HEADER_LEN);
Jeej 37:e04613e021f2 532 g_com_ctx.state = SEARCH_BODY;
Jeej 42:1578f0480dcb 533
Jeej 42:1578f0480dcb 534 // Start parsing if data is already available
Jeej 42:1578f0480dcb 535 if (g_com_ctx.data_available >= g_com_ctx.msg.blen)
Jeej 42:1578f0480dcb 536 {
Jeej 42:1578f0480dcb 537 g_com_ctx.state = PARSE_BODY;
Jeej 42:1578f0480dcb 538 g_com_ctx.data_parsing->release();
Jeej 42:1578f0480dcb 539 }
Jeej 42:1578f0480dcb 540
Jeej 42:1578f0480dcb 541 DPRINT("COM header found (body %d/%d bytes)\r\n", g_com_ctx.data_available, g_com_ctx.msg.blen);
Jeej 33:f9a542d3efaa 542 break;
Jeej 33:f9a542d3efaa 543 }
Jeej 24:a8433b091764 544 }
Jeej 37:e04613e021f2 545
Jeej 37:e04613e021f2 546 // byte skipped
Jeej 37:e04613e021f2 547 WARNING(g_com_ctx.skipped_bytes != 1, "COM not sync. Searching for header.\r\n");
Jeej 37:e04613e021f2 548 d7a_com_forward_buffer(1);
Jeej 37:e04613e021f2 549 }
Jeej 37:e04613e021f2 550
Jeej 37:e04613e021f2 551 if (g_com_ctx.skipped_bytes)
Jeej 37:e04613e021f2 552 {
Jeej 37:e04613e021f2 553 WARNING(false, "Skipped %d bytes.\r\n", g_com_ctx.skipped_bytes);
Jeej 37:e04613e021f2 554 #if 0
Jeej 37:e04613e021f2 555 uint8_t* temp = (uint8_t*)MALLOC(g_com_ctx.skipped_bytes);
Jeej 37:e04613e021f2 556 d7a_com_copy_to_linear(temp, g_com_ctx.read_idx - g_com_ctx.skipped_bytes, g_com_ctx.skipped_bytes);
Jeej 37:e04613e021f2 557 PRINT_DATA("", "%02X ", temp, g_com_ctx.skipped_bytes, "\r\n");
Jeej 37:e04613e021f2 558 FREE(temp);
Jeej 34:1311cc53201a 559 #endif
Jeej 37:e04613e021f2 560 g_com_ctx.skipped_bytes = 0;
Jeej 37:e04613e021f2 561 }
Jeej 37:e04613e021f2 562 }
Jeej 37:e04613e021f2 563
Jeej 37:e04613e021f2 564 /**
Jeej 37:e04613e021f2 565 Reads the Rx buffer, parses the packets
Jeej 37:e04613e021f2 566
Jeej 37:e04613e021f2 567 @param void
Jeej 37:e04613e021f2 568 @return void
Jeej 37:e04613e021f2 569 */
Jeej 37:e04613e021f2 570 static void parse_packet_body(void)
Jeej 37:e04613e021f2 571 {
Jeej 42:1578f0480dcb 572 ASSERT(g_com_ctx.data_available >= g_com_ctx.msg.blen, "Not enough data for body\r\n");
Jeej 42:1578f0480dcb 573
Jeej 37:e04613e021f2 574 if (KAL_COM_FLOWID(g_com_ctx.msg.id) != KAL_COM_FLOWID_TRC)
Jeej 37:e04613e021f2 575 {
Jeej 37:e04613e021f2 576 //DPRINT("Got packet id 0x%02X len %d\r\n", id, len);
Jeej 37:e04613e021f2 577
Jeej 37:e04613e021f2 578 d7a_com_rx_msg_t* pkt = NULL;
Jeej 37:e04613e021f2 579 pkt = (d7a_com_rx_msg_t*)MALLOC(sizeof(d7a_com_rx_msg_t) - 1 + g_com_ctx.msg.blen);
Jeej 37:e04613e021f2 580
Jeej 37:e04613e021f2 581 // copy data to buffer
Jeej 37:e04613e021f2 582 pkt->blen = g_com_ctx.msg.blen;
Jeej 37:e04613e021f2 583 pkt->id = g_com_ctx.msg.id;
Jeej 37:e04613e021f2 584 d7a_com_copy_to_linear(pkt->buffer, g_com_ctx.read_idx, g_com_ctx.msg.blen);
Jeej 37:e04613e021f2 585
Jeej 37:e04613e021f2 586 // add packet to queue
Jeej 37:e04613e021f2 587 d7a_com_new_pkt(pkt);
Jeej 37:e04613e021f2 588 }
Jeej 37:e04613e021f2 589 else
Jeej 37:e04613e021f2 590 {
Jeej 37:e04613e021f2 591 // Ignore packet
Jeej 24:a8433b091764 592 }
Jeej 33:f9a542d3efaa 593
Jeej 33:f9a542d3efaa 594 // update buffer indexes
Jeej 37:e04613e021f2 595 d7a_com_forward_buffer(g_com_ctx.msg.blen);
Jeej 37:e04613e021f2 596 g_com_ctx.state = SEARCH_HEADER;
Jeej 42:1578f0480dcb 597
Jeej 42:1578f0480dcb 598 // Start parsing if data is already available
Jeej 42:1578f0480dcb 599 if (g_com_ctx.data_available >= KAL_COM_HEADER_LEN)
Jeej 42:1578f0480dcb 600 {
Jeej 42:1578f0480dcb 601 g_com_ctx.state = PARSE_HEADER;
Jeej 42:1578f0480dcb 602 g_com_ctx.data_parsing->release();
Jeej 42:1578f0480dcb 603 }
Jeej 24:a8433b091764 604 }
Jeej 24:a8433b091764 605
Jeej 24:a8433b091764 606
Jeej 24:a8433b091764 607 // Thread for parsing packets from RX buffer.
Jeej 31:ab9bfdbc6b44 608 void d7a_com_rx_thread( void const *p )
Jeej 24:a8433b091764 609 {
Jeej 25:aac250164497 610 FPRINT("\r\n");
Jeej 24:a8433b091764 611 while (true)
Jeej 24:a8433b091764 612 {
Jeej 37:e04613e021f2 613 if (!g_com_ctx.rx_started)
Jeej 37:e04613e021f2 614 {
Jeej 37:e04613e021f2 615 g_com_ctx.rx_thread->signal_wait(START_SIGNAL);
Jeej 37:e04613e021f2 616 }
Jeej 37:e04613e021f2 617
Jeej 24:a8433b091764 618 // wait for data available
Jeej 24:a8433b091764 619 g_com_ctx.data_parsing->wait();
Jeej 37:e04613e021f2 620
Jeej 37:e04613e021f2 621 if (g_com_ctx.state == PARSE_HEADER)
Jeej 33:f9a542d3efaa 622 {
Jeej 37:e04613e021f2 623 parse_packet_header();
Jeej 37:e04613e021f2 624 }
Jeej 37:e04613e021f2 625 else if (g_com_ctx.state == PARSE_BODY)
Jeej 37:e04613e021f2 626 {
Jeej 37:e04613e021f2 627 parse_packet_body();
Jeej 33:f9a542d3efaa 628 }
Jeej 24:a8433b091764 629 }
Jeej 24:a8433b091764 630 }
Jeej 31:ab9bfdbc6b44 631
Jeej 31:ab9bfdbc6b44 632 void d7a_com_tx_thread( void const *p )
Jeej 31:ab9bfdbc6b44 633 {
Jeej 31:ab9bfdbc6b44 634 FPRINT("\r\n");
Jeej 31:ab9bfdbc6b44 635
Jeej 31:ab9bfdbc6b44 636 d7a_com_tx_buf_t* msg;
Jeej 31:ab9bfdbc6b44 637 osEvent evt;
Jeej 34:1311cc53201a 638 uint8_t flow_id;
Jeej 34:1311cc53201a 639
Jeej 31:ab9bfdbc6b44 640 while (true)
Jeej 31:ab9bfdbc6b44 641 {
Jeej 37:e04613e021f2 642 if (!g_com_ctx.tx_started)
Jeej 37:e04613e021f2 643 {
Jeej 37:e04613e021f2 644 g_com_ctx.tx_thread->signal_wait(START_SIGNAL);
Jeej 37:e04613e021f2 645 }
Jeej 37:e04613e021f2 646
Jeej 31:ab9bfdbc6b44 647 // wait for data to send
Jeej 31:ab9bfdbc6b44 648 evt = g_com_ctx.tx_queue.get();
Jeej 31:ab9bfdbc6b44 649 msg = (evt.status == osEventMessage)? (d7a_com_tx_buf_t*)evt.value.p : NULL;
Jeej 37:e04613e021f2 650
Jeej 31:ab9bfdbc6b44 651
Jeej 31:ab9bfdbc6b44 652 // send message
Jeej 31:ab9bfdbc6b44 653 if (msg != NULL)
Jeej 31:ab9bfdbc6b44 654 {
Jeej 34:1311cc53201a 655 flow_id = msg->buf[4];
Jeej 34:1311cc53201a 656 DPRINT("<-- (0x%02X) %d\r\n", flow_id, (msg->len - KAL_COM_HEADER_LEN));
Jeej 34:1311cc53201a 657
Jeej 31:ab9bfdbc6b44 658 d7a_com_send(msg->buf, msg->len);
Jeej 31:ab9bfdbc6b44 659 FREE(msg->buf);
Jeej 31:ab9bfdbc6b44 660 FREE(msg);
Jeej 34:1311cc53201a 661
Jeej 34:1311cc53201a 662 if (KAL_COM_FLOW_SYS_PING == flow_id)
Jeej 34:1311cc53201a 663 {
Jeej 34:1311cc53201a 664 g_com_ctx.tim.reset();
Jeej 34:1311cc53201a 665 g_com_ctx.tim.start();
Jeej 34:1311cc53201a 666 }
Jeej 34:1311cc53201a 667
Jeej 34:1311cc53201a 668 if (KAL_COM_FLOW_SYS_XACK == flow_id)
Jeej 34:1311cc53201a 669 {
Jeej 42:1578f0480dcb 670 DPRINT("XACK\r\n");
Jeej 34:1311cc53201a 671 g_com_ctx.tx_thread->signal_wait(XON_SIGNAL);
Jeej 34:1311cc53201a 672 }
Jeej 31:ab9bfdbc6b44 673 }
Jeej 31:ab9bfdbc6b44 674 }
Jeej 31:ab9bfdbc6b44 675 }