├── .gitignore ├── README.rst ├── custom_gpio_handler ├── CMakeLists.txt ├── boards │ └── nrf52dk_nrf52832.overlay ├── prj.conf ├── sample.yaml └── src │ └── main.c ├── disable_uart_runtime ├── CMakeLists.txt ├── boards │ ├── nrf52833dk_nrf52833.overlay │ ├── nrf52840dk_nrf52840.overlay │ └── ri700.overlay ├── prj.conf ├── sample.yaml └── src │ └── main.c ├── dual_uart_int ├── CMakeLists.txt ├── nrf52833dk_nrf52833.overlay ├── prj.conf └── src │ └── main.c ├── gnss_coap ├── CMakeLists.txt ├── Kconfig ├── nrf9160dk_nrf9160_ns.overlay ├── overlay-pgps.conf ├── prj.conf ├── sample.yaml └── src │ ├── assistance.c │ ├── assistance.h │ └── main.c ├── hello_world_rtt ├── CMakeLists.txt ├── prj.conf ├── sample.yaml └── src │ └── main.c ├── i2c_scanner ├── CMakeLists.txt ├── not_nrf9160dk_nrf9160_ns.overlay ├── prj.conf └── src │ └── main.c ├── interval_beacon ├── CMakeLists.txt ├── boards │ ├── nrf21540dk_nrf52840.conf │ ├── nrf52840dk_nrf52840.overlay │ └── rv32m1_vega_ri5cy.overlay ├── fem.conf ├── prj-coex.conf ├── prj.conf ├── sample.yaml └── src │ └── main.c ├── lora_overlay └── boards │ └── nrf52840dk_nrf52840.overlay ├── lp_hci_nrf9160dk ├── beacon │ ├── CMakeLists.txt │ ├── README.rst │ ├── boards │ │ ├── nrf9160dk_nrf9160_ns.conf │ │ ├── nrf9160dk_nrf9160_ns.overlay │ │ ├── nrf9160dk_nrf9160_ns_0_14_0.overlay │ │ └── rv32m1_vega_ri5cy.overlay │ ├── child_image │ │ └── spm.conf │ ├── prj.conf │ ├── sample.yaml │ └── src │ │ └── main.c └── hci_lpuart │ ├── .vscode │ └── settings.json │ ├── CMakeLists.txt │ ├── README.rst │ ├── boards │ ├── nrf9160dk_nrf52840.conf │ ├── nrf9160dk_nrf52840.overlay │ ├── nrf9160dk_nrf52840_0_14_0.overlay │ ├── thingy91_nrf52840.conf │ └── thingy91_nrf52840.overlay │ ├── debug.conf │ ├── prj.conf │ └── sample.yaml ├── lte_tests ├── CMakeLists.txt ├── Kconfig ├── prj.conf ├── release.conf ├── sample.yaml └── src │ └── main.c ├── nrf21540dk_confs ├── tx_10db.conf └── tx_20db.conf ├── peripheral_cts_client ├── CMakeLists.txt ├── README.rst ├── cts_central.ncs ├── prj.conf ├── sample.yaml └── src │ └── main.c ├── peripheral_hr_coded_multi ├── .vscode │ └── settings.json ├── CMakeLists.txt ├── README.rst ├── child_image │ └── hci_rpmsg.conf ├── prj.conf ├── sample.yaml ├── settings.json └── src │ └── main.c ├── peripheral_uart_beacon ├── CMakeLists.txt ├── Kconfig ├── Kconfig.sysbuild ├── README.rst ├── VERSION ├── app.overlay ├── boards │ ├── thingy53_nrf5340_cpuapp.conf │ ├── thingy53_nrf5340_cpuapp.overlay │ ├── thingy53_nrf5340_cpuapp_ns.conf │ └── thingy53_nrf5340_cpuapp_ns.overlay ├── nrf5340dk_app_sr_net.conf ├── nrf5340dk_mcuboot_sr_net.conf ├── prj.conf ├── prj_cdc.conf ├── prj_minimal.conf ├── sample.yaml ├── src │ ├── main.c │ ├── uart_async_adapter.c │ └── uart_async_adapter.h └── usb.overlay ├── rtc_sleep ├── CMakeLists.txt ├── README.rst ├── boards │ └── nrf52840dk_nrf52840.overlay ├── prj.conf ├── sample.yaml └── src │ └── main.c ├── rtc_sleep_dual_uart ├── CMakeLists.txt ├── README.rst ├── prj.conf ├── sample.yaml └── src │ └── main.c ├── rtc_sleep_uart ├── CMakeLists.txt ├── README.rst ├── boards │ ├── nrf52833dk_nrf52833.overlay │ └── nrf52840dk_nrf52840.overlay ├── prj.conf ├── sample.yaml └── src │ └── main.c ├── sensor_thingy ├── CMakeLists.txt ├── prj.conf └── src │ └── main.c ├── simple_service ├── central_simple_service │ ├── CMakeLists.txt │ ├── README.rst │ ├── prj.conf │ ├── sample.yaml │ └── src │ │ ├── main.c │ │ ├── simple_service.h │ │ ├── simple_service_client.c │ │ └── simple_service_client.h └── peripheral_simple_service │ ├── CMakeLists.txt │ ├── README.rst │ ├── prj.conf │ ├── sample.yaml │ └── src │ └── main.c ├── timer_dppi_spim ├── .vscode │ ├── .cortex-debug.peripherals.state.json │ ├── .cortex-debug.registers.state.json │ ├── c_cpp_properties.json │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── CMakeLists.txt ├── prj.conf ├── sample.yaml └── src │ └── main.c ├── timer_gppi_gpiote ├── CMakeLists.txt ├── prj.conf ├── sample.yaml └── src │ └── main.c └── uart_wakeup_rx ├── CMakeLists.txt ├── boards └── nrf52840dk_nrf52840.overlay ├── prj.conf ├── sample.yaml └── src └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | .code-workspace 3 | .vscode/ 4 | workspace.code-workspace 5 | *.zip -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ================================= 2 | nRF-Examples by Joao Dullius 3 | ================================= 4 | 5 | nRF-Examples is a repository containing sample code that demonstrates various functionalities of the nRF9160 development board. The examples cover a range of topics, including low-power modes, wireless communication, and hardware peripherals. 6 | 7 | ================================= 8 | Examples 9 | ================================= 10 | 11 | * **disable_uart_runtime** - This example demonstrates how to disable UARTs during runtime to conserve power. By disabling the UARTs when they are not in use, this can significantly reduce the power consumption of the device, making it ideal for battery-powered devices. 12 | 13 | * **gnss_coap** - This example showcases how to obtain a GPS fix and send the data to a CoAP server using the nRF9160 modem. This can be used in location-based applications where the device needs to communicate its position to a server. It demonstrates how to configure the modem, set up a GNSS receiver, and communicate with a CoAP server. 14 | 15 | * **hello_world_rtt** - This is a simple "Hello World" example that demonstrates the use of the Segger Real-Time Transfer (RTT) interface for console output. The RTT interface allows for efficient debugging and logging without the need for a physical UART connection. It demonstrates how to configure the RTT interface and how to use it for console output. 16 | 17 | * **i2c_scanner** - This example demonstrates how to scan the I2C bus for connected devices. It can be used to detect and troubleshoot I2C communication issues in embedded systems. It demonstrates how to configure the I2C interface and how to scan the bus for connected devices. 18 | 19 | * **lp_hc_nrf9160dk** - This example shows how to run a Bluetooth Low Energy (BLE) Host on a nRF9160 and a BLE Controller on a nRF523, interfacing through hci_lpuart. It demonstrates how to set up a BLE connection and communicate between the devices using HCI over UART. 20 | 21 | * **rtc_sleep** - This example demonstrates a simple Real-Time Counter (RTC) timer that toggles an LED. This can be used to measure the current baseline power consumption of the device. It demonstrates how to configure the RTC timer and how to toggle an LED using the General-Purpose Input/Output (GPIO) interface. 22 | 23 | * **rtc_sleep_dual_uart** - This is the same as the above example, but it disables UART0 and UART1 during runtime. This can reduce the power consumption of the device when the UARTs are not in use. 24 | 25 | * **simple_service** - This example demonstrates how to implement a custom BLE service on both the peripheral (advertising and GATT definition) and server side (discovery and connection). It also implements simple fixed password pairing and bonding. It demonstrates how to set up a custom BLE service and how to handle pairing and bonding between devices. 26 | 27 | * **timer_gppi_gpiote** - This example implements a hardware timer that is connected by either PPI or DPPI to a GPIOTE to blink an LED. It demonstrates how to configure the timer and how to use the Programmable Peripheral Interconnect (PPI) or Direct Peripheral-to-Peripheral Interconnect (DPPI) interfaces to trigger a GPIOTE event. 28 | 29 | * **uart_wakeup_rx** - This example demonstrates how to wake up the nRF9160 from sleep using UART activity on RX. It uses low-power states and enables UART only when needed to reduce current consumption. Useful for applications waiting for external commands or serial triggers without wasting energy in idle mode. 30 | 31 | ================================= 32 | Other Examples 33 | ================================= 34 | 35 | There are also other examples in the repository not listed here, which are older ones that are pending review. 36 | -------------------------------------------------------------------------------- /custom_gpio_handler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 5 | project(button) 6 | 7 | target_sources(app PRIVATE src/main.c) 8 | -------------------------------------------------------------------------------- /custom_gpio_handler/boards/nrf52dk_nrf52832.overlay: -------------------------------------------------------------------------------- 1 | // To get started, press Ctrl+Space to bring up the completion menu and view the available nodes. 2 | 3 | // You can also use the buttons in the sidebar to perform actions on nodes. 4 | // Actions currently available include: 5 | 6 | // * Enabling / disabling the node 7 | // * Adding the bus to a bus 8 | // * Removing the node 9 | // * Connecting ADC channels 10 | 11 | // For more help, browse the DeviceTree documentation at https://docs.zephyrproject.org/latest/guides/dts/index.html 12 | // You can also visit the nRF DeviceTree extension documentation at https://nrfconnect.github.io/vscode-nrf-connect/devicetree/nrfdevicetree.html 13 | 14 | / { 15 | gpiocustom { 16 | compatible = "gpio-keys"; 17 | gpiocustom1: gpiocustom1 { 18 | gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; 19 | label = "Custom gpio 1"; 20 | }; 21 | }; 22 | aliases { 23 | ch1 = &gpiocustom1; 24 | }; 25 | }; -------------------------------------------------------------------------------- /custom_gpio_handler/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_GPIO=y 2 | -------------------------------------------------------------------------------- /custom_gpio_handler/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: Button Sample 3 | tests: 4 | sample.basic.button: 5 | tags: button gpio 6 | filter: dt_enabled_alias_with_parent_compat("sw0", "gpio-keys") 7 | depends_on: gpio 8 | harness: button 9 | -------------------------------------------------------------------------------- /custom_gpio_handler/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Open-RnD Sp. z o.o. 3 | * Copyright (c) 2020 Nordic Semiconductor ASA 4 | * 5 | * SPDX-License-Identifier: Apache-2.0 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define SLEEP_TIME_MS 1 16 | 17 | static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(DT_ALIAS(ch1), gpios); 18 | static struct gpio_callback button_cb_data; 19 | 20 | void button_pressed(const struct device *dev, struct gpio_callback *cb, 21 | uint32_t pins) 22 | { 23 | printk("Button pressed at %" PRIu32 "\n", k_cycle_get_32()); 24 | } 25 | 26 | int main(void) 27 | { 28 | int ret; 29 | 30 | if (!gpio_is_ready_dt(&button)) { 31 | printk("Error: button device %s is not ready\n", 32 | button.port->name); 33 | return 0; 34 | } 35 | 36 | ret = gpio_pin_configure_dt(&button, GPIO_INPUT); 37 | if (ret != 0) { 38 | printk("Error %d: failed to configure %s pin %d\n", 39 | ret, button.port->name, button.pin); 40 | return 0; 41 | } 42 | 43 | ret = gpio_pin_interrupt_configure_dt(&button, 44 | GPIO_INT_EDGE_TO_ACTIVE); 45 | if (ret != 0) { 46 | printk("Error %d: failed to configure interrupt on %s pin %d\n", 47 | ret, button.port->name, button.pin); 48 | return 0; 49 | } 50 | 51 | gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin)); 52 | gpio_add_callback(button.port, &button_cb_data); 53 | printk("Set up button at %s pin %d\n", button.port->name, button.pin); 54 | 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /disable_uart_runtime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /disable_uart_runtime/boards/nrf52833dk_nrf52833.overlay: -------------------------------------------------------------------------------- 1 | &uart1 { 2 | status = "disabled"; 3 | }; -------------------------------------------------------------------------------- /disable_uart_runtime/boards/nrf52840dk_nrf52840.overlay: -------------------------------------------------------------------------------- 1 | &uart1 { 2 | status = "disabled"; 3 | }; -------------------------------------------------------------------------------- /disable_uart_runtime/boards/ri700.overlay: -------------------------------------------------------------------------------- 1 | &uart0 { 2 | status = "disabled"; 3 | }; -------------------------------------------------------------------------------- /disable_uart_runtime/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_PM=y 2 | CONFIG_PM_DEVICE=y 3 | CONFIG_SERIAL=y -------------------------------------------------------------------------------- /disable_uart_runtime/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Hello World sample, the simplest Zephyr 3 | application 4 | name: hello world 5 | common: 6 | tags: introduction 7 | integration_platforms: 8 | - native_posix 9 | harness: console 10 | harness_config: 11 | type: one_line 12 | regex: 13 | - "Hello World! (.*)" 14 | tests: 15 | sample.basic.helloworld: 16 | tags: introduction 17 | -------------------------------------------------------------------------------- /disable_uart_runtime/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | void main(void) 12 | { 13 | const struct device *uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); 14 | printk("Hello World! %s\n", CONFIG_BOARD); 15 | 16 | if (!device_is_ready(uart_dev)) { 17 | return; 18 | } 19 | 20 | while(1) 21 | { 22 | pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND); 23 | k_sleep(K_MSEC(2000)); 24 | printk("Should not be printed, since uart0 is disabled! %s\n", CONFIG_BOARD); 25 | pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME); 26 | k_sleep(K_MSEC(2000)); 27 | printk("Should be printed, since uart0 is enabled! %s\n", CONFIG_BOARD); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /dual_uart_int/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(uart_pool) 7 | 8 | target_sources(app PRIVATE src/main.c) -------------------------------------------------------------------------------- /dual_uart_int/nrf52833dk_nrf52833.overlay: -------------------------------------------------------------------------------- 1 | // To get started, press Ctrl+Space to bring up the completion menu and view the available nodes. 2 | 3 | // You can also use the buttons in the sidebar to perform actions on nodes. 4 | // Actions currently available include: 5 | 6 | // * Enabling / disabling the node 7 | // * Adding the bus to a bus 8 | // * Removing the node 9 | // * Connecting ADC channels 10 | 11 | // For more help, browse the DeviceTree documentation at https://docs.zephyrproject.org/latest/guides/dts/index.html 12 | // You can also visit the nRF DeviceTree extension documentation at https://nrfconnect.github.io/vscode-nrf-connect/devicetree/nrfdevicetree.html 13 | 14 | &uart1 { 15 | status = "okay"; 16 | current-speed = <57600>; 17 | }; 18 | -------------------------------------------------------------------------------- /dual_uart_int/prj.conf: -------------------------------------------------------------------------------- 1 | #Config Serial 2 | CONFIG_SERIAL=y 3 | CONFIG_UART_INTERRUPT_DRIVEN=y -------------------------------------------------------------------------------- /dual_uart_int/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Libre Solar Technologies GmbH 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | /* change this to any other UART peripheral if desired */ 14 | 15 | 16 | #define MSG_SIZE 32 17 | 18 | /* queue to store up to 10 messages (aligned to 4-byte boundary) */ 19 | K_MSGQ_DEFINE(uart0_msgq, MSG_SIZE, 10, 4); 20 | K_MSGQ_DEFINE(uart1_msgq, MSG_SIZE, 10, 4); 21 | 22 | static const struct device *uart0_dev = DEVICE_DT_GET(DT_NODELABEL(uart0)); 23 | static const struct device *uart1_dev = DEVICE_DT_GET(DT_NODELABEL(uart1)); 24 | 25 | /* receive buffer used in UART ISR callback */ 26 | static char rx0_buf[MSG_SIZE], rx1_buf[MSG_SIZE]; 27 | static char tx0_buf[MSG_SIZE], tx1_buf[MSG_SIZE]; 28 | static int rx0_buf_pos, rx1_buf_pos; 29 | 30 | 31 | /* 32 | * Read characters from UART until line end is detected. Afterwards push the 33 | * data to the message queue. 34 | */ 35 | void uart0_cb(const struct device *dev, void *user_data) 36 | { 37 | uint8_t c; 38 | 39 | if (!uart_irq_update(uart0_dev)) { 40 | return; 41 | } 42 | 43 | while (uart_irq_rx_ready(uart0_dev)) { 44 | 45 | uart_fifo_read(uart0_dev, &c, 1); 46 | 47 | if ((c == '\n' || c == '\r') && rx0_buf_pos > 0) { 48 | /* terminate string */ 49 | rx0_buf[rx0_buf_pos] = '\0'; 50 | 51 | /* if queue is full, message is silently dropped */ 52 | k_msgq_put(&uart0_msgq, &rx0_buf, K_NO_WAIT); 53 | 54 | /* reset the buffer (it was copied to the msgq) */ 55 | rx0_buf_pos = 0; 56 | } else if (rx0_buf_pos < (sizeof(rx0_buf) - 1)) { 57 | rx0_buf[rx0_buf_pos++] = c; 58 | } 59 | /* else: characters beyond buffer size are dropped */ 60 | } 61 | } 62 | 63 | void uart1_cb(const struct device *dev, void *user_data) 64 | { 65 | uint8_t c; 66 | 67 | if (!uart_irq_update(uart1_dev)) { 68 | return; 69 | } 70 | 71 | while (uart_irq_rx_ready(uart1_dev)) { 72 | 73 | uart_fifo_read(uart1_dev, &c, 1); 74 | 75 | if ((c == '\n' || c == '\r') && rx1_buf_pos > 0) { 76 | /* terminate string */ 77 | rx0_buf[rx1_buf_pos] = '\0'; 78 | 79 | /* if queue is full, message is silently dropped */ 80 | k_msgq_put(&uart1_msgq, &rx1_buf, K_NO_WAIT); 81 | 82 | /* reset the buffer (it was copied to the msgq) */ 83 | rx1_buf_pos = 0; 84 | } else if (rx1_buf_pos < (sizeof(rx1_buf) - 1)) { 85 | rx1_buf[rx1_buf_pos++] = c; 86 | } 87 | /* else: characters beyond buffer size are dropped */ 88 | } 89 | } 90 | 91 | void print_uart(const struct device * dev, char *buf) 92 | { 93 | int msg_len = strlen(buf); 94 | 95 | for (int i = 0; i < msg_len; i++) { 96 | uart_poll_out(dev, buf[i]); 97 | } 98 | } 99 | 100 | /* 101 | * Print a null-terminated string character by character to the UART interface 102 | */ 103 | #define PRINT_THREAD_STACK 2048 104 | void print_uart0_fn(void){ 105 | while (1) 106 | { 107 | /* indefinitely wait for input from the user */ 108 | /* Uart_0 waits Uart_1 to print*/ 109 | while (k_msgq_get(&uart1_msgq, &tx1_buf, K_FOREVER) == 0) { 110 | print_uart(uart0_dev, "From Uart1: "); 111 | print_uart(uart0_dev, tx1_buf); 112 | print_uart(uart0_dev, "\r\n"); 113 | } 114 | } 115 | } 116 | 117 | void print_uart1_fn(void){ 118 | while (1) 119 | { 120 | /* indefinitely wait for input from the user */ 121 | /* Uart_1 waits Uart_0 to print*/ 122 | while (k_msgq_get(&uart0_msgq, &tx0_buf, K_FOREVER) == 0) { 123 | print_uart(uart1_dev, "From Uart0: "); 124 | print_uart(uart1_dev, tx0_buf); 125 | print_uart(uart1_dev, "\r\n"); 126 | } 127 | } 128 | } 129 | 130 | 131 | 132 | void main(void) 133 | { 134 | 135 | if (uart0_dev == NULL || !device_is_ready(uart0_dev)) { 136 | printk("UART_0 device not found!"); 137 | return; 138 | } 139 | 140 | if (uart1_dev == NULL || !device_is_ready(uart1_dev)) { 141 | printk("UART_1 device not found!"); 142 | return; 143 | } 144 | 145 | 146 | /* configure interrupt and callback to receive data */ 147 | uart_irq_callback_user_data_set(uart0_dev, uart0_cb, NULL); 148 | uart_irq_rx_enable(uart0_dev); 149 | 150 | /* configure interrupt and callback to receive data */ 151 | uart_irq_callback_user_data_set(uart1_dev, uart1_cb, NULL); 152 | uart_irq_rx_enable(uart1_dev); 153 | 154 | print_uart(uart0_dev, "Hello! This is Uart_0\r\n"); 155 | print_uart(uart0_dev, "Tell me something and press enter:\r\n"); 156 | 157 | print_uart(uart1_dev, "Hello! This is Uart_1\r\n"); 158 | print_uart(uart1_dev, "Tell me something and press enter:\r\n"); 159 | 160 | } 161 | 162 | K_THREAD_DEFINE(print_uart0_thread, PRINT_THREAD_STACK, 163 | print_uart0_fn, NULL, NULL, NULL, 164 | K_LOWEST_APPLICATION_THREAD_PRIO, 0, 0); 165 | 166 | K_THREAD_DEFINE(print_uart1_thread, PRINT_THREAD_STACK, 167 | print_uart1_fn, NULL, NULL, NULL, 168 | K_LOWEST_APPLICATION_THREAD_PRIO, 0, 0); -------------------------------------------------------------------------------- /gnss_coap/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.20.0) 8 | 9 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 10 | project(gnss_sample) 11 | 12 | zephyr_library_sources(src/main.c) 13 | 14 | zephyr_library_sources_ifdef(CONFIG_GNSS_SAMPLE_ASSISTANCE_NRF_CLOUD src/assistance.c) -------------------------------------------------------------------------------- /gnss_coap/Kconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2020 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | menu "GNSS UDP Setttings" 8 | 9 | config GNSS_SIMULATE_FIX 10 | bool "Simulated GPS Fix" 11 | default n 12 | 13 | config UDP_DATA_UPLOAD_SIZE_BYTES 14 | int "Number of bytes transmitted to the server" 15 | default 10 16 | 17 | config UDP_DATA_UPLOAD_FREQUENCY_SECONDS 18 | int "How often data is transmitted to the server" 19 | default 900 20 | 21 | config UDP_SERVER_ADDRESS_STATIC 22 | string "UDP server IP address" 23 | default "8.8.8.8" 24 | 25 | config UDP_SERVER_PORT 26 | int "UDP server port number" 27 | default "2469" 28 | 29 | config UDP_PSM_ENABLE 30 | bool "Enable LTE Power Saving Mode" 31 | default y 32 | 33 | config UDP_EDRX_ENABLE 34 | bool "Enable LTE enhanced Discontinuous Reception" 35 | 36 | config UDP_RAI_ENABLE 37 | bool "Enable LTE Release Assistance Indication" 38 | 39 | config GNSS_PERIODIC_INTERVAL 40 | int "Fix interval for periodic GPS fixes" 41 | range 10 65535 42 | default 120 43 | help 44 | Fix interval (in seconds) for periodic fixes. 45 | 46 | config GNSS_PERIODIC_TIMEOUT 47 | int "Fix timeout for periodic GPS fixes" 48 | range 0 65535 49 | default 480 50 | help 51 | Fix timeout (in seconds) for periodic fixes. 52 | If set to zero, GNSS is allowed to run indefinitely until a valid PVT estimate is produced. 53 | 54 | endmenu 55 | 56 | module = UDP 57 | module-str = UDP sample 58 | source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" 59 | 60 | menu "Zephyr Kernel" 61 | source "Kconfig.zephyr" 62 | endmenu -------------------------------------------------------------------------------- /gnss_coap/nrf9160dk_nrf9160_ns.overlay: -------------------------------------------------------------------------------- 1 | &gpio0 { 2 | sense-edge-mask = <((1 << 6) | (1 << 7)| (1 << 8)| (1 << 9))>; 3 | }; -------------------------------------------------------------------------------- /gnss_coap/overlay-pgps.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | # P-GPS overlay configuration 8 | 9 | # Enable nRF Cloud assistance for GNSS sample 10 | CONFIG_GNSS_SAMPLE_ASSISTANCE_NRF_CLOUD=y 11 | 12 | # P-GPS 13 | CONFIG_NRF_CLOUD_PGPS=y 14 | CONFIG_NRF_CLOUD_PGPS_REPLACEMENT_THRESHOLD=4 15 | 16 | # Disable A-GPS, comment this if you want to use both A-GPS and P-GPS at the same time 17 | CONFIG_NRF_CLOUD_AGPS=n 18 | 19 | # Storage for P-GPS 20 | CONFIG_STREAM_FLASH=y 21 | CONFIG_FLASH=y 22 | CONFIG_FLASH_PAGE_LAYOUT=y 23 | CONFIG_FLASH_MAP=y 24 | CONFIG_FCB=y 25 | CONFIG_SETTINGS=y 26 | CONFIG_SETTINGS_FCB=y 27 | CONFIG_MPU_ALLOW_FLASH_WRITE=y 28 | 29 | # P-GPS needs more heap 30 | CONFIG_HEAP_MEM_POOL_SIZE=8192 31 | -------------------------------------------------------------------------------- /gnss_coap/prj.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2020 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | CONFIG_GNSS_SIMULATE_FIX=y 8 | 9 | # General config 10 | CONFIG_PM=y 11 | CONFIG_PM_DEVICE=y 12 | CONFIG_FPU=y 13 | CONFIG_NEWLIB_LIBC=y 14 | CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y 15 | CONFIG_THREAD_NAME=y 16 | CONFIG_DATE_TIME=y 17 | CONFIG_DATE_TIME_AUTO_UPDATE=y 18 | CONFIG_DATE_TIME_MODEM=y 19 | CONFIG_DATE_TIME_NTP=y 20 | CONFIG_DATE_TIME_LOG_LEVEL_DBG=y 21 | 22 | #Debugs - Turn off to low Power 23 | CONFIG_SERIAL=y 24 | CONFIG_LOG=y 25 | CONFIG_NRF_MODEM_LIB_TRACE=n 26 | 27 | # Network 28 | CONFIG_NETWORKING=y 29 | CONFIG_NET_NATIVE=n 30 | CONFIG_NET_SOCKETS=y 31 | CONFIG_NET_SOCKETS_OFFLOAD=y 32 | 33 | # LTE link control 34 | CONFIG_LTE_LINK_CONTROL=y 35 | CONFIG_LTE_AUTO_INIT_AND_CONNECT=n 36 | 37 | # Modem library 38 | CONFIG_NRF_MODEM_LIB=y 39 | 40 | # Heap and stacks 41 | CONFIG_HEAP_MEM_POOL_SIZE=1024 42 | CONFIG_MAIN_STACK_SIZE=4096 43 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 44 | 45 | # LTE parameters 46 | ## Network Mode / LTE category 47 | #CONFIG_LTE_NETWORK_MODE_LTE_M_GPS=y 48 | CONFIG_LTE_NETWORK_MODE_NBIOT_GPS=y 49 | 50 | ## PSM 51 | CONFIG_UDP_PSM_ENABLE=y 52 | CONFIG_LTE_PSM_REQ_RPTAU="00100001" 53 | CONFIG_LTE_PSM_REQ_RAT="00000000" 54 | 55 | ## eDRX 56 | CONFIG_UDP_EDRX_ENABLE=n 57 | CONFIG_LTE_EDRX_REQ_VALUE_LTE_M="1001" 58 | 59 | ## RAI 60 | CONFIG_UDP_RAI_ENABLE=y 61 | CONFIG_LTE_RAI_REQ_VALUE="3" 62 | 63 | #CoAP 64 | CONFIG_COAP=y -------------------------------------------------------------------------------- /gnss_coap/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: GNSS sample 3 | tests: 4 | sample.nrf9160.gnss: 5 | build_only: true 6 | integration_platforms: 7 | - nrf9160dk_nrf9160_ns 8 | platform_allow: nrf9160dk_nrf9160_ns 9 | tags: ci_build 10 | -------------------------------------------------------------------------------- /gnss_coap/src/assistance.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #if defined(CONFIG_NRF_CLOUD_AGPS) 14 | #include 15 | #endif /* CONFIG_NRF_CLOUD_AGPS */ 16 | #if defined(CONFIG_NRF_CLOUD_PGPS) 17 | #include 18 | #endif /* CONFIG_NRF_CLOUD_PGPS */ 19 | 20 | #include "assistance.h" 21 | 22 | LOG_MODULE_DECLARE(gnss_udp, CONFIG_GNSS_SAMPLE_LOG_LEVEL); 23 | 24 | static char jwt_buf[600]; 25 | static char rx_buf[2048]; 26 | 27 | #if defined(CONFIG_NRF_CLOUD_AGPS) 28 | static char agps_data_buf[3500]; 29 | #endif /* CONFIG_NRF_CLOUD_AGPS */ 30 | 31 | #if defined(CONFIG_NRF_CLOUD_PGPS) 32 | static struct nrf_modem_gnss_agps_data_frame agps_need; 33 | static struct gps_pgps_request pgps_request; 34 | static struct nrf_cloud_pgps_prediction *prediction; 35 | static struct k_work get_pgps_data_work; 36 | static struct k_work inject_pgps_data_work; 37 | #endif /* CONFIG_NRF_CLOUD_PGPS */ 38 | 39 | static struct k_work_q *work_q; 40 | static volatile bool assistance_active; 41 | 42 | #if defined(CONFIG_NRF_CLOUD_AGPS) 43 | static int serving_cell_info_get(struct lte_lc_cell *serving_cell) 44 | { 45 | int err; 46 | 47 | err = modem_info_init(); 48 | if (err) { 49 | return err; 50 | } 51 | 52 | char resp_buf[MODEM_INFO_MAX_RESPONSE_SIZE]; 53 | 54 | err = modem_info_string_get(MODEM_INFO_CELLID, 55 | resp_buf, 56 | MODEM_INFO_MAX_RESPONSE_SIZE); 57 | if (err < 0) { 58 | return err; 59 | } 60 | 61 | serving_cell->id = strtol(resp_buf, NULL, 16); 62 | 63 | err = modem_info_string_get(MODEM_INFO_AREA_CODE, 64 | resp_buf, 65 | MODEM_INFO_MAX_RESPONSE_SIZE); 66 | if (err < 0) { 67 | return err; 68 | } 69 | 70 | serving_cell->tac = strtol(resp_buf, NULL, 16); 71 | 72 | /* Request for MODEM_INFO_MNC returns both MNC and MCC in the same string. */ 73 | err = modem_info_string_get(MODEM_INFO_OPERATOR, 74 | resp_buf, 75 | MODEM_INFO_MAX_RESPONSE_SIZE); 76 | if (err < 0) { 77 | return err; 78 | } 79 | 80 | serving_cell->mnc = strtol(&resp_buf[3], NULL, 10); 81 | /* Null-terminate MCC, read and store it. */ 82 | resp_buf[3] = '\0'; 83 | serving_cell->mcc = strtol(resp_buf, NULL, 10); 84 | 85 | return 0; 86 | } 87 | #endif /* CONFIG_NRF_CLOUD_AGPS */ 88 | 89 | #if defined(CONFIG_NRF_CLOUD_PGPS) 90 | static void get_pgps_data_work_fn(struct k_work *work) 91 | { 92 | ARG_UNUSED(work); 93 | 94 | int err; 95 | 96 | assistance_active = true; 97 | 98 | LOG_INF("Sending request for P-GPS predictions to nRF Cloud..."); 99 | 100 | err = nrf_cloud_jwt_generate(0, jwt_buf, sizeof(jwt_buf)); 101 | if (err) { 102 | LOG_ERR("Failed to generate JWT, error: %d", err); 103 | 104 | goto exit; 105 | } 106 | 107 | struct nrf_cloud_rest_context rest_ctx = { 108 | .connect_socket = -1, 109 | .keep_alive = false, 110 | .timeout_ms = NRF_CLOUD_REST_TIMEOUT_NONE, 111 | .auth = jwt_buf, 112 | .rx_buf = rx_buf, 113 | .rx_buf_len = sizeof(rx_buf), 114 | .fragment_size = 0, /* Defaults to CONFIG_NRF_CLOUD_REST_FRAGMENT_SIZE when 0 */ 115 | .status = 0, 116 | .response = NULL, 117 | .response_len = 0, 118 | .total_response_len = 0 119 | }; 120 | 121 | struct nrf_cloud_rest_pgps_request request = { 122 | .pgps_req = &pgps_request 123 | }; 124 | 125 | err = nrf_cloud_rest_pgps_data_get(&rest_ctx, &request); 126 | if (err) { 127 | LOG_ERR("Failed to send P-GPS request, error: %d", err); 128 | 129 | nrf_cloud_pgps_request_reset(); 130 | 131 | goto exit; 132 | } 133 | 134 | LOG_INF("Processing P-GPS response"); 135 | 136 | err = nrf_cloud_pgps_process(rest_ctx.response, rest_ctx.response_len); 137 | if (err) { 138 | LOG_ERR("Failed to process P-GPS response, error: %d", err); 139 | 140 | nrf_cloud_pgps_request_reset(); 141 | 142 | goto exit; 143 | } 144 | 145 | LOG_INF("P-GPS response processed"); 146 | 147 | exit: 148 | assistance_active = false; 149 | } 150 | 151 | static void inject_pgps_data_work_fn(struct k_work *work) 152 | { 153 | ARG_UNUSED(work); 154 | 155 | int err; 156 | 157 | assistance_active = true; 158 | 159 | LOG_INF("Injecting P-GPS ephemerides"); 160 | 161 | err = nrf_cloud_pgps_inject(prediction, &agps_need); 162 | if (err) { 163 | LOG_ERR("Failed to inject P-GPS ephemerides"); 164 | } 165 | 166 | err = nrf_cloud_pgps_preemptive_updates(); 167 | if (err) { 168 | LOG_ERR("Failed to request P-GPS updates"); 169 | } 170 | 171 | assistance_active = false; 172 | } 173 | 174 | static void pgps_event_handler(struct nrf_cloud_pgps_event *event) 175 | { 176 | switch (event->type) { 177 | case PGPS_EVT_AVAILABLE: 178 | prediction = event->prediction; 179 | 180 | k_work_submit_to_queue(work_q, &inject_pgps_data_work); 181 | break; 182 | 183 | case PGPS_EVT_REQUEST: 184 | memcpy(&pgps_request, event->request, sizeof(pgps_request)); 185 | 186 | k_work_submit_to_queue(work_q, &get_pgps_data_work); 187 | break; 188 | 189 | case PGPS_EVT_LOADING: 190 | LOG_INF("Loading P-GPS predictions"); 191 | assistance_active = true; 192 | break; 193 | 194 | case PGPS_EVT_READY: 195 | LOG_INF("P-GPS predictions ready"); 196 | assistance_active = false; 197 | break; 198 | 199 | default: 200 | /* No action needed */ 201 | break; 202 | } 203 | } 204 | #endif /* CONFIG_NRF_CLOUD_PGPS */ 205 | 206 | int assistance_init(struct k_work_q *assistance_work_q) 207 | { 208 | work_q = assistance_work_q; 209 | 210 | #if defined(CONFIG_NRF_CLOUD_PGPS) 211 | k_work_init(&get_pgps_data_work, get_pgps_data_work_fn); 212 | k_work_init(&inject_pgps_data_work, inject_pgps_data_work_fn); 213 | 214 | struct nrf_cloud_pgps_init_param pgps_param = { 215 | .event_handler = pgps_event_handler, 216 | /* storage is defined by CONFIG_NRF_CLOUD_PGPS_STORAGE */ 217 | .storage_base = 0u, 218 | .storage_size = 0u 219 | }; 220 | 221 | if (nrf_cloud_pgps_init(&pgps_param) != 0) { 222 | LOG_ERR("Failed to initialize P-GPS"); 223 | return -1; 224 | } 225 | #endif /* CONFIG_NRF_CLOUD_PGPS */ 226 | 227 | return 0; 228 | } 229 | 230 | int assistance_request(struct nrf_modem_gnss_agps_data_frame *agps_request) 231 | { 232 | int err = 0; 233 | 234 | #if defined(CONFIG_NRF_CLOUD_PGPS) 235 | /* Store the A-GPS data request for P-GPS use. */ 236 | memcpy(&agps_need, agps_request, sizeof(agps_need)); 237 | 238 | #if defined(CONFIG_NRF_CLOUD_AGPS) 239 | if (!agps_request->data_flags) { 240 | /* No assistance needed from A-GPS, skip directly to P-GPS. */ 241 | nrf_cloud_pgps_notify_prediction(); 242 | return 0; 243 | } 244 | 245 | /* P-GPS will handle ephemerides, so skip those. */ 246 | agps_request->sv_mask_ephe = 0; 247 | /* Almanacs are not needed with P-GPS, so skip those. */ 248 | agps_request->sv_mask_alm = 0; 249 | #endif /* CONFIG_NRF_CLOUD_AGPS */ 250 | #endif /* CONFIG_NRF_CLOUD_PGPS */ 251 | #if defined(CONFIG_NRF_CLOUD_AGPS) 252 | assistance_active = true; 253 | 254 | err = nrf_cloud_jwt_generate(0, jwt_buf, sizeof(jwt_buf)); 255 | if (err) { 256 | LOG_ERR("Failed to generate JWT, error: %d", err); 257 | goto agps_exit; 258 | } 259 | 260 | struct nrf_cloud_rest_context rest_ctx = { 261 | .connect_socket = -1, 262 | .keep_alive = false, 263 | .timeout_ms = NRF_CLOUD_REST_TIMEOUT_NONE, 264 | .auth = jwt_buf, 265 | .rx_buf = rx_buf, 266 | .rx_buf_len = sizeof(rx_buf), 267 | .fragment_size = 0, /* Defaults to CONFIG_NRF_CLOUD_REST_FRAGMENT_SIZE when 0 */ 268 | .status = 0, 269 | .response = NULL, 270 | .response_len = 0, 271 | .total_response_len = 0 272 | }; 273 | 274 | struct nrf_cloud_rest_agps_request request = { 275 | .type = NRF_CLOUD_REST_AGPS_REQ_CUSTOM, 276 | .agps_req = agps_request, 277 | .net_info = NULL, 278 | #if defined(CONFIG_NRF_CLOUD_AGPS_FILTERED_RUNTIME) 279 | .filtered = true, 280 | /* Note: if you change the mask angle here, you may want to 281 | * also change it to match in gnss_init_and_start() in main.c. 282 | */ 283 | .mask_angle = CONFIG_NRF_CLOUD_AGPS_ELEVATION_MASK 284 | /* Note: if CONFIG_NRF_CLOUD_AGPS_FILTERED is enabled but 285 | * CONFIG_NRF_CLOUD_AGPS_FILTERED_RUNTIME is not, 286 | * the nrf_cloud_rest library will set the above fields to 287 | * true and CONFIG_NRF_CLOUD_AGPS_ELEVATION_MASK respectively. 288 | * When CONFIG_NRF_CLOUD_AGPS_FILTERED is disabled, it will 289 | * set them to false and 0. 290 | */ 291 | #endif 292 | }; 293 | 294 | struct nrf_cloud_rest_agps_result result = { 295 | .buf = agps_data_buf, 296 | .buf_sz = sizeof(agps_data_buf), 297 | .agps_sz = 0 298 | }; 299 | 300 | struct lte_lc_cells_info net_info = { 0 }; 301 | 302 | err = serving_cell_info_get(&net_info.current_cell); 303 | if (err) { 304 | LOG_ERR("Could not get cell info, error: %d", err); 305 | } else { 306 | /* Network info for the location request. */ 307 | request.net_info = &net_info; 308 | } 309 | 310 | LOG_INF("Requesting A-GPS data, ephe 0x%08x, alm 0x%08x, flags 0x%02x", 311 | agps_request->sv_mask_ephe, 312 | agps_request->sv_mask_alm, 313 | agps_request->data_flags); 314 | 315 | err = nrf_cloud_rest_agps_data_get(&rest_ctx, &request, &result); 316 | if (err) { 317 | LOG_ERR("Failed to get A-GPS data, error: %d", err); 318 | goto agps_exit; 319 | } 320 | 321 | LOG_INF("Processing A-GPS data"); 322 | 323 | err = nrf_cloud_agps_process(result.buf, result.agps_sz); 324 | if (err) { 325 | LOG_ERR("Failed to process A-GPS data, error: %d", err); 326 | goto agps_exit; 327 | } 328 | 329 | LOG_INF("A-GPS data processed"); 330 | 331 | agps_exit: 332 | assistance_active = false; 333 | #endif /* CONFIG_NRF_CLOUD_AGPS */ 334 | 335 | #if defined(CONFIG_NRF_CLOUD_PGPS) 336 | nrf_cloud_pgps_notify_prediction(); 337 | #endif /* CONFIG_NRF_CLOUD_PGPS */ 338 | 339 | return err; 340 | } 341 | 342 | bool assistance_is_active(void) 343 | { 344 | return assistance_active; 345 | } 346 | -------------------------------------------------------------------------------- /gnss_coap/src/assistance.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | #ifndef ASSISTANCE_H_ 8 | #define ASSISTANCE_H_ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Initializes the assistance module. 16 | * 17 | * @param[in] assistance_work_q Work queue that can be used by the assistance module. 18 | * 19 | * @retval 0 on success. 20 | * @retval -1 in case of an error. 21 | */ 22 | int assistance_init(struct k_work_q *assistance_work_q); 23 | 24 | /** 25 | * @brief Handles an assistance data request. 26 | * 27 | * @details Fetches and injects assistance data to the GNSS. 28 | * 29 | * @param[in] agps_request A-GPS data requested by GNSS. 30 | * 31 | * @retval 0 on success. 32 | * @retval <0 in case of an error. 33 | */ 34 | int assistance_request(struct nrf_modem_gnss_agps_data_frame *agps_request); 35 | 36 | /** 37 | * @brief Returns assistance module state. 38 | * 39 | * @retval true if assistance module is downloading data. 40 | * @retval false if assistance module is idle. 41 | */ 42 | bool assistance_is_active(void); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* ASSISTANCE_H_ */ 49 | -------------------------------------------------------------------------------- /hello_world_rtt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /hello_world_rtt/prj.conf: -------------------------------------------------------------------------------- 1 | # nothing here 2 | CONFIG_USE_SEGGER_RTT=y 3 | 4 | #Config console 5 | CONFIG_RTT_CONSOLE=y 6 | CONFIG_UART_CONSOLE=n -------------------------------------------------------------------------------- /hello_world_rtt/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Hello World sample, the simplest Zephyr 3 | application 4 | name: hello world 5 | common: 6 | tags: introduction 7 | integration_platforms: 8 | - native_posix 9 | harness: console 10 | harness_config: 11 | type: one_line 12 | regex: 13 | - "Hello World! (.*)" 14 | tests: 15 | sample.basic.helloworld: 16 | tags: introduction 17 | -------------------------------------------------------------------------------- /hello_world_rtt/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | 9 | void main(void) 10 | { 11 | printk("Hello World! %s\n", CONFIG_BOARD); 12 | } 13 | -------------------------------------------------------------------------------- /i2c_scanner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2018 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.13.1) 8 | 9 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 10 | project(NONE) 11 | 12 | # NORDIC SDK APP START 13 | target_sources(app PRIVATE src/main.c) 14 | # NORDIC SDK APP END 15 | -------------------------------------------------------------------------------- /i2c_scanner/not_nrf9160dk_nrf9160_ns.overlay: -------------------------------------------------------------------------------- 1 | &uart0 { 2 | //rts-pin = <27>; 3 | //cts-pin = <26>; 4 | 5 | rts-pin = <30>; 6 | cts-pin = <31>; 7 | }; 8 | 9 | &i2c2 { 10 | //sda-pin = <30>; 11 | //scl-pin = <31>; 12 | 13 | sda-pin = <26>; 14 | scl-pin = <27>; 15 | 16 | 17 | }; -------------------------------------------------------------------------------- /i2c_scanner/prj.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic 5 | # 6 | # General config 7 | CONFIG_ASSERT=y 8 | 9 | CONFIG_NEWLIB_LIBC=y 10 | 11 | #I2C 12 | CONFIG_I2C=y 13 | CONFIG_I2C_NRFX=y 14 | #CONFIG_I2C_2=y 15 | #CONFIG_I2C_2_NRF_TWIM=y 16 | 17 | #CONFIG_LOG=y 18 | #CONFIG_I2C_LOG_LEVEL_DBG=y 19 | #CONFIG_LOG_BACKEND_UART=y 20 | #CONFIG_I2C_INIT_PRIORITY=60 21 | 22 | 23 | 24 | 25 | # Stacks and heaps 26 | CONFIG_MAIN_STACK_SIZE=2048 27 | CONFIG_HEAP_MEM_POOL_SIZE=8192 28 | -------------------------------------------------------------------------------- /i2c_scanner/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Sigurd Nevstad 3 | * Copyright (c) 2021 Joao Dullius 4 | * Based on: 5 | * https://github.com/sigurdnev/ncs-playground/tree/master/samples/i2c_scanner 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define I2C_DEV DT_NODELABEL(arduino_i2c) 18 | 19 | void main(void) 20 | { 21 | const struct device *i2c_dev; 22 | 23 | k_sleep(K_SECONDS(1)); 24 | 25 | printk("Starting i2c scanner at %s\n", DT_LABEL(I2C_DEV)); 26 | 27 | i2c_dev = device_get_binding(DT_LABEL(I2C_DEV)); 28 | if (!i2c_dev) { 29 | printk("I2C: Device driver not found.\n"); 30 | return; 31 | } 32 | 33 | uint8_t error = 0u; 34 | 35 | i2c_configure(i2c_dev, I2C_SPEED_SET(I2C_SPEED_STANDARD)); 36 | 37 | for (uint8_t i = 4; i <= 0x77; i++) { 38 | struct i2c_msg msgs[1]; 39 | uint8_t dst = 1; 40 | 41 | /* Send the address to read from */ 42 | msgs[0].buf = &dst; 43 | msgs[0].len = 1U; 44 | msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP; 45 | 46 | error = i2c_transfer(i2c_dev, &msgs[0], 1, i); 47 | if (error == 0) { 48 | printk("0x%2x FOUND\n", i); 49 | } 50 | else { 51 | //printk("error %d \n", error); 52 | } 53 | 54 | } 55 | printk("Scanning done\n"); 56 | 57 | } -------------------------------------------------------------------------------- /interval_beacon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 5 | project(beacon) 6 | 7 | target_sources(app PRIVATE src/main.c) 8 | -------------------------------------------------------------------------------- /interval_beacon/boards/nrf21540dk_nrf52840.conf: -------------------------------------------------------------------------------- 1 | CONFIG_MPSL_FEM=y 2 | CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=0 3 | CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20 4 | CONFIG_BT_CTLR_LE_POWER_CONTROL=y 5 | CONFIG_BT_CTLR_TX_PWR_ANTENNA=20 6 | CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y -------------------------------------------------------------------------------- /interval_beacon/boards/nrf52840dk_nrf52840.overlay: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dronetag 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /{ 7 | coex_gpio: coex { 8 | compatible = "gpio-radio-coex"; 9 | grant-gpios = <&gpio1 0 (GPIO_PULL_DOWN | GPIO_ACTIVE_LOW)>; 10 | grant-delay-us = <150>; 11 | }; 12 | }; 13 | 14 | &radio { 15 | coex = <&coex_gpio>; 16 | }; 17 | -------------------------------------------------------------------------------- /interval_beacon/boards/rv32m1_vega_ri5cy.overlay: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 NXP 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | &lptmr1 { 8 | interrupt-parent = <&intmux0_ch2>; 9 | }; 10 | 11 | &intmux0_ch2 { 12 | status = "okay"; 13 | }; 14 | 15 | &intmux0_ch3 { 16 | status = "okay"; 17 | }; 18 | 19 | &generic_fsk { 20 | interrupt-parent = <&intmux0_ch3>; 21 | status = "okay"; 22 | }; 23 | -------------------------------------------------------------------------------- /interval_beacon/fem.conf: -------------------------------------------------------------------------------- 1 | CONFIG_MPSL_FEM=y 2 | CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=0 3 | CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20 4 | CONFIG_BT_CTLR_LE_POWER_CONTROL=y 5 | CONFIG_BT_CTLR_TX_PWR_ANTENNA=20 6 | CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y -------------------------------------------------------------------------------- /interval_beacon/prj-coex.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | CONFIG_BT_DEBUG_LOG=y 3 | CONFIG_BT_DEVICE_NAME="Test beacon" 4 | 5 | CONFIG_BT_LL_SW_SPLIT=y 6 | CONFIG_BT_CTLR_COEX_DRIVERS=y 7 | CONFIG_BT_CTLR_COEX_TICKER=y 8 | -------------------------------------------------------------------------------- /interval_beacon/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | CONFIG_BT_DEBUG_LOG=y 3 | CONFIG_BT_DEVICE_NAME="Test Interval Beacon" 4 | CONFIG_SERIAL=n 5 | CONFIG_PM=y -------------------------------------------------------------------------------- /interval_beacon/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: Bluetooth Beacon 3 | tests: 4 | sample.bluetooth.beacon: 5 | harness: bluetooth 6 | platform_allow: qemu_cortex_m3 qemu_x86 nrf52dk_nrf52832 7 | tags: bluetooth 8 | integration_platforms: 9 | - qemu_cortex_m3 10 | 11 | sample.bluetooth.beacon-coex: 12 | extra_args: CONF_FILE="prj-coex.conf" 13 | harness: bluetooth 14 | platform_allow: nrf52840dk_nrf52840 15 | tags: bluetooth 16 | -------------------------------------------------------------------------------- /interval_beacon/src/main.c: -------------------------------------------------------------------------------- 1 | /* main.c - Application main entry point */ 2 | 3 | /* 4 | * Copyright (c) 2015-2016 Intel Corporation 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #define DEVICE_NAME CONFIG_BT_DEVICE_NAME 18 | #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) 19 | 20 | #define ACTIVE_TIME K_SECONDS(30) 21 | #define SLEEP_TIME K_SECONDS(180) 22 | 23 | /* 24 | * Set Advertisement data. Based on the Eddystone specification: 25 | * https://github.com/google/eddystone/blob/master/protocol-specification.md 26 | * https://github.com/google/eddystone/tree/master/eddystone-url 27 | */ 28 | static const struct bt_data ad[] = { 29 | BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR), 30 | BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0xaa, 0xfe), 31 | BT_DATA_BYTES(BT_DATA_SVC_DATA16, 32 | 0xaa, 0xfe, /* Eddystone UUID */ 33 | 0x10, /* Eddystone-URL frame type */ 34 | 0x00, /* Calibrated Tx power at 0m */ 35 | 0x00, /* URL Scheme Prefix http://www. */ 36 | 'z', 'e', 'p', 'h', 'y', 'r', 37 | 'p', 'r', 'o', 'j', 'e', 'c', 't', 38 | 0x08) /* .org */ 39 | }; 40 | 41 | /* Set Scan Response data */ 42 | static const struct bt_data sd[] = { 43 | BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), 44 | }; 45 | 46 | void stop_adv_handler(struct k_work *work); 47 | 48 | static struct k_work_delayable start_adv_work; 49 | static struct k_work_delayable stop_adv_work; 50 | 51 | /* Delayable workqueue item to start advertising */ 52 | void start_adv_handler(struct k_work *work) 53 | { 54 | int err; 55 | char addr_s[BT_ADDR_LE_STR_LEN]; 56 | bt_addr_le_t addr = {0}; 57 | size_t count = 1; 58 | 59 | /* Customize advertising period*/ 60 | #define BT_LE_ADV_CUSTOM BT_LE_ADV_PARAM(BT_LE_ADV_OPT_USE_IDENTITY, \ 61 | BT_GAP_ADV_SLOW_INT_MIN, \ 62 | BT_GAP_ADV_SLOW_INT_MAX, \ 63 | NULL) 64 | 65 | 66 | err = bt_le_adv_start(BT_LE_ADV_CUSTOM, ad, ARRAY_SIZE(ad), 67 | sd, ARRAY_SIZE(sd)); 68 | if (err) { 69 | printk("Advertising failed to start (err %d)\n", err); 70 | return; 71 | } 72 | 73 | bt_id_get(&addr, &count); 74 | bt_addr_le_to_str(&addr, addr_s, sizeof(addr_s)); 75 | 76 | printk("Beacon started, advertising as %s\n", addr_s); 77 | 78 | k_work_reschedule(&stop_adv_work, ACTIVE_TIME); 79 | } 80 | 81 | /* Delayable workqueue item do stop advertising*/ 82 | 83 | void stop_adv_handler(struct k_work *work) 84 | { 85 | int err; 86 | 87 | err = bt_le_adv_stop(); 88 | if (err) { 89 | printk("Advertising failed to stop (err %d)\n", err); 90 | return; 91 | } 92 | printk("Beacon stoped\n"); 93 | k_work_reschedule(&start_adv_work, SLEEP_TIME); 94 | 95 | } 96 | 97 | static void bt_ready(int err) 98 | { 99 | if (err) { 100 | printk("Bluetooth init failed (err %d)\n", err); 101 | return; 102 | } 103 | 104 | printk("Bluetooth initialized\n"); 105 | 106 | k_work_init_delayable(&start_adv_work, start_adv_handler); 107 | k_work_init_delayable(&stop_adv_work, stop_adv_handler); 108 | 109 | /* Start advertising */ 110 | k_work_reschedule(&start_adv_work, K_NO_WAIT); 111 | 112 | /* For connectable advertising you would use 113 | * bt_le_oob_get_local(). For non-connectable non-identity 114 | * advertising an non-resolvable private address is used; 115 | * there is no API to retrieve that. 116 | */ 117 | } 118 | 119 | int main(void) 120 | { 121 | int err; 122 | 123 | printk("Starting Beacon Demo\n"); 124 | 125 | /* Initialize the Bluetooth Subsystem */ 126 | err = bt_enable(bt_ready); 127 | if (err) { 128 | printk("Bluetooth init failed (err %d)\n", err); 129 | } 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /lora_overlay/boards/nrf52840dk_nrf52840.overlay: -------------------------------------------------------------------------------- 1 | #include 2 | / { 3 | aliases { 4 | lora0 = &lora; 5 | }; 6 | }; 7 | 8 | &spi1 { 9 | lora: lora@0 { 10 | compatible = "semtech,sx1262"; 11 | reg = <0>; 12 | reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; 13 | busy-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; 14 | tx-enable-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; 15 | rx-enable-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; 16 | dio1-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>; 17 | dio2-tx-enable; 18 | dio3-tcxo-voltage = ; 19 | tcxo-power-startup-delay-ms = <5>; 20 | spi-max-frequency = <1000000>; 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 5 | project(beacon) 6 | 7 | target_sources(app PRIVATE src/main.c) 8 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/README.rst: -------------------------------------------------------------------------------- 1 | .. _bluetooth-beacon-sample: 2 | 3 | Bluetooth: Beacon 4 | ################# 5 | 6 | Overview 7 | ******** 8 | 9 | A simple application demonstrating the BLE Broadcaster role functionality by 10 | advertising an Eddystone URL (the Zephyr website). 11 | 12 | 13 | 14 | Requirements 15 | ************ 16 | 17 | * BlueZ running on the host, or 18 | * A board with BLE support 19 | 20 | Building and Running 21 | ******************** 22 | 23 | This sample can be found under :zephyr_file:`samples/bluetooth/beacon` in the 24 | Zephyr tree. 25 | 26 | See :ref:`bluetooth samples section ` for details. 27 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/boards/nrf9160dk_nrf9160_ns.conf: -------------------------------------------------------------------------------- 1 | CONFIG_NRF_SW_LPUART=y 2 | CONFIG_NRF_SW_LPUART_INT_DRIVEN=y 3 | 4 | CONFIG_UART_2_ASYNC=y 5 | CONFIG_UART_2_INTERRUPT_DRIVEN=n 6 | CONFIG_UART_2_NRF_HW_ASYNC=y 7 | CONFIG_UART_2_NRF_HW_ASYNC_TIMER=2 8 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/boards/nrf9160dk_nrf9160_ns.overlay: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | / { 4 | chosen { 5 | zephyr,bt-uart=&lpuart; 6 | }; 7 | }; 8 | 9 | &gpiote { 10 | interrupts = <49 NRF_DEFAULT_IRQ_PRIORITY>; 11 | }; 12 | 13 | &uart2 { 14 | current-speed = <1000000>; 15 | status = "okay"; 16 | /delete-property/ hw-flow-control; 17 | 18 | pinctrl-0 = <&uart2_default_alt>; 19 | pinctrl-1 = <&uart2_sleep_alt>; 20 | pinctrl-names = "default", "sleep"; 21 | lpuart: nrf-sw-lpuart { 22 | compatible = "nordic,nrf-sw-lpuart"; 23 | status = "okay"; 24 | label = "LPUART"; 25 | req-pin = <21>; /* <&interface_to_nrf52840 3 0>; */ 26 | rdy-pin = <19>; /* <&interface_to_nrf52840 2 0>; */ 27 | }; 28 | }; 29 | 30 | &pinctrl { 31 | uart2_default_alt: uart2_default_alt { 32 | group1 { 33 | psels = , 34 | ; 35 | }; 36 | }; 37 | 38 | uart2_sleep_alt: uart2_sleep_alt { 39 | group1 { 40 | psels = , 41 | ; 42 | low-power-enable; 43 | }; 44 | }; 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/boards/nrf9160dk_nrf9160_ns_0_14_0.overlay: -------------------------------------------------------------------------------- 1 | /* Use the reset line that is available starting from v0.14.0 of the DK. */ 2 | #include 3 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/boards/rv32m1_vega_ri5cy.overlay: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 NXP 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | &lptmr1 { 8 | interrupt-parent = <&intmux0_ch2>; 9 | }; 10 | 11 | &intmux0_ch2 { 12 | status = "okay"; 13 | }; 14 | 15 | &intmux0_ch3 { 16 | status = "okay"; 17 | }; 18 | 19 | &generic_fsk { 20 | interrupt-parent = <&intmux0_ch3>; 21 | status = "okay"; 22 | }; 23 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/child_image/spm.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | # This sample runs as a non-secure application on nRF91. Therefore, it 8 | # requires the secure_partition_manager that prepares the required 9 | # peripherals to be available for the application. 10 | # 11 | # Configure the SPM image to enable the peripherals that this sample 12 | # needs. 13 | 14 | # Set UARTE2 as non-secure, used for HCI 15 | CONFIG_NRF_UARTE2_SECURE=n 16 | 17 | # Temporary mitigation for NCSIDB-356 18 | CONFIG_ZERO_LATENCY_IRQS=n 19 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | CONFIG_BT_DEBUG_LOG=y 3 | CONFIG_BT_DEVICE_NAME="nRF9160DK Beacon" 4 | 5 | #Aditional configuration for BLE through HCI 6 | CONFIG_BT_H4=y 7 | CONFIG_BT_WAIT_NOP=y 8 | CONFIG_UART_INTERRUPT_DRIVEN=y 9 | 10 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: Bluetooth Beacon 3 | tests: 4 | sample.bluetooth.beacon: 5 | harness: bluetooth 6 | platform_allow: qemu_cortex_m3 qemu_x86 nrf52dk_nrf52832 7 | tags: bluetooth 8 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/beacon/src/main.c: -------------------------------------------------------------------------------- 1 | /* main.c - Application main entry point */ 2 | 3 | /* 4 | * Copyright (c) 2015-2016 Intel Corporation 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #define DEVICE_NAME CONFIG_BT_DEVICE_NAME 18 | #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) 19 | 20 | /* 21 | * Set Advertisement data. Based on the Eddystone specification: 22 | * https://github.com/google/eddystone/blob/master/protocol-specification.md 23 | * https://github.com/google/eddystone/tree/master/eddystone-url 24 | */ 25 | static const struct bt_data ad[] = { 26 | BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR), 27 | BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0xaa, 0xfe), 28 | BT_DATA_BYTES(BT_DATA_SVC_DATA16, 29 | 0xaa, 0xfe, /* Eddystone UUID */ 30 | 0x10, /* Eddystone-URL frame type */ 31 | 0x00, /* Calibrated Tx power at 0m */ 32 | 0x00, /* URL Scheme Prefix http://www. */ 33 | 'z', 'e', 'p', 'h', 'y', 'r', 34 | 'p', 'r', 'o', 'j', 'e', 'c', 't', 35 | 0x08) /* .org */ 36 | }; 37 | 38 | /* Set Scan Response data */ 39 | static const struct bt_data sd[] = { 40 | BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), 41 | }; 42 | 43 | static void bt_ready(int err) 44 | { 45 | char addr_s[BT_ADDR_LE_STR_LEN]; 46 | bt_addr_le_t addr = {0}; 47 | size_t count = 1; 48 | 49 | if (err) { 50 | printk("Bluetooth init failed (err %d)\n", err); 51 | return; 52 | } 53 | 54 | printk("Bluetooth initialized\n"); 55 | 56 | /* Start advertising */ 57 | err = bt_le_adv_start(BT_LE_ADV_NCONN_IDENTITY, ad, ARRAY_SIZE(ad), 58 | sd, ARRAY_SIZE(sd)); 59 | if (err) { 60 | printk("Advertising failed to start (err %d)\n", err); 61 | return; 62 | } 63 | 64 | 65 | /* For connectable advertising you would use 66 | * bt_le_oob_get_local(). For non-connectable non-identity 67 | * advertising an non-resolvable private address is used; 68 | * there is no API to retrieve that. 69 | */ 70 | 71 | bt_id_get(&addr, &count); 72 | bt_addr_le_to_str(&addr, addr_s, sizeof(addr_s)); 73 | 74 | printk("Beacon started, advertising as %s\n", addr_s); 75 | } 76 | 77 | void main(void) 78 | { 79 | int err; 80 | 81 | printk("Starting Beacon Demo\n"); 82 | 83 | /* Initialize the Bluetooth Subsystem */ 84 | err = bt_enable(bt_ready); 85 | if (err) { 86 | printk("Bluetooth init failed (err %d)\n", err); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "nrf-connect.topdir": "${nrf-connect.sdk:2.0.0}", 3 | "nrf-connect.toolchain.path": "${nrf-connect.toolchain:2.0.0}", 4 | "nrf-connect.applications": [ 5 | "c:\\Work\\nrf-examples\\lp_hci_nrf9160dk\\hci_lpuart", 6 | "c:\\Work\\nrf-examples\\lp_hci_nrf9160dk\\lte_ble_gateway" 7 | ] 8 | } -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hci_lpuart) 7 | 8 | # NORDIC SDK APP START 9 | target_sources(app PRIVATE ${ZEPHYR_BASE}/samples/bluetooth/hci_uart/src/main.c) 10 | # NORDIC SDK APP END 11 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/README.rst: -------------------------------------------------------------------------------- 1 | .. _bluetooth-hci-lpuart-sample: 2 | 3 | Bluetooth: HCI low power UART 4 | ############################# 5 | 6 | .. contents:: 7 | :local: 8 | :depth: 2 9 | 10 | The HCI low power UART sample is based on the :ref:`zephyr:bluetooth-hci-uart-sample` but is using the :ref:`uart_nrf_sw_lpuart` for HCI UART communication. 11 | 12 | Requirements 13 | ************ 14 | 15 | The sample supports the following development kit: 16 | 17 | .. table-from-sample-yaml:: 18 | 19 | Overview 20 | ******** 21 | 22 | The sample implements the Bluetooth® HCI controller using the :ref:`uart_nrf_sw_lpuart` for UART communication. 23 | 24 | This sample is also supported on the Thingy:91. 25 | However, it must be programmed using a debugger and a 10-pin SWD cable. 26 | Firmware updates over serial using MCUboot are not supported for either of the MCUs on the Thingy:91 in this configuration. 27 | 28 | Building and running 29 | ******************** 30 | 31 | .. |sample path| replace:: :file:`samples/bluetooth/hci_lpuart` 32 | 33 | .. include:: /includes/build_and_run.txt 34 | 35 | Programming the sample 36 | ====================== 37 | 38 | To program the nRF9160 development kit with the sample: 39 | 40 | 1. Set the **SW10** switch, marked as debug/prog, in the **NRF52** position. 41 | In nRF9160 DK v0.9.0 and earlier, the switch is called **SW5** 42 | #. Build the :ref:`bluetooth-hci-lpuart-sample` sample for the nrf9160dk_nrf52840 build target and program the development kit with it. 43 | 44 | Testing 45 | ======= 46 | 47 | The methodology to use to test this sample depends on the host application. 48 | 49 | Dependencies 50 | ************ 51 | 52 | This sample uses the following |NCS| driver: 53 | 54 | * :ref:`uart_nrf_sw_lpuart` 55 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/boards/nrf9160dk_nrf52840.conf: -------------------------------------------------------------------------------- 1 | # Override prj.conf defaults 2 | 3 | CONFIG_GPIO=y 4 | CONFIG_MAIN_STACK_SIZE=1024 5 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 6 | CONFIG_BT_MAX_CONN=16 7 | CONFIG_BT_TINYCRYPT_ECC=n 8 | CONFIG_BT_CTLR_DTM_HCI=y 9 | CONFIG_BT_CTLR_ASSERT_HANDLER=y 10 | 11 | CONFIG_UART_1_ASYNC=y 12 | CONFIG_UART_1_INTERRUPT_DRIVEN=n 13 | CONFIG_UART_1_NRF_HW_ASYNC=y 14 | CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2 15 | CONFIG_NRF_SW_LPUART=y 16 | CONFIG_NRF_SW_LPUART_INT_DRIVEN=y 17 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/boards/nrf9160dk_nrf52840.overlay: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | 3 | #include 4 | #include 5 | 6 | &pinctrl { 7 | uart0_default_alt: uart0_default_alt { 8 | group1 { 9 | psels = ; 10 | }; 11 | }; 12 | 13 | uart0_sleep_alt: uart0_sleep_alt { 14 | group1 { 15 | psels = ; 16 | low-power-enable; 17 | }; 18 | }; 19 | 20 | uart1_default_alt: uart1_default_alt { 21 | group1 { 22 | psels = , 23 | ; 24 | }; 25 | }; 26 | 27 | uart1_sleep_alt: uart1_sleep_alt { 28 | group1 { 29 | psels = , 30 | ; 31 | low-power-enable; 32 | }; 33 | }; 34 | 35 | }; 36 | 37 | &uart1 { 38 | current-speed = <1000000>; 39 | pinctrl-0 = <&uart1_default_alt>; 40 | pinctrl-1 = <&uart1_sleep_alt>; 41 | pinctrl-names = "default", "sleep"; 42 | 43 | lpuart: nrf-sw-lpuart { 44 | compatible = "nordic,nrf-sw-lpuart"; 45 | status = "okay"; 46 | label = "LPUART"; 47 | req-pin = <15>; /* <&interface_to_nrf9160 2 0>; */ 48 | rdy-pin = <22>; /* <&interface_to_nrf9160 3 0>; */ 49 | }; 50 | }; 51 | 52 | / { 53 | chosen { 54 | zephyr,bt-c2h-uart=&lpuart; 55 | }; 56 | }; 57 | 58 | &gpiote { 59 | interrupts = <6 NRF_DEFAULT_IRQ_PRIORITY>; 60 | }; 61 | 62 | /* Disabling uart rx pin to get low power */ 63 | &uart0 { 64 | pinctrl-0 = <&uart0_default_alt>; 65 | pinctrl-1 = <&uart0_sleep_alt>; 66 | pinctrl-names = "default", "sleep"; 67 | disable-rx; 68 | }; 69 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/boards/nrf9160dk_nrf52840_0_14_0.overlay: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | 3 | /* Use the reset line that is available starting from v0.14.0 of the DK. */ 4 | #include 5 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/boards/thingy91_nrf52840.conf: -------------------------------------------------------------------------------- 1 | # Override prj.conf defaults 2 | 3 | CONFIG_GPIO=y 4 | CONFIG_BT_CTLR=y 5 | CONFIG_MAIN_STACK_SIZE=1024 6 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 7 | CONFIG_BT_WAIT_NOP=y 8 | CONFIG_BT_MAX_CONN=16 9 | CONFIG_BT_TINYCRYPT_ECC=n 10 | CONFIG_BT_CTLR_DTM_HCI=y 11 | CONFIG_BT_CTLR_ASSERT_HANDLER=y 12 | 13 | CONFIG_UART_1_ASYNC=y 14 | CONFIG_UART_1_INTERRUPT_DRIVEN=n 15 | CONFIG_UART_1_NRF_HW_ASYNC=y 16 | CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2 17 | CONFIG_NRF_SW_LPUART=y 18 | CONFIG_NRF_SW_LPUART_INT_DRIVEN=y 19 | 20 | CONFIG_GPIO_AS_PINRESET=y 21 | 22 | CONFIG_USE_SEGGER_RTT=y 23 | CONFIG_RTT_CONSOLE=y 24 | CONFIG_UART_CONSOLE=n 25 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/boards/thingy91_nrf52840.overlay: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | 3 | / { 4 | chosen { 5 | zephyr,bt-c2h-uart=&lpuart; 6 | }; 7 | }; 8 | 9 | &uart1 { 10 | current-speed = <1000000>; 11 | status = "okay"; 12 | 13 | pinctrl-0 = <&uart1_default_alt>; 14 | pinctrl-1 = <&uart1_sleep_alt>; 15 | pinctrl-names = "default", "sleep"; 16 | lpuart: nrf-sw-lpuart { 17 | compatible = "nordic,nrf-sw-lpuart"; 18 | status = "okay"; 19 | label = "LPUART"; 20 | req-pin = <22>; 21 | rdy-pin = <19>; 22 | }; 23 | }; 24 | 25 | &gpiote { 26 | interrupts = <6 NRF_DEFAULT_IRQ_PRIORITY>; 27 | }; 28 | 29 | /* Disabling uart rx pin to get low power */ 30 | &uart0 { 31 | compatible = "nordic,nrf-uart"; 32 | disable-rx; 33 | }; 34 | 35 | &pinctrl { 36 | uart1_default_alt: uart1_default_alt { 37 | group1 { 38 | psels = , 39 | ; 40 | }; 41 | }; 42 | 43 | uart1_sleep_alt: uart1_sleep_alt { 44 | group1 { 45 | psels = , 46 | ; 47 | low-power-enable; 48 | }; 49 | }; 50 | }; 51 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/debug.conf: -------------------------------------------------------------------------------- 1 | CONFIG_ASSERT=y 2 | 3 | CONFIG_THREAD_NAME=y 4 | CONFIG_THREAD_ANALYZER=y 5 | CONFIG_THREAD_ANALYZER_AUTO=y 6 | CONFIG_THREAD_ANALYZER_RUN_UNLOCKED=y 7 | 8 | CONFIG_HW_STACK_PROTECTION=y 9 | 10 | CONFIG_CONSOLE=y 11 | CONFIG_BT_DEBUG_LOG=y 12 | CONFIG_LOG_BUFFER_SIZE=4096 13 | CONFIG_RTT_CONSOLE=y 14 | CONFIG_LOG_BACKEND_RTT=y 15 | CONFIG_LOG_BACKEND_RTT_MODE_DROP=n 16 | CONFIG_USE_SEGGER_RTT=y 17 | CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096 18 | CONFIG_LOG_BACKEND_SHOW_COLOR=n 19 | CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=1024 20 | 21 | CONFIG_LOG_DEFAULT_LEVEL=3 22 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_SERIAL=y 2 | CONFIG_UART_INTERRUPT_DRIVEN=y 3 | CONFIG_BT=y 4 | CONFIG_BT_HCI_RAW=y 5 | CONFIG_BT_HCI_RAW_H4=y 6 | CONFIG_BT_HCI_RAW_H4_ENABLE=y 7 | CONFIG_BT_BUF_ACL_RX_SIZE=251 8 | CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 9 | 10 | # Mitigation for NCSIDB-356 11 | CONFIG_BT_LL_SW_SPLIT=y 12 | CONFIG_ZERO_LATENCY_IRQS=n 13 | -------------------------------------------------------------------------------- /lp_hci_nrf9160dk/hci_lpuart/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: TBD 3 | name: TBD 4 | tests: 5 | sample.bluetooth.hci_lpuart: 6 | platform_allow: nrf9160dk_nrf52840 7 | integration_platforms: 8 | - nrf9160dk_nrf52840 9 | tags: uart bluetooth 10 | -------------------------------------------------------------------------------- /lte_tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.20.0) 8 | 9 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 10 | project(cellular_fundamentals) 11 | 12 | # NORDIC SDK APP START 13 | target_sources(app PRIVATE src/main.c) 14 | # NORDIC SDK APP END 15 | -------------------------------------------------------------------------------- /lte_tests/Kconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | menu "nRF91 Simple Tracker" 8 | 9 | config TRACKER_VERSION_MAJOR 10 | int "Major verison number" 11 | default 0 12 | 13 | config TRACKER_VERSION_MINOR 14 | int "Minor verison number" 15 | default 2 16 | 17 | config TRACKER_VERSION_PATCH 18 | int "Patch verison number" 19 | default 1 20 | 21 | config COAP_DEVICE_NAME 22 | string "Device resource name - this will be the device name on the CoAP server" 23 | default "cali.test.nrf91" 24 | 25 | config COAP_POST_RESOURCE 26 | string "Parent CoAP resource - this is the parent resource of your device resource name" 27 | default "echo" 28 | 29 | config COAP_SERVER_HOSTNAME 30 | string "CoAP server hostname" 31 | default "californium.eclipseprojects.io" 32 | 33 | config COAP_SERVER_PORT 34 | int "CoAP server port" 35 | default 5684 36 | 37 | config COAP_SERVER_PSK 38 | string "Server PSK" 39 | default "2e666f726e69756d" 40 | 41 | config TRACKER_PERIODIC_INTERVAL 42 | int "Fix interval for periodic GPS fixes. This determines your tracking frequency" 43 | range 10 65535 44 | default 120 45 | help 46 | Fix interval (in seconds) for periodic fixes. 47 | 48 | config TRACKER_PERIODIC_TIMEOUT 49 | int "Fix timeout for periodic GPS fixes" 50 | range 0 65535 51 | default 600 52 | help 53 | Fix timeout (in seconds) for periodic fixes. 54 | If set to zero, GNSS is allowed to run indefinitely until a valid PVT estimate is produced. 55 | 56 | config GNSS_LOW_ACCURACY 57 | bool "Allow low accuracy fixes." 58 | help 59 | Helps with faster fixes.GNSS demonstrates a looser acceptance criterion for a fix. 60 | 61 | config GNSS_HIGH_ACCURACY_TIMING_SOURCE 62 | bool "Use Crystal oscillator" 63 | help 64 | Use crystal oscillator (TCXO) timing source for the GNSS interface 65 | instead of the default Real time clock (RTC).TCXO has higher power consumption than RTC 66 | 67 | endmenu 68 | 69 | menu "Zephyr Kernel" 70 | source "Kconfig.zephyr" 71 | endmenu 72 | -------------------------------------------------------------------------------- /lte_tests/prj.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2019 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | # Logging 8 | CONFIG_LOG=y 9 | CONFIG_LOG_PRINTK=y 10 | 11 | # Button and LED support 12 | CONFIG_DK_LIBRARY=y 13 | 14 | # Newlib 15 | CONFIG_NEWLIB_LIBC=y 16 | CONFIG_FPU=y 17 | CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y 18 | 19 | # Networking 20 | CONFIG_NETWORKING=y 21 | CONFIG_NET_NATIVE=n 22 | CONFIG_NET_SOCKETS_OFFLOAD=y 23 | CONFIG_NET_SOCKETS=y 24 | CONFIG_NET_SOCKETS_POSIX_NAMES=y 25 | 26 | # Memory 27 | CONFIG_MAIN_STACK_SIZE=8192 28 | CONFIG_HEAP_MEM_POOL_SIZE=8192 29 | 30 | # Modem library 31 | CONFIG_NRF_MODEM_LIB=y 32 | CONFIG_MODEM_KEY_MGMT=y 33 | 34 | # LTE link control 35 | CONFIG_LTE_LINK_CONTROL=y 36 | CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS=y 37 | 38 | # AT commands interface 39 | CONFIG_AT_HOST_LIBRARY=n 40 | CONFIG_UART_INTERRUPT_DRIVEN=y 41 | 42 | # CoAP 43 | CONFIG_COAP=y 44 | CONFIG_COAP_DEVICE_NAME="" -------------------------------------------------------------------------------- /lte_tests/release.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | # Release Kconfig fragment to disable debug features 7 | # This should be included as a Kconfig fragment 8 | CONFIG_BOOT_BANNER=n 9 | CONFIG_CONSOLE=n 10 | CONFIG_UART_CONSOLE=n 11 | CONFIG_USE_SEGGER_RTT=n 12 | CONFIG_SERIAL=n 13 | CONFIG_LOG=n 14 | CONFIG_ASSERT_VERBOSE=n 15 | CONFIG_PRINTK=n 16 | CONFIG_THREAD_NAME=n -------------------------------------------------------------------------------- /lte_tests/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: Cellular IoT Fundamentals Course 3 | tests: 4 | samples.cellular.fundamentals_course: 5 | build_only: true 6 | platform_allow: nrf9161dk_nrf9161_ns nrf9160dk_nrf9160_ns thingy91_nrf9160_ns 7 | integration_platforms: 8 | - nrf9161dk_nrf9161_ns 9 | - nrf9160dk_nrf9160_ns 10 | - thingy91_nrf9160_ns 11 | tags: ci_build 12 | -------------------------------------------------------------------------------- /lte_tests/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clausee 5 | * Th 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #if NCS_VERSION_NUMBER < 0x20600 22 | #include 23 | #else 24 | #include 25 | #endif 26 | 27 | #define SEC_TAG 12 28 | #define APP_COAP_SEND_INTERVAL_MS 60000 29 | #define APP_COAP_MAX_MSG_LEN 1280 30 | #define APP_COAP_VERSION 1 31 | static int sock; 32 | static struct sockaddr_storage server; 33 | static uint16_t next_token; 34 | K_SEM_DEFINE(lte_connected, 0, 1); 35 | K_SEM_DEFINE(gnss_fix_sem, 0, 1); 36 | LOG_MODULE_REGISTER(Cellfund_Project, LOG_LEVEL_INF); 37 | static uint8_t coap_buf[APP_COAP_MAX_MSG_LEN]; 38 | static uint8_t coap_sendbug[64]; 39 | static struct nrf_modem_gnss_pvt_data_frame current_pvt; 40 | static struct nrf_modem_gnss_pvt_data_frame last_pvt; 41 | static enum tracker_status {status_nolte = DK_LED1, status_searching = DK_LED2, status_fixed = DK_LED3} device_status; 42 | static int resolve_address_lock = 0; 43 | static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data) 44 | { 45 | printk("Latitude: %.06f\n", pvt_data->latitude); 46 | printk("Longitude: %.06f\n", pvt_data->longitude); 47 | printk("Altitude: %.01f m\n", pvt_data->altitude); 48 | printk("Time (UTC): %02u:%02u:%02u.%03u\n", 49 | pvt_data->datetime.hour, 50 | pvt_data->datetime.minute, 51 | pvt_data->datetime.seconds, 52 | pvt_data->datetime.ms); 53 | } 54 | 55 | static void gnss_event_handler(int event) 56 | { 57 | int retval; 58 | switch (event) { 59 | case NRF_MODEM_GNSS_EVT_PVT: 60 | LOG_INF("Searching for GNSS Satellites....\n\r"); 61 | device_status = status_searching; 62 | break; 63 | case NRF_MODEM_GNSS_EVT_FIX: 64 | LOG_INF("GNSS fix event\n\r"); 65 | break; 66 | case NRF_MODEM_GNSS_EVT_PERIODIC_WAKEUP: 67 | LOG_INF("GNSS woke up in periodic mode\n\r"); 68 | break; 69 | case NRF_MODEM_GNSS_EVT_BLOCKED: 70 | LOG_INF("GNSS is blocked by LTE event\n\r"); 71 | break; 72 | case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_FIX: 73 | LOG_INF("GNSS enters sleep because fix was achieved in periodic mode\n\r"); 74 | device_status = status_fixed; 75 | retval = nrf_modem_gnss_read(&last_pvt, sizeof(last_pvt), NRF_MODEM_GNSS_DATA_PVT); 76 | if (retval == 0){ 77 | current_pvt = last_pvt; 78 | print_fix_data(¤t_pvt); 79 | k_sem_give(&gnss_fix_sem); 80 | } 81 | break; 82 | case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_TIMEOUT: 83 | LOG_INF("GNSS enters sleep because fix retry timeout was reached\n\r"); 84 | break; 85 | 86 | default: 87 | 88 | break; 89 | } 90 | } 91 | 92 | static int gnss_init_and_start(void) 93 | { 94 | #if defined(CONFIG_GNSS_HIGH_ACCURACY_TIMING_SOURCE) 95 | if (nrf_modem_gnss_timing_source_set(NRF_MODEM_GNSS_TIMING_SOURCE_TCXO)){ 96 | LOG_ERR("Failed to set TCXO timing source"); 97 | return -1; 98 | } 99 | #endif 100 | #if defined(CONFIG_GNSS_LOW_ACCURACY) || defined (CONFIG_BOARD_THINGY91_NRF9160_NS) 101 | uint8_t use_case; 102 | use_case = NRF_MODEM_GNSS_USE_CASE_MULTIPLE_HOT_START | NRF_MODEM_GNSS_USE_CASE_LOW_ACCURACY; 103 | if (nrf_modem_gnss_use_case_set(use_case) != 0) { 104 | LOG_ERR("Failed to set low accuracy use case"); 105 | return -1; 106 | } 107 | #endif 108 | /* Configure GNSS event handler . */ 109 | if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) { 110 | LOG_ERR("Failed to set GNSS event handler"); 111 | return -1; 112 | } 113 | 114 | if (nrf_modem_gnss_fix_interval_set(CONFIG_TRACKER_PERIODIC_INTERVAL) != 0) { 115 | LOG_ERR("Failed to set GNSS fix interval"); 116 | return -1; 117 | } 118 | 119 | if (nrf_modem_gnss_fix_retry_set(CONFIG_TRACKER_PERIODIC_TIMEOUT) != 0) { 120 | LOG_ERR("Failed to set GNSS fix retry"); 121 | return -1; 122 | } 123 | 124 | if (nrf_modem_gnss_start() != 0) { 125 | LOG_ERR("Failed to start GNSS"); 126 | return -1; 127 | } 128 | if (nrf_modem_gnss_prio_mode_enable() != 0){ 129 | LOG_ERR("Error setting GNSS priority mode"); 130 | return -1; 131 | } 132 | return 0; 133 | } 134 | 135 | /**@brief Resolves the configured hostname. */ 136 | static int server_resolve(void) 137 | { 138 | int err; 139 | struct addrinfo *result; 140 | struct addrinfo hints = { 141 | .ai_family = AF_INET, 142 | .ai_socktype = SOCK_DGRAM 143 | }; 144 | char ipv4_addr[NET_IPV4_ADDR_LEN]; 145 | 146 | err = getaddrinfo(CONFIG_COAP_SERVER_HOSTNAME, NULL, &hints, &result); 147 | if (err != 0) { 148 | LOG_ERR("ERROR: getaddrinfo failed %d\n", err); 149 | return -EIO; 150 | } 151 | 152 | if (result == NULL) { 153 | LOG_ERR("ERROR: Address not found\n"); 154 | return -ENOENT; 155 | } 156 | 157 | /* IPv4 Address. */ 158 | struct sockaddr_in *server4 = ((struct sockaddr_in *)&server); 159 | 160 | server4->sin_addr.s_addr = 161 | ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr; 162 | server4->sin_family = AF_INET; 163 | server4->sin_port = htons(CONFIG_COAP_SERVER_PORT); 164 | 165 | inet_ntop(AF_INET, &server4->sin_addr.s_addr, ipv4_addr, 166 | sizeof(ipv4_addr)); 167 | LOG_INF("IPv4 Address found %s\n", ipv4_addr); 168 | 169 | /* Free the address. */ 170 | freeaddrinfo(result); 171 | 172 | return 0; 173 | } 174 | 175 | /**@brief Initialize the CoAP client */ 176 | static int server_connect(void) 177 | { 178 | int err; 179 | 180 | sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_DTLS_1_2); 181 | if (sock < 0) { 182 | LOG_ERR("Failed to create CoAP socket: %d.\n", errno); 183 | return -errno; 184 | } 185 | 186 | int verify; 187 | sec_tag_t sec_tag_list[] = { 12 }; 188 | 189 | enum { 190 | NONE = 0, 191 | OPTIONAL = 1, 192 | REQUIRED = 2, 193 | }; 194 | 195 | verify = REQUIRED; 196 | 197 | err = setsockopt(sock, SOL_TLS, TLS_PEER_VERIFY, &verify, sizeof(verify)); 198 | if (err) { 199 | LOG_ERR("Failed to setup peer verification, errno %d\n", errno); 200 | return -errno; 201 | } 202 | 203 | err = setsockopt(sock, SOL_TLS, TLS_HOSTNAME, CONFIG_COAP_SERVER_HOSTNAME, 204 | strlen(CONFIG_COAP_SERVER_HOSTNAME)); 205 | if (err) { 206 | LOG_ERR("Failed to setup TLS hostname (%s), errno %d\n", 207 | CONFIG_COAP_SERVER_HOSTNAME, errno); 208 | return -errno; 209 | } 210 | 211 | err = setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_list, 212 | sizeof(sec_tag_t) * ARRAY_SIZE(sec_tag_list)); 213 | if (err) { 214 | LOG_ERR("Failed to setup socket security tag, errno %d\n", errno); 215 | return -errno; 216 | } 217 | 218 | err = connect(sock, (struct sockaddr *)&server, 219 | sizeof(struct sockaddr_in)); 220 | if (err < 0) { 221 | LOG_ERR("Connect failed : %d\n", errno); 222 | return -errno; 223 | } 224 | 225 | /* Randomize token. */ 226 | next_token = sys_rand32_get(); 227 | 228 | return 0; 229 | } 230 | 231 | /**@brief Handles responses from the remote CoAP server. */ 232 | static int client_handle_get_response(uint8_t *buf, int received) 233 | { 234 | int err; 235 | struct coap_packet reply; 236 | const uint8_t *payload; 237 | uint16_t payload_len; 238 | uint8_t token[8]; 239 | uint16_t token_len; 240 | static uint8_t temp_buf[128]; 241 | 242 | err = coap_packet_parse(&reply, buf, received, NULL, 0); 243 | if (err < 0) { 244 | LOG_ERR("Malformed response received: %d\n", err); 245 | return err; 246 | } 247 | 248 | payload = coap_packet_get_payload(&reply, &payload_len); 249 | token_len = coap_header_get_token(&reply, token); 250 | 251 | if ((token_len != sizeof(next_token)) || 252 | (memcmp(&next_token, token, sizeof(next_token)) != 0)) { 253 | LOG_ERR("Invalid token received: 0x%02x%02x\n", 254 | token[1], token[0]); 255 | return 0; 256 | } 257 | 258 | if (payload_len > 0) { 259 | snprintf(temp_buf, MIN(payload_len + 1, sizeof(temp_buf)), "%s", payload); 260 | } else { 261 | strcpy(temp_buf, "EMPTY"); 262 | } 263 | 264 | LOG_INF("CoAP response: Code 0x%x, Token 0x%02x%02x, Payload: %s", 265 | coap_header_get_code(&reply), token[1], token[0], temp_buf); 266 | return 0; 267 | } 268 | 269 | static void lte_handler(const struct lte_lc_evt *const evt) 270 | { 271 | switch (evt->type) { 272 | case LTE_LC_EVT_NW_REG_STATUS: 273 | if ((evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_HOME) && 274 | (evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_ROAMING)) { 275 | break; 276 | } 277 | 278 | LOG_INF("Network registration status: %s\n", 279 | evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ? 280 | "Connected - home network" : "Connected - roaming\n"); 281 | k_sem_give(<e_connected); 282 | break; 283 | case LTE_LC_EVT_PSM_UPDATE: 284 | LOG_INF("PSM parameter update: TAU: %d, Active time: %d\n", 285 | evt->psm_cfg.tau, evt->psm_cfg.active_time); 286 | break; 287 | case LTE_LC_EVT_EDRX_UPDATE: { 288 | char log_buf[60]; 289 | ssize_t len; 290 | 291 | len = snprintf(log_buf, sizeof(log_buf), 292 | "eDRX parameter update: eDRX: %f, PTW: %f\n", 293 | evt->edrx_cfg.edrx, evt->edrx_cfg.ptw); 294 | if (len > 0) { 295 | LOG_INF("%s\n", log_buf); 296 | } 297 | break; 298 | } 299 | case LTE_LC_EVT_RRC_UPDATE: 300 | LOG_INF("RRC mode: %s\n", 301 | evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ? 302 | "Connected" : "Idle\n"); 303 | break; 304 | case LTE_LC_EVT_CELL_UPDATE: 305 | LOG_INF("LTE cell changed: Cell ID: %d, Tracking area: %d\n", 306 | evt->cell.id, evt->cell.tac); 307 | break; 308 | default: 309 | break; 310 | } 311 | } 312 | 313 | 314 | static int modem_configure(void) 315 | { 316 | int err; 317 | 318 | LOG_INF("Initializing modem library"); 319 | 320 | err = nrf_modem_lib_init(); 321 | if (err) { 322 | LOG_ERR("Failed to initialize the modem library, error: %d", err); 323 | return err; 324 | } 325 | 326 | err = modem_key_mgmt_write(SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY, CONFIG_COAP_DEVICE_NAME, strlen(CONFIG_COAP_DEVICE_NAME)); 327 | if (err) { 328 | LOG_ERR("Failed to write identity: %d\n", err); 329 | return err; 330 | } 331 | 332 | err = modem_key_mgmt_write(SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_PSK, CONFIG_COAP_SERVER_PSK, strlen(CONFIG_COAP_SERVER_PSK)); 333 | if (err) { 334 | LOG_ERR("Failed to write identity: %d\n", err); 335 | return err; 336 | } 337 | 338 | /* lte_lc_init deprecated in >= v2.6.0 */ 339 | #if NCS_VERSION_NUMBER < 0x20600 340 | err = lte_lc_init(); 341 | if (err) { 342 | LOG_ERR("Failed to initialize LTE link control library, error: %d", err); 343 | return err; 344 | } 345 | #endif 346 | 347 | LOG_INF("Connecting to LTE network"); 348 | err = lte_lc_connect_async(lte_handler); 349 | if (err) { 350 | LOG_ERR("Error in lte_lc_connect_async, error: %d", err); 351 | return err; 352 | } 353 | 354 | 355 | /* Decativate LTE and enable GNSS. */ 356 | err = lte_lc_func_mode_set(LTE_LC_FUNC_MODE_DEACTIVATE_LTE); 357 | if (err) { 358 | LOG_ERR("Failed to decativate LTE and enable GNSS functional mode"); 359 | return err; 360 | } 361 | 362 | return 0; 363 | } 364 | 365 | 366 | static int client_post_send(void) 367 | { 368 | int err,ret; 369 | struct coap_packet request; 370 | 371 | next_token++; 372 | 373 | err = coap_packet_init(&request, coap_buf, sizeof(coap_buf), 374 | APP_COAP_VERSION, COAP_TYPE_CON, 375 | sizeof(next_token), (uint8_t *)&next_token, 376 | COAP_METHOD_POST, coap_next_id()); 377 | if (err < 0) { 378 | LOG_ERR("Failed to create CoAP request, %d\n", err); 379 | return err; 380 | } 381 | 382 | err = coap_packet_append_option(&request, COAP_OPTION_URI_PATH, 383 | (uint8_t *)CONFIG_COAP_POST_RESOURCE, 384 | strlen(CONFIG_COAP_POST_RESOURCE)); 385 | if (err < 0) { 386 | LOG_ERR("Failed to encode CoAP option, %d\n", err); 387 | return err; 388 | } 389 | 390 | err = coap_append_option_int(&request, COAP_OPTION_CONTENT_FORMAT, 391 | COAP_CONTENT_FORMAT_TEXT_PLAIN); 392 | if (err < 0) { 393 | LOG_ERR("Failed to encode CoAP CONTENT_FORMAT option, %d", err); 394 | return err; 395 | } 396 | 397 | err = coap_packet_append_option(&request, COAP_OPTION_URI_QUERY, 398 | (uint8_t *)"keep", 399 | strlen("keep")); 400 | if (err < 0) { 401 | LOG_ERR("Failed to encode CoAP URI-QUERY option 'keep', %d", err); 402 | return err; 403 | } 404 | 405 | err = coap_packet_append_payload_marker(&request); 406 | if (err < 0) { 407 | LOG_ERR("Failed to append payload marker, %d\n", err); 408 | return err; 409 | } 410 | 411 | ret = snprintf (coap_sendbug, sizeof(coap_sendbug), "%.06f,%.06f\n%.01f m\n%04u-%02u-%02u %02u:%02u:%02u", 412 | current_pvt.latitude, current_pvt.longitude,current_pvt.accuracy,current_pvt.datetime.year,current_pvt.datetime.month,current_pvt.datetime.day, 413 | current_pvt.datetime.hour, current_pvt.datetime.minute, last_pvt.datetime.seconds); 414 | if (err < 0) { 415 | LOG_ERR("snprintf failed to format string, %d\n", err); 416 | return err; 417 | } 418 | err = coap_packet_append_payload(&request, (uint8_t *)coap_sendbug, ret); 419 | if (err < 0) { 420 | LOG_ERR("Failed to append payload, %d\n", err); 421 | return err; 422 | } 423 | 424 | err = send(sock, request.data, request.offset, 0); 425 | if (err < 0) { 426 | LOG_ERR("Failed to send CoAP request, %d\n", errno); 427 | return -errno; 428 | } 429 | 430 | LOG_INF("CoAP request sent: token 0x%04x\n", next_token); 431 | 432 | return 0; 433 | } 434 | static void button_handler(uint32_t button_state, uint32_t has_changed) 435 | { 436 | static bool toogle = 1; 437 | if (has_changed & DK_BTN1_MSK && button_state & DK_BTN1_MSK) { 438 | if (toogle ==1){ 439 | dk_set_led_on(device_status); 440 | }else{ 441 | dk_set_led_off(DK_LED1); 442 | dk_set_led_off(DK_LED2); 443 | dk_set_led_off(DK_LED3); 444 | } 445 | toogle = !toogle; 446 | } 447 | } 448 | 449 | int main(void) 450 | { 451 | int err; 452 | int received; 453 | LOG_INF("The nRF91 Simple Tracker Version %d.%d.%d started\n",CONFIG_TRACKER_VERSION_MAJOR,CONFIG_TRACKER_VERSION_MINOR,CONFIG_TRACKER_VERSION_PATCH); 454 | 455 | err = dk_leds_init(); 456 | if (err){ 457 | LOG_ERR("Failed to initlize the LEDs Library"); 458 | } 459 | 460 | device_status = status_nolte; 461 | 462 | err = modem_configure(); 463 | if (err) { 464 | LOG_ERR("Failed to configure the modem"); 465 | return 0; 466 | } 467 | 468 | err = dk_buttons_init(button_handler); 469 | if (err) { 470 | LOG_ERR("Failed to initlize button handler: %d\n", err); 471 | return 0; 472 | } 473 | 474 | LOG_INF("Starting GNSS...."); 475 | gnss_init_and_start(); 476 | 477 | while (1) { 478 | k_sem_take(&gnss_fix_sem, K_FOREVER); 479 | err = lte_lc_func_mode_set(LTE_LC_FUNC_MODE_NORMAL); 480 | if (err != 0){ 481 | LOG_ERR("Failed to activate LTE"); 482 | break; 483 | } 484 | k_sem_take(<e_connected, K_FOREVER); 485 | if (resolve_address_lock == 0){ 486 | LOG_INF("Resolving the server address\n\r"); 487 | if (server_resolve() != 0) { 488 | LOG_ERR("Failed to resolve server name\n"); 489 | return 0; 490 | } 491 | resolve_address_lock = 1; 492 | } 493 | 494 | LOG_INF("Sending Data over LTE\r\n"); 495 | if (server_connect() != 0) { 496 | LOG_ERR("Failed to initialize CoAP client\n"); 497 | return 0; 498 | } 499 | 500 | if (client_post_send() != 0) { 501 | LOG_ERR("Failed to send GET request, exit...\n"); 502 | break; 503 | } 504 | 505 | received = recv(sock, coap_buf, sizeof(coap_buf), 0); 506 | if (received < 0) { 507 | LOG_ERR("Error reading response\n"); 508 | break; 509 | } else if (received == 0) { 510 | LOG_ERR("Disconnected\n"); 511 | break; 512 | } 513 | 514 | err = client_handle_get_response(coap_buf, received); 515 | if (err < 0) { 516 | LOG_ERR("Invalid response, exit...\n"); 517 | break; 518 | } 519 | 520 | (void)close(sock); 521 | 522 | err = lte_lc_func_mode_set(LTE_LC_FUNC_MODE_DEACTIVATE_LTE); 523 | if (err != 0){ 524 | LOG_ERR("Failed to decativate LTE and enable GNSS functional mode"); 525 | break; 526 | } 527 | } 528 | 529 | device_status = status_nolte; 530 | LOG_ERR("Error occoured. Shutting down modem"); 531 | (void)lte_lc_power_off(); 532 | (void)nrf_modem_lib_shutdown(); 533 | 534 | return 0; 535 | } 536 | -------------------------------------------------------------------------------- /nrf21540dk_confs/tx_10db.conf: -------------------------------------------------------------------------------- 1 | CONFIG_MPSL_FEM=y 2 | CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=10 3 | CONFIG_BT_CTLR_TX_PWR_ANTENNA=10 4 | -------------------------------------------------------------------------------- /nrf21540dk_confs/tx_20db.conf: -------------------------------------------------------------------------------- 1 | CONFIG_MPSL_FEM=y 2 | CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20 3 | CONFIG_BT_CTLR_TX_PWR_ANTENNA=20 4 | -------------------------------------------------------------------------------- /peripheral_cts_client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2020 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | cmake_minimum_required(VERSION 3.20.0) 7 | 8 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 9 | project(peripheral_cts_client) 10 | 11 | FILE(GLOB app_sources src/*.c) 12 | # NORDIC SDK APP START 13 | target_sources(app PRIVATE ${app_sources}) 14 | # NORDIC SDK APP END 15 | -------------------------------------------------------------------------------- /peripheral_cts_client/README.rst: -------------------------------------------------------------------------------- 1 | .. _peripheral_cts_client: 2 | 3 | Bluetooth: Peripheral CTS client 4 | ################################ 5 | 6 | .. contents:: 7 | :local: 8 | :depth: 2 9 | 10 | The Peripheral CTS client sample demonstrates how to use the :ref:`cts_client_readme`. 11 | 12 | Overview 13 | ******** 14 | 15 | The CTS client sample implements a Current Time Service client. It uses the Current Time Service to read the current time. The time received is printed on the UART. 16 | 17 | Requirements 18 | ************ 19 | 20 | The sample supports the following development kits: 21 | 22 | .. table-from-rows:: /includes/sample_board_rows.txt 23 | :header: heading 24 | :rows: nrf5340dk_nrf5340_cpuapp_and_cpuapp_ns, nrf52840dk_nrf52840, nrf52833dk_nrf52833, nrf52dk_nrf52832 25 | 26 | The sample also requires a device running a CTS Server to connect with (for example, a Bluetooth® Low Energy dongle and nRF Connect for Desktop). 27 | 28 | User interface 29 | ************** 30 | 31 | LED 1: 32 | * Blinks with a period of 2 seconds, duty cycle 50%, when the main loop is running. 33 | 34 | LED 2: 35 | * On when connected. 36 | 37 | Button 1: 38 | * Read the current time. 39 | 40 | Building and running 41 | ******************** 42 | .. |sample path| replace:: :file:`samples/bluetooth/peripheral_cts_client` 43 | 44 | .. include:: /includes/build_and_run.txt 45 | 46 | .. _peripheral_cts_client_testing: 47 | 48 | Testing 49 | ======= 50 | 51 | After programming the sample to your development kit, you can test it with `nRF Connect for Desktop`_ by performing the following steps. 52 | 53 | 1. |connect_terminal_specific| 54 | #. Reset the kit. 55 | #. Start `nRF Connect for Desktop`_ and select the connected dongle that is used for communication. 56 | #. Go to the :guilabel:`Server setup` tab. 57 | Click the dongle configuration and select :guilabel:`Load setup`. 58 | Load the :file:`cts_central.ncs` file that is located under :file:`samples/bluetooth/peripheral_cts_client` in the |NCS| folder structure. 59 | #. Click :guilabel:`Apply to device`. 60 | #. Go to the :guilabel:`Connection Map` tab. 61 | Click the dongle configuration and select :guilabel:`Security parameters`. 62 | Check :guilabel:`Perform Bonding`, and click :guilabel:`Apply`. 63 | #. Set the value of :guilabel:`Current Time Service` > :guilabel:`Current Time` to ``C2 07 0B 0F 0C 22 38 06 80 02`` and click Write. 64 | #. Connect to the device from nRF Connect. The device is advertising as "Nordic_CTS". 65 | #. Wait until the bond is established. Verify that the UART data is received as follows:: 66 | 67 | Connected xx:xx:xx:xx:xx:xx (random) 68 | The discovery procedure succeeded 69 | Security changed: xx:xx:xx:xx:xx:xx (random) level 2 70 | Pairing completed: xx:xx:xx:xx:xx:xx (random), bonded: 1 71 | 72 | #. Press **Button 1** on the kit. 73 | Verify that the current time printed on the UART matches the time that was input in the Current Time characteristic (UUID 0x2A2B):: 74 | 75 | Current Time: 76 | 77 | Date: 78 | Day of week Saturday 79 | Day of month 15 80 | Month of year November 81 | Year 1986 82 | 83 | Time: 84 | Hours 12 85 | Minutes 34 86 | Seconds 56 87 | Fractions 128/256 of a second 88 | 89 | Adjust Reason: 90 | Daylight savings 0 91 | Time zone 0 92 | External update 1 93 | Manual update 0 94 | 95 | #. Change the value of :guilabel:`Current Time Service` > :guilabel:`Current Time` to ``C2 07 0B 0F 0D 25 2A 06 FE 08``. It generates a notification. Verify that the current time printed on the UART matches the time that was input:: 96 | 97 | Current Time: 98 | 99 | Date: 100 | Day of week Saturday 101 | Day of month 15 102 | Month of year November 103 | Year 1986 104 | 105 | Time: 106 | Hours 13 107 | Minutes 37 108 | Seconds 42 109 | Fractions 254/256 of a second 110 | 111 | Adjust Reason: 112 | Daylight savings 1 113 | Time zone 0 114 | External update 0 115 | Manual update 0 116 | 117 | #. Disconnect the device in nRF Connect. 118 | #. As bond information is preserved by nRF Connect, you can immediately reconnect to the device by clicking the Connect button again. 119 | 120 | Dependencies 121 | ************ 122 | 123 | This sample uses the following |NCS| libraries: 124 | 125 | * :ref:`cts_client_readme` 126 | * :ref:`gatt_dm_readme` 127 | * :ref:`dk_buttons_and_leds_readme` 128 | 129 | In addition, it uses the following Zephyr libraries: 130 | 131 | * ``include/zephyr/types.h`` 132 | * ``lib/libc/minimal/include/errno.h`` 133 | * ``include/sys/printk.h`` 134 | * :ref:`zephyr:bluetooth_api`: 135 | 136 | * ``include/bluetooth/bluetooth.h`` 137 | * ``include/bluetooth/conn.h`` 138 | * ``include/bluetooth/uuid.h`` 139 | * ``include/bluetooth/gatt.h`` 140 | -------------------------------------------------------------------------------- /peripheral_cts_client/cts_central.ncs: -------------------------------------------------------------------------------- 1 | {"selectedComponent":null,"showingDeleteDialog":false,"showingClearDialog":false,"showingDiscardDialog":false,"children":{"local.server.8":{"instanceId":"local.server.8","uuid":"1800","name":"Generic Access","expanded":false,"discoveringChildren":false,"children":{"local.server.8.15":{"instanceId":"local.server.8.15","uuid":"2A00","name":"Device Name","value":[110,82,70,53,117],"properties":{"read":true,"write":true},"readPerm":"open","writePerm":"open","fixedLength":false,"maxLength":20,"expanded":false,"discoveringChildren":false,"children":{},"errorMessage":null},"local.server.8.16":{"instanceId":"local.server.8.16","uuid":"2A01","name":"Appearance","value":[0,0],"properties":{"read":true},"readPerm":"open","writePerm":"open","fixedLength":false,"maxLength":20,"expanded":false,"discoveringChildren":false,"children":{},"errorMessage":null},"local.server.8.17":{"instanceId":"local.server.8.17","uuid":"2A04","name":"Peripheral Preferred Connection Parameters","value":[255,255,255,255,0,0,255,255],"properties":{"read":true},"readPerm":"open","writePerm":"open","fixedLength":false,"maxLength":20,"expanded":false,"discoveringChildren":false,"children":{},"errorMessage":null}}},"local.server.9":{"instanceId":"local.server.9","uuid":"1801","name":"Generic Attribute","expanded":true,"discoveringChildren":false,"children":{}},"local.server.10":{"instanceId":"local.server.10","uuid":"1805","name":"Current Time Service","expanded":true,"discoveringChildren":false,"children":{"local.server.10.18":{"instanceId":"local.server.10.18","uuid":"2A2B","name":"Current Time","value":[0],"properties":{"broadcast":false,"read":false,"write":true,"notify":true,"indicate":false},"readPerm":"open","writePerm":"open","fixedLength":false,"maxLength":20,"expanded":true,"discoveringChildren":false,"children":{"local.server.10.18.19":{"instanceId":"local.server.10.18.19","uuid":"2902","name":"Client Characteristic Configuration","value":[0],"readPerm":"open","writePerm":"open","fixedLength":false,"maxLength":20,"errorMessage":null}},"errorMessage":null}}}}} -------------------------------------------------------------------------------- /peripheral_cts_client/prj.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2020 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | CONFIG_HEAP_MEM_POOL_SIZE=1024 8 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 9 | 10 | CONFIG_BT=y 11 | CONFIG_BT_PERIPHERAL=y 12 | CONFIG_BT_DEVICE_NAME="Nordic_CTS" 13 | CONFIG_BT_SMP=y 14 | CONFIG_BT_GATT_CLIENT=y 15 | CONFIG_BT_GATT_DM=y 16 | 17 | # Enable CTS client 18 | CONFIG_BT_CTS_CLIENT=y 19 | 20 | # Enable bonding 21 | CONFIG_BT_SETTINGS=y 22 | CONFIG_FLASH=y 23 | CONFIG_FLASH_PAGE_LAYOUT=y 24 | CONFIG_FLASH_MAP=y 25 | CONFIG_NVS=y 26 | CONFIG_SETTINGS=y 27 | 28 | # Enable DK LED and Buttons library 29 | CONFIG_DK_LIBRARY=y 30 | -------------------------------------------------------------------------------- /peripheral_cts_client/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: BLE CTS client sample 3 | description: Bluetooth Low Energy CTS client sample 4 | tests: 5 | samples.bluetooth.peripheral_cts_client.build: 6 | build_only: true 7 | platform_allow: nrf52dk_nrf52832 nrf52840dk_nrf52840 nrf5340dk_nrf5340_cpuapp nrf5340dk_nrf5340_cpuapp_ns 8 | integration_platforms: 9 | - nrf52dk_nrf52832 10 | - nrf52840dk_nrf52840 11 | - nrf5340dk_nrf5340_cpuapp 12 | - nrf5340dk_nrf5340_cpuapp_ns 13 | tags: bluetooth ci_build 14 | -------------------------------------------------------------------------------- /peripheral_cts_client/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include 21 | 22 | #define DEVICE_NAME CONFIG_BT_DEVICE_NAME 23 | #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) 24 | 25 | #define RUN_STATUS_LED DK_LED1 26 | #define CON_STATUS_LED DK_LED2 27 | #define RUN_LED_BLINK_INTERVAL 1000 28 | 29 | #define KEY_READ_TIME DK_BTN1_MSK 30 | 31 | static struct bt_cts_client cts_c; 32 | 33 | static bool has_cts; 34 | 35 | static const struct bt_data ad[] = { 36 | BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, 37 | (CONFIG_BT_DEVICE_APPEARANCE >> 0) & 0xff, 38 | (CONFIG_BT_DEVICE_APPEARANCE >> 8) & 0xff), 39 | BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_LIMITED | BT_LE_AD_NO_BREDR)), 40 | BT_DATA_BYTES(BT_DATA_SOLICIT16, 0x05, 0x18), 41 | BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), 42 | }; 43 | 44 | static const char *day_of_week[] = { "Unknown", "Monday", "Tuesday", 45 | "Wednesday", "Thursday", "Friday", 46 | "Saturday", "Sunday" }; 47 | 48 | static const char *month_of_year[] = { "Unknown", "January", "February", 49 | "March", "April", "May", 50 | "June", "July", "August", 51 | "September", "October", "November", 52 | "December" }; 53 | 54 | static void current_time_print(struct bt_cts_current_time *current_time) 55 | { 56 | printk("\nCurrent Time:\n"); 57 | printk("\nDate:\n"); 58 | 59 | printk("\tDay of week %s\n", 60 | day_of_week[current_time->exact_time_256.day_of_week]); 61 | 62 | if (current_time->exact_time_256.day == 0) { 63 | printk("\tDay of month Unknown\n"); 64 | } else { 65 | printk("\tDay of month %u\n", 66 | current_time->exact_time_256.day); 67 | } 68 | 69 | printk("\tMonth of year %s\n", 70 | month_of_year[current_time->exact_time_256.month]); 71 | if (current_time->exact_time_256.year == 0) { 72 | printk("\tYear Unknown\n"); 73 | } else { 74 | printk("\tYear %u\n", 75 | current_time->exact_time_256.year); 76 | } 77 | printk("\nTime:\n"); 78 | printk("\tHours %u\n", current_time->exact_time_256.hours); 79 | printk("\tMinutes %u\n", current_time->exact_time_256.minutes); 80 | printk("\tSeconds %u\n", current_time->exact_time_256.seconds); 81 | printk("\tFractions %u/256 of a second\n", 82 | current_time->exact_time_256.fractions256); 83 | 84 | printk("\nAdjust reason:\n"); 85 | printk("\tDaylight savings %x\n", 86 | current_time->adjust_reason.change_of_daylight_savings_time); 87 | printk("\tTime zone %x\n", 88 | current_time->adjust_reason.change_of_time_zone); 89 | printk("\tExternal update %x\n", 90 | current_time->adjust_reason.external_reference_time_update); 91 | printk("\tManual update %x\n", 92 | current_time->adjust_reason.manual_time_update); 93 | } 94 | 95 | static void notify_current_time_cb(struct bt_cts_client *cts_c, 96 | struct bt_cts_current_time *current_time) 97 | { 98 | current_time_print(current_time); 99 | } 100 | 101 | static void enable_notifications(void) 102 | { 103 | int err; 104 | 105 | if (has_cts && (bt_conn_get_security(cts_c.conn) >= BT_SECURITY_L2)) { 106 | err = bt_cts_subscribe_current_time(&cts_c, 107 | notify_current_time_cb); 108 | if (err) { 109 | printk("Cannot subscribe to current time value notification (err %d)\n", 110 | err); 111 | } 112 | } 113 | } 114 | 115 | static void discover_completed_cb(struct bt_gatt_dm *dm, void *ctx) 116 | { 117 | int err; 118 | 119 | printk("The discovery procedure succeeded\n"); 120 | 121 | bt_gatt_dm_data_print(dm); 122 | 123 | err = bt_cts_handles_assign(dm, &cts_c); 124 | if (err) { 125 | printk("Could not assign CTS client handles, error: %d\n", err); 126 | } else { 127 | has_cts = true; 128 | 129 | if (bt_conn_get_security(cts_c.conn) < BT_SECURITY_L2) { 130 | err = bt_conn_set_security(cts_c.conn, BT_SECURITY_L2); 131 | if (err) { 132 | printk("Failed to set security (err %d)\n", 133 | err); 134 | } 135 | } else { 136 | enable_notifications(); 137 | } 138 | } 139 | 140 | err = bt_gatt_dm_data_release(dm); 141 | if (err) { 142 | printk("Could not release the discovery data, error " 143 | "code: %d\n", 144 | err); 145 | } 146 | } 147 | 148 | static void discover_service_not_found_cb(struct bt_conn *conn, void *ctx) 149 | { 150 | printk("The service could not be found during the discovery\n"); 151 | } 152 | 153 | static void discover_error_found_cb(struct bt_conn *conn, int err, void *ctx) 154 | { 155 | printk("The discovery procedure failed, err %d\n", err); 156 | } 157 | 158 | static const struct bt_gatt_dm_cb discover_cb = { 159 | .completed = discover_completed_cb, 160 | .service_not_found = discover_service_not_found_cb, 161 | .error_found = discover_error_found_cb, 162 | }; 163 | 164 | static void connected(struct bt_conn *conn, uint8_t err) 165 | { 166 | char addr[BT_ADDR_LE_STR_LEN]; 167 | 168 | if (err) { 169 | printk("Connection failed (err 0x%02x)\n", err); 170 | return; 171 | } 172 | 173 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 174 | printk("Connected %s\n", addr); 175 | 176 | dk_set_led_on(CON_STATUS_LED); 177 | 178 | has_cts = false; 179 | 180 | err = bt_gatt_dm_start(conn, BT_UUID_CTS, &discover_cb, NULL); 181 | if (err) { 182 | printk("Failed to start discovery (err %d)\n", err); 183 | } 184 | } 185 | 186 | static void disconnected(struct bt_conn *conn, uint8_t reason) 187 | { 188 | char addr[BT_ADDR_LE_STR_LEN]; 189 | 190 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 191 | printk("Disconnected from %s (reason 0x%02x)\n", addr, reason); 192 | 193 | dk_set_led_off(CON_STATUS_LED); 194 | } 195 | 196 | static void security_changed(struct bt_conn *conn, bt_security_t level, 197 | enum bt_security_err err) 198 | { 199 | char addr[BT_ADDR_LE_STR_LEN]; 200 | 201 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 202 | 203 | if (!err) { 204 | printk("Security changed: %s level %u\n", addr, level); 205 | 206 | enable_notifications(); 207 | } else { 208 | printk("Security failed: %s level %u err %d\n", addr, level, 209 | err); 210 | } 211 | } 212 | 213 | static struct bt_conn_cb conn_callbacks = { 214 | .connected = connected, 215 | .disconnected = disconnected, 216 | .security_changed = security_changed, 217 | }; 218 | 219 | static void auth_cancel(struct bt_conn *conn) 220 | { 221 | char addr[BT_ADDR_LE_STR_LEN]; 222 | 223 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 224 | 225 | printk("Pairing cancelled: %s\n", addr); 226 | 227 | bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); 228 | } 229 | 230 | static void pairing_confirm(struct bt_conn *conn) 231 | { 232 | char addr[BT_ADDR_LE_STR_LEN]; 233 | 234 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 235 | 236 | bt_conn_auth_pairing_confirm(conn); 237 | 238 | printk("Pairing confirmed: %s\n", addr); 239 | } 240 | 241 | static void pairing_complete(struct bt_conn *conn, bool bonded) 242 | { 243 | char addr[BT_ADDR_LE_STR_LEN]; 244 | 245 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 246 | 247 | printk("Pairing completed: %s, bonded: %d\n", addr, bonded); 248 | } 249 | 250 | static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) 251 | { 252 | char addr[BT_ADDR_LE_STR_LEN]; 253 | 254 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 255 | 256 | printk("Pairing failed conn: %s, reason %d\n", addr, reason); 257 | 258 | bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); 259 | } 260 | 261 | static struct bt_conn_auth_cb conn_auth_callbacks = { 262 | .cancel = auth_cancel, 263 | .pairing_confirm = pairing_confirm, 264 | .pairing_complete = pairing_complete, 265 | .pairing_failed = pairing_failed 266 | }; 267 | 268 | static void read_current_time_cb(struct bt_cts_client *cts_c, 269 | struct bt_cts_current_time *current_time, 270 | int err) 271 | { 272 | char addr[BT_ADDR_LE_STR_LEN]; 273 | 274 | bt_addr_le_to_str(bt_conn_get_dst(cts_c->conn), addr, sizeof(addr)); 275 | 276 | if (err) { 277 | printk("Cannot read Current Time: %s, error: %d\n", addr, err); 278 | return; 279 | } 280 | 281 | current_time_print(current_time); 282 | } 283 | 284 | static void button_changed(uint32_t button_state, uint32_t has_changed) 285 | { 286 | uint32_t buttons = button_state & has_changed; 287 | int err; 288 | 289 | if (buttons & KEY_READ_TIME) { 290 | err = bt_cts_read_current_time(&cts_c, read_current_time_cb); 291 | if (err) { 292 | printk("Failed reading current time (err: %d)\n", err); 293 | } 294 | } 295 | } 296 | 297 | static int init_button(void) 298 | { 299 | int err; 300 | 301 | err = dk_buttons_init(button_changed); 302 | if (err) { 303 | printk("Cannot init buttons (err: %d)\n", err); 304 | } 305 | 306 | return err; 307 | } 308 | 309 | void main(void) 310 | { 311 | int blink_status = 0; 312 | int err; 313 | 314 | printk("Starting Current Time Service client example\n"); 315 | 316 | err = bt_cts_client_init(&cts_c); 317 | if (err) { 318 | printk("CTS client init failed (err %d)\n", err); 319 | return; 320 | } 321 | 322 | err = dk_leds_init(); 323 | if (err) { 324 | printk("LEDs init failed (err %d)\n", err); 325 | return; 326 | } 327 | 328 | err = init_button(); 329 | if (err) { 330 | printk("Button init failed (err %d)\n", err); 331 | return; 332 | } 333 | 334 | err = bt_enable(NULL); 335 | if (err) { 336 | printk("BLE init failed (err %d)\n", err); 337 | return; 338 | } 339 | 340 | if (IS_ENABLED(CONFIG_SETTINGS)) { 341 | settings_load(); 342 | } 343 | 344 | bt_conn_cb_register(&conn_callbacks); 345 | if (err) { 346 | printk("Failed to register connection callbacks\n"); 347 | return; 348 | } 349 | 350 | err = bt_conn_auth_cb_register(&conn_auth_callbacks); 351 | if (err) { 352 | printk("Failed to register authorization callbacks\n"); 353 | return; 354 | } 355 | 356 | err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); 357 | if (err) { 358 | printk("Advertising failed to start (err %d)\n", err); 359 | return; 360 | } 361 | 362 | printk("Advertising successfully started\n"); 363 | 364 | for (;;) { 365 | dk_set_led(RUN_STATUS_LED, (++blink_status) % 2); 366 | k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL)); 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /peripheral_hr_coded_multi/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp.default.configurationProvider": "nrf-connect" 3 | } -------------------------------------------------------------------------------- /peripheral_hr_coded_multi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2020 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | cmake_minimum_required(VERSION 3.20.0) 7 | 8 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 9 | project(peripheral_hr) 10 | 11 | # NORDIC SDK APP START 12 | target_sources(app PRIVATE 13 | src/main.c 14 | ) 15 | # NORDIC SDK APP END 16 | 17 | zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) 18 | -------------------------------------------------------------------------------- /peripheral_hr_coded_multi/README.rst: -------------------------------------------------------------------------------- 1 | .. _peripheral_hr_coded: 2 | 3 | Bluetooth: Peripheral Heart Rate Monitor with Coded PHY 4 | ####################################################### 5 | 6 | .. contents:: 7 | :local: 8 | :depth: 2 9 | 10 | The Peripheral Heart Rate Monitor with Coded PHY offers similar functionality to the :ref:`zephyr:peripheral_hr` sample from Zephyr. 11 | However, this sample supports LE Coded PHY. 12 | 13 | Overview 14 | ******** 15 | 16 | The sample demonstrates a basic Bluetooth® Low Energy Peripheral role functionality that exposes the Heart Rate GATT Service with LE Coded PHY support, which is not available in Zephyr Bluetooth LE Controller (See :ref:`ug_ble_controller` for more information). 17 | Once it connects to a Central device, it generates dummy heart rate values. 18 | It can be used together with the :ref:`bluetooth_central_hr_coded` sample. 19 | 20 | Requirements 21 | ************ 22 | 23 | The sample supports the following development kits: 24 | 25 | .. table-from-rows:: /includes/sample_board_rows.txt 26 | :header: heading 27 | :rows: nrf5340dk_nrf5340_cpuapp_and_cpuapp_ns, nrf52840dongle_nrf52840, nrf52840dk_nrf52840 28 | 29 | .. include:: /includes/hci_rpmsg_overlay.txt 30 | 31 | The sample also requires: 32 | 33 | * A device running a Heart Rate Server with LE Coded PHY support to connect to. 34 | For example, another development kit running the :ref:`bluetooth_central_hr_coded` sample. 35 | 36 | Building and running 37 | ******************** 38 | .. |sample path| replace:: :file:`samples/bluetooth/peripheral_hr_coded` 39 | 40 | .. include:: /includes/build_and_run.txt 41 | 42 | 43 | Testing 44 | ======= 45 | 46 | After programming the sample to your development kit, you can test it by connecting to another development kit that runs the :ref:`bluetooth_central_hr_coded`. 47 | 48 | 1. |connect_terminal_specific| 49 | #. Reset the kit. 50 | #. Program the other kit with the :ref:`bluetooth_central_hr_coded` sample. 51 | #. Wait until the Coded advertiser is detected by the Central. 52 | In the terminal window, check for information similar to the following:: 53 | 54 | Connected: xx.xx.xx.xx.xx.xx (random), tx_phy 4, rx_phy 4 55 | 56 | #. In the terminal window, observe that notifications are enabled:: 57 | 58 | hrs: HRS notifications enabled 59 | 60 | Dependencies 61 | ************ 62 | 63 | This sample uses the following Zephyr libraries: 64 | 65 | * ``include/zephyr/types.h`` 66 | * ``include/errno.h`` 67 | * ``include/zephyr.h`` 68 | * ``include/sys/printk.h`` 69 | * ``include/sys/byteorder.h`` 70 | * :ref:`zephyr:kernel_api`: 71 | 72 | * ``include/kernel.h`` 73 | 74 | * :ref:`zephyr:bluetooth_api`: 75 | 76 | * ``include/bluetooth/bluetooth.h`` 77 | * ``include/bluetooth/conn.h`` 78 | * ``include/bluetooth/uuid.h`` 79 | * ``include/bluetooth/gatt.h`` 80 | * ``include/bluetooth/services/bas.h`` 81 | * ``include/bluetooth/services/hrs.h`` 82 | -------------------------------------------------------------------------------- /peripheral_hr_coded_multi/child_image/hci_rpmsg.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | CONFIG_BT_EXT_ADV=y 8 | CONFIG_BT_CTLR_ADV_EXT=y 9 | CONFIG_BT_CTLR_PHY_CODED=y 10 | 11 | CONFIG_BT_USER_PHY_UPDATE=y 12 | 13 | CONFIG_BT_MAX_CONN=3 14 | CONFIG_BT_EXT_ADV_MAX_ADV_SET=2 15 | CONFIG_SDC_SLAVE_COUNT=2 -------------------------------------------------------------------------------- /peripheral_hr_coded_multi/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_BT=y 2 | CONFIG_BT_DEBUG_LOG=y 3 | CONFIG_BT_PERIPHERAL=y 4 | CONFIG_BT_DIS=y 5 | CONFIG_BT_DIS_PNP=n 6 | CONFIG_BT_BAS=y 7 | CONFIG_BT_HRS=y 8 | 9 | CONFIG_BT_CTLR_PHY_CODED=y 10 | CONFIG_BT_EXT_ADV=y 11 | CONFIG_BT_USER_PHY_UPDATE=y 12 | 13 | CONFIG_BT_MAX_CONN=2 14 | CONFIG_BT_EXT_ADV_MAX_ADV_SET=2 15 | 16 | CONFIG_BT_DEVICE_NAME="Zephyr Heartrate Sensor" 17 | CONFIG_BT_DEVICE_APPEARANCE=833 18 | -------------------------------------------------------------------------------- /peripheral_hr_coded_multi/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: Bluetooth LE peripheral HR Coded 3 | description: Bluetooth Low Energy peripheral heart rate service connecting on LE Coded PHY 4 | tests: 5 | samples.bluetooth.peripheral_hr_coded: 6 | build_only: true 7 | platform_allow: nrf52840dk_nrf52840 nrf5340dk_nrf5340_cpuapp 8 | integration_platforms: 9 | - nrf52840dk_nrf52840 10 | - nrf5340dk_nrf5340_cpuapp 11 | tags: bluetooth ci_build 12 | -------------------------------------------------------------------------------- /peripheral_hr_coded_multi/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp.default.configurationProvider": "nrf-connect" 3 | } -------------------------------------------------------------------------------- /peripheral_hr_coded_multi/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | /** @file 8 | * @brief Peripheral Heart Rate over LE Coded PHY sample 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | static struct k_work start_coded_advertising_worker; 26 | static struct k_work start_regular_advertising_worker; 27 | 28 | static struct bt_le_ext_adv *adv_coded; 29 | static struct bt_le_ext_adv *adv_regular; 30 | 31 | static const struct bt_data ad_coded[] = { 32 | BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), 33 | BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x0d, 0x18, 0x0f, 0x18, 0x0a, 0x18), 34 | }; 35 | 36 | static const struct bt_data ad_regular[] = { 37 | BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), 38 | BT_DATA_BYTES(BT_DATA_UUID16_ALL, 39 | BT_UUID_16_ENCODE(BT_UUID_HRS_VAL), 40 | BT_UUID_16_ENCODE(BT_UUID_BAS_VAL), 41 | BT_UUID_16_ENCODE(BT_UUID_DIS_VAL)) 42 | }; 43 | 44 | static void connected(struct bt_conn *conn, uint8_t conn_err) 45 | { 46 | int err; 47 | struct bt_conn_info info; 48 | char addr[BT_ADDR_LE_STR_LEN]; 49 | 50 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 51 | 52 | if (conn_err) { 53 | printk("Connection failed (err %d)\n", conn_err); 54 | return; 55 | } 56 | 57 | err = bt_conn_get_info(conn, &info); 58 | 59 | if (err) { 60 | printk("Failed to get connection info\n"); 61 | } else { 62 | const struct bt_conn_le_phy_info *phy_info; 63 | phy_info = info.le.phy; 64 | 65 | printk("Connected: %s, tx_phy %u, rx_phy %u\n", 66 | addr, phy_info->tx_phy, phy_info->rx_phy); 67 | } 68 | } 69 | 70 | static void disconnected(struct bt_conn *conn, uint8_t reason) 71 | { 72 | int err; 73 | struct bt_conn_info info; 74 | char addr[BT_ADDR_LE_STR_LEN]; 75 | printk("Disconnected (reason 0x%02x)\n", reason); 76 | 77 | err = bt_conn_get_info(conn, &info); 78 | 79 | if (err) { 80 | printk("Failed to get connection info\n"); 81 | } else { 82 | const struct bt_conn_le_phy_info *phy_info; 83 | phy_info = info.le.phy; 84 | 85 | printk("Disconnect: %s, tx_phy %u, rx_phy %u\n", 86 | addr, phy_info->tx_phy, phy_info->rx_phy); 87 | 88 | if(phy_info->tx_phy==4) { 89 | k_work_submit(&start_coded_advertising_worker); 90 | } else { 91 | k_work_submit(&start_regular_advertising_worker); 92 | } 93 | } 94 | } 95 | 96 | static struct bt_conn_cb conn_callbacks = { 97 | .connected = connected, 98 | .disconnected = disconnected, 99 | }; 100 | 101 | static int create_advertising_coded(void) 102 | { 103 | int err; 104 | struct bt_le_adv_param param = 105 | BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE | 106 | BT_LE_ADV_OPT_EXT_ADV | 107 | BT_LE_ADV_OPT_CODED, 108 | BT_GAP_ADV_FAST_INT_MIN_2, 109 | BT_GAP_ADV_FAST_INT_MAX_2, 110 | NULL); 111 | 112 | err = bt_le_ext_adv_create(¶m, NULL, &adv_coded); 113 | if (err) { 114 | printk("Failed to create advertiser coded set (%d)\n", err); 115 | return err; 116 | } 117 | 118 | printk("Created adv_coded: %p\n", adv_coded); 119 | 120 | err = bt_le_ext_adv_set_data(adv_coded, ad_coded, ARRAY_SIZE(ad_coded), NULL, 0); 121 | if (err) { 122 | printk("Failed to set advertising coded data (%d)\n", err); 123 | return err; 124 | } 125 | 126 | return 0; 127 | } 128 | 129 | static int create_advertising_regular(void) 130 | { 131 | int err; 132 | struct bt_le_adv_param param = 133 | BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE | 134 | BT_LE_ADV_OPT_USE_NAME, 135 | BT_GAP_ADV_FAST_INT_MIN_2, 136 | BT_GAP_ADV_FAST_INT_MAX_2, 137 | NULL); 138 | 139 | err = bt_le_ext_adv_create(¶m, NULL, &adv_regular); 140 | if (err) { 141 | printk("Failed to create advertiser regular set (%d)\n", err); 142 | return err; 143 | } 144 | 145 | printk("Created adv_regular: %p\n", adv_regular); 146 | 147 | err = bt_le_ext_adv_set_data(adv_regular, ad_regular, ARRAY_SIZE(ad_regular), NULL, 0); 148 | if (err) { 149 | printk("Failed to set advertising data (%d)\n", err); 150 | return err; 151 | } 152 | 153 | return 0; 154 | } 155 | 156 | static void start_advertising_coded(struct k_work *item) 157 | { 158 | int err; 159 | 160 | err = bt_le_ext_adv_start(adv_coded, NULL); 161 | if (err) { 162 | printk("Failed to start coded advertising set (%d)\n", err); 163 | return; 164 | } 165 | 166 | printk("Advertiser Coded %p set started\n", adv_coded); 167 | } 168 | 169 | static void start_advertising_regular(struct k_work *item) 170 | { 171 | int err; 172 | 173 | err = bt_le_ext_adv_start(adv_regular, NULL); 174 | if (err) { 175 | printk("Failed to start regular advertising set (%d)\n", err); 176 | return; 177 | } 178 | 179 | printk("Advertiser Regular %p set started\n", adv_regular); 180 | } 181 | 182 | static void bt_ready(void) 183 | { 184 | int err = 0; 185 | 186 | printk("Bluetooth initialized\n"); 187 | 188 | k_work_init(&start_coded_advertising_worker, start_advertising_coded); 189 | k_work_init(&start_regular_advertising_worker, start_advertising_regular); 190 | 191 | err = create_advertising_coded(); 192 | if (err) { 193 | printk("Advertising Coded failed to create (err %d)\n", err); 194 | return; 195 | } 196 | 197 | err = create_advertising_regular(); 198 | if (err) { 199 | printk("Advertising failed to create (err %d)\n", err); 200 | return; 201 | } 202 | 203 | k_work_submit(&start_coded_advertising_worker); 204 | k_work_submit(&start_regular_advertising_worker); 205 | } 206 | 207 | static void bas_notify(void) 208 | { 209 | uint8_t battery_level = bt_bas_get_battery_level(); 210 | 211 | battery_level--; 212 | 213 | if (!battery_level) { 214 | battery_level = 100U; 215 | } 216 | 217 | bt_bas_set_battery_level(battery_level); 218 | } 219 | 220 | static void hrs_notify(void) 221 | { 222 | static uint8_t heartrate = 90U; 223 | 224 | /* Heartrate measurements simulation */ 225 | heartrate++; 226 | if (heartrate == 160U) { 227 | heartrate = 90U; 228 | } 229 | 230 | bt_hrs_notify(heartrate); 231 | } 232 | 233 | void main(void) 234 | { 235 | int err; 236 | 237 | err = bt_enable(NULL); 238 | if (err) { 239 | printk("Bluetooth init failed (err %d)\n", err); 240 | return; 241 | } 242 | 243 | bt_ready(); 244 | 245 | bt_conn_cb_register(&conn_callbacks); 246 | 247 | /* Implement notification. At the moment there is no suitable way 248 | * of starting delayed work so we do it here 249 | */ 250 | while (1) { 251 | k_sleep(K_SECONDS(1)); 252 | 253 | /* Heartrate measurements simulation */ 254 | hrs_notify(); 255 | 256 | /* Battery level simulation */ 257 | bas_notify(); 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2018 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | cmake_minimum_required(VERSION 3.20.0) 7 | 8 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 9 | project(peripheral_uart) 10 | 11 | # NORDIC SDK APP START 12 | target_sources(app PRIVATE 13 | src/main.c 14 | ) 15 | 16 | # Include UART ASYNC API adapter 17 | target_sources_ifdef(CONFIG_BT_NUS_UART_ASYNC_ADAPTER app PRIVATE 18 | src/uart_async_adapter.c 19 | ) 20 | 21 | # NORDIC SDK APP END 22 | 23 | zephyr_library_include_directories(.) 24 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/Kconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2018 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | source "Kconfig.zephyr" 8 | 9 | menu "Nordic UART BLE GATT service sample" 10 | 11 | config BT_NUS_THREAD_STACK_SIZE 12 | int "Thread stack size" 13 | default 1024 14 | help 15 | Stack size used in each of the two threads 16 | 17 | config BT_NUS_UART_BUFFER_SIZE 18 | int "UART payload buffer element size" 19 | default 40 20 | help 21 | Size of the payload buffer in each RX and TX FIFO element 22 | 23 | config BT_NUS_SECURITY_ENABLED 24 | bool "Enable security" 25 | default y 26 | select BT_SMP 27 | help 28 | "Enable BLE security for the UART service" 29 | 30 | config BT_NUS_UART_RX_WAIT_TIME 31 | int "Timeout for UART RX complete event" 32 | default 50000 33 | help 34 | Wait for RX complete event time in microseconds 35 | 36 | config BT_NUS_UART_ASYNC_ADAPTER 37 | bool "Enable UART async adapter" 38 | select SERIAL_SUPPORT_ASYNC 39 | help 40 | Enables asynchronous adapter for UART drives that supports only 41 | IRQ interface. 42 | 43 | endmenu 44 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/Kconfig.sysbuild: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2023 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" 8 | 9 | config NRF_DEFAULT_BLUETOOTH 10 | default y 11 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/README.rst: -------------------------------------------------------------------------------- 1 | Bluetooth: Peripheral UART + Beacon 2 | ########################## 3 | 4 | This example implements a BLE UART peripheral (NUS from Nordic) but also adds the capability to change function to a simple beacon. -------------------------------------------------------------------------------- /peripheral_uart_beacon/VERSION: -------------------------------------------------------------------------------- 1 | VERSION_MAJOR = 2 2 | VERSION_MINOR = 5 3 | PATCHLEVEL = 0 4 | VERSION_TWEAK = 0 5 | EXTRAVERSION = 6 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/app.overlay: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | / { 8 | chosen { 9 | nordic,nus-uart = &uart0; 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/boards/thingy53_nrf5340_cpuapp.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | ################################################################################ 7 | # Application overlay - Thingy:53 DFU 8 | 9 | CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y 10 | 11 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 12 | 13 | ################################################################################ 14 | # Configure USB CDC ACM 15 | 16 | CONFIG_USB_DEVICE_PRODUCT="Thingy:53 Nordic UART Service sample" 17 | CONFIG_USB_DEVICE_PID=0x530E 18 | CONFIG_USB_COMPOSITE_DEVICE=y 19 | 20 | # Enable back logging over UART as this sample config uses only RTT by default 21 | CONFIG_LOG_BACKEND_UART=y 22 | 23 | CONFIG_BT_NUS_UART_ASYNC_ADAPTER=y 24 | CONFIG_UART_INTERRUPT_DRIVEN=y 25 | 26 | # Disable the UARTE0 enabled in default project configuration 27 | CONFIG_NRFX_UARTE0=n 28 | CONFIG_UART_NRFX=n 29 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/boards/thingy53_nrf5340_cpuapp.overlay: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | / { 8 | chosen { 9 | nordic,nus-uart = &cdc_acm_uart1; 10 | }; 11 | }; 12 | 13 | &zephyr_udc0 { 14 | cdc_acm_uart1: cdc_acm_uart1 { 15 | compatible = "zephyr,cdc-acm-uart"; 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/boards/thingy53_nrf5340_cpuapp_ns.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 Nordic Semiconductor ASA 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | ################################################################################ 7 | # Application overlay - Thingy:53 DFU 8 | 9 | CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y 10 | 11 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 12 | 13 | ################################################################################ 14 | # Configure USB CDC ACM 15 | 16 | CONFIG_USB_DEVICE_PRODUCT="Thingy:53 Nordic UART Service sample" 17 | CONFIG_USB_DEVICE_PID=0x530E 18 | CONFIG_USB_COMPOSITE_DEVICE=y 19 | 20 | # Enable back logging over UART as this sample config uses only RTT by default 21 | CONFIG_LOG_BACKEND_UART=y 22 | 23 | CONFIG_BT_NUS_UART_ASYNC_ADAPTER=y 24 | CONFIG_UART_INTERRUPT_DRIVEN=y 25 | 26 | # Disable the UARTE0 enabled in default project configuration 27 | CONFIG_NRFX_UARTE0=n 28 | CONFIG_UART_NRFX=n 29 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/boards/thingy53_nrf5340_cpuapp_ns.overlay: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | / { 8 | chosen { 9 | nordic,nus-uart = &cdc_acm_uart1; 10 | }; 11 | }; 12 | 13 | &zephyr_udc0 { 14 | cdc_acm_uart1: cdc_acm_uart1 { 15 | compatible = "zephyr,cdc-acm-uart"; 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/nrf5340dk_app_sr_net.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | CONFIG_BOOTLOADER_MCUBOOT=y 8 | CONFIG_NRF53_UPGRADE_NETWORK_CORE=y 9 | CONFIG_ADD_MCUBOOT_MEDIATE_SIM_FLASH_DTS=y 10 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/nrf5340dk_mcuboot_sr_net.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2022 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | CONFIG_MAIN_STACK_SIZE=10240 8 | # Flash 9 | CONFIG_FLASH=y 10 | 11 | # MCUBoot serial 12 | CONFIG_MCUBOOT_SERIAL=y 13 | CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y 14 | 15 | # Decrease memory footprint 16 | CONFIG_CBPRINTF_NANO=y 17 | CONFIG_TIMESLICING=n 18 | CONFIG_BOOT_BANNER=n 19 | CONFIG_CONSOLE=n 20 | CONFIG_CONSOLE_HANDLER=n 21 | CONFIG_UART_CONSOLE=n 22 | CONFIG_RTT_CONSOLE=n 23 | CONFIG_USE_SEGGER_RTT=n 24 | CONFIG_LOG=n 25 | CONFIG_RESET_ON_FATAL_ERROR=n 26 | 27 | # The following configurations are required to support serial recovery of the 28 | # network image 29 | CONFIG_PCD_APP=y 30 | 31 | CONFIG_FLASH_SIMULATOR=y 32 | CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y 33 | CONFIG_FLASH_SIMULATOR_STATS=n 34 | 35 | CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y 36 | CONFIG_NRF53_RECOVERY_NETWORK_CORE=y 37 | 38 | CONFIG_MCUBOOT_INDICATION_LED=y 39 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/prj.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2018 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | # Enable the UART driver 8 | CONFIG_UART_ASYNC_API=y 9 | CONFIG_NRFX_UARTE0=y 10 | CONFIG_SERIAL=y 11 | 12 | CONFIG_GPIO=y 13 | 14 | # Make sure printk is printing to the UART console 15 | CONFIG_CONSOLE=y 16 | CONFIG_UART_CONSOLE=y 17 | 18 | CONFIG_HEAP_MEM_POOL_SIZE=2048 19 | 20 | CONFIG_BT=y 21 | CONFIG_BT_PERIPHERAL=y 22 | CONFIG_BT_DEVICE_NAME="Nordic_UART_Service" 23 | CONFIG_BT_DEVICE_APPEARANCE=833 24 | CONFIG_BT_MAX_CONN=1 25 | CONFIG_BT_MAX_PAIRED=1 26 | 27 | # Enable the NUS service 28 | CONFIG_BT_NUS=y 29 | 30 | # Enable bonding 31 | CONFIG_BT_SETTINGS=y 32 | CONFIG_FLASH=y 33 | CONFIG_FLASH_PAGE_LAYOUT=y 34 | CONFIG_FLASH_MAP=y 35 | CONFIG_NVS=y 36 | CONFIG_SETTINGS=y 37 | 38 | # Enable DK LED and Buttons library 39 | CONFIG_DK_LIBRARY=y 40 | 41 | # This example requires more stack 42 | CONFIG_MAIN_STACK_SIZE=1152 43 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 44 | 45 | # Config logger 46 | CONFIG_LOG=y 47 | CONFIG_USE_SEGGER_RTT=y 48 | CONFIG_LOG_BACKEND_RTT=y 49 | CONFIG_LOG_BACKEND_UART=n 50 | CONFIG_LOG_PRINTK=n 51 | 52 | CONFIG_ASSERT=y 53 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/prj_cdc.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | # Enable the UART driver 8 | CONFIG_UART_LINE_CTRL=y 9 | CONFIG_UART_INTERRUPT_DRIVEN=y 10 | CONFIG_BT_NUS_UART_ASYNC_ADAPTER=y 11 | CONFIG_USB_DEVICE_STACK=y 12 | CONFIG_USB_DEVICE_REMOTE_WAKEUP=n 13 | CONFIG_USB_CDC_ACM=y 14 | CONFIG_USB_CDC_ACM_LOG_LEVEL_OFF=y 15 | 16 | # Disable the UARTE0 enabled in default project configuration 17 | CONFIG_NRFX_UARTE0=n 18 | CONFIG_UART_NRFX=n 19 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/prj_minimal.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 Nordic Semiconductor 3 | # 4 | # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | # 6 | 7 | # Enable the UART driver 8 | CONFIG_UART_ASYNC_API=y 9 | CONFIG_NRFX_UARTE0=y 10 | CONFIG_SERIAL=y 11 | 12 | CONFIG_HEAP_MEM_POOL_SIZE=2048 13 | 14 | CONFIG_BT=y 15 | CONFIG_BT_PERIPHERAL=y 16 | CONFIG_BT_DEVICE_NAME="Nordic_UART_Service" 17 | CONFIG_BT_DEVICE_APPEARANCE=833 18 | CONFIG_BT_MAX_CONN=1 19 | CONFIG_BT_MAX_PAIRED=1 20 | 21 | # Enable the NUS service 22 | CONFIG_BT_NUS=y 23 | 24 | # Enable bonding 25 | CONFIG_BT_SETTINGS=y 26 | CONFIG_FLASH=y 27 | CONFIG_FLASH_PAGE_LAYOUT=y 28 | CONFIG_FLASH_MAP=y 29 | CONFIG_NVS=y 30 | CONFIG_SETTINGS=y 31 | 32 | # Enable DK LED and Buttons library 33 | CONFIG_DK_LIBRARY=y 34 | 35 | # Drivers and peripherals 36 | CONFIG_I2C=n 37 | CONFIG_WATCHDOG=n 38 | CONFIG_SPI=n 39 | CONFIG_GPIO=n 40 | 41 | # Power management 42 | 43 | # Interrupts 44 | CONFIG_DYNAMIC_INTERRUPTS=n 45 | CONFIG_IRQ_OFFLOAD=n 46 | 47 | # Memory protection 48 | CONFIG_THREAD_STACK_INFO=n 49 | CONFIG_THREAD_CUSTOM_DATA=n 50 | CONFIG_FPU=n 51 | 52 | # Boot 53 | CONFIG_BOOT_BANNER=n 54 | CONFIG_BOOT_DELAY=0 55 | 56 | # Console 57 | CONFIG_CONSOLE=n 58 | CONFIG_UART_CONSOLE=n 59 | CONFIG_STDOUT_CONSOLE=n 60 | CONFIG_PRINTK=n 61 | CONFIG_EARLY_CONSOLE=n 62 | 63 | # Build 64 | CONFIG_SIZE_OPTIMIZATIONS=y 65 | 66 | # ARM 67 | CONFIG_ARM_MPU=n 68 | 69 | # In order to correctly tune the stack sizes for the threads the following 70 | # Configurations can enabled to print the current use: 71 | #CONFIG_THREAD_NAME=y 72 | #CONFIG_THREAD_ANALYZER=y 73 | #CONFIG_THREAD_ANALYZER_AUTO=y 74 | #CONFIG_THREAD_ANALYZER_RUN_UNLOCKED=y 75 | #CONFIG_THREAD_ANALYZER_USE_PRINTK=y 76 | #CONFIG_CONSOLE=y 77 | #CONFIG_UART_CONSOLE=y 78 | #CONFIG_SERIAL=y 79 | #CONFIG_PRINTK=y 80 | 81 | # Example output of thread analyzer 82 | #SDC RX : unused 800 usage 224 / 1024 (21 %) 83 | #BT ECC : unused 216 usage 888 / 1104 (80 %) 84 | #BT RX : unused 1736 usage 464 / 2200 (21 %) 85 | #BT TX : unused 1008 usage 528 / 1536 (34 %) 86 | #ble_write_thread_id : unused 688 usage 336 / 1024 (32 %) 87 | #sysworkq : unused 1912 usage 136 / 2048 (6 %) 88 | #MPSL signal : unused 928 usage 96 / 1024 (9 %) 89 | #idle 00 : unused 224 usage 96 / 320 (30 %) 90 | #main : unused 568 usage 456 / 1024 (44 %) 91 | CONFIG_BT_RX_STACK_SIZE=1024 92 | CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y 93 | CONFIG_BT_HCI_TX_STACK_SIZE=640 94 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 95 | CONFIG_MPSL_WORK_STACK_SIZE=256 96 | CONFIG_MAIN_STACK_SIZE=864 97 | CONFIG_IDLE_STACK_SIZE=128 98 | CONFIG_ISR_STACK_SIZE=1024 99 | CONFIG_BT_NUS_THREAD_STACK_SIZE=512 100 | 101 | # Disable features not needed 102 | CONFIG_TIMESLICING=n 103 | CONFIG_MINIMAL_LIBC_MALLOC=n 104 | CONFIG_LOG=n 105 | CONFIG_ASSERT=n 106 | 107 | # Disable Bluetooth features not needed 108 | CONFIG_BT_DEBUG_NONE=y 109 | CONFIG_BT_ASSERT=n 110 | CONFIG_BT_DATA_LEN_UPDATE=n 111 | CONFIG_BT_PHY_UPDATE=n 112 | CONFIG_BT_GATT_CACHING=n 113 | CONFIG_BT_GATT_SERVICE_CHANGED=n 114 | CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=n 115 | CONFIG_BT_SETTINGS_CCC_LAZY_LOADING=y 116 | CONFIG_BT_HCI_VS_EXT=n 117 | 118 | # Disable Bluetooth controller features not needed 119 | CONFIG_BT_CTLR_PRIVACY=n 120 | CONFIG_BT_CTLR_PHY_2M=n 121 | 122 | # Reduce Bluetooth buffers 123 | CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT=1 124 | CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=43 125 | CONFIG_BT_BUF_EVT_RX_COUNT=2 126 | 127 | CONFIG_BT_CONN_TX_MAX=2 128 | CONFIG_BT_L2CAP_TX_BUF_COUNT=2 129 | CONFIG_BT_CTLR_RX_BUFFERS=1 130 | CONFIG_BT_BUF_ACL_TX_COUNT=3 131 | CONFIG_BT_BUF_ACL_TX_SIZE=27 132 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Bluetooth Low Energy UART service sample 3 | name: BLE UART service 4 | tests: 5 | sample.bluetooth.peripheral_uart: 6 | build_only: true 7 | platform_allow: nrf52dk_nrf52832 nrf52833dk_nrf52833 nrf52840dk_nrf52840 8 | nrf5340dk_nrf5340_cpuapp nrf5340dk_nrf5340_cpuapp_ns thingy53_nrf5340_cpuapp 9 | thingy53_nrf5340_cpuapp_ns nrf21540dk_nrf52840 10 | integration_platforms: 11 | - nrf52dk_nrf52832 12 | - nrf52833dk_nrf52833 13 | - nrf52840dk_nrf52840 14 | - nrf5340dk_nrf5340_cpuapp 15 | - nrf5340dk_nrf5340_cpuapp_ns 16 | - thingy53_nrf5340_cpuapp 17 | - thingy53_nrf5340_cpuapp_ns 18 | - nrf21540dk_nrf52840 19 | tags: bluetooth ci_build 20 | sample.bluetooth.peripheral_uart.sysbuild: 21 | build_only: true 22 | sysbuild: true 23 | platform_allow: nrf52840dk_nrf52840 nrf5340dk_nrf5340_cpuapp 24 | nrf5340dk_nrf5340_cpuapp_ns 25 | integration_platforms: 26 | - nrf52840dk_nrf52840 27 | - nrf5340dk_nrf5340_cpuapp 28 | - nrf5340dk_nrf5340_cpuapp_ns 29 | tags: bluetooth ci_build sysbuild 30 | sample.bluetooth.peripheral_uart_cdc: 31 | build_only: true 32 | extra_args: OVERLAY_CONFIG=prj_cdc.conf DTC_OVERLAY_FILE="usb.overlay" 33 | integration_platforms: 34 | - nrf52840dk_nrf52840 35 | - nrf52833dk_nrf52833 36 | platform_allow: nrf52840dk_nrf52840 nrf52833dk_nrf52833 37 | tags: bluetooth ci_build 38 | sample.bluetooth.peripheral_uart_minimal: 39 | build_only: true 40 | extra_args: OVERLAY_CONFIG=prj_minimal.conf 41 | integration_platforms: 42 | - nrf52dk_nrf52810 43 | - nrf52840dk_nrf52811 44 | - nrf52833dk_nrf52820 45 | platform_allow: nrf52dk_nrf52810 nrf52840dk_nrf52811 nrf52833dk_nrf52820 46 | tags: bluetooth ci_build 47 | sample.bluetooth.peripheral_uart_ble_rpc: 48 | build_only: true 49 | extra_configs: 50 | - CONFIG_BT_RPC_STACK=y 51 | integration_platforms: 52 | - nrf5340dk_nrf5340_cpuapp 53 | platform_allow: nrf5340dk_nrf5340_cpuapp 54 | tags: bluetooth ci_build 55 | sample.bluetooth.peripheral_uart.security_disabled: 56 | build_only: true 57 | platform_allow: nrf52dk_nrf52832 nrf52833dk_nrf52833 nrf52840dk_nrf52840 58 | nrf5340dk_nrf5340_cpuapp nrf5340dk_nrf5340_cpuapp_ns thingy53_nrf5340_cpuapp 59 | thingy53_nrf5340_cpuapp_ns nrf21540dk_nrf52840 60 | integration_platforms: 61 | - nrf52840dk_nrf52840 62 | tags: bluetooth ci_build 63 | extra_configs: 64 | - CONFIG_BT_NUS_SECURITY_ENABLED=n 65 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/src/uart_async_adapter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | /** @file 8 | * @brief UART asynchronous API adapter 9 | */ 10 | 11 | /** 12 | * @brief UART asynchronous API universal adapter 13 | * @defgroup uart_async_adapter UART ASYNC adapter 14 | * @{ 15 | * 16 | * This module acts as an adapter between UART interrupt and async interface. 17 | * 18 | * @note The UART ASYNC API adapter implementation is experimental. 19 | * It means it is not guaranteed to work in any corner situation. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | 27 | /** 28 | * @brief UART asynch adapter data structure 29 | * 30 | * The data used by asynch adapter. 31 | */ 32 | struct uart_async_adapter_data { 33 | /** Target device pointer */ 34 | const struct device *target; 35 | /** User callback function for synchronous interface */ 36 | uart_callback_t user_callback; 37 | /** Pointer to the user data */ 38 | void *user_data; 39 | 40 | /* The interface realization */ 41 | /** Lock for the data that requires it */ 42 | struct k_spinlock lock; 43 | 44 | /** Data used for output transmission */ 45 | struct { 46 | /** The original buffer pointer set when data transfer was requested */ 47 | const uint8_t *buf; 48 | /** Current buffer position */ 49 | const uint8_t *curr_buf; 50 | /** Number of data left in the current buffer */ 51 | volatile size_t size_left; 52 | /** Timer used for timeout */ 53 | struct k_timer timeout_timer; 54 | /** Tx state */ 55 | bool enabled; 56 | } tx; 57 | 58 | /** Data used for input transmission */ 59 | struct { 60 | /** Base buffer pointer used now for data reception */ 61 | uint8_t *buf; 62 | /** Current position to write data into */ 63 | uint8_t *curr_buf; 64 | /** Last position of the notified buffer */ 65 | uint8_t *last_notify_buf; 66 | /** Number of bytes left in the current buffer */ 67 | size_t size_left; 68 | /** Buffer prepared for the next transfer */ 69 | uint8_t *next_buf; 70 | /** The size of the buffer for the next transfer */ 71 | size_t next_buf_len; 72 | /** Timeout set by the user */ 73 | int32_t timeout; 74 | /** Timer used for timeout */ 75 | struct k_timer timeout_timer; 76 | /** RX state */ 77 | bool enabled; 78 | } rx; 79 | }; 80 | 81 | /** 82 | * @brief Driver API for ASYNC adapter 83 | * 84 | * The API of the UART async adapter uses standard UART API structure. 85 | */ 86 | extern const struct uart_driver_api uart_async_adapter_driver_api; 87 | 88 | /** 89 | * @brief The name of the data instance connected with created device instance 90 | * 91 | * @name _dev_name The name of the created device instance 92 | */ 93 | #define UART_ASYNC_ADAPTER_INST_DATA_NAME(_dev_name) _CONCAT(uart_async_adapter_data_, _dev_name) 94 | 95 | #define UART_ASYNC_ADAPTER_INST_STATE_NAME(_dev_name) _CONCAT(uart_async_adapter_state_, _dev_name) 96 | 97 | #define UART_ASYNC_ADAPTER_INST_NAME(_dev_name) _CONCAT(_dev_name, _inst) 98 | 99 | /** 100 | * @brief The macro that creates and instance of the UART async adapter 101 | * 102 | * @name _dev The name of the created device instance 103 | */ 104 | #define UART_ASYNC_ADAPTER_INST_DEFINE(_dev) \ 105 | static struct uart_async_adapter_data UART_ASYNC_ADAPTER_INST_DATA_NAME(_dev); \ 106 | static struct device_state UART_ASYNC_ADAPTER_INST_STATE_NAME(_dev); \ 107 | static const struct device UART_ASYNC_ADAPTER_INST_NAME(_dev) = { \ 108 | .name = STRINGIFY(_dev), \ 109 | .api = &uart_async_adapter_driver_api, \ 110 | .state = &UART_ASYNC_ADAPTER_INST_STATE_NAME(_dev), \ 111 | .data = &UART_ASYNC_ADAPTER_INST_DATA_NAME(_dev), \ 112 | }; \ 113 | static const struct device *const _dev = &UART_ASYNC_ADAPTER_INST_NAME(_dev) 114 | 115 | /** 116 | * @brief Initialize adapter 117 | * 118 | * Call this function before uart adapter is used. 119 | * The function configures connected UART device to work with the adapter. 120 | * 121 | * @param dev The adapter interface 122 | * @param target Target UART device with only interrupt interface 123 | */ 124 | void uart_async_adapter_init(const struct device *dev, const struct device *target); 125 | 126 | /** @} */ 127 | -------------------------------------------------------------------------------- /peripheral_uart_beacon/usb.overlay: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Nordic Semiconductor ASA 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause 5 | */ 6 | 7 | / { 8 | chosen { 9 | zephyr,console = &cdc_acm_uart0; 10 | nordic,nus-uart = &cdc_acm_uart0; 11 | }; 12 | }; 13 | 14 | &zephyr_udc0 { 15 | cdc_acm_uart0: cdc_acm_uart0 { 16 | compatible = "zephyr,cdc-acm-uart"; 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /rtc_sleep/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /rtc_sleep/README.rst: -------------------------------------------------------------------------------- 1 | .. _hello_world: 2 | 3 | Hello World 4 | ########### 5 | 6 | Overview 7 | ******** 8 | 9 | A simple sample that can be used with any :ref:`supported board ` and 10 | prints "Hello World" to the console. 11 | 12 | Building and Running 13 | ******************** 14 | 15 | This application can be built and executed on QEMU as follows: 16 | 17 | .. zephyr-app-commands:: 18 | :zephyr-app: samples/hello_world 19 | :host-os: unix 20 | :board: qemu_x86 21 | :goals: run 22 | :compact: 23 | 24 | To build for another board, change "qemu_x86" above to that board's name. 25 | 26 | Sample Output 27 | ============= 28 | 29 | .. code-block:: console 30 | 31 | Hello World! x86 32 | 33 | Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. 34 | -------------------------------------------------------------------------------- /rtc_sleep/boards/nrf52840dk_nrf52840.overlay: -------------------------------------------------------------------------------- 1 | &uart1 { 2 | status = "disabled"; 3 | }; -------------------------------------------------------------------------------- /rtc_sleep/prj.conf: -------------------------------------------------------------------------------- 1 | # nothing here 2 | CONFIG_PM=y 3 | CONFIG_PM_DEVICE=y 4 | CONFIG_GPIO=y 5 | CONFIG_NRFX_RTC2=y 6 | CONFIG_SERIAL=y -------------------------------------------------------------------------------- /rtc_sleep/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Hello World sample, the simplest Zephyr 3 | application 4 | name: hello world 5 | common: 6 | tags: introduction 7 | integration_platforms: 8 | - native_posix 9 | harness: console 10 | harness_config: 11 | type: one_line 12 | regex: 13 | - "Hello World! (.*)" 14 | tests: 15 | sample.basic.helloworld: 16 | tags: introduction 17 | -------------------------------------------------------------------------------- /rtc_sleep/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define RTC_INSTANCE 2 8 | #define CC_CHANNEL 0 9 | #define RTC_TIMEOUT_MS 5000 10 | #define RTC_PRESCALER_MS 125 11 | BUILD_ASSERT(RTC_PRESCALER_MS <= 125, "VALUE_MS must be less than or equal to 125"); 12 | 13 | 14 | static nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(RTC_INSTANCE); 15 | static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); 16 | 17 | void rtc_event_handler(nrfx_rtc_int_type_t int_type) 18 | { 19 | switch(int_type) { 20 | case NRFX_RTC_INT_COMPARE0: 21 | printk("RTC compare event occurred\n"); 22 | gpio_pin_toggle_dt(&led); 23 | nrfx_rtc_counter_clear(&rtc); 24 | nrfx_rtc_cc_set(&rtc, CC_CHANNEL, RTC_TIMEOUT_MS / RTC_PRESCALER_MS, true); 25 | break; 26 | default: 27 | break; 28 | } 29 | } 30 | 31 | void main(void) 32 | { 33 | printk("Hello World!\n"); 34 | 35 | nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG; 36 | printk("RTC_PRESCALER_MS: %d\n", RTC_PRESCALER_MS); 37 | printk("RTC prescaler in Hz: %d\n", 1000 / RTC_PRESCALER_MS); 38 | config.prescaler = RTC_FREQ_TO_PRESCALER(1000 / RTC_PRESCALER_MS); 39 | printk("RTC prescaler: %d\n", config.prescaler); 40 | 41 | nrfx_rtc_init(&rtc, &config, rtc_event_handler); 42 | 43 | IRQ_CONNECT(DT_IRQN(DT_NODELABEL(rtc2)), 44 | DT_IRQ(DT_NODELABEL(rtc2), priority), 45 | nrfx_isr, nrfx_rtc_2_irq_handler, 0); 46 | irq_enable(DT_IRQN(DT_NODELABEL(rtc2))); 47 | 48 | if (!device_is_ready(led.port)) { 49 | return; 50 | } 51 | 52 | if (gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE) < 0) { 53 | return; 54 | } 55 | 56 | nrfx_rtc_tick_disable(&rtc); 57 | nrfx_rtc_counter_clear(&rtc); 58 | nrfx_rtc_enable(&rtc); 59 | nrfx_rtc_cc_set(&rtc, CC_CHANNEL, RTC_TIMEOUT_MS / RTC_PRESCALER_MS, true); 60 | printk("RTC Compare value: %d\n", RTC_TIMEOUT_MS / RTC_PRESCALER_MS); 61 | 62 | } -------------------------------------------------------------------------------- /rtc_sleep_dual_uart/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /rtc_sleep_dual_uart/README.rst: -------------------------------------------------------------------------------- 1 | .. _hello_world: 2 | 3 | Hello World 4 | ########### 5 | 6 | Overview 7 | ******** 8 | 9 | A simple sample that can be used with any :ref:`supported board ` and 10 | prints "Hello World" to the console. 11 | 12 | Building and Running 13 | ******************** 14 | 15 | This application can be built and executed on QEMU as follows: 16 | 17 | .. zephyr-app-commands:: 18 | :zephyr-app: samples/hello_world 19 | :host-os: unix 20 | :board: qemu_x86 21 | :goals: run 22 | :compact: 23 | 24 | To build for another board, change "qemu_x86" above to that board's name. 25 | 26 | Sample Output 27 | ============= 28 | 29 | .. code-block:: console 30 | 31 | Hello World! x86 32 | 33 | Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. 34 | -------------------------------------------------------------------------------- /rtc_sleep_dual_uart/prj.conf: -------------------------------------------------------------------------------- 1 | # nothing here 2 | CONFIG_PM=y 3 | CONFIG_PM_DEVICE=y 4 | CONFIG_GPIO=y 5 | CONFIG_NRFX_RTC2=y 6 | CONFIG_SERIAL=n -------------------------------------------------------------------------------- /rtc_sleep_dual_uart/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Hello World sample, the simplest Zephyr 3 | application 4 | name: hello world 5 | common: 6 | tags: introduction 7 | integration_platforms: 8 | - native_posix 9 | harness: console 10 | harness_config: 11 | type: one_line 12 | regex: 13 | - "Hello World! (.*)" 14 | tests: 15 | sample.basic.helloworld: 16 | tags: introduction 17 | -------------------------------------------------------------------------------- /rtc_sleep_dual_uart/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define RTC_INSTANCE 2 9 | #define CC_CHANNEL 0 10 | #define RTC_TIMEOUT_MS 5000 11 | #define RTC_PRESCALER_MS 125 12 | BUILD_ASSERT(RTC_PRESCALER_MS <= 125, "VALUE_MS must be less than or equal to 125"); 13 | 14 | 15 | static nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(RTC_INSTANCE); 16 | static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); 17 | 18 | #ifdef CONFIG_SERIAL 19 | const struct device *uart_dev0 = DEVICE_DT_GET(DT_NODELABEL(uart0)); 20 | const struct device *uart_dev1 = DEVICE_DT_GET(DT_NODELABEL(uart1)); 21 | #endif 22 | 23 | void rtc_event_handler(nrfx_rtc_int_type_t int_type) 24 | { 25 | switch(int_type) { 26 | case NRFX_RTC_INT_COMPARE0: 27 | gpio_pin_toggle_dt(&led); 28 | nrfx_rtc_counter_clear(&rtc); 29 | nrfx_rtc_cc_set(&rtc, CC_CHANNEL, RTC_TIMEOUT_MS / RTC_PRESCALER_MS, true); 30 | break; 31 | default: 32 | break; 33 | } 34 | } 35 | 36 | void main(void) 37 | { 38 | 39 | printk("Turn off both UARTs\n"); 40 | 41 | #ifdef CONFIG_SERIAL 42 | pm_device_action_run(uart_dev0, PM_DEVICE_ACTION_SUSPEND); 43 | pm_device_action_run(uart_dev1, PM_DEVICE_ACTION_SUSPEND); 44 | #endif 45 | 46 | 47 | // Configure RTC & LED 48 | nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG; 49 | printk("RTC_PRESCALER_MS: %d\n", RTC_PRESCALER_MS); 50 | printk("RTC prescaler in Hz: %d\n", 1000 / RTC_PRESCALER_MS); 51 | config.prescaler = RTC_FREQ_TO_PRESCALER(1000 / RTC_PRESCALER_MS); 52 | printk("RTC prescaler: %d\n", config.prescaler); 53 | 54 | nrfx_rtc_init(&rtc, &config, rtc_event_handler); 55 | 56 | IRQ_CONNECT(DT_IRQN(DT_NODELABEL(rtc2)), 57 | DT_IRQ(DT_NODELABEL(rtc2), priority), 58 | nrfx_isr, nrfx_rtc_2_irq_handler, 0); 59 | irq_enable(DT_IRQN(DT_NODELABEL(rtc2))); 60 | 61 | if (!device_is_ready(led.port)) { 62 | return; 63 | } 64 | 65 | if (gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE) < 0) { 66 | return; 67 | } 68 | 69 | nrfx_rtc_tick_disable(&rtc); 70 | nrfx_rtc_counter_clear(&rtc); 71 | nrfx_rtc_enable(&rtc); 72 | nrfx_rtc_cc_set(&rtc, CC_CHANNEL, RTC_TIMEOUT_MS / RTC_PRESCALER_MS, true); 73 | printk("RTC Compare value: %d\n", RTC_TIMEOUT_MS / RTC_PRESCALER_MS); 74 | 75 | } -------------------------------------------------------------------------------- /rtc_sleep_uart/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /rtc_sleep_uart/README.rst: -------------------------------------------------------------------------------- 1 | .. _hello_world: 2 | 3 | Hello World 4 | ########### 5 | 6 | Overview 7 | ******** 8 | 9 | A simple sample that can be used with any :ref:`supported board ` and 10 | prints "Hello World" to the console. 11 | 12 | Building and Running 13 | ******************** 14 | 15 | This application can be built and executed on QEMU as follows: 16 | 17 | .. zephyr-app-commands:: 18 | :zephyr-app: samples/hello_world 19 | :host-os: unix 20 | :board: qemu_x86 21 | :goals: run 22 | :compact: 23 | 24 | To build for another board, change "qemu_x86" above to that board's name. 25 | 26 | Sample Output 27 | ============= 28 | 29 | .. code-block:: console 30 | 31 | Hello World! x86 32 | 33 | Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. 34 | -------------------------------------------------------------------------------- /rtc_sleep_uart/boards/nrf52833dk_nrf52833.overlay: -------------------------------------------------------------------------------- 1 | &uart1 { 2 | status = "disabled"; 3 | }; -------------------------------------------------------------------------------- /rtc_sleep_uart/boards/nrf52840dk_nrf52840.overlay: -------------------------------------------------------------------------------- 1 | &uart1 { 2 | status = "disabled"; 3 | }; -------------------------------------------------------------------------------- /rtc_sleep_uart/prj.conf: -------------------------------------------------------------------------------- 1 | # nothing here 2 | CONFIG_PM=y 3 | CONFIG_PM_DEVICE=y 4 | CONFIG_GPIO=y 5 | CONFIG_NRFX_RTC2=y 6 | CONFIG_SERIAL=y -------------------------------------------------------------------------------- /rtc_sleep_uart/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Hello World sample, the simplest Zephyr 3 | application 4 | name: hello world 5 | common: 6 | tags: introduction 7 | integration_platforms: 8 | - native_posix 9 | harness: console 10 | harness_config: 11 | type: one_line 12 | regex: 13 | - "Hello World! (.*)" 14 | tests: 15 | sample.basic.helloworld: 16 | tags: introduction 17 | -------------------------------------------------------------------------------- /rtc_sleep_uart/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define RTC_INSTANCE 2 9 | #define CC_CHANNEL 0 10 | #define RTC_TIMEOUT_MS 5000 11 | #define RTC_PRESCALER_MS 125 12 | BUILD_ASSERT(RTC_PRESCALER_MS <= 125, "VALUE_MS must be less than or equal to 125"); 13 | 14 | 15 | static nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(RTC_INSTANCE); 16 | static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); 17 | 18 | const struct device *uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); 19 | 20 | void rtc_event_handler(nrfx_rtc_int_type_t int_type) 21 | { 22 | switch(int_type) { 23 | case NRFX_RTC_INT_COMPARE0: 24 | pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME); 25 | printk("RTC compare event occurred\n"); 26 | pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND); 27 | gpio_pin_toggle_dt(&led); 28 | nrfx_rtc_counter_clear(&rtc); 29 | nrfx_rtc_cc_set(&rtc, CC_CHANNEL, RTC_TIMEOUT_MS / RTC_PRESCALER_MS, true); 30 | break; 31 | default: 32 | break; 33 | } 34 | } 35 | 36 | void main(void) 37 | { 38 | 39 | printk("RTC Sleep with UART Disable\n"); 40 | 41 | if (!device_is_ready(uart_dev)) { 42 | return; 43 | } 44 | pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND); 45 | 46 | nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG; 47 | printk("RTC_PRESCALER_MS: %d\n", RTC_PRESCALER_MS); 48 | printk("RTC prescaler in Hz: %d\n", 1000 / RTC_PRESCALER_MS); 49 | config.prescaler = RTC_FREQ_TO_PRESCALER(1000 / RTC_PRESCALER_MS); 50 | printk("RTC prescaler: %d\n", config.prescaler); 51 | 52 | nrfx_rtc_init(&rtc, &config, rtc_event_handler); 53 | 54 | IRQ_CONNECT(DT_IRQN(DT_NODELABEL(rtc2)), 55 | DT_IRQ(DT_NODELABEL(rtc2), priority), 56 | nrfx_isr, nrfx_rtc_2_irq_handler, 0); 57 | irq_enable(DT_IRQN(DT_NODELABEL(rtc2))); 58 | 59 | if (!device_is_ready(led.port)) { 60 | return; 61 | } 62 | 63 | if (gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE) < 0) { 64 | return; 65 | } 66 | 67 | nrfx_rtc_tick_disable(&rtc); 68 | nrfx_rtc_counter_clear(&rtc); 69 | nrfx_rtc_enable(&rtc); 70 | nrfx_rtc_cc_set(&rtc, CC_CHANNEL, RTC_TIMEOUT_MS / RTC_PRESCALER_MS, true); 71 | printk("RTC Compare value: %d\n", RTC_TIMEOUT_MS / RTC_PRESCALER_MS); 72 | 73 | } -------------------------------------------------------------------------------- /sensor_thingy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(sensor_thingy) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /sensor_thingy/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_SENSOR=y 2 | CONFIG_ADXL362=y 3 | CONFIG_ADXL362_TRIGGER_GLOBAL_THREAD=y 4 | 5 | CONFIG_CBPRINTF_FP_SUPPORT=y -------------------------------------------------------------------------------- /sensor_thingy/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static void imu_trigger_handler(const struct device *dev, 7 | const struct sensor_trigger *trig) 8 | { 9 | struct sensor_value accel[3]; 10 | sensor_sample_fetch(dev); 11 | sensor_channel_get(dev, SENSOR_CHAN_ACCEL_XYZ, accel); 12 | printf("%.3f\t%.3f\t%.3f\r\n", 13 | sensor_value_to_double(&accel[0]), 14 | sensor_value_to_double(&accel[1]), 15 | sensor_value_to_double(&accel[2])); 16 | } 17 | 18 | 19 | int main() { 20 | setvbuf(stdout, NULL, _IONBF, 0); 21 | 22 | const struct device *imu = DEVICE_DT_GET_ONE(adi_adxl362); 23 | if (!device_is_ready(imu)) { 24 | printf("imu device not ready\n"); 25 | return 1; 26 | } 27 | 28 | // Set scale to ±2g 29 | struct sensor_value scale_val = { 30 | .val1 = 2, 31 | .val2 = 0, 32 | }; 33 | sensor_attr_set(imu, SENSOR_CHAN_ACCEL_XYZ, SENSOR_ATTR_FULL_SCALE, &scale_val); 34 | 35 | // Set ODR to 400 Hz 36 | struct sensor_value odr_val = { 37 | .val1 = 400, 38 | .val2 = 0, 39 | }; 40 | sensor_attr_set(imu, SENSOR_CHAN_ACCEL_XYZ, SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_val); 41 | 42 | struct sensor_trigger trig = { 43 | .type = SENSOR_TRIG_DATA_READY, 44 | .chan = SENSOR_CHAN_ACCEL_XYZ, 45 | }; 46 | 47 | sensor_trigger_set(imu, &trig, imu_trigger_handler); 48 | } 49 | -------------------------------------------------------------------------------- /simple_service/central_simple_service/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 5 | project(scan_adv) 6 | 7 | FILE(GLOB app_sources src/*.c) 8 | target_sources(app PRIVATE ${app_sources}) 9 | 10 | zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) -------------------------------------------------------------------------------- /simple_service/central_simple_service/README.rst: -------------------------------------------------------------------------------- 1 | .. _bluetooth-scan-adv-sample: 2 | 3 | Bluetooth: Scan & Advertise 4 | ########################### 5 | 6 | Overview 7 | ******** 8 | 9 | A simple application demonstrating combined BLE Broadcaster & Observer 10 | role functionality. The application will periodically send out 11 | advertising packets with a manufacturer data element. The content of the 12 | data is a single byte indicating how many advertising packets the device 13 | has received (the number will roll back to 0 after 255). 14 | 15 | Requirements 16 | ************ 17 | 18 | * BlueZ running on the host, or 19 | * A board with BLE support 20 | 21 | Building and Running 22 | ******************** 23 | 24 | This sample can be found under :zephyr_file:`samples/bluetooth/scan_adv` in the 25 | Zephyr tree. 26 | 27 | See :ref:`bluetooth samples section ` for details. 28 | -------------------------------------------------------------------------------- /simple_service/central_simple_service/prj.conf: -------------------------------------------------------------------------------- 1 | # Enable the BLE stack with GATT Client configuration 2 | CONFIG_BT=y 3 | CONFIG_BT_CENTRAL=y 4 | CONFIG_BT_SMP=y 5 | 6 | CONFIG_BT_DEBUG_LOG=y 7 | 8 | # Enable the BLE modules from NCS 9 | CONFIG_BT_SCAN=y 10 | CONFIG_BT_SCAN_FILTER_ENABLE=y 11 | CONFIG_BT_SCAN_UUID_CNT=1 12 | CONFIG_BT_GATT_CLIENT=y 13 | CONFIG_BT_GATT_DM=y 14 | CONFIG_BT_TINYCRYPT_ECC=y 15 | CONFIG_HEAP_MEM_POOL_SIZE=2048 16 | 17 | #Enable to Save BLE Settings 18 | CONFIG_BT_SETTINGS=y 19 | CONFIG_FLASH=y 20 | CONFIG_FLASH_PAGE_LAYOUT=y 21 | CONFIG_FLASH_MAP=y 22 | CONFIG_NVS=y 23 | CONFIG_SETTINGS=y 24 | 25 | # This example requires more workqueue stack 26 | CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 27 | 28 | 29 | CONFIG_SERIAL=y 30 | CONFIG_CONSOLE=y 31 | CONFIG_UART_CONSOLE=y 32 | CONFIG_LOG=y 33 | 34 | # Configure buttons and LEDs. 35 | CONFIG_DK_LIBRARY=y 36 | 37 | CONFIG_THREAD_NAME=y 38 | CONFIG_LOG_DEFAULT_LEVEL=4 39 | 40 | CONFIG_BT_GATT_DM_DATA_PRINT=y 41 | 42 | 43 | -------------------------------------------------------------------------------- /simple_service/central_simple_service/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: TBD 3 | name: TBD 4 | tests: 5 | sample.bluetooth.scan_adv: 6 | harness: bluetooth 7 | platform_allow: qemu_cortex_m3 qemu_x86 8 | tags: bluetooth 9 | -------------------------------------------------------------------------------- /simple_service/central_simple_service/src/main.c: -------------------------------------------------------------------------------- 1 | /* main.c - Application main entry point */ 2 | 3 | /* 4 | * Copyright (c) 2015-2016 Intel Corporation 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | */ 8 | 9 | #include "simple_service.h" 10 | #include "simple_service_client.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | #define LOG_MODULE_NAME ble_scanner 31 | LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG); 32 | 33 | #define CHRC_STATUS_LED DK_LED1 34 | #define CON_STATUS_LED DK_LED2 35 | 36 | #define FIXED_PASSWORD 123456 37 | 38 | static struct bt_conn *default_conn; 39 | static struct bt_simple_service simple_service; 40 | 41 | static void discovery_completed_cb(struct bt_gatt_dm *dm, 42 | void *context) 43 | { 44 | int err; 45 | 46 | LOG_INF("The discovery procedure succeeded"); 47 | 48 | bt_gatt_dm_data_print(dm); 49 | 50 | err = bt_simple_service_handles_assign(dm, &simple_service); 51 | if (err) { 52 | LOG_ERR("Could not init client object, error: %d", err); 53 | } 54 | 55 | bt_simple_service_subscribe_receive(&simple_service); 56 | 57 | err = bt_gatt_dm_data_release(dm); 58 | if (err) { 59 | LOG_ERR("Could not release the discovery data, error " 60 | "code: %d", err); 61 | } 62 | } 63 | 64 | static void discovery_service_not_found_cb(struct bt_conn *conn, 65 | void *context) 66 | { 67 | LOG_ERR("The service could not be found during the discovery"); 68 | } 69 | 70 | static void discovery_error_found_cb(struct bt_conn *conn, 71 | int err, 72 | void *context) 73 | { 74 | LOG_ERR("The discovery procedure failed with %d", err); 75 | } 76 | 77 | static const struct bt_gatt_dm_cb discovery_cb = { 78 | .completed = discovery_completed_cb, 79 | .service_not_found = discovery_service_not_found_cb, 80 | .error_found = discovery_error_found_cb, 81 | }; 82 | 83 | static void gatt_discover(struct bt_conn *conn) 84 | { 85 | int err; 86 | 87 | LOG_DBG("Running Gatt Discover Function"); 88 | 89 | err = bt_gatt_dm_start(conn, BT_UUID_CUSTOM_SERVICE, &discovery_cb, NULL); 90 | if (err) { 91 | LOG_ERR("Failed to start discovery (err %d)", err); 92 | } 93 | } 94 | 95 | static void connected(struct bt_conn *conn, uint8_t conn_err) 96 | { 97 | char addr[BT_ADDR_LE_STR_LEN]; 98 | int err; 99 | 100 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 101 | 102 | if (conn_err) { 103 | LOG_INF("Failed to connect to %s (%d)", addr, conn_err); 104 | 105 | if (default_conn == conn) { 106 | bt_conn_unref(default_conn); 107 | default_conn = NULL; 108 | 109 | err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); 110 | if (err) { 111 | LOG_ERR("Scanning failed to start (err %d)", 112 | err); 113 | } 114 | } 115 | 116 | return; 117 | } 118 | 119 | LOG_INF("Connected: %s", addr); 120 | 121 | err = bt_conn_set_security(conn, BT_SECURITY_L4); 122 | if (err) { 123 | LOG_WRN("Failed to set security: %d", err); 124 | gatt_discover(conn); 125 | } 126 | 127 | err = bt_scan_stop(); 128 | if ((!err) && (err != -EALREADY)) { 129 | LOG_ERR("Stop LE scan failed (err %d)", err); 130 | } 131 | dk_set_led_on(CON_STATUS_LED); 132 | } 133 | 134 | static void disconnected(struct bt_conn *conn, uint8_t reason) 135 | { 136 | char addr[BT_ADDR_LE_STR_LEN]; 137 | int err; 138 | 139 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 140 | 141 | LOG_INF("Disconnected: %s (reason %u)", addr, reason); 142 | 143 | if (default_conn != conn) { 144 | return; 145 | } 146 | 147 | bt_conn_unref(default_conn); 148 | default_conn = NULL; 149 | 150 | err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); 151 | if (err) { 152 | LOG_ERR("Scanning failed to start (err %d)", 153 | err); 154 | } 155 | dk_set_led_off(CON_STATUS_LED); 156 | } 157 | 158 | static void security_changed(struct bt_conn *conn, bt_security_t level, 159 | enum bt_security_err err) 160 | { 161 | char addr[BT_ADDR_LE_STR_LEN]; 162 | 163 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 164 | 165 | if (!err) { 166 | LOG_WRN("Security changed: %s level %u", addr, level); 167 | gatt_discover(conn); 168 | } else { 169 | LOG_ERR("Security failed: %s level %u err %d", addr, 170 | level, err); 171 | } 172 | 173 | 174 | } 175 | 176 | BT_CONN_CB_DEFINE(conn_callbacks) = { 177 | .connected = connected, 178 | .disconnected = disconnected, 179 | .security_changed = security_changed 180 | }; 181 | 182 | static void scan_filter_match(struct bt_scan_device_info *device_info, 183 | struct bt_scan_filter_match *filter_match, 184 | bool connectable) 185 | { 186 | char addr[BT_ADDR_LE_STR_LEN]; 187 | 188 | bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr)); 189 | 190 | LOG_INF("Filters matched. Address: %s connectable: %d", 191 | addr, connectable); 192 | } 193 | 194 | static void scan_connecting_error(struct bt_scan_device_info *device_info) 195 | { 196 | LOG_WRN("Connecting failed"); 197 | } 198 | 199 | static void scan_connecting(struct bt_scan_device_info *device_info, 200 | struct bt_conn *conn) 201 | { 202 | default_conn = bt_conn_ref(conn); 203 | } 204 | 205 | static void ble_data_sent(struct bt_simple_service *simple_service, uint8_t err, 206 | const uint8_t *const data, uint16_t len) 207 | { 208 | ARG_UNUSED(simple_service); 209 | 210 | LOG_DBG("Local BLE Write Callback fired. Nothing else to do."); 211 | 212 | if (err) { 213 | LOG_WRN("ATT error code: 0x%02X", err); 214 | } 215 | } 216 | 217 | static uint8_t ble_data_received(struct bt_simple_service *simple_service, 218 | const uint8_t *data, uint16_t len) 219 | { 220 | ARG_UNUSED(simple_service); 221 | 222 | if (*data == 0x01) { 223 | LOG_DBG("Received value: 0x01, setting LED on"); 224 | dk_set_led_on(CHRC_STATUS_LED); 225 | 226 | } else if (*data == 0x00) { 227 | 228 | LOG_DBG("Received value: 0x00, setting LED off"); 229 | dk_set_led_off(CHRC_STATUS_LED); 230 | } 231 | 232 | 233 | return BT_GATT_ITER_CONTINUE; 234 | } 235 | 236 | 237 | static int simple_service_client_init(void) 238 | { 239 | int err; 240 | 241 | struct bt_simple_service_client_init_param init = { 242 | .cb = { 243 | .received = ble_data_received, 244 | .sent = ble_data_sent, 245 | } 246 | }; 247 | 248 | err = bt_simple_service_client_init(&simple_service, &init); 249 | if (err) { 250 | LOG_ERR("Client initialization failed (err %d)", err); 251 | return err; 252 | } 253 | 254 | 255 | LOG_INF("Client module initialized"); 256 | return err; 257 | } 258 | 259 | BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL, 260 | scan_connecting_error, scan_connecting); 261 | 262 | static int scan_init(void) 263 | { 264 | int err; 265 | struct bt_scan_init_param scan_init = { 266 | .connect_if_match = 1, 267 | }; 268 | 269 | 270 | bt_scan_init(&scan_init); 271 | bt_scan_cb_register(&scan_cb); 272 | 273 | err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_CUSTOM_SERVICE); 274 | if (err) { 275 | LOG_ERR("Scanning filters cannot be set (err %d)", err); 276 | return err; 277 | } 278 | 279 | err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false); 280 | if (err) { 281 | LOG_ERR("Filters cannot be turned on (err %d)", err); 282 | return err; 283 | } 284 | 285 | LOG_INF("Scan module initialized"); 286 | return err; 287 | } 288 | 289 | 290 | static void auth_passkey_entry(struct bt_conn *conn) 291 | { 292 | char addr[BT_ADDR_LE_STR_LEN]; 293 | 294 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 295 | 296 | // Check for passkey entry event 297 | unsigned int passkey = FIXED_PASSWORD; 298 | LOG_INF("Passkey entered %s: %06u", addr, passkey); 299 | 300 | // Set passkey using bt_conn_auth_passkey_entry() 301 | bt_conn_auth_passkey_entry(conn, passkey); 302 | } 303 | 304 | static void auth_cancel(struct bt_conn *conn) 305 | { 306 | char addr[BT_ADDR_LE_STR_LEN]; 307 | 308 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 309 | 310 | LOG_INF("Pairing cancelled: %s", addr); 311 | } 312 | 313 | 314 | static void pairing_complete(struct bt_conn *conn, bool bonded) 315 | { 316 | char addr[BT_ADDR_LE_STR_LEN]; 317 | 318 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 319 | 320 | LOG_INF("Pairing completed: %s, bonded: %d", addr, bonded); 321 | } 322 | 323 | 324 | static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) 325 | { 326 | char addr[BT_ADDR_LE_STR_LEN]; 327 | 328 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 329 | 330 | LOG_ERR("Pairing failed conn: %s, reason %d", addr, reason); 331 | } 332 | 333 | 334 | 335 | static struct bt_conn_auth_cb conn_auth_callbacks = { 336 | .passkey_entry = auth_passkey_entry, 337 | .cancel = auth_cancel, 338 | }; 339 | 340 | 341 | static struct bt_conn_auth_info_cb conn_auth_info_callbacks = { 342 | .pairing_complete = pairing_complete, 343 | .pairing_failed = pairing_failed 344 | }; 345 | 346 | 347 | void button_handler(uint32_t button_state, uint32_t has_changed) 348 | { 349 | 350 | if (has_changed) 351 | { 352 | switch (has_changed) 353 | { 354 | case DK_BTN1_MSK: 355 | LOG_INF("Button 1 state = %d.", button_state); 356 | bt_simple_service_set_led(&simple_service, (uint8_t)button_state); 357 | break; 358 | case DK_BTN2_MSK: 359 | break; 360 | case DK_BTN3_MSK: 361 | break; 362 | case DK_BTN4_MSK: 363 | break; 364 | default: 365 | break; 366 | } 367 | 368 | } 369 | } 370 | 371 | void main(void) 372 | { 373 | int err; 374 | 375 | err = dk_leds_init(); 376 | if (err) { 377 | LOG_ERR("LEDs init failed (err %d)", err); 378 | return; 379 | } 380 | 381 | err = dk_buttons_init(button_handler); 382 | if (err) { 383 | LOG_ERR("'Co'uldn't init buttons (err %d)", err); 384 | } 385 | 386 | err = bt_conn_auth_cb_register(&conn_auth_callbacks); 387 | if (err) { 388 | LOG_ERR("Failed to register authorization callbacks."); 389 | return; 390 | } 391 | 392 | err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks); 393 | if (err) { 394 | LOG_ERR("Failed to register authorization info callbacks."); 395 | return; 396 | } 397 | 398 | err = bt_enable(NULL); 399 | 400 | if (err) { 401 | LOG_ERR("Bluetooth init failed (err %d)", err); 402 | return; 403 | } 404 | 405 | LOG_INF("Bluetooth initialized"); 406 | 407 | if (IS_ENABLED(CONFIG_SETTINGS)) { 408 | settings_load(); 409 | } 410 | 411 | simple_service_client_init(); 412 | scan_init(); 413 | 414 | LOG_INF("Scanning successfully started"); 415 | err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE); 416 | if (err) { 417 | LOG_ERR("Scanning failed to start (err %d)", err); 418 | return; 419 | } 420 | 421 | LOG_INF("Scanning successfully started"); 422 | } 423 | 424 | -------------------------------------------------------------------------------- /simple_service/central_simple_service/src/simple_service.h: -------------------------------------------------------------------------------- 1 | #define BT_UUID_CUSTOM_SERV_VAL \ 2 | BT_UUID_128_ENCODE(0x86b50001, 0x7ff7, 0x496e, 0xaa9c, 0x05fc11855eb3) 3 | #define BT_UUID_CUSTOM_SERVICE BT_UUID_DECLARE_128(BT_UUID_CUSTOM_SERV_VAL) 4 | 5 | #define BT_UUID_CUSTOM_LED_CHAR_VAL \ 6 | BT_UUID_128_ENCODE(0x86b50002, 0x7ff7, 0x496e, 0xaa9c, 0x05fc11855eb3) 7 | #define BT_UUID_CUSTOM_LED BT_UUID_DECLARE_128(BT_UUID_CUSTOM_LED_CHAR_VAL) 8 | 9 | #define BT_UUID_BUTTON_CHRC_VAL \ 10 | BT_UUID_128_ENCODE(0x86b50003, 0x7ff7, 0x496e, 0xaa9c, 0x05fc11855eb3) 11 | #define BT_UUID_BUTTON_CHRC BT_UUID_DECLARE_128(BT_UUID_BUTTON_CHRC_VAL) -------------------------------------------------------------------------------- /simple_service/central_simple_service/src/simple_service_client.c: -------------------------------------------------------------------------------- 1 | #include "simple_service.h" 2 | #include "simple_service_client.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #define LOG_MODULE_NAME simple_service 21 | LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG); 22 | 23 | enum { 24 | SIMPLE_SERVICE_C_INITIALIZED, 25 | SIMPLE_SERVICE_C_BUTTOM_NOTIF_ENABLED, 26 | SIMPLE_SERVICE_C_RX_WRITE_PENDING 27 | }; 28 | 29 | int bt_simple_service_client_init(struct bt_simple_service *simple_service_c, 30 | const struct bt_simple_service_client_init_param *simple_service_c_init) 31 | { 32 | if (!simple_service_c || !simple_service_c_init) { 33 | return -EINVAL; 34 | } 35 | 36 | if (atomic_test_and_set_bit(&simple_service_c->state, SIMPLE_SERVICE_C_INITIALIZED)) { 37 | return -EALREADY; 38 | } 39 | 40 | memcpy(&simple_service_c->cb, &simple_service_c_init->cb, sizeof(simple_service_c->cb)); 41 | 42 | return 0; 43 | } 44 | 45 | int bt_simple_service_handles_assign(struct bt_gatt_dm *dm, 46 | struct bt_simple_service *simple_service_c) 47 | 48 | { 49 | const struct bt_gatt_dm_attr *gatt_service_attr = 50 | bt_gatt_dm_service_get(dm); 51 | const struct bt_gatt_service_val *gatt_service = 52 | bt_gatt_dm_attr_service_val(gatt_service_attr); 53 | const struct bt_gatt_dm_attr *gatt_chrc; 54 | const struct bt_gatt_dm_attr *gatt_desc; 55 | 56 | if (bt_uuid_cmp(gatt_service->uuid, BT_UUID_CUSTOM_SERVICE)) { 57 | return -ENOTSUP; 58 | } 59 | LOG_DBG("Getting handles from Custom Auth service."); 60 | memset(&simple_service_c->handles, 0xFF, sizeof(simple_service_c->handles)); 61 | 62 | /* Get Led (WRITE) Chatacteristic */ 63 | gatt_chrc = bt_gatt_dm_char_by_uuid(dm, BT_UUID_CUSTOM_LED); 64 | if (!gatt_chrc) { 65 | LOG_ERR("Missing LED Write characteristic."); 66 | return -EINVAL; 67 | } 68 | gatt_desc = bt_gatt_dm_desc_by_uuid(dm, gatt_chrc, BT_UUID_CUSTOM_LED); 69 | if (!gatt_desc) { 70 | LOG_ERR("Missing LED Write value descriptor in characteristic."); 71 | return -EINVAL; 72 | } 73 | LOG_DBG("Found handle for LED Write characteristic = 0x%x.", gatt_desc->handle); 74 | simple_service_c->handles.led = gatt_desc->handle; 75 | 76 | 77 | /* Get Button (READ) Characterstic and CCC*/ 78 | gatt_chrc = bt_gatt_dm_char_by_uuid(dm, BT_UUID_BUTTON_CHRC); 79 | if (!gatt_chrc) { 80 | LOG_ERR("Missing Button Read characteristic."); 81 | return -EINVAL; 82 | } 83 | gatt_desc = bt_gatt_dm_desc_by_uuid(dm, gatt_chrc, BT_UUID_BUTTON_CHRC); 84 | if (!gatt_desc) { 85 | LOG_ERR("Missing Button Read value descriptor in characteristic."); 86 | return -EINVAL; 87 | } 88 | LOG_DBG("Found handle for BUTTON Read characteristic."); 89 | simple_service_c->handles.button = gatt_desc->handle; 90 | /* Button (Read) CCC */ 91 | gatt_desc = bt_gatt_dm_desc_by_uuid(dm, gatt_chrc, BT_UUID_GATT_CCC); 92 | if (!gatt_desc) { 93 | LOG_ERR("Missing Button Read CCC in characteristic."); 94 | return -EINVAL; 95 | } 96 | LOG_DBG("Found handle for CCC of BUTTON Read characteristic."); 97 | simple_service_c->handles.button_ccc = gatt_desc->handle; 98 | 99 | 100 | /* Assign connection instance. */ 101 | simple_service_c->conn = bt_gatt_dm_conn_get(dm); 102 | return 0; 103 | } 104 | 105 | static uint8_t on_received(struct bt_conn *conn, 106 | struct bt_gatt_subscribe_params *params, 107 | const void *data, uint16_t length) 108 | { 109 | struct bt_simple_service *simple_service; 110 | 111 | /* Retrieve Client module context. */ 112 | simple_service = CONTAINER_OF(params, struct bt_simple_service, button_notif_params); 113 | 114 | if (!data) { 115 | LOG_DBG("[UNSUBSCRIBED]"); 116 | params->value_handle = 0; 117 | atomic_clear_bit(&simple_service->state, SIMPLE_SERVICE_C_BUTTOM_NOTIF_ENABLED); 118 | if (simple_service->cb.unsubscribed) { 119 | simple_service->cb.unsubscribed(simple_service); 120 | } 121 | return BT_GATT_ITER_STOP; 122 | } 123 | 124 | uint8_t value = *((uint8_t*)data); 125 | LOG_DBG("[NOTIFICATION] data %p length %u value %d", data, length, value); 126 | /* 127 | if (value == 0x01) { 128 | LOG_DBG("Received value: 0x01, setting LED on"); 129 | dk_set_led_on(CHRC_STATUS_LED); 130 | 131 | } else if (value == 0x00) { 132 | 133 | LOG_DBG("Received value: 0x00, setting LED off"); 134 | dk_set_led_off(CHRC_STATUS_LED); 135 | } 136 | */ 137 | 138 | if (simple_service->cb.received) { 139 | return simple_service->cb.received(simple_service, data, length); 140 | } 141 | 142 | return BT_GATT_ITER_CONTINUE; 143 | } 144 | 145 | int bt_simple_service_subscribe_receive(struct bt_simple_service *simple_service_c) 146 | { 147 | int err; 148 | 149 | if (atomic_test_and_set_bit(&simple_service_c->state, SIMPLE_SERVICE_C_BUTTOM_NOTIF_ENABLED)) { 150 | return -EALREADY; 151 | } 152 | 153 | simple_service_c->button_notif_params.notify = on_received; 154 | simple_service_c->button_notif_params.value = BT_GATT_CCC_NOTIFY; 155 | simple_service_c->button_notif_params.value_handle = simple_service_c->handles.button; 156 | simple_service_c->button_notif_params.ccc_handle = simple_service_c->handles.button_ccc; 157 | atomic_set_bit(simple_service_c->button_notif_params.flags, 158 | BT_GATT_SUBSCRIBE_FLAG_VOLATILE); 159 | 160 | err = bt_gatt_subscribe(simple_service_c->conn, &simple_service_c->button_notif_params); 161 | if (err) { 162 | LOG_ERR("Subscribe failed (err %d)", err); 163 | atomic_clear_bit(&simple_service_c->state, SIMPLE_SERVICE_C_BUTTOM_NOTIF_ENABLED); 164 | } else { 165 | LOG_DBG("[SUBSCRIBED]"); 166 | } 167 | 168 | return err; 169 | } 170 | 171 | static void on_sent(struct bt_conn *conn, uint8_t err, 172 | struct bt_gatt_write_params *params) 173 | { 174 | 175 | struct bt_simple_service *simple_service_c; 176 | const void *data; 177 | uint16_t length; 178 | 179 | /* Retrieve module context. */ 180 | simple_service_c = CONTAINER_OF(params, struct bt_simple_service, write_params); 181 | 182 | /* Make a copy of volatile data that is required by the callback. */ 183 | data = params->data; 184 | length = params->length; 185 | 186 | atomic_clear_bit(&simple_service_c->state, SIMPLE_SERVICE_C_RX_WRITE_PENDING); 187 | if (simple_service_c->cb.sent) { 188 | simple_service_c->cb.sent(simple_service_c, err, data, length); 189 | } 190 | 191 | } 192 | 193 | int bt_simple_service_set_led(struct bt_simple_service *simple_service_c, const uint8_t data) 194 | { 195 | int err; 196 | 197 | if (!simple_service_c->conn) { 198 | return -ENOTCONN; 199 | } 200 | 201 | if (atomic_test_and_set_bit(&simple_service_c->state, SIMPLE_SERVICE_C_RX_WRITE_PENDING)) { 202 | return -EALREADY; 203 | } 204 | 205 | simple_service_c->write_params.func = on_sent; 206 | simple_service_c->write_params.handle = simple_service_c->handles.led; /* replace with the handle of the characteristic */ 207 | simple_service_c->write_params.length = sizeof(data); 208 | simple_service_c->write_params.offset = 0; 209 | simple_service_c->write_params.data = &data; 210 | 211 | err = bt_gatt_write(simple_service_c->conn, &simple_service_c->write_params); 212 | if (err) { 213 | atomic_clear_bit(&simple_service_c->state, SIMPLE_SERVICE_C_RX_WRITE_PENDING); 214 | LOG_ERR("bt_gatt_write Error"); 215 | } 216 | 217 | return err; 218 | 219 | } -------------------------------------------------------------------------------- /simple_service/central_simple_service/src/simple_service_client.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | /** @brief Handles on the connected peer device that are needed to interact with 12 | * the device. 13 | */ 14 | struct bt_simple_service_client_handles { 15 | 16 | /** Handle of the LED characteristic, as provided by 17 | * a discovery. 18 | */ 19 | uint16_t led; 20 | uint16_t button; 21 | uint16_t button_ccc; 22 | }; 23 | 24 | struct bt_simple_service; 25 | 26 | struct bt_simple_service_cb { 27 | /** @brief Data received callback. 28 | * 29 | * The data has been received as a notification of the Read 30 | * Characteristic. 31 | * 32 | * @param[in] simple_service Simple Service Client instance. 33 | * @param[in] data Received data. 34 | * @param[in] len Length of received data. 35 | * 36 | * @retval BT_GATT_ITER_CONTINUE To keep notifications enabled. 37 | * @retval BT_GATT_ITER_STOP To disable notifications. 38 | */ 39 | uint8_t (*received)(struct bt_simple_service *simple_service, const uint8_t *data, uint16_t len); 40 | 41 | /** @brief Data sent callback. 42 | * 43 | * The data has been sent and written to the Write Characteristic. 44 | * 45 | * @param[in] simple_service Simple Service Client instance. 46 | * @param[in] err ATT error code. 47 | * @param[in] data Transmitted data. 48 | * @param[in] len Length of transmitted data. 49 | */ 50 | void (*sent)(struct bt_simple_service *simple_service, uint8_t err, const uint8_t *data, uint16_t len); 51 | 52 | /** @brief TX notifications disabled callback. 53 | * 54 | * TX notifications have been disabled. 55 | * 56 | * @param[in] simple_service Simple Service Client instance. 57 | */ 58 | void (*unsubscribed)(struct bt_simple_service *simple_service); 59 | }; 60 | 61 | /** @brief NUS Client initialization structure. */ 62 | struct bt_simple_service_client_init_param { 63 | 64 | /** Callbacks provided by the user. */ 65 | struct bt_simple_service_cb cb; 66 | }; 67 | 68 | /** 69 | * @brief Custom Auth object. 70 | * 71 | * @note 72 | * This structure is defined here to allow the user to allocate the memory 73 | * for it in an application-dependent manner. 74 | * Do not use any of the fields here directly, but use the accessor functions. 75 | * There are accessors for every field you might need. 76 | */ 77 | struct bt_simple_service { 78 | /** Connection object. */ 79 | struct bt_conn *conn; 80 | /** Internal state. */ 81 | atomic_t state; 82 | /** Handles on the connected peer device that are needed to interact with the device. */ 83 | struct bt_simple_service_client_handles handles; 84 | 85 | /** GATT subscribe parameters for BUTTON Characteristic. */ 86 | struct bt_gatt_subscribe_params button_notif_params; 87 | 88 | /** GATT write parameters for LED Characteristic. */ 89 | struct bt_gatt_write_params write_params; 90 | 91 | /** Application callbacks. */ 92 | struct bt_simple_service_cb cb; 93 | }; 94 | 95 | 96 | 97 | /** @brief Assign handles to the NUS Client instance. 98 | * 99 | * This function should be called when a link with a peer has been established 100 | * to associate the link to this instance of the module. This makes it 101 | * possible to handle several links and associate each link to a particular 102 | * instance of this module. The GATT attribute handles are provided by the 103 | * GATT DB discovery module. 104 | * 105 | * @param[in] dm Discovery object. 106 | * @param[in,out] nus NUS Client instance. 107 | * 108 | * @retval 0 If the operation was successful. 109 | * @retval (-ENOTSUP) Special error code used when UUID 110 | * of the service does not match the expected UUID. 111 | * @retval Otherwise, a negative error code is returned. 112 | */ 113 | int bt_simple_service_handles_assign(struct bt_gatt_dm *dm, 114 | struct bt_simple_service *simple_service_c); 115 | 116 | 117 | 118 | 119 | /** @brief Request the peer to start sending notifications for the TX 120 | * Characteristic. 121 | * 122 | * This function enables notifications for the NUS TX Characteristic at the peer 123 | * by writing to the CCC descriptor of the NUS TX Characteristic. 124 | * 125 | * @param[in,out] nus NUS Client instance. 126 | * 127 | * @retval 0 If the operation was successful. 128 | * Otherwise, a negative error code is returned. 129 | */ 130 | int bt_simple_service_subscribe_receive(struct bt_simple_service *simple_service_c); 131 | 132 | int bt_simple_service_set_led(struct bt_simple_service *simple_service_c, const uint8_t data); 133 | 134 | 135 | int bt_simple_service_client_init(struct bt_simple_service *simple_service_c, 136 | const struct bt_simple_service_client_init_param *simple_service_c_init); -------------------------------------------------------------------------------- /simple_service/peripheral_simple_service/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) -------------------------------------------------------------------------------- /simple_service/peripheral_simple_service/README.rst: -------------------------------------------------------------------------------- 1 | .. _hello_world: 2 | 3 | Hello World 4 | ########### 5 | 6 | Overview 7 | ******** 8 | 9 | A simple sample that can be used with any :ref:`supported board ` and 10 | prints "Hello World" to the console. 11 | 12 | Building and Running 13 | ******************** 14 | 15 | This application can be built and executed on QEMU as follows: 16 | 17 | .. zephyr-app-commands:: 18 | :zephyr-app: samples/hello_world 19 | :host-os: unix 20 | :board: qemu_x86 21 | :goals: run 22 | :compact: 23 | 24 | To build for another board, change "qemu_x86" above to that board's name. 25 | 26 | Sample Output 27 | ============= 28 | 29 | .. code-block:: console 30 | 31 | Hello World! x86 32 | 33 | Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. 34 | -------------------------------------------------------------------------------- /simple_service/peripheral_simple_service/prj.conf: -------------------------------------------------------------------------------- 1 | # Configure logger 2 | CONFIG_LOG=y 3 | CONFIG_USE_SEGGER_RTT=n 4 | CONFIG_LOG_BACKEND_UART=y 5 | CONFIG_LOG_DEFAULT_LEVEL=4 6 | 7 | # Configure buttons and LEDs. 8 | CONFIG_DK_LIBRARY=y 9 | 10 | # Configure Bluetooth 11 | CONFIG_BT=y 12 | CONFIG_BT_PERIPHERAL=y 13 | CONFIG_BT_SMP=y 14 | CONFIG_BT_DEVICE_NAME="Custom Service" 15 | CONFIG_BT_DEBUG_LOG=y 16 | CONFIG_BT_MAX_CONN=1 17 | CONFIG_BT_MAX_PAIRED=1 18 | CONFIG_BT_SMP_SC_ONLY=y 19 | CONFIG_BT_TINYCRYPT_ECC=y 20 | 21 | #Enable to Save BLE Settings 22 | CONFIG_BT_SETTINGS=y 23 | CONFIG_FLASH=y 24 | CONFIG_FLASH_PAGE_LAYOUT=y 25 | CONFIG_FLASH_MAP=y 26 | CONFIG_NVS=y 27 | CONFIG_SETTINGS=y 28 | -------------------------------------------------------------------------------- /simple_service/peripheral_simple_service/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Hello World sample, the simplest Zephyr 3 | application 4 | name: hello world 5 | common: 6 | tags: introduction 7 | integration_platforms: 8 | - native_posix 9 | harness: console 10 | harness_config: 11 | type: one_line 12 | regex: 13 | - "Hello World! (.*)" 14 | tests: 15 | sample.basic.helloworld: 16 | tags: introduction 17 | -------------------------------------------------------------------------------- /simple_service/peripheral_simple_service/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2014 Wind River Systems, Inc. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | static uint8_t button_value = 0; 22 | 23 | static bool notify_enabled; 24 | 25 | 26 | #define LOG_MODULE_NAME app 27 | LOG_MODULE_REGISTER(LOG_MODULE_NAME); 28 | 29 | #define CHRC_STATUS_LED DK_LED1 30 | #define CON_STATUS_LED DK_LED2 31 | 32 | #define DEVICE_NAME CONFIG_BT_DEVICE_NAME 33 | #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME)-1) 34 | 35 | #define BT_UUID_CUSTOM_SERV_VAL \ 36 | BT_UUID_128_ENCODE(0x86b50001, 0x7ff7, 0x496e, 0xaa9c, 0x05fc11855eb3) 37 | #define BT_UUID_CUSTOM_SERVICE BT_UUID_DECLARE_128(BT_UUID_CUSTOM_SERV_VAL) 38 | 39 | #define BT_UUID_CUSTOM_LED_CHAR_VAL \ 40 | BT_UUID_128_ENCODE(0x86b50002, 0x7ff7, 0x496e, 0xaa9c, 0x05fc11855eb3) 41 | #define BT_UUID_CUSTOM_LED BT_UUID_DECLARE_128(BT_UUID_CUSTOM_LED_CHAR_VAL) 42 | 43 | #define BT_UUID_BUTTON_CHRC_VAL \ 44 | BT_UUID_128_ENCODE(0x86b50003, 0x7ff7, 0x496e, 0xaa9c, 0x05fc11855eb3) 45 | #define BT_UUID_BUTTON_CHRC BT_UUID_DECLARE_128(BT_UUID_BUTTON_CHRC_VAL) 46 | 47 | #define FIXED_PASSWORD 123456 48 | 49 | static struct bt_conn *current_conn; 50 | static struct bt_conn *auth_conn; 51 | static const struct bt_data ad[] = { 52 | BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), 53 | BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), 54 | }; 55 | 56 | static const struct bt_data sd[] = { 57 | BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_CUSTOM_SERV_VAL), 58 | }; 59 | 60 | void on_sent(struct bt_conn *conn, void *user_data) 61 | { 62 | ARG_UNUSED(user_data); 63 | LOG_INF("Notification sent on connection %p", (void *)conn); 64 | } 65 | 66 | static ssize_t on_write(struct bt_conn *conn, const struct bt_gatt_attr *attr, 67 | const void *buf, uint16_t len, uint16_t offset, 68 | uint8_t flags) 69 | { 70 | uint8_t temp_str[len+1]; 71 | memcpy(temp_str, buf, len); 72 | temp_str[len] = 0x00; 73 | 74 | //LOG_DBG("Received data on conn %p. Len: %d", (void *)conn, len); 75 | //LOG_HEXDUMP_DBG(temp_str, len, "Received"); 76 | 77 | if (temp_str[0] == 0x01) { 78 | LOG_DBG("Received value: 0x01, setting LED on"); 79 | dk_set_led_on(CHRC_STATUS_LED); 80 | 81 | } else if (temp_str[0] == 0x00) { 82 | 83 | LOG_DBG("Received value: 0x00, setting LED off"); 84 | dk_set_led_off(CHRC_STATUS_LED); 85 | } 86 | return len; 87 | } 88 | 89 | void button_chrc_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) 90 | { 91 | notify_enabled = (value == BT_GATT_CCC_NOTIFY); 92 | LOG_INF("Notifications %s", notify_enabled? "enabled":"disabled"); 93 | 94 | } 95 | 96 | 97 | static ssize_t read_button_chrc_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr, 98 | void *buf, uint16_t len, uint16_t offset) 99 | { 100 | LOG_DBG("Attribute read, handle: %u, conn: %p", attr->handle, 101 | (void *)conn); 102 | 103 | return bt_gatt_attr_read(conn, attr, buf, len, offset, &button_value, 104 | sizeof(button_value)); 105 | } 106 | 107 | BT_GATT_SERVICE_DEFINE( custom_srv, 108 | BT_GATT_PRIMARY_SERVICE(BT_UUID_CUSTOM_SERVICE), 109 | 110 | // BUTTON 111 | BT_GATT_CHARACTERISTIC( BT_UUID_BUTTON_CHRC, 112 | BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, 113 | BT_GATT_PERM_READ_AUTHEN, 114 | read_button_chrc_cb, 115 | NULL, NULL), 116 | BT_GATT_CCC(button_chrc_ccc_cfg_changed, BT_GATT_PERM_READ_AUTHEN | BT_GATT_PERM_WRITE_AUTHEN), 117 | 118 | //LED 119 | BT_GATT_CHARACTERISTIC( BT_UUID_CUSTOM_LED, 120 | BT_GATT_CHRC_WRITE, 121 | BT_GATT_PERM_WRITE_AUTHEN, 122 | NULL, on_write, NULL), 123 | ); 124 | 125 | static void connected(struct bt_conn *conn, uint8_t err) 126 | { 127 | char addr[BT_ADDR_LE_STR_LEN]; 128 | 129 | if (err) { 130 | LOG_ERR("Connection failed (err %u)", err); 131 | return; 132 | } 133 | 134 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 135 | LOG_INF("Connected %s", addr); 136 | 137 | current_conn = bt_conn_ref(conn); 138 | 139 | dk_set_led_on(CON_STATUS_LED); 140 | } 141 | 142 | static void disconnected(struct bt_conn *conn, uint8_t reason) 143 | { 144 | char addr[BT_ADDR_LE_STR_LEN]; 145 | 146 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 147 | 148 | LOG_INF("Disconnected: %s (reason %u)", addr, reason); 149 | 150 | if (auth_conn) { 151 | bt_conn_unref(auth_conn); 152 | auth_conn = NULL; 153 | } 154 | 155 | if (current_conn) { 156 | bt_conn_unref(current_conn); 157 | current_conn = NULL; 158 | dk_set_led_off(CON_STATUS_LED); 159 | } 160 | } 161 | 162 | static void security_changed(struct bt_conn *conn, bt_security_t level, 163 | enum bt_security_err err) 164 | { 165 | char addr[BT_ADDR_LE_STR_LEN]; 166 | 167 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 168 | 169 | if (!err) { 170 | LOG_WRN("Security changed: %s level %u", addr, level); 171 | } else { 172 | LOG_ERR("Security failed: %s level %u err %d", addr, 173 | level, err); 174 | } 175 | } 176 | BT_CONN_CB_DEFINE(conn_callbacks) = { 177 | .connected = connected, 178 | .disconnected = disconnected, 179 | .security_changed = security_changed, 180 | }; 181 | 182 | static void auth_passkey_entry(struct bt_conn *conn) 183 | { 184 | char addr[BT_ADDR_LE_STR_LEN]; 185 | 186 | auth_conn = bt_conn_ref(conn); 187 | 188 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 189 | 190 | // Check for passkey entry event 191 | unsigned int passkey = FIXED_PASSWORD; 192 | LOG_INF("Passkey entered %s: %06u", addr, passkey); 193 | 194 | // Set passkey using bt_conn_auth_passkey_entry() 195 | bt_conn_auth_passkey_entry(conn, passkey); 196 | } 197 | 198 | static void auth_cancel(struct bt_conn *conn) 199 | { 200 | char addr[BT_ADDR_LE_STR_LEN]; 201 | 202 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 203 | 204 | LOG_ERR("Pairing cancelled: %s", addr); 205 | } 206 | static void pairing_confirm(struct bt_conn *conn) 207 | { 208 | char addr[BT_ADDR_LE_STR_LEN]; 209 | 210 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 211 | 212 | bt_conn_auth_pairing_confirm(conn); 213 | 214 | LOG_INF("Pairing confirmed: %s", addr); 215 | } 216 | static void pairing_complete(struct bt_conn *conn, bool bonded) 217 | { 218 | char addr[BT_ADDR_LE_STR_LEN]; 219 | 220 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 221 | 222 | LOG_INF("Pairing completed: %s, bonded: %d", addr, bonded); 223 | } 224 | 225 | static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) 226 | { 227 | char addr[BT_ADDR_LE_STR_LEN]; 228 | 229 | bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); 230 | 231 | LOG_INF("Pairing failed conn: %s, reason %d", addr, reason); 232 | 233 | bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); 234 | } 235 | 236 | /* Callbacks */ 237 | static struct bt_conn_auth_cb conn_auth_callbacks = { 238 | .passkey_display = NULL, 239 | .passkey_confirm = NULL, 240 | .passkey_entry = auth_passkey_entry, 241 | .cancel = auth_cancel, 242 | .pairing_confirm = pairing_confirm, 243 | }; 244 | 245 | static struct bt_conn_auth_info_cb conn_auth_info_callbacks = { 246 | .pairing_complete = pairing_complete, 247 | .pairing_failed = pairing_failed 248 | }; 249 | 250 | int send_button_notification(struct bt_conn *conn, uint8_t value) 251 | { 252 | if (!notify_enabled) { 253 | return -EACCES; 254 | } 255 | int err = 0; 256 | 257 | return bt_gatt_notify(NULL, &custom_srv.attrs[2], 258 | &button_value, 259 | sizeof(button_value)); 260 | 261 | struct bt_gatt_notify_params params = {0}; 262 | const struct bt_gatt_attr *attr = &custom_srv.attrs[2]; 263 | 264 | params.attr = attr; 265 | params.data = &value; 266 | params.len = 1; 267 | params.func = on_sent; 268 | 269 | err = bt_gatt_notify_cb(conn, ¶ms); 270 | 271 | return err; 272 | } 273 | 274 | 275 | void button_handler(uint32_t button_state, uint32_t has_changed) 276 | { 277 | uint8_t err; 278 | 279 | if (has_changed) 280 | { 281 | switch (has_changed) 282 | { 283 | case DK_BTN1_MSK: 284 | button_value = button_state; 285 | err = send_button_notification(current_conn, button_value); 286 | if (err) { 287 | LOG_ERR("Couldn't send notificaton. (err: %d)", err); 288 | } 289 | LOG_INF("Button 1 pressed - %d.", button_value); 290 | break; 291 | case DK_BTN2_MSK: 292 | break; 293 | case DK_BTN3_MSK: 294 | break; 295 | case DK_BTN4_MSK: 296 | break; 297 | default: 298 | break; 299 | } 300 | 301 | } 302 | } 303 | 304 | void main(void) 305 | { 306 | int err; 307 | 308 | LOG_INF("Starting Hello Bluetooth"); 309 | 310 | err = dk_leds_init(); 311 | if (err) { 312 | LOG_ERR("LEDs init failed (err %d)", err); 313 | return; 314 | } 315 | 316 | err = dk_buttons_init(button_handler); 317 | if (err) { 318 | LOG_ERR("Couldn't init buttons (err %d)", err); 319 | } 320 | 321 | 322 | err = bt_conn_auth_cb_register(&conn_auth_callbacks); 323 | if (err) { 324 | LOG_ERR("Failed to register authorization callbacks."); 325 | return; 326 | } 327 | 328 | err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks); 329 | if (err) { 330 | LOG_ERR("Failed to register authorization info callbacks."); 331 | return; 332 | } 333 | 334 | 335 | err = bt_enable(NULL); 336 | if (err) { 337 | LOG_ERR("Bluetooth init failed (err %d)", err); 338 | return; 339 | } 340 | LOG_INF("Bluetooth initialized"); 341 | 342 | if (IS_ENABLED(CONFIG_SETTINGS)) { 343 | settings_load(); 344 | } 345 | 346 | err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, 347 | ARRAY_SIZE(sd)); 348 | if (err) { 349 | LOG_ERR("Advertising failed to start (err %d)", err); 350 | return; 351 | } 352 | 353 | LOG_INF("Advertising successfully started"); 354 | 355 | } 356 | -------------------------------------------------------------------------------- /timer_dppi_spim/.vscode/.cortex-debug.peripherals.state.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /timer_dppi_spim/.vscode/.cortex-debug.registers.state.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /timer_dppi_spim/.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Win32", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "C:/Work/nrf-tm/v1.6.1/zephyr/include/**" 8 | ], 9 | "defines": [ 10 | "_DEBUG", 11 | "UNICODE", 12 | "_UNICODE" 13 | ], 14 | "compilerPath": "C:/gnuarmemb/bin/arm-none-eabi-gcc.exe", 15 | "cStandard": "c17", 16 | "cppStandard": "c++17", 17 | "intelliSenseMode": "clang-x64", 18 | "configurationProvider": "nrf-connect" 19 | } 20 | ], 21 | "version": 4 22 | } -------------------------------------------------------------------------------- /timer_dppi_spim/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "arm-none-eabi-gcc.exe - Build and debug active file", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${fileDirname}\\${fileBasenameNoExtension}.exe", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "C:/gnuarmemb/bin", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "gdb", 18 | "miDebuggerPath": "C:\\gnuarmemb\\bin\\gdb.exe", 19 | "setupCommands": [ 20 | { 21 | "description": "Enable pretty-printing for gdb", 22 | "text": "-enable-pretty-printing", 23 | "ignoreFailures": true 24 | } 25 | ], 26 | "preLaunchTask": "C/C++: arm-none-eabi-gcc.exe build active file" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /timer_dppi_spim/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "timing.h": "c", 4 | "nrfx_gpiote.h": "c", 5 | "nrfx_dppi.h": "c", 6 | "nrfx_spim.h": "c" 7 | }, 8 | "nrf-connect.applications": [ 9 | "c:\\Work\\Ventrix\\blinky" 10 | ], 11 | "kconfig.zephyr.west": "c:\\Work\\nrf-tm\\v1.7.0\\toolchain\\opt\\bin\\Scripts\\west.exe", 12 | "kconfig.zephyr.base": "c:\\Work\\nrf-tm\\v1.7.0\\zephyr", 13 | "kconfig.zephyr.board": { 14 | "board": "nrf5340dk_nrf5340_cpuappns", 15 | "arch": "arm", 16 | "dir": "c:\\Work\\nrf-tm\\v1.6.1\\zephyr\\boards\\arm\\nrf5340dk_nrf5340" 17 | }, 18 | "nrf-connect.toolchain.path": "c:\\Work\\nrf-tm\\v1.7.0\\toolchain", 19 | "nrf-connect.topdir": "c:\\Work\\nrf-tm\\v1.7.0" 20 | } -------------------------------------------------------------------------------- /timer_dppi_spim/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "type": "cppbuild", 5 | "label": "C/C++: arm-none-eabi-gcc.exe build active file", 6 | "command": "C:/gnuarmemb/bin/arm-none-eabi-gcc.exe", 7 | "args": [ 8 | "-g", 9 | "${file}", 10 | "-o", 11 | "${fileDirname}\\${fileBasenameNoExtension}.exe" 12 | ], 13 | "options": { 14 | "cwd": "C:/gnuarmemb/bin" 15 | }, 16 | "problemMatcher": [ 17 | "$gcc" 18 | ], 19 | "group": { 20 | "kind": "build", 21 | "isDefault": true 22 | }, 23 | "detail": "Task generated by Debugger." 24 | } 25 | ], 26 | "version": "2.0.0" 27 | } -------------------------------------------------------------------------------- /timer_dppi_spim/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.13.1) 4 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 5 | project(blinky) 6 | 7 | target_sources(app PRIVATE src/main.c) 8 | -------------------------------------------------------------------------------- /timer_dppi_spim/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_GPIO=y 2 | CONFIG_LOG=y 3 | 4 | CONFIG_THREAD_ANALYZER=y 5 | CONFIG_THREAD_NAME=y 6 | CONFIG_ZERO_LATENCY_IRQS=y 7 | CONFIG_ASSERT=y 8 | 9 | CONFIG_NRFX_TIMER=y 10 | CONFIG_NRFX_TIMER1=y 11 | CONFIG_NRFX_PPI=y 12 | CONFIG_NRFX_SPIM=y 13 | CONFIG_NRFX_SPIM2=y -------------------------------------------------------------------------------- /timer_dppi_spim/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: Blinky Sample 3 | tests: 4 | sample.basic.blinky: 5 | tags: LED gpio 6 | filter: dt_enabled_alias_with_parent_compat("led0", "gpio-leds") 7 | depends_on: gpio 8 | harness: led 9 | integration_platforms: 10 | - frdm_k64f 11 | -------------------------------------------------------------------------------- /timer_dppi_spim/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Joao Dullius 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | LOG_MODULE_REGISTER(timer_dppi_spim, LOG_LEVEL_INF); 17 | 18 | static const nrfx_timer_t m_sample_timer = NRFX_TIMER_INSTANCE(1); 19 | 20 | #define BUF_SIZE 10 21 | uint8_t buffer_tx[BUF_SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 22 | uint8_t buffer_rx[BUF_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 23 | 24 | nrfx_spim_xfer_desc_t transfer = { 25 | .p_tx_buffer = buffer_tx, ///< Pointer to TX buffer. 26 | .tx_length = BUF_SIZE, ///< TX buffer length. 27 | .p_rx_buffer = buffer_rx, ///< Pointer to RX buffer. 28 | .rx_length = BUF_SIZE ///< RX buffer length. 29 | }; 30 | 31 | nrfx_spim_t spi_instance = NRFX_SPIM_INSTANCE(2); 32 | nrfx_spim_config_t spi_config = 33 | NRFX_SPIM_DEFAULT_CONFIG(28, 29, 30, NRFX_SPIM_PIN_NOT_USED); 34 | 35 | void timer_handler(nrf_timer_event_t event_type, void* p_context) 36 | { 37 | LOG_DBG("Timer Handler."); 38 | 39 | } 40 | 41 | static void timer_init(void) 42 | { 43 | nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG; 44 | timer_config.bit_width = NRF_TIMER_BIT_WIDTH_32; 45 | nrfx_err_t err_code = nrfx_timer_init(&m_sample_timer, &timer_config, timer_handler); 46 | if (err_code != NRFX_SUCCESS) { 47 | LOG_ERR("nrfx_timer_init error: %08x", err_code); 48 | return; 49 | } 50 | nrfx_timer_extended_compare(&m_sample_timer, 51 | NRF_TIMER_CC_CHANNEL0, 52 | nrfx_timer_us_to_ticks(&m_sample_timer, 500), 53 | NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, 54 | true); 55 | 56 | LOG_INF("Timer 1 initialized."); 57 | nrfx_timer_enable(&m_sample_timer); 58 | 59 | 60 | IRQ_CONNECT(TIMER1_IRQn, 0, 61 | nrfx_timer_1_irq_handler, NULL, 0); 62 | } 63 | 64 | static void spim_handler(nrfx_spim_evt_t const *p_event, void *p_context) 65 | { 66 | if (p_event->type == NRFX_SPIM_EVENT_DONE) { 67 | LOG_INF("SPI transfer finished"); 68 | } 69 | } 70 | 71 | static void spi_init(void) 72 | { 73 | nrfx_err_t err_code; 74 | 75 | spi_config.frequency = NRF_SPIM_FREQ_1M; 76 | 77 | IRQ_CONNECT(SPIM2_SPIS2_TWIM2_TWIS2_UARTE2_IRQn, 5, nrfx_isr, 78 | nrfx_spim_2_irq_handler, 0); 79 | 80 | err_code = nrfx_spim_init(&spi_instance, &spi_config, spim_handler, NULL); 81 | 82 | if (err_code != NRFX_SUCCESS) { 83 | LOG_ERR("nrfx_spim_init error: %08x", err_code); 84 | return; 85 | } 86 | 87 | err_code = nrfx_spim_xfer(&spi_instance, &transfer, 0); 88 | if (err_code != NRFX_SUCCESS) { 89 | LOG_ERR("SPI transfer error: %08x", err_code); 90 | return; 91 | } 92 | 93 | } 94 | 95 | static void dppi_init(void) 96 | { 97 | uint8_t dppi_ch_1; 98 | nrfx_err_t err = nrfx_dppi_channel_alloc(&dppi_ch_1); 99 | if (err != NRFX_SUCCESS) { 100 | LOG_ERR("Err %d", err); 101 | return; 102 | } 103 | 104 | err = nrfx_dppi_channel_enable(dppi_ch_1); 105 | if (err != NRFX_SUCCESS) { 106 | LOG_ERR("Err %d", err); 107 | return; 108 | } 109 | 110 | nrfx_gppi_channel_endpoints_setup(dppi_ch_1, 111 | nrf_timer_event_address_get(m_sample_timer.p_reg, 112 | NRF_TIMER_EVENT_COMPARE0), 113 | nrf_spim_task_address_get(NRF_SPIM2, 114 | NRF_SPIM_TASK_START)); 115 | 116 | 117 | /* Tie it all together */ 118 | nrf_timer_publish_set(m_sample_timer.p_reg, NRF_TIMER_EVENT_COMPARE0, dppi_ch_1); 119 | nrf_spim_subscribe_set(spi_instance.p_reg, NRF_SPIM_TASK_START, dppi_ch_1); 120 | } 121 | 122 | void main(void) 123 | { 124 | LOG_INF("Timer + DPPI + SPIM Application..."); 125 | timer_init(); 126 | spi_init(); 127 | dppi_init(); 128 | } 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /timer_gppi_gpiote/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.13.1) 4 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 5 | project(blinky) 6 | 7 | target_sources(app PRIVATE src/main.c) 8 | -------------------------------------------------------------------------------- /timer_gppi_gpiote/prj.conf: -------------------------------------------------------------------------------- 1 | CONFIG_ASSERT=y 2 | CONFIG_GPIO=n 3 | CONFIG_NRFX_GPIOTE=y 4 | CONFIG_NRFX_TIMER1=y 5 | CONFIG_LOG=y 6 | CONFIG_THREAD_NAME=y -------------------------------------------------------------------------------- /timer_gppi_gpiote/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | name: Blinky Sample 3 | tests: 4 | sample.basic.blinky: 5 | tags: LED gpio 6 | filter: dt_enabled_alias_with_parent_compat("led0", "gpio-leds") 7 | depends_on: gpio 8 | harness: led 9 | integration_platforms: 10 | - frdm_k64f 11 | -------------------------------------------------------------------------------- /timer_gppi_gpiote/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | //GPPI + PPI/DPPI includes based on DPPI presence on platform 11 | #include 12 | #if defined(DPPI_PRESENT) 13 | #include 14 | #else 15 | #include 16 | #endif 17 | 18 | #include 19 | LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); 20 | 21 | /* The devicetree node identifier for the "led0" alias. */ 22 | #define LED0_PIN DT_GPIO_PIN(DT_ALIAS(led0), gpios) 23 | 24 | static const nrfx_timer_t m_sample_timer = NRFX_TIMER_INSTANCE(1); 25 | 26 | void timer_handler(nrf_timer_event_t event_type, void* p_context) 27 | { 28 | //Nothing here due to DPPI 29 | } 30 | 31 | static void timer_init(void) 32 | { 33 | nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG; 34 | timer_config.bit_width = NRF_TIMER_BIT_WIDTH_32; 35 | nrfx_err_t err_code = nrfx_timer_init(&m_sample_timer, &timer_config, timer_handler); 36 | if (err_code != NRFX_SUCCESS) { 37 | LOG_ERR("nrfx_timer_init error: %08x", err_code); 38 | return; 39 | } 40 | nrfx_timer_extended_compare(&m_sample_timer, 41 | NRF_TIMER_CC_CHANNEL0, 42 | nrfx_timer_ms_to_ticks(&m_sample_timer, 500), 43 | NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, 44 | true); 45 | 46 | LOG_INF("Timer 1 initialized."); 47 | nrfx_timer_enable(&m_sample_timer); 48 | 49 | 50 | IRQ_CONNECT(TIMER1_IRQn, 0, 51 | nrfx_timer_1_irq_handler, NULL, 0); 52 | } 53 | 54 | static void gpiote_init(void) 55 | { 56 | nrfx_err_t err; 57 | uint8_t out_channel; 58 | 59 | /* Initialize GPIOTE (the interrupt priority passed as the parameter 60 | * here is ignored, see nrfx_glue.h). 61 | */ 62 | err = nrfx_gpiote_init(0); 63 | if (err != NRFX_SUCCESS) { 64 | LOG_ERR("nrfx_gpiote_init error: 0x%08X", err); 65 | return; 66 | } 67 | 68 | err = nrfx_gpiote_channel_alloc(&out_channel); 69 | if (err != NRFX_SUCCESS) { 70 | LOG_ERR("Failed to allocate out_channel, error: 0x%08X", err); 71 | return; 72 | } 73 | 74 | /* Initialize output pin. SET task will turn the LED on, 75 | * CLR will turn it off and OUT will toggle it. 76 | */ 77 | static const nrfx_gpiote_output_config_t output_config = { 78 | .drive = NRF_GPIO_PIN_S0S1, 79 | .input_connect = NRF_GPIO_PIN_INPUT_DISCONNECT, 80 | .pull = NRF_GPIO_PIN_NOPULL, 81 | }; 82 | const nrfx_gpiote_task_config_t task_config = { 83 | .task_ch = out_channel, 84 | .polarity = NRF_GPIOTE_POLARITY_TOGGLE, 85 | .init_val = 1, 86 | }; 87 | err = nrfx_gpiote_output_configure(LED0_PIN, 88 | &output_config, 89 | &task_config); 90 | if (err != NRFX_SUCCESS) { 91 | LOG_ERR("nrfx_gpiote_output_configure error: 0x%08X", err); 92 | return; 93 | } 94 | 95 | nrfx_gpiote_out_task_enable(LED0_PIN); 96 | 97 | LOG_INF("nrfx_gpiote initialized"); 98 | 99 | } 100 | 101 | 102 | static void gppi_init(void) 103 | { 104 | nrfx_err_t err; 105 | uint8_t ppi_channel; 106 | 107 | /* Allocate a (D)PPI channel. */ 108 | err = nrfx_gppi_channel_alloc(&ppi_channel); 109 | if (err != NRFX_SUCCESS) { 110 | LOG_ERR("nrfx_gppi_channel_alloc error: 0x%08X", err); 111 | return; 112 | } 113 | 114 | /* Configure a (D)PPI channel to toggle the LED0 pin on TIMER0 COMPARE[0] match. */ 115 | nrfx_gppi_channel_endpoints_setup(ppi_channel, 116 | nrf_timer_event_address_get(m_sample_timer.p_reg, NRF_TIMER_EVENT_COMPARE0), 117 | nrfx_gpiote_out_task_addr_get(LED0_PIN)); 118 | 119 | /* Enable the channel. */ 120 | nrfx_gppi_channels_enable(BIT(ppi_channel)); 121 | } 122 | 123 | 124 | void main(void) 125 | { 126 | #if defined(DPPI_PRESENT) 127 | LOG_INF("Starting Timer + DPPI + GPIOTE Application..."); 128 | #else 129 | LOG_INF("Starting Timer + PPI + GPIOTE Application..."); 130 | #endif 131 | 132 | timer_init(); 133 | gpiote_init(); 134 | gppi_init(); 135 | 136 | } 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /uart_wakeup_rx/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | cmake_minimum_required(VERSION 3.20.0) 4 | 5 | find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) 6 | project(hello_world) 7 | 8 | target_sources(app PRIVATE src/main.c) 9 | -------------------------------------------------------------------------------- /uart_wakeup_rx/boards/nrf52840dk_nrf52840.overlay: -------------------------------------------------------------------------------- 1 | &uart1 { 2 | status = "disabled"; 3 | }; 4 | -------------------------------------------------------------------------------- /uart_wakeup_rx/prj.conf: -------------------------------------------------------------------------------- 1 | # nothing here 2 | CONFIG_PM=y 3 | CONFIG_PM_DEVICE=y 4 | CONFIG_GPIO=y 5 | CONFIG_SERIAL=y -------------------------------------------------------------------------------- /uart_wakeup_rx/sample.yaml: -------------------------------------------------------------------------------- 1 | sample: 2 | description: Hello World sample, the simplest Zephyr 3 | application 4 | name: hello world 5 | common: 6 | tags: introduction 7 | integration_platforms: 8 | - native_posix 9 | harness: console 10 | harness_config: 11 | type: one_line 12 | regex: 13 | - "Hello World! (.*)" 14 | tests: 15 | sample.basic.helloworld: 16 | tags: introduction 17 | -------------------------------------------------------------------------------- /uart_wakeup_rx/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); 11 | static const struct gpio_dt_spec button1 = GPIO_DT_SPEC_GET(DT_ALIAS(sw1), gpios); 12 | 13 | const struct device *uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); 14 | 15 | // Referente the UART RX pin on nRF52840DK 16 | #define RX_DEVICE DT_NODELABEL(gpio0) 17 | #define RX_PIN 8 18 | const struct device *gpio_dev; 19 | 20 | 21 | static void uart0_set_enable(bool enable) 22 | { 23 | const struct device *uart_dev = DEVICE_DT_GET(DT_NODELABEL(uart0)); 24 | 25 | if (!device_is_ready(uart_dev)) { 26 | return; 27 | } 28 | 29 | gpio_pin_interrupt_configure(gpio_dev, RX_PIN, enable? GPIO_INT_DISABLE : GPIO_INT_EDGE_TO_ACTIVE); 30 | gpio_pin_set_dt(&led, enable ? 1 : 0); 31 | pm_device_action_run(uart_dev, enable ? PM_DEVICE_ACTION_RESUME : PM_DEVICE_ACTION_SUSPEND); 32 | } 33 | 34 | /* Button handler functions */ 35 | static void rx_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins) 36 | { 37 | uart0_set_enable(true); 38 | } 39 | static struct gpio_callback rx_cb; 40 | 41 | static void button1_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins) 42 | { 43 | uart0_set_enable(false); 44 | } 45 | static struct gpio_callback button1_cb; 46 | 47 | void main(void) 48 | { 49 | 50 | printk("Initializing...\n"); 51 | /* 52 | gpio_pin_configure_dt(&button0, GPIO_INPUT); 53 | gpio_pin_interrupt_configure_dt(&button0, GPIO_INT_EDGE_TO_ACTIVE); 54 | gpio_init_callback(&button0_cb, button0_handler, BIT(button0.pin)); 55 | gpio_add_callback(button0.port, &button0_cb); 56 | */ 57 | 58 | gpio_pin_configure_dt(&button1, GPIO_INPUT); 59 | gpio_pin_interrupt_configure_dt(&button1, GPIO_INT_EDGE_TO_ACTIVE); 60 | gpio_init_callback(&button1_cb, button1_handler, BIT(button1.pin)); 61 | gpio_add_callback(button1.port, &button1_cb); 62 | 63 | 64 | gpio_dev = DEVICE_DT_GET(RX_DEVICE); 65 | //gpio_pin_configure(gpio_dev, RX_PIN, GPIO_INPUT | GPIO_PULL_UP); 66 | gpio_pin_interrupt_configure(gpio_dev, RX_PIN, GPIO_INT_EDGE_TO_ACTIVE); 67 | gpio_init_callback(&rx_cb, rx_handler, BIT(RX_PIN)); 68 | gpio_add_callback(gpio_dev, &rx_cb); 69 | 70 | uart0_set_enable(true); 71 | 72 | if (!device_is_ready(led.port)) { 73 | return; 74 | } 75 | 76 | if (gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE) < 0) { 77 | return; 78 | } 79 | 80 | while (1) { 81 | printk("Printing...\n"); 82 | k_sleep(K_SECONDS(1)); 83 | } 84 | 85 | } --------------------------------------------------------------------------------