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 }

This documentation for µracoli was generated on Wed Feb 2 2011 by  doxygen 1.7.1