From e74e5699c3b1eae0620e9f8a05413a2f7d03a1a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20J=C3=B8lsgard?= Date: Thu, 29 Feb 2024 15:15:55 +0100 Subject: [PATCH] samples: dect: add simple sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add simple dect sample. Signed-off-by: Eivind Jølsgard --- .../dect/dect_phy/hello_dect/CMakeLists.txt | 14 + samples/dect/dect_phy/hello_dect/Kconfig | 52 +++ samples/dect/dect_phy/hello_dect/README.rst | 127 +++++++ samples/dect/dect_phy/hello_dect/prj.conf | 10 + samples/dect/dect_phy/hello_dect/sample.yaml | 9 + samples/dect/dect_phy/hello_dect/src/main.c | 321 ++++++++++++++++++ samples/dect/dect_phy/hello_dect/west.yml | 48 +++ west.yml | 5 +- 8 files changed, 585 insertions(+), 1 deletion(-) create mode 100644 samples/dect/dect_phy/hello_dect/CMakeLists.txt create mode 100644 samples/dect/dect_phy/hello_dect/Kconfig create mode 100644 samples/dect/dect_phy/hello_dect/README.rst create mode 100644 samples/dect/dect_phy/hello_dect/prj.conf create mode 100644 samples/dect/dect_phy/hello_dect/sample.yaml create mode 100644 samples/dect/dect_phy/hello_dect/src/main.c create mode 100644 samples/dect/dect_phy/hello_dect/west.yml diff --git a/samples/dect/dect_phy/hello_dect/CMakeLists.txt b/samples/dect/dect_phy/hello_dect/CMakeLists.txt new file mode 100644 index 000000000000..e7b554343b74 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(hello_dect) + +# NORDIC SDK APP START +target_sources(app PRIVATE src/main.c) +# NORDIC SDK APP END diff --git a/samples/dect/dect_phy/hello_dect/Kconfig b/samples/dect/dect_phy/hello_dect/Kconfig new file mode 100644 index 000000000000..b637a60b5bd7 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/Kconfig @@ -0,0 +1,52 @@ +# +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +config CARRIER + int "Carrier to use" + default 1677 #during development, remove default from sample so cutomer must address it?- + help + The availability of the channels and the exact regulation to use them varies in different countries. + See ETSI TS 103 636-2 5.4.2 for the calculation. + +config NETWORK_ID + int "Network ID" + range 1 4294967295 + default 91 + +config MCS + int "MCS" + default 1 + help + The MCS impacts how much data can be fit into subslots/slots. + +config TX_POWER + int "Transmission power" + range 0 11 + default 11 + help + TX power, 11 == 19 dBm, maximum of the HW(!) + +config TX_TRANSMISSIONS + int "TX transmissions" + range 0 4294967295 + default 30 + help + Transmissions before sample exits, use 0 to transmit forever. + +config RX_PERIOD_S + int "RX period" + default 5 + help + Receive window period. + Time is given in seconds. + +module = DECT_PHY_HELLO_TX +module-str = DECT NR+ PHY hello DECT +source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" + +menu "Zephyr Kernel" +source "Kconfig.zephyr" +endmenu diff --git a/samples/dect/dect_phy/hello_dect/README.rst b/samples/dect/dect_phy/hello_dect/README.rst new file mode 100644 index 000000000000..3e9cefb26ee6 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/README.rst @@ -0,0 +1,127 @@ +.. _nrf_modem_dect_phy_hello: + +nRF91x1: DECT NR+ PHY hello sample +################################## + +.. contents:: + :local: + :depth: 2 + +This sample demonstrates how to set up a simple DECT NR+ application with the DECT PHY modem firmware. + +.. important:: + + DECT NR+ operates on free but regulated radio channels. The regulation and availability of the channels varies in different countries. + It is the responsibility of the developer to operate the devices according to the local regulation, both at the development site and the device operation regions. + +Requirements +************ + +The sample needs at least two nRF91x1 Development Kits. + +See :ref:`nrf91x1_ug_intro` for more details. + +.. note:: + + The :ref:`nrf_modem_dect_phy_simple` require a special modem firmware to run on the nRF91x1 modem core. Please contact our sales department to know more. + + +.. include:: /includes/tfm.txt + +Overview +******** + +The sample shows a simple broadcast and reception of DECT NR+ messages between devices on a hard-coded channel. + +After initialization the devices will run a loop, transmitting a counter value before listening for incomming receptions for :kconfig:option:`CONFIG_RX_PERIOD_S`. +The loop is exited after a number of transmissions given by the :kconfig:option:`CONFIG_TX_TRANSMISSIONS` Kconfig option, or continue forever if the :kconfig:option:`CONFIG_TX_TRANSMISSIONS` Kconfig option is ``0``. + +Each device can be reset to run the sample again. + +Building and running +******************** + +.. |sample path| replace:: :file:`samples/modem_trace_flash` + +.. include:: /includes/build_and_run_ns.txt + +Testing +======= + +|test_sample| + +After programming the sample to your development kits, test it by performing the following steps: + +#. |connect_kit| +#. |connect_terminal| +#. Observe that the devices will transmit a counter value that is received by the other devices. +#. After a given number of transmissions, observe that the devices shut down and exit the sample. + +Sample output +============= + +The sample shows an output similar to the following: + +Device 1: + +.. code-block:: console + + *** Booting nRF Connect SDK v3.5.99-ncs1 *** + [00:00:00.378,784] app: Dect NR+ PHY sample started + [00:00:00.691,375] app: Dect NR+ PHY initialized, device ID: 12345 + [00:00:00.691,406] app: Transmitting 0 + [00:00:05.697,784] app: Transmitting 1 + [00:00:10.704,193] app: Transmitting 2 + [00:00:14.186,553] app: Received header from device ID 67890 + [00:00:14.186,889] app: Received data (RSSI: -54.5): Hello DECT! 0 + [00:00:15.710,571] app: Transmitting 3 + [00:00:19.192,932] app: Received header from device ID 67890 + [00:00:19.193,267] app: Received data (RSSI: -54.5): Hello DECT! 1 + [00:00:20.716,949] app: Transmitting 4 + ... + [00:02:24.352,661] app: Received header from device ID 67890 + [00:02:24.352,996] app: Received data (RSSI: -54.5): Hello DECT! 26 + [00:02:25.876,739] app: Transmitting 29 + [00:02:25.876,831] app: Reached maximum number of transmissions (30) + [00:02:25.876,831] app: Shutting down + [00:02:25.893,554] app: Bye! + +Device 2: + +.. code-block:: console + + *** Booting nRF Connect SDK v3.5.99-ncs1 *** + [00:00:00.407,287] app: Dect NR+ PHY sample started + [00:00:00.719,238] app: Dect NR+ PHY initialized, device ID: 67890 + [00:00:00.719,268] app: Transmitting 0 + [00:00:02.254,211] app: Received header from device ID 12345 + [00:00:02.254,547] app: Received data (RSSI: -54.5): Hello DECT! 3 + [00:00:05.725,646] app: Transmitting 1 + [00:00:07.260,620] app: Received header from device ID 12345 + [00:00:07.260,955] app: Received data (RSSI: -54.5): Hello DECT! 4 + ... + [00:02:10.885,284] app: Transmitting 26 + [00:02:12.420,318] app: Received header from device ID 12345 + [00:02:12.420,654] app: Received data (RSSI: -54.5): Hello DECT! 29 + [00:02:15.891,693] app: Transmitting 27 + [00:02:20.898,071] app: Transmitting 28 + [00:02:25.904,449] app: Transmitting 29 + [00:02:25.904,541] app: Reached maximum number of transmissions (30) + [00:02:25.904,571] app: Shutting down + [00:02:25.921,325] app: Bye! + +Dependencies +************ + +It uses the following `sdk-nrfxlib`_ libraries: + +* :ref:`nrfxlib:nrf_modem` + +It uses the following Zephyr libraries: + +* :ref:`zephyr:uart_api` + + +In addition, it uses the following secure firmware components: + +* :ref:`Trusted Firmware-M ` diff --git a/samples/dect/dect_phy/hello_dect/prj.conf b/samples/dect/dect_phy/hello_dect/prj.conf new file mode 100644 index 000000000000..15aa49536e0b --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/prj.conf @@ -0,0 +1,10 @@ +CONFIG_DK_LIBRARY=y +CONFIG_LOG=y + +CONFIG_MODEM_ANTENNA_AT_MAGPIO="" +CONFIG_MODEM_ANTENNA_AT_COEX0="" + +CONFIG_NRF_MODEM_LIB=y + +CONFIG_NRF_MODEM_LINK_BINARY_DECT_PHY=y +CONFIG_HWINFO=y diff --git a/samples/dect/dect_phy/hello_dect/sample.yaml b/samples/dect/dect_phy/hello_dect/sample.yaml new file mode 100644 index 000000000000..5c4742faec44 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/sample.yaml @@ -0,0 +1,9 @@ +sample: + name: Modem trace flash +tests: + sample.nrf9160.modem_trace_flash: + build_only: true + integration_platforms: + - nrf9160dk_nrf9160_ns + platform_allow: nrf9160dk_nrf9160_ns + tags: ci_build diff --git a/samples/dect/dect_phy/hello_dect/src/main.c b/samples/dect/dect_phy/hello_dect/src/main.c new file mode 100644 index 000000000000..223afd7003f4 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/src/main.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(app); + +#define DATA_LEN_MAX 32 + +static bool exit; +static uint16_t device_id; + +struct phy_ctrl_field_common +{ + uint32_t packet_length : 4; + uint32_t packet_length_type : 1; + uint32_t header_format : 3; + uint32_t short_network_id : 8; + uint32_t transmitter_id_hi : 8; + uint32_t transmitter_id_lo : 8; + uint32_t df_mcs : 3; + uint32_t reserved : 1; + uint32_t transmit_power : 4; + uint32_t pad : 24; +}; + +/* Semaphore to synchronize modem calls. */ +K_SEM_DEFINE(modem_sem, 0, 1); + +/* Callback after init operation. */ +static void init(const uint64_t *time, int16_t temp, enum nrf_modem_dect_phy_err err, + const struct nrf_modem_dect_phy_modem_cfg *cfg) +{ + if (err) { + LOG_ERR("Init failed, err %d", err); + exit = true; + return; + } + + k_sem_give(&modem_sem); +} + +/* Callback after deinit operation. */ +static void deinit(const uint64_t *time, enum nrf_modem_dect_phy_err err) +{ + if (err) { + LOG_ERR("Deinit failed, err %d", err); + return; + } + + k_sem_give(&modem_sem); +} + +/* Operation complete notification. */ +static void op_complete(const uint64_t *time, int16_t temperature, + enum nrf_modem_dect_phy_err err, uint32_t handle) +{ + LOG_DBG("operation_complete_cb Status %d Handle %d", err, handle); + k_sem_give(&modem_sem); +} + +/* Callback after receive stop operation. */ +static void rx_stop(const uint64_t *time, enum nrf_modem_dect_phy_err err, uint32_t handle) +{ + LOG_DBG("operation_stop_cb Status %d Handle %d", err, handle); + k_sem_give(&modem_sem); +} + +/* Physical Control Channel reception notification. */ +static void pcc( + const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pcc_status *status, + const union nrf_modem_dect_phy_hdr *hdr) +{ + struct phy_ctrl_field_common *header = (struct phy_ctrl_field_common *)hdr->type_1; + LOG_INF("Received header from device ID %d", + header->transmitter_id_hi << 8 | header->transmitter_id_lo); +} + +/* Physical Control Channel CRC error notification. */ +static void pcc_crc_err(const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pcc_crc_failure *crc_failure) +{ + LOG_DBG("PCC CRC error"); +} + +/* Physical Data Channel reception notification. */ +static void pdc( const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pdc_status *status, + const void *data, uint32_t len) +{ + LOG_INF("Received data (RSSI: %d.%d): %s", + (status->rssi_2 / 2), (status->rssi_2 & 0b1) * 5, (char *)data); +} + +/* Physical Data Channel CRC error notification. */ +static void pdc_crc_err( + const uint64_t *time, const struct nrf_modem_dect_phy_rx_pdc_crc_failure *crc_failure) +{ + LOG_DBG("PDC CRC error"); +} + +/* RSSI measurement result notification. */ +static void rssi(const uint64_t *time, const struct nrf_modem_dect_phy_rssi_meas *status) +{ + LOG_DBG("RSSI measurement for carrier %d", status->carrier); +} + +/* callback after link configuration operation. */ +static void link_config(const uint64_t *time, enum nrf_modem_dect_phy_err err) +{ + LOG_DBG("Link configuration callback"); +} + +/* Callback after time queuery operation. */ +static void time_get(const uint64_t *time, enum nrf_modem_dect_phy_err err) +{ + LOG_DBG("time_query_cb time %"PRIu64" Status %d", *time, err); +} + +/* Callback after capability get operation. */ +static void capability_get(const uint64_t *time, enum nrf_modem_dect_phy_err err, + const struct nrf_modem_dect_phy_capability *capability) +{ + LOG_DBG("capability_get time %"PRIu64" Status %d", *time, err); +} + +/* Dect PHY callbacks. */ +static struct nrf_modem_dect_phy_callbacks dect_phy_callbacks = { + .init = init, + .deinit = deinit, + .op_complete = op_complete, + .rx_stop = rx_stop, + .pcc = pcc, + .pcc_crc_err = pcc_crc_err, + .pdc = pdc, + .pdc_crc_err = pdc_crc_err, + .rssi = rssi, + .link_config = link_config, + .time_get = time_get, + .capability_get = capability_get, +}; + +/* Dect PHY init parameters. */ +static struct nrf_modem_dect_phy_init_params dect_phy_init_params = { + .harq_rx_expiry_time_us = 5000000, + .harq_rx_process_count = 4, +}; + +/* Send and receive operation, start immediately. */ +static int modem_tx(uint32_t handle, void *data, size_t data_len) +{ + int err; + + struct phy_ctrl_field_common header = { + .header_format = (uint8_t)0x0, + .packet_length_type = (uint8_t)0x0, + .packet_length = (uint8_t) 0x01, + .short_network_id = (uint8_t)(CONFIG_NETWORK_ID & 0xff), + .transmitter_id_hi = (uint8_t) (device_id >> 8), + .transmitter_id_lo = (uint8_t) (device_id & 0xff), + .transmit_power = CONFIG_TX_POWER, + .reserved = 0, + .df_mcs = CONFIG_MCS, + }; + + struct nrf_modem_dect_phy_tx_params tx_op_params = { + .start_time = 0, + .handle = handle, + .network_id = CONFIG_NETWORK_ID, + .phy_type = 0, + .lbt_rssi_threshold_max = 0, + .carrier = CONFIG_CARRIER, + .lbt_period = NRF_MODEM_DECT_LBT_PERIOD_MAX, + .phy_header = (union nrf_modem_dect_phy_hdr *)&header, + .data = data, + .data_size = data_len, + }; + + err = nrf_modem_dect_phy_tx(&tx_op_params); + if (err != 0) { + return err; + } + + return 0; +} + +/* Send and receive operation, start immediately. */ +static int modem_rx(uint32_t handle) +{ + int err; + + struct nrf_modem_dect_phy_rx_params rx_op_params = { + .start_time = 0, + .handle = handle, + .network_id = CONFIG_NETWORK_ID, + .mode = NRF_MODEM_DECT_PHY_RX_MODE_CONTINUOUS, + .rssi_interval = NRF_MODEM_DECT_PHY_RSSI_INTERVAL_OFF, + .link_id = NRF_MODEM_DECT_PHY_LINK_UNSPECIFIED, + .rssi_level = -60, + .carrier = CONFIG_CARRIER, + .duration = CONFIG_RX_PERIOD_S * MSEC_PER_SEC * + NRF_MODEM_DECT_MODEM_TIME_TICK_RATE_KHZ, + .filter.short_network_id = CONFIG_NETWORK_ID & 0xff, + .filter.is_short_network_id_used = 1, + /* listen for everything (broadcast mode used) */ + .filter.receiver_identity = 0, + }; + + err = nrf_modem_dect_phy_rx(&rx_op_params); + if (err!=0) { + return err; + } + + return 0; +} + +int main(void) +{ + int err; + uint32_t handle = 0; + + uint8_t tx_buf[DATA_LEN_MAX]; + size_t tx_len; + uint32_t tx_counter_value = 0; + + LOG_INF("Dect NR+ PHY sample started"); + + err = nrf_modem_lib_init(); + if (err) { + LOG_ERR("modem init failed, err %d", err); + return err; + } + + err = nrf_modem_dect_phy_callback_set(&dect_phy_callbacks); + if (err) { + LOG_ERR("nrf_modem_dect_phy_callback_set failed, err %d", err); + return err; + } + + err = nrf_modem_dect_phy_init(&dect_phy_init_params); + if (err) { + LOG_ERR("nrf_modem_dect_phy_init failed, err %d", err); + return err; + } + + k_sem_take(&modem_sem, K_FOREVER); + if (exit) { + return -EIO; + } + + hwinfo_get_device_id((void *)&device_id, sizeof(device_id)); + + LOG_INF("Dect NR+ PHY initialized, device ID: %d", device_id); + + while (1) { + /** Transmitting message */ + LOG_INF("Transmitting %d", tx_counter_value); + tx_len = sprintf(tx_buf, "Hello DECT! %d", tx_counter_value); + + err = modem_tx(handle, tx_buf, tx_len); + if (err) { + LOG_ERR("Modem TX failed, err %d", err); + return err; + } + + handle++; + tx_counter_value++; + + if ((tx_counter_value >= CONFIG_TX_TRANSMISSIONS) && CONFIG_TX_TRANSMISSIONS) { + LOG_INF("Reached maximum number of transmissions (%d)", + CONFIG_TX_TRANSMISSIONS); + break; + } else if (tx_counter_value == UINT32_MAX) { + tx_counter_value = 0; + } + + /* Wait for TX operation to complete. */ + k_sem_take(&modem_sem, K_FOREVER); + + /** Receiving messages for CONFIG_RX_PERIOD_S seconds. */ + err = modem_rx(handle); + if (err) { + LOG_ERR("Modem TX failed, err %d", err); + return err; + } + + handle++; + + /* Wait for RX operation to complete. */ + k_sem_take(&modem_sem, K_FOREVER); + } + + LOG_INF("Shutting down"); + + err = nrf_modem_dect_phy_deinit(); + if (err) { + LOG_ERR("nrf_modem_dect_phy_deinit() failed, err %d", err); + return err; + } + + k_sem_take(&modem_sem, K_FOREVER); + + err = nrf_modem_lib_shutdown(); + if (err) { + LOG_ERR("nrf_modem_lib_shutdown() failed, err %d", err); + return err; + } + + LOG_INF("Bye!"); + + return 0; +} diff --git a/samples/dect/dect_phy/hello_dect/west.yml b/samples/dect/dect_phy/hello_dect/west.yml new file mode 100644 index 000000000000..725725c119fe --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/west.yml @@ -0,0 +1,48 @@ +# The west manifest file for the Nordic Modem Library. +# +# The per-installation west configuration file specifies the location of this +# manifest file. The "path" option in the [manifest] section of .west/config +# defines the folder that contains west.yml. The path is relative to the folder +# that contains .west. See the west documentation for more information. + +manifest: + defaults: + remote: ncs + + remotes: + - name: ncs + url-base: https://github.com/nrfconnect + - name: nordicsemi + url-base: https://github.com/NordicSemiconductor + - name: nordicplayground + url-base: https://github.com/NordicPlayground + - name: eivindj-nordic + url-base: https://github.com/lemrey + + group-filter: + - -default + - -test + + # Use the `ncs` remote when updating the manifest to tag a release. + # Otherwise, if submitting a PR to libmodem which needs changes `sdk-nrf` or `nrfxlib`, + # submit a PR to the integration branches in `nrfxlib` and `sdk-nrf` (lemrey/libmodem) + # and point the manifest to those PR (pull/xxx/head). + # This is necessary for CI to run correctly on the PR to libmodem. + # Finally, when the PRs to the integration branches are merged, + # update the manifest in your libmodem PR to point to the integration + # branches instead, i.e. lemrey/libmodem. + + projects: + - name: libmodem + path: libmodem + remote: nordicplayground + revision: main + import: true + + - name: nrf-dect + path: nrf-dect + remote: nordicsemi + revision: pull/4/head + + self: + path: eivindj-nordic/dect-testapp diff --git a/west.yml b/west.yml index afa1bb3222e0..e2d137be8514 100644 --- a/west.yml +++ b/west.yml @@ -39,6 +39,8 @@ manifest: url-base: https://github.com/BabbleSim - name: bosch url-base: https://github.com/boschsensortec + - name: lemrey + url-base: https://github.com/lemrey # If not otherwise specified, the projects below should be obtained # from the ncs remote. @@ -142,7 +144,8 @@ manifest: - name: nrfxlib repo-path: sdk-nrfxlib path: nrfxlib - revision: v2.6.0 + remote: lemrey + revision: pull/44/head - name: trusted-firmware-m repo-path: sdk-trusted-firmware-m path: modules/tee/tf-m/trusted-firmware-m