Embedded System Design 2 - Project
rn2483.c
Go to the documentation of this file.
1 /* ____ ____ _ __ __ ____ ___
2  * | _ \| _ \ / \ | \/ |/ ___/ _ \
3  * | | | | |_) | / _ \ | |\/| | | | | | |
4  * | |_| | _ < / ___ \| | | | |__| |_| |
5  * |____/|_| \_\/_/ \_\_| |_|\____\___/
6  * research group
7  * dramco.be/
8  *
9  * KU Leuven - Technology Campus Gent,
10  * Gebroeders De Smetstraat 1,
11  * B-9000 Gent, Belgium
12  *
13  * File: rn2483.c
14  * Created: 2018-01-18
15  * Author: Guus Leenders - Modified by Brecht Van Eeckhoudt
16  *
17  * Description: Interfacing with the RN2483 LoRa modem.
18  * Wraps commands in a more readable format. Handles serial
19  * command-response mechanism.
20  */
21 
22 #include <stdint.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <em_device.h>
27 #include <em_chip.h>
28 #include <em_cmu.h>
29 #include <em_gpio.h>
30 #include <em_usart.h>
31 #include <em_leuart.h>
32 
33 #include "lora.h" /* LoRa functionality */
34 #include "leuart.h" /* leuart functionality */
35 #include "rn2483.h" /* RN2483_xxxx */
36 
37 #include "delay.h" /* Delay functionality */
38 #include "pin_mapping.h" /* PORT and PIN definitions */
39 #include "util_string.h" /* Utility functionality regarding strings */
40 
41 
43 
44 static RN2483_Status_t RN2483_ProcessMacCommand(char * receiveBuffer, uint8_t bufferSize, bool secondResponse){
45  volatile bool dummy = false;
47  return (RN_TX_TIMEOUT);
48  }
49 
50  /* Read first response */
51  Leuart_ReadResponse(receiveBuffer, bufferSize);
52 
53  /* Analyze response */
54  if(StringStartsWith(receiveBuffer, "ok")){
55  if(secondResponse){
56  /* Wait for second response */
57  Leuart_WaitForResponse(receiveBuffer, bufferSize);
58  /* Read second response */
59  Leuart_ReadResponse(receiveBuffer, bufferSize);
60  /* Analyze response */
61  if(StringStartsWith(receiveBuffer, "accepted")){
62  return (JOIN_ACCEPTED);
63  } else if(StringStartsWith(receiveBuffer, "denied")){
64  return (JOIN_DENIED);
65  } else if(StringStartsWith(receiveBuffer, "mac_tx_ok")){
66  return (MAC_TX_OK);
67  } else if(StringStartsWith(receiveBuffer, "mac_rx")){
68  // TODO: capture data
69  return (MAC_RX);
70  } else if(StringStartsWith(receiveBuffer, "mac_err")){
71  return (MAC_ERR);
72  } else if(StringStartsWith(receiveBuffer, "invalid_data_len")){
73  return (INVALID_DATA_LEN);
74  } else if(StringStartsWith(receiveBuffer, "radio_tx_ok")){
75  return (RADIO_TX_OK);
76  } else if(StringStartsWith(receiveBuffer, "radio_err")){
77  return (RADIO_ERR);
78  }
79  return (UNKOWN_ERR);
80  } else {
81  return (MAC_OK);
82  }
83  }
84  else if(StringStartsWith(receiveBuffer, "invalid_param")){
85  return (INVALID_PARAM);
86  } else if(StringStartsWith(receiveBuffer, "not_joined")){
87  return (NOT_JOINED);
88  } else if(StringStartsWith(receiveBuffer, "no_free_ch")){
89  return (NO_FREE_CH);
90  } else if(StringStartsWith(receiveBuffer, "silent")){
91  return (SILENT);
92  } else if(StringStartsWith(receiveBuffer, "frame_counter_err_rejoin_needed")){
94  } else if(StringStartsWith(receiveBuffer, "busy")){
95  return (BUSY);
96  } else if(StringStartsWith(receiveBuffer, "mac_paused")){
97  return (MAC_PAUSED);
98  } else if(StringStartsWith(receiveBuffer, "invalid_data_len")){
99  return (INVALID_DATA_LEN);
100  }
101 
102  return (DATA_RETURNED);
103 }
104 
105 static RN2483_Status_t RN2483_ProcessSleepCommand(char * receiveBuffer, uint8_t bufferSize, volatile bool * wakeUp){
106  if(Leuart_SendCommand(commandBuffer, strlen(commandBuffer), wakeUp) == TX_TIMEOUT){
107  return (RN_TX_TIMEOUT);
108  }
109 
110  /* Read first response */
111  Leuart_ReadResponse(receiveBuffer, bufferSize);
112 
113  /* Analyze response */
114  if(StringStartsWith(receiveBuffer, "ok")){
115  return (MAC_OK);
116  } else if(StringStartsWith(receiveBuffer, "invalid_param")){
117  return (INVALID_PARAM);
118  }
119 
120  return (UNKOWN_ERR);
121 }
122 
123 void RN2483_Init(void){ /* Setup with autobaud */
124  GPIO_PinModeSet(RN2483_TX_PORT, RN2483_TX_PIN, gpioModePushPull, 1);
125  delay(100);
126  GPIO_PinModeSet(RN2483_RESET_PORT, RN2483_RESET_PIN, gpioModePushPull, 1);
127  delay(50);
128  GPIO_PinModeSet(RN2483_RESET_PORT, RN2483_RESET_PIN, gpioModePushPull, 0);
129  delay(50);
130  GPIO_PinModeSet(RN2483_RESET_PORT, RN2483_RESET_PIN, gpioModePushPull, 1);
131  delay(350);
132 
134 
135  Leuart_Init();
136 }
137 
138 RN2483_Status_t RN2483_MacReset(char * receiveBuffer, uint8_t bufferSize){
139  sprintf(commandBuffer, "mac reset 868\r\n");
140  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
141 }
142 
144  sprintf(commandBuffer, "mac get deveui\r\n");
145  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
146 }
147 
149  sprintf(commandBuffer, "sys get ver\r\n");
150  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
151 }
152 
154  sprintf(commandBuffer, "sys get appeui\r\n");
155  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
156 }
157 
158 RN2483_Status_t RN2483_SetDeviceEUI(char * eui, char * receiveBuffer, uint8_t bufferSize){
159  sprintf(commandBuffer, "mac set deveui %s\r\n", eui);
160  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
161 }
162 
163 RN2483_Status_t RN2483_SetApplicationEUI(char * eui, char * receiveBuffer, uint8_t bufferSize){
164  sprintf(commandBuffer, "mac set appeui %s\r\n", eui);
165  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
166 }
167 
168 RN2483_Status_t RN2483_SetApplicationKey(char * key, char * receiveBuffer, uint8_t bufferSize){
169  sprintf(commandBuffer, "mac set appkey %s\r\n", key);
170  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
171 }
172 
173 RN2483_Status_t RN2483_SetApplicationSessionKey(char * key, char * receiveBuffer, uint8_t bufferSize){
174  sprintf(commandBuffer, "mac set appskey %s\r\n", key);
175  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
176 }
177 
178 RN2483_Status_t RN2483_SetNetworkSessionKey(char * key, char * receiveBuffer, uint8_t bufferSize){
179  sprintf(commandBuffer, "mac set nwkskey %s\r\n", key);
180  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
181 }
182 
183 RN2483_Status_t RN2483_SetDeviceAddress(char * address, char * receiveBuffer, uint8_t bufferSize){
184  sprintf(commandBuffer, "mac set devaddr %s\r\n", address);
185  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
186 }
187 
188 RN2483_Status_t RN2483_SetOutputPower(uint8_t pwr, char * receiveBuffer, uint8_t bufferSize){
189  sprintf(commandBuffer, "mac set pwridx %i\r\n", pwr);
190  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
191 }
192 
194  sprintf(commandBuffer, "mac set adr off\r\n");
195  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
196 }
197 
199  sprintf(commandBuffer, "mac set ar off\r\n");
200  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
201 }
202 
203 RN2483_Status_t RN2483_SetDataRate(uint8_t dr, char * receiveBuffer, uint8_t bufferSize){
204  sprintf(commandBuffer, "mac set dr %i\r\n", dr);
205  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
206 }
207 
208 RN2483_Status_t RN2483_GetDataRate(int8_t *dr, char * receiveBuffer, uint8_t bufferSize){
209  sprintf(commandBuffer, "mac get dr\r\n");
210  RN2483_Status_t status = RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false);
211  if(status != DATA_RETURNED){
212  return (status);
213  }
214 
215  /* Convert ascii to unsigned */
216  *dr = receiveBuffer[0] - '0';
217  /* Final data check */
218  if(*dr >= 0 && *dr <= 7){
219  return (MAC_OK);
220  }
221  else{
222  return (MAC_ERR);
223  }
224 }
225 
227  sprintf(commandBuffer, "mac set adr on\r\n");
228  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
229 }
230 
231 RN2483_Status_t RN2483_SetBatteryLevel(uint8_t battery, char * receiveBuffer, uint8_t bufferSize){
232  sprintf(commandBuffer, "mac set bat %i\r\n", battery);
233  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
234 }
235 
236 RN2483_Status_t RN2483_JoinOTAA(char * receiveBuffer, uint8_t bufferSize){
237  sprintf(commandBuffer, "mac join otaa\r\n");
238  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, true));
239 }
240 
241 RN2483_Status_t RN2483_JoinABP(char * receiveBuffer, uint8_t bufferSize){
242  sprintf(commandBuffer, "mac join abp\r\n");
243  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, true));
244 }
245 
246 static RN2483_Status_t RN2483_SetDefaultOperation(LoRaSettings_t settings, char * receiveBuffer, uint8_t bufferSize){
247  RN2483_Status_t status = RN2483_SetOutputPower(RN2483_POWER_14DBM, receiveBuffer, bufferSize);
248  if(status != MAC_OK){
249  return (status);
250  }
251  status = RN2483_DisableAutomaticReplies(receiveBuffer, bufferSize);
252  if(status != MAC_OK){
253  return (status);
254  }
255  status = RN2483_DisableAdaptiveDataRate(receiveBuffer, bufferSize);
256  if(status != MAC_OK){
257  return (status);
258  }
259  status = RN2483_SetDataRate(settings.dataRate, receiveBuffer, bufferSize);
260  if(status != MAC_OK){
261  return (status);
262  }
263  status = RN2483_EnableAdaptiveDataRate(receiveBuffer, bufferSize);
264  if(status != MAC_OK){
265  return (status);
266  }
267  return (RN2483_SetBatteryLevel(254, receiveBuffer, bufferSize));
268 }
269 
270 RN2483_Status_t RN2483_Setup(LoRaSettings_t settings, char * receiveBuffer, uint8_t bufferSize){
271  if(settings.activationMethod == OTAA){
272  return (RN2483_SetupOTAA(settings, receiveBuffer, bufferSize));
273  }else{
274  return (RN2483_SetupABP(settings, receiveBuffer, bufferSize));
275  }
276 }
277 
278 RN2483_Status_t RN2483_SetupOTAA(LoRaSettings_t settings, char * receiveBuffer, uint8_t bufferSize){
279  RN2483_Status_t status = RN2483_MacReset(receiveBuffer, bufferSize);
280  if(status != MAC_OK){
281  return (status);
282  }
283  if(settings.deviceEUI == NULL){
284  status = RN2483_GetHardwareEUI(receiveBuffer, bufferSize);
285  if(status != DATA_RETURNED){
286  return (status);
287  }
288  char address[16];
289  sprintf(address, "%s", receiveBuffer);
290  status = RN2483_SetDeviceEUI(address, receiveBuffer, bufferSize);
291  if(status != MAC_OK){
292  return (status);
293  }
294  }else{
295  status = RN2483_SetDeviceEUI(settings.deviceEUI, receiveBuffer, bufferSize);
296  if(status != MAC_OK){
297  return (status);
298  }
299  }
300  status = RN2483_SetApplicationEUI(settings.applicationEUI, receiveBuffer, bufferSize);
301  if(status != MAC_OK){
302  return (status);
303  }
304  status = RN2483_SetApplicationKey(settings.applicationKey, receiveBuffer, bufferSize);
305  if(status != MAC_OK){
306  return (status);
307  }
308  status = RN2483_SetDefaultOperation(settings, receiveBuffer, bufferSize);
309  if(status != MAC_OK){
310  return (status);
311  }
312  return (RN2483_JoinOTAA(receiveBuffer, bufferSize));
313 }
314 
315 RN2483_Status_t RN2483_SetupABP(LoRaSettings_t settings, char * receiveBuffer, uint8_t bufferSize){
316  RN2483_Status_t status = RN2483_MacReset(receiveBuffer, bufferSize);
317  if(status != MAC_OK){
318  return (status);
319  }
320  status = RN2483_SetDeviceAddress(settings.deviceAddress, receiveBuffer, bufferSize);
321  if(status != MAC_OK){
322  return (status);
323  }
324  status = RN2483_SetNetworkSessionKey(settings.networkSessionKey, receiveBuffer, bufferSize);
325  if(status != MAC_OK){
326  return (status);
327  }
328  status = RN2483_SetApplicationSessionKey(settings.applicationSessionKey, receiveBuffer, bufferSize);
329  if(status != MAC_OK){
330  return (status);
331  }
332  status = RN2483_SetDefaultOperation(settings, receiveBuffer, bufferSize);
333  if(status != MAC_OK){
334  return (status);
335  }
336  return (RN2483_JoinABP(receiveBuffer, bufferSize));
337 }
338 
339 RN2483_Status_t RN2483_TransmitUnconfirmed(uint8_t * data, uint8_t payloadSize, char * receiveBuffer, uint8_t bufferSize){
340  char * encodedPayload;
341  if(!HexToString(data, payloadSize, &encodedPayload )){
342  return (MAC_ERR);
343  }
344  //StringToHexString(data, payloadSize/2, &decodedPayload);
345 
346  // Sprintf caused a problem where it would overwrite data when using long LoRaWAN packets because the malloc statement
347  // in HexToString would create a too small buffer (according to RN2483_COMMANDBUFFER_SIZE, was 80 and increased to 160)
348  // compared to the data of the converted LoRaWAN packet.
349  sprintf(commandBuffer, "mac tx uncnf 1 %s\r\n", encodedPayload);
350  free(encodedPayload);
351  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, true));
352 }
353 
354 RN2483_Status_t RN2483_TransmitConfirmed(uint8_t * data, uint8_t payloadSize, char * receiveBuffer, uint8_t bufferSize){
355  char * encodedPayload;
356  if(!HexToString(data, payloadSize, &encodedPayload )){
357  return (MAC_ERR);
358  }
359  sprintf(commandBuffer, "mac tx cnf 1 %s\r\n", encodedPayload);
360  free(encodedPayload);
361  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, true));
362 }
363 
364 RN2483_Status_t RN2483_SaveMac(char * receiveBuffer, uint8_t bufferSize){
365  sprintf(commandBuffer, "mac save\r\n");
366  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
367 }
368 
369 RN2483_Status_t RN2483_ResumeMac(char * receiveBuffer, uint8_t bufferSize){
370  sprintf(commandBuffer, "mac resume\r\n");
371  return (RN2483_ProcessMacCommand(receiveBuffer, bufferSize, false));
372 }
373 
374 RN2483_Status_t RN2483_Sleep(uint32_t sleepTime, volatile bool * wakeUp, char * receiveBuffer, uint8_t bufferSize){
375  sprintf(commandBuffer, "sys sleep %lu\r\n", (unsigned long) sleepTime);
376  return (RN2483_ProcessSleepCommand(receiveBuffer, bufferSize, wakeUp));
377 }
378 
379 RN2483_Status_t RN2483_Wake(char * receiveBuffer, uint8_t bufferSize){
380  Leuart_Reinit();
381 
382  /* Capture response "ok" from previous sleep command */
384  /* Read second response */
385  Leuart_ReadResponse(receiveBuffer, bufferSize);
386  if(StringStartsWith(receiveBuffer, "ok")){
387  return (MAC_OK);
388  }
389 
390  return (MAC_ERR);
391 }
static RN2483_Status_t RN2483_ProcessMacCommand(char *receiveBuffer, uint8_t bufferSize, bool secondResponse)
Definition: rn2483.c:44
char applicationKey[32+1]
Definition: lora.h:59
Definition: rn2483.h:40
RN2483_Status_t RN2483_SetDeviceEUI(char *eui, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:158
void Leuart_Reinit(void)
Definition: leuart.c:323
char deviceAddress[8+1]
Definition: lora.h:60
RN2483_Status_t RN2483_GetApplicationEUI(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:153
#define RN2483_RESET_PORT
Definition: pin_mapping.h:121
char networkSessionKey[32+1]
Definition: lora.h:61
char applicationEUI[16+1]
Definition: lora.h:58
RN2483_Status_t RN2483_Wake(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:379
Leuart_Status_t Leuart_SendCommand(char *cb, uint8_t cbl, volatile bool *wakeUp)
Definition: leuart.c:392
Definition: rn2483.h:46
bool HexToString(uint8_t *bin, uint8_t binsz, char **result)
Definition: util_string.c:37
#define RN2483_RESET_PIN
Definition: pin_mapping.h:122
void Leuart_Init(void)
Definition: leuart.c:306
RN2483_Status_t RN2483_EnableAdaptiveDataRate(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:226
Definition: rn2483.h:42
MeasurementData_t data
Definition: main.c:189
Leuart_Status_t Leuart_WaitForResponse()
Definition: leuart.c:430
#define RN2483_TX_PIN
Definition: pin_mapping.h:118
RN2483_Status_t RN2483_SetApplicationKey(char *key, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:168
RN2483_Status_t RN2483_DisableAutomaticReplies(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:198
RN2483_Status_t RN2483_GetDataRate(int8_t *dr, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:208
Definition: rn2483.h:47
bool StringStartsWith(char *str, char *seq)
Definition: util_string.c:27
RN2483_Status_t RN2483_SetOutputPower(uint8_t pwr, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:188
#define RN2483_TX_PORT
Definition: pin_mapping.h:117
#define RN2483_POWER_14DBM
Definition: rn2483.h:27
RN2483_Status_t RN2483_TransmitConfirmed(uint8_t *data, uint8_t payloadSize, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:354
char deviceEUI[16+1]
Definition: lora.h:57
static RN2483_Status_t RN2483_ProcessSleepCommand(char *receiveBuffer, uint8_t bufferSize, volatile bool *wakeUp)
Definition: rn2483.c:105
RN2483_Status_t RN2483_Setup(LoRaSettings_t settings, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:270
RN2483_Status_t RN2483_JoinOTAA(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:236
RN2483_Status_t RN2483_SaveMac(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:364
void RN2483_Init(void)
Definition: rn2483.c:123
RN2483_Status_t RN2483_SetApplicationEUI(char *eui, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:163
RN2483_Status_t RN2483_SetDataRate(uint8_t dr, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:203
RN2483_Status_t RN2483_SetBatteryLevel(uint8_t battery, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:231
RN2483_Status_t RN2483_TransmitUnconfirmed(uint8_t *data, uint8_t payloadSize, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:339
The pin definitions for the regular and custom Happy Gecko board.
Definition: lora.h:40
Delay functionality.
RN2483_Status_t RN2483_ResumeMac(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:369
char commandBuffer[160]
Definition: rn2483.c:42
void delay(uint32_t msDelay)
Wait for a certain amount of milliseconds in EM2/3.
Definition: delay.c:124
static RN2483_Status_t RN2483_SetDefaultOperation(LoRaSettings_t settings, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:246
RN2483_Status_t RN2483_SetDeviceAddress(char *address, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:183
enum rn2483_statuses RN2483_Status_t
LoRaActivationMethod_t activationMethod
Definition: lora.h:55
RN2483_Status_t RN2483_SetupOTAA(LoRaSettings_t settings, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:278
#define RN2483_COMMANDBUFFER_SIZE
Definition: rn2483.h:26
LoRaDataRate_t dataRate
Definition: lora.h:56
RN2483_Status_t RN2483_GetSystemVersion(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:148
RN2483_Status_t RN2483_GetHardwareEUI(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:143
RN2483_Status_t RN2483_MacReset(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:138
char applicationSessionKey[32+1]
Definition: lora.h:62
RN2483_Status_t RN2483_DisableAdaptiveDataRate(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:193
Definition: rn2483.h:34
RN2483_Status_t RN2483_SetApplicationSessionKey(char *key, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:173
RN2483_Status_t RN2483_SetNetworkSessionKey(char *key, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:178
RN2483_Status_t RN2483_SetupABP(LoRaSettings_t settings, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:315
RN2483_Status_t RN2483_Sleep(uint32_t sleepTime, volatile bool *wakeUp, char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:374
void Leuart_ReadResponse(char *buffer, uint8_t bufferLength)
Definition: leuart.c:351
char receiveBuffer[50]
Definition: leuart.c:78
RN2483_Status_t RN2483_JoinABP(char *receiveBuffer, uint8_t bufferSize)
Definition: rn2483.c:241