/******************************************************************************* * @note Copyright (C) 2020 Shanghai Panchip Microelectronics Co., Ltd. All rights reserved. * * @file pan3031.c * @brief * * @history - V3.0, 2021-11-05 *******************************************************************************/ #include "pan3031_port.h" bool pan3031_irq_trigged_flag = false; uint8_t reg_agc_value[98] = {0x90,0xff,0x64,0x24,0x00,0x03,0x24,0x24,0x00,0x03,0x24,0x24,0x00,0x03,0x24,0x24,\ 0x00,0x03,0x24,0x24,0x00,0x03,0x24,0x24,0x00,0x03,0x24,0x24,0x00,0x03,0x24,0x24,\ 0x00,0x03,0x24,0x24,0x00,0x03,0x24,0x24,0x00,0x03,0x24,0x24,0x00,0x03,0x24,0x2A,\ 0x20,0x03,0x2A,0x30,0x40,0x03,0x30,0x36,0x60,0x03,0x36,0x3B,0x80,0x03,0x3B,0x41,\ 0x84,0x03,0x41,0x46,0x88,0x03,0x46,0x4B,0x8C,0x03,0x4B,0x50,0x90,0x03,0x50,0x56,\ 0x91,0x03,0x56,0x06,0xFF,0x40,0x42,0x0F,0x00,0x00,0x01,0xF4,0x2F,0xF3,0x0F,0x00,0x00,0x00}; /** * @brief read one byte from register in current page * @param[in] register address to write * @return value read from register */ static uint8_t PAN3031_read_reg(uint8_t addr) { uint8_t temreg = 0x00; rf_port.spi_cs_low(); rf_port.spi_readwrite(0x00 | (addr<<1)); temreg=rf_port.spi_readwrite(0x00); rf_port.spi_cs_high(); return temreg; } /** * @brief write global register in current page and chick * @param[in] register address to write * @param[in] address value to write to rgister * @return result */ static uint32_t PAN3031_write_reg(uint8_t addr,uint8_t value) { uint16_t tmpreg = 0; uint16_t addr_w = (0x01 | (addr << 1)); rf_port.spi_cs_low(); rf_port.spi_readwrite(addr_w); rf_port.spi_readwrite(value); rf_port.spi_cs_high(); tmpreg = PAN3031_read_reg(addr); if(tmpreg == value) { return OK; } else { return FAIL; } } /** * @brief rf send data fifo,send bytes register * @param[in] register address to write * @param[in] send data buffer * @param[in] send data size * @return none */ static void PAN3031_write_fifo(uint8_t addr,uint8_t *buffer,int size) { int i; uint8_t addr_w = (0x01 | (addr << 1)); rf_port.spi_cs_low(); rf_port.spi_readwrite(addr_w); for(i =0;i register address to write * @param[in] receive data buffer * @param[in] receive data size * @return none */ static void PAN3031_read_fifo(uint8_t addr,uint8_t *buffer,int size) { int i; uint8_t addr_w = (0x00 | (addr<<1)); rf_port.spi_cs_low(); rf_port.spi_readwrite(addr_w); for(i =0;i page to switch * @return result */ static uint32_t PAN3031_switch_page(enum PAGE_SEL page) { uint8_t page_sel = 0x00; uint8_t tmpreg = 0x00; tmpreg = PAN3031_read_reg(REG_SYS_CTL); page_sel = (tmpreg & 0xfc )| page; PAN3031_write_reg(REG_SYS_CTL, page_sel); if((PAN3031_read_reg(REG_SYS_CTL) &0x03) == page) { return OK; }else { return FAIL; } } /** * @brief This function write a value to register in specific page * @param[in] the page of register * @param[in] register address * @param[in] value to write * @return result */ uint32_t PAN3031_write_spec_page_reg(enum PAGE_SEL page,uint8_t addr,uint8_t value) { if(PAN3031_switch_page(page) != OK) { return FAIL; } if(PAN3031_write_reg(addr, value) != OK) { return FAIL; } else { return OK; } } /** * @brief read a value to register in specific page * @param[in] the page of register * @param[in] register address * @return success(register value) or failure */ uint8_t PAN3031_read_spec_page_reg(enum PAGE_SEL page,uint8_t addr) { if(PAN3031_switch_page(page) != OK) { return FAIL; } return PAN3031_read_reg(addr); } /** * @brief write continue register valuies(buffer) in specific addr page * @param[in] the page of register * @param[in] register start address * @param[in] values to write * @param[in] buffer len * @return result */ uint32_t PAN3031_write_read_continue_regs(enum PAGE_SEL page,uint8_t addr,uint8_t *buffer,uint8_t len) { uint8_t i,temreg[256]; uint16_t addr_w; if(PAN3031_switch_page(page) != OK) { return FAIL; } addr_w = (0x01 | (addr << 1)); rf_port.spi_cs_low(); rf_port.spi_readwrite(addr_w); for(i=0;i * @return result */ uint8_t PAN3031_clr_irq(void) { uint8_t clr_cnt = 0; uint16_t a = 0, b = 0; while(clr_cnt < 3) { PAN3031_write_spec_page_reg(PAGE0_SEL, 0x6C, 0x1f);//clr irq if(PAN3031_read_spec_page_reg(PAGE0_SEL, 0x6C)==0) { return OK; }else{ clr_cnt++; for(a=0;a<1200;a++) //10ms for(b=0;b<100;b++); continue; } } return FAIL; } /** * @brief get irq status * @param[in] * @return ira status */ uint8_t PAN3031_get_irq(void) { uint8_t tmpreg; tmpreg = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x6C); return tmpreg; } /** * @brief software reset * @param[in] * @return result */ uint32_t PAN3031_rst(void) { uint8_t tmpreg = 0; tmpreg = PAN3031_read_reg(REG_SYS_CTL); tmpreg |= 0x80; PAN3031_write_reg(REG_SYS_CTL, tmpreg); tmpreg = PAN3031_read_reg(REG_SYS_CTL); tmpreg &= 0x7F; PAN3031_write_reg(REG_SYS_CTL, tmpreg); return OK; } /** * @brief clear packet count register * @param[in] * @return none */ void PAN3031_clr_pkt_cnt(void) { uint8_t tmpreg; tmpreg = PAN3031_read_reg(REG_SYS_CTL); tmpreg = (tmpreg & 0xbf) | 0x40 ; PAN3031_write_reg(REG_SYS_CTL,tmpreg); tmpreg = PAN3031_read_reg(REG_SYS_CTL); tmpreg = (tmpreg & 0xbf); PAN3031_write_reg(REG_SYS_CTL, tmpreg); } /** * @brief enable AGC function * @param[in] * AGC_OFF/AGC_ON * @return result */ uint32_t PAN3031_agc_enable(uint32_t state) { uint8_t reg_val = 0x02; if(state == AGC_OFF) { reg_val = 0x03; } else { reg_val = 0x02; } if(PAN3031_write_spec_page_reg(PAGE2_SEL, 0x06, reg_val) != OK) { return FAIL; } return OK; } /** * @brief configure AGC function * @param[in] * @return result */ uint32_t PAN3031_agc_config(void) { return PAN3031_write_read_continue_regs(PAGE2_SEL, 0x07, reg_agc_value,98); } /** * @brief do basic configuration to initialize * @param[in] * @return result */ uint32_t PAN3031_init(void) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x06, 0x01) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x1f, 0x18) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x20, 0x15) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x23, 0x08) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x25, 0x08) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x27, 0x04) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x28, 0x14) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x2d, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x2e, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x2f, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x30, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x31, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x32, 0x60) != OK)//HIGH { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x33, 0x07) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x3e, 0x2c) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x3c, 0xff) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x40, 0x50) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4c, 0xbf) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4d, 0x0e) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x55, 0x02) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x0e, 0x44) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x0f, 0x0a) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x1e, 0x00) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x11, 0xA1) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x15, 0x38) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x2f, 0x0c) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x38, 0x02) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x57, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x58, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x59, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x5a, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x5b, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x5c, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x5d, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x5e, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x5f, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x60, 0x33) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x61, 0x11) != OK) { return FAIL; } // if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x67, 0xc0) != OK)/*add PA*/ // { // return FAIL; // } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x06, 0x26) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x10, 0x80) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x11, 0x0d) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x12, 0x16) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x18, 0xff) != OK) { return FAIL; } return OK; } /** * @brief change PAN3031 mode from deep sleep to standby3(STB3) * @param[in] * @return result */ uint32_t PAN3031_deepsleep_wakeup(void) { uint8_t rstreg = 0,porreg = 0; porreg = PAN3031_read_reg(0x04); porreg |= 0x10; PAN3031_write_reg(0x04, porreg); rf_port.delayus(10); porreg &= 0xEF; PAN3031_write_reg(0x04, porreg); rstreg = PAN3031_read_reg(REG_SYS_CTL); rstreg &= 0x7F; PAN3031_write_reg(REG_SYS_CTL, rstreg); rf_port.delayus(10); rstreg |= 0x80; PAN3031_write_reg(REG_SYS_CTL, rstreg); rf_port.delayus(10); rstreg &= 0x7F; PAN3031_write_reg(REG_SYS_CTL, rstreg); rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_DEEP_SLEEP) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_SLEEP) != OK) { return FAIL; } rf_port.delayms(1); if(PAN3031_write_reg(0x03, 0x1b) != OK) { return FAIL; } if(PAN3031_write_reg(0x04, 0x76) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x26, 0x40) != OK) { return FAIL; } rf_port.tcxo_init(); rf_port.delayms(1); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB1) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB2) != OK) { return FAIL; } rf_port.delayms(1); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB3) != OK) { return FAIL; } else { rf_port.delayus(10); return OK; } } /** * @brief change PAN3031 mode from sleep to standby3(STB3) * @param[in] * @return result */ uint32_t PAN3031_sleep_wakeup(void) { rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_SLEEP) != OK) { return FAIL; } rf_port.delayms(1); if(PAN3031_write_reg(0x03, 0x1b) != OK) { return FAIL; } if(PAN3031_write_reg(0x04, 0x76) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x26, 0x40) != OK) { return FAIL; } rf_port.tcxo_init(); rf_port.delayms(1); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB1) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB2) != OK) { return FAIL; } rf_port.delayms(1); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB3) != OK) { return FAIL; } else { rf_port.delayus(10); 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 PAN3031_deepsleep(void) { rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB3) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB2) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB1) != OK) { return FAIL; } rf_port.delayus(10); rf_port.tcxo_close(); if(PAN3031_write_reg(0x04, 0x06) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_SLEEP) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_DEEP_SLEEP) != OK) { return FAIL; } else { return OK; } } /** * @brief change PAN3031 mode from standby3(STB3) to sleep, PAN3031 should set DCDC_OFF before enter sleep * @param[in] * @return result */ uint32_t PAN3031_sleep(void) { rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB3) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB2) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_STB1) != OK) { return FAIL; } rf_port.delayus(10); rf_port.tcxo_close(); if(PAN3031_write_reg(0x04, 0x16) != OK) { return FAIL; } rf_port.delayus(10); if(PAN3031_write_reg(REG_OP_MODE, PAN3031_MODE_SLEEP) != OK) { return FAIL; } else { rf_port.delayus(10); return OK; } } /** * @brief set LO frequency * @param[in] LO frequency * LO_400M / LO_800M * @return result */ uint32_t PAN3031_set_lo_freq(uint32_t lo) { uint32_t reg_val = 0; reg_val = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x45); reg_val &= ~(0x03); if(lo == LO_400M) { reg_val |= 0x02; } else { reg_val |= 0x01; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x45, reg_val) != OK) { return FAIL; } return OK; } /** * @brief set frequence * @param[in] RF frequency(in Hz) to set * @return result */ uint32_t PAN3031_set_freq(uint32_t freq) { uint8_t reg_read; uint8_t reg_freq; uint32_t tmp_var = 0; uint32_t integer_part = 0; uint32_t fractional_part = 0; uint8_t lowband_sel = 0; int fb,fc; if ( (freq >= freq_360000000) && (freq <= freq_370000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x0f) != OK) { return FAIL; } lowband_sel = 1; tmp_var = freq / 1000 * 25; integer_part = tmp_var / 100000; fb = integer_part - 20; fractional_part = tmp_var % 100000; fc = (fractional_part * 4)/1000; PAN3031_set_lo_freq(LO_400M); } else if ( (freq >= freq_370000000) && (freq <= freq_385000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x2f) != OK) { return FAIL; } lowband_sel = 1; tmp_var = freq / 1000 * 25; integer_part = tmp_var / 100000; fb = integer_part - 20; fractional_part = tmp_var % 100000; fc = (fractional_part * 4)/1000; PAN3031_set_lo_freq(LO_400M); } else if ( (freq >= freq_385000000) && (freq <= freq_405000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x4f) != OK) { return FAIL; } lowband_sel = 1; tmp_var = freq / 1000 * 25; integer_part = tmp_var / 100000; fb = integer_part - 20; fractional_part = tmp_var % 100000; fc = (fractional_part * 4)/1000; PAN3031_set_lo_freq(LO_400M); } else if ( (freq > freq_405000000) && (freq <= freq_430000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x6f) != OK) { return FAIL; } lowband_sel = 1; tmp_var = freq / 1000 * 25; integer_part = tmp_var / 100000; fb = integer_part - 20; fractional_part = tmp_var % 100000; fc = (fractional_part * 4)/1000; PAN3031_set_lo_freq(LO_400M); } else if ( (freq > freq_430000000) && (freq <= freq_460000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x8f) != OK) { return FAIL; } lowband_sel = 1; tmp_var = freq / 1000 * 25; integer_part = tmp_var / 100000; fb = integer_part - 20; fractional_part = tmp_var % 100000; fc = (fractional_part * 4)/1000; PAN3031_set_lo_freq(LO_400M); } else if ( (freq > freq_460000000) && (freq <= freq_495000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0xaf) != OK) { return FAIL; } lowband_sel = 1; tmp_var = freq / 1000 * 25; integer_part = tmp_var / 100000; fb = integer_part - 20; fractional_part = tmp_var % 100000; fc = (fractional_part * 4)/1000; PAN3031_set_lo_freq(LO_400M); } else if ( (freq > freq_495000000) && (freq <= freq_535000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0xcf) != OK) { return FAIL; } lowband_sel = 1; tmp_var = freq / 1000 * 25; integer_part = tmp_var / 100000; fb = integer_part - 20; fractional_part = tmp_var % 100000; fc = (fractional_part * 4)/1000; PAN3031_set_lo_freq(LO_400M); } else if ( (freq > freq_535000000) && (freq <= freq_600000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0xef) != OK) { return FAIL; } lowband_sel = 1; tmp_var = freq / 1000 * 25; //freq * 4 * 1.0 / 16000000,-5 integer_part = tmp_var / 100000; fb = integer_part - 20; fractional_part = tmp_var % 100000; fc = (fractional_part * 4)/1000;//lowband_sel = 1,1600/4,-5+2 PAN3031_set_lo_freq(LO_400M); } else if ( (freq >= freq_720000000) && (freq <= freq_740000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x0f) != OK) { return FAIL; } lowband_sel = 0; tmp_var = freq / 1000 * 125; //freq * 2 * 1.0 / 16000000,-6 integer_part = tmp_var / 1000000; fb = integer_part - 20; fractional_part = tmp_var % 1000000; fc = (fractional_part * 8)/10000;//lowband_sel = 0,1600/4,-6+2 PAN3031_set_lo_freq(LO_800M); } else if ( (freq >= freq_740000000) && (freq <= freq_770000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x2f) != OK) { return FAIL; } lowband_sel = 0; tmp_var = freq / 1000 * 125; integer_part = tmp_var / 1000000; fb = integer_part - 20; fractional_part = tmp_var % 1000000; fc = (fractional_part * 8)/10000; PAN3031_set_lo_freq(LO_800M); } else if((freq > freq_770000000) && (freq <= freq_810000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x4f) != OK) { return FAIL; } lowband_sel = 0; tmp_var = freq / 1000 * 125; integer_part = tmp_var / 1000000; fb = integer_part - 20; fractional_part = tmp_var % 1000000; fc = (fractional_part * 8)/10000; PAN3031_set_lo_freq(LO_800M); } else if((freq > freq_810000000) && (freq <= freq_860000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x6f) != OK) { return FAIL; } lowband_sel = 0; tmp_var = freq / 1000 * 125; integer_part = tmp_var / 1000000; fb = integer_part - 20; fractional_part = tmp_var % 1000000; fc = (fractional_part * 8)/10000; PAN3031_set_lo_freq(LO_800M); } else if((freq > freq_860000000) && (freq <= freq_920000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x8f) != OK) { return FAIL; } lowband_sel = 0; tmp_var = freq / 1000 * 125; integer_part = tmp_var / 1000000; fb = integer_part - 20; fractional_part = tmp_var % 1000000; fc = (fractional_part * 8)/10000; PAN3031_set_lo_freq(LO_800M); } else if((freq > freq_920000000) && (freq <= freq_990000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0xaf) != OK) { return FAIL; } lowband_sel = 0; tmp_var = freq / 1000 * 125; integer_part = tmp_var / 1000000; fb = integer_part - 20; fractional_part = tmp_var % 1000000; fc = (fractional_part * 8)/10000; PAN3031_set_lo_freq(LO_800M); } else if((freq > freq_990000000) && (freq <= freq_1070000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0xcf) != OK) { return FAIL; } lowband_sel = 0; tmp_var = freq / 1000 * 125; integer_part = tmp_var / 1000000; fb = integer_part - 20; fractional_part = tmp_var % 1000000; fc = (fractional_part * 8)/10000; PAN3031_set_lo_freq(LO_800M); } else if((freq > freq_1070000000) && (freq <= freq_1200000000)) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0xef) != OK) { return FAIL; } lowband_sel = 0; tmp_var = freq / 1000 * 125; integer_part = tmp_var / 1000000; fb = integer_part - 20; fractional_part = tmp_var % 1000000; fc = (fractional_part * 8)/10000; PAN3031_set_lo_freq(LO_800M); } else { return FAIL; } if ( (freq >= freq_360000000) && (freq <= freq_600000000)) { if(fc < 0xff) { fb = fb - 1; fc = fc + 400; } } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x15, (fb & 0x7F)) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x16,(fc & 0xff)) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x17,((fc >> 8) & 0x0f)) != OK) { return FAIL; } reg_read = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x18); reg_read &= ~((1 << 2) | (1 << 1)); reg_read |= (1 << 3) | (lowband_sel << 2) | (lowband_sel << 1); if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x18, reg_read) != OK) { return FAIL; } reg_freq = freq & 0xff; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x09, reg_freq) != OK) { return FAIL; } reg_freq = (freq >> 8) & 0xff; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x0a, reg_freq) != OK) { return FAIL; } reg_freq = (freq >> 16) & 0xff; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x0b, reg_freq) != OK) { return FAIL; } reg_freq = (freq >> 24) & 0xff; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x0c, reg_freq) != OK) { return FAIL; } return OK; } /** * @brief read frequency(in Hz) * @param[in] * @return frequency(in Hz) */ uint32_t PAN3031_read_freq(void) { uint8_t reg1, reg2, reg3 , reg4; uint32_t freq = 0x00; reg1 = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x09); reg2 = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0a); reg3 = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0b); reg4 = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0c); freq = (reg4 << 24) | (reg3 << 16) | (reg2 << 8) | reg1; return freq; } /** * @brief calculate tx time * @param[in] * @return tx time(ms) */ uint32_t PAN3031_calculate_tx_time(void) { int bw_val; float tx_done_time; uint8_t pl = PAN3031_read_spec_page_reg(PAGE1_SEL,REG_PAYLOAD_LEN); uint8_t sf = PAN3031_get_sf(); uint8_t crc = PAN3031_get_crc(); uint8_t code_rate = PAN3031_get_code_rate(); uint8_t bw = PAN3031_get_bw(); float a,b,c,d=0.00; if(bw == 7) { bw_val = 125000; } if(bw == 8) { bw_val = 250000; } if(bw == 9) { bw_val = 500000; } a = (float)(8 * pl - 4 * sf + 28 + 16 *crc) / (float)(4 * sf); b = ceil(a); c = code_rate + 4; d = ((float)((2<<(sf-1))) / bw_val); tx_done_time =(12.25 +8 + b*c)*d*1000 ; return tx_done_time + 5; } /** * @brief set bandwidth * @param[in] value relate to bandwidth * BW_125K / BW_250K / BW_500K * @return result */ uint32_t PAN3031_set_bw(uint32_t bw_val) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0d); temp_val_2 = ((temp_val_1 & 0x0F) | (bw_val << 4)) ; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x0d, temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief read bandwidth * @param[in] * @return bandwidth */ uint8_t PAN3031_get_bw(void) { uint8_t tmpreg; tmpreg = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0d); return (tmpreg & 0xff) >> 4; } /** * @brief set spread factor * @param[in] spread factor to set * SF_7 / SF_8 / SF_9 * @return result */ uint32_t PAN3031_set_sf(uint32_t sf_val) { uint8_t temp_val_1; uint8_t temp_val_2; if(sf_val < 7 || sf_val > 12) { return FAIL; } else { temp_val_1 = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0e); temp_val_2 = ((temp_val_1 & 0x0F) | (sf_val << 4)) ; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x0e, temp_val_2) != OK) { return FAIL; } else { return OK; } } } /** * @brief read Spreading Factor * @param[in] * @return Spreading Factor */ uint8_t PAN3031_get_sf(void) { uint8_t tmpreg; tmpreg = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0e); return (tmpreg & 0xff) >> 4; } /** * @brief set payload CRC * @param[in] CRC to set * CRC_ON / CRC_OFF * @return result */ uint32_t PAN3031_set_crc(uint32_t crc_val) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0e); temp_val_2 = ((temp_val_1 & 0xF7) | (crc_val << 3)) ; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x0e, temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief read payload CRC * @param[in] * @return CRC status */ uint8_t PAN3031_get_crc(void) { uint8_t tmpreg; tmpreg = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0e); return (tmpreg & 0x08) >> 3; } /** * @brief set code rate * @param[in] code rate to set * CODE_RATE_45 / CODE_RATE_46 / CODE_RATE_47 / CODE_RATE_48 * @return result */ uint32_t PAN3031_set_code_rate(uint8_t code_rate) { uint8_t tmpreg = 0; tmpreg = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0d); tmpreg &= ~(0x7 << 1); tmpreg |= (code_rate << 1); if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x0d, tmpreg) != OK) { return FAIL; } else { return OK; } } /** * @brief get code rate * @param[in] * @return code rate */ uint8_t PAN3031_get_code_rate(void) { uint8_t code_rate = 0; uint8_t tmpreg = 0; tmpreg = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0d); code_rate = ((tmpreg & 0x0e) >> 1); return code_rate; } /** * @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 PAN3031_set_mode(uint8_t mode) { if(PAN3031_write_reg(REG_OP_MODE,mode) != OK) { return FAIL; } else { return OK; } } /** * @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 PAN3031_get_mode(void) { return PAN3031_read_reg(REG_OP_MODE); } /** * @brief set rf Tx mode * @param[in] * PAN3031_TX_SINGLE/PAN3031_TX_CONTINOUS * @return result */ uint32_t PAN3031_set_tx_mode(uint8_t mode) { uint8_t tmp; tmp = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x06); tmp = tmp & (~(1 << 2)); tmp = tmp | (mode << 2); if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x06, tmp) != OK) { return FAIL; } else { return OK; } } /** * @brief set rf Rx mode * @param[in] * PAN3031_RX_SINGLE/PAN3031_RX_SINGLE_TIMEOUT/PAN3031_RX_CONTINOUS * @return result */ uint32_t PAN3031_set_rx_mode(uint8_t mode) { uint8_t tmp; tmp = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x06); tmp = tmp & (~(3 << 0)); tmp = tmp | (mode << 0); if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x06, tmp) != OK) { return FAIL; } else { return OK; } } /** * @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 PAN3031_set_timeout(uint32_t timeout) { uint8_t timeout_lsb = 0; uint8_t timeout_msb = 0; if(timeout > 0xffff) { timeout = 0xffff; } timeout_lsb = timeout & 0xff; timeout_msb = (timeout >> 8) & 0xff; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x07, timeout_lsb) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x08, timeout_msb) != OK) { return FAIL; } else { return OK; } } /** * @brief get snr value * @param[in] * @return snr */ float PAN3031_get_snr(void) { float snr_val=0.0; uint8_t sig_pow_l, sig_pow_m, sig_pow_h; uint8_t noise_pow_l, noise_pow_m, noise_pow_h; uint32_t sig_pow_val; uint32_t noise_pow_val; uint32_t sf_val; sig_pow_l = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x74); sig_pow_m = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x75); sig_pow_h = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x76); sig_pow_val = ((sig_pow_h << 16) | (sig_pow_m << 8) | sig_pow_l ); noise_pow_l = PAN3031_read_spec_page_reg(PAGE2_SEL, 0x71); noise_pow_m = PAN3031_read_spec_page_reg(PAGE2_SEL, 0x72); noise_pow_h = PAN3031_read_spec_page_reg(PAGE2_SEL, 0x73); noise_pow_val = ((noise_pow_h << 16) | (noise_pow_m << 8) | noise_pow_l ); sf_val = (PAN3031_read_spec_page_reg(PAGE1_SEL, 0x7c) & 0xf0) >> 4; if(noise_pow_val == 0) { noise_pow_val = 1; } snr_val = (float)(10 * log10((sig_pow_val / pow(2,sf_val)) / noise_pow_val)); return snr_val; } /** * @brief get rssi value * @param[in] * @return rssi */ float PAN3031_get_rssi(void) { float rssi_val; int rssi_mix_val; int bw_pow_val; float snr; float Pn; int bw_val = PAN3031_get_bw(); switch(bw_val) { case 6 : bw_pow_val = 15; break; case 7 : bw_pow_val = 12; break; case 8: bw_pow_val = 9; break; case 9: bw_pow_val = 6; break; } snr = PAN3031_get_snr(); if(snr < 6) { Pn = bw_pow_val - 0.9*snr; rssi_mix_val = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x7e); rssi_val = (float)rssi_mix_val - 256 - Pn; }else{ rssi_mix_val = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x7e); rssi_val = rssi_mix_val - 256; } return rssi_val; } /** * @brief set PA2_IB * @param[in] PA2_IB * @return result */ uint32_t PAN3031_set_PA2_IB(uint8_t mode) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x4B); temp_val_2 = ((temp_val_1 & 0xF0) | (mode << 3)) ; if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4B,temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief set PA1_IB * @param[in] PA1_IB * @return result */ uint32_t PAN3031_set_PA1_IB(uint8_t mode) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x43); temp_val_2 = ((temp_val_1 & 0xF0) | (mode << 3)) ; #if defined(JAP_915) temp_val_2 = 0xf2; #endif if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x43,temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief set LDO_TX_VSEL * @param[in] LDO_TX_VSEL * @return result */ uint32_t PAN3031_set_LDO_TX_VSEL(uint8_t mode) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x35); temp_val_2 = ((temp_val_1 & 0xF8) | mode) ; if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x35,temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief set pwr * @param[in] PA_PWR * @return result */ uint32_t PAN3031_set_PWR(uint8_t tx_power) { return PAN3031_write_spec_page_reg(PAGE1_SEL, 0x63, tx_power); } /** * @brief set tx_power * @param[in] Reference datasheet for tx_power parameter description * @return result */ uint32_t PAN3031_set_tx_power(uint8_t tx_power) { if(tx_power == 0) { if(PAN3031_set_PWR(0) != OK) { return FAIL; } if(PAN3031_set_PA2_IB(0) != OK) { return FAIL; } if(PAN3031_set_PA1_IB(0) != OK) { return FAIL; } if(PAN3031_set_LDO_TX_VSEL(0) != OK) { return FAIL; } } else if(tx_power == 1) { if(PAN3031_set_PWR(0) != OK) { return FAIL; } if(PAN3031_set_PA2_IB(0) != OK) { return FAIL; } if(PAN3031_set_PA1_IB(0) != OK) { return FAIL; } if(PAN3031_set_LDO_TX_VSEL(3) != OK) { return FAIL; } } else if(tx_power == 2) { if(PAN3031_set_PWR(0) != OK) { return FAIL; } if(PAN3031_set_PA2_IB(0) != OK) { return FAIL; } if(PAN3031_set_PA1_IB(1) != OK) { return FAIL; } if(PAN3031_set_LDO_TX_VSEL(3) != OK) { return FAIL; } } else if((tx_power > 2)&&(tx_power < 11)) { if(PAN3031_set_PWR(tx_power-3) != OK) { return FAIL; } if(PAN3031_set_PA2_IB(1) != OK) { return FAIL; } if(PAN3031_set_PA1_IB(1) != OK) { return FAIL; } if(PAN3031_set_LDO_TX_VSEL(3) != OK) { return FAIL; } } else if((tx_power > 10)&&(tx_power < 25)) { if(PAN3031_set_PWR(((tx_power-10) << 4) | 0x07) != OK) { return FAIL; } if(PAN3031_set_PA2_IB(1) != OK) { return FAIL; } if(PAN3031_set_PA1_IB(1) != OK) { return FAIL; } if(PAN3031_set_LDO_TX_VSEL(3) != OK) { return FAIL; } }else if(tx_power == 25) { if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x63, 0xE7) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x35, 0x1F) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x43, 0xF1) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4B, 0x4F) != OK) { return FAIL; } }else if(tx_power == 26) { if(PAN3031_set_PWR(((tx_power-11) << 4) | 0x07) != OK) { return FAIL; } if(PAN3031_set_PA2_IB(1) != OK) { return FAIL; } if(PAN3031_set_PA1_IB(1) != OK) { return FAIL; } if(PAN3031_set_LDO_TX_VSEL(3) != OK) { return FAIL; } } else if((tx_power > 26)&&(tx_power < 31)) { if(PAN3031_set_PWR(0xf7) != OK) { return FAIL; } if(PAN3031_set_PA2_IB(1) != OK) { return FAIL; } if(PAN3031_set_PA1_IB(1) != OK) { return FAIL; } if(PAN3031_set_LDO_TX_VSEL(tx_power-23) != OK) { return FAIL; } } else { return FAIL; } return OK; } /** * @brief get tx_power * @param[in] * @return tx_power */ uint32_t PAN3031_get_tx_power(void) { uint8_t pa_1st_pwr, pa_2nd_pwr, pa1, pa1_reg_val, pa2, pa2_reg_val, ldo, ldo_reg_val, txpower; pa_2nd_pwr = (PAN3031_read_spec_page_reg(PAGE1_SEL, 0x63)& 0xf0) >> 4; pa_1st_pwr = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x63)& 0x0f; pa1_reg_val = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x43)& 0x0f; pa2_reg_val = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x4B)& 0x0f; ldo_reg_val = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x35)& 0x07; if((pa_2nd_pwr == 0x0e)&&(pa_1st_pwr == 0x07)&&(pa1_reg_val == 0x01)&&(pa2_reg_val == 0x0f)&&(ldo_reg_val == 0x07)) { return 25; } if(pa2_reg_val) { pa2 = 1; }else { pa2 = 0; } if(pa1_reg_val) { pa1 = 1; }else { pa1 = 0; } if(ldo_reg_val) { ldo = ldo_reg_val - 2; }else { ldo = 0; } txpower = pa_2nd_pwr+pa_1st_pwr+pa2+pa1+ldo; if(txpower > 24) { return (txpower + 1); }else { return txpower; } } /** * @brief set preamble * @param[in] preamble * @return result */ uint32_t PAN3031_set_preamble(uint16_t reg) { uint8_t tmp_value; tmp_value = reg & 0xff; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x13, tmp_value) != OK) { return FAIL; } tmp_value = (reg >> 8) & 0xff; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x14, tmp_value) != OK) { return FAIL; } return OK; } /** * @brief set RF GPIO as input * @param[in] pin number of GPIO to be enable * @return result */ uint32_t PAN3031_set_gpio_input(uint8_t gpio_pin) { uint8_t tmpreg = 0; if(gpio_pin < 8) { tmpreg = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x63); tmpreg |= (1 << gpio_pin); if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x63, tmpreg) != OK) { return FAIL; } else { return OK; } } else { tmpreg = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x64); tmpreg |= (1 << (gpio_pin - 8)); if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x64, tmpreg) != OK) { return FAIL; } else { return OK; } } } /** * @brief set RF GPIO as output * @param[in] pin number of GPIO to be enable * @return result */ uint32_t PAN3031_set_gpio_output(uint8_t gpio_pin) { uint8_t tmpreg = 0; if(gpio_pin < 8) { tmpreg = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x65); tmpreg |= (1 << gpio_pin); if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x65, tmpreg) != OK) { return FAIL; } else { return OK; } } else { tmpreg = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x66); tmpreg |= (1 << (gpio_pin - 8)); if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x66, tmpreg) != OK) { return FAIL; } else { return OK; } } } /** * @brief set GPIO output state, SET or RESET * @param[in] pin number of GPIO to be opearted * 0 - reset, * 1 - set * @return result */ uint32_t PAN3031_set_gpio_state(uint8_t gpio_pin, uint8_t state) { uint8_t tmpreg = 0; if(gpio_pin < 8) { tmpreg = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x67); if(state == 0) { tmpreg &= ~(1 << gpio_pin); } else { tmpreg |= (1 << gpio_pin); } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x67, tmpreg) != OK) { return FAIL; } else { return OK; } } else { tmpreg = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x68); if(state == 0) { tmpreg &= ~(1 << (gpio_pin - 8)); } else { tmpreg |= (1 << (gpio_pin - 8)); } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x68, tmpreg) != OK) { return FAIL; } else { return OK; } } } /** * @brief CAD function enable * @param[in] * @return result */ uint32_t PAN3031_cad_en(void) { PAN3031_set_gpio_output(11); if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x0f, 0x10) != OK) { return FAIL; } return OK; } /** * @brief CAD function disable * @param[in] * @return result */ uint32_t PAN3031_cad_off(void) { uint8_t tmpreg = 0; tmpreg = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x66); tmpreg &= 0xf7; if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x66, tmpreg) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x0f, 0x0a) != OK) { return FAIL; } return OK; } /** * @brief set rf syncword * @param[in] syncword * @return result */ uint32_t PAN3031_set_syncword(uint32_t sync) { if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x0f, sync) != OK) { return FAIL; } else { return OK; } } /** * @brief read rf syncword * @param[in] * @return syncword */ uint8_t PAN3031_get_syncword(void) { uint8_t tmpreg; tmpreg = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x0f); return tmpreg; } /** * @brief send one packet * @param[in] buffer contain data to send * @param[in] the length of data to send * @return result */ uint32_t PAN3031_send_packet(uint8_t *buff, uint32_t len) { // if(len > 64) // { // return FAIL; // } if(PAN3031_write_spec_page_reg(PAGE1_SEL,REG_PAYLOAD_LEN,len) != OK) { return FAIL; } if(PAN3031_write_reg(REG_OP_MODE,PAN3031_MODE_TX) != OK) { return FAIL; } else { PAN3031_write_fifo(REG_FIFO_ACC_ADDR,buff,len); return OK; } } /** * @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 */ uint8_t PAN3031_recv_packet(uint8_t *buff) { uint32_t len = 0; len = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x7D); PAN3031_read_fifo(REG_FIFO_ACC_ADDR,buff,len); /* clear rx done irq */ PAN3031_clr_irq(); return len; } /** * @brief set early interruption * @param[in] PLHD IRQ to set * PLHD_IRQ_ON / PLHD_IRQ_OFF * @return result */ uint32_t PAN3031_set_early_irq(uint32_t earlyirq_val) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x2d); temp_val_2 = ((temp_val_1 & 0x7f) | (earlyirq_val << 7)) ; if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x2d, temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief read plhd irq status * @param[in] * @return plhd irq status */ uint8_t PAN3031_get_early_irq(void) { uint8_t tmpreg; tmpreg = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x2d); return tmpreg; } /** * @brief set plhd * @param[in] PLHD start addr,Range:0..7f * PLHD len * PLHD_LEN8 / PLHD_LEN16 * @return result */ uint32_t PAN3031_set_plhd(uint8_t addr,uint8_t len) { uint8_t temp_val_2; temp_val_2 = ((addr & 0x7f) | (len << 7)) ; if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x2e, temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief read plhd status * @param[in] * @return plhd status */ uint8_t PAN3031_get_plhd(void) { uint8_t tmpreg; tmpreg = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x2e); return ((tmpreg & 0x80) >> 7); } /** * @brief set plhd mask * @param[in] plhd mask to set * PLHD_ON / PLHD_OFF * @return result */ uint32_t PAN3031_set_plhd_mask(uint32_t plhd_val) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x58); temp_val_2 = ((temp_val_1 & 0xef) | (plhd_val << 4)) ; if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x58, temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief read plhd mask * @param[in] * @return plhd mask */ uint8_t PAN3031_get_plhd_mask(void) { uint8_t tmpreg; tmpreg = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x58); return tmpreg; } /** * @brief receive 8 bytes plhd data * @param[in] buffer provide for data to receive * @return result */ uint8_t PAN3031_recv_plhd8(uint8_t *buff) { uint32_t i,len = 8; for(i = 0; i < len; i++) { buff[i] = PAN3031_read_spec_page_reg(PAGE2_SEL, 0x76 + i); } PAN3031_clr_irq(); return len; } /** * @brief receive 16 bytes plhd data * @param[in] buffer provide for data to receive * @return result */ uint8_t PAN3031_recv_plhd16(uint8_t *buff) { uint32_t i,len = 16; for(i = 0; i < len; i++) { if(i<10) { buff[i] = PAN3031_read_spec_page_reg(PAGE2_SEL, 0x76 + i); }else{ buff[i] = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x76 + i - 10); } } PAN3031_clr_irq(); return len; } /** * @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 PAN3031_plhd_receive(uint8_t *buf,uint8_t len) { if(len == PLHD_LEN8) { return PAN3031_recv_plhd8(buf); }else if (len == PLHD_LEN16) { return PAN3031_recv_plhd16(buf); } return FAIL; } /** * @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 PAN3031_set_dcdc_mode(uint32_t dcdc_val) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x1e); temp_val_2 = ((temp_val_1 & 0xfe) | (dcdc_val << 0)) ; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x1e, temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief set LDR mode * @param[in] LDR switch * LDR_ON / LDR_OFF * @return result */ uint32_t PAN3031_set_ldr(uint32_t mode) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE3_SEL, 0x12); temp_val_2 = ((temp_val_1 & 0xF7) | (mode << 3)) ; if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x12, temp_val_2) != OK) { return FAIL; } else { return OK; } } /** * @brief set preamble by Spreading Factor,It is useful in all_sf_search mode * @param[in] Spreading Factor * @return result */ uint32_t PAN3031_set_all_sf_preamble(uint32_t sf) { switch(sf) { case 7: if (PAN3031_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK) { return FAIL; } if (PAN3031_write_spec_page_reg(PAGE3_SEL, 0x13, 128) != OK) { return FAIL; }else { return OK; } case 8: if (PAN3031_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK) { return FAIL; } if (PAN3031_write_spec_page_reg(PAGE3_SEL, 0x13, 80) != OK) { return FAIL; }else { return OK; } case 9: if (PAN3031_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK) { return FAIL; } if (PAN3031_write_spec_page_reg(PAGE3_SEL, 0x13, 48) != OK) { return FAIL; }else { return OK; } default: return FAIL; } } /** * @brief open all sf auto-search mode * @param[in] * @return result */ uint32_t PAN3031_set_all_sf_search(void) { uint8_t tmp_val; tmp_val = (PAN3031_read_spec_page_reg(PAGE3_SEL, 0x12) | 0x01); if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x12, tmp_val) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x2d, 0x07) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x06, 0x01) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, 0xaf) != OK) { return FAIL; } if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x0f, 0x0a) != OK) { return FAIL; } return OK; } /** * @brief close all sf auto-search mode * @param[in] * @return result */ uint32_t PAN3031_set_all_sf_search_off(void) { uint8_t tmp_val; if (PAN3031_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK) { return FAIL; } if (PAN3031_write_spec_page_reg(PAGE3_SEL, 0x13, 8) != OK) { return FAIL; } tmp_val = (PAN3031_read_spec_page_reg(PAGE3_SEL, 0x12) & 0xFE); if(PAN3031_write_spec_page_reg(PAGE3_SEL, 0x12, tmp_val) != OK) { return FAIL; } else { return OK; } } /** * @brief set rf vco * @param[in] * PAN3031_MODE_TX / PAN3031_MODE_RX * @return result */ uint32_t PAN3031_set_vco(uint8_t mode) { uint8_t temp_val_1; uint8_t temp_val_2; temp_val_1 = PAN3031_read_spec_page_reg(PAGE0_SEL, 0x4a); if(mode == PAN3031_MODE_TX) { temp_val_2 = ((temp_val_1 & 0xEF) | (1 << 4)); if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, temp_val_2) != OK) { return FAIL; } else { return OK; } } else if(mode == PAN3031_MODE_RX) { temp_val_2 = (temp_val_1 & 0xEF); if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x4a, temp_val_2) != OK) { return FAIL; } else { return OK; } }else{ return FAIL; } } /** * @brief set rf lna gain * @param[in] * LNA_GAIN_LOW / LNA_GAIN_HIGH * @return result */ uint32_t PAN3031_set_lna_gain(uint8_t mode) { if(mode == LNA_GAIN_LOW) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x32, 0) != OK) { return FAIL; } else { return OK; } } else if(mode == LNA_GAIN_HIGH) { if(PAN3031_write_spec_page_reg(PAGE0_SEL, 0x32, 0x60) != OK) { return FAIL; } else { return OK; } }else{ return FAIL; } } /** * @brief RF IRQ server routine, it should be call at ISR of IRQ pin * @param[in] * @return */ void PAN3031_irq_handler(void) { pan3031_irq_trigged_flag = true; } /** * @brief set carrier_wave mode on * @param[in] * @return result */ uint32_t PAN3031_set_carrier_wave_on(void) { uint8_t temp_val_1; uint8_t temp_val_2; if(PAN3031_write_reg(REG_OP_MODE,PAN3031_MODE_STB3) != OK) { return FAIL; } PAN3031_set_tx_mode(PAN3031_TX_CONTINOUS); PAN3031_set_bw(BW_500K); PAN3031_set_sf(SF_7); PAN3031_set_tx_power(29); temp_val_1 = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x1e); temp_val_2 = ((temp_val_1 & 0xFE) | (1 << 0)) ; if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x1e, temp_val_2) != OK) { return FAIL; } return OK; } /** * @brief set carrier_wave mode frequence * @param[in] RF frequency(in Hz) to set * @return result */ uint32_t PAN3031_set_carrier_wave_freq(uint32_t freq) { uint8_t buf[1]={0}; if(PAN3031_write_reg(REG_OP_MODE,PAN3031_MODE_STB3) != OK) { return FAIL; } if(PAN3031_set_freq(freq) != OK) { return FAIL; } rf_port.set_tx(); if(PAN3031_set_vco(PAN3031_MODE_TX) != OK) { return FAIL; } if(PAN3031_send_packet(buf, 1) != OK) { return FAIL; } return OK; } /** * @brief set carrier_wave mode off * @param[in] * @return result */ uint32_t PAN3031_set_carrier_wave_off(void) { uint8_t temp_val_1; uint8_t temp_val_2; if(PAN3031_write_reg(REG_OP_MODE,PAN3031_MODE_STB3) != OK) { return FAIL; } temp_val_1 = PAN3031_read_spec_page_reg(PAGE1_SEL, 0x1e); temp_val_2 = ((temp_val_1 & 0xFE) | (0 << 0)) ; if(PAN3031_write_spec_page_reg(PAGE1_SEL, 0x1e, temp_val_2) != OK) { return FAIL; } return OK; }