# diagradio.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: diagradio.c,v 1.8 2010/04/26 19:33:39 awachtler Exp $ */
    00040 #include <string.h>
    00041 #include "radio.h"
    00042 #include "transceiver.h"
    00043 #include "ioutil.h"
    00044 #include "timer.h"
    00045 /* === Types ===============================================*/
    00046
    00047 typedef struct
    00048 {
    00049     uint8_t new;
    00050     uint8_t len;
    00051     uint8_t crc;
    00052     uint8_t lqi;
    00053     uint8_t ed;
    00054     uint8_t seq;
    00055 } rx_frame_t;
    00056
    00057
    00058 typedef struct
    00059 {
    00060     uint32_t rxcnt;
    00061     uint32_t crcerr;
    00062     uint32_t ed;
    00063     uint32_t lqi;
    00064
    00065     uint32_t txcnt;
    00066     time_t   start;
    00067 } statistic_t;
    00068
    00069
    00070 typedef struct
    00071 {
    00072     channel_t channel;
    00073     txpwr_t   txpwr;
    00074     ccamode_t ccamode;
    00075     rxidle_t  rxidle;
    00076 } rdiag_ctx_t;
    00077
    00078 /* === Prototypes ==========================================*/
    00079 void rdiag_init(void);
    00080 void set_next_channel(channel_t chaninc);
    00081 void set_next_pwr(int8_t pwrinc);
    00082 void set_next_cca(void);
    00083
    00084 void toggle_rxon_idle(void);
    00085 void send_frame(uint8_t seq);
    00086 void send_continous(void);
    00087 void show_statistic(bool reset);
    00088 void help(void);
    00089 time_t blink(timer_arg_t t);
    00090
    00091 /* === Globals =============================================*/
    00092 static uint8_t RxBuf[MAX_FRAME_SIZE];
    00093 static uint8_t TxBuf[MAX_FRAME_SIZE];
    00094 static rx_frame_t rxfrm;
    00095
    00096 statistic_t RdiagStat;
    00097 static rdiag_ctx_t RdiagCtx;
    00098
    00099
    00100
    00101 int8_t verbose;
    00102 bool   conttx;
    00103 uint8_t tx_length = 42;
    00104 #define TBLINK_PERIOD (500)
    00105 #define NL "\n\r"
    00106 timer_hdl_t  th_blink;
    00107
    00109 trx_param_t PROGMEM trxp_flash = {chan: 13, txp: 0, cca: 1, edt: 11, clkm: 0};
    00110
    00119 int main(void)
    00120 {
    00121
    00122 uint16_t inchar;
    00123 uint8_t tmp, seq, *p;
    00124 trx_param_t trxp;
    00125 #if 0
    00126 trx_cfg_t cfgt;
    00127 #endif
    00128
    00129     rdiag_init();
    00130
    00131     PRINT(NL"Radio Diag 0.20"NL);
    00132     tmp = trx_reg_read(RG_TRX_STATUS);
    00133     PRINTF(">RADIO INIT[%s]: %s (status=0x%02x)"NL, BOARD_NAME, (tmp == 8 ? "OK" : "FAIL"), tmp );
    00134     PRINTF("Timer-Tick %lx"NL, TIMER_TICK);
    00135     tmp = trx_reg_read(RG_PART_NUM);
    00136     PRINTF("RADIO_PART_NUM = 0x%02x, RG_PART_NUM = 0x%02x"NL,
    00137        RADIO_PART_NUM, tmp);
    00138     tmp = trx_reg_read(RG_VERSION_NUM);
    00139     PRINTF("RADIO_VERSION_NUM = 0x%02x, RG_VERSION_NUM = 0x%02x"NL,
    00140        RADIO_VERSION_NUM, tmp);
    00141     PRINT("Config: ");
    00142
    00143     /* CONFIG */
    00144 #if 0
    00145     cfgt = radio_config_recall();
    00146     if (cfgt != CFG_NONE)
    00147     {
    00148         PRINTF("use settings from %s"NL, (cfgt == CFG_EEPROM ? "eeprom" : "flash"));
    00149     }
    00150 #else
    00151 #warning "no radio_config_recall()"
    00152 #endif
    00153     th_blink = timer_start(blink,TBLINK_PERIOD,0);
    00154     seq = 0;
    00155
    00156     while(1)
    00157     {
    00158         inchar = hif_getc();
    00159         if(inchar<0x100)
    00160         {
    00161             switch ((char)inchar)
    00162             {
    00163
    00164                 case '+':
    00165                     set_next_channel(+1);
    00166                     break;
    00167                 case '-':
    00168                     set_next_channel(-1);
    00169                     break;
    00170
    00171                 case 'p':
    00172                     set_next_pwr(-1);
    00173                     break;
    00174                 case 'P':
    00175                     set_next_pwr(1);
    00176                     break;
    00177
    00178                 case 'c':
    00179                     tmp = radio_do_cca();
    00180                     PRINTF(">CCA: status=%d"NL, tmp);
    00181                     break;
    00182                 case 'C':
    00183                     set_next_cca();
    00184                     break;
    00185
    00186                 case 'R':
    00187                     toggle_rxon_idle();
    00188                     break;
    00189
    00190                 case 'r':
    00191                     radio_set_state(STATE_RX);
    00192                     PRINT(">SATE_RX"NL);
    00193                     break;
    00194
    00195                 case 't':
    00196                     radio_set_state(STATE_TX);
    00197                     PRINT(">SATE_TX"NL);
    00198                     break;
    00199
    00200                 case 'o':
    00201                     radio_set_state(STATE_OFF);
    00202                     PRINT(">SATE_OFF"NL);
    00203                     break;
    00204
    00205                 case 'l':
    00206                     tx_length += 1;
    00207                     tx_length &= 0x7f;
    00208                     PRINTF(">TX LEN = %d"NL,tx_length);
    00209                     break;
    00210
    00211                 case 'L':
    00212                     tx_length += 10;
    00213                     tx_length &= 0x7f;
    00214                     PRINTF(">TX LEN = %d"NL,tx_length);
    00215                     break;
    00216
    00217                 case 's':
    00218                     send_frame(tx_length);
    00219                     break;
    00220
    00221                 case 'S':
    00222                     send_continous();
    00223                     break;
    00224
    00225                 case 'i':
    00226                     show_statistic(0);
    00227                     break;
    00228
    00229                 case 'I':
    00230                     show_statistic(1);
    00231                     break;
    00232
    00233                 case 'h':
    00234                     help();
    00235                     break;
    00236
    00237                 case 'v':
    00238                     if(verbose>0) verbose --;
    00239                     PRINTF(">VERBOSE: %d"NL,verbose);
    00240                     break;
    00241
    00242                 case 'V':
    00243                     if(verbose<2) verbose ++;
    00244                     PRINTF(">VERBOSE: %d"NL,verbose);
    00245                     break;
    00246
    00247                 case 'g':
    00248                     trx_parms_get(&trxp);
    00249                     PRINTF("{"\
    00250                            "chan: %d, txp: %d,"\
    00251                            " cca: %d,\n\r edt: %d,"\
    00252                            " clkm: %d}"NL,
    00253                             trxp.chan, trxp.txp, trxp.cca,
    00254                             trxp.edt, trxp.clkm);
    00255                     p = (uint8_t*)&trxp;
    00256                     PRINTF("avrdude: w ee 8 0x%x 0x%x 0x%x 0x%x 0x%x"NL,
    00257                            p[0],p[1],p[2],p[3],p[4]);
    00258                     break;
    00259
    00260 #if 0
    00261                 case 'G':
    00262                     radio_config_store();
    00263                     PRINT("params stored in EEPROM"NL);
    00264                     break;
    00265
    00266
    00267                 case 'b':
    00268                     JUMP_BOOT_LOADER();
    00269                     PRINT("There is no BootLoader defined"NL);
    00270                     break;
    00271 #endif
    00272             default:
    00273                     PRINTF("unsuppored command: %s"NL, inchar);
    00274
    00275             }
    00276         }
    00277
    00278         if(rxfrm.new == 1)
    00279         {
    00280             if (verbose > 0)
    00281             {
    00282                 PRINTF("++FRAME len=%d, crc=%3s, lqi=%d ed=%d seq=%d"NL,
    00283                     rxfrm.len, rxfrm.crc ? "ERR" : "OK",
    00284                     rxfrm.lqi, rxfrm.ed, rxfrm.seq);
    00285             }
    00286             if (verbose > 1)
    00287             {
    00288                 DUMP(rxfrm.len, RxBuf);
    00289             }
    00290             rxfrm.new = 0;
    00291         }
    00292
    00293     }
    00294     return 0;
    00295
    00296 }
    00297
    00298
    00299 void rdiag_init(void)
    00300 {
    00301     memset(TxBuf, 0x55, sizeof(TxBuf));
    00302     memset(RxBuf, 0xff, sizeof(RxBuf));
    00303     /* reset ressource  radio parameter */
    00304     LED_INIT();
    00305     KEY_INIT();
    00306     timer_init();
    00307     hif_init(9600);
    00308     radio_init(RxBuf, MAX_FRAME_SIZE);
    00309
    00310     sei();
    00311
    00312     /* init radio parameter */
    00313
    00314     RdiagCtx.channel = TRX_MIN_CHANNEL;
    00315     radio_set_param(RP_CHANNEL(RdiagCtx.channel));
    00316
    00317     RdiagCtx.txpwr = 0;
    00318     radio_set_param(RP_TXPWR(RdiagCtx.txpwr));
    00319
    00320     RdiagCtx.ccamode = 1;
    00321     radio_set_param(RP_CCAMODE(RdiagCtx.ccamode));
    00322
    00323     RdiagCtx.rxidle = false;
    00324     radio_set_param(RP_IDLESTATE(STATE_OFF));
    00325 }
    00326
    00330 void set_next_channel(int8_t chaninc)
    00331 {
    00332
    00333     if (chaninc > 0)
    00334     {
    00335         RdiagCtx.channel = TRX_NEXT_CHANNEL_WRAP(RdiagCtx.channel);
    00336     }
    00337     else if (chaninc < 0)
    00338     {
    00339         RdiagCtx.channel = TRX_PREV_CHANNEL_WRAP(RdiagCtx.channel);
    00340     }
    00341
    00342     radio_set_param(RP_CHANNEL(RdiagCtx.channel));
    00343     PRINTF(">CHAN: %d"NL, RdiagCtx.channel);
    00344 }
    00345
    00349 void toggle_rxon_idle(void)
    00350 {
    00351     RdiagCtx.rxidle ^= 1;
    00352     if (RdiagCtx.rxidle == 1)
    00353     {
    00354         radio_set_param(RP_IDLESTATE(STATE_RX));
    00355     }
    00356     else
    00357     {
    00358         radio_set_param(RP_IDLESTATE(STATE_OFF));
    00359     }
    00360     PRINTF(">RXON_IDLE: %d"NL, RdiagCtx.rxidle);
    00361 }
    00362
    00366 void set_next_pwr(int8_t pwrinc)
    00367 {
    00368
    00369     RdiagCtx.txpwr +=  pwrinc;
    00370     if (RdiagCtx.txpwr > 15)
    00371     {
    00372         RdiagCtx.txpwr = 0;
    00373     }
    00374     else if (RdiagCtx.txpwr < 0)
    00375     {
    00376         RdiagCtx.txpwr = 15;
    00377     }
    00378     radio_set_param(RP_TXPWR(RdiagCtx.txpwr));
    00379     PRINTF(">PWR: %d"NL, RdiagCtx.txpwr);
    00380 }
    00381
    00382
    00386 void set_next_cca(void)
    00387 {
    00388
    00389 char *pcca[] = {"?","ED","CS","CS&ED"};
    00390
    00391     RdiagCtx.ccamode += 1;
    00392     if (RdiagCtx.ccamode > 3)
    00393     {
    00394         RdiagCtx.ccamode = 1;
    00395     }
    00396
    00397     radio_set_param(RP_CCAMODE(RdiagCtx.ccamode));
    00398
    00399     PRINTF(">CCA: mode=%d (%s)"NL, RdiagCtx.ccamode, pcca[RdiagCtx.ccamode]);
    00400 }
    00401
    00402
    00406 void send_frame(uint8_t frmlen)
    00407 {
    00408     static uint8_t seqnb;
    00409
    00410     seqnb ++;
    00411     if (frmlen < 5)
    00412     {
    00413         frmlen = 5;
    00414     }
    00415     if (frmlen > MAX_FRAME_SIZE)
    00416     {
    00417         frmlen = MAX_FRAME_SIZE;
    00418     }
    00419     TxBuf[0] = 1;
    00420     TxBuf[1] = 0;
    00421     TxBuf[2] = seqnb;
    00422     TxBuf[frmlen - 2] = 0;
    00423     TxBuf[frmlen - 1] = 0;
    00424     radio_set_state(STATE_TX);
    00425     radio_send_frame(frmlen, TxBuf, 0);
    00426
    00427     PRINTF(">SEND len=%d"NL,frmlen);
    00428     if (verbose > 1)
    00429     {
    00430         DUMP(frmlen, TxBuf);
    00431     }
    00432 }
    00433
    00437 void send_continous(void)
    00438 {
    00439 static bool active = 0;
    00440
    00441     active  ^= 1;
    00442
    00443     if(active)
    00444     {
    00445         RdiagCtx.rxidle = 2;
    00446         radio_set_param(RP_IDLESTATE(STATE_TX));
    00447     }
    00448     else
    00449     {
    00450         RdiagCtx.rxidle = 0;
    00451         radio_set_param(RP_IDLESTATE(STATE_OFF));
    00452
    00453     }
    00454     PRINTF(">SEND CONTINOUS %s"NL, (RdiagCtx.rxidle ? "START":"STOP"));
    00455     if(RdiagCtx.rxidle)
    00456     {
    00457         send_frame(tx_length);
    00458     }
    00459 }
    00460
    00461
    00462
    00466 uint8_t * usr_radio_receive_frame(uint8_t len, uint8_t *frm, uint8_t lqi,
    00467                                   int8_t ed, uint8_t crc)
    00468 {
    00469     rxfrm.new = 1;
    00470     rxfrm.len = len;
    00471     rxfrm.crc = crc;
    00472     rxfrm.lqi = lqi;
    00473     rxfrm.ed = ed;
    00474     if (rxfrm.len > 3)
    00475     {
    00476         rxfrm.seq = frm[2];
    00477     }
    00478
    00479     RdiagStat.crcerr += ( (crc != 0)||(len==0) ? 1 : 0);
    00480     RdiagStat.rxcnt ++;
    00481     RdiagStat.lqi += lqi;
    00482     RdiagStat.ed += ed;
    00483     return frm;
    00484 }
    00485
    00489 void usr_radio_tx_done(radio_tx_done_t status)
    00490 {
    00491 static uint8_t sn;
    00492    RdiagStat.txcnt++;
    00493    if(conttx)
    00494    {
    00495         /* force next frame sending */
    00496         TRX_SLPTR_HIGH();
    00497         TRX_SLPTR_LOW();
    00498         trx_sram_write(3, 1, &sn);
    00499         sn ++;
    00500    }
    00501 }
    00502
    00506 void show_statistic(bool reset)
    00507 {
    00508
    00509 time_t now;
    00510
    00511     now = timer_systime();
    00512     PRINTF(
    00513         ">STAT"
    00514         " duration: %ld ticks"NL,
    00515             now - RdiagStat.start);
    00516
    00517     PRINTF(
    00518         " RX:"
    00519         " frames: %ld"
    00520         " crcerr: %ld"NL,
    00521             RdiagStat.rxcnt, RdiagStat.crcerr);
    00522     PRINTF(
    00523         " RX: channel %d"
    00524         " avg ed: %ld"
    00525         " avg lqi:  %ld"NL,
    00526             RdiagCtx.channel,
    00527             RdiagStat.ed/RdiagStat.rxcnt, RdiagStat.lqi/RdiagStat.rxcnt);
    00528
    00529     PRINTF(
    00530         " TX:"
    00531         " frames: %ld"NL,
    00532             RdiagStat.txcnt);
    00533     if (reset)
    00534     {
    00535         memset(&RdiagStat, 0, sizeof(RdiagStat));
    00536         RdiagStat.start = timer_systime();
    00537     }
    00538 }
    00539
    00540
    00544 void usr_radio_error(radio_error_t err)
    00545 {
    00546 uint8_t regval, r2, r3;
    00547 uint16_t t;
    00548     regval = trx_reg_read(RG_TRX_STATUS);
    00549     r2 = trx_reg_read(0x30);
    00550     r3 = trx_reg_read(RG_VREG_CTRL);
    00551     while(1)
    00552     {
    00553
    00554         PRINTF("\n\rRADIO ERROR : %d radio status : 0x%02x:0x%02x:0x%02x\n\r",
    00555                 err, regval, r2, r3);
    00556         t = 2000;
    00557         while(t--)
    00558         {
    00559             DELAY_US(1000);
    00560         }
    00561     }
    00562 }
    00563
    00564
    00565
    00569 void help(void)
    00570 {
    00571     PRINT("i/I : show / show and reset statistic"NL);
    00572     PRINT("o   : set state OFF"NL);
    00573     PRINT("r   : set state RX"NL);
    00574     PRINT("t   : set state TX"NL);
    00575     PRINT("+/- : incr./decr. channel"NL);
    00576     PRINT("s   : send a test frame"NL);
    00577     PRINT("S   : start/stop continous sending frames"NL);
    00578     PRINT("R   : toggle RXON_IDLE parameter"NL);
    00579     PRINT("P/p : incr./decr. power"NL);
    00580     PRINT("c   : do CCA measurement"NL);
    00581     PRINT("C   : change CCA mode"NL);
    00582     PRINT("V/v : incr./decr. verbosity (0...2)"NL);
    00583     PRINT("G/g : store/show seetings"NL);
    00584 }
    00585
    00586
    00587
    00588
    00592 time_t blink(timer_arg_t t)
    00593 {
    00594 #if LED_NUMBER > 0
    00595 static volatile uint8_t btick;
    00596 #endif
    00597     LED_SET_VALUE(btick++);
    00598     /* restart the timer again */
    00599     return  TBLINK_PERIOD;
    00600 }
    00601