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.
 
 
 
 
 
 

374 lines
11 KiB

  1. /*!
  2. * \file main.c
  3. *
  4. * \brief Ping-Pong implementation
  5. *
  6. * \copyright Revised BSD License, see section \ref LICENSE.
  7. *
  8. * \code
  9. * ______ _
  10. * / _____) _ | |
  11. * ( (____ _____ ____ _| |_ _____ ____| |__
  12. * \____ \| ___ | (_ _) ___ |/ ___) _ \
  13. * _____) ) ____| | | || |_| ____( (___| | | |
  14. * (______/|_____)_|_|_| \__)_____)\____)_| |_|
  15. * (C)2013-2017 Semtech
  16. *
  17. * \endcode
  18. *
  19. * \author Miguel Luis ( Semtech )
  20. *
  21. * \author Gregory Cristian ( Semtech )
  22. */
  23. #include <string.h>
  24. #include "board.h"
  25. #include "gpio.h"
  26. #include "delay.h"
  27. #include "timer.h"
  28. #include "radio.h"
  29. #if defined( REGION_AS923 )
  30. #define RF_FREQUENCY 923000000 // Hz
  31. #elif defined( REGION_AU915 )
  32. #define RF_FREQUENCY 915000000 // Hz
  33. #elif defined( REGION_CN470 )
  34. #define RF_FREQUENCY 470000000 // Hz
  35. #elif defined( REGION_CN779 )
  36. #define RF_FREQUENCY 779000000 // Hz
  37. #elif defined( REGION_EU433 )
  38. #define RF_FREQUENCY 433000000 // Hz
  39. #elif defined( REGION_EU868 )
  40. #define RF_FREQUENCY 868000000 // Hz
  41. #elif defined( REGION_KR920 )
  42. #define RF_FREQUENCY 920000000 // Hz
  43. #elif defined( REGION_IN865 )
  44. #define RF_FREQUENCY 865000000 // Hz
  45. #elif defined( REGION_US915 )
  46. #define RF_FREQUENCY 915000000 // Hz
  47. #elif defined( REGION_RU864 )
  48. #define RF_FREQUENCY 864000000 // Hz
  49. #else
  50. #error "Please define a frequency band in the compiler options."
  51. #endif
  52. #define TX_OUTPUT_POWER 14 // dBm
  53. #if defined( USE_MODEM_LORA )
  54. #define LORA_BANDWIDTH 0 // [0: 125 kHz,
  55. // 1: 250 kHz,
  56. // 2: 500 kHz,
  57. // 3: Reserved]
  58. #define LORA_SPREADING_FACTOR 7 // [SF7..SF12]
  59. #define LORA_CODINGRATE 1 // [1: 4/5,
  60. // 2: 4/6,
  61. // 3: 4/7,
  62. // 4: 4/8]
  63. #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
  64. #define LORA_SYMBOL_TIMEOUT 5 // Symbols
  65. #define LORA_FIX_LENGTH_PAYLOAD_ON false
  66. #define LORA_IQ_INVERSION_ON false
  67. #elif defined( USE_MODEM_FSK )
  68. #define FSK_FDEV 25000 // Hz
  69. #define FSK_DATARATE 50000 // bps
  70. #define FSK_BANDWIDTH 50000 // Hz
  71. #define FSK_AFC_BANDWIDTH 83333 // Hz
  72. #define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx
  73. #define FSK_FIX_LENGTH_PAYLOAD_ON false
  74. #else
  75. #error "Please define a modem in the compiler options."
  76. #endif
  77. typedef enum
  78. {
  79. LOWPOWER,
  80. RX,
  81. RX_TIMEOUT,
  82. RX_ERROR,
  83. TX,
  84. TX_TIMEOUT,
  85. }States_t;
  86. #define RX_TIMEOUT_VALUE 1000
  87. #define BUFFER_SIZE 64 // Define the payload size here
  88. const uint8_t PingMsg[] = "PING";
  89. const uint8_t PongMsg[] = "PONG";
  90. uint16_t BufferSize = BUFFER_SIZE;
  91. uint8_t Buffer[BUFFER_SIZE];
  92. States_t State = LOWPOWER;
  93. int8_t RssiValue = 0;
  94. int8_t SnrValue = 0;
  95. /*!
  96. * Radio events function pointer
  97. */
  98. static RadioEvents_t RadioEvents;
  99. /*!
  100. * LED GPIO pins objects
  101. */
  102. extern Gpio_t Led1;
  103. extern Gpio_t Led2;
  104. /*!
  105. * \brief Function to be executed on Radio Tx Done event
  106. */
  107. void OnTxDone( void );
  108. /*!
  109. * \brief Function to be executed on Radio Rx Done event
  110. */
  111. void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
  112. /*!
  113. * \brief Function executed on Radio Tx Timeout event
  114. */
  115. void OnTxTimeout( void );
  116. /*!
  117. * \brief Function executed on Radio Rx Timeout event
  118. */
  119. void OnRxTimeout( void );
  120. /*!
  121. * \brief Function executed on Radio Rx Error event
  122. */
  123. void OnRxError( void );
  124. /**
  125. * Main application entry point.
  126. */
  127. int main( void )
  128. {
  129. bool isMaster = true;
  130. uint8_t i;
  131. // Target board initialization
  132. BoardInitMcu( );
  133. BoardInitPeriph( );
  134. // Radio initialization
  135. RadioEvents.TxDone = OnTxDone;
  136. RadioEvents.RxDone = OnRxDone;
  137. RadioEvents.TxTimeout = OnTxTimeout;
  138. RadioEvents.RxTimeout = OnRxTimeout;
  139. RadioEvents.RxError = OnRxError;
  140. Radio.Init( &RadioEvents );
  141. Radio.SetChannel( RF_FREQUENCY );
  142. #if defined( USE_MODEM_LORA )
  143. Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
  144. LORA_SPREADING_FACTOR, LORA_CODINGRATE,
  145. LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
  146. true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );
  147. Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
  148. LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
  149. LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
  150. 0, true, 0, 0, LORA_IQ_INVERSION_ON, true );
  151. Radio.SetMaxPayloadLength( MODEM_LORA, BUFFER_SIZE );
  152. #elif defined( USE_MODEM_FSK )
  153. Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
  154. FSK_DATARATE, 0,
  155. FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
  156. true, 0, 0, 0, 3000 );
  157. Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
  158. 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
  159. 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true,
  160. 0, 0,false, true );
  161. Radio.SetMaxPayloadLength( MODEM_FSK, BUFFER_SIZE );
  162. #else
  163. #error "Please define a frequency band in the compiler options."
  164. #endif
  165. Radio.Rx( RX_TIMEOUT_VALUE );
  166. while( 1 )
  167. {
  168. switch( State )
  169. {
  170. case RX:
  171. if( isMaster == true )
  172. {
  173. if( BufferSize > 0 )
  174. {
  175. if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
  176. {
  177. // Indicates on a LED that the received frame is a PONG
  178. GpioToggle( &Led1 );
  179. // Send the next PING frame
  180. Buffer[0] = 'P';
  181. Buffer[1] = 'I';
  182. Buffer[2] = 'N';
  183. Buffer[3] = 'G';
  184. // We fill the buffer with numbers for the payload
  185. for( i = 4; i < BufferSize; i++ )
  186. {
  187. Buffer[i] = i - 4;
  188. }
  189. DelayMs( 1 );
  190. Radio.Send( Buffer, BufferSize );
  191. }
  192. else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
  193. { // A master already exists then become a slave
  194. isMaster = false;
  195. GpioToggle( &Led2 ); // Set LED off
  196. Radio.Rx( RX_TIMEOUT_VALUE );
  197. }
  198. else // valid reception but neither a PING or a PONG message
  199. { // Set device as master ans start again
  200. isMaster = true;
  201. Radio.Rx( RX_TIMEOUT_VALUE );
  202. }
  203. }
  204. }
  205. else
  206. {
  207. if( BufferSize > 0 )
  208. {
  209. if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
  210. {
  211. // Indicates on a LED that the received frame is a PING
  212. GpioToggle( &Led1 );
  213. // Send the reply to the PONG string
  214. Buffer[0] = 'P';
  215. Buffer[1] = 'O';
  216. Buffer[2] = 'N';
  217. Buffer[3] = 'G';
  218. // We fill the buffer with numbers for the payload
  219. for( i = 4; i < BufferSize; i++ )
  220. {
  221. Buffer[i] = i - 4;
  222. }
  223. DelayMs( 1 );
  224. Radio.Send( Buffer, BufferSize );
  225. }
  226. else // valid reception but not a PING as expected
  227. { // Set device as master and start again
  228. isMaster = true;
  229. Radio.Rx( RX_TIMEOUT_VALUE );
  230. }
  231. }
  232. }
  233. State = LOWPOWER;
  234. break;
  235. case TX:
  236. // Indicates on a LED that we have sent a PING [Master]
  237. // Indicates on a LED that we have sent a PONG [Slave]
  238. GpioToggle( &Led2 );
  239. Radio.Rx( RX_TIMEOUT_VALUE );
  240. State = LOWPOWER;
  241. break;
  242. case RX_TIMEOUT:
  243. case RX_ERROR:
  244. if( isMaster == true )
  245. {
  246. // Send the next PING frame
  247. Buffer[0] = 'P';
  248. Buffer[1] = 'I';
  249. Buffer[2] = 'N';
  250. Buffer[3] = 'G';
  251. for( i = 4; i < BufferSize; i++ )
  252. {
  253. Buffer[i] = i - 4;
  254. }
  255. DelayMs( 1 );
  256. Radio.Send( Buffer, BufferSize );
  257. }
  258. else
  259. {
  260. Radio.Rx( RX_TIMEOUT_VALUE );
  261. }
  262. State = LOWPOWER;
  263. break;
  264. case TX_TIMEOUT:
  265. Radio.Rx( RX_TIMEOUT_VALUE );
  266. State = LOWPOWER;
  267. break;
  268. case LOWPOWER:
  269. default:
  270. // Set low power
  271. break;
  272. }
  273. BoardLowPowerHandler( );
  274. // Process Radio IRQ
  275. if( Radio.IrqProcess != NULL )
  276. {
  277. Radio.IrqProcess( );
  278. }
  279. }
  280. }
  281. void OnTxDone( void )
  282. {
  283. Radio.Sleep( );
  284. State = TX;
  285. }
  286. void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
  287. {
  288. Radio.Sleep( );
  289. BufferSize = size;
  290. memcpy( Buffer, payload, BufferSize );
  291. RssiValue = rssi;
  292. SnrValue = snr;
  293. State = RX;
  294. }
  295. void OnTxTimeout( void )
  296. {
  297. Radio.Sleep( );
  298. State = TX_TIMEOUT;
  299. }
  300. void OnRxTimeout( void )
  301. {
  302. Radio.Sleep( );
  303. State = RX_TIMEOUT;
  304. }
  305. void OnRxError( void )
  306. {
  307. Radio.Sleep( );
  308. State = RX_ERROR;
  309. }