IoT-MBBR (masterthesis)
Masterthesis upgrading a Moving Bed BioReactor with extra sensors and cloud connectivity.
BG96_at_driver.c
Go to the documentation of this file.
1 /***************************************************************************//**
2  * @file BG96_at_driver.c
3  * @brief BG96 AT-command driver functionality.
4  * @version 1.0
5  * @author Brecht Van Eeckhoudt
6  *
7  * ******************************************************************************
8  *
9  * @section Versions
10  *
11  * @li v1.0: Basic functionality to send measurements to the cloud using NB-IoT
12  * without timeout functionality.
13  *
14  * ******************************************************************************
15  *
16  * @section License
17  *
18  * **Copyright (C) 2020 - Brecht Van Eeckhoudt**
19  *
20  * This program is free software: you can redistribute it and/or modify
21  * it under the terms of the **GNU General Public License** as published by
22  * the Free Software Foundation, either **version 3** of the License, or
23  * (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28  * GNU General Public License for more details.
29  *
30  * *A copy of the GNU General Public License can be found in the `LICENSE`
31  * file along with this source code.*
32  *
33  * @n
34  *
35  * Some methods use code obtained from examples from [Silicon Labs' GitHub](https://github.com/SiliconLabs/peripheral_examples).
36  * These sections are licensed under the Silabs License Agreement. See the file
37  * "Silabs_License_Agreement.txt" for details. Before using this software for
38  * any purpose, you must agree to the terms of that agreement.
39  *
40  ******************************************************************************/
41 
42 
43 #include <stdint.h> /* (u)intXX_t */
44 #include <stdbool.h> /* "bool", "true", "false" */
45 #include "em_cmu.h" /* Clock Management Unit */
46 #include "em_device.h" /* Include necessary MCU-specific header file */
47 #include "em_gpio.h" /* General Purpose IO */
48 
49 #include "BG96_at_driver.h" /* Corresponding header file */
50 #include "debug_dbprint.h" /* Enable or disable printing to UART */
51 #include "delay.h" /* Delay functionality */
52 #include "util_string.h" /* String functionality */
53 #include "datatypes.h" /* Definitions of the custom data-types */
54 #include "credentials.h" /* DEVICE_ID and DEVICE_TOKEN */
55 #include "pin_mapping.h" /* PORT and PIN definitions */
56 
57 
58 /* Local definitions */
59 #define PRINT_ID_TOKEN 0 /* 0 = don't print ID & Token, 1 = print ID & Token */
60 
61 
62 /* Local variables */
63 /* Convert ASCII to hex:
64  * => "-1" to get the correct length because the NULL termination character is at the end of the array
65  * => "*2" because one ASCII char becomes two HEX chars
66  * => "+1" to add the NULL termination character at the end
67  */
68 char DEVICE_ID_hex[2*(sizeof(DEVICE_ID)-1) +1];
69 char DEVICE_TOKEN_hex[2*(sizeof(DEVICE_TOKEN)-1) +1];
70 
71 
72 /* Local prototypes */
73 static bool transmissionBegin (bool continueCode);
74 static bool transmissionEnd (bool continueCode);
75 
76 
77 /**************************************************************************//**
78  * @brief
79  * Initialize the GPIO pins and UART0 module necessary to communicate with
80  * the BG96 module.
81  *****************************************************************************/
82 void initBG96 (void)
83 {
84  /* Convert ID & Token */
87 
88 #if PRINT_ID_TOKEN == 1 /* PRINT_ID_TOKEN */
89 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
90  dbprint("INFO: DEVICE_ID = ");
92  dbprint("INFO: DEVICE_ID_hex = ");
94  dbprintln("");
95  dbprint("INFO: DEVICE_TOKEN = ");
97  dbprint("INFO: DEVICE_TOKEN_hex = ");
99  dbprintln("");
100 #endif /* DEBUG_DBPRINT */
101 #endif /* PRINT_ID_TOKEN */
102 
103  /* Enable oscillator to GPIO*/
104  CMU_ClockEnable(cmuClock_GPIO, true);
105 
106  /* Initialize GPIO pin for PWR key */
107  /* In the case of gpioModePushPull, the last argument directly sets the pin state */
108  GPIO_PinModeSet(BG96_PWRKEY_PORT, BG96_PWRKEY_PIN, gpioModePushPull, 0);
109 
110  /*
111  * USART_INITASYNC_DEFAULT:
112  * config.enable = usartEnable // Specifies whether TX and/or RX is enabled when initialization is completed
113  * // (Enable RX/TX when initialization is complete).
114  * config.refFreq = 0 // USART/UART reference clock assumed when configuring baud rate setup
115  * // (0 = Use current configured reference clock for configuring baud rate).
116  * config.baudrate = 115200 // Desired baudrate (115200 bits/s).
117  * config.oversampling = usartOVS16 // Oversampling used (16x oversampling).
118  * config.databits = usartDatabits8 // Number of data bits in frame (8 data bits).
119  * config.parity = usartNoParity // Parity mode to use (no parity).
120  * config.stopbits = usartStopbits1 // Number of stop bits to use (1 stop bit).
121  * config.mvdis = false // Majority Vote Disable for 16x, 8x and 6x oversampling modes (Do not disable majority vote).
122  * config.prsRxEnable = false // Enable USART Rx via PRS (Not USART PRS input mode).
123  * config.prsRxCh = 0 // Select PRS channel for USART Rx. (Only valid if prsRxEnable is true - PRS channel 0).
124  * config.autoCsEnable = false // Auto CS enabling (Auto CS functionality enable/disable switch - disabled).
125  */
126 
127  USART_InitAsync_TypeDef config = USART_INITASYNC_DEFAULT;
128 
129  /* Enable oscillator to USARTx modules */
130  if (BG96_UART == USART0) CMU_ClockEnable(cmuClock_USART0, true);
131  else if (BG96_UART == USART1) CMU_ClockEnable(cmuClock_USART1, true);
132 
133  /* Set pin modes for UART TX and RX pins */
134  if (BG96_UART == USART0)
135  {
136  switch (BG96_UART_LOC)
137  {
138  case 0:
139  GPIO_PinModeSet(gpioPortE, 11, gpioModeInput, 0); /* RX */
140  GPIO_PinModeSet(gpioPortE, 10, gpioModePushPull, 1); /* TX */
141  break;
142  case 2:
143  GPIO_PinModeSet(gpioPortC, 10, gpioModeInput, 0); /* RX */
144  /* No TX pin in this mode */
145  break;
146  case 3:
147  GPIO_PinModeSet(gpioPortE, 12, gpioModeInput, 0); /* RX */
148  GPIO_PinModeSet(gpioPortE, 13, gpioModePushPull, 1); /* TX */
149  break;
150  case 4:
151  GPIO_PinModeSet(gpioPortB, 8, gpioModeInput, 0); /* RX */
152  GPIO_PinModeSet(gpioPortB, 7, gpioModePushPull, 1); /* TX */
153  break;
154  case 5:
155  case 6:
156  GPIO_PinModeSet(gpioPortC, 1, gpioModeInput, 0); /* RX */
157  GPIO_PinModeSet(gpioPortC, 0, gpioModePushPull, 1); /* TX */
158  break;
159  /* default: */
160  /* No default */
161  }
162  }
163  else if (BG96_UART == USART1)
164  {
165  switch (BG96_UART_LOC)
166  {
167  case 0:
168  GPIO_PinModeSet(gpioPortC, 1, gpioModeInput, 0); /* RX */
169  GPIO_PinModeSet(gpioPortC, 0, gpioModePushPull, 1); /* TX */
170  break;
171  case 2:
172  case 3:
173  GPIO_PinModeSet(gpioPortD, 6, gpioModeInput, 0); /* RX */
174  GPIO_PinModeSet(gpioPortD, 7, gpioModePushPull, 1); /* TX */
175  break;
176  case 4:
177  GPIO_PinModeSet(gpioPortA, 0, gpioModeInput, 0); /* RX */
178  GPIO_PinModeSet(gpioPortF, 2, gpioModePushPull, 1); /* TX */
179  break;
180  case 5:
181  GPIO_PinModeSet(gpioPortC, 2, gpioModeInput, 0); /* RX */
182  GPIO_PinModeSet(gpioPortC, 1, gpioModePushPull, 1); /* TX */
183  break;
184  /* default: */
185  /* No default */
186  }
187  }
188 
189  /* Initialize USART asynchronous mode */
190  USART_InitAsync(BG96_UART, &config);
191 
192  /* Route pins */
193  switch (BG96_UART_LOC)
194  {
195  case 0:
196  BG96_UART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC0;
197  break;
198  case 1:
199  BG96_UART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC1;
200  break;
201  case 2:
202  BG96_UART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC2;
203  break;
204  case 3:
205  BG96_UART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC3;
206  break;
207  case 4:
208  BG96_UART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC4;
209  break;
210  case 5:
211  BG96_UART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC5;
212  break;
213  case 6:
214  BG96_UART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_LOC6;
215  break;
216  default:
217  BG96_UART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_LOCATION_DEFAULT;
218  }
219 
220 }
221 
222 
223 /**************************************************************************//**
224  * @brief
225  * Send measurements to the cloud using NB-IoT.
226  *
227  * @param[in] data
228  * The measurements to send
229  *****************************************************************************/
231 {
232  /* Begin transmission */
233  bool continueCode = transmissionBegin(true);
234 
235  if (continueCode)
236  {
237 
238 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
239  dbprintln("INFO: Sending the following values to the cloud:");
240  dbprint(" t1 = ");
241  dbprintInt(data->t1);
242  dbprint(", t2 = ");
243  dbprintInt(data->t2);
244  dbprint(", p = ");
245  dbprintInt(data->p);
246  dbprint(", n1 = ");
247  dbprintInt(data->n1);
248  dbprint(", n2 = ");
249  dbprintInt(data->n2);
250  dbprint(", r = ");
251  dbprintInt(data->r);
252  dbprint(", c = ");
253  dbprintlnInt(data->c);
254 #endif /* DEBUG_DBPRINT */
255 
256  /* Convert values */
257  char t1_hex[9]; // TODO: Use less chars here because we use uint16_t (check if values aren't bigger than 0xFFFF)
258  uint32_to_charHex(data->t1, t1_hex); // TODO: Make sure we can send negative values!
259  char t2_hex[9];
260  uint32_to_charHex(data->t2, t2_hex); // TODO: Make sure we can send negative values!
261  char p_hex[9];
262  uint32_to_charHex(data->p, p_hex);
263  char n1_hex[9];
264  uint32_to_charHex(data->n1, n1_hex);
265  char n2_hex[9];
266  uint32_to_charHex(data->n2, n2_hex);
267  char r_hex[9];
268  uint32_to_charHex(data->r, r_hex);
269  char c_hex[9];
270  uint32_to_charHex(data->c, c_hex);
271 
272  /*
273  * http://cbor.me/
274  *
275  * Diagnostic:
276  * {
277  * "t1": 2345,
278  * "t2": 2345,
279  * "p": 2345,
280  * "n1": 2345,
281  * "n2": 2345,
282  * "r": 2345,
283  * "c": 2345
284  * }
285  *
286  * CBOR:
287  * A7 # map(7)
288  * 62 # text(2)
289  * 7431 # "t1"
290  * 19 0929 # unsigned(2345) (19 ~ uint16_t)
291  * 62 # text(2)
292  * 7432 # "t2"
293  * 19 0929 # unsigned(2345)
294  * 61 # text(1)
295  * 70 # "p"
296  * 19 0929 # unsigned(2345)
297  * 62 # text(2)
298  * 6E31 # "n1"
299  * 19 0929 # unsigned(2345)
300  * 62 # text(2)
301  * 6E32 # "n2"
302  * 19 0929 # unsigned(2345)
303  * 61 # text(1)
304  * 72 # "r"
305  * 19 0929 # unsigned(2345)
306  * 61 # text(1)
307  * 63 # "c"
308  * 19 0929 # unsigned(2345)
309  */
310 
311  /* Send commands */
312  sendCMD("AT+QISENDEX=0,\"");
314  sendCMD("0a"); /* \n */
316  sendCMD("0a"); /* \n */
317  sendCMD("a762743119"); /* 0xa6 = map(7), 0x62 = text(2), 0x7431 = "t1", 0x19 = uint16_t */
318  sendCMD(t1_hex);
319  sendCMD("62743219"); /* 0x62 = text(2), 0x7432 = "t2", 0x19 = uint16_t */
320  sendCMD(t2_hex);
321  sendCMD("617019"); /* 0x61 = text(1), 0x70 = "p", 0x19 = uint16_t */
322  sendCMD(p_hex);
323  sendCMD("626e3119"); /* 0x62 = text(2), 0x6e31 = "n1", 0x19 = uint16_t */
324  sendCMD(n1_hex);
325  sendCMD("626e3219"); /* 0x62 = text(2), 0x6e32 = "n2", 0x19 = uint16_t */
326  sendCMD(n2_hex);
327  sendCMD("617219"); /* 0x61 = text(1), 0x72 = "r", 0x19 = uint16_t */
328  sendCMD(r_hex);
329  sendCMD("616319"); /* 0x61 = text(1), 0x63 = "c", 0x19 = uint16_t */
330  sendCMD(c_hex);
331  sendCMD("\"\n\r");
332 
333  /* Wait for the correct response */
334  continueCode = waitForResponse("SEND OK", 5);
335  }
336 
337  /* End transmission */
338  continueCode = transmissionEnd(continueCode);
339 }
340 
341 
342 /**************************************************************************//**
343  * @brief
344  * Send status to the cloud using NB-IoT.
345  *
346  * @param[in] status
347  * The status value to send
348  *****************************************************************************/
349 void sendStatus (int8_t status)
350 {
351  /* Begin transmission */
352  bool continueCode = transmissionBegin(true);
353 
354  if (continueCode)
355  {
356 
357 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
358  dbprintln("INFO: Sending status ");
359  dbprintInt(status);
360  dbprintln(" to the cloud.");
361 #endif /* DEBUG_DBPRINT */
362 
363  /* Convert values */
364  char s_hex[9]; // TODO: Use less chars here because we use uint16_t (check if values aren't bigger than 0xFFFF)
365  uint32_to_charHex(status, s_hex); // TODO: Make sure we can send negative values!
366 
367  /*
368  * http://cbor.me/
369  *
370  * Diagnostic:
371  * {
372  * "s": 2345
373  * }
374  *
375  * CBOR:
376  * A1 # map(1)
377  * 61 # text(1)
378  * 73 # "s"
379  * 19 0929 # unsigned(2345) (19 ~ uint16_t)
380  */
381 
382  /* Send commands */
383  sendCMD("AT+QISENDEX=0,\"");
385  sendCMD("0a"); /* \n */
387  sendCMD("0a"); /* \n */
388  sendCMD("a1617319"); /* 0xa1 = map(1), 0x61 = text(1), 0x73 = "s", 0x19 = uint16_t */
389  sendCMD(s_hex);
390  sendCMD("\"\n\r");
391 
392  /* Wait for the correct response */
393  continueCode = waitForResponse("SEND OK", 5);
394  }
395 
396  /* End transmission */
397  continueCode = transmissionEnd(continueCode);
398 }
399 
400 
401 /**************************************************************************//**
402  * @brief
403  * Send current pulses to the cloud using NB-IoT.
404  *
405  * @param[in] number
406  * @li `0` - PULSE0 selected.
407  * @li `1` - PULSE0 selected.
408  *
409  * @param[in] pulse
410  * The pulse value to send
411  *****************************************************************************/
412 void sendPulse (uint8_t number, uint8_t pulse)
413 {
414  /* Begin transmission */
415  bool continueCode = transmissionBegin(true);
416 
417  if (continueCode)
418  {
419 
420 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
421  dbprintln("INFO: Sending pulse(s) [");
422  dbprintInt(pulse);
423  dbprintln("] to the cloud.");
424 #endif /* DEBUG_DBPRINT */
425 
426  /* Convert values */
427  char pulse_hex[9]; // TODO: Use less chars here because we use uint16_t (check if values aren't bigger than 0xFFFF)
428  uint32_to_charHex(pulse, pulse_hex);
429 
430  /*
431  * http://cbor.me/
432  *
433  * Diagnostic:
434  * {
435  * "p1": 2345
436  * }
437  *
438  * CBOR:
439  * A1 # map(1)
440  * 62 # text(2)
441  * 7031 # "p1"
442  * 19 0929 # unsigned(2345) (19 ~ uint16_t)
443  */
444 
445  /* Send commands */
446  sendCMD("AT+QISENDEX=0,\"");
448  sendCMD("0a"); /* \n */
450  sendCMD("0a"); /* \n */
451  if (number == 0) sendCMD("a162703119"); /* 0xa1 = map(1), 0x62 = text(2), 0x7031 = "p1", 0x19 = uint16_t */
452  else if (number == 1) sendCMD("a162703219"); /* 0xa1 = map(1), 0x62 = text(2), 0x7032 = "p2", 0x19 = uint16_t */
453  sendCMD(pulse_hex);
454  sendCMD("\"\n\r");
455 
456  /* Wait for the correct response */
457  continueCode = waitForResponse("SEND OK", 5);
458  }
459 
460  /* End transmission */
461  continueCode = transmissionEnd(continueCode);
462 }
463 
464 
465 /**************************************************************************//**
466  * @brief
467  * Code for the start of a NB-IoT transmission.
468  *
469  * @note
470  * This is a static method because it's only internally used in this file
471  * and called by other methods if necessary.
472  *
473  * @param[in] continueCode
474  * Functionality to skip code if previous code failed.
475  *
476  * @return
477  * If the code finished okay/failed.
478  *****************************************************************************/
479 static bool transmissionBegin (bool continueCode)
480 {
481 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
482  dbinfo("Powering on BG96");
483 #endif /* DEBUG_DBPRINT */
484 
485  powerBG96(); /* Power up BG96 */
486  continueCode = waitForResponse("APP RDY", 5); /* Wait for the correct response */
487 
488  sleep(8); // TODO: Wait some time before activating PDP?
489 
490  if (continueCode)
491  {
492 
493 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
494  dbinfo("Sending Activate PDP command...");
495 #endif /* DEBUG_DBPRINT */
496 
497  sendCMD("AT+QIACT=1\r");
498  continueCode = waitForResponse("OK", 5); /* Wait for the correct response */
499 
500  while (!continueCode) // TODO: update timeout functionality
501  {
502  sleep(2); /* Sleep for 2s */
503  sendCMD("AT+QIACT=1\r");
504  continueCode = waitForResponse("OK", 5); /* Wait for the correct response */
505  }
506  }
507 
508 
509  if (continueCode)
510  {
511 
512 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
513  dbinfo("Sending Create UDP command...");
514 #endif /* DEBUG_DBPRINT */
515 
516  sendCMD("AT+QIOPEN=1,0,\"UDP\",\"40.68.172.187\",8891\r"); // BEFORE: api.allthingstalk.io
517  continueCode = waitForResponse("OK", 5); /* Wait for the correct response */
518  continueCode = waitForResponse("+QIOPEN: 0,0", 5); /* Wait for the correct response */
519  }
520 
521  return (continueCode);
522 }
523 
524 
525 /**************************************************************************//**
526  * @brief
527  * Code for the end of a NB-IoT transmission.
528  *
529  * @note
530  * This is a static method because it's only internally used in this file
531  * and called by other methods if necessary.
532  *
533  * @param[in] continueCode
534  * Functionality to skip code if previous code failed.
535  *
536  * @return
537  * If the code finished okay/failed.
538  *****************************************************************************/
539 static bool transmissionEnd (bool continueCode)
540 {
541 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
542  dbinfo("Sending Deactivate PDP command...");
543 #endif /* DEBUG_DBPRINT */
544 
545  sendCMD("AT+QIDEACT=1\r");
546  continueCode = waitForResponse("OK", 5); /* Wait for the correct response */
547 
548  if (continueCode)
549  {
550 
551 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
552  dbinfo("Sending Power down command...");
553 #endif /* DEBUG_DBPRINT */
554 
555  sendCMD("AT+QPOWD\r");
556  continueCode = waitForResponse("OK", 5); /* Wait for the correct response */
557  continueCode = waitForResponse("POWERED DOWN", 5); /* Wait for the correct response */
558  }
559  else
560  {
561 
562 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
563  dbwarn("Powering down BG96 using hardware...");
564 #endif /* DEBUG_DBPRINT */
565 
566  powerBG96();
567  }
568 
569  sleep(2); // TODO: Wait less
570 
571  return (continueCode);
572 }
573 
574 
575 /**************************************************************************//**
576  * @brief
577  * Method to enable the `power key` for 100ms to enable/disable the module.
578  *****************************************************************************/
579 void powerBG96 (void)
580 {
581  /* Set PWK high for 100ms */
582  GPIO_PinOutSet(BG96_PWRKEY_PORT, BG96_PWRKEY_PIN);
583  delay(100);
584  GPIO_PinOutClear(BG96_PWRKEY_PORT, BG96_PWRKEY_PIN);
585 }
586 
587 
588 /**************************************************************************//**
589  * @brief
590  * Disable echo.
591  *****************************************************************************/
592 void disableEcho (void)
593 {
594 
595 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
596  dbinfo("Sending Disable Echo command...");
597 #endif /* DEBUG_DBPRINT */
598 
599  bool continueCode = true;
600 
601  sendCMD("ATE0\r");
602 
603  while (!continueCode) // TODO: update this code with timeout functionality?
604  {
605  sleep(2);
606  sendCMD("ATE0\r");
607  continueCode = waitForResponse("OK", 5); /* Wait for the correct response */
608  }
609 }
610 
611 
612 /**************************************************************************//**
613  * @brief
614  * Print a string (char array) to USARTx.
615  *
616  * @note
617  * If the input is not a string (ex.: `"Hello world!"`) but a char array,
618  * the input message (array) needs to end with NULL (`"\0"`)!
619  *
620  * @param[in] message
621  * The string to print to USARTx.
622  *****************************************************************************/
623 void sendCMD (char *message)
624 {
625  /* "message[i] != 0" makes "uint32_t length = strlen(message)"
626  * not necessary (given string MUST be terminated by NULL for this to work) */
627  for (uint32_t i = 0; message[i] != 0; i++)
628  {
629  USART_Tx(BG96_UART, message[i]);
630  }
631 }
632 
633 
634 /**************************************************************************//**
635  * @brief
636  * Read a string (char array) from USARTx.
637  *
638  * @note
639  * The reading stops when a `"LF"` (Line Feed) character
640  * is received or the maximum length (`UART_BUFFER_SIZE`) is reached.
641  *
642  * @param[in] buf
643  * The buffer to put the resulting string in.@n
644  * **This needs to have a length of `UART_BUFFER_SIZE` for the function
645  * to work properly: `char buf[UART_BUFFER_SIZE];`!**
646  *****************************************************************************/
647 void readResponse (char *buf)
648 {
649  for (uint32_t i = 0; i < UART_BUFFER_SIZE - 1 ; i++ )
650  {
651  char localBuffer = USART_Rx(BG96_UART);
652 
653  /* Check if a LF character is received */
654  if (localBuffer == '\n')
655  {
656  /* End with a null termination character */
657  buf[i] = '\0';
658  break;
659  }
660  else
661  {
662  buf[i] = localBuffer;
663  }
664  }
665 }
666 
667 
668 /**************************************************************************//**
669  * @brief
670  * Wait for the correct response using sleep/timeout functionality.
671  *
672  * @param[in] response
673  * The correct response to look for.
674  *
675  * @param[in] timeout
676  * The timeout value.
677  *
678  * @return
679  * @li `true` - Module responded correctly before timeout.
680  * @li `false` - The module timed out or gave only incorrect responses.
681  *****************************************************************************/
682 bool waitForResponse (char *response, uint8_t timeout)
683 {
684  uint8_t i = 0;
685 
686  char rxBuf[UART_BUFFER_SIZE];
687 
688  while (i < timeout) // TODO: update timeout functionality
689  {
690  readResponse(rxBuf);
691 
692  if (stringStartsWith((char *)rxBuf, response))
693  {
694 
695  // Printing breaks timing!
696 //#if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
697 // dbprint("INFO: > ");
698 // dbprint(response);
699 // dbprintln("");
700 //#endif /* DEBUG_DBPRINT */
701 
702  return(true);
703  }
704  else if (stringStartsWith((char *)rxBuf, "ERROR"))
705  {
706 
707  // Printing breaks timing!
708 //#if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
709 // dbcrit(" > ERROR");
710 //#endif /* DEBUG_DBPRINT */
711 
712  return(false);
713  }
714 
715  i++;
716  }
717 
718 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
719  dbprint_color("CRIT: Timeout reached while waiting on ", RED);
720  dbprint(response);
721  dbprint_color(" command", RED);
722  dbprintln("");
723 #endif /* DEBUG_DBPRINT */
724 
725  return(false);
726 }
void dbprint(char *message)
Print a string (char array) to USARTx.
Definition: dbprint.c:375
void dbprintlnInt(int32_t value)
Print a number in decimal notation to USARTx and go to the next line.
Definition: dbprint.c:776
void sendMeasurements(MeasurementData_t *data)
Send measurements to the cloud using NB-IoT.
Definition: dbprint.h:54
static bool transmissionEnd(bool continueCode)
Code for the end of a NB-IoT transmission.
#define DEVICE_TOKEN
Definition: credentials.h:17
void dbprintln(char *message)
Print a string (char array) to USARTx and go to the next line.
Definition: dbprint.c:397
void powerBG96(void)
Method to enable the power key for 100ms to enable/disable the module.
#define DEVICE_ID
Definition: credentials.h:16
signed char int8_t
Typedef defining 8 bit char type. The developer should modify this to suit the platform being deploye...
Definition: vl53l1_types.h:103
#define BG96_UART_LOC
Definition: pin_mapping.h:72
Definitions of the custom data-types used.
MeasurementData_t data
Definition: main.c:86
#define BG96_PWRKEY_PIN
Definition: pin_mapping.h:78
void dbwarn(char *message)
Print a warning string (char array) in yellow to USARTx and go to the next line.
Definition: dbprint.c:523
void sendStatus(int8_t status)
Send status to the cloud using NB-IoT.
String (char array) conversion functionality.
void dbinfo(char *message)
Print an info string (char array) to USARTx and go to the next line.
Definition: dbprint.c:505
#define UART_BUFFER_SIZE
void charASCII_to_charHex(char *inbuf, char *outbuf)
Convert an ASCII char array (string) to a hexadecimal char array.
Definition: util_string.c:63
bool stringStartsWith(char *inbuf, char *sequence)
Check if a given char array (string) starts with a given sequence.
Definition: util_string.c:203
#define BG96_UART
Definition: pin_mapping.h:71
void readResponse(char *buf)
Read a string (char array) from USARTx.
void sendCMD(char *message)
Print a string (char array) to USARTx.
char DEVICE_ID_hex[2 *(sizeof(DEVICE_ID) -1)+1]
bool waitForResponse(char *response, uint8_t timeout)
Wait for the correct response using sleep/timeout functionality.
Header file containing DEVICE_ID and DEVICE_ID.
#define BG96_PWRKEY_PORT
Definition: pin_mapping.h:77
The pin definitions for the custom board.
Delay functionality.
static bool transmissionBegin(bool continueCode)
Code for the start of a NB-IoT transmission.
Enable or disable printing to UART with dbprint.
void delay(uint32_t msDelay)
Wait for a certain amount of milliseconds in EM2/3.
Definition: delay.c:124
BG96 AT-command driver functionality.
void dbprintInt(int32_t value)
Print a number in decimal notation to USARTx.
Definition: dbprint.c:740
void initBG96(void)
Initialize the GPIO pins and UART0 module necessary to communicate with the BG96 module.
void sleep(uint32_t sSleep)
Sleep for a certain amount of seconds in EM2/3.
Definition: delay.c:293
char DEVICE_TOKEN_hex[2 *(sizeof(DEVICE_TOKEN) -1)+1]
static void uint32_to_charHex(char *buf, uint32_t value, bool spacing)
Convert a uint32_t value to a hexadecimal char array (string).
Definition: dbprint.c:1063
void sendPulse(uint8_t number, uint8_t pulse)
Send current pulses to the cloud using NB-IoT.
void dbprint_color(char *message, dbprint_color_t color)
Print a string (char array) to USARTx in a given color.
Definition: dbprint.c:423
unsigned char uint8_t
Typedef defining 8 bit unsigned char type. The developer should modify this to suit the platform bein...
Definition: vl53l1_types.h:98
void disableEcho(void)
Disable echo.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type. The developer should modify this to suit the platform bein...
Definition: vl53l1_types.h:78