/** * @brief radio_set_state to STATE_RX * * bring the the radio in the requested state of STATE_RX * * the radio state does not return to STATE_RX automatically if ZR_TXWAIT_AFTER is not used * thus why this is provided * * see radio.h for more info */ void cMxRadio::setStateRx() { if (setautorx) radio_set_state(STATE_RXAUTO); else radio_set_state(STATE_RX); }
void p2p_send(uint16_t dst, uint8_t cmd, uint8_t flags, uint8_t *data, uint8_t lendata) { p2p_hdr_t *hdr = (p2p_hdr_t*) data; __FILL_P2P_HEADER__(hdr, ((flags & P2P_ACK) ? 0x8861 : 0x8841), NodeConfig.pan_id, dst, NodeConfig.short_addr, cmd); radio_set_state(STATE_TX); radio_set_state(STATE_TXAUTO); radio_send_frame(lendata + 2, data, 1); /* +2: add CRC bytes (FCF) */ }
/** * @brief IRQ handler for radio functions. * * This function is called in the transceiver interrupt routine. * Keep the implementation of the callback functions * (usr_radio_irq, usr_radio_receive_frame) short and efficient. * * @parm cause value of the interrupt status register * */ void radio_irq_handler(uint8_t cause) { if (cause & TRX_IRQ_TRX_END) { if (STATE_RX == radiostatus.state || STATE_RXAUTO == radiostatus.state) { radio_receive_frame(); } else if (STATE_TX == radiostatus.state) { #ifdef TRX_TX_PA_EI TRX_TX_PA_DI(); #endif usr_radio_tx_done(TX_OK); radio_set_state(radiostatus.idle_state); } else if (STATE_TXAUTO == radiostatus.state) { #ifdef TRX_TX_PA_EI TRX_TX_PA_DI(); #endif uint8_t trac_status = trx_bit_read(SR_TRAC_STATUS); uint8_t result; switch (trac_status) { case TRAC_SUCCESS: #if defined TRAC_SUCCESS_DATA_PENDING case TRAC_SUCCESS_DATA_PENDING: #endif #if defined TRAC_SUCCESS_WAIT_FOR_ACK case TRAC_SUCCESS_WAIT_FOR_ACK: #endif result = TX_OK; break; case TRAC_CHANNEL_ACCESS_FAILURE: result = TX_CCA_FAIL; break; case TRAC_NO_ACK: result = TX_NO_ACK; break; default: result = TX_FAIL; } usr_radio_tx_done(result); radio_set_state(radiostatus.idle_state); } } usr_radio_irq(cause); }
/** * @brief Raw Frame Transmit * * Transmits a frame * Warning: no frame header or FCS is added * * @param frm array containing frame data * @param len length of the frame */ void zr_txFrame(uint8_t* frm, uint8_t len) { #ifdef ZRC_TXWAIT_BEFORE zr_waitTxDone(0xFFFF); #endif zr_txIsBusy = 1; radio_set_state(STATE_TX); ZR_RFTX_LED_ON(); radio_send_frame(len, frm, 0); #ifdef ZRC_TXWAIT_AFTER zr_waitTxDone(0xFFFF); radio_set_state(STATE_RX); zr_txIsBusy = 0; #endif }
/** * @brief Set Radio State Wrapper * * sets or forces the radio into a state * * see radio.h for more info * * @param state requested radio state * @param force boolean indicating to force the state */ void cMxRadio::setState(radio_state_t state, uint8_t force) { if (force) radio_force_state(state); else radio_set_state(state); }
char p2p_init() { char cfg_location = '?'; /* === read node configuration data ===================================== */ /* 1st trial: read from EEPROM */ if (get_node_config_eeprom(&NodeConfig, 0) == 0) { /* using EEPROM config */; cfg_location = 'E'; } /* 2nd trial: read from FLASHEND */ else if (get_node_config(&NodeConfig) == 0) { /* using FLASHEND config */; cfg_location = 'F'; } /* 3rd trial: read default values compiled into the application */ else { /* using application default config */; memcpy_P(&NodeConfig, (PGM_VOID_P) & nc_flash, sizeof(node_config_t)); cfg_location = 'D'; } radio_init(rxbuf, sizeof(rxbuf)/sizeof(rxbuf[0])); radio_set_state(STATE_OFF); radio_set_param(RP_IDLESTATE(STATE_OFF)); radio_set_param(RP_CHANNEL(NodeConfig.channel)); radio_set_param(RP_SHORTADDR(NodeConfig.short_addr)); radio_set_param(RP_PANID(NodeConfig.pan_id)); return cfg_location; }
/** * @brief TX a Byte * * If "beginTrasmission" was used, then it writes into the transmit buffer for non-immediate mode * If "beginTrasmission" was not used, then it transmits the single byte immediately (slower for multiple bytes) * * @param c character to be sent */ void cMxRadio::write(uint8_t c) { if (usedBeginTransmission) { if (txTmpBufferLength < ZR_TXTMPBUFF_SIZE - 2) { txTmpBuffer[txTmpBufferLength] = c; txTmpBufferLength++; if (txTmpBufferLength >= ZR_TXTMPBUFF_SIZE - 2) { // buffer is now full // just send it all out so we have more room endTransmission(); beginTransmission(); } } } else { txTmpBuffer[HeadSize] = c; // set payload txTmpBuffer[HeadSize+1] = 0; // empty FCS txTmpBuffer[HeadSize+2] = 0; // empty FCS #ifdef ZR_TXWAIT_BEFORE waitTxDone(0xFFFF); #endif txIsBusy = 1; if (setautotx) radio_set_state(STATE_TXAUTO); else radio_set_state(STATE_TX); ZR_RFTX_LED_ON(); radio_send_frame(10, txTmpBuffer, 0); #ifdef ZR_TXWAIT_AFTER waitTxDone(0xFFFF); if (setautorx) radio_set_state(STATE_RXAUTO); else radio_set_state(STATE_RX); txIsBusy = 0; #endif } }
/** * @brief Finalize Trasmission * * Finalize the payload and transmits it when ready * */ void zr_endTransmission() { zr_usedBeginTransmission = 0; // empty FCS field zr_txTmpBufferLength += 2; #ifdef ZRC_TXWAIT_BEFORE zr_waitTxDone(0xFFFF); #endif zr_txIsBusy = 1; radio_set_state(STATE_TX); ZR_RFTX_LED_ON(); radio_send_frame(zr_txTmpBufferLength, zr_txTmpBuffer, 0); #ifdef ZRC_TXWAIT_AFTER zr_waitTxDone(0xFFFF); radio_set_state(STATE_RX); zr_txIsBusy = 0; #endif }
/** * @brief Raw Frame Transmit * * Transmits a frame * Warning: no frame header or FCS is added * * @param frm array containing frame data * @param len length of the frame */ void cMxRadio::txFrame(uint8_t* frm, uint8_t len) { #ifdef ZR_TXWAIT_BEFORE waitTxDone(0xFFFF); #endif txIsBusy = 1; if (setautotx) radio_set_state(STATE_TXAUTO); else radio_set_state(STATE_TX); ZR_RFTX_LED_ON(); radio_send_frame(len, frm, 0); #ifdef ZR_TXWAIT_AFTER waitTxDone(0xFFFF); if (setautorx) radio_set_state(STATE_RXAUTO); else radio_set_state(STATE_RX); txIsBusy = 0; #endif }
void cMxRadio::begin(channel_t chan,uint16_t panid,uint16_t localaddress,bool needackval,bool autotxval,bool autorxval,char autoretrycount) { setautotx=autotxval; setautorx=autorxval; needack=needackval; radio_init(rxFrameBuffer, MAX_FRAME_SIZE); ////////////////////////////// #ifdef SR_MAX_FRAME_RETRES trx_bit_write(SR_MAX_FRAME_RETRES,autoretrycount & 0Xf);//for auto wake up ////////////////////////////// #endif if(!needack) txTmpBuffer[0] = 0x41; else txTmpBuffer[0] = 0x61; //ack required txTmpBuffer[1] = 0x88; txTmpBuffer[2] = 0; txTmpBuffer[3]=(uint8_t)(panid & 0xFF ); txTmpBuffer[4]=(uint8_t)((panid>>8) & 0xFF ); txTmpBuffer[5] = 0xFF; //dest address low byte txTmpBuffer[6] = 0xFF; //dest address hight byte txTmpBuffer[7] = (uint8_t)(localaddress & 0xFF ); txTmpBuffer[8] = (uint8_t)((localaddress>>8) & 0xFF ); setParam(phyPanId,(uint16_t)panid ); setParam(phyShortAddr,(uint16_t)localaddress ); radio_set_param(RP_CHANNEL(chan)); // default to receiver if (setautorx) radio_set_state(STATE_RXAUTO); else radio_set_state(STATE_RX); #ifdef ENABLE_DIG3_DIG4 trx_bit_write(SR_PA_EXT_EN, 1); #endif }
/** * @brief Radio Initialization * * Overload for radio initalization that allows for the user to set a custom frame header * * @param chan channel number for the radio to use, 11 to 26 * @param frameHeader HeadSize byte custom frame header */ void cMxRadio::begin(channel_t chan, uint8_t* frameHeader) { radio_init(rxFrameBuffer, MAX_FRAME_SIZE); if (frameHeader) { // copy custom frame header int i; for (i = 0; i < HeadSize; i++) txTmpBuffer[i] = frameHeader[i]; } else { txTmpBuffer[0] = 0x41; txTmpBuffer[1] = 0x88; txTmpBuffer[2] = 0; txTmpBuffer[3]=0xCD; txTmpBuffer[4]=0xAB; txTmpBuffer[5] = 0xFF; //dest address low byte txTmpBuffer[6] = 0xFF; //dest address hight byte txTmpBuffer[7] = 0x01;; txTmpBuffer[8] = 0x00;; } // set the channel radio_set_param(RP_CHANNEL(chan)); // default to receiver if (setautorx) radio_set_state(STATE_RXAUTO); else radio_set_state(STATE_RX); #ifdef ENABLE_DIG3_DIG4 trx_bit_write(SR_PA_EXT_EN, 1); #endif }
/** * @brief TX a Byte * * If "beginTrasmission" was used, then it writes into the transmit buffer for non-immediate mode * If "beginTrasmission" was not used, then it transmits the single byte immediately (slower for multiple bytes) * * @param c character to be sent */ void zr_write(uint8_t c) { if (zr_usedBeginTransmission) { if (zr_txTmpBufferLength < ZRC_TXTMPBUFF_SIZE - 2) { zr_txTmpBuffer[zr_txTmpBufferLength] = c; zr_txTmpBufferLength++; if (zr_txTmpBufferLength >= ZRC_TXTMPBUFF_SIZE - 2) { // buffer is now full // just send it all out so we have more room zr_endTransmission(); zr_beginTransmission(); } } } else { zr_txTmpBuffer[7] = c; // set payload zr_txTmpBuffer[8] = 0; // empty FCS zr_txTmpBuffer[9] = 0; // empty FCS #ifdef ZRC_TXWAIT_BEFORE zr_waitTxDone(0xFFFF); #endif zr_txIsBusy = 1; radio_set_state(STATE_TX); ZR_RFTX_LED_ON(); radio_send_frame(10, zr_txTmpBuffer, 0); #ifdef ZRC_TXWAIT_AFTER zr_waitTxDone(0xFFFF); radio_set_state(STATE_RX); zr_txIsBusy = 0; #endif } }
/** * @brief Finalize Trasmission * * Finalize the payload and transmits it when ready * */ void cMxRadio::endTransmission() { usedBeginTransmission = 0; // empty FCS field txTmpBufferLength += 2; #ifdef ZR_TXWAIT_BEFORE waitTxDone(0xFFFF); #endif txIsBusy = 1; if (setautotx) radio_set_state(STATE_TXAUTO); else radio_set_state(STATE_TX); ZR_RFTX_LED_ON(); //if broadcase ,cant need ack if(txTmpBuffer[5]==0xff && txTmpBuffer[5]==0xff) txTmpBuffer[0]=txTmpBuffer[0]&0xdf; else { if(!needack) txTmpBuffer[0] = 0x41; else txTmpBuffer[0] = 0x61; //ack required } radio_send_frame(txTmpBufferLength, txTmpBuffer, 0); #ifdef ZR_TXWAIT_AFTER waitTxDone(0xFFFF); if (setautorx) radio_set_state(STATE_RXAUTO); else radio_set_state(STATE_RX); txIsBusy = 0; #endif }
void app_init(void) { LED_INIT(); KEY_INIT(); hif_init(HIF_DEFAULT_BAUDRATE); timer_init(); radio_init(RxFrame, sizeof(RxFrame)); radio_set_state(STATE_OFF); radio_set_param(RP_CHANNEL(CHANNEL)); radio_set_param(RP_IDLESTATE(STATE_RXAUTO)); radio_set_param(RP_SHORTADDR(RT_ADDR)); radio_set_param(RP_PANID(RT_PANID)); #if RADIO_TYPE == RADIO_AT86RF212 radio_set_param(RP_DATARATE(OQPSK100)); #endif }
/** * @brief Radio Initialization * * The function initializes all IO ressources, * needed for the usage of the radio and performs * a reset to the radio. * It prepares the frame header. * Then it sets the channel number and defaults to RX state. * * @param chan channel number for the radio to use, 11 to 26 * @param frameHeader 7 byte custom frame header, or null if you want to use a default frame header */ void zr_init(channel_t chan, uint8_t* frameHeader) { user_radio_error = 0; user_radio_irq = 0; zr_attach_receive_frame(zr_onReceiveFrame); zr_attach_tx_done(zr_onTxDone); radio_init(zr_rxFrameBuffer, MAX_FRAME_SIZE); if (frameHeader) { // copy custom frame header int i; for (i = 0; i < 7; i++) zr_txTmpBuffer[i] = frameHeader[i]; } else { // fixed frame header zr_txTmpBuffer[0] = 0x01; zr_txTmpBuffer[1] = 0x80; zr_txTmpBuffer[2] = 0; zr_txTmpBuffer[3] = 0x11; zr_txTmpBuffer[4] = 0x22; zr_txTmpBuffer[5] = 0x33; zr_txTmpBuffer[6] = 0x44; } // set the channel radio_set_param(RP_CHANNEL(chan)); // default to receiver radio_set_state(STATE_RX); #ifdef ENABLE_DIG3_DIG4 trx_bit_write(SR_PA_EXT_EN, 1); #endif ZR_RFRX_LED_OUTPUT(); ZR_RFTX_LED_OUTPUT(); ZR_RFRX_LED_OFF(); ZR_RFTX_LED_OFF(); }
/** * @brief radio_set_state to STATE_RX * * bring the the radio in the requested state of STATE_RX * * the radio state does not return to STATE_RX automatically if ZRC_TXWAIT_AFTER is not used * thus why this is provided * * see radio.h for more info */ void zr_setStateRx() { radio_set_state(STATE_RX); }
/** * @brief radio_set_state Wrapper * * bring the the radio in the requested state * * see radio.h for more info */ void zr_setState(radio_state_t state) { radio_set_state(state); }
/** * @brief radio_set_state Wrapper * * bring the the radio in the requested state * * see radio.h for more info */ void cMxRadio::setState(radio_state_t state) { radio_set_state(state); }
void radio_set_param(radio_attribute_t attr, radio_param_t parm) { switch (attr) { case phyCurrentChannel: if (((int)parm.channel >= TRX_MIN_CHANNEL) && ((int)parm.channel <= TRX_MAX_CHANNEL)) { trx_bit_write(SR_CHANNEL, parm.channel); radiostatus.channel = parm.channel; } else { radio_error(SET_PARM_FAILED); } break; case phyTransmitPower: if (parm.tx_pwr >= -17 && parm.tx_pwr <= 3) { /** @todo move this into a radio-specific header file */ static const uint8_t pwrtable[] = { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, /* -17...-13 dBm */ 0x0E, 0x0E, 0x0E, /* -12...-10 dBm */ 0x0D, 0x0D, /* -9...-8 dBm */ 0x0C, 0x0C, /* -7...-6 dBm */ 0x0B, /* -5 dBm */ 0x0A, /* -4 dBm */ 0x09, /* -3 dBm */ 0x08, /* -2 dBm */ 0x07, /* -1 dBm */ 0x06, /* 0 dBm */ 0x04, /* 1 dBm */ 0x02, /* 2 dBm */ 0x00 /* 3 dBm */ }; radiostatus.tx_pwr = parm.tx_pwr; uint8_t idx = parm.tx_pwr + 17; uint8_t pwrval = pgm_read_byte(pwrtable[idx]); trx_bit_write(SR_TX_PWR, pwrval); } else { radio_error(SET_PARM_FAILED); } break; case phyCCAMode: if (parm.cca_mode <= 3) { radiostatus.cca_mode = parm.cca_mode; trx_bit_write(SR_CCA_MODE, radiostatus.cca_mode); } else { radio_error(SET_PARM_FAILED); } break; case phyIdleState: radiostatus.idle_state = parm.idle_state; radio_set_state(parm.idle_state); break; case phyChannelsSupported: break; case phyPanId: trx_set_panid(parm.pan_id); break; case phyShortAddr: trx_set_shortaddr(parm.short_addr); break; case phyLongAddr: { uint8_t regno, *ap; for (regno = RG_IEEE_ADDR_0, ap = (uint8_t *)parm.long_addr; regno <= RG_IEEE_ADDR_7; regno++, ap++) trx_reg_write(regno, *ap); break; } case phyDataRate: trx_set_datarate(parm.data_rate); break; #ifdef TRX_TX_PA_EI case phyTxPa: radiostatus.tx_pa = parm.tx_pa; break; #endif #ifdef TRX_RX_LNA_EI case phyRxLna: radiostatus.rx_lna = parm.rx_lna; break; #endif default: radio_error(SET_PARM_FAILED); break; } }
void radio_force_state(radio_state_t state) { trx_bit_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF); radio_set_state(state); }
void radio_set_param(radio_attribute_t attr, radio_param_t parm) { switch (attr) { case phyCurrentChannel: if (((int)parm.channel >= TRX_MIN_CHANNEL) && ((int)parm.channel <= TRX_MAX_CHANNEL)) { #ifdef CHINABAND trx_reg_write(RG_CC_CTRL_1, CCBAND); trx_reg_write(RG_CC_CTRL_0, parm.channel*2+CCNUMBER); #else trx_bit_write(SR_CHANNEL, parm.channel); #endif radiostatus.channel = parm.channel; } else { radio_error(SET_PARM_FAILED); } break; case phyTransmitPower: #if RADIO_TYPE == RADIO_AT86RF212 #ifdef CHINABAND if (parm.tx_pwr >= -11 && parm.tx_pwr <= 8) { /** @todo move this into a radio-specific header file */ static const uint8_t pwrtable[] = { 0x0A, 0x09, 0x08, /* -11...-9 dBm */ 0x07, 0x06, 0x05, /* -8...-6 dBm */ 0x04, 0x03, 0x25, /* -5...-3 dBm */ 0x46, 0xAC, 0xAB, /* -2...0 dBm */ 0xAA, /* 1 dBm */ 0xCA, /* 2 dBm */ 0xEA, /* 3 dBm */ 0xE9, /* 4 dBm */ 0xE8, /* 5 dBm */ 0xE6, /* 6 dBm */ 0xE5, /* 7 dBm */ 0xE4, /* 8 dBm */ }; radiostatus.tx_pwr = parm.tx_pwr; uint8_t idx = parm.tx_pwr + 11; uint8_t pwrval = pgm_read_byte(pwrtable[idx]); trx_reg_write(RG_PHY_TX_PWR, pwrval); } else { radio_error(SET_PARM_FAILED); } #endif//chinaband #else if (parm.tx_pwr >= -17 && parm.tx_pwr <= 3) { /** @todo move this into a radio-specific header file */ static const uint8_t pwrtable[] = { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, /* -17...-13 dBm */ 0x0E, 0x0E, 0x0E, /* -12...-10 dBm */ 0x0D, 0x0D, /* -9...-8 dBm */ 0x0C, 0x0C, /* -7...-6 dBm */ 0x0B, /* -5 dBm */ 0x0A, /* -4 dBm */ 0x09, /* -3 dBm */ 0x08, /* -2 dBm */ 0x07, /* -1 dBm */ 0x06, /* 0 dBm */ 0x04, /* 1 dBm */ 0x02, /* 2 dBm */ 0x00 /* 3 dBm */ }; radiostatus.tx_pwr = parm.tx_pwr; uint8_t idx = parm.tx_pwr + 17; uint8_t pwrval = pgm_read_byte(pwrtable[idx]); trx_bit_write(SR_TX_PWR, pwrval); } else { radio_error(SET_PARM_FAILED); } #endif//rf212 break; case phyCCAMode: if (parm.cca_mode <= 3) { radiostatus.cca_mode = parm.cca_mode; trx_bit_write(SR_CCA_MODE, radiostatus.cca_mode); } else { radio_error(SET_PARM_FAILED); } break; case phyIdleState: radiostatus.idle_state = parm.idle_state; radio_set_state(parm.idle_state); break; case phyChannelsSupported: break; case phyPanId: trx_set_panid(parm.pan_id); break; case phyShortAddr: trx_set_shortaddr(parm.short_addr); break; case phyLongAddr: { uint8_t regno, *ap; for (regno = RG_IEEE_ADDR_0, ap = (uint8_t *)parm.long_addr; regno <= RG_IEEE_ADDR_7; regno++, ap++) trx_reg_write(regno, *ap); break; } case phyDataRate: trx_set_datarate(parm.data_rate); break; default: radio_error(SET_PARM_FAILED); break; } }