|
- /*!
- * \file lr1110mb1xxs-board.c
- *
- * \brief Target board LR1110MB1XXS shield driver implementation
- *
- * \copyright Revised BSD License, see section \ref LICENSE.
- *
- * \code
- * ______ _
- * / _____) _ | |
- * ( (____ _____ ____ _| |_ _____ ____| |__
- * \____ \| ___ | (_ _) ___ |/ ___) _ \
- * _____) ) ____| | | || |_| ____( (___| | | |
- * (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2019-2019 Semtech
- *
- * \endcode
- *
- */
- #include <stdlib.h>
- #include "utilities.h"
- #include "board-config.h"
- #include "delay.h"
- #include "rtc-board.h"
- #include "radio.h"
-
- #include "lr1110_hal.h"
- #include "lr1110_radio.h"
- #include "lr1110_system.h"
- #include "lr1110_regmem.h"
-
- #include "lr1110-board.h"
-
- #define LR1110_SHIELD_HAS_TCXO 1
-
- #if( LR1110_SHIELD_HAS_TCXO == 1 )
- #undef BOARD_TCXO_WAKEUP_TIME
- #define BOARD_TCXO_WAKEUP_TIME 5 // 5 milliseconds
- #endif
-
- /*!
- * Debug GPIO pins objects
- */
- #if defined( USE_RADIO_DEBUG )
- Gpio_t DbgPinTx;
- Gpio_t DbgPinRx;
- #endif
-
- static void lr1110_board_init_tcxo_io( const void* context );
-
- void lr1110_board_init_io( const void* context )
- {
- GpioInit( &( ( lr1110_t* ) context )->reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
- GpioInit( &( ( lr1110_t* ) context )->spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
- GpioInit( &( ( lr1110_t* ) context )->dio_1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
- GpioInit( &( ( lr1110_t* ) context )->busy, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
- }
-
- void lr1110_board_deinit_io( const void* context )
- {
- GpioInit( &( ( lr1110_t* ) context )->reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
- GpioInit( &( ( lr1110_t* ) context )->spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
- GpioInit( &( ( lr1110_t* ) context )->dio_1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
- GpioInit( &( ( lr1110_t* ) context )->busy, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
- }
-
- void lr1110_board_init_dbg_io( const void* context )
- {
- #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 lr1110_board_set_rf_tx_power( const void* context, int8_t power )
- {
- // TODO: Add PA Config check
- if( power > 0 )
- {
- if( power > 22 )
- {
- power = 22;
- }
- }
- else
- {
- if( power < -9 )
- {
- power = -9;
- }
- }
- lr1110_radio_set_tx_params( context, power, LR1110_RADIO_RAMP_TIME_40U );
- }
-
- uint32_t lr1110_board_get_tcxo_wakeup_time( const void* context )
- {
- return BOARD_TCXO_WAKEUP_TIME;
- }
-
- uint32_t lr1110_get_dio_1_pin_state( const void* context )
- {
- return GpioRead( &( ( lr1110_t* ) context )->dio_1 );
- }
-
- void lr1110_board_init( const void* context, lr1110_dio_irq_handler dio_irq )
- {
- lr1110_system_reset( context );
- lr1110_hal_set_operating_mode( context, LR1110_HAL_OP_MODE_STDBY_RC );
-
- // Attach interrupt handler to radio irq pin
- GpioSetInterrupt( &( ( lr1110_t* ) context )->dio_1, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, dio_irq );
-
- lr1110_system_stat1_t stat1;
- lr1110_system_stat2_t stat2;
- uint32_t irq = 0;
- lr1110_system_get_status( context, &stat1, &stat2, &irq );
- lr1110_system_version_t version;
- lr1110_system_get_version( context, &version );
- lr1110_system_errors_t errors = { 0 };
- lr1110_system_get_errors( context, &errors );
- lr1110_system_clear_errors( context );
-
- // Initialize TCXO control
- lr1110_board_init_tcxo_io( context );
-
- // Initialize RF switch control
- lr1110_system_rfswitch_config_t rf_switch_configuration;
- rf_switch_configuration.enable = LR1110_SYSTEM_RFSW0_HIGH | LR1110_SYSTEM_RFSW1_HIGH;
- rf_switch_configuration.standby = 0;
- rf_switch_configuration.rx = LR1110_SYSTEM_RFSW0_HIGH;
- rf_switch_configuration.tx = LR1110_SYSTEM_RFSW0_HIGH | LR1110_SYSTEM_RFSW1_HIGH;
- rf_switch_configuration.wifi = 0;
- rf_switch_configuration.gnss = 0;
-
- lr1110_system_set_dio_as_rf_switch( context, &rf_switch_configuration );
-
- lr1110_radio_pa_config_t paConfig = {
- .pa_sel = LR1110_RADIO_PA_SEL_LP,
- .pa_reg_supply = LR1110_RADIO_PA_REG_SUPPLY_DCDC,
- .pa_dutycycle = 0x04,
- .pa_hp_sel = 0x00,
- };
- lr1110_radio_set_pa_config( context, &paConfig );
-
- // Set packet type
- lr1110_radio_packet_types_t packet_type = LR1110_RADIO_PACKET_LORA;
- lr1110_radio_set_packet_type( context, packet_type );
- }
-
- static void lr1110_board_init_tcxo_io( const void* context )
- {
- #if( LR1110_SHIELD_HAS_TCXO == 1 )
- lr1110_system_set_tcxo_mode( context, LR1110_SYSTEM_TCXO_SUPPLY_VOLTAGE_1_8V,
- ( lr1110_board_get_tcxo_wakeup_time( context ) * 1000 ) / 30.52 );
-
- uint8_t calib_params = LR1110_SYSTEM_CALIBRATE_LF_RC_MASK | LR1110_SYSTEM_CALIBRATE_HF_RC_MASK |
- LR1110_SYSTEM_CALIBRATE_PLL_MASK | LR1110_SYSTEM_CALIBRATE_ADC_MASK |
- LR1110_SYSTEM_CALIBRATE_IMG_MASK | LR1110_SYSTEM_CALIBRATE_PLL_TX_MASK;
- lr1110_system_calibrate( context, calib_params );
- #endif
- }
-
- //
- // lr1110_hal.h API implementation
- //
-
- static lr1110_hal_status_t lr1110_hal_wait_on_busy( const void* context );
-
- lr1110_hal_status_t lr1110_hal_write( const void* context, const uint8_t* command, const uint16_t command_length,
- const uint8_t* data, const uint16_t data_length )
-
- {
- if( lr1110_hal_wakeup( context ) == LR1110_HAL_STATUS_OK )
- {
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
- for( uint16_t i = 0; i < command_length; i++ )
- {
- SpiInOut( &( ( lr1110_t* ) context )->spi, command[i] );
- }
- for( uint16_t i = 0; i < data_length; i++ )
- {
- SpiInOut( &( ( lr1110_t* ) context )->spi, data[i] );
- }
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
-
- // 0x011B - LR1110_SYSTEM_SET_SLEEP_OC
- if( ( ( command[0] << 8 ) | command[1] ) != 0x011B )
- {
- return lr1110_hal_wait_on_busy( context );
- }
- else
- {
- return LR1110_HAL_STATUS_OK;
- }
- }
- return LR1110_HAL_STATUS_ERROR;
- }
-
- lr1110_hal_status_t lr1110_hal_read( const void* context, const uint8_t* command, const uint16_t command_length,
- uint8_t* data, const uint16_t data_length )
- {
- if( lr1110_hal_wakeup( context ) == LR1110_HAL_STATUS_OK )
- {
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
-
- for( uint16_t i = 0; i < command_length; i++ )
- {
- SpiInOut( &( ( lr1110_t* ) context )->spi, command[i] );
- }
-
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
-
- lr1110_hal_wait_on_busy( context );
-
- // Send dummy byte
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
-
- SpiInOut( &( ( lr1110_t* ) context )->spi, 0 );
-
- for( uint16_t i = 0; i < data_length; i++ )
- {
- data[i] = SpiInOut( &( ( lr1110_t* ) context )->spi, 0 );
- }
-
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
-
- return lr1110_hal_wait_on_busy( context );
- }
- return LR1110_HAL_STATUS_ERROR;
- }
-
- lr1110_hal_status_t lr1110_hal_write_read( const void* context, const uint8_t* command, uint8_t* data,
- const uint16_t data_length )
- {
- if( lr1110_hal_wakeup( context ) == LR1110_HAL_STATUS_OK )
- {
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
-
- for( uint16_t i = 0; i < data_length; i++ )
- {
- data[i] = SpiInOut( &( ( lr1110_t* ) context )->spi, command[i] );
- }
-
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
-
- // 0x011B - LR1110_SYSTEM_SET_SLEEP_OC
- if( ( ( command[0] << 8 ) | command[1] ) != 0x011B )
- {
- return lr1110_hal_wait_on_busy( context );
- }
- else
- {
- return LR1110_HAL_STATUS_OK;
- }
- }
- return LR1110_HAL_STATUS_ERROR;
- }
-
- void lr1110_hal_reset( const void* context )
- {
- GpioWrite( &( ( lr1110_t* ) context )->reset, 0 );
- DelayMs( 1 );
- GpioWrite( &( ( lr1110_t* ) context )->reset, 1 );
- }
-
- lr1110_hal_status_t lr1110_hal_wakeup( const void* context )
- {
- if( ( lr1110_hal_get_operating_mode( context ) == LR1110_HAL_OP_MODE_SLEEP ) ||
- ( lr1110_hal_get_operating_mode( context ) == LR1110_HAL_OP_MODE_RX_DC ) )
- {
- // Wakeup radio
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
- GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
-
- // Radio is awake in STDBY_RC mode
- ( ( lr1110_t* ) context )->op_mode = LR1110_HAL_OP_MODE_STDBY_RC;
- }
-
- // Wait on busy pin for 100 ms
- return lr1110_hal_wait_on_busy( context );
- }
-
- static lr1110_hal_status_t lr1110_hal_wait_on_busy( const void* context )
- {
- while( GpioRead( &( ( lr1110_t* ) context )->busy ) == 1 )
- {
- ;
- }
- return LR1110_HAL_STATUS_OK;
- }
-
- lr1110_hal_operating_mode_t lr1110_hal_get_operating_mode( const void* context )
- {
- return ( ( lr1110_t* ) context )->op_mode;
- }
-
- void lr1110_hal_set_operating_mode( const void* context, lr1110_hal_operating_mode_t op_mode )
- {
- ( ( lr1110_t* ) context )->op_mode = op_mode;
-
- #if defined( USE_RADIO_DEBUG )
- switch( op_mode )
- {
- case LR1110_HAL_OP_MODE_TX:
- GpioWrite( &DbgPinTx, 1 );
- GpioWrite( &DbgPinRx, 0 );
- break;
- case LR1110_HAL_OP_MODE_RX:
- case LR1110_HAL_OP_MODE_RX_C:
- case LR1110_HAL_OP_MODE_RX_DC:
- GpioWrite( &DbgPinTx, 0 );
- GpioWrite( &DbgPinRx, 1 );
- break;
- default:
- GpioWrite( &DbgPinTx, 0 );
- GpioWrite( &DbgPinRx, 0 );
- break;
- }
- #endif
- }
|