Implement a secure ICS protocol targeting LoRa Node151 microcontroller for controlling irrigation.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

321 lines
9.9 KiB

  1. /*!
  2. * \file lr1110mb1xxs-board.c
  3. *
  4. * \brief Target board LR1110MB1XXS shield driver implementation
  5. *
  6. * \copyright Revised BSD License, see section \ref LICENSE.
  7. *
  8. * \code
  9. * ______ _
  10. * / _____) _ | |
  11. * ( (____ _____ ____ _| |_ _____ ____| |__
  12. * \____ \| ___ | (_ _) ___ |/ ___) _ \
  13. * _____) ) ____| | | || |_| ____( (___| | | |
  14. * (______/|_____)_|_|_| \__)_____)\____)_| |_|
  15. * (C)2019-2019 Semtech
  16. *
  17. * \endcode
  18. *
  19. */
  20. #include <stdlib.h>
  21. #include "utilities.h"
  22. #include "board-config.h"
  23. #include "delay.h"
  24. #include "rtc-board.h"
  25. #include "radio.h"
  26. #include "lr1110_hal.h"
  27. #include "lr1110_radio.h"
  28. #include "lr1110_system.h"
  29. #include "lr1110_regmem.h"
  30. #include "lr1110-board.h"
  31. #define LR1110_SHIELD_HAS_TCXO 1
  32. #if( LR1110_SHIELD_HAS_TCXO == 1 )
  33. #undef BOARD_TCXO_WAKEUP_TIME
  34. #define BOARD_TCXO_WAKEUP_TIME 5 // 5 milliseconds
  35. #endif
  36. /*!
  37. * Debug GPIO pins objects
  38. */
  39. #if defined( USE_RADIO_DEBUG )
  40. Gpio_t DbgPinTx;
  41. Gpio_t DbgPinRx;
  42. #endif
  43. static void lr1110_board_init_tcxo_io( const void* context );
  44. void lr1110_board_init_io( const void* context )
  45. {
  46. GpioInit( &( ( lr1110_t* ) context )->reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  47. GpioInit( &( ( lr1110_t* ) context )->spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  48. GpioInit( &( ( lr1110_t* ) context )->dio_1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  49. GpioInit( &( ( lr1110_t* ) context )->busy, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  50. }
  51. void lr1110_board_deinit_io( const void* context )
  52. {
  53. GpioInit( &( ( lr1110_t* ) context )->reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  54. GpioInit( &( ( lr1110_t* ) context )->spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  55. GpioInit( &( ( lr1110_t* ) context )->dio_1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  56. GpioInit( &( ( lr1110_t* ) context )->busy, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  57. }
  58. void lr1110_board_init_dbg_io( const void* context )
  59. {
  60. #if defined( USE_RADIO_DEBUG )
  61. GpioInit( &DbgPinTx, RADIO_DBG_PIN_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  62. GpioInit( &DbgPinRx, RADIO_DBG_PIN_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  63. #endif
  64. }
  65. void lr1110_board_set_rf_tx_power( const void* context, int8_t power )
  66. {
  67. // TODO: Add PA Config check
  68. if( power > 0 )
  69. {
  70. if( power > 22 )
  71. {
  72. power = 22;
  73. }
  74. }
  75. else
  76. {
  77. if( power < -9 )
  78. {
  79. power = -9;
  80. }
  81. }
  82. lr1110_radio_set_tx_params( context, power, LR1110_RADIO_RAMP_TIME_40U );
  83. }
  84. uint32_t lr1110_board_get_tcxo_wakeup_time( const void* context )
  85. {
  86. return BOARD_TCXO_WAKEUP_TIME;
  87. }
  88. uint32_t lr1110_get_dio_1_pin_state( const void* context )
  89. {
  90. return GpioRead( &( ( lr1110_t* ) context )->dio_1 );
  91. }
  92. void lr1110_board_init( const void* context, lr1110_dio_irq_handler dio_irq )
  93. {
  94. lr1110_system_reset( context );
  95. lr1110_hal_set_operating_mode( context, LR1110_HAL_OP_MODE_STDBY_RC );
  96. // Attach interrupt handler to radio irq pin
  97. GpioSetInterrupt( &( ( lr1110_t* ) context )->dio_1, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, dio_irq );
  98. lr1110_system_stat1_t stat1;
  99. lr1110_system_stat2_t stat2;
  100. uint32_t irq = 0;
  101. lr1110_system_get_status( context, &stat1, &stat2, &irq );
  102. lr1110_system_version_t version;
  103. lr1110_system_get_version( context, &version );
  104. lr1110_system_errors_t errors = { 0 };
  105. lr1110_system_get_errors( context, &errors );
  106. lr1110_system_clear_errors( context );
  107. // Initialize TCXO control
  108. lr1110_board_init_tcxo_io( context );
  109. // Initialize RF switch control
  110. lr1110_system_rfswitch_config_t rf_switch_configuration;
  111. rf_switch_configuration.enable = LR1110_SYSTEM_RFSW0_HIGH | LR1110_SYSTEM_RFSW1_HIGH;
  112. rf_switch_configuration.standby = 0;
  113. rf_switch_configuration.rx = LR1110_SYSTEM_RFSW0_HIGH;
  114. rf_switch_configuration.tx = LR1110_SYSTEM_RFSW0_HIGH | LR1110_SYSTEM_RFSW1_HIGH;
  115. rf_switch_configuration.wifi = 0;
  116. rf_switch_configuration.gnss = 0;
  117. lr1110_system_set_dio_as_rf_switch( context, &rf_switch_configuration );
  118. lr1110_radio_pa_config_t paConfig = {
  119. .pa_sel = LR1110_RADIO_PA_SEL_LP,
  120. .pa_reg_supply = LR1110_RADIO_PA_REG_SUPPLY_DCDC,
  121. .pa_dutycycle = 0x04,
  122. .pa_hp_sel = 0x00,
  123. };
  124. lr1110_radio_set_pa_config( context, &paConfig );
  125. // Set packet type
  126. lr1110_radio_packet_types_t packet_type = LR1110_RADIO_PACKET_LORA;
  127. lr1110_radio_set_packet_type( context, packet_type );
  128. }
  129. static void lr1110_board_init_tcxo_io( const void* context )
  130. {
  131. #if( LR1110_SHIELD_HAS_TCXO == 1 )
  132. lr1110_system_set_tcxo_mode( context, LR1110_SYSTEM_TCXO_SUPPLY_VOLTAGE_1_8V,
  133. ( lr1110_board_get_tcxo_wakeup_time( context ) * 1000 ) / 30.52 );
  134. uint8_t calib_params = LR1110_SYSTEM_CALIBRATE_LF_RC_MASK | LR1110_SYSTEM_CALIBRATE_HF_RC_MASK |
  135. LR1110_SYSTEM_CALIBRATE_PLL_MASK | LR1110_SYSTEM_CALIBRATE_ADC_MASK |
  136. LR1110_SYSTEM_CALIBRATE_IMG_MASK | LR1110_SYSTEM_CALIBRATE_PLL_TX_MASK;
  137. lr1110_system_calibrate( context, calib_params );
  138. #endif
  139. }
  140. //
  141. // lr1110_hal.h API implementation
  142. //
  143. static lr1110_hal_status_t lr1110_hal_wait_on_busy( const void* context );
  144. lr1110_hal_status_t lr1110_hal_write( const void* context, const uint8_t* command, const uint16_t command_length,
  145. const uint8_t* data, const uint16_t data_length )
  146. {
  147. if( lr1110_hal_wakeup( context ) == LR1110_HAL_STATUS_OK )
  148. {
  149. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
  150. for( uint16_t i = 0; i < command_length; i++ )
  151. {
  152. SpiInOut( &( ( lr1110_t* ) context )->spi, command[i] );
  153. }
  154. for( uint16_t i = 0; i < data_length; i++ )
  155. {
  156. SpiInOut( &( ( lr1110_t* ) context )->spi, data[i] );
  157. }
  158. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
  159. // 0x011B - LR1110_SYSTEM_SET_SLEEP_OC
  160. if( ( ( command[0] << 8 ) | command[1] ) != 0x011B )
  161. {
  162. return lr1110_hal_wait_on_busy( context );
  163. }
  164. else
  165. {
  166. return LR1110_HAL_STATUS_OK;
  167. }
  168. }
  169. return LR1110_HAL_STATUS_ERROR;
  170. }
  171. lr1110_hal_status_t lr1110_hal_read( const void* context, const uint8_t* command, const uint16_t command_length,
  172. uint8_t* data, const uint16_t data_length )
  173. {
  174. if( lr1110_hal_wakeup( context ) == LR1110_HAL_STATUS_OK )
  175. {
  176. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
  177. for( uint16_t i = 0; i < command_length; i++ )
  178. {
  179. SpiInOut( &( ( lr1110_t* ) context )->spi, command[i] );
  180. }
  181. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
  182. lr1110_hal_wait_on_busy( context );
  183. // Send dummy byte
  184. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
  185. SpiInOut( &( ( lr1110_t* ) context )->spi, 0 );
  186. for( uint16_t i = 0; i < data_length; i++ )
  187. {
  188. data[i] = SpiInOut( &( ( lr1110_t* ) context )->spi, 0 );
  189. }
  190. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
  191. return lr1110_hal_wait_on_busy( context );
  192. }
  193. return LR1110_HAL_STATUS_ERROR;
  194. }
  195. lr1110_hal_status_t lr1110_hal_write_read( const void* context, const uint8_t* command, uint8_t* data,
  196. const uint16_t data_length )
  197. {
  198. if( lr1110_hal_wakeup( context ) == LR1110_HAL_STATUS_OK )
  199. {
  200. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
  201. for( uint16_t i = 0; i < data_length; i++ )
  202. {
  203. data[i] = SpiInOut( &( ( lr1110_t* ) context )->spi, command[i] );
  204. }
  205. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
  206. // 0x011B - LR1110_SYSTEM_SET_SLEEP_OC
  207. if( ( ( command[0] << 8 ) | command[1] ) != 0x011B )
  208. {
  209. return lr1110_hal_wait_on_busy( context );
  210. }
  211. else
  212. {
  213. return LR1110_HAL_STATUS_OK;
  214. }
  215. }
  216. return LR1110_HAL_STATUS_ERROR;
  217. }
  218. void lr1110_hal_reset( const void* context )
  219. {
  220. GpioWrite( &( ( lr1110_t* ) context )->reset, 0 );
  221. DelayMs( 1 );
  222. GpioWrite( &( ( lr1110_t* ) context )->reset, 1 );
  223. }
  224. lr1110_hal_status_t lr1110_hal_wakeup( const void* context )
  225. {
  226. if( ( lr1110_hal_get_operating_mode( context ) == LR1110_HAL_OP_MODE_SLEEP ) ||
  227. ( lr1110_hal_get_operating_mode( context ) == LR1110_HAL_OP_MODE_RX_DC ) )
  228. {
  229. // Wakeup radio
  230. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 0 );
  231. GpioWrite( &( ( lr1110_t* ) context )->spi.Nss, 1 );
  232. // Radio is awake in STDBY_RC mode
  233. ( ( lr1110_t* ) context )->op_mode = LR1110_HAL_OP_MODE_STDBY_RC;
  234. }
  235. // Wait on busy pin for 100 ms
  236. return lr1110_hal_wait_on_busy( context );
  237. }
  238. static lr1110_hal_status_t lr1110_hal_wait_on_busy( const void* context )
  239. {
  240. while( GpioRead( &( ( lr1110_t* ) context )->busy ) == 1 )
  241. {
  242. ;
  243. }
  244. return LR1110_HAL_STATUS_OK;
  245. }
  246. lr1110_hal_operating_mode_t lr1110_hal_get_operating_mode( const void* context )
  247. {
  248. return ( ( lr1110_t* ) context )->op_mode;
  249. }
  250. void lr1110_hal_set_operating_mode( const void* context, lr1110_hal_operating_mode_t op_mode )
  251. {
  252. ( ( lr1110_t* ) context )->op_mode = op_mode;
  253. #if defined( USE_RADIO_DEBUG )
  254. switch( op_mode )
  255. {
  256. case LR1110_HAL_OP_MODE_TX:
  257. GpioWrite( &DbgPinTx, 1 );
  258. GpioWrite( &DbgPinRx, 0 );
  259. break;
  260. case LR1110_HAL_OP_MODE_RX:
  261. case LR1110_HAL_OP_MODE_RX_C:
  262. case LR1110_HAL_OP_MODE_RX_DC:
  263. GpioWrite( &DbgPinTx, 0 );
  264. GpioWrite( &DbgPinRx, 1 );
  265. break;
  266. default:
  267. GpioWrite( &DbgPinTx, 0 );
  268. GpioWrite( &DbgPinRx, 0 );
  269. break;
  270. }
  271. #endif
  272. }