void radio_init(uint8_t * rxbuf, uint8_t rxbufsz) { trx_regval_t status; /* init cpu peripherals and global IRQ enable */ radiostatus.rxframe = rxbuf; radiostatus.rxframesz = rxbufsz; //trx_set_irq_handler(radio_irq_handler); /* transceiver initialization */ TRX_RESET_LOW(); TRX_SLPTR_LOW(); DELAY_US(TRX_RESET_TIME_US); #if defined(CUSTOM_RESET_TIME_MS) DELAY_MS(CUSTOM_RESET_TIME_MS); #endif TRX_RESET_HIGH(); /* disable IRQ and clear any pending IRQs */ trx_reg_write(RG_IRQ_MASK, 0); trx_reg_read(RG_IRQ_STATUS); trx_bit_write(SR_TRX_CMD, CMD_TRX_OFF); DELAY_US(510); status = trx_bit_read(SR_TRX_STATUS); if (status != TRX_OFF) { radio_error(STATE_SET_FAILED); } trx_bit_write(SR_TX_AUTO_CRC_ON, 1); trx_reg_write(RG_IRQ_MASK, TRX_IRQ_RX_START | TRX_IRQ_RX_END | TRX_IRQ_TX_END); radiostatus.state = STATE_OFF; radiostatus.idle_state = STATE_OFF; }
void radio_send_frame(uint8_t len, uint8_t *frm, uint8_t compcrc) { trx_frame_write(len, frm); // frm[2] = frm[2]+1; TRX_SLPTR_HIGH(); TRX_SLPTR_LOW(); }
void radio_send_frame(uint8_t len, uint8_t *frm, uint8_t compcrc) { /* this block should be made atomic */ trx_frame_write(len, frm); TRX_SLPTR_HIGH(); TRX_SLPTR_LOW(); /***********************************/ }
void radio_init(uint8_t * rxbuf, uint8_t rxbufsz) { trx_regval_t status; /* init cpu peripherals and global IRQ enable */ radiostatus.rxframe = rxbuf; radiostatus.rxframesz = rxbufsz; trx_io_init(DEFAULT_SPI_RATE); trx_set_irq_handler(radio_irq_handler); /* transceiver initialization */ TRX_RESET_LOW(); TRX_SLPTR_LOW(); DELAY_US(TRX_RESET_TIME_US); #if defined(CUSTOM_RESET_TIME_MS) DELAY_MS(CUSTOM_RESET_TIME_MS); #endif TRX_RESET_HIGH(); /* disable IRQ and clear any pending IRQs */ trx_reg_write(RG_IRQ_MASK, 0); trx_reg_read(RG_IRQ_STATUS); #if RADIO_TYPE == RADIO_AT86RF212 trx_reg_write(RG_TRX_CTRL_0, 0x19); #ifdef CHINABAND trx_reg_write(RG_CC_CTRL_1, CCBAND ); trx_reg_write(RG_CC_CTRL_0, CCNUMBER);//channel 0 trx_reg_write(RG_TRX_CTRL_2, TRX_OQPSK250); /*trx_bit_write(SR_OQPSK_SUB1_RC_EN,1); trx_bit_write(SR_BPSK_OQPSK,1); trx_bit_write(SR_SUB_MODE,1); trx_bit_write(SR_OQPSK_DATA_RATE,0); trx_bit_write(SR_CC_BAND,CCBAND); */ DELAY_US(510); #endif trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF); DELAY_US(510); #else trx_bit_write(SR_TRX_CMD, CMD_TRX_OFF); DELAY_US(510); #endif do { status = trx_bit_read(SR_TRX_STATUS); } while (status != TRX_OFF); trx_bit_write(SR_TX_AUTO_CRC_ON, 1); trx_reg_write(RG_IRQ_MASK, TRX_IRQ_RX_START | TRX_IRQ_TRX_END); radiostatus.state = STATE_OFF; radiostatus.idle_state = STATE_OFF; }
void radio_send_frame(uint8_t len, uint8_t *frm, uint8_t compcrc) { #ifdef TRX_TX_PA_EI if (radiostatus.tx_pa) { TRX_TX_PA_EI(); } #endif /* this block should be made atomic */ TRX_SLPTR_HIGH(); TRX_SLPTR_LOW(); trx_frame_write(len, frm); /***********************************/ }
int main(void) { trx_regval_t rval; /* This will stop the application before initializing the radio transceiver * (ISP issue with MISO pin, see FAQ) */ trap_if_key_pressed(); /* Step 0: init MCU peripherals */ LED_INIT(); trx_io_init(SPI_RATE_1_2); LED_SET_VALUE(LED_MAX_VALUE); LED_SET_VALUE(0); /* Step 1: initialize the transceiver */ TRX_RESET_LOW(); TRX_SLPTR_LOW(); DELAY_US(TRX_RESET_TIME_US); TRX_RESET_HIGH(); trx_reg_write(RG_TRX_STATE,CMD_TRX_OFF); DELAY_US(TRX_INIT_TIME_US); rval = trx_bit_read(SR_TRX_STATUS); ERR_CHECK(TRX_OFF!=rval); LED_SET_VALUE(1); /* Step 2: setup transmitter * - configure radio channel * - go into RX state, * - enable "receive end" IRQ */ trx_bit_write(SR_CHANNEL,CHANNEL); trx_reg_write(RG_TRX_STATE,CMD_RX_ON); #if defined(TRX_IRQ_TRX_END) trx_reg_write(RG_IRQ_MASK,TRX_IRQ_TRX_END); #elif defined(TRX_IRQ_RX_END) trx_reg_write(RG_IRQ_MASK,TRX_IRQ_RX_END); #else # error "Unknown IRQ bits" #endif sei(); LED_SET_VALUE(2); /* Step 3: Going to receive frames */ rxcnt = 0; LED_SET_VALUE(0); while(1); }
uint8_t wibo_run(void) { uint8_t isLeave=0; uint8_t isStay=0; unsigned long timeout = WIBO_TIMEOUT; while(!isLeave) { #if !defined(NO_LEDS) LED_CLR(PROGLED); #endif if (!(isStay)) { while(!(wibo_available()) && (timeout--)) _delay_ms(1); // minimum frame time @ 250kbps ~ 2ms. if (!(wibo_available())) // no packets received, bye bye! { isLeave=1; return isLeave; } } else { while(!(wibo_available())); // wait for next packet } trx_reg_write(RG_IRQ_STATUS, TRX_IRQ_RX_END); /* clear the flag */ trx_frame_read(rxbuf.data, sizeof(rxbuf.data) / sizeof(rxbuf.data[0]), &tmp); /* dont use LQI, write into tmp variable */ #if !defined(NO_LEDS) LED_SET(PROGLED); /* light as long as actions are running */ #endif switch (rxbuf.hdr.cmd) { case P2P_PING_REQ: isStay=1; if (0 == deaf) { pingrep.hdr.dst = rxbuf.hdr.src; pingrep.hdr.seq++; pingrep.crc = datacrc; trx_reg_write(RG_TRX_STATE, CMD_TX_ARET_ON); /* no need to make block atomic since no IRQs are used */ TRX_SLPTR_HIGH() ; TRX_SLPTR_LOW() ; trx_frame_write(sizeof(p2p_ping_cnf_t) + sizeof(BOARD_NAME) + 2, (uint8_t*) &pingrep); /*******************************************************/ #if defined(_DEBUG_SERIAL_) printf("Pinged by 0x%04X"EOL, rxbuf.hdr.src); #endif #if defined(TRX_IF_RFA1) while (!(trx_reg_read(RG_IRQ_STATUS) & TRX_IRQ_TX_END)) ; trx_reg_write(RG_IRQ_STATUS, TRX_IRQ_TX_END); /* clear the flag */ #else while (!(trx_reg_read(RG_IRQ_STATUS) & TRX_IRQ_TRX_END)) ; #endif /* defined(TRX_IF_RFA1) */ trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON); } /* (0 == deaf) */ break; case P2P_WIBO_TARGET: isStay=1; target = rxbuf.wibo_target.targmem; #if defined(_DEBUG_SERIAL_) printf("Set Target to %c"EOL, target); #endif break; case P2P_WIBO_RESET: isStay=1; #if defined(_DEBUG_SERIAL_) printf("Reset"EOL); #endif addr = SPM_PAGESIZE; /* misuse as counter */ ptr = pagebuf; do { *ptr++ = 0xFF; } while (--addr); addr = 0; datacrc = 0; pagebufidx = 0; deaf = 0; break; case P2P_WIBO_ADDR: isStay=1; #if defined(_DEBUG_SERIAL_) printf("Set address: 0x%08lX"EOL, rxbuf.wibo_addr.address); #endif addr = rxbuf.wibo_addr.address; pagebufidx = 0; break; case P2P_WIBO_DATA: isStay=1; #if defined(_DEBUG_SERIAL_) printf("Data[%d]", rxbuf.wibo_data.dsize); uint8_t len = rxbuf.wibo_data.dsize; if (len > 10) len = 10; for(uint8_t j=0;j<len;j++) { printf(" %02X", rxbuf.wibo_data.data[j]); } if (len != rxbuf.wibo_data.dsize) printf("..."); printf(EOL); #endif tmp = rxbuf.wibo_data.dsize; ptr = rxbuf.wibo_data.data; do { datacrc = _crc_ccitt_update(datacrc, *ptr); pagebuf[pagebufidx++] = *ptr; if (pagebufidx >= PAGEBUFSIZE) { /* LED off to save current and avoid flash corruption * because of possible voltage drops */ #if !defined(NO_LEDS) LED_CLR(PROGLED); #endif if (target == 'F') /* Flash memory */ { boot_program_page(addr, pagebuf); } else if (target == 'E') { /* not implemented */ } else { /* unknown target, dry run */ } /* also for dry run! */ addr += SPM_PAGESIZE; pagebufidx = 0; } ptr++; } while (--tmp); break; #if defined(WIBO_FLAVOUR_BOOTLUP) case P2P_WIBO_BOOTLUP: isStay=1; bootlup(); break; #endif case P2P_WIBO_FINISH: isStay=1; #if defined(_DEBUG_SERIAL_) printf("Finish"EOL); #endif if (target == 'F') /* Flash memory */ { boot_program_page(addr, pagebuf); } else if (target == 'E') { /* not implemented */ } else { /* unknown target, dry run */ } /* also for dry run! */ addr += SPM_PAGESIZE; pagebufidx = 0; break; case P2P_WIBO_EXIT: #if defined(_DEBUG_SERIAL_) printf("Exit"EOL); #endif #if !defined(NO_LEDS) LED_CLR(PROGLED); #endif isLeave=1; break; case P2P_WIBO_DEAF: isStay=1; deaf = 1; break; default: /* unknown or unhandled command */ if (!(isStay)) { if (!(timeout--)) { isLeave = 1; } } break; }; /* switch (rxbuf.hdr.cmd) */ } return isLeave; }
void wibo_init(uint8_t channel, uint16_t pan_id, uint16_t short_addr, uint64_t ieee_addr) { #if defined(WIBO_FLAVOUR_KEYPRESS) || defined(WIBO_FLAVOUR_MAILBOX) uint8_t run_bootloader = 0; #endif /* only stay in bootloader if key is pressed */ #if defined(WIBO_FLAVOUR_KEYPRESS) #if defined(NO_KEYS) #error "No Keys defined for WIBO_FLAVOUR_KEYPRESS" #endif KEY_INIT(); if(KEY_GET() != 0) { run_bootloader = 1; } #endif /* defined(WIBO_FLAVOUR_KEYPRESS) */ #if defined(WIBO_FLAVOUR_MAILBOX) #if !defined(WIBO_FLAVOUR_MAILBOX_REGISTER) || !defined(WIBO_FLAVOUR_MAILBOX_CODE) #error "WIBO_FLAVOUR_MAILBOX not defined correctly" #endif if(WIBO_FLAVOUR_MAILBOX_REGISTER == WIBO_FLAVOUR_MAILBOX_CODE) { run_bootloader = 1; } //WIBO_MAILBOX_CLR(); #endif /* defined(WIBO_FLAVOUR_MAILBOX) */ #if defined(WIBO_FLAVOUR_KEYPRESS) || defined(WIBO_FLAVOUR_MAILBOX) if(run_bootloader == 0) { app(); } #endif #if !defined(NO_LEDS) LED_INIT(); LED_SET(PROGLED); #endif nodeconfig.channel=channel; nodeconfig.pan_id=pan_id; nodeconfig.short_addr=short_addr; nodeconfig.ieee_addr = ieee_addr; trx_io_init(DEFAULT_SPI_RATE); TRX_RESET_LOW(); TRX_SLPTR_LOW(); TRX_RESET_HIGH(); #if defined(DI_TRX_IRQ) DI_TRX_IRQ(); #endif trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF); #if (RADIO_TYPE == RADIO_AT86RF230A) || (RADIO_TYPE == RADIO_AT86RF230B) trx_reg_write(RG_PHY_TX_PWR, 0x80); /* set TX_AUTO_CRC bit, and TX_PWR = max */ #else trx_reg_write(RG_TRX_CTRL_1, 0x20); /* set TX_AUTO_CRC bit */ #endif /* setup network addresses for auto modes */ pingrep.hdr.pan = nodeconfig.pan_id; pingrep.hdr.src = nodeconfig.short_addr; trx_set_panid(nodeconfig.pan_id); trx_set_shortaddr(nodeconfig.short_addr); /* use register write to save code space, overwrites Bits CCA_REQUEST CCA_MODE[1] CCA_MODE[0] * which is accepted */ trx_reg_write(RG_PHY_CC_CCA, nodeconfig.channel); #if RADIO_TYPE == RADIO_AT86RF212 /* reset value, BPSK-40 */ /* trx_reg_write(RG_TRX_CTRL_2, 0x24); */ /* +5dBm acc. to datasheet AT86RF212 table 7-15 */ trx_reg_write(RG_PHY_TX_PWR, 0x84); #endif /* RADIO_TYPE == RADIO_AT86RF212 */ trx_reg_write(RG_CSMA_SEED_0, nodeconfig.short_addr); /* some seeding */ trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON); trx_reg_write(RG_IRQ_STATUS, TRX_IRQ_RX_END); /* clear the flag */ #if defined(_DEBUG_SERIAL_) void sendchar(char c); static FILE usart_stdio = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE); stdout = stderr = &usart_stdio; printf("WIBO Bootlapp Serial Debug"EOL); printf("PANID=%04X SHORTADDR=%04X CHANNEL=%d"EOL, nodeconfig.pan_id, nodeconfig.short_addr, nodeconfig.channel); #endif }
void radio_set_state(volatile radio_state_t state) { volatile trx_regval_t cmd, expstatus, currstatus; uint8_t retries; bool do_sleep = false; switch(state) { case STATE_OFF: expstatus = TRX_OFF; cmd = CMD_TRX_OFF; break; case STATE_RX: expstatus = RX_ON; cmd = CMD_RX_ON; break; case STATE_TX: expstatus = PLL_ON; cmd = CMD_PLL_ON; break; case STATE_RXAUTO: expstatus = RX_AACK_ON; cmd = CMD_RX_AACK_ON; break; case STATE_TXAUTO: expstatus = TX_ARET_ON; cmd = CMD_TX_ARET_ON; break; case STATE_SLEEP: expstatus = TRX_OFF; cmd = CMD_FORCE_TRX_OFF; do_sleep = true; break; default: radio_error(GENERAL_ERROR); expstatus = TRX_OFF; cmd = CMD_TRX_OFF; break; } if (STATE_SLEEP == radiostatus.state) { if (do_sleep) { return; } TRX_SLPTR_LOW(); /* * Give the xosc some time to start up. Once it started, the * SPI interface is operational, and the transceiver state can * be polled. The state reads as 0b0011111 ("state transition * in progress") while the transceiver is still in its startup * phase, which does not match any of the "expstatus" values, * so polling just continues. */ DELAY_US(500); /* * The exact wake-up timing is very board-dependent. * Contributing parameters are the effective series resitance * of the crystal, and the external bypass capacitor that has * to be charged by the voltage regulator. Give the crystal * oscillator some time to start up. 5 ms (100 * 50 us) ought * to be enough under all circumstances. */ retries = 100; do { currstatus = trx_bit_read(SR_TRX_STATUS); /* * Sleep could only be entered from TRX_OFF, so that's * what is expected again. */ if (TRX_OFF == currstatus) { break; } DELAY_US(50); } while (--retries); if (currstatus != TRX_OFF) { /* radio didn't wake up */ radio_error(STATE_SET_FAILED); } } trx_bit_write(SR_TRX_CMD, cmd); retries = 140; /* enough to await an ongoing frame * reception */ do { currstatus = trx_bit_read(SR_TRX_STATUS); if (expstatus == currstatus) { break; } /** @todo must wait longer for 790/868/900 MHz radios */ DELAY_US(32); } while (--retries); if (expstatus != currstatus) { radio_error(STATE_SET_FAILED); } if (do_sleep) { TRX_SLPTR_HIGH(); } radiostatus.state = state; }
void radio_set_state(radio_state_t state) { volatile trx_regval_t cmd, expstatus, currstatus; uint8_t retries; bool do_sleep = false; switch(state) { case STATE_OFF: expstatus = TRX_OFF; cmd = CMD_TRX_OFF; break; case STATE_RX: expstatus = RX_ON; cmd = CMD_RX_ON; break; case STATE_TX: expstatus = PLL_ON; cmd = CMD_PLL_ON; break; case STATE_RXAUTO: expstatus = RX_AACK_ON; cmd = CMD_RX_AACK_ON; break; case STATE_TXAUTO: expstatus = TX_ARET_ON; cmd = CMD_TX_ARET_ON; break; case STATE_SLEEP: expstatus = TRX_OFF; cmd = CMD_FORCE_TRX_OFF; do_sleep = true; break; default: radio_error(GENERAL_ERROR); expstatus = TRX_OFF; cmd = CMD_TRX_OFF; break; } if (STATE_SLEEP == radiostatus.state) { if (do_sleep) { return; } TRX_SLPTR_LOW(); /* * Give the xosc some time to start up. Once it started, the * SPI interface is operational, and the transceiver state can * be polled. The state reads as 0b0011111 ("state transition * in progress") while the transceiver is still in its startup * phase, which does not match any of the "expstatus" values, * so polling just continues. */ DELAY_US(500); } trx_bit_write(SR_TRX_CMD, cmd); retries = 140; /* enough to await an ongoing frame * reception */ do { currstatus = trx_bit_read(SR_TRX_STATUS); if (expstatus == currstatus) { break; } /** @todo must wait longer for 790/868/900 MHz radios */ DELAY_US(32); } while (--retries); if (expstatus != currstatus) { radio_error(STATE_SET_FAILED); } if (do_sleep) { TRX_SLPTR_HIGH(); } radiostatus.state = state; }
int main(void) { trx_regval_t rval; /* This will stop the application before initializing the radio transceiver * (ISP issue with MISO pin, see FAQ) */ trap_if_key_pressed(); /* Step 0: init MCU peripherals */ LED_INIT(); trx_io_init(SPI_RATE_1_2); LED_SET_VALUE(LED_MAX_VALUE); LED_SET_VALUE(0); /* Step 1: initialize the transceiver */ TRX_RESET_LOW(); TRX_SLPTR_LOW(); DELAY_US(TRX_RESET_TIME_US); TRX_RESET_HIGH(); trx_reg_write(RG_TRX_STATE,CMD_TRX_OFF); DELAY_MS(TRX_INIT_TIME_US); rval = trx_bit_read(SR_TRX_STATUS); ERR_CHECK(TRX_OFF!=rval); LED_SET_VALUE(1); /* Step 2: setup transmitter * - configure radio channel * - enable transmitters automatic crc16 generation * - go into RX AACK state, * - configure address filter * - enable "receive end" IRQ */ trx_bit_write(SR_CHANNEL,CHANNEL); trx_bit_write(SR_TX_AUTO_CRC_ON,1); trx_reg_write(RG_PAN_ID_0,(PANID&0xff)); trx_reg_write(RG_PAN_ID_1,(PANID>>8)); trx_reg_write(RG_SHORT_ADDR_0,(SHORT_ADDR&0xff)); trx_reg_write(RG_SHORT_ADDR_1,(SHORT_ADDR>>8)); trx_reg_write(RG_TRX_STATE,CMD_RX_AACK_ON); #if defined(TRX_IRQ_TRX_END) trx_reg_write(RG_IRQ_MASK,TRX_IRQ_TRX_END); #elif defined(TRX_IRQ_RX_END) trx_reg_write(RG_IRQ_MASK,TRX_IRQ_RX_END); #else # error "Unknown IRQ bits" #endif sei(); LED_SET_VALUE(2); /* Step 3: send a frame each 500ms */ tx_cnt = 0; tx_in_progress = false; LED_SET_VALUE(0); while(1); }