/*! * \file sx1272-board.c * * \brief Target board SX1272 driver implementation * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * ______ _ * / _____) _ | | * ( (____ _____ ____ _| |_ _____ ____| |__ * \____ \| ___ | (_ _) ___ |/ ___) _ \ * _____) ) ____| | | || |_| ____( (___| | | | * (______/|_____)_|_|_| \__)_____)\____)_| |_| * (C)2013-2017 Semtech * * \endcode * * \author Miguel Luis ( Semtech ) * * \author Gregory Cristian ( Semtech ) */ #include <stdlib.h> #include "utilities.h" #include "board-config.h" #include "delay.h" #include "radio.h" #include "sx1272-board.h" /*! * Flag used to set the RF switch control pins in low power mode when the radio is not active. */ static bool RadioIsActive = false; /*! * Radio driver structure initialization */ const struct Radio_s Radio = { SX1272Init, SX1272GetStatus, SX1272SetModem, SX1272SetChannel, SX1272IsChannelFree, SX1272Random, SX1272SetRxConfig, SX1272SetTxConfig, SX1272CheckRfFrequency, SX1272GetTimeOnAir, SX1272Send, SX1272SetSleep, SX1272SetStby, SX1272SetRx, SX1272StartCad, SX1272SetTxContinuousWave, SX1272ReadRssi, SX1272Write, SX1272Read, SX1272WriteBuffer, SX1272ReadBuffer, SX1272SetMaxPayloadLength, SX1272SetPublicNetwork, SX1272GetWakeupTime, NULL, // void ( *IrqProcess )( void ) NULL, // void ( *RxBoosted )( uint32_t timeout ) - SX126x Only NULL, // void ( *SetRxDutyCycle )( uint32_t rxTime, uint32_t sleepTime ) - SX126x Only }; /*! * Antenna switch GPIO pins objects */ Gpio_t RadioSwitchCtrl1; Gpio_t RadioSwitchCtrl2; Gpio_t RadioPwrAmpCtrl; /*! * Debug GPIO pins objects */ #if defined( USE_RADIO_DEBUG ) Gpio_t DbgPinTx; Gpio_t DbgPinRx; #endif /* PD_2=0 PD_2=1 op PaB rfo rfo 0 4.6 18.5 27.0 1 5.6 21.1 28.1 2 6.7 23.3 29.1 3 7.7 25.3 30.1 4 8.8 26.2 30.7 5 9.8 27.3 31.2 6 10.7 28.1 31.6 7 11.7 28.6 32.2 8 12.8 29.2 32.4 9 13.7 29.9 32.9 10 14.7 30.5 33.1 11 15.6 30.8 33.4 12 16.4 30.9 33.6 13 17.1 31.0 33.7 14 17.8 31.1 33.7 15 18.4 31.1 33.7 */ // txpow: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 static const uint8_t PaBTable[20] = { 0, 0, 0, 0, 0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15 }; // txpow: 20 21 22 23 24 25 26 27 28 29 30 static const uint8_t RfoTable[11] = { 1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 9 }; void SX1272IoInit( void ) { GpioInit( &SX1272.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); GpioInit( &SX1272.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &SX1272.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &SX1272.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &SX1272.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &SX1272.DIO4, RADIO_DIO_4, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &SX1272.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); } void SX1272IoIrqInit( DioIrqHandler **irqHandlers ) { GpioSetInterrupt( &SX1272.DIO0, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[0] ); GpioSetInterrupt( &SX1272.DIO1, IRQ_RISING_FALLING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[1] ); GpioSetInterrupt( &SX1272.DIO2, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[2] ); GpioSetInterrupt( &SX1272.DIO3, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[3] ); GpioSetInterrupt( &SX1272.DIO4, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[4] ); GpioSetInterrupt( &SX1272.DIO5, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[5] ); } void SX1272IoDeInit( void ) { GpioInit( &SX1272.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); GpioInit( &SX1272.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &SX1272.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &SX1272.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &SX1272.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &SX1272.DIO4, RADIO_DIO_4, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &SX1272.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); } void SX1272IoDbgInit( void ) { #if defined( USE_RADIO_DEBUG ) GpioInit( &DbgPinTx, RADIO_DBG_PIN_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &DbgPinRx, RADIO_DBG_PIN_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif } void SX1272IoTcxoInit( void ) { // No TCXO component available on this board design. } void SX1272SetBoardTcxo( uint8_t state ) { // No TCXO component available on this board design. #if 0 if( state == true ) { TCXO_ON( ); DelayMs( BOARD_TCXO_WAKEUP_TIME ); } else { TCXO_OFF( ); } #endif } uint32_t SX1272GetBoardTcxoWakeupTime( void ) { return BOARD_TCXO_WAKEUP_TIME; } void SX1272Reset( void ) { // Enables the TCXO if available on the board design SX1272SetBoardTcxo( true ); // Set RESET pin to 1 GpioInit( &SX1272.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); // Wait 1 ms DelayMs( 1 ); // Configure RESET as input GpioInit( &SX1272.Reset, RADIO_RESET, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); // Wait 6 ms DelayMs( 6 ); } void SX1272SetRfTxPower( int8_t power ) { uint8_t paConfig = 0; uint8_t paDac = 0; paConfig = Radio.Read( REG_PACONFIG ); paDac = Radio.Read( REG_PADAC ); if( power > 19 ) { paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | RF_PACONFIG_PASELECT_RFO; paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | RfoTable[power - 20]; } else { paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | RF_PACONFIG_PASELECT_PABOOST; paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | PaBTable[MAX( power, 0 )]; } Radio.Write( REG_PACONFIG, paConfig ); Radio.Write( REG_PADAC, paDac ); } void SX1272SetAntSwLowPower( bool status ) { if( RadioIsActive != status ) { RadioIsActive = status; if( status == false ) { SX1272AntSwInit( ); } else { SX1272AntSwDeInit( ); } } } void SX1272AntSwInit( void ) { GpioInit( &RadioSwitchCtrl1, RADIO_SWITCH_CTRL1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &RadioSwitchCtrl2, RADIO_SWITCH_CTRL2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &RadioPwrAmpCtrl , RADIO_PWRAMP_CTRL , PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); } void SX1272AntSwDeInit( void ) { GpioInit( &RadioSwitchCtrl1, RADIO_SWITCH_CTRL1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &RadioSwitchCtrl2, RADIO_SWITCH_CTRL2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &RadioPwrAmpCtrl , RADIO_PWRAMP_CTRL , PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); } void SX1272SetAntSw( uint8_t opMode ) { switch( opMode ) { case RFLR_OPMODE_TRANSMITTER: if( ( Radio.Read( REG_PACONFIG ) & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST ) { GpioWrite( &RadioSwitchCtrl1, 1 ); GpioWrite( &RadioSwitchCtrl2, 0 ); } else { GpioWrite( &RadioSwitchCtrl1, 0 ); GpioWrite( &RadioSwitchCtrl2, 1 ); } break; case RFLR_OPMODE_RECEIVER: case RFLR_OPMODE_RECEIVER_SINGLE: case RFLR_OPMODE_CAD: GpioWrite( &RadioSwitchCtrl1, 1 ); GpioWrite( &RadioSwitchCtrl2, 1 ); break; default: GpioWrite( &RadioSwitchCtrl1, 0 ); GpioWrite( &RadioSwitchCtrl2, 0 ); GpioWrite( &RadioPwrAmpCtrl, 0 ); break; } } bool SX1272CheckRfFrequency( uint32_t frequency ) { // Implement check. Currently all frequencies are supported return true; } uint32_t SX1272GetDio1PinState( void ) { return GpioRead( &SX1272.DIO1 ); } #if defined( USE_RADIO_DEBUG ) void SX1272DbgPinTxWrite( uint8_t state ) { GpioWrite( &DbgPinTx, state ); } void SX1272DbgPinRxWrite( uint8_t state ) { GpioWrite( &DbgPinRx, state ); } #endif