/*! * \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 #include "utilities.h" #include "board-config.h" #include "delay.h" #include "radio.h" #include "sx1272-board.h" /*! * \brief Gets the board PA selection configuration * * \param [IN] channel Channel frequency in Hz * \retval PaSelect RegPaConfig PaSelect value */ static uint8_t SX1272GetPaSelect( uint32_t channel ); /*! * 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 AntTx; Gpio_t AntRx; /*! * Debug GPIO pins objects */ #if defined( USE_RADIO_DEBUG ) Gpio_t DbgPinTx; Gpio_t DbgPinRx; #endif 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 ); // DIO4 and DIO5 aren't connected. // Initialize Gpio_t port to NULL. SX1272.DIO4.port = NULL; SX1272.DIO5.port = NULL; } 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] ); } 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 ); } 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 = SX1272Read( REG_PACONFIG ); paDac = SX1272Read( REG_PADAC ); paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | SX1272GetPaSelect( SX1272.Settings.Channel ); if( ( paConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST ) { if( power > 17 ) { paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON; } else { paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF; } if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON ) { if( power < 5 ) { power = 5; } if( power > 20 ) { power = 20; } paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F ); } else { if( power < 2 ) { power = 2; } if( power > 17 ) { power = 17; } paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F ); } } else { if( power < -1 ) { power = -1; } if( power > 14 ) { power = 14; } paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F ); } SX1272Write( REG_PACONFIG, paConfig ); SX1272Write( REG_PADAC, paDac ); } static uint8_t SX1272GetPaSelect( uint32_t channel ) { return RF_PACONFIG_PASELECT_RFO; } void SX1272SetAntSwLowPower( bool status ) { if( RadioIsActive != status ) { RadioIsActive = status; if( status == false ) { SX1272AntSwInit( ); } else { SX1272AntSwDeInit( ); } } } void SX1272AntSwInit( void ) { GpioInit( &AntTx, RADIO_ANT_SWITCH_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); GpioInit( &AntRx, RADIO_ANT_SWITCH_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 ); } void SX1272AntSwDeInit( void ) { GpioInit( &AntTx, RADIO_ANT_SWITCH_TX, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &AntRx, RADIO_ANT_SWITCH_RX, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); } void SX1272SetAntSw( uint8_t opMode ) { switch( opMode ) { case RFLR_OPMODE_TRANSMITTER: GpioWrite( &AntTx, 1 ); GpioWrite( &AntRx, 0 ); break; case RFLR_OPMODE_RECEIVER: case RFLR_OPMODE_RECEIVER_SINGLE: case RFLR_OPMODE_CAD: default: GpioWrite( &AntTx, 0 ); GpioWrite( &AntRx, 1 ); 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