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