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