/* / _____) _ | | ( (____ _____ ____ _| |_ _____ ____| |__ \____ \| ___ | (_ _) ___ |/ ___) _ \ _____) ) ____| | | || |_| ____( (___| | | | (______/|_____)_|_|_| \__)_____)\____)_| |_| (C)2014 Semtech Description: sx1208 dirver License: Revised BSD License, see LICENSE.TXT file include in the project Maintainer: Leo Xie, Jiapeng Li */ #include "myRadio_gpio.h" #include "sx1208-reg.h" #include "sx1208.h" #include "string.h" #include "sx1208-state-grid.h" #include "sx1231_params.h" #define SX1208_RX_FIFO_THRESH (66-15) #define SX1208_TX_FIFO_THRESH (15) #define SX1208_PAYLOAD_LENGTH_MAX (0xFF) uint8_t sx1208_read(uint8_t addr); void sx1208_write(uint8_t addr, uint8_t data); void sx1208_rmw(uint8_t addr, uint8_t mask, uint8_t val); void sx1208_rmw_bit(uint8_t addr, uint8_t bit, uint8_t val); void sx1208_read_burst(uint8_t addr, uint8_t *buf, uint16_t len); void sx1208_write_burst(uint8_t addr, uint8_t *buf, uint16_t len); int sx1208_read_fifo(uint8_t *buf, uint16_t len); int sx1208_write_fifo(uint8_t *buf, uint16_t len); // static void sx1208_set_rxbw(uint32_t fdev, uint32_t br); static void sx1208_set_preamble_reg(uint16_t len); static void sx1208_set_crc_auto_clear(sx1208_crc_auto_clear_t crcac_opt); void sx1208_irq_dio0(void); void sx1208_irq_dio1(void); void sx1208_irq_dio2(void); void sx1208_irq_dio3(void); void sx1208_irq_dio4(void); void sx1208_irq_dio5(void); volatile uint8_t sx1208_ext_fifo[256]; volatile uint8_t sx1208_ext_fifo_rd_index; volatile uint8_t sx1208_ext_fifo_wr_index; volatile int16_t sx1208_ext_fifo_count; static volatile sx1208_callback_t sx1208_callback_g; static volatile uint16_t sx1208_tx_preamble_len_g; static volatile uint16_t sx1208_rx_preamble_len_g; static volatile uint8_t sx1208_high_power; // 0: off, 1: on static sx1208_rx_pkt_t sx1208_rx_pkt; static uint16_t sx1208_rx_payload_length; static sx1208_protocol_t sx1208_protocol; bool Irq0Fired = false; #define SX1208_FSK_RXBW_TAB_LENGTH (21) static const uint32_t sx1208_fsk_rxbw_tab[SX1208_FSK_RXBW_TAB_LENGTH]={ 2600, 3100, 3900, 5200, 6300, 7800, 10400, 12500, 15600, 20800, 25000, 31300, 41700, 50000, 62500, 83300, 100000, 125000, 166700, 200000, 250000 }; static void delay_ms(uint32_t delay_ms) { uint32_t i = 0; uint32_t j = 0; for (i = 0; i < delay_ms; i++) { for (j = 0; j < 10000; j++) { ; } } } void sx1208_reset(void) { uint8_t i; // HAL_SX1208_RST_OUTPUT(); RF_SX12xx_RST_H(); delay_ms(1); // HAL_SX1208_RST_INPUT(); RF_SX12xx_RST_L(); delay_ms(6); } void sx1208_initParams(void) { uint8_t i; sx1208_params_unit_t *params; params = (sx1208_params_unit_t *)sx1231ParamsList; for ( i = 0; i < sizeof(sx1231ParamsList) / 2; i++) { if (params->addr != 0xff) { sx1208_write(params->addr, params->value); } params ++; } } void sx1208_init(sx1208_callback_t sx1208_cb) { uint8_t i; /** sfotware reset sx1208 */ sx1208_reset(); // sx1208_initParams(); /** Callback function */ sx1208_callback_g = NULL; if(sx1208_cb != NULL){ sx1208_callback_g = sx1208_cb; } sx1208_ext_fifo_rd_index = 0; sx1208_ext_fifo_count = 0; sx1208_ext_fifo_wr_index = 0; sx1208_high_power = 0; sx1208_rx_pkt.buf = NULL; sx1208_rx_payload_length = 0; /** write default value to SX1208, refer to SX1208-Datasheet for register description */ sx1208_write(REG_RXBW, 0x55); sx1208_write(REG_AFCBW, 0x8B); sx1208_write(REG_DIOMAPPING2, 0x07); for(i=0; i<8; i++){ sx1208_write(REG_SYNCVALUE1+i, 0x01); // Write SyncWord to default value } sx1208_write(REG_FIFOTHRESH, 0x8F); /** Receiver optimized */ sx1208_write(REG_TESTLNA, 0X2D); // =0x2D,enable sensitivity boost, this is optional // =0x1B,disable sensitivity boost { /* read test */ // uint8_t read_reg; // read_reg = sx1208_read(REG_RSSITHRESH); // read_reg = sx1208_read(REG_PACKETCONFIG2); // read_reg = sx1208_read(REG_TESTLNA); // read_reg = sx1208_read(REG_TESTLNA); } { //LNA \AGC config sx1208_write(REG_LNA, 0X89); // 0x89 means 200 Ohm LNA and AGC OFF with G1 sx1208_write(REG_DAGC, 0x30); // } { sx1208_write(REG_RSSITHRESH, 0xE8); // =0xE8,Auto threshold: sx1208_write(REG_PACKETCONFIG2, 0x04); // .AutoRxRestartOn = 1, } // sx1208_write(REG_RSSICONFIG, sx1208_read(REG_RSSICONFIG) | RF_RSSI_START); { // uint8_t i = 0; // /** configure DIO Mapping */ // sx1208_write( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00 | \ // RF_DIOMAPPING1_DIO1_00 | \ // RF_DIOMAPPING1_DIO2_00 | \ // RF_DIOMAPPING1_DIO3_FIFO_FULL ); // //fifo总共66BYTE,写完DIO3会拉高 // while(READ_RF_SX12xx_DIO3() == 0) // { // sx1208_write(REG_FIFO, 0xff); // i ++; // if (i >= 66) // { // break; // } // } // delay_ms(10); // //FifoOverrun位写1,DIO3会置低,不操作该bit,电平会一直保持 // sx1208_write(REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN); // while (1) // { // ; // } } delay_ms(10); } void sx1208_set_mode(sx1208_mode_t mode) { uint8_t cur_mode; cur_mode = sx1208_read(REG_OPMODE) & (~RF_OPMODE_MASK); if(cur_mode != mode){ /** adjust high power option, must be closed during RX */ switch(mode){ case RF_OPMODE_TRANSMITTER: if( sx1208_high_power && (sx1208_read(REG_OCP) != 0x0F) ){ sx1208_write(REG_OCP, 0x0F); sx1208_write(REG_TEST_PA1, 0x5D); sx1208_write(REG_TEST_PA2, 0x7C); } break; case RF_OPMODE_RECEIVER: if( sx1208_high_power && (sx1208_read(REG_OCP) != 0x1F) ){ sx1208_write(REG_OCP, 0x1F); sx1208_write(REG_TEST_PA1, 0x55); sx1208_write(REG_TEST_PA2, 0x70); } break; default: break; } sx1208_rmw(REG_OPMODE, RF_OPMODE_MASK, mode); } while( (sx1208_read(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00 ); } void sx1208_set_config(sx1208_config_t *config) { sx1208_protocol = config->protocol; sx1208_set_frf(config->frf); sx1208_set_fdev(config->fdev); sx1208_set_bitrate(config->bitrate); sx1208_set_rxbw(config->fdev, config->bitrate); sx1208_set_tx_power(config->tx_power); sx1208_set_sync_word(config->sync_word, config->sync_word_len); switch(sx1208_protocol){ case SX1208_PROTOCOL_STATE_GRID: /** To implement state grid protocol, we need use software crc and fixed length packet */ sx1208_set_header_mode(SX1208_HEADER_DISABLE); sx1208_set_crc_mode(SX1208_CRC_OFF); sx1208_write(REG_PAYLOADLENGTH, SX1208_PAYLOAD_LENGTH_MAX); break; case SX1208_PROTOCOL_NONE: sx1208_set_header_mode(config->header_mode); if(config->header_mode == SX1208_HEADER_DISABLE){ sx1208_write(REG_PAYLOADLENGTH, config->payload_len); } sx1208_set_crc_mode(config->crc_mode); break; } /** If CRC AUTO CLEAR is on, then there will be not PKT_READY interrupt, when crc is error Turn it off to make sure PKT_READY is generated at any time */ sx1208_set_crc_auto_clear(SX1208_CRC_AUTO_CLEAR_OFF); sx1208_set_preamble(SX1208_TX_PREAMBLE, config->tx_preamble_len); sx1208_set_preamble(SX1208_RX_PREAMBLE, config->rx_preamble_len); } int8_t sx1208_send(uint8_t *buf, uint8_t len, uint16_t timeout) { int i; uint8_t mode; uint16_t crc; uint8_t frame_length; mode = sx1208_read(REG_OPMODE) & (~RF_OPMODE_MASK); if( mode == RF_OPMODE_TRANSMITTER || mode == RF_OPMODE_RECEIVER ){ return -1; } if(len == 0){ return -2; } /** TX start is triggered by FifoLevel */ if(len > SX1208_TX_FIFO_THRESH){ /** set fifo threshold for TX mode, make a software FIFO ALMOST Empty INTERRUPT*/ sx1208_write(REG_FIFOTHRESH, SX1208_TX_FIFO_THRESH); }else{ sx1208_write(REG_FIFOTHRESH, len-1); } /** rewrite tx_preamble length to preamble length register */ sx1208_set_preamble_reg(sx1208_tx_preamble_len_g); /** configure DIO Mapping */ sx1208_write( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_PKT_SENT | \ RF_DIOMAPPING1_DIO1_FIFO_LEVEL | \ RF_DIOMAPPING1_DIO2_FIFO_NEMPTY | \ RF_DIOMAPPING1_DIO3_FIFO_FULL ); switch(sx1208_protocol){ case SX1208_PROTOCOL_STATE_GRID: /** State Grid Length area, length of payload */ sx1208_write(REG_FIFO, sx1208_state_grid_whitening_reverse_data(len, 0)); // Use index 0 to whitening the first byte (length). /** State Grid Whole Frame Length, 1 byte for length, 2 bytes for CRC, "len" bytes for payload */ sx1208_write(REG_PAYLOADLENGTH, len+3); /** calculate and append crc bytes */ crc = sx1208_state_grid_crc_calc(buf, len); buf[len] = (uint8_t)crc; buf[len+1] = (uint8_t)(crc>>8); /** recalculate frame length */ frame_length = len + 2; sx1208_state_grid_whitening_reverse_buf(buf, frame_length, 1); // Use index 1 to whitening and reverse payload and crc break; case SX1208_PROTOCOL_NONE: if(sx1208_read(REG_PACKETCONFIG1) & RF_PACKET1_FORMAT_VARIABLE){ sx1208_write(REG_FIFO, len); }else{ sx1208_write(REG_PAYLOADLENGTH, len); } /** recalculate frame length */ frame_length = len; break; } i=0; while(READ_RF_SX12xx_DIO3() == 0){ sx1208_write(REG_FIFO, buf[i]); i++; if(i >= frame_length){ break; } } // TODO: protect this section code /** i shouldn't be re-initialized */ for(; i> 16 ) & 0xFF ) ); sx1208_write( REG_FRFMID, ( uint8_t )( ( frf >> 8 ) & 0xFF ) ); sx1208_write( REG_FRFLSB, ( uint8_t )( frf & 0xFF ) ); } void sx1208_set_fdev( uint32_t fdev ) { if(fdev>100000){ fdev=100000; } fdev = ( uint32_t )( ( double )fdev / ( double )SX1208_FREQ_STEP ); sx1208_write( REG_FDEVMSB, ( uint8_t )( ( fdev >> 8 ) & 0xFF ) ); sx1208_write( REG_FDEVLSB, ( uint8_t )( fdev & 0xFF ) ); } void sx1208_set_bitrate( uint32_t br ) { if(br>100000){ br=100000; } br = ( uint32_t )( ( double )SX1208_FXOSC / ( double )br ); sx1208_write( REG_BITRATEMSB, ( uint8_t )( ( br >> 8 ) & 0xFF ) ); sx1208_write( REG_BITRATELSB, ( uint8_t )( br & 0xFF ) ); } void sx1208_set_rxbw(uint32_t fdev, uint32_t br) { uint8_t reg, RxBwMant, RxBwExp, i; uint32_t sum; sum = fdev * 2 + br; for(i=0; i sum){ break; } } if(i == SX1208_FSK_RXBW_TAB_LENGTH){ // invalid fdev and bitrate (Fdev + bitrate/2 > RxBw) // fdev and bitrate are out of range, use the largest RXBW i = (SX1208_FSK_RXBW_TAB_LENGTH-1); } RxBwExp = 7 - i/3; RxBwMant = 2 - i%3; reg = sx1208_read(REG_RXBW); reg = (reg&RF_RXBW_DCCFREQ_111) | (RxBwMant<<3) | RxBwExp; sx1208_write(REG_RXBW, reg); } sx1208_tx_port_t hal_sx1208_get_tx_port(void) { #if 0 /** use RFIO as OUTPUT port*/ return SX1208_TX_PORT_RFIO; #else /** use PA_BOOST as OUTPUT port */ return SX1208_TX_PORT_PA_BOOST; #endif } void sx1208_set_tx_power( int8_t pow ) { uint8_t reg = 0; uint8_t OutputPower; /** reset power setings, start TX power configuration from exact state */ sx1208_write(REG_PALEVEL, 0x9F); /** disable high power output */ sx1208_write(REG_OCP, 0x1F); sx1208_write(REG_TEST_PA1, 0x55); sx1208_write(REG_TEST_PA2, 0x70); sx1208_high_power = 0; if( hal_sx1208_get_tx_port() == SX1208_TX_PORT_PA_BOOST ){ /** Adjust power value if it is out of range */ if(pow>20){ pow = 20; }else if(pow < 2){ pow = 2; } /** TX on PA_BOOST, this driver doesn't support to use PA1 alone Use PA1 only with PA_BOOST, HW should be different with use both PA1 and PA2*/ if(pow<=17){ if (pow<=13) { reg = RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_OFF; OutputPower = 18 + pow; } else { /** Enable both PA1 and PA2 on PA_BOOST */ reg = RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON; OutputPower = 14 + pow; } }else{ /** Enable both PA1 and PA2 on PA_BOOST, and enable high power output */ reg = RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON; sx1208_write(REG_OCP, 0x0F); sx1208_write(REG_TEST_PA1, 0x5D); sx1208_write(REG_TEST_PA2, 0x7C); OutputPower = 11 + pow; sx1208_high_power = 1; // high power mode } }else{ /** TX on RFIO */ if(pow>13){ pow = 13; }else if(pow < -18){ pow = -18; } /** Enable PA0 on RFIO */ reg = RF_PALEVEL_PA0_ON; OutputPower = 18 + pow; } reg |= OutputPower; sx1208_write(REG_PALEVEL, reg); } void sx1208_set_sync_word(uint8_t *sync_word, uint8_t len) { int8_t i; if(len == 0 || sync_word == NULL){ sx1208_rmw(REG_SYNCCONFIG, RF_SYNC_MASK, RF_SYNC_OFF); for(i = 0; i<8; i++){ sx1208_write(REG_SYNCVALUE1+i, 0x00); } }else if(len <= 8){ sx1208_rmw(REG_SYNCCONFIG, RF_SYNC_MASK, RF_SYNC_ON); // sync word on sx1208_rmw(REG_SYNCCONFIG, RF_SYNC_SIZE_MASK, (len-1)<<3); // sync word size for(i = 0; i>8)); sx1208_write(REG_PREAMBLELSB, (uint8_t)len); } /** low level functions */ uint8_t sx1208_read(uint8_t addr) { uint8_t ret; BOARD_SPI_NSS_L(); SpiReadWrite( (~0x80) & addr ); ret = SpiReadWrite( 0x00 ); BOARD_SPI_NSS_H(); return ret; } void sx1208_write(uint8_t addr, uint8_t data) { BOARD_SPI_NSS_L(); SpiReadWrite( 0x80 | addr ); SpiReadWrite( data ); BOARD_SPI_NSS_H(); } uint8_t sx1208_read_int(uint8_t addr) { uint8_t ret; BOARD_SPI_NSS_L(); SpiReadWrite( (~0x80) & addr ); ret = SpiReadWrite( 0x00 ); BOARD_SPI_NSS_H(); return ret; } void sx1208_write_int(uint8_t addr, uint8_t data) { BOARD_SPI_NSS_L(); SpiReadWrite( 0x80 | addr ); SpiReadWrite( data ); BOARD_SPI_NSS_H(); } /** read-modify write register */ void sx1208_rmw(uint8_t addr, uint8_t mask, uint8_t val) { uint8_t ret; /** read register */ BOARD_SPI_NSS_L(); SpiReadWrite( (~0x80) & addr ); ret = SpiReadWrite( 0x00 ); BOARD_SPI_NSS_H(); /** modify the data */ ret = (ret & mask) | (val & ~mask); /** write data back */ BOARD_SPI_NSS_L(); SpiReadWrite( 0x80 | addr ); SpiReadWrite( ret ); BOARD_SPI_NSS_H(); } /** read-modify write register */ void sx1208_rmw_int(uint8_t addr, uint8_t mask, uint8_t val) { uint8_t ret; /** read register */ BOARD_SPI_NSS_L(); SpiReadWrite( (~0x80) & addr ); ret = SpiReadWrite( 0x00 ); BOARD_SPI_NSS_H(); /** modify the data */ ret = (ret & mask) | (val & ~mask); /** write data back */ BOARD_SPI_NSS_L(); SpiReadWrite( 0x80 | addr ); SpiReadWrite( ret ); BOARD_SPI_NSS_H(); } void sx1208_rmw_bit(uint8_t addr, uint8_t bit, uint8_t val) { uint8_t ret; /** read register */ BOARD_SPI_NSS_L(); SpiReadWrite( (~0x80) & addr ); ret = SpiReadWrite( 0x00 ); BOARD_SPI_NSS_H(); /** modify the data */ ret = (val == 0)? (ret & bit) : (ret | bit); /** write data back */ BOARD_SPI_NSS_L(); SpiReadWrite( 0x80 | addr ); SpiReadWrite( ret ); BOARD_SPI_NSS_H(); } void sx1208_read_burst(uint8_t addr, uint8_t *buf, uint16_t len) { int i; BOARD_SPI_NSS_L(); SpiReadWrite( (~0x80) & addr ); for(i = 0; i SX1208_RX_FIFO_THRESH ){ sx1208_write_int(REG_FIFOTHRESH, SX1208_RX_FIFO_THRESH); }else if(remain_len < 5){ return -1; }else{ sx1208_write_int(REG_FIFOTHRESH, remain_len-2); } return 0; } void sx1208_onDioIrq( void ) { Irq0Fired = true; } void sx1208_process(void) { uint8_t irq_flag2, mode, crc_sta; if (Irq0Fired == true) { Irq0Fired = false; irq_flag2 = sx1208_read_int(REG_IRQFLAGS2); mode = sx1208_read_int(REG_OPMODE) & (~RF_OPMODE_MASK); crc_sta = sx1208_read_int(REG_PACKETCONFIG1) & (~RF_PACKET1_CRC_MASK); switch(mode){ case RF_OPMODE_TRANSMITTER: if(irq_flag2 & RF_IRQFLAGS2_PACKETSENT){ /** package sent, exit */ sx1208_rmw_int(REG_OPMODE, RF_OPMODE_MASK, RF_OPMODE_SLEEP); while( (sx1208_read_int(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00 ); sx1208_callback_g(SX1208_TX_DONE, NULL); } break; case RF_OPMODE_RECEIVER: if( (irq_flag2 & RF_IRQFLAGS2_PAYLOADREADY) &&( (!crc_sta) || (irq_flag2 & RF_IRQFLAGS2_CRCOK) ) ){ while( (READ_RF_SX12xx_DIO2() == 1) && (sx1208_ext_fifo_count < 256) ){ sx1208_ext_fifo[sx1208_ext_fifo_wr_index++] = sx1208_read_int(REG_FIFO); sx1208_ext_fifo_count++; } sx1208_rx_pkt.raw_rssi = sx1208_read_int(REG_RSSIVALUE); switch(sx1208_protocol){ case SX1208_PROTOCOL_STATE_GRID: /** should never here */ if( SX1208_STATE_GRID_GOOD_CRC == sx1208_state_grid_crc_check((void *)(sx1208_ext_fifo+1), sx1208_rx_payload_length-3) ){ memcpy(sx1208_rx_pkt.buf, (void *)(sx1208_ext_fifo+1), sx1208_ext_fifo_count-1); sx1208_rx_pkt.len = sx1208_ext_fifo_count-3; sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_DONE, &sx1208_rx_pkt); }else{ sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_ERROR, NULL); } break; case SX1208_PROTOCOL_NONE: memcpy(sx1208_rx_pkt.buf, (void *)(sx1208_ext_fifo+1), sx1208_ext_fifo_count-1); sx1208_rx_pkt.len = sx1208_ext_fifo_count-1; sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_DONE, &sx1208_rx_pkt); break; } }else{ /** CRC error */ /** package received, exit */ sx1208_rmw_int(REG_OPMODE, RF_OPMODE_MASK, RF_OPMODE_SLEEP); while( (sx1208_read_int(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00 ); sx1208_ext_fifo_count = 0; sx1208_ext_fifo_wr_index = 0; sx1208_callback_g(SX1208_RX_ERROR, NULL); } break; default: break; } } } void sx1208_irq_dio0(void) { uint8_t irq_flag2, mode, crc_sta; irq_flag2 = sx1208_read_int(REG_IRQFLAGS2); mode = sx1208_read_int(REG_OPMODE) & (~RF_OPMODE_MASK); crc_sta = sx1208_read_int(REG_PACKETCONFIG1) & (~RF_PACKET1_CRC_MASK); switch(mode){ case RF_OPMODE_TRANSMITTER: if(irq_flag2 & RF_IRQFLAGS2_PACKETSENT){ /** package sent, exit */ sx1208_rmw_int(REG_OPMODE, RF_OPMODE_MASK, RF_OPMODE_SLEEP); while( (sx1208_read_int(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00 ); sx1208_callback_g(SX1208_TX_DONE, NULL); } break; case RF_OPMODE_RECEIVER: if( (irq_flag2 & RF_IRQFLAGS2_PAYLOADREADY) &&( (!crc_sta) || (irq_flag2 & RF_IRQFLAGS2_CRCOK) ) ){ while( (READ_RF_SX12xx_DIO2() == 1) && (sx1208_ext_fifo_count < 256) ){ sx1208_ext_fifo[sx1208_ext_fifo_wr_index++] = sx1208_read_int(REG_FIFO); sx1208_ext_fifo_count++; } /** package received, exit receive mode */ sx1208_rmw_int(REG_OPMODE, RF_OPMODE_MASK, RF_OPMODE_SLEEP); while( (sx1208_read_int(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00 ); switch(sx1208_protocol){ case SX1208_PROTOCOL_STATE_GRID: /** should never here */ if( SX1208_STATE_GRID_GOOD_CRC == sx1208_state_grid_crc_check((void *)(sx1208_ext_fifo+1), sx1208_rx_payload_length-3) ){ memcpy(sx1208_rx_pkt.buf, (void *)(sx1208_ext_fifo+1), sx1208_ext_fifo_count-1); sx1208_rx_pkt.len = sx1208_ext_fifo_count-3; sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_DONE, &sx1208_rx_pkt); }else{ sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_ERROR, NULL); } break; case SX1208_PROTOCOL_NONE: memcpy(sx1208_rx_pkt.buf, (void *)(sx1208_ext_fifo+1), sx1208_ext_fifo_count-1); sx1208_rx_pkt.len = sx1208_ext_fifo_count-1; sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_DONE, &sx1208_rx_pkt); break; } }else{ /** CRC error */ /** package received, exit */ sx1208_rmw_int(REG_OPMODE, RF_OPMODE_MASK, RF_OPMODE_SLEEP); while( (sx1208_read_int(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00 ); sx1208_ext_fifo_count = 0; sx1208_ext_fifo_wr_index = 0; sx1208_callback_g(SX1208_RX_ERROR, NULL); } break; default: break; } } void sx1208_irq_dio1(void) { uint8_t irq_flag2, mode, len; uint16_t fifo_bytes_remain; irq_flag2 = sx1208_read_int(REG_IRQFLAGS2); mode = sx1208_read_int(REG_OPMODE) & (~RF_OPMODE_MASK); switch(mode){ case RF_OPMODE_TRANSMITTER: if(irq_flag2 & RF_IRQFLAGS2_FIFOLEVEL){ /** rising edge */ }else{ /** falling edge, FIFO almost empty */ while( (READ_RF_SX12xx_DIO3() == 0) && (sx1208_ext_fifo_count > 0) ){ sx1208_write_int(REG_FIFO, sx1208_ext_fifo[sx1208_ext_fifo_rd_index++]); sx1208_ext_fifo_count--; } } break; case RF_OPMODE_RECEIVER: if(irq_flag2 & RF_IRQFLAGS2_FIFOLEVEL){ /** rising edge */ fifo_bytes_remain = 256 - sx1208_ext_fifo_count; fifo_bytes_remain = sx1208_rx_payload_length; len = sx1208_read_fifo( (uint8_t *)sx1208_ext_fifo + (uint8_t)sx1208_ext_fifo_wr_index, fifo_bytes_remain ); sx1208_ext_fifo_wr_index += len; sx1208_ext_fifo_count += len; switch(sx1208_protocol){ case SX1208_PROTOCOL_STATE_GRID: if(sx1208_update_fifo_thresh(sx1208_rx_payload_length, sx1208_ext_fifo_count) < 0){ while(sx1208_ext_fifo_count < sx1208_rx_payload_length){ len = sx1208_read_fifo( (uint8_t *)sx1208_ext_fifo + (uint8_t)sx1208_ext_fifo_wr_index, sx1208_rx_payload_length ); sx1208_ext_fifo_wr_index += len; sx1208_ext_fifo_count += len; } /** package received, exit */ sx1208_rmw_int(REG_OPMODE, RF_OPMODE_MASK, RF_OPMODE_SLEEP); while( (sx1208_read_int(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00 ); sx1208_state_grid_reverse_whitening_buf((void *)sx1208_ext_fifo, sx1208_rx_payload_length ,0); if( SX1208_STATE_GRID_GOOD_CRC == sx1208_state_grid_crc_check((void *)(sx1208_ext_fifo+1), sx1208_rx_payload_length-3) ){ memcpy(sx1208_rx_pkt.buf, (void *)(sx1208_ext_fifo+1), sx1208_ext_fifo_count-1); sx1208_rx_pkt.len = sx1208_ext_fifo_count-3; sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_DONE, &sx1208_rx_pkt); }else{ sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_ERROR, NULL); } } break; case SX1208_PROTOCOL_NONE: break; } }else{ /** falling edge */ } break; default: break; } } void sx1208_irq_dio2(void) { uint8_t irq_flag2, mode, len; irq_flag2 = sx1208_read_int(REG_IRQFLAGS2); mode = sx1208_read_int(REG_OPMODE) & (~RF_OPMODE_MASK); switch(mode){ case RF_OPMODE_TRANSMITTER: break; case RF_OPMODE_RECEIVER: if(irq_flag2 & RF_IRQFLAGS2_FIFONOTEMPTY){ /** rising edge */ switch(sx1208_protocol){ case SX1208_PROTOCOL_STATE_GRID: /** read first byte back, this byte is the length of this frame */ if(sx1208_ext_fifo_wr_index == 0){ sx1208_read_fifo( (uint8_t *)sx1208_ext_fifo + (uint8_t)sx1208_ext_fifo_wr_index, 1 ); sx1208_rx_payload_length = sx1208_state_grid_reverse_whitening_data(sx1208_ext_fifo[0], 0)+3; /** payload length is out of range */ if(sx1208_rx_payload_length > 0xFF){ sx1208_rmw_int(REG_OPMODE, RF_OPMODE_MASK, RF_OPMODE_SLEEP); while( (sx1208_read_int(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00 ); sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_ERROR, NULL); break; } sx1208_ext_fifo_wr_index++; sx1208_ext_fifo_count++; if(sx1208_update_fifo_thresh(sx1208_rx_payload_length, sx1208_ext_fifo_count) < 0){ while(sx1208_ext_fifo_count < sx1208_rx_payload_length){ len = sx1208_read_fifo( (uint8_t *)sx1208_ext_fifo + (uint8_t)sx1208_ext_fifo_wr_index, sx1208_rx_payload_length ); sx1208_ext_fifo_wr_index += len; sx1208_ext_fifo_count += len; } /** package received, exit */ sx1208_rmw_int(REG_OPMODE, RF_OPMODE_MASK, RF_OPMODE_SLEEP); while( (sx1208_read_int(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00 ); sx1208_state_grid_reverse_whitening_buf((void *)sx1208_ext_fifo, sx1208_rx_payload_length ,0); if( SX1208_STATE_GRID_GOOD_CRC == sx1208_state_grid_crc_check((void *)(sx1208_ext_fifo+1), sx1208_rx_payload_length-3) ){ memcpy(sx1208_rx_pkt.buf, (void *)(sx1208_ext_fifo+1), sx1208_ext_fifo_count-1); sx1208_rx_pkt.len = sx1208_ext_fifo_count-3; sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_DONE, &sx1208_rx_pkt); }else{ sx1208_ext_fifo_count = 0; sx1208_callback_g(SX1208_RX_ERROR, NULL); } } } break; case SX1208_PROTOCOL_NONE: break; } } break; default: break; } } void sx1208_irq_dio3(void) { uint8_t irq_flag1, mode, afc_ctl; afc_ctl = sx1208_read_int(REG_AFCCTRL); irq_flag1 = sx1208_read_int(REG_IRQFLAGS1); mode = sx1208_read_int(REG_OPMODE) & (~RF_OPMODE_MASK); switch(mode){ case RF_OPMODE_TRANSMITTER: break; case RF_OPMODE_RECEIVER: if(afc_ctl & RF_AFCCTRL_PREAMBLEDETECT){ //sx1208_rx_pkt.raw_rssi = sx1208_read_rssi(); sx1208_write_int(REG_RSSICONFIG, sx1208_read_int(REG_RSSICONFIG) | RF_RSSI_START); while( 0 == ( sx1208_read_int(REG_RSSICONFIG) & RF_RSSI_DONE ) ); sx1208_rx_pkt.raw_rssi = sx1208_read_int(REG_RSSIVALUE); }else if(irq_flag1 & RF_IRQFLAGS1_SYNCADDRESSMATCH){ //sx1208_rx_pkt.raw_rssi = sx1208_read_rssi(); sx1208_write_int(REG_RSSICONFIG, sx1208_read_int(REG_RSSICONFIG) | RF_RSSI_START); while( 0 == ( sx1208_read_int(REG_RSSICONFIG) & RF_RSSI_DONE ) ); sx1208_rx_pkt.raw_rssi = sx1208_read_int(REG_RSSIVALUE); } break; default: break; } } void sx1208_irq_dio4(void) { }