# wuart.c

Go to the documentation of this file.

    00001 /* Copyright (c) 2007 Axel Wachtler
    00002    All rights reserved.
    00003
    00004    Redistribution and use in source and binary forms, with or without
    00005    modification, are permitted provided that the following conditions
    00006    are met:
    00007
    00008    * Redistributions of source code must retain the above copyright
    00009      notice, this list of conditions and the following disclaimer.
    00010    * Redistributions in binary form must reproduce the above copyright
    00011      notice, this list of conditions and the following disclaimer in the
    00012      documentation and/or other materials provided with the distribution.
    00013    * Neither the name of the authors nor the names of its contributors
    00014      may be used to endorse or promote products derived from this software
    00015      without specific prior written permission.
    00016
    00017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    00018    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    00019    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    00020    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    00021    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    00022    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    00023    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    00024    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    00025    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    00026    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    00027    POSSIBILITY OF SUCH DAMAGE. */
    00028
    00029 /* $Id: wuart.c,v 1.8 2010/04/26 19:33:39 awachtler Exp $ */
    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 /* === Macros ======================================== */
    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 /* === Types ========================================= */
    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 /* === globals ====================================== */
    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 /* === prototypes ================================= */
    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 //    hif_init(19200);
    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                             /* backoff manual */
    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                     /* outa here, make a break for a while */
    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                     /* terminate string */
    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         /* uart transmit handler */
    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                                   int8_t ed, 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             /* yes, we can do a swap */
    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         /* check pattern for occurence of +++ */
    00404         if (size > 3)
    00405         {
    00406             /* more data received */
    00407             esc_state = ESC_NONE;
    00408             tmo = 0;
    00409             pattern = 0;
    00410         }
    00411         else
    00412         {
    00413             /* there could be the +++ sequence in */
    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         /* counting the occurences of empty interface */
    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 }