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
00040 #include <string.h>
00041 #include "radio.h"
00042 #include "transceiver.h"
00043 #include "ioutil.h"
00044 #include "timer.h"
00045
00046
00047 typedef struct
00048 {
00049 uint8_t new;
00050 uint8_t len;
00051 uint8_t crc;
00052 uint8_t lqi;
00053 uint8_t rssi;
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 rssi;
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
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
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
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 rssi=%d seq=%d"NL,
00283 rxfrm.len, rxfrm.crc ? "ERR" : "OK",
00284 rxfrm.lqi, rxfrm.rssi, 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
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
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 uint8_t rssi, uint8_t crc)
00468 {
00469 rxfrm.new = 1;
00470 rxfrm.len = len;
00471 rxfrm.crc = crc;
00472 rxfrm.lqi = lqi;
00473 rxfrm.rssi = rssi;
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.rssi += rssi;
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
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 rssi: %ld"
00525 " avg lqi: %ld"NL,
00526 RdiagCtx.channel,
00527 RdiagStat.rssi/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
00599 return TBLINK_PERIOD;
00600 }
00601