SX1276GenericLib to support sx1276 bassed LoRa modules, including HopeRF RFM95, Murata CMWX1ZZABZ and Semtech SX1276MB1MAS/SX1276MB1LAS modules
Dependents: DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_USB_Rx ... more
Fork of SX1276Lib by
Diff: sx1276/sx1276-mbed-hal.cpp
- Revision:
- 36:f2b885b6f33e
- Parent:
- 35:c278a826a8e2
- Child:
- 38:d9189d958db8
diff -r c278a826a8e2 -r f2b885b6f33e sx1276/sx1276-mbed-hal.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sx1276/sx1276-mbed-hal.cpp Sat May 06 12:10:11 2017 +0000 @@ -0,0 +1,416 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2014 Semtech + +Description: - + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ + +/* + * additional development to make it more generic across multiple os versions + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + +#include "sx1276-mbed-hal.h" + +const RadioRegisters_t SX1276Generic::RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE; + +SX1276Generic::SX1276Generic( RadioEvents_t *events, BoardType_t board, + PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset, + PinName dio0, PinName dio1, PinName dio2, PinName dio3, PinName dio4, PinName dio5, + PinName antSwitch, PinName antSwitchTX, PinName antSwitchTXBoost, PinName tcxo) + : SX1276( events) +{ + this->RadioEvents = events; + boardConnected = board; + + _antSwitch = NULL; + _antSwitchTX = NULL; + _antSwitchTXBoost = NULL; + + _tcxo = NULL; + if (tcxo != NC) + _tcxo = new DigitalOut(tcxo); + + switch(boardConnected) { + case SX1276MB1MAS: + case SX1276MB1LAS: + _antSwitch = new DigitalInOut(antSwitch); + break; + case RFM95_SX1276: + break; + case MURATA_SX1276: + _antSwitch = new DigitalInOut(antSwitch); + _antSwitchTX = new DigitalInOut(antSwitchTX); + _antSwitchTXBoost = new DigitalInOut(antSwitchTXBoost); + break; + default: + break; + } + _spi = new SPI(mosi, miso, sclk ); + _nss = new DigitalOut(nss); + + _reset = new DigitalInOut(reset); + + _dio0 = NULL; + _dio1 = NULL; + _dio2 = NULL; + _dio3 = NULL; + _dio4 = NULL; + _dio5 = NULL; + if (dio0 != NC) + _dio0 = new InterruptIn(dio0); + if (dio1 != NC) + _dio1 = new InterruptIn(dio1); + if (dio2 != NC) + _dio2 = new InterruptIn(dio2); + if (dio3 != NC) + _dio3 = new InterruptIn(dio3); + if (dio4 != NC) + _dio4 = new InterruptIn(dio4); + if (dio5 != NC) + _dio5 = new DigitalIn(dio5); + + Reset( ); + + IoInit( ); + + RxChainCalibration( ); + + SetOpMode( RF_OPMODE_SLEEP ); + + IoIrqInit( dioIrq ); + + RadioRegistersInit( ); + + SetModem( MODEM_FSK ); + + this->settings.State = RF_IDLE ; +} + +SX1276Generic::~SX1276Generic() +{ + if (_antSwitch) + delete _antSwitch; + if (_antSwitchTX) + delete _antSwitchTX; + if (_antSwitchTXBoost) + delete _antSwitchTXBoost; + + if (_tcxo) { + *_tcxo = 0; + delete (_tcxo); + } + delete _reset; + delete _spi; + delete _nss; + + if (_dio0) + delete _dio0; + if (_dio1) + delete _dio1; + if (_dio2) + delete _dio2; + if (_dio3) + delete _dio3; + if (_dio4) + delete _dio4; + if (_dio5) + delete _dio5; +} + +//------------------------------------------------------------------------- +// Board relative functions +//------------------------------------------------------------------------- +uint8_t SX1276Generic::DetectBoardType( void ) +{ + return boardConnected; +} + +void SX1276Generic::IoInit( void ) +{ + if (_tcxo) + *_tcxo = 1; + AntSwInit( ); + SpiInit( ); +} + +void SX1276Generic::RadioRegistersInit( ) +{ + uint8_t i = 0; + for( i = 0; i < sizeof( RadioRegsInit ) / sizeof( RadioRegisters_t ); i++ ) + { + SetModem( RadioRegsInit[i].Modem ); + Write( RadioRegsInit[i].Addr, RadioRegsInit[i].Value ); + } +} + +void SX1276Generic::SpiInit( void ) +{ + *_nss = 1; + _spi->format( 8,0 ); + uint32_t frequencyToSet = 8000000; +#ifdef TARGET_KL25Z //busclock frequency is halved -> double the spi frequency to compensate + _spi->frequency( frequencyToSet * 2 ); +#else + _spi->frequency( frequencyToSet ); +#endif + wait_ms(100); +} + +void SX1276Generic::IoIrqInit( DioIrqHandler *irqHandlers ) +{ +#if( defined ( TARGET_NUCLEO_L152RE ) || defined ( TARGET_LPC11U6X ) ) + dio0.mode( PullDown ); + dio1.mode( PullDown ); + dio2.mode( PullDown ); + dio3.mode( PullDown ); + dio4.mode( PullDown ); +#endif + if (_dio0) + _dio0->rise(callback(this, static_cast< TriggerMB1xAS > ( irqHandlers[0] ))); + if (_dio1) + _dio1->rise(callback(this, static_cast< TriggerMB1xAS > ( irqHandlers[1] ))); + if (_dio2) + _dio2->rise(callback(this, static_cast< TriggerMB1xAS > ( irqHandlers[2] ))); + if (_dio3) + _dio3->rise(callback(this, static_cast< TriggerMB1xAS > ( irqHandlers[3] ))); + if (_dio4) + _dio4->rise(callback(this, static_cast< TriggerMB1xAS > ( irqHandlers[4] ))); +} + +void SX1276Generic::IoDeInit( void ) +{ + //nothing +} + +void SX1276Generic::SetRfTxPower( int8_t power ) +{ + uint8_t paConfig = 0; + uint8_t paDac = 0; + + paConfig = Read( REG_PACONFIG ); + paDac = Read( REG_PADAC ); + + paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | GetPaSelect( this->settings.Channel ); + paConfig = ( paConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70; + + 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 & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F ); + } + else + { + if( power < 2 ) + { + power = 2; + } + if( power > 17 ) + { + power = 17; + } + paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F ); + } + } + else + { + if( power < -1 ) + { + power = -1; + } + if( power > 14 ) + { + power = 14; + } + paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F ); + } + Write( REG_PACONFIG, paConfig ); + Write( REG_PADAC, paDac ); +} + + +uint8_t SX1276Generic::GetPaSelect( uint32_t channel ) +{ + if( channel > RF_MID_BAND_THRESH ) + { + if( boardConnected == SX1276MB1LAS || boardConnected == RFM95_SX1276) + { + return RF_PACONFIG_PASELECT_PABOOST; + } + else + { + return RF_PACONFIG_PASELECT_RFO; + } + } + else + { + return RF_PACONFIG_PASELECT_RFO; + } +} + +void SX1276Generic::SetAntSwLowPower( bool status ) +{ + if( isRadioActive != status ) + { + isRadioActive = status; + + if( status == false ) + { + AntSwInit( ); + } + else + { + AntSwDeInit( ); + } + } +} + +void SX1276Generic::AntSwInit( void ) +{ + if (_antSwitch) + *_antSwitch = 0; + if (boardConnected == MURATA_SX1276) { + *_antSwitchTX = 0; + *_antSwitchTXBoost = 0; + } +} + +void SX1276Generic::AntSwDeInit( void ) +{ + if (_antSwitch) + *_antSwitch = 0; + if (boardConnected == MURATA_SX1276) { + *_antSwitchTX = 0; + *_antSwitchTXBoost = 0; + } +} + + +void SX1276Generic::SetAntSw( uint8_t opMode ) +{ + switch( opMode ) + { + case RFLR_OPMODE_TRANSMITTER: + if (boardConnected == MURATA_SX1276) { + *_antSwitch = 0;// Murata-RX + *_antSwitchTX = 1; // alternate: antSwitchTXBoost = 1 + *_antSwitchTXBoost = 0; + } else { + if (_antSwitch) + *_antSwitch = 1; + } + break; + case RFLR_OPMODE_RECEIVER: + case RFLR_OPMODE_RECEIVER_SINGLE: + case RFLR_OPMODE_CAD: + if (boardConnected == MURATA_SX1276) { + *_antSwitch = 1; // Murata-RX + *_antSwitchTX = 0; + *_antSwitchTXBoost = 0; + } else { + if (_antSwitch) + _antSwitch = 0; + } + break; + default: + if (boardConnected == MURATA_SX1276) { + *_antSwitch = 0; //Murata-RX + *_antSwitchTX = 0; + *_antSwitchTXBoost = 0; + } else { + if (_antSwitch) + *_antSwitch = 0; + } + break; + } +} + +bool SX1276Generic::CheckRfFrequency( uint32_t frequency ) +{ + // Implement check. Currently all frequencies are supported + return true; +} + +void SX1276Generic::Reset( void ) +{ + _reset->output(); + *_reset = 0; + wait_ms( 1 ); + *_reset = 1; + _reset->input(); // I don't know my input again, maybe to save power (Helmut T) + wait_ms( 6 ); +} + +void SX1276Generic::Write( uint8_t addr, uint8_t data ) +{ + Write( addr, &data, 1 ); +} + +uint8_t SX1276Generic::Read( uint8_t addr ) +{ + uint8_t data; + Read( addr, &data, 1 ); + return data; +} + +void SX1276Generic::Write( uint8_t addr, uint8_t *buffer, uint8_t size ) +{ + uint8_t i; + + *_nss = 0; // what about SPI hold/release timing on fast MCUs? Helmut + _spi->write( addr | 0x80 ); + for( i = 0; i < size; i++ ) + { + _spi->write( buffer[i] ); + } + *_nss = 1; +} + +void SX1276Generic::Read( uint8_t addr, uint8_t *buffer, uint8_t size ) +{ + uint8_t i; + + *_nss = 0; // what about SPI hold/release timing on fast MCUs? Helmut + _spi->write( addr & 0x7F ); + for( i = 0; i < size; i++ ) + { + buffer[i] = _spi->write( 0 ); + } + *_nss = 1; +} + +void SX1276Generic::WriteFifo( uint8_t *buffer, uint8_t size ) +{ + Write( 0, buffer, size ); +} + +void SX1276Generic::ReadFifo( uint8_t *buffer, uint8_t size ) +{ + Read( 0, buffer, size ); +}