From ec9a4615f82035729645cb623d65e0b6fd53a5b9 Mon Sep 17 00:00:00 2001 From: Graham Wacey Date: Wed, 17 Jul 2024 16:19:28 +0100 Subject: [PATCH] applications: nrf5340_audio: Audio Module Template Implement an audio template to allow rapid development od new audio module. Signed-off-by: Graham Wacey --- include/audio_modules/audio_module_template.h | 50 +++ subsys/CMakeLists.txt | 1 + subsys/Kconfig | 1 + .../audio_module_template/CMakeLists.txt | 10 + .../audio_module_template/Kconfig | 27 ++ .../audio_module_template.c | 200 +++++++++++ .../audio_module_template/CMakeLists.txt | 17 + .../audio_module_template/prj.conf | 17 + .../audio_module_template/src/main.c | 11 + .../audio_module_template/src/template_test.c | 311 ++++++++++++++++++ .../audio_module_template/testcase.yaml | 7 + 11 files changed, 652 insertions(+) create mode 100644 include/audio_modules/audio_module_template.h create mode 100644 subsys/audio_modules/audio_module_template/CMakeLists.txt create mode 100644 subsys/audio_modules/audio_module_template/Kconfig create mode 100644 subsys/audio_modules/audio_module_template/audio_module_template.c create mode 100644 tests/subsys/audio_modules/audio_module_template/CMakeLists.txt create mode 100644 tests/subsys/audio_modules/audio_module_template/prj.conf create mode 100644 tests/subsys/audio_modules/audio_module_template/src/main.c create mode 100644 tests/subsys/audio_modules/audio_module_template/src/template_test.c create mode 100644 tests/subsys/audio_modules/audio_module_template/testcase.yaml diff --git a/include/audio_modules/audio_module_template.h b/include/audio_modules/audio_module_template.h new file mode 100644 index 000000000000..6142ddf4b8bb --- /dev/null +++ b/include/audio_modules/audio_module_template.h @@ -0,0 +1,50 @@ +/* + * Copyright(c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#ifndef _AUDIO_MODULE_TEMPLATE_H_ +#define _AUDIO_MODULE_TEMPLATE_H_ + +#include +#include +#include +#include "audio_defines.h" +#include "audio_module.h" + +#define AUDIO_MODULE_TEMPLATE_LAST_BYTES (10) + +/** + * @brief Private pointer to the module's parameters. + * + */ +extern struct audio_module_description *audio_module_template_description; + +/** + * @brief The module configuration structure. + * + */ +struct audio_module_template_configuration { + /* The rate. */ + uint32_t sample_rate_hz; + + /* the depth. */ + uint32_t bit_depth; + + /* A string .*/ + char *some_text; +}; + +/** + * @brief Private module context. + * + */ +struct audio_module_template_context { + /* Array of data to illustrate the data process function. */ + uint8_t audio_module_template_data[AUDIO_MODULE_TEMPLATE_LAST_BYTES]; + + /* The template configuration. */ + struct audio_module_template_configuration config; +}; + +#endif /* _AUDIO_MODULE_TEMPLATE_H_ */ diff --git a/subsys/CMakeLists.txt b/subsys/CMakeLists.txt index 7afba217388b..66f6a888a244 100644 --- a/subsys/CMakeLists.txt +++ b/subsys/CMakeLists.txt @@ -70,6 +70,7 @@ add_subdirectory_ifdef(CONFIG_NRF_DM dm) add_subdirectory_ifdef(CONFIG_EMDS emds) add_subdirectory_ifdef(CONFIG_NET_CORE_MONITOR net_core_monitor) add_subdirectory_ifdef(CONFIG_AUDIO_MODULE audio_module) +add_subdirectory_ifdef(CONFIG_AUDIO_MODULE_TEMPLATE audio_modules/audio_module_template) add_subdirectory_ifdef(CONFIG_UART_ASYNC_ADAPTER uart_async_adapter) add_subdirectory_ifdef(CONFIG_SDFW_SERVICES_ENABLED sdfw_services) add_subdirectory(suit) diff --git a/subsys/Kconfig b/subsys/Kconfig index 04ba79518fee..be5bf05bed23 100644 --- a/subsys/Kconfig +++ b/subsys/Kconfig @@ -34,6 +34,7 @@ rsource "dm/Kconfig" rsource "nrf_security/Kconfig" rsource "net_core_monitor/Kconfig" rsource "audio_module/Kconfig" +rsource "audio_modules/audio_module_template/Kconfig" rsource "uart_async_adapter/Kconfig" rsource "trusted_storage/Kconfig" rsource "logging/Kconfig" diff --git a/subsys/audio_modules/audio_module_template/CMakeLists.txt b/subsys/audio_modules/audio_module_template/CMakeLists.txt new file mode 100644 index 000000000000..41d86a5587ce --- /dev/null +++ b/subsys/audio_modules/audio_module_template/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2023 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/audio_module_template.c) + +target_include_directories(app PRIVATE ${ZEPHYR_NRF_MODULE_DIR}/include/audio_module + ${ZEPHYR_NRF_MODULE_DIR}/include/audio_modules) diff --git a/subsys/audio_modules/audio_module_template/Kconfig b/subsys/audio_modules/audio_module_template/Kconfig new file mode 100644 index 000000000000..e055063a721e --- /dev/null +++ b/subsys/audio_modules/audio_module_template/Kconfig @@ -0,0 +1,27 @@ +# +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# +menu "Audio Modules" + +config AUDIO_MODULE_TEMPLATE + bool "Audio module template" + help + Enable the audio module template, the + starting point for a new audio module + +if AUDIO_MODULE_TEMPLATE + +#----------------------------------------------------------------------------# +menu "Log levels" + +module = AUDIO_MODULE_TEMPLATE +module-str = audio_module +source "subsys/logging/Kconfig.template.log_config" + +endmenu # Log levels + +endif # AUDIO_MODULE_TEMPLATE + +endmenu # Audio Modules diff --git a/subsys/audio_modules/audio_module_template/audio_module_template.c b/subsys/audio_modules/audio_module_template/audio_module_template.c new file mode 100644 index 000000000000..18b55c28a98c --- /dev/null +++ b/subsys/audio_modules/audio_module_template/audio_module_template.c @@ -0,0 +1,200 @@ +/* + * Copyright(c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include "audio_module_template.h" + +#include +#include +#include +#include +#include +#include +#include "audio_defines.h" +#include "audio_module.h" + +#include +LOG_MODULE_REGISTER(audio_module_template, CONFIG_AUDIO_MODULE_TEMPLATE_LOG_LEVEL); + +static int audio_module_template_open(struct audio_module_handle_private *handle, + struct audio_module_configuration const *const configuration) + +{ + struct audio_module_handle *hdl = (struct audio_module_handle *)handle; + struct audio_module_template_context *ctx = + (struct audio_module_template_context *)hdl->context; + struct audio_module_template_configuration *config = + (struct audio_module_template_configuration *)configuration; + + /* Perform any other functions required to open the module. */ + + /* For example: Clear the module's context. + * Save the initial configuration to the module context. + */ + memset(ctx, 0, sizeof(struct audio_module_template_context)); + memcpy(&ctx->config, config, sizeof(struct audio_module_template_configuration)); + + LOG_DBG("Open %s module", hdl->name); + + return 0; +} + +static int audio_module_template_close(struct audio_module_handle_private *handle) +{ + struct audio_module_handle *hdl = (struct audio_module_handle *)handle; + struct audio_module_template_context *ctx = + (struct audio_module_template_context *)hdl->context; + + /* Perform any other functions required to close the module. */ + + /* For example: Clear the context data */ + memset(ctx, 0, sizeof(struct audio_module_template_context)); + + LOG_DBG("Close %s module", hdl->name); + + return 0; +} + +static int audio_module_template_configuration_set( + struct audio_module_handle_private *handle, + struct audio_module_configuration const *const configuration) +{ + struct audio_module_template_configuration *config = + (struct audio_module_template_configuration *)configuration; + struct audio_module_handle *hdl = (struct audio_module_handle *)handle; + struct audio_module_template_context *ctx = + (struct audio_module_template_context *)hdl->context; + + /* Perform any other functions to configure the module. */ + + /* For example: Copy the configuration into the context. */ + memcpy(&ctx->config, config, sizeof(struct audio_module_template_configuration)); + + LOG_DBG("Set the configuration for %s module: rate = %d depth = %d string = %s", + hdl->name, ctx->config.sample_rate_hz, ctx->config.bit_depth, + ctx->config.some_text); + + return 0; +} + +static int +audio_module_template_configuration_get(struct audio_module_handle_private const *const handle, + struct audio_module_configuration *configuration) +{ + struct audio_module_template_configuration *config = + (struct audio_module_template_configuration *)configuration; + struct audio_module_handle *hdl = (struct audio_module_handle *)handle; + struct audio_module_template_context *ctx = + (struct audio_module_template_context *)hdl->context; + + /* Perform any other functions to extract the configuration of the module. */ + + /* For example: Copy the configuration from the context into the output configuration. */ + memcpy(config, &ctx->config, sizeof(struct audio_module_template_configuration)); + + LOG_DBG("Get the configuration for %s module: rate = %d depth = %d string = %s", + hdl->name, config->sample_rate_hz, config->bit_depth, config->some_text); + + return 0; +} + +static int audio_module_template_start(struct audio_module_handle_private *handle) +{ + struct audio_module_handle *hdl = (struct audio_module_handle *)handle; + + /* Perform any other functions to start the module. */ + + LOG_DBG("Start the %s module", hdl->name); + + return 0; +} + +static int audio_module_template_stop(struct audio_module_handle_private *handle) +{ + struct audio_module_handle *hdl = (struct audio_module_handle *)handle; + + /* Perform any other functions to stop the module. */ + + LOG_DBG("Stop the %s module", hdl->name); + + return 0; +} + +static int audio_module_template_data_process(struct audio_module_handle_private *handle, + struct audio_data const *const audio_data_in, + struct audio_data *audio_data_out) +{ + struct audio_module_handle *hdl = (struct audio_module_handle *)handle; + + /* Perform any other functions to process the data within the module. */ + + /* For example: Copy the input to the output. */ + { + size_t size = audio_data_in->data_size < audio_data_out->data_size + ? audio_data_in->data_size + : audio_data_out->data_size; + + memcpy(&audio_data_out->meta, &audio_data_in->meta, sizeof(struct audio_metadata)); + memcpy((uint8_t *)audio_data_out->data, (uint8_t *)audio_data_in->data, size); + audio_data_out->data_size = size; + } + + LOG_DBG("Process the input audio data into the output audio data item for %s module", + hdl->name); + + return 0; +} + +/** + * @brief Table of the dummy module functions. + */ +const struct audio_module_functions audio_module_template_functions = { + /** + * @brief Function to an open the dummy module. + */ + .open = audio_module_template_open, + + /** + * @brief Function to close the dummy module. + */ + .close = audio_module_template_close, + + /** + * @brief Function to set the configuration of the dummy module. + */ + .configuration_set = audio_module_template_configuration_set, + + /** + * @brief Function to get the configuration of the dummy module. + */ + .configuration_get = audio_module_template_configuration_get, + + /** + * @brief Start a module processing data. + */ + .start = audio_module_template_start, + + /** + * @brief Pause a module processing data. + */ + .stop = audio_module_template_stop, + + /** + * @brief The core data processing function in the dummy module. + */ + .data_process = audio_module_template_data_process, +}; + +/** + * @brief The set-up description for the LC3 decoder. + */ +struct audio_module_description audio_module_template_dept = { + .name = "Audio Module Temp", + .type = AUDIO_MODULE_TYPE_IN_OUT, + .functions = &audio_module_template_functions}; + +/** + * @brief A private pointer to the LC3 decoder set-up parameters. + */ +struct audio_module_description *audio_module_template_description = &audio_module_template_dept; diff --git a/tests/subsys/audio_modules/audio_module_template/CMakeLists.txt b/tests/subsys/audio_modules/audio_module_template/CMakeLists.txt new file mode 100644 index 000000000000..18cf31748ead --- /dev/null +++ b/tests/subsys/audio_modules/audio_module_template/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Copyright (c) 20234 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project("Audio module Template") + +target_sources(app PRIVATE + src/main.c + src/template_test.c +) + +target_include_directories(app PRIVATE ${ZEPHYR_NRF_MODULE_DIR}/subsys/audio_modules/audio_module_template) diff --git a/tests/subsys/audio_modules/audio_module_template/prj.conf b/tests/subsys/audio_modules/audio_module_template/prj.conf new file mode 100644 index 000000000000..5aa1308f4a9e --- /dev/null +++ b/tests/subsys/audio_modules/audio_module_template/prj.conf @@ -0,0 +1,17 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_ZTEST=y +CONFIG_ZTEST_STACK_SIZE=8196 +CONFIG_IRQ_OFFLOAD=y +CONFIG_DATA_FIFO=y +CONFIG_AUDIO_MODULE=y +CONFIG_AUDIO_MODULE_TEMPLATE=y + +# The large stack size can be optimized +CONFIG_MAIN_STACK_SIZE=16000 + +CONFIG_STACK_SENTINEL=y diff --git a/tests/subsys/audio_modules/audio_module_template/src/main.c b/tests/subsys/audio_modules/audio_module_template/src/main.c new file mode 100644 index 000000000000..fe0369f7b663 --- /dev/null +++ b/tests/subsys/audio_modules/audio_module_template/src/main.c @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +ZTEST_SUITE(suite_audio_module_template, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/audio_modules/audio_module_template/src/template_test.c b/tests/subsys/audio_modules/audio_module_template/src/template_test.c new file mode 100644 index 000000000000..7f9914579f32 --- /dev/null +++ b/tests/subsys/audio_modules/audio_module_template/src/template_test.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +#include "audio_module.h" +#include "audio_module_template.h" + +/* Define a timeout to prevent system locking */ +#define TEST_TX_RX_TIMEOUT_US (K_FOREVER) + +#define CONFIG_TEXT "Template config" +#define RECONFIG_TEXT "Template reconfig" + +#define TEST_MSG_QUEUE_SIZE (4) +#define TEST_MOD_THREAD_STACK_SIZE (2048) +#define TEST_MOD_THREAD_PRIORITY (4) +#define TEST_CONNECTIONS_NUM (5) +#define TEST_MODULES_NUM (TEST_CONNECTIONS_NUM - 1) +#define TEST_MOD_DATA_SIZE (40) +#define TEST_MSG_SIZE (sizeof(struct audio_module_message)) +#define TEST_AUDIO_DATA_ITEMS_NUM (20) + +struct mod_config { + int test_int1; + int test_int2; + int test_int3; + int test_int4; +}; + +struct mod_context { + const char *test_string; + uint32_t test_uint32; + + struct mod_config config; +}; + +const char *test_instance_name = "Test instance"; +struct audio_metadata test_metadata = {.data_coding = LC3, + .data_len_us = 10000, + .sample_rate_hz = 48000, + .bits_per_sample = 16, + .carried_bits_per_sample = 16, + .locations = 0x00000003, + .reference_ts_us = 0, + .data_rx_ts_us = 0, + .bad_data = false}; + +K_THREAD_STACK_ARRAY_DEFINE(mod_temp_stack, TEST_MODULES_NUM, TEST_MOD_THREAD_STACK_SIZE); +DATA_FIFO_DEFINE(msg_fifo_tx, TEST_MSG_QUEUE_SIZE, TEST_MSG_SIZE); +DATA_FIFO_DEFINE(msg_fifo_rx, TEST_MSG_QUEUE_SIZE, TEST_MSG_SIZE); +DATA_FIFO_DEFINE(msg_fifo_tx1, TEST_MSG_QUEUE_SIZE, TEST_MSG_SIZE); +DATA_FIFO_DEFINE(msg_fifo_rx1, TEST_MSG_QUEUE_SIZE, TEST_MSG_SIZE); +DATA_FIFO_DEFINE(msg_fifo_tx2, TEST_MSG_QUEUE_SIZE, TEST_MSG_SIZE); +DATA_FIFO_DEFINE(msg_fifo_rx2, TEST_MSG_QUEUE_SIZE, TEST_MSG_SIZE); +DATA_FIFO_DEFINE(msg_fifo_tx3, TEST_MSG_QUEUE_SIZE, TEST_MSG_SIZE); +DATA_FIFO_DEFINE(msg_fifo_rx3, TEST_MSG_QUEUE_SIZE, TEST_MSG_SIZE); +K_MEM_SLAB_DEFINE(mod_data_slab, TEST_MOD_DATA_SIZE, TEST_MSG_QUEUE_SIZE, 4); + +struct data_fifo *msg_fifo_tx_array[TEST_MODULES_NUM] = {&msg_fifo_tx, &msg_fifo_tx1, &msg_fifo_tx2, + &msg_fifo_tx3}; +struct data_fifo *msg_fifo_rx_array[TEST_MODULES_NUM] = {&msg_fifo_rx, &msg_fifo_rx1, &msg_fifo_rx2, + &msg_fifo_rx3}; + +ZTEST(suite_audio_module_template, test_module_template) +{ + int ret; + int i; + char *base_name, instance_name[CONFIG_AUDIO_MODULE_NAME_SIZE]; + + struct audio_data audio_data_tx; + struct audio_data audio_data_rx; + + struct audio_module_parameters mod_parameters; + + struct audio_module_template_configuration configuration = { + .sample_rate_hz = 48000, .bit_depth = 12345, .some_text = CONFIG_TEXT}; + struct audio_module_template_configuration reconfiguration = { + .sample_rate_hz = 16000, .bit_depth = 54321, .some_text = RECONFIG_TEXT}; + struct audio_module_template_configuration return_configuration; + + struct audio_module_template_context context = {0}; + + uint8_t test_data_in[TEST_MOD_DATA_SIZE * TEST_AUDIO_DATA_ITEMS_NUM]; + uint8_t test_data_out[TEST_MOD_DATA_SIZE * TEST_AUDIO_DATA_ITEMS_NUM]; + + struct audio_module_handle handle; + + mod_parameters.description = audio_module_template_description; + mod_parameters.thread.stack = mod_temp_stack[0]; + mod_parameters.thread.stack_size = TEST_MOD_THREAD_STACK_SIZE; + mod_parameters.thread.priority = TEST_MOD_THREAD_PRIORITY; + mod_parameters.thread.data_slab = &mod_data_slab; + mod_parameters.thread.data_size = TEST_MOD_DATA_SIZE; + mod_parameters.thread.msg_rx = &msg_fifo_rx; + mod_parameters.thread.msg_tx = &msg_fifo_tx; + + ret = audio_module_open( + &mod_parameters, (struct audio_module_configuration const *const)&configuration, + test_instance_name, (struct audio_module_context *)&context, &handle); + zassert_equal(ret, 0, "Open function did not return successfully (0): ret %d", ret); + + { + struct audio_module_template_context *ctx = + (struct audio_module_template_context *)handle.context; + struct audio_module_template_configuration *test_config = &ctx->config; + + zassert_equal(test_config->bit_depth, configuration.bit_depth, + "Failed to configure module in the open function"); + zassert_equal(test_config->sample_rate_hz, configuration.sample_rate_hz, + "Failed to configure module in the open function"); + zassert_mem_equal(test_config->some_text, configuration.some_text, + sizeof(CONFIG_TEXT), + "Failed to configure module in the open function"); + } + + zassert_equal_ptr(handle.description->name, audio_module_template_description->name, + "Failed open for names, base name should be %s, but is %s", + audio_module_template_description->name, handle.description->name); + zassert_mem_equal(&handle.name[0], test_instance_name, strlen(test_instance_name), + "Failed open for names, instance name should be %s, but is %s", + test_instance_name, handle.name); + zassert_equal(handle.state, AUDIO_MODULE_STATE_CONFIGURED, + "Not in configured state after call to open the audio module"); + + ret = audio_module_names_get(&handle, &base_name, &instance_name[0]); + zassert_equal(ret, 0, "Get names function did not return successfully (0): ret %d", ret); + zassert_mem_equal(base_name, audio_module_template_description->name, + strlen(audio_module_template_description->name), + "Failed get names, base name should be %s, but is %s", + audio_module_template_description->name, base_name); + zassert_mem_equal(&instance_name[0], test_instance_name, strlen(test_instance_name), + "Failed get names, instance name should be %s, but is %s", handle.name, + &instance_name[0]); + + ret = audio_module_configuration_get( + &handle, (struct audio_module_configuration *)&return_configuration); + zassert_equal(ret, 0, "Configuration get function did not return successfully (0): ret %d", + ret); + zassert_equal(return_configuration.bit_depth, configuration.bit_depth, + "Failed to get configuration"); + zassert_equal(return_configuration.sample_rate_hz, configuration.sample_rate_hz, + "Failed to get configuration"); + zassert_mem_equal(return_configuration.some_text, configuration.some_text, + sizeof(CONFIG_TEXT), "Failed to get configuration"); + + ret = audio_module_connect(&handle, NULL, true); + zassert_equal(ret, 0, "Connect function did not return successfully (0): ret %d", ret); + zassert_equal(handle.use_tx_queue, 1, "Connect queue size is not %d, but is %d", 1, + handle.use_tx_queue); + + ret = audio_module_start(&handle); + zassert_equal(ret, 0, "Start function did not return successfully (0): ret %d", ret); + zassert_equal(handle.state, AUDIO_MODULE_STATE_RUNNING, + "Not in running state after call to start the audio module"); + + for (i = 0; i < TEST_AUDIO_DATA_ITEMS_NUM; i++) { + audio_data_tx.data = (void *)&test_data_in[i * TEST_MOD_DATA_SIZE]; + audio_data_tx.data_size = TEST_MOD_DATA_SIZE; + memcpy(&audio_data_tx.meta, &test_metadata, sizeof(struct audio_metadata)); + + audio_data_rx.data = (void *)&test_data_out[i * TEST_MOD_DATA_SIZE]; + audio_data_rx.data_size = TEST_MOD_DATA_SIZE; + + ret = audio_module_data_tx_rx(&handle, &handle, &audio_data_tx, &audio_data_rx, + TEST_TX_RX_TIMEOUT_US); + zassert_equal(ret, 0, "Data TX-RX function did not return successfully (0): ret %d", + ret); + zassert_mem_equal(audio_data_tx.data, audio_data_rx.data, TEST_MOD_DATA_SIZE, + "Failed to process data"); + zassert_equal(audio_data_tx.data_size, audio_data_rx.data_size, + "Failed to process data, sizes differ"); + zassert_mem_equal(&audio_data_tx.meta, &audio_data_rx.meta, + sizeof(struct audio_metadata), + "Failed to process data, meta data differs"); + + if (i == TEST_AUDIO_DATA_ITEMS_NUM / 2) { + ret = audio_module_stop(&handle); + zassert_equal(ret, 0, + "Stop function did not return successfully (0): ret %d", ret); + + ret = audio_module_reconfigure( + &handle, + (const struct audio_module_configuration *const)&reconfiguration); + zassert_equal( + ret, 0, + "Reconfigure function did not return successfully (0): ret %d", + ret); + zassert_equal(reconfiguration.bit_depth, reconfiguration.bit_depth, + "Failed to reconfigure module"); + zassert_equal(reconfiguration.sample_rate_hz, + reconfiguration.sample_rate_hz, + "Failed to reconfigure module"); + zassert_mem_equal(reconfiguration.some_text, reconfiguration.some_text, + sizeof(RECONFIG_TEXT), "Failed to reconfigure module"); + + ret = audio_module_start(&handle); + zassert_equal(ret, 0, + "Start function did not return successfully (0): ret %d", + ret); + zassert_equal(handle.state, AUDIO_MODULE_STATE_RUNNING, + "Not in running state after call to start the audio module"); + } + } + + ret = audio_module_disconnect(&handle, NULL, true); + zassert_equal(ret, 0, "Disconnect function did not return successfully (0): ret %d", ret); + zassert_equal(handle.use_tx_queue, 0, "Disconnect queue size is not %d, but is %d", 0, + handle.use_tx_queue); + + ret = audio_module_stop(&handle); + zassert_equal(ret, 0, "Stop function did not return successfully (0): ret %d", ret); + zassert_equal(handle.state, AUDIO_MODULE_STATE_STOPPED, + "Not in stopped state after call to stop the audio module"); + + ret = audio_module_close(&handle); + zassert_equal(ret, 0, "Close function did not return successfully (0): ret %d", ret); +} + +ZTEST(suite_audio_module_template, test_module_template_stream) +{ + int ret; + int i; + char inst_name[CONFIG_AUDIO_MODULE_NAME_SIZE]; + + struct audio_data audio_data_tx; + struct audio_data audio_data_rx; + + struct audio_module_parameters mod_parameters; + + struct audio_module_template_configuration configuration = { + .sample_rate_hz = 48000, .bit_depth = 12345, .some_text = CONFIG_TEXT}; + + struct audio_module_template_context context = {0}; + + uint8_t test_data_in[TEST_MOD_DATA_SIZE * TEST_AUDIO_DATA_ITEMS_NUM]; + uint8_t test_data_out[TEST_MOD_DATA_SIZE * TEST_AUDIO_DATA_ITEMS_NUM]; + + struct audio_module_handle handle[TEST_MODULES_NUM]; + + for (i = 0; i < TEST_MODULES_NUM; i++) { + + memset(&handle[i], 0, sizeof(struct audio_module_handle)); + + mod_parameters.description = audio_module_template_description; + mod_parameters.thread.stack = mod_temp_stack[i]; + mod_parameters.thread.stack_size = TEST_MOD_THREAD_STACK_SIZE; + mod_parameters.thread.priority = TEST_MOD_THREAD_PRIORITY; + mod_parameters.thread.data_slab = &mod_data_slab; + mod_parameters.thread.data_size = TEST_MOD_DATA_SIZE; + mod_parameters.thread.msg_rx = msg_fifo_rx_array[i]; + mod_parameters.thread.msg_tx = msg_fifo_tx_array[i]; + + ret = audio_module_open( + &mod_parameters, + (const struct audio_module_configuration *const)&configuration, + &inst_name[0], (struct audio_module_context *)&context, &handle[i]); + zassert_equal(ret, 0, "Open function did not return successfully (0): ret %d", ret); + } + + for (i = 1; i < TEST_MODULES_NUM; i++) { + ret = audio_module_connect(&handle[i - 1], &handle[i], false); + zassert_equal(ret, 0, "Connect function did not return successfully (0): ret %d", + ret); + } + + ret = audio_module_connect(&handle[TEST_MODULES_NUM - 1], NULL, true); + zassert_equal(ret, 0, "Connect function did not return successfully (0): ret %d", ret); + + for (i = 0; i < TEST_MODULES_NUM; i++) { + ret = audio_module_start(&handle[i]); + zassert_equal(ret, 0, "Start function did not return successfully (0): ret %d", + ret); + } + + for (i = 0; i < TEST_AUDIO_DATA_ITEMS_NUM; i++) { + audio_data_tx.data = (void *)&test_data_in[i * TEST_MOD_DATA_SIZE]; + audio_data_tx.data_size = TEST_MOD_DATA_SIZE; + memcpy(&audio_data_tx.meta, &test_metadata, sizeof(struct audio_metadata)); + + audio_data_rx.data = (void *)&test_data_out[i * TEST_MOD_DATA_SIZE]; + audio_data_rx.data_size = TEST_MOD_DATA_SIZE; + + ret = audio_module_data_tx_rx(&handle[0], &handle[TEST_MODULES_NUM - 1], + &audio_data_tx, &audio_data_rx, + TEST_TX_RX_TIMEOUT_US); + zassert_equal(ret, 0, "Data TX-RX function did not return successfully (0): ret %d", + ret); + zassert_mem_equal(audio_data_tx.data, audio_data_rx.data, TEST_MOD_DATA_SIZE, + "Failed to process data"); + zassert_equal(audio_data_tx.data_size, audio_data_rx.data_size, + "Failed to process data, sizes differ"); + zassert_mem_equal(&audio_data_tx.meta, &audio_data_rx.meta, + sizeof(struct audio_metadata), + "Failed to process data, meta data differs"); + } + + for (i = 1; i < TEST_MODULES_NUM; i++) { + ret = audio_module_stop(&handle[i]); + zassert_equal(ret, 0, "Stop function did not return successfully (0): ret %d", ret); + + ret = audio_module_close(&handle[i]); + zassert_equal(ret, 0, "Close function did not return successfully (0): ret %d", + ret); + } +} diff --git a/tests/subsys/audio_modules/audio_module_template/testcase.yaml b/tests/subsys/audio_modules/audio_module_template/testcase.yaml new file mode 100644 index 000000000000..75f6f3f693e4 --- /dev/null +++ b/tests/subsys/audio_modules/audio_module_template/testcase.yaml @@ -0,0 +1,7 @@ +tests: + nrf5340_audio.audio_module_template: + sysbuild: true + platform_allow: qemu_cortex_m3 + integration_platforms: + - qemu_cortex_m3 + tags: audio_module audio_module_template nrf5340_audio_unit_tests sysbuild