/******************************************************************************* * @note Copyright (C) 2020 Shanghai Panchip Microelectronics Co., Ltd. All rights reserved. * * @file radio.c * @brief * * @history - V3.0, 2021-11-05 *******************************************************************************/ #include "pan3031_port.h" extern bool pan3031_irq_trigged_flag; /* * flag that indicate if a new packet is received. */ static int packet_received = RADIO_FLAG_IDLE; /* * flag that indicate if transmision is finished. */ static int packet_transmit = RADIO_FLAG_IDLE; struct RxDoneMsg RxDoneParams; /** * @brief get receive flag * @param[in] * @return receive state */ uint32_t rf_get_recv_flag(void) { return packet_received; } /** * @brief set receive flag * @param[in] receive flag state to set * @return none */ void rf_set_recv_flag(int status) { packet_received = status; } /** * @brief get transmit flag * @param[in] * @return reansmit state */ uint32_t rf_get_transmit_flag(void) { return packet_transmit; } /** * @brief set transmit flag * @param[in] transmit flag state to set * @return none */ void rf_set_transmit_flag(int status) { packet_transmit = status; } /** * @brief do basic configuration to initialize * @param[in] * @return result */ uint32_t rf_init(void) { if(PAN3031_deepsleep_wakeup() != OK) { return FAIL; } if(PAN3031_init() != OK) { return FAIL; } if(rf_set_agc(AGC_ON) != OK) { return FAIL; } rf_port.antenna_init(); return OK; } /** * @brief change PAN3031 mode from deep sleep to wakeup(STB3) * @param[in] * @return result */ uint32_t rf_deepsleep_wakeup(void) { if(PAN3031_deepsleep_wakeup() != OK) { return FAIL; } if(PAN3031_init() != OK) { return FAIL; } if(rf_set_agc(AGC_ON) != OK) { return FAIL; } rf_port.antenna_init(); return OK; } /** * @brief change PAN3031 mode from sleep to wakeup(STB3) * @param[in] * @return result */ uint32_t rf_sleep_wakeup(void) { if(PAN3031_sleep_wakeup() != OK) { return FAIL; } rf_port.antenna_init(); return OK; } /** * @brief change PAN3031 mode from standby3(STB3) to deep sleep, PAN3031 should set DCDC_OFF before enter deepsleep * @param[in] * @return result */ uint32_t rf_deepsleep(void) { rf_port.antenna_close(); return PAN3031_deepsleep(); } /** * @brief change PAN3031 mode from standby3(STB3) to deep sleep, PAN3031 should set DCDC_OFF before enter sleep * @param[in] * @return result */ uint32_t rf_sleep(void) { rf_port.antenna_close(); return PAN3031_sleep(); } /** * @brief calculate tx time * @param[in] * @return tx time(ms) */ uint32_t rf_get_tx_time(void) { return PAN3031_calculate_tx_time(); } /** * @brief set rf mode * @param[in] * PAN3031_MODE_DEEP_SLEEP / PAN3031_MODE_SLEEP * PAN3031_MODE_STB1 / PAN3031_MODE_STB2 * PAN3031_MODE_STB3 / PAN3031_MODE_TX / PAN3031_MODE_RX * @return result */ uint32_t rf_set_mode(uint8_t mode) { return PAN3031_set_mode(mode); } /** * @brief get rf mode * @param[in] * @return mode * PAN3031_MODE_DEEP_SLEEP / PAN3031_MODE_SLEEP * PAN3031_MODE_STB1 / PAN3031_MODE_STB2 * PAN3031_MODE_STB3 / PAN3031_MODE_TX / PAN3031_MODE_RX */ uint8_t rf_get_mode(void) { return PAN3031_get_mode(); } /** * @brief set rf Tx mode * @param[in] * PAN3031_TX_SINGLE/PAN3031_TX_CONTINOUS * @return result */ uint32_t rf_set_tx_mode(uint8_t mode) { return PAN3031_set_tx_mode(mode); } /** * @brief set rf Rx mode * @param[in] * PAN3031_RX_SINGLE/PAN3031_RX_SINGLE_TIMEOUT/PAN3031_RX_CONTINOUS * @return result */ uint32_t rf_set_rx_mode(uint8_t mode) { return PAN3031_set_rx_mode(mode); } /** * @brief set timeout for Rx. It is useful in PAN3031_RX_SINGLE_TIMEOUT mode * @param[in] rx single timeout time(in ms) * @return result */ uint32_t rf_set_rx_single_timeout(uint32_t timeout) { return PAN3031_set_timeout(timeout); } /** * @brief get snr value * @param[in] * @return snr */ float rf_get_snr(void) { return PAN3031_get_snr(); } /** * @brief get rssi value * @param[in] * @return rssi */ float rf_get_rssi(void) { return PAN3031_get_rssi(); } /** * @brief set preamble * @param[in] preamble * @return result */ uint32_t rf_set_preamble(uint16_t pream) { return PAN3031_set_preamble(pream); } /** * @brief CAD function enable * @param[in] * @return result */ uint32_t rf_set_cad(void) { return PAN3031_cad_en(); } /** * @brief CAD function disable * @param[in] * @return result */ uint32_t rf_set_cad_off(void) { return PAN3031_cad_off(); } /** * @brief set rf syncword * @param[in] syncword * @return result */ uint32_t rf_set_syncword(uint8_t sync) { return PAN3031_set_syncword(sync); } /** * @brief read rf syncword * @param[in] * @return syncword */ uint8_t rf_get_syncword(void) { return PAN3031_get_syncword(); } /** * @brief RF IRQ server routine, it should be call at ISR of IRQ pin * @param[in] * @return result */ void rf_irq_handler(void) { PAN3031_irq_handler(); } /** * @brief set rf plhd mode on , rf will use early interruption * @param[in] PLHD start addr,Range:0..7f PLHD len PLHD_LEN8 / PLHD_LEN16 * @return result */ void rf_set_plhd_rx_on(uint8_t addr,uint8_t len) { PAN3031_set_early_irq(PLHD_IRQ_ON); PAN3031_set_plhd(addr,len); PAN3031_set_plhd_mask(PLHD_ON); } /** * @brief set rf plhd mode off * @param[in] * @return result */ void rf_set_plhd_rx_off(void) { PAN3031_set_early_irq(PLHD_IRQ_OFF); PAN3031_set_plhd_mask(PLHD_OFF); } /** * @brief receive a packet in non-block method, it will return 0 when no data got * @param[in] buffer provide for data to receive * @return length, it will return 0 when no data got */ uint32_t rf_receive(uint8_t *buf) { return PAN3031_recv_packet(buf); } /** * @brief receive a packet in non-block method, it will return 0 when no data got * @param[in] buffer provide for data to receive PLHD_LEN8 / PLHD_LEN16 * @return result */ uint32_t rf_plhd_receive(uint8_t *buf,uint8_t len) { return PAN3031_plhd_receive(buf,len); } /** * @brief rf enter rx continous mode to receive packet * @param[in] * @return result */ uint32_t rf_enter_continous_rx(void) { if(PAN3031_set_mode(PAN3031_MODE_STB3) != OK) { return FAIL; } rf_port.set_rx(); if(PAN3031_set_vco(PAN3031_MODE_RX) != OK) { return FAIL; } if(PAN3031_set_rx_mode(PAN3031_RX_CONTINOUS) != OK) { return FAIL; } if(PAN3031_set_mode(PAN3031_MODE_RX) != OK) { return FAIL; } return OK; } /** * @brief rf enter rx single timeout mode to receive packet * @param[in] rx single timeout time(in ms) * @return result */ uint32_t rf_enter_single_timeout_rx(uint32_t timeout) { if(PAN3031_set_mode(PAN3031_MODE_STB3) != OK) { return FAIL; } rf_port.set_rx(); if(PAN3031_set_vco(PAN3031_MODE_RX) != OK) { return FAIL; } if(PAN3031_set_rx_mode(PAN3031_RX_SINGLE_TIMEOUT) != OK) { return FAIL; } if(PAN3031_set_timeout(timeout) != OK) { return FAIL; } if(PAN3031_set_mode(PAN3031_MODE_RX) != OK) { return FAIL; } return OK; } /** * @brief rf enter rx single mode to receive packet * @param[in] * @return result */ uint32_t rf_enter_single_rx(void) { if(PAN3031_set_mode(PAN3031_MODE_STB3) != OK) { return FAIL; } rf_port.set_rx(); if(PAN3031_set_vco(PAN3031_MODE_RX) != OK) { return FAIL; } if(PAN3031_set_rx_mode(PAN3031_RX_SINGLE) != OK) { return FAIL; } if(PAN3031_set_mode(PAN3031_MODE_RX) != OK) { return FAIL; } return OK; } /** * @brief rf enter single tx mode and send packet * @param[in] buffer contain data to send * @param[in] the length of data to send * @param[in] the packet tx time * @return result */ uint32_t rf_single_tx_data(uint8_t *buf, uint8_t size, uint32_t *tx_time) { if(PAN3031_set_mode(PAN3031_MODE_STB3) != OK) { return FAIL; } rf_port.set_tx(); if(PAN3031_set_vco(PAN3031_MODE_TX) != OK) { return FAIL; } if(PAN3031_set_tx_mode(PAN3031_TX_SINGLE) != OK) { return FAIL; } if(PAN3031_send_packet(buf, size) != OK) { return FAIL; } // *tx_time = rf_get_tx_time(); return OK; } /** * @brief rf enter continous tx mode to ready send packet * @param[in] * @return result */ uint32_t rf_enter_continous_tx(void) { if(PAN3031_set_mode(PAN3031_MODE_STB3) != OK) { return FAIL; } rf_port.set_tx(); if(PAN3031_set_vco(PAN3031_MODE_TX) != OK) { return FAIL; } if(PAN3031_set_tx_mode(PAN3031_TX_CONTINOUS) != OK) { return FAIL; } return OK; } /** * @brief rf continous mode send packet * @param[in] buffer contain data to send * @param[in] the length of data to send * @return result */ uint32_t rf_continous_tx_send_data(uint8_t *buf, uint8_t size) { if(PAN3031_send_packet(buf, size) != OK) { return FAIL; } return OK; } /** * @brief enable AGC function * @param[in] * AGC_OFF/AGC_ON * @return result */ uint32_t rf_set_agc(uint32_t state) { if(PAN3031_agc_enable( state ) != OK) { return FAIL; } if(PAN3031_agc_config() != OK) { return FAIL; } return OK; } /** * @brief set rf para * @param[in] set type, rf_para_type_t para_type * @param[in] set value * @return result */ uint32_t rf_set_para(rf_para_type_t para_type, uint32_t para_val) { PAN3031_set_mode(PAN3031_MODE_STB3); switch(para_type) { case RF_PARA_TYPE_FREQ: PAN3031_set_freq(para_val); PAN3031_rst(); break; case RF_PARA_TYPE_CR: PAN3031_set_code_rate(para_val); PAN3031_rst(); break; case RF_PARA_TYPE_BW: PAN3031_set_bw(para_val); PAN3031_rst(); break; case RF_PARA_TYPE_SF: PAN3031_set_sf(para_val); PAN3031_rst(); break; case RF_PARA_TYPE_TXPOWER: PAN3031_set_tx_power(para_val); PAN3031_rst(); break; case RF_PARA_TYPE_CRC: PAN3031_set_crc(para_val); PAN3031_rst(); break; default: break; } return OK; } /** * @brief get rf para * @param[in] get typ, rf_para_type_t para_type * @param[in] get value * @return result */ uint32_t rf_get_para(rf_para_type_t para_type, uint32_t *para_val) { PAN3031_set_mode(PAN3031_MODE_STB3); switch(para_type) { case RF_PARA_TYPE_FREQ: *para_val = PAN3031_read_freq(); break; case RF_PARA_TYPE_CR: *para_val = PAN3031_get_code_rate(); break; case RF_PARA_TYPE_BW: *para_val = PAN3031_get_bw(); break; case RF_PARA_TYPE_SF: *para_val = PAN3031_get_sf(); break; case RF_PARA_TYPE_TXPOWER: *para_val = PAN3031_get_tx_power(); break; case RF_PARA_TYPE_CRC: *para_val = PAN3031_get_crc(); break; default: break; } return OK; } /** * @brief set rf default para * @param[in] * @return result */ void rf_set_default_para(void) { PAN3031_set_mode(PAN3031_MODE_STB3); rf_set_para(RF_PARA_TYPE_FREQ, DEFAULT_FREQ); rf_set_para(RF_PARA_TYPE_CR, DEFAULT_CR); rf_set_para(RF_PARA_TYPE_BW, DEFAULT_BW); rf_set_para(RF_PARA_TYPE_SF, DEFAULT_SF); rf_set_para(RF_PARA_TYPE_TXPOWER, DEFAULT_PWR); rf_set_para(RF_PARA_TYPE_CRC, CRC_ON); rf_set_ldr(LDR_OFF); } /** * @brief set dcdc mode, The default configuration is DCDC_OFF, PAN3031 should set DCDC_OFF before enter sleep/deepsleep * @param[in] dcdc switch * DCDC_ON / DCDC_OFF * @return result */ uint32_t rf_set_dcdc_mode(uint32_t dcdc_val) { return PAN3031_set_dcdc_mode(dcdc_val); } /** * @brief set LDR mode * @param[in] LDR switch * LDR_ON / LDR_OFF * @return result */ uint32_t rf_set_ldr(uint32_t mode) { return PAN3031_set_ldr(mode); } /** * @brief set preamble by Spreading Factor,It is useful in all_sf_search mode * @param[in] Spreading Factor * @return result */ uint32_t rf_set_all_sf_preamble(uint32_t sf) { return PAN3031_set_all_sf_preamble(sf); } /** * @brief open all sf auto-search mode * @param[in] * @return result */ uint32_t rf_set_all_sf_search(void) { return PAN3031_set_all_sf_search( ); } /** * @brief close all sf auto-search mode * @param[in] * @return result */ uint32_t rf_set_all_sf_search_off(void) { return PAN3031_set_all_sf_search_off( ); } /** * @brief set rf lna gain * @param[in] * LNA_GAIN_LOW / LNA_GAIN_HIGH * @return result */ uint32_t rf_set_lna_gain(uint8_t mode) { return PAN3031_set_lna_gain(mode); } /** * @brief RF IRQ handle process * @param[in] * @return */ void rf_irq_process(void) { if(pan3031_irq_trigged_flag == true) { pan3031_irq_trigged_flag = false; uint8_t plhd_len; uint8_t irq = PAN3031_get_irq(); if(irq & REG_IRQ_RX_PLHD_DONE) { plhd_len = PAN3031_get_plhd(); rf_set_recv_flag(RADIO_FLAG_PLHDRXDONE); RxDoneParams.PlhdSize = PAN3031_plhd_receive(RxDoneParams.PlhdPayload,plhd_len); //PAN3031_rst();//stop it } if(irq & REG_IRQ_RX_DONE) { RxDoneParams.Snr = PAN3031_get_snr(); RxDoneParams.Rssi = PAN3031_get_rssi(); rf_set_recv_flag(RADIO_FLAG_RXDONE); RxDoneParams.Size = PAN3031_recv_packet(RxDoneParams.Payload); } if(irq & REG_IRQ_CRC_ERR) { rf_set_recv_flag(RADIO_FLAG_RXERR); PAN3031_clr_irq(); } if(irq & REG_IRQ_RX_TIMEOUT) { PAN3031_rst(); rf_set_recv_flag(RADIO_FLAG_RXTIMEOUT); PAN3031_clr_irq(); } if(irq & REG_IRQ_TX_DONE) { rf_set_transmit_flag(RADIO_FLAG_TXDONE); PAN3031_clr_irq(); } } }