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..5942a3f51ea4 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/Kconfig @@ -0,0 +1,42 @@ +# +# 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 MCS + int + default 1 + help + The MCS impacts how much data can be fit into subslots/slots. + This is now hardcoded assuming MCS 1. + +config TX_POWER + int "Transmission power" + range 0 11 + default 1 + help + TX power, 11 == 19 dBm, maximum of the HW(!) + +config TX_INTERVAL_SECONDS + int "Transmission interval in seconds" + default 5 + +config TX_TRANSMISSION_CYCLES_BEFORE_EXIT + int "Number of transmissions lost before receiver device times out" + default 3 + +module = DECT_PHY_HELLO +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..d3c398b7db7b --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/README.rst @@ -0,0 +1,95 @@ +.. _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 of DECT NR+ messages from one device to other devices on a hard-coded channel. + +During initialization the devices listens on the channel for broadcast transmissions. +Dependent on the detection of transmissions, the device takes one of the following roles: + +* If no transmission is detected, the device takes the role as a tranceiver. In this role, the device sends an incrementing counter value on the hard-coded channel. The period between each transmission is decided by the :kconfig:option:`CONFIG_TX_INTERVAL_SECONDS` Kconfig option. +* If a transmission is detected, the device takes the role as a receiver. In this role, the device listens for incomming messages. + By comparing the counter value with the previous one, the device detects if messages are lost in transmission. + +The device will exit the sample if the user presses button 1, ``exit`` is entered in the terminal or if an irrecoverable error occurs. +A device in the receiving role will also exit if no message is received within a given number of transmission cycles, see :kconfig:option:`CONFIG_TX_TRANSMISSION_CYCLES_BEFORE_EXIT. + +Upon exit, devices in the receiving role will print a simple statistics. +Each device can be reset to run the sample again. + +TX Mode: led 1 on, led 2 blinks +RX mode: led 1 off, led 2 blinks + +User interface +*************** + +Button 1: + Exits the sample. + + +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 device will start listening for incomming data. If data is received, the device will take the receiver role, if not the device will take the transmitter role. +#. Observe that the transmitter device will transmit a counter value that is received by the other devices. +#. Press button 1 on the transmitter device. Observe that the device stops transmitting, and the other devices stop receiving. +#. After some time, observe that the receiver devices prints the simple statistics and exit the sample. + + +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..1bc35301c91d --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/prj.conf @@ -0,0 +1,9 @@ +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 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..265b37de7c9a --- /dev/null +++ b/samples/dect/dect_phy/hello_dect/src/main.c @@ -0,0 +1,534 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(app); + +/* Note that the MCS impacts how much data can be fit into subslots/slots + * this is now hardcoded assuming MCS 1. + */ +#define CONFIG_MCS 1 +/* This depends on the MCS above */ +#define DATA_LEN_MAX 4 + +BUILD_ASSERT(CONFIG_CARRIER != 0, "Please set carrier in project configuration"); + +#define RX_TIMEOUT_SECONDS (CONFIG_TX_TRANSMISSION_CYCLES_BEFORE_EXIT * CONFIG_TX_INTERVAL_SECONDS) + +static enum device_role { UNSPECIFIED, RECEIVER, TRANSMITTER } role = UNSPECIFIED; +static bool exit; + +/* Handle values for API calls. Keep TX and RX values separated TODO: WHY?. */ +#define TX_HANDLE_MIN 1 +#define TX_HANDLE_MAX 0x7fff +#define RX_HANDLE_MIN 0x8000 +#define RX_HANDLE_MAX 0xffff + +static uint32_t handle = 1; + +static uint32_t rx_counter_previous; +static uint32_t num_missing_errors; +static uint32_t num_crc_errors; +static uint32_t num_msg_received; +static uint32_t tx_counter_value; + +static uint8_t tx_buf[DATA_LEN_MAX]; + +K_SEM_DEFINE(modem_sem, 0, 1); +K_SEM_DEFINE(rx_tx_sem, 0, 1); + +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; +}; + +union nrf_modem_dect_phy_hdr phyHeader; + +static void rx_tx_timer_callback(struct k_timer *dummy); + +K_TIMER_DEFINE(rx_tx_timer, rx_tx_timer_callback, NULL); + +/* Timer is called if: + * - The device is in receiver mode and nothing is received within RX_TIMEOUT_SECONDS. + * - The device is in transmitter mode to schadule a transmission. + * Transmission interval is decided by CONFIG_TX_INTERVAL_SECONDS. + * - The device is initializing (mode unspecified), and no transmission is received within the + * initialization timeout (RX_TIMEOUT_SECONDS). + */ +static void rx_tx_timer_callback(struct k_timer *dummy) +{ + switch (role) { + case RECEIVER: + printk("Receive timeout\n"); + exit = true; + break; + case TRANSMITTER: + break; + case UNSPECIFIED: + /* Timer will be restarted when device enters receiver or transmitter role. */ + k_timer_stop(&rx_tx_timer); + /* No transmission detected, will take transmitter role. */ + LOG_INF("Assigning role transmitter"); + role = TRANSMITTER; + default: + break; + } + + k_sem_give(&rx_tx_sem); +} + +static void button_handler(uint32_t button_state, uint32_t has_changed) +{ + exit = true; + k_sem_give(&rx_tx_sem); +} + +/* ETSI TS 103 636-2 spec 8.3.3 RSSI is reported every 0.5dbm */ +int32_t calcRSSI(int16_t recrssi){ + return (int32_t)(-20 + ((recrssi + 1) * 0.5)); +} + +/* Callback after init operation. */ +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. */ +void deinit(const uint64_t *time, enum nrf_modem_dect_phy_err err) +{ + if (err) { + LOG_ERR("Deinit failed, err %d, exit", err); + exit = true; + return; + } + + k_sem_give(&modem_sem); +} + +/* Operation complete notification. */ +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. */ +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. */ +void pcc( + const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pcc_status *status, + const union nrf_modem_dect_phy_hdr *hdr) +{ + LOG_DBG("pcc_cb header_status: %d rssi_2: %d", status->header_status, status->rssi_2); +} + +/* Physical Control Channel CRC error notification. */ +void pcc_crc_err(const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pcc_crc_failure *crc_failure) +{ + num_crc_errors++; + int16_t resp = calcRSSI(crc_failure->rssi_2); + LOG_ERR("PCC CRC error, rssi_2, %d, crc error count: %d", resp, num_crc_errors); +} + +/* Physical Data Channel reception notification. */ +void pdc( const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pdc_status *status, + const void *data, uint32_t len) +{ + int rx_counter; + int32_t rx_rssi; + uint8_t *rx_data; + + k_timer_start(&rx_tx_timer, + K_SECONDS(RX_TIMEOUT_SECONDS), + K_SECONDS(RX_TIMEOUT_SECONDS)); + + /* Unpack data */ + rx_data = (uint8_t *)data; + rx_counter = (rx_data[0]<<24) + (rx_data[1]<<16) + (rx_data[2]<<8) + (rx_data[3]); + + num_msg_received++; + + if (rx_counter % 2 == 0) { + dk_set_led_on(DK_LED2); + } else { + dk_set_led_off(DK_LED2); + } + + if (rx_counter_previous > rx_counter) { + /* Counter is reset as it reached the maximum. */ + num_missing_errors = num_missing_errors + rx_counter; + } else if (rx_counter_previous > 0 && rx_counter != rx_counter_previous + 1){ + num_missing_errors = num_missing_errors + (rx_counter - rx_counter_previous) - 1; + } + + rx_counter_previous = rx_counter; + + rx_rssi = calcRSSI(status->rssi_2); + LOG_INF("Received data, counter: %d, rssi_2: %d, missed/crc errors: %d", + rx_counter, rx_rssi, num_missing_errors); + + if (role == UNSPECIFIED) { + /* Transmission detected, will take receiver role. */ + role = RECEIVER; + } + + k_sem_give(&rx_tx_sem); +} + +/* Physical Data Channel CRC error notification. */ +void pdc_crc_err( + const uint64_t *time, const struct nrf_modem_dect_phy_rx_pdc_crc_failure *crc_failure) +{ + num_crc_errors++; + int16_t resp=calcRSSI(crc_failure->rssi_2); + LOG_ERR("PDC CRC error, rssi_2: %d, CRC error count: %d", resp, num_crc_errors); +} + +/* RSSI measurement result notification. */ +void rssi(const uint64_t *time, const struct nrf_modem_dect_phy_rssi_meas *status) +{ + LOG_DBG("RSSI measurement for carrier %d", status->carrier); + k_sem_give(&modem_sem); +} + +/* callback after link configuration operation. */ +void link_config(const uint64_t *time, enum nrf_modem_dect_phy_err err) +{ + return; +} + +/* Callback after time queuery operation. */ +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. */ +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. */ +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. */ +struct nrf_modem_dect_phy_init_params dect_phy_init_params = { + .harq_rx_expiry_time_us = 5000000, + .harq_rx_process_count = 4, +}; + +/* Receive operation, listen for listen_time_ms duration */ +int modem_rx(uint32_t rxMode, int listen_time_ms, uint32_t handle) +{ + int err; + struct nrf_modem_dect_phy_rx_params rxOpsParams = { + .start_time = 0, + .handle = handle, + .network_id=0, + .mode = rxMode, + .rssi_interval = NRF_MODEM_DECT_PHY_RSSI_INTERVAL_OFF, + .link_id = NRF_MODEM_DECT_PHY_LINK_UNSPECIFIED, + .rssi_level = -60, + .carrier = CONFIG_CARRIER, + .duration = listen_time_ms * NRF_MODEM_DECT_MODEM_TIME_TICK_RATE_KHZ, + .filter.short_network_id = (uint8_t)(0x0a), + .filter.is_short_network_id_used = 1, + /* listen for everything (broadcast mode used) */ + .filter.receiver_identity = 0, + }; + + err = k_sem_take(&modem_sem, K_SECONDS(RX_TIMEOUT_SECONDS)); + if (err) { + LOG_ERR("Failed to take modem sem, err %d", err); + return err; + } + + err = nrf_modem_dect_phy_rx(&rxOpsParams); + if (err) { + LOG_ERR("Receive failure, err %d", err); + return err; + } + + return 0; +} + +/* Send operation, start immediately. */ +int modem_tx(uint32_t handle, void *data, size_t data_len) +{ + int err; + struct nrf_modem_dect_phy_tx_params txOpsParams = { 0 }; + + 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)(0x0a & 0xff), + + .transmitter_id_hi = (uint8_t) (0x0101 >> 8), + .transmitter_id_lo = (uint8_t) (0x0101 & 0xff), + .transmit_power = CONFIG_TX_POWER, + .reserved = 0, + .df_mcs = CONFIG_MCS + }; + + memcpy(&phyHeader.type_1, &header, 5); + +/* + phyHeader.hdr_type_1.header_format = (uint8_t)0x0; //broadcast + phyHeader.hdr_type_1.packet_length_type = (uint8_t)0x0; + phyHeader.hdr_type_1.packet_length = (uint8_t) 0x01; + phyHeader.hdr_type_1.short_network_id = (uint8_t)(0x0a & 0xff); + + phyHeader.hdr_type_1.transmitter_id_hi = (uint8_t) (0x0101 >> 8); + phyHeader.hdr_type_1.transmitter_id_lo = (uint8_t) (0x0101 & 0xff); + phyHeader.hdr_type_1.transmit_power = CONFIG_TX_POWER; + phyHeader.hdr_type_1.reserved = 0; + phyHeader.hdr_type_1.df_mcs = CONFIG_MCS; +*/ + txOpsParams.start_time = 0; + txOpsParams.handle = handle; + txOpsParams.network_id = 0x0a; + txOpsParams.phy_type = 0; + txOpsParams.lbt_rssi_threshold_max = 0; + txOpsParams.carrier = CONFIG_CARRIER; + txOpsParams.lbt_period = NRF_MODEM_DECT_LBT_PERIOD_MAX; + txOpsParams.phy_header = &phyHeader; + txOpsParams.data = data; + txOpsParams.data_size = data_len; + + k_sem_take(&modem_sem, K_FOREVER); + + err = nrf_modem_dect_phy_tx(&txOpsParams); + if (err!=0) { + return err; + } + + return 0; +} + +/* Transmit counter value on the air. */ +static int transmit_counter(uint32_t handle, uint32_t counter) +{ + int err; + + if(counter % 2==0) { + dk_set_led_on(DK_LED2); + } + else { + dk_set_led_off(DK_LED2); + } + + /* Format TX buffer */ + for (int i = 0; i < DATA_LEN_MAX; i++) { + tx_buf[(DATA_LEN_MAX - 1) - i] = (counter >> (i * 8)) & 0xff; + } + + err = modem_tx(handle, tx_buf, sizeof(tx_buf)); + if (err) { + LOG_ERR("Modem TX failed, err %d", err); + return err; + } + + return 0; +} + + +static int shell_exit(const struct shell *shell, size_t argc, char **argv) +{ + ARG_UNUSED(argc); + ARG_UNUSED(argv); + + LOG_INF("Exit request received"); + exit = true; + k_sem_give(&rx_tx_sem); + + return 0; +} + +SHELL_CMD_REGISTER(exit, NULL, "Exit sample", shell_exit); + + +int main(void) +{ + int err; + + LOG_INF("Dect NR+ PHY sample started"); + + err = dk_buttons_init(button_handler); + if (err) { + LOG_ERR("dk_buttons_init failed, err %d", err); + } + + err = dk_leds_init(); + if (err) { + LOG_ERR("dk_leds_init failed, err %d", err); + } + + 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; + } + + LOG_INF("Dect NR+ PHY initialized %d", err); + + /* Wait for initial listen to decide what role to take. */ + LOG_INF("Listening for transmissions on channel %d for %d secs", + CONFIG_CARRIER, RX_TIMEOUT_SECONDS); + err = modem_rx(NRF_MODEM_DECT_PHY_RX_MODE_SINGLE_SHOT, + RX_TIMEOUT_SECONDS * MSEC_PER_SEC, 0); + if (err) { + LOG_ERR("Modem RX failed during initialization, err %d", err); + return err; + } + + k_timer_start(&rx_tx_timer, K_SECONDS(RX_TIMEOUT_SECONDS), K_SECONDS(RX_TIMEOUT_SECONDS)); + + k_sem_take(&rx_tx_sem, K_FOREVER); + k_sem_give(&rx_tx_sem); + + LOG_INF("Press button 1 or enter 'exit' to exit the sample"); + + if (role == TRANSMITTER) { + LOG_INF("Taking transmitter role"); + dk_set_led_on(DK_LED1); + + k_timer_start(&rx_tx_timer, K_NO_WAIT, K_SECONDS(CONFIG_TX_INTERVAL_SECONDS)); + + while (1) { + handle++; + + if(handle == UINT32_MAX) { + handle = TX_HANDLE_MIN; + } + + k_sem_take(&rx_tx_sem, K_FOREVER); + if (exit) { + break; + } + + err = transmit_counter(handle, tx_counter_value); + if (err) { + LOG_ERR("transmit failed, err %d", err); + continue; + } + + LOG_INF("Data sent, counter %d",tx_counter_value); + + tx_counter_value++; + + if (tx_counter_value == UINT32_MAX) { + tx_counter_value = 0; + LOG_WRN("TX integer value looped"); + } + } + + k_timer_stop(&rx_tx_timer); + + LOG_INF("Exit on user input"); + LOG_INF("*********************************************"); + LOG_INF("Sent messages %d", tx_counter_value - 1); + LOG_INF("**************** exit *************************"); + } else if (role == RECEIVER) { + LOG_INF("Taking receiver role"); + dk_set_led_off(DK_LED1); + + k_timer_start(&rx_tx_timer, + K_SECONDS(RX_TIMEOUT_SECONDS), + K_SECONDS(RX_TIMEOUT_SECONDS)); + + while (1) { + handle++; + + if (handle == RX_HANDLE_MAX) { + handle= RX_HANDLE_MIN; + } + + k_sem_take(&rx_tx_sem, K_FOREVER); + if (exit) { + break; + } + + err = modem_rx(NRF_MODEM_DECT_PHY_RX_MODE_SINGLE_SHOT, + RX_TIMEOUT_SECONDS * MSEC_PER_SEC, handle); + if (err) { + LOG_ERR("Modem RX failed, err %d", err); + } + } + + k_timer_stop(&rx_tx_timer); + + LOG_INF("Exit on timeout or user input"); + LOG_INF("*********************************************"); + LOG_INF("Received messages %d", num_msg_received); + /* CRC error causes a missed message, so missing errors includes also CRC */ + LOG_INF("Missed messages %d", (num_missing_errors - num_crc_errors)); + LOG_INF("CRC errors %d", num_crc_errors); + LOG_INF("**************** exit *************************"); + } + + 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/samples/dect/dect_phy/hello_dect_rx/CMakeLists.txt b/samples/dect/dect_phy/hello_dect_rx/CMakeLists.txt new file mode 100644 index 000000000000..e7b554343b74 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rx/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_rx/Kconfig b/samples/dect/dect_phy/hello_dect_rx/Kconfig new file mode 100644 index 000000000000..430208ceba88 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rx/Kconfig @@ -0,0 +1,32 @@ +# +# 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 RX_TIMEOUT_S + int "RX timeout" + default 30 + help + Time to wait before sample exits after last successful reception. + Time is given in seconds. + +module = DECT_PHY_HELLO_RX +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_rx/README.rst b/samples/dect/dect_phy/hello_dect_rx/README.rst new file mode 100644 index 000000000000..d3c398b7db7b --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rx/README.rst @@ -0,0 +1,95 @@ +.. _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 of DECT NR+ messages from one device to other devices on a hard-coded channel. + +During initialization the devices listens on the channel for broadcast transmissions. +Dependent on the detection of transmissions, the device takes one of the following roles: + +* If no transmission is detected, the device takes the role as a tranceiver. In this role, the device sends an incrementing counter value on the hard-coded channel. The period between each transmission is decided by the :kconfig:option:`CONFIG_TX_INTERVAL_SECONDS` Kconfig option. +* If a transmission is detected, the device takes the role as a receiver. In this role, the device listens for incomming messages. + By comparing the counter value with the previous one, the device detects if messages are lost in transmission. + +The device will exit the sample if the user presses button 1, ``exit`` is entered in the terminal or if an irrecoverable error occurs. +A device in the receiving role will also exit if no message is received within a given number of transmission cycles, see :kconfig:option:`CONFIG_TX_TRANSMISSION_CYCLES_BEFORE_EXIT. + +Upon exit, devices in the receiving role will print a simple statistics. +Each device can be reset to run the sample again. + +TX Mode: led 1 on, led 2 blinks +RX mode: led 1 off, led 2 blinks + +User interface +*************** + +Button 1: + Exits the sample. + + +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 device will start listening for incomming data. If data is received, the device will take the receiver role, if not the device will take the transmitter role. +#. Observe that the transmitter device will transmit a counter value that is received by the other devices. +#. Press button 1 on the transmitter device. Observe that the device stops transmitting, and the other devices stop receiving. +#. After some time, observe that the receiver devices prints the simple statistics and exit the sample. + + +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_rx/prj.conf b/samples/dect/dect_phy/hello_dect_rx/prj.conf new file mode 100644 index 000000000000..8ca959f05cf8 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rx/prj.conf @@ -0,0 +1,8 @@ +CONFIG_LOG=y +CONFIG_DECT_PHY_HELLO_RX_LOG_LEVEL_INF=y + +CONFIG_MODEM_ANTENNA_AT_MAGPIO="" +CONFIG_MODEM_ANTENNA_AT_COEX0="" + +CONFIG_NRF_MODEM_LIB=y +CONFIG_NRF_MODEM_LINK_BINARY_DECT_PHY=y diff --git a/samples/dect/dect_phy/hello_dect_rx/sample.yaml b/samples/dect/dect_phy/hello_dect_rx/sample.yaml new file mode 100644 index 000000000000..5c4742faec44 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rx/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_rx/src/main.c b/samples/dect/dect_phy/hello_dect_rx/src/main.c new file mode 100644 index 000000000000..5a515626be46 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rx/src/main.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(app_rx, CONFIG_DECT_PHY_HELLO_RX_LOG_LEVEL); + +BUILD_ASSERT(CONFIG_CARRIER != 0, "Please set carrier in project configuration"); + +/* Handle values for API calls */ +#define RX_HANDLE_MIN 0x7fff +#define RX_HANDLE_MAX 0xffff + +static uint32_t handle = 1; + +static bool exit; + +K_SEM_DEFINE(modem_sem, 0, 1); +K_SEM_DEFINE(rx_sem, 0, 1); + +/* ETSI TS 103 636-2 spec 8.3.3 RSSI is reported every 0.5dbm */ +int32_t calcRSSI(int16_t recrssi){ + return (int32_t)(-20 + ((recrssi + 1) * 0.5)); +} + +/* Callback after init operation. */ +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. */ +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. */ +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. */ +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. */ +void pcc( + const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pcc_status *status, + const union nrf_modem_dect_phy_hdr *hdr) +{ + LOG_DBG("pcc_cb header_status: %d rssi_2: %d", status->header_status, status->rssi_2); + +} + +/* Physical Control Channel CRC error notification. */ +void pcc_crc_err(const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pcc_crc_failure *crc_failure) +{ + int16_t resp = calcRSSI(crc_failure->rssi_2); + LOG_ERR("PCC CRC error, rssi_2, %d", resp); +} + +/* Physical Data Channel reception notification. */ +void pdc( const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pdc_status *status, + const void *data, uint32_t len) +{ + int32_t rx_rssi; + + rx_rssi = calcRSSI(status->rssi_2); + + LOG_INF("Received data (RSSI: %d): %s", rx_rssi, (char *)data); + + k_sem_give(&rx_sem); +} + +/* Physical Data Channel CRC error notification. */ +void pdc_crc_err( + const uint64_t *time, const struct nrf_modem_dect_phy_rx_pdc_crc_failure *crc_failure) +{ + int16_t resp=calcRSSI(crc_failure->rssi_2); + LOG_ERR("PDC CRC error, rssi_2: %d", resp); +} + +/* RSSI measurement result notification. */ +void rssi(const uint64_t *time, const struct nrf_modem_dect_phy_rssi_meas *status) +{ + return; +} + +/* callback after link configuration operation. */ +void link_config(const uint64_t *time, enum nrf_modem_dect_phy_err err) +{ + return; +} + +/* Callback after time queuery operation. */ +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. */ +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. */ +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. */ +struct nrf_modem_dect_phy_init_params dect_phy_init_params = { + .harq_rx_expiry_time_us = 5000000, + .harq_rx_process_count = 4, +}; + +/* Receive operation, listen for listen_time_ms duration */ +int modem_rx(uint32_t rxMode, int listen_time_ms, uint32_t handle) +{ + int err; + struct nrf_modem_dect_phy_rx_params rxOpsParams = { + .start_time = 0, + .handle = handle, + .network_id = CONFIG_NETWORK_ID, + .mode = rxMode, + .rssi_interval = NRF_MODEM_DECT_PHY_RSSI_INTERVAL_OFF, + .link_id = NRF_MODEM_DECT_PHY_LINK_UNSPECIFIED, + .rssi_level = -60, + .carrier = CONFIG_CARRIER, + .duration = listen_time_ms * 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 = k_sem_take(&modem_sem, K_SECONDS(CONFIG_RX_TIMEOUT_S)); + if (err) { + LOG_ERR("Failed to take modem sem, err %d", err); + return err; + } + + err = nrf_modem_dect_phy_rx(&rxOpsParams); + if (err) { + LOG_ERR("Receive failure, err %d", err); + return err; + } + + return 0; +} + +int main(void) +{ + int err; + + 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); + k_sem_give(&modem_sem); + if (exit) { + return -EIO; + } + + LOG_INF("Dect NR+ PHY initialized %d", err); + LOG_INF("Starting to receive"); + + while (1) { + handle++; + if (handle == RX_HANDLE_MAX) { + handle= RX_HANDLE_MIN; + } + + err = modem_rx(NRF_MODEM_DECT_PHY_RX_MODE_SINGLE_SHOT, + CONFIG_RX_TIMEOUT_S * MSEC_PER_SEC, handle); + if (err) { + LOG_ERR("Modem RX failed, err %d", err); + } + + err = k_sem_take(&rx_sem, K_SECONDS(CONFIG_RX_TIMEOUT_S)); + if (err) { + LOG_INF("Receive timeout"); + break; + } + } + + 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; + } + + 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_rx/west.yml b/samples/dect/dect_phy/hello_dect_rx/west.yml new file mode 100644 index 000000000000..725725c119fe --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rx/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/samples/dect/dect_phy/hello_dect_rxtx/CMakeLists.txt b/samples/dect/dect_phy/hello_dect_rxtx/CMakeLists.txt new file mode 100644 index 000000000000..e7b554343b74 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rxtx/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_rxtx/Kconfig b/samples/dect/dect_phy/hello_dect_rxtx/Kconfig new file mode 100644 index 000000000000..580d09b0d06a --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rxtx/Kconfig @@ -0,0 +1,56 @@ +# +# 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_INTERVAL_SECONDS + int "Transmission interval in seconds" + default 5 + +config TX_TRANSMISSIONS + int "TX transmissions" + range 0 4294967295 + default 0 + help + Transmissions before sample exits, use 0 to transmit forever. + +config RX_TIMEOUT_S + int "RX timeout" + default 60 + help + Time to wait before sample exits after last successful reception. + 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_rxtx/README.rst b/samples/dect/dect_phy/hello_dect_rxtx/README.rst new file mode 100644 index 000000000000..d3c398b7db7b --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rxtx/README.rst @@ -0,0 +1,95 @@ +.. _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 of DECT NR+ messages from one device to other devices on a hard-coded channel. + +During initialization the devices listens on the channel for broadcast transmissions. +Dependent on the detection of transmissions, the device takes one of the following roles: + +* If no transmission is detected, the device takes the role as a tranceiver. In this role, the device sends an incrementing counter value on the hard-coded channel. The period between each transmission is decided by the :kconfig:option:`CONFIG_TX_INTERVAL_SECONDS` Kconfig option. +* If a transmission is detected, the device takes the role as a receiver. In this role, the device listens for incomming messages. + By comparing the counter value with the previous one, the device detects if messages are lost in transmission. + +The device will exit the sample if the user presses button 1, ``exit`` is entered in the terminal or if an irrecoverable error occurs. +A device in the receiving role will also exit if no message is received within a given number of transmission cycles, see :kconfig:option:`CONFIG_TX_TRANSMISSION_CYCLES_BEFORE_EXIT. + +Upon exit, devices in the receiving role will print a simple statistics. +Each device can be reset to run the sample again. + +TX Mode: led 1 on, led 2 blinks +RX mode: led 1 off, led 2 blinks + +User interface +*************** + +Button 1: + Exits the sample. + + +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 device will start listening for incomming data. If data is received, the device will take the receiver role, if not the device will take the transmitter role. +#. Observe that the transmitter device will transmit a counter value that is received by the other devices. +#. Press button 1 on the transmitter device. Observe that the device stops transmitting, and the other devices stop receiving. +#. After some time, observe that the receiver devices prints the simple statistics and exit the sample. + + +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_rxtx/prj.conf b/samples/dect/dect_phy/hello_dect_rxtx/prj.conf new file mode 100644 index 000000000000..15aa49536e0b --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rxtx/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_rxtx/sample.yaml b/samples/dect/dect_phy/hello_dect_rxtx/sample.yaml new file mode 100644 index 000000000000..5c4742faec44 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rxtx/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_rxtx/src/main.c b/samples/dect/dect_phy/hello_dect_rxtx/src/main.c new file mode 100644 index 000000000000..651f46d1089b --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rxtx/src/main.c @@ -0,0 +1,360 @@ +/* + * 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 16 + +#define CONFIG_TX_INTERVAL_SECONDS 5 + +static bool exit; +static uint16_t device_id; + +K_SEM_DEFINE(modem_sem, 0, 1); +K_SEM_DEFINE(tx_sem, 0, 1); +K_SEM_DEFINE(rx_sem, 0, 1); + +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; +}; + +static void tx_timer_callback(struct k_timer *dummy) +{ + k_sem_give(&tx_sem); +} + +K_TIMER_DEFINE(tx_timer, tx_timer_callback, NULL); + +/* ETSI TS 103 636-2 spec 8.3.3 RSSI is reported every 0.5dbm */ +int32_t calcRSSI(int16_t recrssi){ + return (int32_t)(-20 + ((recrssi + 1) * 0.5)); +} + +/* Callback after init operation. */ +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. */ +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. */ +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. */ +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. */ +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. */ +void pcc_crc_err(const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pcc_crc_failure *crc_failure) +{ + return; +} + +/* Physical Data Channel reception notification. */ +void pdc( const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pdc_status *status, + const void *data, uint32_t len) +{ + int32_t rx_rssi; + + rx_rssi = calcRSSI(status->rssi_2); + + LOG_INF("Received data (RSSI: %d): %s", rx_rssi, (char *)data); + + k_sem_give(&rx_sem); +} + +/* Physical Data Channel CRC error notification. */ +void pdc_crc_err( + const uint64_t *time, const struct nrf_modem_dect_phy_rx_pdc_crc_failure *crc_failure) +{ + return; +} + +/* RSSI measurement result notification. */ +void rssi(const uint64_t *time, const struct nrf_modem_dect_phy_rssi_meas *status) +{ + LOG_DBG("RSSI measurement for carrier %d", status->carrier); + k_sem_give(&modem_sem); +} + +/* callback after link configuration operation. */ +void link_config(const uint64_t *time, enum nrf_modem_dect_phy_err err) +{ + return; +} + +/* Callback after time queuery operation. */ +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. */ +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. */ +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. */ +struct nrf_modem_dect_phy_init_params dect_phy_init_params = { + .harq_rx_expiry_time_us = 5000000, + .harq_rx_process_count = 4, +}; + +/* Send operation, start immediately. */ +int modem_tx(uint32_t handle, void *data, size_t data_len) +{ + int err; + union nrf_modem_dect_phy_hdr phyHeader; + struct nrf_modem_dect_phy_tx_params txOpsParams = { 0 }; + + + 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, + }; + + memcpy(&phyHeader.type_1, &header, 5); + + txOpsParams.start_time = 0; + txOpsParams.handle = handle; + txOpsParams.network_id = CONFIG_NETWORK_ID; + txOpsParams.phy_type = 0; + txOpsParams.lbt_rssi_threshold_max = 0; + txOpsParams.carrier = CONFIG_CARRIER; + txOpsParams.lbt_period = NRF_MODEM_DECT_LBT_PERIOD_MAX; + txOpsParams.phy_header = &phyHeader; + txOpsParams.data = data; + txOpsParams.data_size = data_len; + + k_sem_take(&modem_sem, K_FOREVER); + + err = nrf_modem_dect_phy_tx(&txOpsParams); + if (err!=0) { + return err; + } + + return 0; +} + +/* Receive operation, listen for listen_time_ms duration */ +int modem_rx(uint32_t rxMode, int listen_time_ms, uint32_t handle) +{ + int err; + struct nrf_modem_dect_phy_rx_params rxOpsParams = { + .start_time = 0, + .handle = handle, + .network_id = CONFIG_NETWORK_ID, + .mode = rxMode, + .rssi_interval = NRF_MODEM_DECT_PHY_RSSI_INTERVAL_OFF, + .link_id = NRF_MODEM_DECT_PHY_LINK_UNSPECIFIED, + .rssi_level = -60, + .carrier = CONFIG_CARRIER, + .duration = listen_time_ms * 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 = k_sem_take(&modem_sem, K_SECONDS(CONFIG_RX_TIMEOUT_S)); + if (err) { + LOG_ERR("Failed to take modem sem, err %d", err); + return err; + } + + err = nrf_modem_dect_phy_rx(&rxOpsParams); + if (err) { + LOG_ERR("Receive failure, err %d", err); + 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); + k_sem_give(&modem_sem); + 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); + + + k_timer_start(&tx_timer, K_NO_WAIT, K_SECONDS(CONFIG_TX_INTERVAL_SECONDS)); + + while (1) { + /** Transmitting message */ + LOG_INF("Transmitting message %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; + } + + tx_counter_value++; + handle++; + + 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; + } + + err = modem_rx(NRF_MODEM_DECT_PHY_RX_MODE_SINGLE_SHOT, + CONFIG_RX_TIMEOUT_S * MSEC_PER_SEC, handle); + if (err) { + LOG_ERR("Modem RX failed, err %d", err); + } + + handle++; + + err = k_sem_take(&rx_sem, K_SECONDS(CONFIG_RX_TIMEOUT_S)); + if (err) { + LOG_INF("Receive timeout"); + break; + } + + k_sem_take(&tx_sem, K_FOREVER); + } + + k_timer_stop(&tx_timer); + + 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_rxtx/west.yml b/samples/dect/dect_phy/hello_dect_rxtx/west.yml new file mode 100644 index 000000000000..725725c119fe --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_rxtx/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/samples/dect/dect_phy/hello_dect_tx/CMakeLists.txt b/samples/dect/dect_phy/hello_dect_tx/CMakeLists.txt new file mode 100644 index 000000000000..e7b554343b74 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_tx/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_tx/Kconfig b/samples/dect/dect_phy/hello_dect_tx/Kconfig new file mode 100644 index 000000000000..ef2f912a7377 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_tx/Kconfig @@ -0,0 +1,49 @@ +# +# 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_INTERVAL_SECONDS + int "Transmission interval in seconds" + default 5 + +config TX_TRANSMISSIONS + int "TX transmissions" + range 0 4294967295 + default 0 + help + Transmissions before sample exits, use 0 to transmit forever. + +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_tx/README.rst b/samples/dect/dect_phy/hello_dect_tx/README.rst new file mode 100644 index 000000000000..d3c398b7db7b --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_tx/README.rst @@ -0,0 +1,95 @@ +.. _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 of DECT NR+ messages from one device to other devices on a hard-coded channel. + +During initialization the devices listens on the channel for broadcast transmissions. +Dependent on the detection of transmissions, the device takes one of the following roles: + +* If no transmission is detected, the device takes the role as a tranceiver. In this role, the device sends an incrementing counter value on the hard-coded channel. The period between each transmission is decided by the :kconfig:option:`CONFIG_TX_INTERVAL_SECONDS` Kconfig option. +* If a transmission is detected, the device takes the role as a receiver. In this role, the device listens for incomming messages. + By comparing the counter value with the previous one, the device detects if messages are lost in transmission. + +The device will exit the sample if the user presses button 1, ``exit`` is entered in the terminal or if an irrecoverable error occurs. +A device in the receiving role will also exit if no message is received within a given number of transmission cycles, see :kconfig:option:`CONFIG_TX_TRANSMISSION_CYCLES_BEFORE_EXIT. + +Upon exit, devices in the receiving role will print a simple statistics. +Each device can be reset to run the sample again. + +TX Mode: led 1 on, led 2 blinks +RX mode: led 1 off, led 2 blinks + +User interface +*************** + +Button 1: + Exits the sample. + + +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 device will start listening for incomming data. If data is received, the device will take the receiver role, if not the device will take the transmitter role. +#. Observe that the transmitter device will transmit a counter value that is received by the other devices. +#. Press button 1 on the transmitter device. Observe that the device stops transmitting, and the other devices stop receiving. +#. After some time, observe that the receiver devices prints the simple statistics and exit the sample. + + +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_tx/prj.conf b/samples/dect/dect_phy/hello_dect_tx/prj.conf new file mode 100644 index 000000000000..1bc35301c91d --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_tx/prj.conf @@ -0,0 +1,9 @@ +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 diff --git a/samples/dect/dect_phy/hello_dect_tx/sample.yaml b/samples/dect/dect_phy/hello_dect_tx/sample.yaml new file mode 100644 index 000000000000..5c4742faec44 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_tx/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_tx/src/main.c b/samples/dect/dect_phy/hello_dect_tx/src/main.c new file mode 100644 index 000000000000..733a76172805 --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_tx/src/main.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(app); + +#define DATA_LEN_MAX 16 + +#define CONFIG_TX_INTERVAL_SECONDS 5 + +static bool exit; + +static uint8_t tx_buf[DATA_LEN_MAX]; + +K_SEM_DEFINE(modem_sem, 0, 1); +K_SEM_DEFINE(tx_sem, 0, 1); + +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; +}; + +static void tx_timer_callback(struct k_timer *dummy) +{ + k_sem_give(&tx_sem); +} + +K_TIMER_DEFINE(tx_timer, tx_timer_callback, NULL); + +/* ETSI TS 103 636-2 spec 8.3.3 RSSI is reported every 0.5dbm */ +int32_t calcRSSI(int16_t recrssi){ + return (int32_t)(-20 + ((recrssi + 1) * 0.5)); +} + +/* Callback after init operation. */ +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. */ +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. */ +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. */ +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. */ +void pcc( + const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pcc_status *status, + const union nrf_modem_dect_phy_hdr *hdr) +{ + return; +} + +/* Physical Control Channel CRC error notification. */ +void pcc_crc_err(const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pcc_crc_failure *crc_failure) +{ + return; +} + +/* Physical Data Channel reception notification. */ +void pdc( const uint64_t *time, + const struct nrf_modem_dect_phy_rx_pdc_status *status, + const void *data, uint32_t len) +{ + return; +} + +/* Physical Data Channel CRC error notification. */ +void pdc_crc_err( + const uint64_t *time, const struct nrf_modem_dect_phy_rx_pdc_crc_failure *crc_failure) +{ + return; +} + +/* RSSI measurement result notification. */ +void rssi(const uint64_t *time, const struct nrf_modem_dect_phy_rssi_meas *status) +{ + LOG_DBG("RSSI measurement for carrier %d", status->carrier); + k_sem_give(&modem_sem); +} + +/* callback after link configuration operation. */ +void link_config(const uint64_t *time, enum nrf_modem_dect_phy_err err) +{ + return; +} + +/* Callback after time queuery operation. */ +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. */ +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. */ +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. */ +struct nrf_modem_dect_phy_init_params dect_phy_init_params = { + .harq_rx_expiry_time_us = 5000000, + .harq_rx_process_count = 4, +}; + +/* Send operation, start immediately. */ +int modem_tx(uint32_t handle, void *data, size_t data_len) +{ + int err; + union nrf_modem_dect_phy_hdr phyHeader; + struct nrf_modem_dect_phy_tx_params txOpsParams = { 0 }; + + + 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) (0x0101 >> 8), + .transmitter_id_lo = (uint8_t) (0x0101 & 0xff), + .transmit_power = CONFIG_TX_POWER, + .reserved = 0, + .df_mcs = CONFIG_MCS, + }; + + memcpy(&phyHeader.type_1, &header, 5); + + txOpsParams.start_time = 0; + txOpsParams.handle = handle; + txOpsParams.network_id = CONFIG_NETWORK_ID; + txOpsParams.phy_type = 0; + txOpsParams.lbt_rssi_threshold_max = 0; + txOpsParams.carrier = CONFIG_CARRIER; + txOpsParams.lbt_period = NRF_MODEM_DECT_LBT_PERIOD_MAX; + txOpsParams.phy_header = &phyHeader; + txOpsParams.data = data; + txOpsParams.data_size = data_len; + + k_sem_take(&modem_sem, K_FOREVER); + + err = nrf_modem_dect_phy_tx(&txOpsParams); + if (err!=0) { + return err; + } + + return 0; +} + +/* Transmit counter value on the air. */ +static int transmit_counter(uint32_t counter) +{ + int err; + size_t len; + + /* Format TX buffer */ + len = sprintf(tx_buf, "Hello DECT! %d", counter); + + err = modem_tx(counter, tx_buf, len); + if (err) { + LOG_ERR("Modem TX failed, err %d", err); + return err; + } + + return 0; +} + +int main(void) +{ + int err; + 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); + k_sem_give(&modem_sem); + if (exit) { + return -EIO; + } + + + LOG_INF("Dect NR+ PHY initialized %d", err); + + + k_timer_start(&tx_timer, K_NO_WAIT, K_SECONDS(CONFIG_TX_INTERVAL_SECONDS)); + + while (1) { + LOG_INF("Transmitting"); + err = transmit_counter(tx_counter_value); + if (err) { + LOG_ERR("transmit failed, err %d", err); + continue; + } + + LOG_INF("Data sent %d",tx_counter_value); + + tx_counter_value++; + + if ((tx_counter_value >= CONFIG_TX_TRANSMISSIONS) && CONFIG_TX_TRANSMISSIONS) { + break; + } else if (tx_counter_value == UINT32_MAX) { + tx_counter_value = 0; + } + + k_sem_take(&tx_sem, K_FOREVER); + } + + k_timer_stop(&tx_timer); + + LOG_INF("Reached maximum number of transmissions (%d)", CONFIG_TX_TRANSMISSIONS); + 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_tx/west.yml b/samples/dect/dect_phy/hello_dect_tx/west.yml new file mode 100644 index 000000000000..725725c119fe --- /dev/null +++ b/samples/dect/dect_phy/hello_dect_tx/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