00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00039 #include <string.h>
00040 #include "radio.h"
00041 #include "transceiver.h"
00042 #include "ioutil.h"
00043 #include "timer.h"
00044 #include "prot_wuart.h"
00045
00046
00047
00049 #define PAYLD_SIZE (PROT_WUART_PAYLD_SIZE)
00050
00051 #define CRC_SIZE (sizeof(crc_t))
00052
00053 #define UART_FRAME_SIZE (PROT_WUART_HEADER_SIZE +\
00054 PAYLD_SIZE + CRC_SIZE )
00055
00056 #define PAYLD_START (PROT_WUART_HEADER_SIZE)
00057
00058 #define PAYLD_END (UART_FRAME_SIZE - CRC_SIZE)
00059
00060 #define NL "\n\r"
00061
00063 #define ESC_NONE (0)
00064
00066 #define ESC_TMO_1 (1)
00067
00069 #define ESC_PATTERN (2)
00070
00072 #define ESC_TMO_2 (3)
00073
00074
00075
00076
00078 typedef uint16_t crc_t;
00079
00081 typedef struct
00082 {
00083 uint8_t start;
00084 uint8_t end;
00085 uint8_t buf[UART_FRAME_SIZE];
00086 } wuart_buffer_t;
00087
00088
00090 typedef enum
00091 {
00093 CMD_MODE,
00095 DATA_MODE,
00096 } wuart_state_t;
00097
00098
00099 static uint16_t rxcnt;
00100 static uint16_t txcnt;
00101
00102 volatile bool chkrxbuf;
00103 volatile bool txpending;
00104 volatile wuart_state_t wuart_state;
00105 bool echo = false;
00106
00107 timer_hdl_t tmr_uart;
00108 wuart_buffer_t rxbuf[2];
00109 volatile uint8_t rxbuf_idx = 0;
00110
00111 wuart_state_t wuart_check_escape(uint8_t * cmd, uint8_t size);
00112 wuart_state_t wuart_parse_at_command(char *cmd);
00113
00114
00115
00119 void wuart_init()
00120 {
00121 trx_param_t trxp;
00122
00123 LED_INIT();
00124 LED_SET_VALUE(0);
00125 KEY_INIT();
00126
00127 hif_init(9600);
00128 timer_init();
00129
00130 rxbuf_idx = 0;
00131 memset(rxbuf, 0, sizeof(rxbuf));
00132 rxbuf[0].end = PAYLD_START;
00133 rxbuf[1].end = PAYLD_START;
00134 radio_init(rxbuf[rxbuf_idx].buf, UART_FRAME_SIZE);
00135
00136
00137
00138 sei();
00139
00140 #if 0
00141 cfgt = radio_config_recall();
00142 #else
00143 # warning "currently no radio_config_recall()"
00144 #endif
00145 radio_set_state(STATE_OFF);
00146
00147 wuart_state = CMD_MODE;
00148 radio_set_param(RP_CHANNEL(17));
00149 radio_set_param(RP_IDLESTATE(STATE_RX));
00150 trx_parms_get(&trxp);
00151 PRINTF("Wuart 0.2 chan=%d"NL, trxp.chan);
00152
00153 if (trx_identify() != 0)
00154 {
00155 PRINT("RADIO DOES NOT MATCG"NL);
00156 while(1);
00157 }
00158
00159 }
00160
00161
00165 int main(void)
00166 {
00167 uint16_t inchar;
00168
00169 uint8_t txbuf[UART_FRAME_SIZE], cmdidx = 0, inbytes, *cmd, tmp;
00170 wuart_buffer_t *hif_tx_buf;
00171 prot_wuart_header_t *hdr;
00172 time_t lasttxtime = 0, currtime;
00173 bool do_send;
00174
00175 wuart_init();
00176 chkrxbuf = true;
00177 txpending = false;
00178 cmd = &txbuf[PAYLD_START];
00179 hdr = (prot_wuart_header_t*)txbuf;
00180 hdr->fcf = PROT_FCF_DATA;
00181 hdr->seq = 0;
00182 hdr->dst = 0xaa;
00183 hdr->src = 0xbb;
00184 DBG_INIT();
00185
00186 while(1)
00187 {
00188
00189 if (wuart_state == DATA_MODE)
00190 {
00191 currtime = timer_systime();
00192 if (1)
00193 {
00194
00195 inbytes = hif_get_blk(cmd+cmdidx, (PAYLD_SIZE-cmdidx));
00196 cmdidx += inbytes;
00197 if (cmdidx > 0)
00198 {
00199 cmd[cmdidx]=0;
00200 }
00201
00202 #if 0
00203 wuart_state = wuart_check_escape(cmd, cmdidx);
00204 if (wuart_state == CMD_MODE)
00205 {
00206 cmdidx = 0;
00207 radio_set_state(STATE_OFF);
00208 PRINT(NL"EXIT DATA MODE"NL);
00209 break;
00210 }
00211 else
00212 #endif
00213 do_send = false;
00214 if (cmdidx == PAYLD_SIZE)
00215 {
00216 do_send = true;
00217 }
00218 else if (((currtime - lasttxtime) > 20) && (cmdidx > 0))
00219 {
00220 do_send = true;
00221 }
00222 if ((do_send == true) && (txpending == false))
00223 {
00224
00225 radio_set_state(STATE_TX);
00226
00227 tmp = 10;
00228 LED_SET(0);
00229
00230 do
00231 {
00232
00233 if (radio_do_cca() == RADIO_CCA_FREE)
00234 {
00235 hdr->seq ++;
00236 radio_send_frame(PAYLD_START + cmdidx + CRC_SIZE, txbuf, 0);
00237 txpending = true;
00238 lasttxtime = currtime;
00239 cmdidx = 0;
00240 tmp = 0;
00241 LED_SET(1);
00242 }
00243 else
00244 {
00245
00246 DELAY_US(64);
00247 }
00248 }
00249 while(tmp-- > 0);
00250
00251 if (txpending != true)
00252 {
00253 hif_puts(NL"TXFAILED"NL);
00254
00255 }
00256 else
00257 {
00258 LED_CLR(0);
00259 }
00260 if (echo)
00261 {
00262 hif_puts((char*)cmd);
00263 }
00264 }
00265 else if (cmdidx == 0)
00266 {
00267
00268 chkrxbuf = false;
00269 }
00270 }
00271 }
00272
00273 if (wuart_state == CMD_MODE)
00274 {
00275 inchar = hif_getc();
00276 if (inchar < 0x100)
00277 {
00278 if (echo)
00279 {
00280 hif_putc(inchar);
00281 if (inchar == '\n') hif_putc('\r');
00282 if (inchar == '\r') hif_putc('\n');
00283 }
00284 if (inchar == '\n' || inchar == '\r')
00285 {
00286
00287 cmd[cmdidx] = 0;
00288 wuart_state = wuart_parse_at_command((char*)cmd);
00289 cmdidx = 0;
00290 memset(cmd, 0, sizeof(cmd));
00291 if (wuart_state == DATA_MODE)
00292 {
00293 radio_set_state(STATE_RX);
00294 }
00295 }
00296 else
00297 {
00298 cmd[cmdidx++] = inchar;
00299 }
00300 }
00301 }
00302
00303
00304 hif_tx_buf = &rxbuf[(rxbuf_idx + 1)&1];
00305 if (hif_tx_buf->end > PAYLD_START)
00306 {
00307 uint8_t *p = &hif_tx_buf->buf[hif_tx_buf->start];
00308 uint8_t sz = hif_tx_buf->end - hif_tx_buf->start;
00309 hif_tx_buf->start += hif_put_blk(p, sz);
00310 if (hif_tx_buf->start >= hif_tx_buf->end)
00311 {
00312 hif_tx_buf->end = PAYLD_START;
00313 }
00314 }
00315 }
00316 }
00317
00318
00322 #ifdef DOXYGEN
00323 uint8_t * wuart_usr_radio_tx_done()
00324 #else
00325 void usr_radio_tx_done(radio_tx_done_t status)
00326 #endif
00327 {
00328 if (status == TX_OK)
00329 {
00330 LED_CLR(1);
00331 txcnt ++;
00332 }
00333 txpending = false;
00334 }
00335
00339 #ifdef DOXYGEN
00340 uint8_t * wuart_usr_radio_receive_frame()
00341 #else
00342 uint8_t * usr_radio_receive_frame(uint8_t len, uint8_t *frm, uint8_t lqi,
00343 uint8_t rssi, uint8_t crc)
00344 #endif
00345 {
00346 static uint8_t rxseq = 0;
00347 static uint16_t seqerr;
00348 prot_wuart_header_t *rxhdr;
00349 uint8_t __sreg = SREG; cli();
00350 LED_TOGGLE(1);
00351 if (crc == 0)
00352 {
00353 if( rxbuf[(rxbuf_idx^1)].end == PAYLD_START)
00354 {
00355
00356 rxhdr = (prot_wuart_header_t*) frm;
00357 if (rxhdr->seq != rxseq)
00358 {
00359 seqerr++;
00360 }
00361 rxseq = rxhdr->seq+1;
00362 rxbuf[rxbuf_idx].start = PAYLD_START;
00363 rxbuf[rxbuf_idx].end = len - CRC_SIZE;
00364 rxbuf_idx ^= 1;
00365 frm = rxbuf[rxbuf_idx].buf;
00366 }
00367 rxcnt ++;
00368 }
00369 SREG = __sreg;
00370 return frm;
00371 }
00372
00394 wuart_state_t wuart_check_escape(uint8_t * cmd, uint8_t size)
00395 {
00396
00397 static uint8_t pattern, tmo, esc_state, i;
00398 wuart_state_t ret = DATA_MODE;
00399
00400
00401 if (size > 0)
00402 {
00403
00404 if (size > 3)
00405 {
00406
00407 esc_state = ESC_NONE;
00408 tmo = 0;
00409 pattern = 0;
00410 }
00411 else
00412 {
00413
00414 if (esc_state > ESC_NONE)
00415 {
00416 for(i=0; i<size; i++)
00417 {
00418 if (cmd[i] == '+')
00419 {
00420 pattern++;
00421 }
00422 else
00423 {
00424 pattern = 0;
00425 esc_state = ESC_NONE;
00426 }
00427 if (pattern == 3)
00428 {
00429 esc_state = ESC_PATTERN;
00430 tmo = 0;
00431 }
00432 }
00433 }
00434 }
00435 }
00436 else
00437 {
00438
00439 tmo += 1;
00440 if (tmo > 10)
00441 {
00442 esc_state = (esc_state == ESC_PATTERN) ? ESC_TMO_2 : ESC_TMO_1;
00443 tmo = 0;
00444 }
00445 }
00446 ret = (esc_state != ESC_TMO_2) ? DATA_MODE : CMD_MODE;
00447 if (ret == CMD_MODE)
00448 {
00449 esc_state = ESC_NONE;
00450 tmo = 0;
00451 pattern = 0;
00452 }
00453 return ret;
00454 }
00455
00456
00460 wuart_state_t wuart_parse_at_command(char *cmd)
00461 {
00462
00463 wuart_state_t ret = CMD_MODE;
00464 bool atok;
00465 if (cmd[0] == 'A' && cmd[1] == 'T')
00466 {
00467 cmd += 2;
00468 while (*cmd != 0)
00469 {
00470
00471 atok = true;
00472 if (*cmd == 'D')
00473 {
00474 PRINT("ENTER DATA MODE"NL);
00475 ret = DATA_MODE;
00476 }
00477 else if (*cmd == 'E')
00478 {
00479 cmd++;
00480 if (*cmd == '0')
00481 {
00482 echo = false;
00483 }
00484 else if (*cmd == '1')
00485 {
00486 echo = true;
00487
00488 }
00489 else if (*cmd == '?')
00490 {
00491 PRINTF("ECHO %s"NL, echo ? "ON":"OFF");
00492 }
00493 else
00494 {
00495 atok = false;
00496 }
00497 }
00498 else if (*cmd == 'I')
00499 {
00500 trx_param_t trxp;
00501 trx_parms_get(&trxp);
00502 PRINTF( "E%d "\
00503 "CHA:%d TXP:%d "\
00504 "CCA:%d EDT:%d "\
00505 "CLK:%d"NL,
00506 echo,
00507 trxp.chan, trxp.txp, trxp.cca,
00508 trxp.edt, trxp.clkm);
00509 }
00510 else if (*cmd == 'S')
00511 {
00512 uint8_t reg;
00513 cmd++;
00514 reg = 0;
00515 while (*cmd != '=' && *cmd != '?')
00516 {
00517 reg *= 10;
00518 reg += (*cmd++ - '0');
00519 }
00520 if (*cmd == '=')
00521 {
00522 uint8_t val;
00523 cmd ++;
00524 val = 0;
00525 while(*cmd >= '0' && *cmd <= '9' )
00526 {
00527 val *= 10;
00528 val += (*cmd++ - '0');
00529 }
00530 PRINTF("S%d = %d"NL, reg, val);
00531 }
00532 else if (*cmd == '?')
00533 {
00534 PRINTF("S%d = %d"NL, reg, 42);
00535 }
00536 else
00537 {
00538 cmd ++;
00539 atok = false;
00540 }
00541
00542 }
00543 else
00544 {
00545 atok = false;
00546 }
00547 cmd ++;
00548 PRINTF("%s"NL, atok ? "OK" : "ERROR");
00549 }
00550 }
00551 return ret;
00552 }