Data Logger BLE Cellular Board
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1/** \file main.c
2 * \brief Nordic UART Bridge Service (NUS) sample
3 *
4 * \copyright (c) 2018 Nordic Semiconductor ASA
5 *
6 * \note SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
7 */
8
9#if CONFIG_SERIAL
10#include "uart_async_adapter.h"
11#include <zephyr/drivers/uart.h>
12#endif
13
14#include <zephyr/kernel.h>
15#include <zephyr/types.h>
16#include <zephyr/usb/usb_device.h>
17
18#include <soc.h>
19#include <zephyr/device.h>
20#include <zephyr/devicetree.h>
21
22#include <zephyr/bluetooth/bluetooth.h>
23#include <zephyr/bluetooth/gatt.h>
24#include <zephyr/bluetooth/hci.h>
25#include <zephyr/bluetooth/uuid.h>
26
27#include <bluetooth/services/nus.h>
28
29#include <dk_buttons_and_leds.h>
30
31#include <zephyr/settings/settings.h>
32
33#include <stdio.h>
34#include <zephyr/drivers/gpio.h>
35
37#include "mainpage.h"
39#include <zephyr/logging/log.h>
40
41#include "jfet_files/HDC2080.h"
42#include "ncs_version.h"
43// #include <date_time.h>
44#include <stdlib.h>
45#include <time.h>
46#include <zephyr/drivers/i2c.h>
47
48// #define NO_UART0 //!< define to disable UART0 for lower power consumption
49// #ifdef NO_UART0
50#include <zephyr/pm/device.h>
51// #endif
52
53// #define LOG_MODULE_NAME BLE_Prototype
54// LOG_MODULE_REGISTER(LOG_MODULE_NAME);
55// LOG_MODULE_REGISTER(BLE_Prototype, LOG_LEVEL_DBG);
56LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);
57
58#include <zephyr/drivers/gpio.h>
59
60#define STACKSIZE CONFIG_BT_NUS_THREAD_STACK_SIZE //!< stack size for main thread
61#define PRIORITY 7 //!< priority for main thread
62
63#define DEVICE_NAME CONFIG_BT_DEVICE_NAME //!< device name defined in prj.conf
64#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) //!< length of device name
65
66#define RUN_STATUS_LED DK_LED1 //!< LED to indicate the application is running
67#define RUN_LED_BLINK_INTERVAL 1000 //!< interval for blinking the run status LED in milliseconds
68
69#define CON_STATUS_LED DK_LED2 //!< LED to indicate the BLE connection status
70
71#define KEY_PASSKEY_ACCEPT DK_BTN1_MSK //!< Button used to accept a pairing passkey
72#define KEY_PASSKEY_REJECT DK_BTN2_MSK //!< Button used to reject a pairing passkey
73
74#define UART_BUF_SIZE CONFIG_BT_NUS_UART_BUFFER_SIZE //!< size of the buffer for UART data
75#define UART_WAIT_FOR_BUF_DELAY K_MSEC(50) //!< delay to wait for UART buffer availability in milliseconds
76#define UART_WAIT_FOR_RX CONFIG_BT_NUS_UART_RX_WAIT_TIME
77
78/* start I2C test */
79#if 1
80#if DT_NODE_HAS_STATUS(DT_ALIAS(i2c_0), okay) //!< check if i2c_0 alias is okay in devicetree
81#define I2C_DEV_NODE DT_ALIAS(i2c_0) //!< if i2c_0 alias is okay, set I2C_DEV_NODE to i2c_0 alias
82#elif DT_NODE_HAS_STATUS(DT_ALIAS(i2c_1), okay) //!< check if i2c_1 alias is okay in devicetree
83#define I2C_DEV_NODE DT_ALIAS(i2c_1)
84#elif DT_NODE_HAS_STATUS(DT_ALIAS(i2c_2), okay) //!< check if i2c_2 alias is okay in devicetree
85#define I2C_DEV_NODE DT_ALIAS(i2c_2)
86#else
87#error "Please set the correct I2C device"
88#endif
89#endif
90
91#if CONFIG_SERIAL
92#if 1
93#if DT_NODE_HAS_STATUS(DT_ALIAS(uart0), okay)
94#define UART0_DEV_NODE DT_ALIAS(uart0)
95#else
96// #error "Please set the correct UART0 device"
97#warning "UART0 not available"
98#endif
99const struct device *const uart0_dev = DEVICE_DT_GET(UART0_DEV_NODE); //!< pointer to UART0 (CLI) device
100#endif
101#endif
102
103/* prototypes */
104void hdc2080RdyHandler(void);
105
106const struct device *const i2c_dev = DEVICE_DT_GET(I2C_DEV_NODE); //!< get the device structure for the I2C device defined by I2C_DEV_NODE
107/* end I2C test */
108
109static K_SEM_DEFINE(ble_init_ok, 0,
110 1); //!< semaphore to indicate when BLE initialization is complete and the system is ready for BLE operations
111K_SEM_DEFINE(hdc_rdy_seen, 0, 1); //!< semaphore to indicate when the HDC2080 sensor ready signal has been seen
112K_SEM_DEFINE(sw2_rdy_seen, 0, 1); //!< semaphore to indicate when the SW2 button press has been seen
113K_SEM_DEFINE(cli_cmd_seen, 0, 1); //!< semaphore to indicate when a CLI command has been received and is ready for processing
114K_SEM_DEFINE(uart_rx_disabled_sem, 0, 1); //!< semaphore to indicate UART RX is disabled
115
116static struct bt_conn *current_conn; //!< pointer to the current BLE connection structure, used to keep track of the active BLE connection
117 //!< for sending data and managing connection state
118static struct bt_conn *auth_conn; //!< pointer to the BLE connection structure that is currently undergoing authentication, used to manage
119 //!< pairing and security procedures separately from the active connection used for data transfer
120static struct k_work
121 adv_work; //!< work item for handling BLE advertising operations, used to schedule advertising tasks in the system workqueue
122
123/* start dummy timer setup */
124/* commentthis line to yse GDC hardware - uncomment if using simuated interrupt */
125// #define SIMULATED_INTERRUPT
126#ifdef SIMULATED_INTERRUPT
127struct k_timer simulated_interrupt_timer; //!< timer to simulate HDC2080 interrupt
128
129/*!
130 * \fn void simulated_interrupt_handler(struct k_work *work)
131 *
132 * \brief work function GDC2080 simulated interrupt handler
133 *
134 * simulates a HDC2080 interrupt for testing
135 *
136 * \param work ptr to work funtion
137 *
138 *
139 */
140void simulated_interrupt_handler(struct k_work *work) {
141 char str[80];
142 static int count = 0;
143
144 sprintf(str, "count: %d", count++);
145 myPrintkI("HDC Interrupt %s\r\n", str);
146 if (bt_nus_send(NULL, str, strlen(str))) {
147 myPrintkE("Failed to send data over BLE connection\r\n");
148 }
149}
150
151K_WORK_DEFINE(simulated_interrupt_work, simulated_interrupt_handler);
152
153/*!
154 * \fn void simulated_interrupt_handler(struct k_timer *dummy)
155 *
156 * \brief simulated interrupt handler
157 *
158 * timer handler jsimulated interrupt
159 *
160 * \param dummy pointer to a timer sturcture
161 *
162 *
163 */
164void simulated_interrupt_timer_handler(struct k_timer *dummy) { k_work_submit(&simulated_interrupt_work); }
165#endif
166/* end dummy timer setup */
167
168/* start GPIO test */
169
170#if 1
171#define BATEN_NODE DT_ALIAS(baten) //!< check if baten alias is okay in devicetree and set BATEN_NODE to baten alias
172#if !DT_NODE_HAS_STATUS(BATEN_NODE, okay) //!< check if BATEN_NODE is okay in devicetree
173#error "BATEN alias is not defined"
174#endif
175const struct gpio_dt_spec baten =
176 GPIO_DT_SPEC_GET_OR(BATEN_NODE, gpios, {0}); //!< get the GPIO specification for the BATEN pin defined by BATEN_NODE
177#endif
178
179#if 1
180#define HDC2080RDY_NODE \
181 DT_ALIAS(hdc2080rdy) //!< check if hdc2080rdy alias is okay in devicetree and set HDC2080RDY_NODE to hdc2080rdy alias
182#if !DT_NODE_HAS_STATUS(HDC2080RDY_NODE, okay) //!< check if HDC2080RDY_NODE is okay in devicetree
183#error "HDC2080 alias is not defined"
184#endif
185static const struct gpio_dt_spec hdc2080 =
186 GPIO_DT_SPEC_GET_OR(HDC2080RDY_NODE, gpios, {0}); //!< get the GPIO specification for the HDC2080 ready pin defined by HDC2080RDY_NODE
187static struct gpio_callback hdc2080_cb_data; //!< GPIO callback structure for handling HDC2080 ready pin interrupts
188#endif
189
190#if 1
191#define SW2_NODE DT_ALIAS(sw2input) //!< check if sw2input alias is okay in devicetree and set SW2_NODE to sw2input alias
192#if !DT_NODE_HAS_STATUS(SW2_NODE, okay) //!< check if SW2_NODE is okay in devicetree
193#error "SW2 alias is not defined"
194#endif
195static const struct gpio_dt_spec sw2 =
196 GPIO_DT_SPEC_GET_OR(SW2_NODE, gpios, {0}); //!< get the GPIO specification for the SW2 button pin defined by SW2_NODE
197static struct gpio_callback sw2_cb_data; //!< GPIO callback structure for handling SW2 button pin interrupts
198#endif
199
200/* end GPIO test */
201
202/* start SPI test */
203#include <zephyr/drivers/spi.h>
204
205/* end SPI test */
206
207/* start ADC test */
208#include <math.h>
209#include <nrfx_saadc.h>
210#include <zephyr/drivers/adc.h>
211#define ADC_BUFFER_SIZE 1 //!< number of ADC channels to read
212
213#if DT_NODE_HAS_STATUS(DT_ALIAS(adc), okay) //!< check if adc alias is okay in devicetree and set ADC_DEV_NODE to adc alias
214#define ADC_DEV_NODE DT_ALIAS(adc) //!< if adc alias is okay, set ADC_DEV_NODE to adc alias
215#else
216#error "Please set the correct ADC device"
217#endif
218
219////#define ADC_DEVICE_NAME DT_ADC_0_NAME
220#define ADC_RESOLUTION 10 //!< resolution for ADC readings in bits (e.g., 10 bits for values from 0 to 1023)
221#define ADC_GAIN \
222 ADC_GAIN_1_6 //!< gain setting for ADC readings, set to 1/6 to allow for a wider input voltage range (e.g., up to 3.6V with a 3.3V
223 //!< reference)
224#define ADC_REFERENCE \
225 ADC_REF_INTERNAL //!< reference voltage for ADC readings, set to internal reference for stable and consistent measurements
226#define ADC_ACQUISITION_TIME \
227 ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10) //!< acquisition time for ADC readings, set to 10 microseconds to allow for accurate sampling
228 //!< of the input signal while minimizing noise and power consumption
229#define ADC_1ST_CHANNEL_ID 0 //!< channel ID for the first ADC channel to read, set to 0 for the first channel (e.g., AIN0 on nRF52832)
230#define ADC_1ST_CHANNEL_INPUT \
231 NRF_SAADC_INPUT_AIN0 //!< input selection for the first ADC channel, set to AIN0 for the first analog input on nRF52832 (e.g., connected
232 //!< to a sensor output or battery voltage)
233#define ADC_2ND_CHANNEL_ID 1 //!< channel ID for the second ADC channel to read, set to 1 for the second channel (e.g., AIN1 on nRF52832)
234#define ADC_2ND_CHANNEL_INPUT \
235 NRF_SAADC_INPUT_AIN1 //!< input selection for the second ADC channel, set to AIN1 for the second analog input on nRF52832 (e.g., connected
236 //!< to a different sensor output or reference voltage)
237#define ADC_3RD_CHANNEL_ID 2 //!< channel ID for the third ADC channel to read, set to 2 for the third channel (e.g., AIN2 on nRF52832)
238#define ADC_3RD_CHANNEL_INPUT \
239 NRF_SAADC_INPUT_AIN2 //!< input selection for the third ADC channel, set to AIN2 for the third analog input on nRF52832 (e.g., connected
240 //!< to a different sensor output or reference voltage)
241#define ADC_4TH_CHANNEL_ID 3 //!< channel ID for the fourth ADC channel to read, set to 3 for the fourth channel (e.g., AIN3 on nRF52832)
242#define ADC_4TH_CHANNEL_INPUT \
243 NRF_SAADC_INPUT_AIN3 //!< input selection for the fourth ADC channel, set to AIN3 for the fourth analog input on nRF52832 (e.g., connected
244 //!< to a different sensor output or reference voltage)
245#define ADC_5TH_CHANNEL_ID 4 //!< channel ID for the fifth ADC channel to read, set to 4 for the fifth channel (e.g., AIN4 on nRF52832)
246#define ADC_5TH_CHANNEL_INPUT \
247 NRF_SAADC_INPUT_AIN4 //!< input selection for the fifth ADC channel, set to AIN4 for the fifth analog input on nRF52832 (e.g., connected
248 //!< to a different sensor output or reference voltage)
249#define ADC_6ST_CHANNEL_ID 5 //!< channel ID for the sixth ADC channel to read, set to 5 for the sixth channel (e.g., AIN5 on nRF52832)
250#define ADC_6ST_CHANNEL_INPUT \
251 NRF_SAADC_INPUT_AIN5 //!< input selection for the sixth ADC channel, set to AIN5 for the sixth analog input on nRF52832 (e.g., connected
252 //!< to a different sensor output or reference voltage)
253
254const struct device *const adc_dev = DEVICE_DT_GET(ADC_DEV_NODE); //!< get the device structure for the ADC device defined by ADC_DEV_NODE
255
256#if 0
257static const struct adc_channel_cfg m_4th_channel_cfg = //!< ADC config for ADC input
258{
259 .gain = ADC_GAIN,
260 .reference = ADC_REFERENCE,
261 .acquisition_time = ADC_ACQUISITION_TIME,
262 .channel_id = ADC_4TH_CHANNEL_ID,
263#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS)
264 .input_positive = ADC_4TH_CHANNEL_INPUT,
265#endif
266};
267#endif
268
269#if 0
270static const struct adc_channel_cfg m_3rd_channel_cfg =
271{
272 .gain = ADC_GAIN,
273 .reference = ADC_REFERENCE,
274 .acquisition_time = ADC_ACQUISITION_TIME,
275 .channel_id = ADC_3RD_CHANNEL_ID,
276#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS)
277 .input_positive = ADC_3RD_CHANNEL_INPUT,
278#endif
279};
280#endif
281
282#if 0
283static const struct adc_channel_cfg m_2nd_channel_cfg = //!< ADC config for Battery input
284{
285 .gain = ADC_GAIN,
286 .reference = ADC_REFERENCE,
287 .acquisition_time = ADC_ACQUISITION_TIME,
288 .channel_id = ADC_2ND_CHANNEL_ID,
289#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS)
290 .input_positive = ADC_2ND_CHANNEL_INPUT,
291#endif
292};
293#endif
294
295#if 1
296/*!
297 * \brief ADC configuration for the first channel
298 * This structure defines the configuration for the first ADC channel, including gain, reference voltage, acquisition time, channel ID, and
299 * input selection. It is used to set up the ADC for reading from the specified channel with the desired settings.
300 */
301static const struct adc_channel_cfg m_1st_channel_cfg = {
302 .gain = ADC_GAIN,
303 .reference = ADC_REFERENCE,
304 .acquisition_time = ADC_ACQUISITION_TIME,
305 .channel_id = ADC_1ST_CHANNEL_ID,
306#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS)
307 .input_positive = ADC_1ST_CHANNEL_INPUT,
308#endif
309};
310#endif
311
312static int16_t m_sample_buffer[ADC_BUFFER_SIZE]; //!< buffer to receive ADC data from configured channels
313
314#define ADC_REF_MV 3600U
315#define ADC_DIV_MV 1000U
316#define ADC_MAX_VAL ((1U << ADC_RESOLUTION) - 1U)
317
318static const float adc_volts_per_step = (float)ADC_REF_MV / ((float)ADC_MAX_VAL * (float)ADC_DIV_MV);
319
320/** \fn static inline float adc_raw_to_voltage(uint16_t raw)
321 *
322 * \brief Convert raw ADC reading to voltage in volts.
323 *
324 * \param raw Raw ADC sample value (integer from 0..ADC_MAX_VAL)
325 * \return Voltage corresponding to the raw ADC value in volts (float)
326 *
327 * Uses the precomputed adc_volts_per_step factor which incorporates the
328 * reference voltage (ADC_REF_MV), ADC resolution and any divider (ADC_DIV_MV).
329 */
330static inline float adc_raw_to_voltage(uint16_t raw) { return (float)raw * adc_volts_per_step; }
331
332/*!
333 * \fn int adc_sample(void)
334 *
335 * \brief get a single reading from ADC channel
336 *
337 * will read ADC_1ST_CHANNEL_ID\n
338 * resoultion set to ADC_RESOLUTION in millivolts\n
339 * will printout floating point value based on 3.6V max\n
340 *
341 * \return ADC_RESOLUTION value on ADC_1ST_CHANNEL_ID if pass or -1 if failed\n
342 */
343int adc_sample(void) {
344 int ret;
345 const struct adc_sequence sequence = {
346 .channels = BIT(ADC_1ST_CHANNEL_ID),
347 .buffer = m_sample_buffer,
348 .buffer_size = sizeof(m_sample_buffer),
349 .resolution = ADC_RESOLUTION,
350 };
351
352 if (!adc_dev) {
353 return -ENODEV;
354 }
355
356 ret = adc_read(adc_dev, &sequence);
357 if (ret != 0) {
358 myPrintkE("ADC read err: %d\n", ret);
359 return ret;
360 }
361
362 for (int i = 0; i < ADC_BUFFER_SIZE; i++) {
364 }
365
366 return 0;
367}
368
369/* end ADC test */
370
371char device_name[40]; //!< buffer to hold the device name string, used for BLE advertising and identification
372uint8_t device_name_len; //!< length of the device name string, used to ensure proper formatting and transmission in BLE advertising packets
373
374/* enums */
375/*!
376 * \brief Valid command indexes
377 */
381};
382
383char const *validCmds[] = //!< array of valid commands - case insensitive
384 {
385 "cr",
386 "END",
387};
388
389#if CONFIG_SERIAL
390static const struct device *uart =
391 DEVICE_DT_GET(DT_CHOSEN(nordic_nus_uart)); //!< get the device structure for the UART device defined by the nordic_nus_uart alias in
392 //!< devicetree, used for UART communication with the Nordic UART Service (NUS)
393static struct k_work_delayable
394 uart_work; //!< delayable work item for handling UART operations, used to schedule UART tasks in the system workqueue with a delay when
395 //!< necessary (e.g., waiting for buffer availability or processing received data)
396#endif
397
401 uint16_t len;
402}; //!< structure to hold UART data and metadata, including a reserved field for FIFO management, a data buffer for UART communication, and
403 //!< a length field to track the amount of valid data in the buffer
404
405static K_FIFO_DEFINE(fifo_uart_tx_data); //!< FIFO queue for UART data to be transmitted, used to manage outgoing UART data and ensure
406 //!< proper sequencing and flow control
407static K_FIFO_DEFINE(fifo_uart_rx_data); //!< FIFO queue for UART data that has been received, used to manage incoming UART data and ensure
408 //!< proper processing and flow control
409
410// static const struct bt_data ad[] =
411//{
412// BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
413// BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
414// };
415
416static struct bt_data ad[2] = {
417 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
418 BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
419};
420
421static const struct bt_data sd[] = {
422 BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
423};
424
425#if CONFIG_SERIAL
426#if CONFIG_BT_NUS_UART_ASYNC_ADAPTER
427UART_ASYNC_ADAPTER_INST_DEFINE(async_adapter);
428#else
429static const struct device *const async_adapter;
430#endif
431
432/*! \fn static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
433 *
434 * \brief UART callback function to handle UART events
435 *
436 * This function is called by the UART driver when specific UART events occur, such as data transmission completion, data reception, or
437 * errors. It processes the events and manages the UART data buffers accordingly.
438 *
439 * \param dev pointer to the UART device structure that triggered the event
440 * \param evt pointer to the uart_event structure containing details about the event
441 * \param user_data pointer to user-defined data (not used in this implementation)
442 *
443 * The function handles various UART events, including:
444 * - UART_TX_DONE: Indicates that a UART transmission has completed. The function retrieves the transmitted buffer, frees it, and checks for
445 * any pending data to transmit.
446 * - UART_RX_RDY: Indicates that received data is ready for processing. The function updates the length of received data and checks for
447 * newline characters to determine if reception should be disabled.
448 * - UART_RX_DISABLED: Indicates that reception has been disabled. The function allocates a new buffer for receiving data and re-enables
449 * reception.
450 * - UART_RX_BUF_REQUEST: Indicates that the driver requests a new buffer for continuous reception. The function allocates a new buffer and
451 * provides it to the driver.
452 * - UART_RX_BUF_RELEASED: Indicates that a buffer is no longer used by the driver. The function checks if there is valid data in the buffer
453 * and either queues it for processing or frees it.
454 * - UART_TX_ABORTED: Indicates that a transmission was aborted due to timeout or flow control issues. The function manages the aborted
455 * buffer and attempts to retransmit any remaining data.
456 */
457static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data) {
458 ARG_UNUSED(dev);
459
460 static size_t aborted_len;
461 struct uart_data_t *buf;
462 static uint8_t *aborted_buf;
463 static bool disable_req;
464
465 switch (evt->type) {
466 case UART_TX_DONE:
467 // myPrintkW("UART_TX_DONE\r\n");
468 if ((evt->data.tx.len == 0) || (!evt->data.tx.buf)) {
469 return;
470 }
471
472 if (aborted_buf) {
473 buf = CONTAINER_OF(aborted_buf, struct uart_data_t, data[0]);
474 aborted_buf = NULL;
475 aborted_len = 0;
476 } else {
477 buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t, data[0]);
478 }
479
480 k_free(buf);
481
482 buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
483 if (!buf) {
484 return;
485 }
486
487 if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
488 myPrintkW("Failed to send data over UART\r\n");
489 }
490
491 break;
492
493 case UART_RX_RDY:
494 // myPrintkW("UART_RX_RDY\r\n");
495 buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data[0]);
496 buf->len += evt->data.rx.len;
497
498 if (disable_req) {
499 return;
500 }
501
502 if ((evt->data.rx.buf[buf->len - 1] == '\n') || (evt->data.rx.buf[buf->len - 1] == '\r')) {
503 disable_req = true;
504 uart_rx_disable(uart);
505 }
506
507 break;
508
509 case UART_RX_DISABLED:
510 // myPrintkW("UART_RX_DISABLED\r\n");
511 disable_req = false;
512
513 buf = k_malloc(sizeof(*buf));
514 if (buf) {
515 buf->len = 0;
516 } else {
517 myPrintkW("Not able to allocate UART receive buffer\r\n");
518 k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
519 return;
520 }
521
522 /* check if UART0 is disabled */
523 // #ifdef NO_UART0
524 if (flashParameters.nouart0) {
525 /* signal that it is safe to suspend */
526 k_sem_give(&uart_rx_disabled_sem);
527 // #else
528 } else {
529 uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_WAIT_FOR_RX);
530 }
531 // #endif
532 break;
533
534 case UART_RX_BUF_REQUEST:
535 // myPrintkW("UART_RX_BUF_REQUEST\r\n");
536 buf = k_malloc(sizeof(*buf));
537 if (buf) {
538 buf->len = 0;
539 uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
540 } else {
541 myPrintkW("Not able to allocate UART receive buffer\r\n");
542 }
543
544 break;
545
546 case UART_RX_BUF_RELEASED:
547 // myPrintkW("UART_RX_BUF_RELEASED\r\n");
548 buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t, data[0]);
549
550 if (buf->len > 0) {
551 k_fifo_put(&fifo_uart_rx_data, buf);
552 } else {
553 k_free(buf);
554 }
555
556 break;
557
558 case UART_TX_ABORTED:
559 myPrintkW("UART_TX_ABORTED\r\n");
560 if (!aborted_buf) {
561 aborted_buf = (uint8_t *)evt->data.tx.buf;
562 }
563
564 aborted_len += evt->data.tx.len;
565 buf = CONTAINER_OF((void *)aborted_buf, struct uart_data_t, data);
566
567 uart_tx(uart, &buf->data[aborted_len], buf->len - aborted_len, SYS_FOREVER_MS);
568
569 break;
570
571 default:
572 break;
573 }
574}
575#endif
576
577#if CONFIG_SERIAL
578/*!
579 * \fn static void uart_work_handler(struct k_work *item)
580 *
581 * \brief UART callback function to handle UART events
582 *
583 * This function is called by the UART driver when specific UART events occur, such as data transmission completion, data reception, or
584 * errors. It processes the events and manages the UART data buffers accordingly.
585 *
586 * \param dev pointer to the UART device structure that triggered the event
587 * \param evt pointer to the uart_event structure containing details about the event
588 * \param user_data pointer to user-defined data (not used in this implementation)
589 *
590 * The function handles various UART events, including:
591 * - UART_TX_DONE: Indicates that a UART transmission has completed. The function retrieves the transmitted buffer, frees it, and checks
592for
593 * any pending data to transmit.
594 * - UART_RX_RDY: Indicates that received data is ready for processing. The function updates the length of received data and checks for
595 * newline characters to determine if reception should be disabled.
596 * - UART_RX_DISABLED: Indicates that reception has been disabled. The function allocates a new buffer for receiving data and re-enables
597 * reception.
598 * - UART_RX_BUF_REQUEST: Indicates that the driver requests a new buffer for continuous reception. The function allocates a new buffer and
599 * provides it to the driver.
600 * - UART_RX_BUF_RELEASED: Indicates that a buffer is no longer used by the driver. The function checks if there is valid data in the
601buffer
602 * and either queues it for processing or frees it.
603 * - UART_TX_ABORTED: Indicates that a transmission was aborted due to timeout or flow control issues. The function manages the aborted
604 * buffer and attempts to retransmit any remaining data.
605*/
606static void uart_work_handler(struct k_work *item) {
607 struct uart_data_t *buf;
608
609 buf = k_malloc(sizeof(*buf));
610 if (buf) {
611 buf->len = 0;
612 } else {
613 myPrintkW("Not able to allocate UART receive buffer\r\n");
614 k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
615 return;
616 }
617
618 uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_WAIT_FOR_RX);
619}
620#endif
621
622#if CONFIG_SERIAL
623/*!
624 * \fn static bool uart_test_async_api(const struct device *dev)
625 * \brief Test if the UART device supports asynchronous API
626 * \param dev pointer to the UART device structure
627 * \return true if the device supports asynchronous API, false otherwise
628 */
629static bool uart_test_async_api(const struct device *dev) {
630 const struct uart_driver_api *api = (const struct uart_driver_api *)dev->api;
631
632 return (api->callback_set != NULL);
633}
634#endif
635
636#if CONFIG_SERIAL
637/*!
638 * \fn static int uart_init(void)
639 * \brief Initialize the UART device
640 * \return 0 on success, negative error code on failure
641 */
642// static int uart_init(void) {
643int uart_init(void) {
644 int err;
645 int pos;
646 struct uart_data_t *rx;
647 struct uart_data_t *tx;
648
649 if (!device_is_ready(uart)) {
650 return -ENODEV;
651 }
652
653 if (IS_ENABLED(CONFIG_USB_DEVICE_STACK)) {
654 err = usb_enable(NULL);
655 if (err && (err != -EALREADY)) {
656 myPrintkE("Failed to enable USB\r\n");
657 return err;
658 }
659 }
660
661 rx = k_malloc(sizeof(*rx));
662 if (rx) {
663 rx->len = 0;
664 } else {
665 return -ENOMEM;
666 }
667
668 k_work_init_delayable(&uart_work, uart_work_handler);
669
670 if (IS_ENABLED(CONFIG_BT_NUS_UART_ASYNC_ADAPTER) && !uart_test_async_api(uart)) {
671 /* Implement API adapter */
672 uart_async_adapter_init(async_adapter, uart);
673 uart = async_adapter;
674 }
675
676 err = uart_callback_set(uart, uart_cb, NULL);
677 if (err) {
678 k_free(rx);
679 myPrintkE("Cannot initialize UART callback\r\n");
680 return err;
681 }
682
683 if (IS_ENABLED(CONFIG_UART_LINE_CTRL)) {
684 myPrintkI("Wait for DTR\r\n");
685 while (true) {
686 uint32_t dtr = 0;
687
688 uart_line_ctrl_get(uart, UART_LINE_CTRL_DTR, &dtr);
689 if (dtr) {
690 break;
691 }
692 /* Give CPU resources to low priority threads. */
693 k_sleep(K_MSEC(100));
694 }
695 myPrintkI("DTR set\r\n");
696 err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DCD, 1);
697 if (err) {
698 myPrintkW("Failed to set DCD, ret code %d\r\n", err);
699 }
700 err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DSR, 1);
701 if (err) {
702 myPrintkW("Failed to set DSR, ret code %d\r\n", err);
703 }
704 }
705
706 tx = k_malloc(sizeof(*tx));
707
708 if (tx) {
709 pos = snprintf(tx->data, sizeof(tx->data), "Starting BLE Prototype (nRF52832)\r\n");
710
711 if ((pos < 0) || (pos >= sizeof(tx->data))) {
712 k_free(rx);
713 k_free(tx);
714 myPrintkE("snprintf returned %d\r\n", pos);
715 return -ENOMEM;
716 }
717
718 tx->len = pos;
719 } else {
720 k_free(rx);
721 return -ENOMEM;
722 }
723
724 err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
725 if (err) {
726 k_free(rx);
727 k_free(tx);
728 myPrintkE("Cannot display welcome message (err: %d)\r\n", err);
729 return err;
730 }
731
732 err = uart_rx_enable(uart, rx->data, sizeof(rx->data), 50);
733 if (err) {
734 myPrintkE("Cannot enable uart reception (err: %d)\r\n", err);
735 /* Free the rx buffer only because the tx buffer will be handled in the callback */
736 k_free(rx);
737 }
738
739 return err;
740}
741#endif
742
743/*!
744 * \fn static void adv_work_handler(struct k_work *work)
745 * \brief Handler for the advertising work item
746 * \param work pointer to the work item
747 */
748static void adv_work_handler(struct k_work *work) {
749 int err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_2, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
750
751 if (err) {
752 myPrintkE("Advertising failed to start (err %d)\r\n", err);
753 return;
754 }
755
756 myPrintkI("Advertising successfully started\r\n");
757}
758
759/*!
760 * \fn static void advertising_start(void)
761 * \brief Start the advertising process
762 *
763 */
764static void advertising_start(void) { k_work_submit(&adv_work); }
765
766/*!
767 * \fn static void connected(struct bt_conn *conn, uint8_t err)
768 * \brief Callback function for when a Bluetooth connection is established
769 * \param conn pointer to the Bluetooth connection structure
770 * \param err error code indicating the result of the connection attempt
771 * This function is called when a Bluetooth connection is established. It checks for any errors during the connection process and logs the
772 * result. If the connection is successful, it stores a reference to the current connection and updates the connection status LED to
773 * indicate that a device is connected.
774 *
775 */
776static void connected(struct bt_conn *conn, uint8_t err) {
777 char addr[BT_ADDR_LE_STR_LEN];
778
779 if (err) {
780 myPrintkE("Connection failed (err %u)\r\n", err);
781 return;
782 }
783
784 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
785 myPrintkI("Connected %s\r\n", addr);
786
787 current_conn = bt_conn_ref(conn);
788
789 dk_set_led_on(CON_STATUS_LED);
790}
791
792/*!
793 * \fn static void disconnected(struct bt_conn *conn, uint8_t reason)
794 * \brief Callback function for when a Bluetooth connection is lost
795 * \param conn pointer to the Bluetooth connection structure
796 * \param reason reason for the disconnection
797 * This function is called when a Bluetooth connection is lost. It logs the address of the disconnected device and the reason for the
798 * disconnection. It also checks if there are any active connections or authentication processes and cleans up the connection references
799 * accordingly. Finally, it updates the connection status LED to indicate that no device is currently connected.
800 */
801static void disconnected(struct bt_conn *conn, uint8_t reason) {
802 char addr[BT_ADDR_LE_STR_LEN];
803
804 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
805
806 myPrintkI("Disconnected: %s (reason %u)\r\n", addr, reason);
807
808 if (auth_conn) {
809 bt_conn_unref(auth_conn);
810 auth_conn = NULL;
811 }
812
813 if (current_conn) {
814 bt_conn_unref(current_conn);
815 current_conn = NULL;
816 dk_set_led_off(CON_STATUS_LED);
817 }
818}
819
820/*!
821 * \fn static void recycled_cb(void)
822 * \brief Callback function for when a Bluetooth connection object is recycled
823 *
824 * This function is called when a Bluetooth connection object is recycled, which typically occurs after a disconnection has been fully
825 * processed and the connection resources have been released. It logs a message indicating that the connection object is now available for
826 * reuse and starts the advertising process again to allow new devices to connect.
827 *
828 */
829static void recycled_cb(void) {
830 myPrintkI("Connection object available from previous conn. Disconnect is complete!\r\n");
832}
833
834#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
835/*!
836 * \fn static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
837 * \brief Callback function for when the security level of a Bluetooth connection changes
838 * \param conn pointer to the Bluetooth connection structure
839 * \param level new security level
840 * \param err error code indicating the result of the security change attempt
841 * This function is called when the security level of a Bluetooth connection changes. It logs the address of the device and the new security
842 * level if the change was successful, or logs a warning with the error code if the change failed. This is important for managing the
843 * security state of the connection and ensuring that the appropriate security measures are
844 */
845static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {
846 char addr[BT_ADDR_LE_STR_LEN];
847
848 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
849
850 if (!err) {
851 myPrintkI("Security changed: %s level %u\r\n", addr, level);
852 } else {
853 myPrintkW("Security failed: %s level %u err %d\r\n", addr, level, err);
854 }
855}
856#endif
857
858/**
859 * \brief Bluetooth connection callbacks
860 */
861BT_CONN_CB_DEFINE(conn_callbacks) = {
862 .connected = connected,
863 .disconnected = disconnected,
864 .recycled = recycled_cb,
865#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
866 .security_changed = security_changed,
867#endif
868};
869
870#if defined(CONFIG_BT_NUS_SECURITY_ENABLED)
871/*!
872 * \fn static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
873 * \brief Callback function for when a passkey is displayed during authentication
874 * \param conn pointer to the Bluetooth connection structure
875 * \param passkey the passkey to be displayed
876 * This function is called when a passkey needs to be displayed during the authentication process. It logs the address of the device and the
877 * passkey.
878 */
879static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey) {
880 char addr[BT_ADDR_LE_STR_LEN];
881
882 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
883
884 myPrintkI("Passkey for %s: %06u\r\n", addr, passkey);
885}
886
887/*!
888 * \fn static void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey)
889 * \brief Callback function for when a passkey is confirmed during authentication
890 * \param conn pointer to the Bluetooth connection structure
891 * \param passkey the passkey to be confirmed
892 * This function is called when a passkey needs to be confirmed during the authentication process. It logs the address of the device and the
893 * passkey.
894 */
895static void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey) {
896 char addr[BT_ADDR_LE_STR_LEN];
897
898 auth_conn = bt_conn_ref(conn);
899
900 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
901
902 myPrintkI("Passkey for %s: %06u\r\n", addr, passkey);
903 myPrintkI("Press Button 1 to confirm, Button 2 to reject.\r\n");
904}
905
906/*!
907 * \fn static void auth_cancel(struct bt_conn *conn)
908 * \brief Callback function for when pairing is cancelled
909 * \param conn pointer to the Bluetooth connection structure
910 * This function is called when pairing is cancelled. It logs the address of the device.
911 */
912static void auth_cancel(struct bt_conn *conn) {
913 char addr[BT_ADDR_LE_STR_LEN];
914
915 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
916
917 myPrintkI("Pairing cancelled: %s\r\n", addr);
918}
919
920/*!
921 * \fn static void pairing_complete(struct bt_conn *conn, bool bonded)
922 * \brief Callback function for when pairing is completed
923 * \param conn pointer to the Bluetooth connection structure
924 * \param bonded indicates whether the device is bonded after pairing
925 * This function is called when pairing is completed. It logs the address of the device and whether it is bonded.
926 */
927static void pairing_complete(struct bt_conn *conn, bool bonded) {
928 char addr[BT_ADDR_LE_STR_LEN];
929
930 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
931
932 myPrintkI("Pairing completed: %s, bonded: %d\r\n", addr, bonded);
933}
934
935/*!
936 * \fn static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
937 * \brief Callback function for when pairing fails
938 * \param conn pointer to the Bluetooth connection structure
939 * \param reason the reason for the pairing failure
940 * This function is called when pairing fails. It logs the address of the device and the reason for the failure.
941 */
942static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) {
943 char addr[BT_ADDR_LE_STR_LEN];
944
945 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
946
947 myPrintkI("Pairing failed conn: %s, reason %d %s\r\n", addr, reason, bt_security_err_to_str(reason));
948}
949
950/*!
951 * \brief Bluetooth connection authentication callbacks
952 * This structure defines the callbacks for Bluetooth connection authentication events, including passkey display, passkey confirmation, and
953 * cancellation of pairing. It is used to manage the authentication process during Bluetooth pairing and ensure that the appropriate actions
954 * are taken based on user input and authentication events.
955 */
956static struct bt_conn_auth_cb conn_auth_callbacks = {
957 .passkey_display = auth_passkey_display,
958 .passkey_confirm = auth_passkey_confirm,
959 .cancel = auth_cancel,
960};
961
962/*!
963* \brief Bluetooth connection authentication information callbacks
964* This structure defines the callbacks for Bluetooth connection authentication information events, including pairing completion and pairing
965failure. It is used to manage the authentication process during Bluetooth pairing and ensure that the appropriate actions are taken based on
966the outcome of the pairing process, such as logging the results and handling any necessary cleanup or user notifications.
967
968*/
969static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {.pairing_complete = pairing_complete, .pairing_failed = pairing_failed};
970#else
971static struct bt_conn_auth_cb conn_auth_callbacks;
972static struct bt_conn_auth_info_cb conn_auth_info_callbacks;
973#endif
974
975/*!
976 * \fn static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
977 * \brief Callback function for receiving data over Bluetooth
978 * \param conn pointer to the Bluetooth connection structure
979 * \param data pointer to the received data
980 * \param len length of the received data
981 */
982static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data, uint16_t len) {
983 int err;
984 char addr[BT_ADDR_LE_STR_LEN] = {0};
985
986 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, ARRAY_SIZE(addr));
987
988#if 0
989 /* for testing */
990 sprintf(myStr, "%s B", devIDStr);
991 myPrintkS("%s\r\n", myStr);
992 bt_nus_send(NULL, myStr, strlen(myStr));
993 k_sleep(K_SECONDS(2));
994#endif
995
996 myPrintkI("Received data from: %s\r\n", addr);
997
998#if CONFIG_SERIAL
999 for (uint16_t pos = 0; pos != len;) {
1000 struct uart_data_t *tx = k_malloc(sizeof(*tx));
1001
1002 if (!tx) {
1003#if 0
1004 sprintf(myStr, "%s C", devIDStr);
1005 myPrintkS("%s\r\n", myStr);
1006 bt_nus_send(NULL, myStr, strlen(myStr));
1007 k_sleep(K_SECONDS(2));
1008#endif
1009 myPrintkW("Not able to allocate UART send data buffer\r\n");
1010 return;
1011 }
1012
1013 /* Keep the last byte of TX buffer for potential LF char. */
1014 size_t tx_data_size = sizeof(tx->data) - 1;
1015
1016 if ((len - pos) > tx_data_size) {
1017 tx->len = tx_data_size;
1018 } else {
1019 tx->len = (len - pos);
1020 }
1021
1022 memcpy(tx->data, &data[pos], tx->len);
1023
1024 pos += tx->len;
1025
1026 /* Append the LF character when the CR character triggered
1027 * transmission from the peer.
1028 */
1029 if ((pos == len) && (data[len - 1] == '\r')) {
1030 tx->data[tx->len] = '\n';
1031 tx->len++;
1032 }
1033
1034#if 0
1035 sprintf(myStr, "%s D", devIDStr);
1036 myPrintkS("%s\r\n", myStr);
1037 bt_nus_send(NULL, myStr, strlen(myStr));
1038 k_sleep(K_SECONDS(2));
1039#endif
1040
1041 err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
1042 if (err) {
1043 k_fifo_put(&fifo_uart_tx_data, tx);
1044 }
1045
1046 /* show TX sent */
1047 tx->data[tx->len] = '\0';
1048 err = bleCommand(tx->data);
1049 }
1050#else
1051 char bleStr[80];
1052 int lentemp;
1053
1054 for (uint16_t pos = 0; pos != len;) {
1055
1056 /* Keep the last byte of TX buffer for potential LF char. */
1057 size_t tx_data_size = sizeof(bleStr) - 1;
1058
1059 if ((len - pos) > tx_data_size) {
1060 lentemp = tx_data_size;
1061 } else {
1062 lentemp = (len - pos);
1063 }
1064
1065 memcpy(bleStr, &data[pos], lentemp);
1066
1067 pos += lentemp;
1068
1069 /* Append the LF character when the CR character triggered
1070 * transmission from the peer.
1071 */
1072 if ((pos == len) && (data[len - 1] == '\r')) {
1073 bleStr[lentemp] = '\n';
1074 lentemp++;
1075 }
1076
1077 /* show TX sent */
1078 bleStr[lentemp] = '\0';
1079
1080#if 0
1081 sprintf(myStr, "%s DD %s", devIDStr, bleStr);
1082 bt_nus_send(NULL, myStr, strlen(myStr));
1083 k_sleep(K_SECONDS(2));
1084#endif
1085
1086 err = bleCommand(bleStr);
1087 }
1088#endif
1089}
1090
1091/*!
1092 * \brief Bluetooth NUS callbacks
1093 * This structure defines the callbacks for Bluetooth NUS events, including data reception.
1094 */
1095static struct bt_nus_cb nus_cb = {
1096 .received = bt_receive_cb,
1097};
1098
1099/*!
1100 * \fn void error(void)
1101 * \brief Function to handle fatal errors
1102 * This function is called when a fatal error occurs in the system. It turns off all LEDs to indicate an error state and enters an infinite
1103 * loop to halt the system. This is a common error handling approach in embedded systems to prevent further damage or undefined behavior
1104 * after a critical failure. The function also includes a commented-out print statement that could be used to log the error message before
1105 * halting the system, but it is currently disabled to avoid potential issues with logging in an error state.
1106 */
1107void error(void) {
1108 dk_set_leds_state(DK_ALL_LEDS_MSK, DK_NO_LEDS_MSK);
1109
1110 // myprintkE("Fatal Error!!\r\n");
1111 while (true) {
1112 /* Spin for ever */
1113 k_sleep(K_MSEC(1000));
1114 }
1115}
1116
1117#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
1118/*!
1119 * \fn static void num_comp_reply(bool accept)
1120 * \brief Callback function for handling numeric comparison replies
1121 * \param accept boolean indicating whether the numeric comparison was accepted
1122 * This function is called to handle the user's response to a numeric comparison during Bluetooth authentication. If the user accepts the
1123 * comparison, the function confirms the passkey for the current authentication connection. If the user rejects the comparison, the function
1124 * cancels the authentication process. After handling the user's response, the function releases the
1125 */
1126static void num_comp_reply(bool accept) {
1127 if (accept) {
1128 bt_conn_auth_passkey_confirm(auth_conn);
1129 myPrintkI("Numeric Match, conn %p\r\n", (void *)auth_conn);
1130 } else {
1131 bt_conn_auth_cancel(auth_conn);
1132 myPrintkI("Numeric Reject, conn %p\r\n", (void *)auth_conn);
1133 }
1134
1135 bt_conn_unref(auth_conn);
1136 auth_conn = NULL;
1137}
1138
1139/*!
1140 * \fn void button_changed(uint32_t button_state, uint32_t has_changed)
1141 * \brief Callback function for handling button changes
1142 * \param button_state current state of the buttons
1143 * \param has_changed bitmask indicating which buttons have changed
1144 * This function is called when the state of the buttons changes. It checks if there is an active authentication connection and if any of
1145 * the buttons that have changed are the ones used for accepting or rejecting the numeric comparison during authentication. If the accept
1146 * button is pressed, it calls the num_comp_reply function with true to confirm the pass key. If the reject button is pressed, it calls the
1147 * num_comp_reply function with false to cancel the authentication. This allows the user to interact with the authentication process using
1148 * physical buttons on the device.
1149 *
1150 */
1151void button_changed(uint32_t button_state, uint32_t has_changed) {
1152 uint32_t buttons = button_state & has_changed;
1153
1154 if (auth_conn) {
1155 if (buttons & KEY_PASSKEY_ACCEPT) {
1156 num_comp_reply(true);
1157 }
1158
1159 if (buttons & KEY_PASSKEY_REJECT) {
1160 num_comp_reply(false);
1161 }
1162 }
1163}
1164#endif /* CONFIG_BT_NUS_SECURITY_ENABLED */
1165
1166static void configure_gpio(void) {
1167 int err;
1168
1169#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
1170 err = dk_buttons_init(button_changed);
1171 if (err) {
1172 myPrintkE("Cannot init buttons (err: %d)\r\n", err);
1173 }
1174#endif /* CONFIG_BT_NUS_SECURITY_ENABLED */
1175
1176 err = dk_leds_init();
1177 if (err) {
1178 myPrintkE("Cannot init LEDs (err: %d)\r\n", err);
1179 }
1180}
1181
1183
1184/*!
1185 * \fn int main(void)
1186
1187 * \brief Nordic UART Bridge Service (NUS) sample (BLE_Prototype) starting point
1188
1189 * This is the main function of the program, which serves as the entry point for execution. It performs initial setup and configuration,
1190 * including determining the cause of the last reset, configuring GPIOs for buttons and LEDs, and setting up interrupts for the HDC2080
1191 * sensor and SW2 button. It also initializes the Bluetooth functionality and starts advertising for connections. The function includes
1192 * error handling to ensure that any issues during initialization are logged and that the system enters a safe state if critical errors
1193 * occur. Overall, this function orchestrates the initialization and main loop of the application, ensuring that all components are properly
1194 * set up and ready for operation.
1195
1196 * \return TRUE if passed, FALSE if failed
1197 *
1198 */
1199int main(void) {
1200 // int blink_status = 0;
1201 int err = 0;
1202
1203 /* find the reason that we started the program */
1204 ret = NRF_POWER->RESETREAS;
1205 if (ret == 0)
1206 sprintf(resetCause, "Power applied reset, ");
1207 if (ret & 0x1)
1208 strcat(resetCause, "Pin reset, ");
1209 if (ret & 0x2)
1210 strcat(resetCause, "Global Watchdog reset, ");
1211 if (ret & 0x4)
1212 strcat(resetCause, "Wakeup from system off detect from GPIO reset, ");
1213 if (ret & 0x10)
1214 strcat(resetCause, "Wakeup from system off debug interface mode reset, ");
1215 if (ret & 0x10000)
1216 strcat(resetCause, "AIRCR.SYSRESETREQ reset, ");
1217 if (ret & 0x20000)
1218 strcat(resetCause, "CPU lockup reset, ");
1219 if (ret & 0x40000)
1220 strcat(resetCause, "CTRL_AP reset, ");
1221 if (strlen(resetCause) > 90)
1222 resetCause[90] = '\0';
1223 resetCause[strlen(resetCause) - 2] = '\0';
1224 NRF_POWER->RESETREAS = ret;
1225 myPrintkS("resetCause: %s\r\n", resetCause);
1226
1227 bleIndex = 1; /* reset BLE index counter */
1228
1229 configure_gpio(); /* configure buttons and LEDS */
1230
1231 /* start GPIO test */
1232 myPrintk("*** GPIO Init ***\r\n");
1233
1234 /* check if hdc2080 (GPIO Inoput) ready */
1235 if (!gpio_is_ready_dt(&hdc2080)) {
1236 myPrintkE("Error: HDC2080 GPIO %s is not ready\n", hdc2080.port->name);
1237 error();
1238 }
1239 myPrintkI("HDC2080 GPIO %s is ready\n", hdc2080.port->name);
1240
1241 /* configure hdc2080 GPIO as input */
1242 err = gpio_pin_configure_dt(&hdc2080, GPIO_INPUT);
1243 if (err) {
1244 myPrintkE("Error %d: failed to configure %s pin %d\n", err, hdc2080.port->name, hdc2080.pin);
1245 error();
1246 }
1247 myPrintkI("HDC2080 passed configure %s pin %d\n", hdc2080.port->name, hdc2080.pin);
1248
1249 /* configure HDC2080 GPIO interrupt */
1250 // ret = gpio_pin_interrupt_configure_dt(&hdc2080 GPIO_INT_EDGE_TO_ACTIVE);
1251 err = gpio_pin_interrupt_configure_dt(&hdc2080, GPIO_INT_EDGE_FALLING);
1252 // ret = gpio_pin_interrupt_configure_dt(&hdc2080, GPIO_INT_EDGE_RISING);
1253 // ret = gpio_pin_interrupt_configure_dt(&hdc2080, GPIO_INT_EDGE_BOTH);
1254 if (err != 0) {
1255 myPrintkE("Error %d: failed to configure interrupt on %s pin %d\n", err, hdc2080.port->name, hdc2080.pin);
1256 error();
1257 }
1258 myPrintkI("HDC2080 passed configure interrupt on %s pin %d\n", hdc2080.port->name, hdc2080.pin);
1259
1260 /* set up HDC2080 GPIO interrupt callback */
1261 gpio_init_callback(&hdc2080_cb_data, hdc2080_rdy_seen, BIT(hdc2080.pin));
1262 gpio_add_callback(hdc2080.port, &hdc2080_cb_data);
1263 myPrintkI("Set up HDC2080 at %s pin %d\n", hdc2080.port->name, hdc2080.pin);
1264
1265 /* check if SW2 (GPIO Inoput) ready */
1266 if (!gpio_is_ready_dt(&sw2)) {
1267 myPrintkE("Error: SW2 GPIO %s is not ready\n", sw2.port->name);
1268 error();
1269 }
1270 myPrintkI("SW2 GPIO %s is ready\n", sw2.port->name);
1271
1272 /* configure SW2 GPIO as input */
1273 err = gpio_pin_configure_dt(&sw2, GPIO_INPUT);
1274 if (err) {
1275 myPrintkE("Error %d: failed to configure %s pin %d\n", err, sw2.port->name, sw2.pin);
1276 error();
1277 }
1278 myPrintkI("SW2 passed configure %s pin %d\n", sw2.port->name, sw2.pin);
1279
1280#if 1
1281 /* configure sw2 GPIO interrupt */
1282 // ret = gpio_pin_interrupt_configure_dt(&sw2 GPIO_INT_EDGE_TO_ACTIVE);
1283 err = gpio_pin_interrupt_configure_dt(&sw2, GPIO_INT_EDGE_FALLING);
1284 // ret = gpio_pin_interrupt_configure_dt(&sw2, GPIO_INT_EDGE_RISING);
1285 // ret = gpio_pin_interrupt_configure_dt(&sw2, GPIO_INT_EDGE_BOTH);
1286 if (err != 0) {
1287 myPrintkE("Error %d: failed to configure interrupt on %s pin %d\n", err, sw2.port->name, sw2.pin);
1288 error();
1289 }
1290 myPrintkI("SW2 passed configure interrupt on %s pin %d\n", sw2.port->name, sw2.pin);
1291
1292 /* set up SW2 GPIO interrupt callback */
1293 gpio_init_callback(&sw2_cb_data, sw2_seen, BIT(sw2.pin));
1294 gpio_add_callback(sw2.port, &sw2_cb_data);
1295 myPrintkI("Set up SW2 at %s pin %d\n", sw2.port->name, sw2.pin);
1296#endif
1297
1298 /* set up SPI CS1N as output/pullup */
1299 if (!gpio_is_ready_dt(&spics1n)) {
1300 myPrintkE("SPI CS1N device is not ready\r\n");
1301 } else
1302 myPrintkI("SPI CS1N device is ready\r\n");
1303 gpio_pin_configure_dt(&spics1n, GPIO_OUTPUT | GPIO_PULL_UP | GPIO_ACTIVE_LOW);
1304 gpio_pin_set(spics1n.port, spics1n.pin, 0);
1305
1306 /* set up SPI CS2N as output/pullup */
1307 if (!gpio_is_ready_dt(&spics2n)) {
1308 myPrintkE("SPI CS2N device is not ready\r\n");
1309 } else
1310 myPrintkI("SPI CS2N device is ready\r\n");
1311 gpio_pin_configure_dt(&spics2n, GPIO_OUTPUT | GPIO_PULL_UP | GPIO_ACTIVE_LOW);
1312 gpio_pin_set(spics2n.port, spics2n.pin, 0);
1313
1314 /* set up BATEN as output/pullup */
1315 if (!gpio_is_ready_dt(&baten)) {
1316 myPrintkE("BATEN device is not ready\r\n");
1317 } else
1318 myPrintkI("BATEN device is ready\r\n");
1319 gpio_pin_configure_dt(&baten, GPIO_OUTPUT | GPIO_PULL_UP);
1320
1321#if 0
1322/* SW2 switch push test */
1323 int test = 0;
1324 while(1)
1325 {
1326 test = gpio_pin_get(sw2.port, sw2.pin);
1327 myPrintk("SW@: %d\r\n",test);
1328 k_sleep(K_SECONDS(1));
1329 }
1330#endif
1331
1332#if 0
1333 /* SW2 switch interrupt test */
1334 while (1)
1335 {
1336 if (k_sem_take(&sw2_rdy_seen, K_MSEC(100)) == 0 )
1337 {
1338 myPrintk("SW2: %d\r\n", gpio_pin_get(sw2.port, sw2.pin));
1339 }
1340 }
1341#endif
1342
1343#if 0
1344 int test = 0;
1345 while(1)
1346 {
1347 /* toggle test */
1348// gpio_pin_toggle(spics1n.port, spics1n.pin);
1349// k_sleep(K_MSEC(10));
1350
1351 /* set/clear test */
1352 if(test++ & 0x01)
1353 {
1354// printf("set\r\n");
1355 gpio_pin_set(spics1n.port, spics1n.pin, 1);
1356 k_sleep(K_MSEC(10));
1357 }
1358 else
1359 {
1360// printf("clear\r\n");
1361 gpio_pin_set(spics1n.port, spics1n.pin, 0);
1362 k_sleep(K_MSEC(20));
1363 }
1364 }
1365#endif
1366
1367#if 0
1368 int test = 0;
1369 while(1)
1370 {
1371 /* toggle test */
1372// gpio_pin_toggle(spics2n.port, spics2n.pin);
1373// k_sleep(K_MSEC(10));
1374
1375 /* set/clear test */
1376 if(test++ & 0x01)
1377 {
1378// printf("set\r\n");
1379 gpio_pin_set(spics2n.port, spics2n.pin, 1);
1380 }
1381 else
1382 {
1383// printf("clear\r\n");
1384 gpio_pin_set(spics2n.port, spics2n.pin, 0);
1385 }
1386 k_sleep(K_MSEC(20));
1387 }
1388#endif
1389
1390#if 0
1391 int test = 0;
1392 while(1)
1393 {
1394 /* toggle test */
1395// gpio_pin_toggle(baten.port, baten.pin);
1396// k_sleep(K_MSEC(10));
1397
1398 /* set/clear test */
1399 if(test++ & 0x01)
1400 {
1401// printf("set\r\n");
1402 gpio_pin_set(baten.port, baten.pin, 1);
1403 }
1404 else
1405 {
1406// printf("clear\r\n");
1407 gpio_pin_set(baten.port, baten.pin, 0);
1408 }
1409 k_sleep(K_MSEC(20));
1410 }
1411#endif
1412
1413 /* end GPIO test */
1414
1415#if CONFIG_SERIAL
1416 err = uart_init(); /* initialize UART */
1417 if (err) {
1418 // myprintkE("UART device is not ready\r\n");
1419 error();
1420 }
1421 // myprintkI("UART device is ready\r\n");
1422#endif
1423
1424 err = init_i2c(); /* initialize I2C peripheral returns TRUE if passed */
1425 if (err == FALSE) {
1426 // myprintkE("I2C interface is not ready\r\n");
1427 error();
1428 }
1429 // myprintkI("I2C interface is ready\r\n");
1430
1431/* start I2C test */
1432#if 0
1433 unsigned char datas[6];
1434 while(1)
1435 {
1436 /* 4. verify i2c_read() from HDC2080 */
1437 datas[0] = 0xFC;
1438 i2c_write(i2c_dev, datas, 1, 0x40);
1439
1440 i2c_read(i2c_dev, datas, 2, 0x40);
1441 printf("I2C 0x%02X 0x%02X\r\n",datas[0],datas[1]);
1442 k_sleep(K_MSEC(1000));
1443 }
1444#endif
1445
1446 /* end I2C test */
1447 /* start SPI test */
1448
1449 myPrintk("*** SPI Init ***\r\n");
1450
1451 if (!device_is_ready(spi_dev)) {
1452 myPrintkE("SPI device is not ready\r\n");
1453 } else
1454 myPrintkI("SPI device is ready\r\n");
1455
1456#if 0
1457
1458 printf("SPI Test Running\r\n");
1459 while(1)
1460 {
1461 /* zero buffer and load the command */
1462 for(int i=0;i<4;i++)
1463 buffer_tx[i] = 0;
1464 buffer_tx[0] = 0x9F;
1465 tx_bufs[0].len = 4;
1466 rx_bufs[0].len = 4;
1467
1468 /* enable CS1 and send command */
1469 ret = spi_transceive(spi_dev, &spi_cfg1, &tx, &rx);
1470 k_sleep(K_MSEC(10));
1471
1472 /* enable CS2 and send command */
1473 ret = spi_transceive(spi_dev, &spi_cfg2, &tx, &rx);
1474 k_sleep(K_MSEC(10));
1475 }
1476#endif
1477
1478/* end SPi test */
1479
1480/* start Flash test */
1481#if 0
1482 uint8_t readBuffer[10];
1483//uint8_t flashRead[256];
1484//uint8_t data[3];
1485
1486 printf("Flash Test Running\r\n");
1487 while(1)
1488 {
1489// ret = initW25Q64JV();
1490 readNVFlashxStatus(readBuffer);
1491// flashxErasePage(1);
1492// flashxEraseBlock1(1);
1493// flashxEraseBlock2(1);
1494// flashxEraseSector(1);
1495// flashxErase();
1496// flashxReadPage(1, flashRead);
1497// data[0] = 0xAB;
1498// flashxWritePage(1, 3, data, 1);
1499// flashxFillPage(1, 0xCD);
1500// flashxClearParameters();
1501// setFlashxParameters(TRUE);
1502
1503
1504 k_sleep(K_MSEC(100));
1505 }
1506#endif
1507
1508 /* end Flash test */
1509
1510 /* start ADC test */
1511
1512 myPrintk("*** ADC Init ***\r\n");
1513
1514 if (!device_is_ready(adc_dev)) /* check if ADC peripheral ready */
1515 {
1516 myPrintkE("ADC device is not ready\n");
1517 return FALSE;
1518 }
1519 myPrintkI("ADC device is ready\n");
1520
1521 err = adc_channel_setup(adc_dev, &m_1st_channel_cfg);
1522 if (err) {
1523 myPrintkE("Error in adc AIN0 setup: %d\n", err);
1524 }
1525 myPrintkI("ADC AIN0 is ready\n");
1526
1527#if 0
1528
1529 printf("ADC Test Running\r\n");
1530 while(1)
1531 {
1532 err = adc_sample();
1533 printf("ADC: %3.2f\r\n",adc_voltage[0]);
1534 k_sleep(K_MSEC(5000));
1535 }
1536#endif
1537
1538 /* end ADC test */
1539
1540 /* get Nordic unique device ID */
1541 // sprintf(devIDStr, "%08X_%08X", NRF_FICR->DEVICEID[0], NRF_FICR->DEVICEID[1]);
1542 sprintf(devIDStr, "%08X", NRF_FICR->DEVICEID[0]);
1543 // sprintf(devIDStr, "%s", "x");
1544 myPrintkS("Device ID: %s\r\n", devIDStr);
1545 if (flashParameters.nouart0 == false) {
1546 myPrintkS("Board: %s%s\r\nFW VERSION: V %d.%02d %s%s\r\n", BOARD_NAME, BOARD_NAME_EXT, VERSION_MAJOR, VERSION_MINOR, VERSION_DATE,
1548 } else {
1549 myPrintkS("Board: %s%s\r\nFW VERSION: V %d.%02d %s%s\r\n", BOARD_NAME, BOARD_NAME_EXT, VERSION_MAJOR, VERSION_MINOR, VERSION_DATE,
1551 }
1552#ifndef CONFIG_SERIAL
1553 myPrintkS("Board: %s%s\r\nFW VERSION: V %d.%02d %s%s\r\n", BOARD_NAME, BOARD_NAME_EXT, VERSION_MAJOR, VERSION_MINOR, VERSION_DATE,
1555#endif
1556 myPrintkS("SDK Version: %s\r\n", EXPAND_AND_STR(NCS_BUILD_VERSION));
1557 myPrintkS("Built:%s %s\r\n", __DATE__, __TIME__);
1558
1559 /* chacek and load flashparameters */
1560 myPrintkS("Read Flash Parameters size: %d\r\n", sizeof(flashParametersStruct));
1561 getFlashparameters(); /* first read to set flash in correct state */
1563
1564 if (flashParameters.key == 0) {
1565 myPrintkW("Flash key not found, try again\r\n");
1566 getFlashparameters(); /* try one more time to read flash parameters */
1567 }
1568 myPrintk("key: 0x%08X\r\n", flashParameters.key);
1569
1570#if 1
1571 /* check if any flash parameters have been written */
1573 k_sleep(K_SECONDS(1));
1575 } else {
1576 myPrintkW("Flash Parameter Key: %08X Not Set\r\n", flashParameters.key);
1578 setFlashxParameters(true);
1579 }
1580#endif
1581
1582#ifdef SIMULATED_INTERRUPT
1583 /* start simulated interrupt timerr */
1584 k_timer_init(&simulated_interrupt_timer, simulated_interrupt_timer_handler, NULL);
1585 k_timer_start(&simulated_interrupt_timer, K_SECONDS(5), K_SECONDS(5));
1586 k_sleep(K_SECONDS(2));
1587#endif
1588
1589#if 1
1591
1592 if (err) {
1593 myPrintkE("watchdog_init_and_start, error: %d\n", err);
1594 } else {
1595 myPrintkI("watchdog_init_and_start Passed\n");
1596 }
1597#endif
1598
1599 /* is BLE security UART enabled */
1600 if (IS_ENABLED(CONFIG_BT_NUS_SECURITY_ENABLED)) {
1601 err = bt_conn_auth_cb_register(&conn_auth_callbacks); /* register authorization callbacks */
1602 if (err) {
1603 myPrintkE("Failed to register BLE authorization callbacks.\n");
1604 error();
1605 }
1606 myPrintkI("Passed register BLE authorization callbacks.\n");
1607
1608 err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks); /* register authorization info callbacks */
1609 if (err) {
1610 myPrintkE("Failed to register BLE authorization info callbacks.\n");
1611 error();
1612 }
1613 myPrintkI("passed register BLE authorization info callbacks.\n");
1614 }
1615
1616 err = bt_enable(NULL); /* enable Bluetooth */
1617 if (err) {
1618 myPrintkE("Failed to enable BLE. %d\n", err);
1619 error();
1620 }
1621 myPrintkI("Bluetooth Enabled\r\n");
1622
1623 k_sem_give(&ble_init_ok); /* set semaphore to indicate BLE OK */
1624
1625 if (IS_ENABLED(CONFIG_SETTINGS)) {
1626 err = settings_load();
1627 }
1628
1629 err = bt_nus_init(&nus_cb); /* initialize Nordic UART Service */
1630 if (err) {
1631 // sprintfstr, "Failed to initialize UART service (err: %d)", err);
1632 // myprintkE(str);
1633 error();
1634 }
1635 // myprintkI("initialized BLE UART service\r\n");
1636
1637 /* create unique BLE advertizer name */
1638 strcpy(device_name, DEVICE_NAME);
1639 strcat(device_name, devIDStr);
1640 device_name_len = strlen(device_name);
1641 myPrintkS("BLE Advertizing name: %s\r\n", device_name);
1642 ad[1].type = BT_DATA_NAME_COMPLETE;
1643 ad[1].data_len = device_name_len;
1644 ad[1].data = device_name;
1645
1646#ifndef SW2STARTSADVERTISING
1647
1648 k_work_init(&adv_work, adv_work_handler);
1650 // err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); /* start BLE advertising */
1651 // if (err)
1652 // {
1653 // myPrintkE("Advertising failed to start (err %d)", err);
1654 // error();
1655 // }
1656 myPrintkI("Advertising started (name %s)\r\n", device_name);
1657#endif
1658
1659 rescan(); /* scans for all I2C and SPI devices */
1660
1661 /* set HDC2080 interrupt rate */
1662 if (flashParameters.manualTrigger == true) {
1663 setRate(MANUAL); /* set manual trigger */
1664 } else if (flashParameters.dutyCycle > 7) {
1665 setRate(ONE_MINS); /* set auto conversion rate */
1666 hdcMinutes = flashParameters.dutyCycle - 7;
1667 } else {
1668 setRate(flashParameters.dutyCycle); /* set auto conversion rate */
1669 }
1670
1671#if 0
1672 for (;;)
1673 {
1674 dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
1675 k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
1676 }
1677#else
1678
1679#if CONFIG_SERIAL
1680 // #ifdef NO_UART0
1681 if (flashParameters.nouart0) {
1682 myPrintkW("UART0 Disable\r\n");
1683 k_sleep(K_SECONDS(3));
1684 // 1. Disable RX first
1685 err = uart_rx_disable(uart0_dev);
1686 // __ASSERT(err == 0, "Failed to disable uart rx");
1687 if (err == 0) {
1688 myPrintkW("UART0 RX Disabled\r\n");
1689 } else {
1690 myPrintkE("UART0 RX Disable Failed: %d\r\n", err);
1691 }
1692 myPrintkW("UART0 SUSPEND: %d\r\n", err);
1693
1694 // 2. Wait for UART_RX_DISABLED event in your UART callback
1695 // (use a semaphore or flag set in the callback)
1696 k_sem_take(&uart_rx_disabled_sem, K_FOREVER); // Wait for the semaphore to be given in the callback
1697 // 3. Only then suspend the device
1698 err = pm_device_action_run(uart0_dev, PM_DEVICE_ACTION_SUSPEND);
1699 }
1700// #endif
1701#endif
1702
1703 for (;;) {
1704
1705 /* check for CLI commands */
1706 // if (k_sem_take(&cli_cmd_seen, K_MSEC(100)) == 0) {
1707 if (k_sem_take(&cli_cmd_seen, K_NO_WAIT) == 0) {
1708 myPrintk("cli CMD: %s\r\n", cliCMD);
1710 }
1711
1712 /*check for SW2 press */
1713 // if (k_sem_take(&sw2_rdy_seen, K_MSEC(100)) == 0) {
1714 if (k_sem_take(&sw2_rdy_seen, K_NO_WAIT) == 0) {
1715 myPrintk("SW2: %d\r\n", gpio_pin_get(sw2.port, sw2.pin));
1716
1717 // #ifdef SW2STARTSADVERTISING
1718 // /* SW2 seen so start advertising */
1719 // err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); /* start BLE advertising */
1720 // if (err)
1721 // {
1722 // myPrintkE("Advertising failed to start (err %d)", err);
1723 // error();
1724 // }
1725 // myPrintkS("Advertising started (name %s)\r\n", device_name);
1726 // #endif
1727 }
1728
1729 /* Don't go any further until HDC2080 RDY seen */
1730 // k_sem_take(&hdc_rdy_seen, K_FOREVER);
1731
1732 /* check for HDC2080 RDY */
1733 // if (k_sem_take(&hdc_rdy_seen, K_MSEC(100)) == 0) {
1734 if (k_sem_take(&hdc_rdy_seen, K_NO_WAIT) == 0) {
1735 hdc2080RdyHandler(); /* call the HDC2080 RDY handler directly */
1736 } /* end of sem take*/
1737 k_sleep(K_MSEC(100)); /* sleep for 100 ms */
1738 }
1739#endif
1740}
1741
1743 int err = 0;
1744 uint8_t status;
1745 uint8_t byte[2];
1746 uint8_t tempStatus;
1747 uint8_t humidityStatus;
1748 uint8_t intEnables;
1749 // int sectorCount;
1750 myPrintkW("hdc2080RdyHandler called\r\n");
1751
1752 //
1753 // bleLoopCount++; /* update loop count */
1754
1756
1757 // if (flashParameters.silent == false)
1758 {
1759 myPrintkI("\r\nHDC2080 Rdy Seen. Loop Count: %d\r\n", bleLoopCount);
1760
1761 // myPrintkI("meas config: 0x%02X\r\n", byte[0]);
1762 // myPrintkI("Low T: %3.2f High T: %3.2f \r\n", readLowTempThreshold(), readHighTempThreshold());
1763 // myPrintkI("Low H: %3.2f High H: %3.2f \r\n", readLowHumidityThreshold(),
1764 // readHighHumidityThreshold());
1765 }
1766
1767 if (flashParameters.ignoreBME688 == false) {
1768 /* get BME688 data*/
1769 getBME688Data(1, TRUE);
1770 if (flashParameters.silent == false) {
1771 myPrintkI("BME688 Data Read\r\n");
1772 }
1773 }
1774
1775 // int64_t time_ms = k_uptime_get();
1776 // myPrintkW("uptime: %d\r\n", time_ms);
1777 readReg(MEASUREMENT_CONFIG, byte, 1);
1778
1779 status = readInterruptStatus(); /* get current interupt status */
1780 readReg(INTERRUPT_CONFIG, &intEnables, 1); /* get current interup enables */
1781
1782 hdcTemp = readTemp();
1784 if (flashParameters.silent == false) {
1785 myPrintkI("HDC2080 Data Read\r\n");
1786 }
1787 // snprintf(str1, "%3.2f", sizeof(str1), hdcTemp);
1788 // sprintf(str2, "%3.2f", hdcHumidity);
1789 if (flashParameters.silent == false) {
1790 // myPrintkI("Index: %d Temp: %3.2f Humidity: %3.2f 0x%02X\r\n", bleIndex, (double)hdcTemp, (double)hdcHumidity, status);
1791 myPrintkI("gateway Epoch: %s Temp: %d Humidity: %d 0x%02X\r\n", gatewayEpoch, (int)(hdcTemp * 100), (int)(hdcHumidity * 100), status);
1792 }
1793
1794 if (sendingDeviceInfo == true) {
1795 myPrintkW("In the middle of sending device info, skip sending data\r\n");
1796 return; /* skip sending data if we are in the middle of sending device info */
1797 }
1798
1799 /* get interupt state for temp and humidity */
1800 tempStatus = 0;
1801 humidityStatus = 0;
1802 /* set up temp status */
1803 if (status & TL_STATUS) {
1804 tempStatus |= LOWTEMPACTIVE;
1805 }
1806 if (status & TH_STATUS) {
1807 tempStatus |= HIGHTEMPACTIVE;
1808 }
1809 if (intEnables & TL_ENABLE) {
1810 tempStatus |= LOWTEMPENABLE;
1811 }
1812 if (intEnables & TH_ENABLE) {
1813 tempStatus |= HIGHTEMPENABLE;
1814 }
1815
1816 /* set up humidity status */
1817 if (status & HL_STATUS) {
1818 humidityStatus |= LOWHUMIDITYACTIVE;
1819 }
1820 if (status & HH_STATUS) {
1821 humidityStatus |= HIGHHUMIDITYACTIVE;
1822 }
1823 if (intEnables & HL_ENABLE) {
1824 humidityStatus |= LOWHUMIDITYENABLE;
1825 }
1826 if (intEnables & HH_ENABLE) {
1827 humidityStatus |= HIGHHUMIDITYENABLE;
1828 }
1829
1830 if (flashParameters.manualTrigger) { /* if manual trigger sned all */
1831 myPrintkW("Manual Trigger\r\n");
1832
1833 /* send HDC data */
1834 if ((byte[0] & 0x6) == 0x0) /*both temperature and humidity read */
1835 {
1836 // sprintf(myStr,
1837 // sprintf(myStr, "Index: %0d ID: %s t_hdc %3.2f %02X h_hdc %3.2f
1838 //%02X\r\n", bleIndex, devIDStr, hdcTemp, tempStatus, hdcHumidity, humidityStatus);
1839 // sprintf(myStr, "I: %0d ID: %s t %3.2f %02X h %3.2f %02X\r\n", bleIndex, devIDStr, hdcTemp, tempStatus, hdcHumidity,
1840 // humidityStatus);
1841 // sprintf(myStr, "%0d\t%s t1 %3.2f h1 %3.2f", bleIndex, devIDStr, (double)hdcTemp, (double)hdcHumidity);
1842
1843 sprintf(myStr, "%s\t%s t1 %d h1 %d", gatewayEpoch, devIDStr, (int)(hdcTemp * 100), (int)(hdcHumidity * 100));
1844 // sprintf(myStr, "%0d I: %s t %3.2f %02X h %3.2f %d", bleIndex, devIDStr, hdcTemp, tempStatus,
1845 // hdcHumidity, 123456789);
1846 // sprintf(myStr,"0123456789012345678901234567890123456789");
1847 } else if ((byte[0] & 0x6) == 0x2) /* temperature only read */
1848 {
1849 // sprintf(myStr, "I: %0d ID: %s t1 %3.2f\r\n", bleIndex, devIDStr, (double)hdcTemp);
1850 sprintf(myStr, "I: %s ID: %s t1 %d\r\n", gatewayEpoch, devIDStr, (int)(hdcTemp * 100));
1851 } else if ((byte[0] & 0x6) == 0x4) /* humidity only read */
1852 {
1853 // sprintf(myStr, "I: %0d ID: %s h1 %3.2f\r\n", bleIndex, devIDStr, (double)hdcHumidity);
1854 sprintf(myStr, "I: %s ID: %s h1 %d\r\n", gatewayEpoch, devIDStr, (int)(hdcHumidity * 100));
1855 }
1856 if (flashParameters.silent == false) {
1857 myPrintkI("%s\r\n", myStr);
1858 }
1859 bt_nus_send(NULL, myStr, strlen(myStr));
1860 k_sleep(K_SECONDS(2));
1861
1862 if (flashParameters.ignoreBME688 == false) {
1863 /* send BME688 data */
1864 // sprintf(myStr, "%0d %s t %3.2f h %3.2f p %3.2f r %3.2f", bleIndex, devIDStr, BME688Data.temperature,
1865 // BME688Data.humidity, BME688Data.pressure, BME688Data.gas_resistance);
1866 // sprintf(myStr, "%0d\t%s t2 %3.2f h %3.2f", bleIndex, devIDStr, (double)BME688Data.temperature,
1867 // (double)BME688Data.humidity);
1868 sprintf(myStr, "%s\t%s t2 %d h %d", gatewayEpoch, devIDStr, (int)(BME688Data.temperature * 100), (int)(BME688Data.humidity * 100));
1869 // sprintf(myStr, "%0d %s p %3.2f r %3.2f", bleIndex, devIDStr, BME688Data.pressure, BME688Data.gas_resistance);
1870 if (flashParameters.silent == false) {
1871 myPrintkI("%s\r\n", myStr);
1872 }
1873 bt_nus_send(NULL, myStr, strlen(myStr));
1874 k_sleep(K_SECONDS(2));
1875
1876 /* send BME688 data */
1877 // sprintf(myStr, "%0d\t%s p2 %3.2f", bleIndex, devIDStr, BME688Data.pressure);
1878 // sprintf(myStr, "%0d\t%s p2 %d", bleIndex, devIDStr, (int)BME688Data.pressure);
1879 sprintf(myStr, "%s\t%s p2 %d", gatewayEpoch, devIDStr, (int)BME688Data.pressure);
1880 if (flashParameters.silent == false) {
1881 myPrintkI("%s\r\n", myStr);
1882 }
1883 bt_nus_send(NULL, myStr, strlen(myStr));
1884 k_sleep(K_SECONDS(2));
1885
1886 /* send BME688 data */
1887 // sprintf(myStr, "%0d\t%s r2 %3.2f", bleIndex, devIDStr, BME688Data.gas_resistance);
1888 // sprintf(myStr, "%0d\t%s r2 %d", bleIndex, devIDStr, (int)BME688Data.gas_resistance);
1889 sprintf(myStr, "%s\t%s r2 %d", gatewayEpoch, devIDStr, (int)BME688Data.gas_resistance);
1890 if (flashParameters.silent == false) {
1891 myPrintkI("%s\r\n", myStr);
1892 }
1893 bt_nus_send(NULL, myStr, strlen(myStr));
1894 k_sleep(K_SECONDS(2));
1895 }
1896 /* send battery data */
1897 err = adc_sample();
1898 // sprintf(myStr, "%0d\t%s bat %d", bleIndex, devIDStr,
1899 sprintf(myStr, "%s\t%s bat %d", gatewayEpoch, devIDStr,
1900 (int)(adc_voltage[0] * 100)); /* since no battery ADC data just send a dummy value */
1901 if (flashParameters.silent == false) {
1902 myPrintkI("%s\r\n", myStr);
1903 }
1904 bleLoopCount = -1; /* reset loop count */
1905 bt_nus_send(NULL, myStr, strlen(myStr));
1906 k_sleep(K_SECONDS(2));
1907
1908 } else {
1909 // switch ((bleLoopCount & 0x7)) {
1910 // case 0: /* send HDC data */
1911 // if ((byte[0] & 0x6) == 0x0) /*both temperature and humidity read */
1912 // {
1913 // // sprintf(myStr,
1914 // // sprintf(myStr, "Index: %0d ID: %s t_hdc %3.2f %02X h_hdc
1915 // %3.2f
1916 // //%02X\r\n", bleIndex, devIDStr, hdcTemp, tempStatus, hdcHumidity, humidityStatus);
1917 // // sprintf(myStr, "I: %0d ID: %s t %3.2f %02X h %3.2f %02X\r\n", bleIndex, devIDStr, hdcTemp, tempStatus, hdcHumidity,
1918 // // humidityStatus);
1919 // // sprintf(myStr, "%0d\t%s t1 %3.2f h1 %3.2f", bleIndex, devIDStr, (double)hdcTemp, (double)hdcHumidity);
1920 // sprintf(myStr, "%s\t%s t1 %3.2f h1 %3.2f", gatewayEpoch, devIDStr, (double)hdcTemp, (double)hdcHumidity);
1921 // // sprintf(myStr, "%0d I: %s t %3.2f %02X h %3.2f %d", bleIndex, devIDStr, hdcTemp, tempStatus,
1922 // // hdcHumidity, 123456789);
1923 // // sprintf(myStr,"0123456789012345678901234567890123456789");
1924 // } else if ((byte[0] & 0x6) == 0x2) /* temperature only read */
1925 // {
1926 // // sprintf(myStr, "I: %0d ID: %s t1 %3.2f\r\n", bleIndex, devIDStr, (double)hdcTemp);
1927 // sprintf(myStr, "I: %s ID: %s t1 %3.2f\r\n", gatewayEpoch, devIDStr, (double)hdcTemp);
1928 // } else if ((byte[0] & 0x6) == 0x4) /* humidity only read */
1929 // {
1930 // // sprintf(myStr, "I: %0d ID: %s h1 %3.2f\r\n", bleIndex, devIDStr, (double)hdcHumidity);
1931 // sprintf(myStr, "I: %s ID: %s h1 %3.2f\r\n", gatewayEpoch, devIDStr, (double)hdcHumidity);
1932 // }
1933 // break;
1934 //
1935 // case 1: /* send BME688 data */
1936 // // sprintf(myStr, "%0d %s t %3.2f h %3.2f p %3.2f r %3.2f", bleIndex, devIDStr, BME688Data.temperature,
1937 // // BME688Data.humidity, BME688Data.pressure, BME688Data.gas_resistance);
1938 // // sprintf(myStr, "%0d\t%s t2 %3.2f h %3.2f", bleIndex, devIDStr, (double)BME688Data.temperature,
1939 // // (double)BME688Data.humidity);
1940 // sprintf(myStr, "%s\t%s t2 %3.2f h %3.2f", gatewayEpoch, devIDStr, (double)BME688Data.temperature, (double)BME688Data.humidity);
1941 // // sprintf(myStr, "%0d %s p %3.2f r %3.2f", bleIndex, devIDStr, BME688Data.pressure, BME688Data.gas_resistance);
1942 // if (flashParameters.silent == false) {
1943 // myPrintkI("%s\r\n", myStr);
1944 // }
1945 // break;
1946 //
1947 // case 2: /* send BME688 data */
1948 // // sprintf(myStr, "%0d\t%s p2 %3.2f", bleIndex, devIDStr, BME688Data.pressure);
1949 // // sprintf(myStr, "%0d\t%s p2 %d", bleIndex, devIDStr, (int)BME688Data.pressure);
1950 // sprintf(myStr, "%s\t%s p2 %d", gatewayEpoch, devIDStr, (int)BME688Data.pressure);
1951 // if (flashParameters.silent == false) {
1952 // myPrintkI("%s\r\n", myStr);
1953 // }
1954 // break;
1955 //
1956 // case 3: /* send BME688 data */
1957 // // sprintf(myStr, "%0d\t%s r2 %3.2f", bleIndex, devIDStr, BME688Data.gas_resistance);
1958 // // sprintf(myStr, "%0d\t%s r2 %d", bleIndex, devIDStr, (int)BME688Data.gas_resistance);
1959 // sprintf(myStr, "%s\t%s r2 %d", gatewayEpoch, devIDStr, (int)BME688Data.gas_resistance);
1960 // if (flashParameters.silent == false) {
1961 // myPrintkI("%s\r\n", myStr);
1962 // }
1963 // break;
1964 //
1965 // case 4: /* send battery data */
1966 // err = adc_sample();
1967 // // sprintf(myStr, "%0d\t%s bat %d", bleIndex, devIDStr,
1968 // sprintf(myStr, "%s\t%s bat %d", gatewayEpoch, devIDStr,
1969 // (int)(adc_voltage[0] * 100)); /* since no battery ADC data just send a dummy value */
1970 // if (flashParameters.silent == false) {
1971 // myPrintkI("%s\r\n", myStr);
1972 // }
1973 // bleLoopCount = -1; /* reset loop count */
1974 // break;
1975 // } /* end of switch statement */
1976 //
1977 // if (flashParameters.silent == false) {
1978 // // if (status & DRDY_STATUS)
1979 // // myPrintkI("DRDY Set\r\n");
1980 // if (status & TH_STATUS)
1981 // myPrintkI("Temp High Set\r\n");
1982 // if (status & TL_STATUS)
1983 // myPrintkI("Temp Low Set\r\n");
1984 // if (status & HH_STATUS)
1985 // myPrintkI("Humidity High Set\r\n");
1986 // if (status & HL_STATUS)
1987 // myPrintkI("Humidity Low Set\r\n");
1988 // }
1989 //
1990 // if (flashParameters.dutyCycle > 7) {
1991 // hdcMinutes--;
1992 // if (hdcMinutes != 0) {
1993 // return; /* minutes timer not expired */
1994 // } else {
1995 // hdcMinutes = flashParameters.dutyCycle - 7;
1996 // }
1997 // }
1998 // #if 1
1999 // // if ((bleLoopCount & 0x3) == 0)
2000 // {
2001 // bleIndex++; /* update the BLE index counter */
2002 // if (bt_nus_send(NULL, myStr, strlen(myStr))) {
2003 // /* save BLE packet if failed to send */
2004 // if (flashParameters.savedCount < MAX_NUMBER_BLE_PACKETS) {
2005 // memset(tmpData, 0, 256);
2006 // strcpy(tmpData, myStr); /* copy string that did not get sent to empty buffer*/
2007 // flashxWritePage(FLASHBLESTART + flashParameters.nextSavedWrite, 0, tmpData, 256); /* save in flash and update write
2008 // address*/ flashParameters.savedCount++; flashParameters.nextSavedWrite++; setFlashxParameters(false); myPrintkW("BLE packet
2009 // saved to Flash Memory %d of %d\r\n", flashParameters.savedCount, MAX_NUMBER_BLE_PACKETS);
2010 // } else {
2011 // myPrintkW("BLE packet saved Flash Memory full\r\n");
2012 // }
2013 // if (flashParameters.silent == false) {
2014 // myPrintkW("Failed to send data over BLE connection: %d %s\r\n", strlen(myStr), myStr);
2015 // }
2016 // } else {
2017 // /* packet sent correctly */
2018 // if (flashParameters.silent == false) {
2019 // if (flashParameters.savedCount > 0) {
2020 // while (flashParameters.savedCount > 0) {
2021 //
2022 // // k_sleep(K_SECONDS(1)); /* send next saved packet since connection is
2023 // // valid again */
2024 // flashxReadPage(flashParameters.nextSavedRead + FLASHBLESTART, flashReadIn);
2025 // strcpy(myStr, flashReadIn);
2026 // flashParameters.savedCount--;
2027 // flashParameters.nextSavedRead++;
2028 // setFlashxParameters(false);
2029 // bt_nus_send(NULL, myStr, strlen(myStr)); /* send saved packet*/
2030 // myPrintkS("Sent saved data over BLE connection: %s\r\n", myStr);
2031 // }
2032 //
2033 // /* all saved packets have been sent so clear BLE saved packet memory */
2034 // flashParameters.nextSavedRead = 0;
2035 // flashParameters.nextSavedWrite = 0;
2036 // flashParameters.savedCount = 0;
2037 // myPrintkI("Saved JSON Packets Cleared\r\n");
2038 // setFlashxParameters(false);
2039 // sectorCount = (MAX_NUMBER_BLE_PACKETS / 0x10) + 1; /* get number of sectors needed for number of BLE packets*/
2040 // for (int i = 0; i < sectorCount; i++) {
2041 // flashxEraseSector((FLASHBLESTART / 0x10) + i); /* erase the next sector */
2042 // }
2043 // }
2044 // myPrintkS("Sent data over BLE connection: %d %s\r\n", strlen(myStr), myStr);
2045 // }
2046 // }
2047 // }
2048 // #endif
2049 }
2050}
2051
2053#if 0
2054 /* Don't go any further until BLE is initialized */
2055 k_sem_take(&ble_init_ok, K_FOREVER);
2056 struct uart_data_t nus_data = {
2057 .len = 0,
2058 };
2059
2060 for (;;)
2061 {
2062 /* Wait indefinitely for data to be sent over bluetooth */
2063 struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
2064 K_FOREVER);
2065
2066 int plen = MIN(sizeof(nus_data.data) - nus_data.len, buf->len);
2067 int loc = 0;
2068
2069 while (plen > 0)
2070 {
2071 memcpy(&nus_data.data[nus_data.len], &buf->data[loc], plen);
2072 nus_data.len += plen;
2073 loc += plen;
2074
2075 if (nus_data.len >= sizeof(nus_data.data) ||
2076 (nus_data.data[nus_data.len - 1] == '\n') ||
2077 (nus_data.data[nus_data.len - 1] == '\r'))
2078 {
2079 if (bt_nus_send(NULL, nus_data.data, nus_data.len))
2080 {
2081 LOG_WRN("Failed to send data over BLE connection");
2082 }
2083 nus_data.len = 0;
2084 }
2085
2086 plen = MIN(sizeof(nus_data.data), buf->len - loc);
2087 }
2088
2089 k_free(buf);
2090 }
2091#else
2092 uint8_t myBuff[128];
2093 // uint8_t status;
2094 int i;
2095 // uint8_t str[120];
2096
2097 /* Don't go any further until BLE is initialized */
2098 k_sem_take(&ble_init_ok, K_FOREVER);
2099 struct uart_data_t nus_data = {
2100 .len = 0,
2101 };
2102
2103 for (;;) {
2104 /* Wait indefinitely for data to be sent over bluetooth */
2105 struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data, K_FOREVER); /* get uart data */
2106
2107 int plen = MIN(sizeof(nus_data.data) - nus_data.len, buf->len);
2108 int loc = 0;
2109
2110 memset(myBuff, 0, sizeof(myBuff)); /* clear UART recved buffer */
2111 while (plen > 0) {
2112 memcpy(&nus_data.data[nus_data.len], &buf->data[loc], plen);
2113 nus_data.len += plen;
2114 loc += plen;
2115
2116 /* wait for CR or LF */
2117 if (nus_data.len >= sizeof(nus_data.data) || (nus_data.data[nus_data.len - 1] == '\n') || (nus_data.data[nus_data.len - 1] == '\r')) {
2118 nus_data.data[nus_data.len - 1] = '\0';
2119 nus_data.len--;
2120 // printf("RX buf len: %d %s\r\n", nus_data.len, nus_data.data);
2121 strncpy(myBuff, nus_data.data, nus_data.len);
2122 for (i = 0; i < strlen(myBuff); i++) {
2123 if ((myBuff[i] == '\r') || (myBuff[i] == '\n'))
2124 myBuff[i] = '\0';
2125 // printf("i: %d 0x%02X %c\r\n",i,myBuff[i],myBuff[i]);
2126 }
2127 // int len = strlen(myBuff);
2128 strcpy(cliCMD, myBuff);
2129 // executeCmd(myBuff);
2130 k_sem_give(&cli_cmd_seen); /* indicate HDC2080 RDY seen */
2131 // if (bt_nus_send(NULL, nus_data.data, nus_data.len))
2132 // {
2133 // LOG_WRN("Failed to send data over BLE connection");
2134 // }
2135 nus_data.len = 0;
2136 }
2137
2138 plen = MIN(sizeof(nus_data.data), buf->len - loc);
2139 }
2140
2141 k_free(buf);
2142 }
2143#endif
2144}
2145
2146/* TJM added functions */
2147/*!
2148 * \fn int init_i2c()
2149 * \brief Initializes the I2C interface
2150 * \return TRUE if successful, FALSE otherwise
2151 * This function initializes the I2C interface by configuring the I2C peripheral with the specified speed and mode. It checks if the I2C
2152 device is ready and then configures it. If any step fails, it returns FALSE; otherwise, it returns TRUE to indicate successful
2153 initialization.
2154 *
2155 * Note: The I2C speed is set to fast mode, and the device is configured as a controller. The function also includes debug print statements
2156 to indicate the status of the initialization process.
2157
2158 *
2159 */
2161 uint32_t i2c_cfg = I2C_SPEED_SET(I2C_SPEED_FAST) | I2C_MODE_CONTROLLER;
2162
2163 myPrintk("*** I2C Init ***\r\n");
2164 myPrintkS("Initializing I2C device\r\n");
2165
2166 if (!device_is_ready(i2c_dev)) /* check if I2C peripheral ready */
2167 {
2168 myPrintkE("I2C device is not ready\n");
2169 return FALSE;
2170 }
2171 myPrintkI("I2C device is ready\n");
2172
2173 /* 1. verify i2c_configure() */
2174 if (i2c_configure(i2c_dev, i2c_cfg)) /* configure I2C peripheral */
2175 {
2176 myPrintkE("I2C config failed\n");
2177 return FALSE;
2178 }
2179 myPrintkI("I2C config passed %08X\n", i2c_cfg);
2180 return TRUE;
2181}
2182
2183/*!
2184 * \fn void hdc2080_rdy_seen(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
2185 * \brief Callback function for HDC2080 RDY pin
2186 * \param dev Pointer to the device structure
2187 * \param cb Pointer to the GPIO callback structure
2188 * \param pins GPIO pin mask
2189 * This function is a callback that is triggered when the HDC2080 RDY pin is activated. It checks if the specific pin associated with the
2190 * HDC2080 is part of the pins that triggered the callback. If it is, it gives a semaphore to indicate that the HDC2080 RDY signal has been
2191 * seen, allowing other parts of the program to proceed with reading data from the sensor or performing other actions that depend on the RDY
2192 * signal. The function includes commented-out code for debugging purposes, which can be used to print the state of the pin and the pins
2193 * that triggered the callback.
2194 *
2195 */
2196void hdc2080_rdy_seen(const struct device *dev, struct gpio_callback *cb, uint32_t pins) {
2197 // int pinx,piny;
2198
2199 if (BIT(hdc2080.pin) & pins) {
2200 // pinx = gpio_pin_get_raw(hdc2080.port,hdc2080.pin);
2201 // piny = gpio_pin_get(hdc2080.port,hdc2080.pin);
2202 // printf("Button %d %d %08X pressed at %" PRIu32 "\n",pinx, piny, pins, k_cycle_get_32());
2203 /* show RX received */
2204 k_sem_give(&hdc_rdy_seen); /* indicate HDC2080 RDY seen */
2205 }
2206}
2207
2208/*!
2209 * \fn void sw2_seen(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
2210 * \brief Callback function for SW2 button
2211 * \param dev Pointer to the device structure
2212 * \param cb Pointer to the GPIO callback structure
2213 * \param pins GPIO pin mask
2214 * This function is a callback that is triggered when the SW2 button is pressed. It checks if the specific pin associated with the SW2
2215 * button is part of the pins that triggered the callback. If it is, it gives a semaphore to indicate that the SW2 button has been seen,
2216 * allowing other parts of the program to proceed with actions that depend on the SW2 button press. The function includes commented-out code
2217 * for debugging purposes, which can be used to print the state of the pin and the pins that triggered the callback.
2218 */
2219void sw2_seen(const struct device *dev, struct gpio_callback *cb, uint32_t pins) {
2220 // int pinx,piny;
2221
2222 if (BIT(sw2.pin) & pins) {
2223 k_sem_give(&sw2_rdy_seen); /* indicate HDC2080 RDY seen */
2224 }
2225}
2226
2227/**
2228 * \fn uint8_t bleCommand(uint8_t *data)
2229 * \brief Executes a BLE command
2230 * \param data Pointer to the command data
2231 * \return TRUE if the command is executed successfully, FALSE otherwise
2232 * This function takes a pointer to the command data received over BLE, processes it, and executes the corresponding command. It includes
2233 * debug print statements to indicate the received command and its length. The function can be expanded to include specific command parsing
2234 * and execution logic based on the content of the data. In the provided code, there is a placeholder for command execution, and the actual
2235 * implementation can be added as needed. The function currently returns TRUE to indicate that the command has been processed, but this can
2236 * be modified to return FALSE if the command is invalid or if there is an error during execution.
2237 *
2238 */
2239uint8_t bleCommand(uint8_t *data) {
2240// myPrintkI("\r\n BLE Command: %s Len %d\r\n", data, strlen(data));
2241#if 0
2242 int cmd;
2243
2244 cmd = getCmd(data);
2245 myPrintkI("cmd: %d numParameters: %d ", cmd, numParameters);
2246 // for(int i=0;i< numParameters;i++)
2247 // {
2248 // printf("i: %d %s\r\n",i,cmdLineParameter[i]);
2249 // }
2250
2251 /* execute BLE command */
2252 switch (cmd)
2253 {
2254 case CR:
2255 myPrintkI("Conv Rate %d\r\n", atoi(cmdLineParameter[1]));
2256 setRate(atoi(cmdLineParameter[1])); /* set auto conversion rate */
2257 break;
2258
2259 default:
2260 myPrintkW("unknown BLE command %s\r\n", data);
2261 }
2262#else
2263 myPrintkS("BLE Command: %s Len %d\r\n", data, strlen(data));
2264 data[strlen(data) - 2] = '\0';
2266#endif
2267 return TRUE;
2268}
2269
2270/*!
2271 * \fn void rescan(void)
2272 * \brief rescan all I2C and SPI devices
2273 *
2274 * This function rescans all I2C and SPI devices by calling the initialization functions for each device. It checks if the HDC2080,
2275 * W25Q64JV, and BME688 devices are available and properly initialized. If any of the initialization functions fail, it can be modified to
2276 * handle the error accordingly. The function includes calls to the initialization functions for each device and can be expanded to include
2277 * additional devices as needed. The current implementation assumes that the initialization functions will handle any necessary error
2278 * reporting and that the rescan function will simply call them in sequence.
2279 *
2280 */
2281void rescan(void) {
2282 int err;
2283
2284 err = initHDC2080(); /* check if HDC2080 available */
2285
2286 err = initW25Q64JV(); /* check if W25Q64JV available */
2287
2288 if (flashParameters.ignoreBME688 == false) {
2289 err = initBME688(); /* check if BME688 available */
2290 }
2291 return;
2292}
2293
2294/**
2295 * \fn void myPrintk(char *str)
2296 *
2297 * \brief prints a string to the UART
2298 *
2299 * @param str ASCII string to print
2300 *
2301 * \return HAL_OK if passed<p>
2302 *
2303 */
2304// void myPrintk(char *str)
2305//{
2306// printk("%s", str);
2307// return;
2308// }
2309
2310int myPrintk(char *restrict fmt, ...) {
2311 int n = 0;
2312#if CONFIG_SERIAL
2313 va_list ap;
2314
2315 va_start(ap, fmt);
2316 n = vprintf(fmt, ap);
2317 va_end(ap);
2318#endif
2319 return n;
2320}
2321
2322/*
2323 * Black \033[0;30m.
2324 * Red \033[0;31m.
2325 * Green \033[0;32m.
2326 * Yellow \033[0;33m.
2327 * Blue \033[0;34m.
2328 * Purple \033[0;35m.
2329 * Cyan \033[0;36m.
2330 * White \033[0;37m.
2331 */
2332
2333/* yellow (Warning)*/
2334// void myPrintkW(char *str)
2335//{
2336// printk("%s", "\33[1;33m");
2337// printk("%s", str);
2338// // printk("%s", myStr);
2339// printk("%s", "\33[0m");
2340// return;
2341// }
2342
2343/*!
2344 * \fn int myPrintkW(char *restrict fmt, ...)
2345 * \brief prints a warning message to the UART
2346 * \param fmt format string
2347 * \return number of characters printed
2348 * This function prints a warning message to the UART in yellow color. It takes a format string and additional arguments, similar to printf,
2349 * and formats the message accordingly. The function uses ANSI escape codes to set the text color to yellow before printing the message and
2350 * resets it back to default afterward. The number of characters printed is returned as an integer.
2351 *
2352 */
2353int myPrintkW(char *restrict fmt, ...) {
2354 int n = 0;
2355#if CONFIG_SERIAL
2356 va_list ap;
2357
2358 printk("\33[1;33m");
2359 va_start(ap, fmt);
2360 vprintk(fmt, ap);
2361 va_end(ap);
2362 printk("\33[0m");
2363#endif
2364 return n;
2365}
2366
2367/* Green (Information)*/
2368// void myPrintkI(char *str)
2369//{
2370// printk("%s", "\33[1;32m");
2371// printk("%s", str);
2372// printk("%s", "\33[0m");
2373// return;
2374// }
2375
2376/*!
2377 * \fn int myPrintkI(char *restrict fmt, ...)
2378 * \brief prints an information message to the UART
2379 * \param fmt format string
2380 * \return number of characters printed
2381 * This function prints an information message to the UART in green color. It takes a format string and additional arguments, similar to
2382 * printf, and formats the message accordingly. The function uses ANSI escape codes to set the text color to green before printing the
2383 * message and resets it back to default afterward. The number of characters printed is returned as an integer.
2384 *
2385 */
2386int myPrintkI(char *restrict fmt, ...) {
2387 int n = 0;
2388#if CONFIG_SERIAL
2389 va_list ap;
2390
2391 printk("\33[1;32m");
2392 va_start(ap, fmt);
2393 vprintk(fmt, ap);
2394 va_end(ap);
2395 printk("\33[0m");
2396#endif
2397 return n;
2398}
2399
2400/* CYAN (Status)*/
2401// void myPrintkS(char *str)
2402//{
2403// printk("%s", "\33[1;36m");
2404// printk("%s", str);
2405// printk("%s", "\33[0m");
2406// return;
2407// }
2408
2409/*!
2410 * \fn int myPrintkS(char *restrict fmt, ...)
2411 * \brief prints a status message to the UART
2412 * \param fmt format string
2413 * \return number of characters printed
2414 * This function prints a status message to the UART in cyan color. It takes a format string and additional arguments, similar to printf,
2415 * and formats the message accordingly. The function uses ANSI escape codes to set the text color to cyan before printing the message and
2416 * resets it back to default afterward. The number of characters printed is returned as an integer.
2417 *
2418 */
2419int myPrintkS(char *restrict fmt, ...) {
2420 int n = 0;
2421#if CONFIG_SERIAL
2422 va_list ap;
2423
2424 printk("\33[1;36m");
2425 va_start(ap, fmt);
2426 vprintk(fmt, ap);
2427 va_end(ap);
2428 printk("\33[0m");
2429#endif
2430 return n;
2431}
2432
2433/* Red (Error)*/
2434// void myPrintkE(char *str)
2435//{
2436// printk("%s", "\33[1;31m");
2437// printk("%s", str);
2438// printk("%s", "\33[0m");
2439// return;
2440// }
2441
2442/*!
2443 * \fn int myPrintkE(char *restrict fmt, ...)
2444 * \brief prints an error message to the UART
2445 * \param fmt format string
2446 * \return number of characters printed
2447 * This function prints an error message to the UART in red color. It takes a format string and additional arguments, similar to printf,
2448 * and formats the message accordingly. The function uses ANSI escape codes to set the text color to red before printing the message and
2449 * resets it back to default afterward. The number of characters printed is returned as an integer.
2450 *
2451 */
2452int myPrintkE(char *restrict fmt, ...) {
2453 int n = 0;
2454#if CONFIG_SERIAL
2455 va_list ap;
2456
2457 printk("\33[1;31m");
2458 va_start(ap, fmt);
2459 vprintk(fmt, ap);
2460 va_end(ap);
2461 printk("\33[0m");
2462#endif
2463 return n;
2464}
2465
2466K_THREAD_DEFINE(ble_write_thread_id, STACKSIZE, ble_write_thread, NULL, NULL, NULL, PRIORITY, 0, 0);
uint8_t readReg(uint8_t reg, uint8_t *data, uint8_t count)
Reads a specified number of bytes from a sensor register over I2C.
Definition HDC2080.c:172
void setRate(int rate)
Sets the automatic measurement frequency.
Definition HDC2080.c:585
float readHumidity(void)
Reads the relative humidity from the HDC2080 sensor.
Definition HDC2080.c:79
int initHDC2080(void)
Initializes the HDC2080 sensor with default parameters.
Definition HDC2080.c:839
float readTemp(void)
Reads the temperature data from the HDC2080 sensor.
Definition HDC2080.c:24
uint8_t readInterruptStatus(void)
Reads the interrupt status register.
Definition HDC2080.c:702
#define TL_STATUS
Definition HDC2080.h:44
#define HH_ENABLE
Definition HDC2080.h:49
#define HL_STATUS
Definition HDC2080.h:46
#define INTERRUPT_CONFIG
Definition HDC2080.h:60
#define MANUAL
Definition HDC2080.h:30
#define MEASUREMENT_CONFIG
Definition HDC2080.h:68
#define ONE_MINS
Definition HDC2080.h:32
#define HH_STATUS
Definition HDC2080.h:45
#define HL_ENABLE
Definition HDC2080.h:50
#define TH_STATUS
Definition HDC2080.h:43
#define TH_ENABLE
Definition HDC2080.h:47
#define TL_ENABLE
Definition HDC2080.h:48
int initBME688(void)
Initializes the BME688 sensor over SPI. Performs interface initialization, device reset,...
Definition bme68x.c:1831
int getBME688Data(int count, uint8_t quiet)
Triggers and retrieves measurement data from the BME688.
Definition bme68x.c:1916
struct spi_config spi_cfg1
SPI configuration.
Definition globals.c:91
struct spi_buf tx_bufs[]
SPI TX buffer structure.
Definition globals.c:111
const struct spi_buf_set rx
SPI RX buffer structure.
Definition globals.c:127
float hdcHumidity
Definition globals.c:26
const struct device *const spi_dev
Definition globals.c:79
flashParametersStruct flashParameters
working valuses of flash parameters in RAM
Definition globals.c:35
char cliCMD[40]
Definition globals.c:45
char gatewayEpoch[20]
Definition globals.c:48
uint32_t bleIndex
Definition globals.c:37
float adc_voltage[2]
last ADC voltage read [0] battery
Definition globals.c:31
int ret
Definition globals.c:41
const struct gpio_dt_spec spics2n
Definition globals.c:63
struct spi_config spi_cfg2
SPI configuration.
Definition globals.c:101
uint8_t buffer_tx[SPI_BUF_SIZE+8]
SPI transmit buffer.
Definition globals.c:42
uint8_t sendingDeviceInfo
flag to indicate sending device info in BLE packet instead of sensor data
Definition globals.c:46
long long gatewayDateTime
Definition globals.c:47
char * cmdLineParameter[MAX_PARAMETERS]
array of pointers to command line parameter strings
Definition globals.c:27
struct bme68x_data BME688Data
Definition globals.c:44
uint8_t hdcMinutes
Definition globals.c:39
char resetCause[100]
Definition globals.c:33
struct spi_buf rx_bufs[]
SPI RX buffer structure.
Definition globals.c:118
const struct spi_buf_set tx
SPI TX buffer structure.
Definition globals.c:125
char devIDStr[70]
Definition globals.c:29
uint8_t numParameters
Definition globals.c:28
char myStr[256]
Definition globals.c:34
const struct gpio_dt_spec spics1n
Definition globals.c:55
float hdcTemp
Definition globals.c:25
COMMANDS
< vaild command indexes
void executeCmd(char *line)
executes the command in line array.
int uart_init(void)
void int64_to_string(int64_t num, char *str)
Converts a 64-bit signed integer to a null-terminated string.
common struct, enum, externs, prototypes
#define BOARD_NAME
Definition jfet_common.h:34
#define HIGHTEMPACTIVE
Definition jfet_common.h:59
void sw2_seen(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
Callback function for SW2 button.
Definition main.c:2219
#define VERSION_MAJOR
Definition jfet_common.h:30
#define HIGHHUMIDITYACTIVE
Definition jfet_common.h:63
void displayFlashxParameters(void)
displays the NV flash parameters.
Definition w25q64jv.c:1021
#define VERSION_DATE
Definition jfet_common.h:33
void flashxClearParameters(void)
clears/initializes the flash parameters in RAM
Definition w25q64jv.c:939
#define VERSION_DATE_EXT2
Definition jfet_common.h:37
int initW25Q64JV(void)
Initiailizes the W25Q64JW.
Definition w25q64jv.c:1254
#define LOWHUMIDITYACTIVE
Definition jfet_common.h:61
#define VERSION_DATE_EXT3
Definition jfet_common.h:38
struct k_sem uart_rx_disabled_sem
struct k_sem hdc_rdy_seen
#define EXPAND_AND_STR(x)
Definition jfet_common.h:54
#define LOWTEMPENABLE
Definition jfet_common.h:56
#define FLASHPARAMETERKEY
Definition jfet_common.h:79
void hdc2080_rdy_seen(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
Callback function for HDC2080 RDY pin.
Definition main.c:2196
const struct device *const i2c_dev
get the device structure for the I2C device defined by I2C_DEV_NODE
Definition main.c:106
#define VERSION_DATE_EXT1
Definition jfet_common.h:36
const struct gpio_dt_spec baten
get the GPIO specification for the BATEN pin defined by BATEN_NODE
Definition main.c:175
#define TRUE
Definition jfet_common.h:42
#define FALSE
Definition jfet_common.h:41
#define HIGHTEMPENABLE
Definition jfet_common.h:58
const struct device *const uart0_dev
void setFlashxParameters(uint8_t display)
loads the NV Flash parameters from teh RAM flash parameters
Definition w25q64jv.c:1122
#define HIGHHUMIDITYENABLE
Definition jfet_common.h:62
void readNVFlashxStatus(uint8_t *flashStatus)
reads the 3 NV Flash status registers over the SPI bus.
Definition w25q64jv.c:61
#define BOARD_NAME_EXT
Definition jfet_common.h:39
#define LOWTEMPACTIVE
Definition jfet_common.h:57
#define VERSION_MINOR
Definition jfet_common.h:31
#define LOWHUMIDITYENABLE
Definition jfet_common.h:60
void getFlashparameters(void)
Read the stored flash parameter block from serial flash.
Definition w25q64jv.c:1183
int getCmd(uint8_t *line)
#define ADC_RESOLUTION
resolution for ADC readings in bits (e.g., 10 bits for values from 0 to 1023)
Definition main.c:220
int myPrintk(char *restrict fmt,...)
Definition main.c:2310
#define ADC_DIV_MV
Definition main.c:315
#define ADC_REF_MV
Definition main.c:314
void sw2_seen(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
Callback function for SW2 button.
Definition main.c:2219
char const * validCmds[]
array of valid commands - case insensitive
Definition main.c:383
static struct bt_conn_auth_cb conn_auth_callbacks
Definition main.c:971
static void disconnected(struct bt_conn *conn, uint8_t reason)
Callback function for when a Bluetooth connection is lost.
Definition main.c:801
#define ADC_4TH_CHANNEL_ID
channel ID for the fourth ADC channel to read, set to 3 for the fourth channel (e....
Definition main.c:241
K_THREAD_DEFINE(ble_write_thread_id, STACKSIZE, ble_write_thread, NULL, NULL, NULL, PRIORITY, 0, 0)
#define STACKSIZE
stack size for main thread
Definition main.c:60
#define PRIORITY
priority for main thread
Definition main.c:61
static void adv_work_handler(struct k_work *work)
Handler for the advertising work item.
Definition main.c:748
#define ADC_2ND_CHANNEL_INPUT
Definition main.c:234
#define ADC_GAIN
Definition main.c:221
static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
Callback function for receiving data over Bluetooth.
Definition main.c:982
#define ADC_REFERENCE
reference voltage for ADC readings, set to internal reference for stable and consistent measurements
Definition main.c:224
static void configure_gpio(void)
Definition main.c:1166
const struct device *const adc_dev
get the device structure for the ADC device defined by ADC_DEV_NODE
Definition main.c:254
static struct bt_data ad[2]
Definition main.c:416
#define ADC_MAX_VAL
Definition main.c:316
int myPrintkS(char *restrict fmt,...)
prints a status message to the UART
Definition main.c:2419
#define UART_WAIT_FOR_RX
Definition main.c:76
static const float adc_volts_per_step
Definition main.c:318
#define CON_STATUS_LED
LED to indicate the BLE connection status.
Definition main.c:69
#define KEY_PASSKEY_ACCEPT
Button used to accept a pairing passkey.
Definition main.c:71
#define UART_WAIT_FOR_BUF_DELAY
delay to wait for UART buffer availability in milliseconds
Definition main.c:75
static void recycled_cb(void)
Callback function for when a Bluetooth connection object is recycled.
Definition main.c:829
int adc_sample(void)
get a single reading from ADC channel
Definition main.c:343
void hdc2080RdyHandler(void)
< check if i2c_0 alias is okay in devicetree
Definition main.c:1742
void error(void)
Function to handle fatal errors This function is called when a fatal error occurs in the system....
Definition main.c:1107
static struct gpio_callback hdc2080_cb_data
GPIO callback structure for handling HDC2080 ready pin interrupts.
Definition main.c:187
int myPrintkI(char *restrict fmt,...)
prints an information message to the UART
Definition main.c:2386
#define DEVICE_NAME_LEN
length of device name
Definition main.c:64
#define DEVICE_NAME
device name defined in prj.conf
Definition main.c:63
#define ADC_BUFFER_SIZE
number of ADC channels to read
Definition main.c:211
static struct bt_nus_cb nus_cb
Bluetooth NUS callbacks This structure defines the callbacks for Bluetooth NUS events,...
Definition main.c:1095
#define BATEN_NODE
check if BATEN_NODE is okay in devicetree
Definition main.c:171
@ CR
Definition main.c:379
@ NONE
Definition main.c:380
#define RUN_STATUS_LED
LED to indicate the application is running.
Definition main.c:66
static struct k_work adv_work
work item for handling BLE advertising operations, used to schedule advertising tasks in the system w...
Definition main.c:120
static struct bt_conn_auth_info_cb conn_auth_info_callbacks
Definition main.c:972
void hdc2080_rdy_seen(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
Callback function for HDC2080 RDY pin.
Definition main.c:2196
int main(void)
Nordic UART Bridge Service (NUS) sample (BLE_Prototype) starting point.
Definition main.c:1199
#define ADC_3RD_CHANNEL_ID
channel ID for the third ADC channel to read, set to 2 for the third channel (e.g....
Definition main.c:237
int myPrintkE(char *restrict fmt,...)
prints an error message to the UART
Definition main.c:2452
#define SW2_NODE
check if SW2_NODE is okay in devicetree
Definition main.c:191
char device_name[40]
buffer to hold the device name string, used for BLE advertising and identification
Definition main.c:371
BT_CONN_CB_DEFINE(conn_callbacks)
Bluetooth connection callbacks.
uint8_t bleCommand(uint8_t *data)
Executes a BLE command.
Definition main.c:2239
static int16_t m_sample_buffer[ADC_BUFFER_SIZE]
buffer to receive ADC data from configured channels
Definition main.c:312
void ble_write_thread(void)
Definition main.c:2052
static const struct gpio_dt_spec hdc2080
get the GPIO specification for the HDC2080 ready pin defined by HDC2080RDY_NODE
Definition main.c:185
void rescan(void)
rescan all I2C and SPI devices
Definition main.c:2281
static K_FIFO_DEFINE(fifo_uart_tx_data)
int init_i2c()
Initializes the I2C interface.
Definition main.c:2160
#define ADC_3RD_CHANNEL_INPUT
Definition main.c:238
#define ADC_1ST_CHANNEL_ID
channel ID for the first ADC channel to read, set to 0 for the first channel (e.g....
Definition main.c:229
#define UART_BUF_SIZE
size of the buffer for UART data
Definition main.c:74
static void connected(struct bt_conn *conn, uint8_t err)
Callback function for when a Bluetooth connection is established.
Definition main.c:776
#define KEY_PASSKEY_REJECT
Button used to reject a pairing passkey.
Definition main.c:72
int bleLoopCount
Definition main.c:1182
static float adc_raw_to_voltage(uint16_t raw)
Convert raw ADC reading to voltage in volts.
Definition main.c:330
#define HDC2080RDY_NODE
check if HDC2080RDY_NODE is okay in devicetree
Definition main.c:180
static const struct bt_data sd[]
Definition main.c:421
#define ADC_4TH_CHANNEL_INPUT
Definition main.c:242
static const struct gpio_dt_spec sw2
get the GPIO specification for the SW2 button pin defined by SW2_NODE
Definition main.c:195
#define ADC_2ND_CHANNEL_ID
channel ID for the second ADC channel to read, set to 1 for the second channel (e....
Definition main.c:233
static void advertising_start(void)
Start the advertising process.
Definition main.c:764
uint8_t device_name_len
length of the device name string, used to ensure proper formatting and transmission in BLE advertisin...
Definition main.c:372
#define ADC_ACQUISITION_TIME
Definition main.c:226
#define ADC_1ST_CHANNEL_INPUT
Definition main.c:230
LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG)
static struct bt_conn * current_conn
Definition main.c:116
int myPrintkW(char *restrict fmt,...)
prints a warning message to the UART
Definition main.c:2353
static const struct adc_channel_cfg m_1st_channel_cfg
ADC configuration for the first channel This structure defines the configuration for the first ADC ch...
Definition main.c:301
static K_SEM_DEFINE(ble_init_ok, 0, 1)
semaphore to indicate when BLE initialization is complete and the system is ready for BLE operations
static struct bt_conn * auth_conn
Definition main.c:118
static struct gpio_callback sw2_cb_data
GPIO callback structure for handling SW2 button pin interrupts.
Definition main.c:197
#define RUN_LED_BLINK_INTERVAL
interval for blinking the run status LED in milliseconds
Definition main.c:67
Flash parameters structure.
Definition jfet_common.h:90
void * fifo_reserved
Definition main.c:399
uint8_t data[UART_BUF_SIZE]
Definition main.c:400
uint16_t len
Definition main.c:401
int watchdog_init_and_start(void)
Initialize and start the watchdog timer.
Watchdog module for Asset Tracker v2.