diff --git a/CODEOWNERS b/CODEOWNERS index a9e067ad4347..e405a87683d6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -254,6 +254,7 @@ Kconfig* @tejlmand /snippets/nordic-bt-rpc/ @ppryga-nordic /snippets/ci-shell/ @nrfconnect/ncs-protocols-serialization /snippets/zperf/ @nrfconnect/ncs-protocols-serialization +/subsys/audio/ @nrfconnect/ncs-audio /subsys/audio_module/ @nrfconnect/ncs-audio /subsys/bluetooth/ @alwa-nordic @jori-nordic @carlescufi @KAGA164 /subsys/bluetooth/mesh/ @nrfconnect/ncs-paladin @@ -360,6 +361,7 @@ Kconfig* @tejlmand /tests/modules/mcuboot/direct_xip/ @hakonfam /tests/modules/mcuboot/external_flash/ @hakonfam @sigvartmh /tests/nrf5340_audio/ @nrfconnect/ncs-audio @nordic-auko +/tests/subsys/audio/ @nrfconnect/ncs-audio /tests/subsys/audio_module/ @nrfconnect/ncs-audio /tests/subsys/bluetooth/gatt_dm/ @doki-nordic /tests/subsys/bluetooth/mesh/ @nrfconnect/ncs-paladin diff --git a/include/audio/audio_module_template.h b/include/audio/audio_module_template.h new file mode 100644 index 000000000000..64b7b1e32c53 --- /dev/null +++ b/include/audio/audio_module_template.h @@ -0,0 +1,51 @@ +/* + * 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" + +/* @brief Size of the data block within the template context, for testing. */ +#define AUDIO_MODULE_TEMPLATE_DATA_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 sample rate, for testing. */ + uint32_t sample_rate_hz; + + /* The bit depth, for testing. */ + uint8_t bit_depth; + + /* A string for testing.*/ + char *module_description; +}; + +/** + * @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_DATA_BYTES]; + + /* The template configuration. */ + struct audio_module_template_configuration config; +}; + +#endif /* _AUDIO_MODULE_TEMPLATE_H_ */ diff --git a/scripts/ci/tags.yaml b/scripts/ci/tags.yaml index 433474025b68..138546666629 100644 --- a/scripts/ci/tags.yaml +++ b/scripts/ci/tags.yaml @@ -920,6 +920,8 @@ ci_tests_subsys_audio_module: files: - nrf/subsys/audio_module/ - nrf/tests/subsys/audio_module/ + - nrf/subsys/audio/ + - nrf/tests/subsys/audio/ ci_tests_subsys_mpsl: files: diff --git a/subsys/CMakeLists.txt b/subsys/CMakeLists.txt index 7afba217388b..80023be74eea 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/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..b17cb90fd3ac 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/audio_module_template/Kconfig" rsource "uart_async_adapter/Kconfig" rsource "trusted_storage/Kconfig" rsource "logging/Kconfig" diff --git a/subsys/audio/audio_module_template/CMakeLists.txt b/subsys/audio/audio_module_template/CMakeLists.txt new file mode 100644 index 000000000000..b04750c1dcdf --- /dev/null +++ b/subsys/audio/audio_module_template/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2024 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) diff --git a/subsys/audio/audio_module_template/Kconfig b/subsys/audio/audio_module_template/Kconfig new file mode 100644 index 000000000000..6f8ca0f4d7b5 --- /dev/null +++ b/subsys/audio/audio_module_template/Kconfig @@ -0,0 +1,27 @@ +# +# Copyright (c) 2024 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/audio_module_template/audio_module_template.c b/subsys/audio/audio_module_template/audio_module_template.c new file mode 100644 index 000000000000..45924ad6f6e4 --- /dev/null +++ b/subsys/audio/audio_module_template/audio_module_template.c @@ -0,0 +1,201 @@ +/* + * Copyright(c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include "audio_module_template.h" + +#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: sample rate = %d bit depth = %d string = " + "%s", + hdl->name, ctx->config.sample_rate_hz, ctx->config.bit_depth, + ctx->config.module_description); + + 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: sample rate = %d bit depth = %d string = " + "%s", + hdl->name, config->sample_rate_hz, config->bit_depth, config->module_description); + + 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(audio_data_out->data, 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 template set-up parameters. + */ +struct audio_module_description *audio_module_template_description = &audio_module_template_dept; diff --git a/tests/subsys/audio/audio_module_template/CMakeLists.txt b/tests/subsys/audio/audio_module_template/CMakeLists.txt new file mode 100644 index 000000000000..ee674c7ebafc --- /dev/null +++ b/tests/subsys/audio/audio_module_template/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Copyright (c) 2024 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/audio_module_template) diff --git a/tests/subsys/audio/audio_module_template/prj.conf b/tests/subsys/audio/audio_module_template/prj.conf new file mode 100644 index 000000000000..5aa1308f4a9e --- /dev/null +++ b/tests/subsys/audio/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/audio_module_template/src/main.c b/tests/subsys/audio/audio_module_template/src/main.c new file mode 100644 index 000000000000..fe0369f7b663 --- /dev/null +++ b/tests/subsys/audio/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/audio_module_template/src/template_test.c b/tests/subsys/audio/audio_module_template/src/template_test.c new file mode 100644 index 000000000000..89fc3baf2fd4 --- /dev/null +++ b/tests/subsys/audio/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_tx0, TEST_MSG_QUEUE_SIZE, TEST_MSG_SIZE); +DATA_FIFO_DEFINE(msg_fifo_rx0, 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_tx0, &msg_fifo_tx1, + &msg_fifo_tx2, &msg_fifo_tx3}; +struct data_fifo *msg_fifo_rx_array[TEST_MODULES_NUM] = {&msg_fifo_rx0, &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 = 24, .module_description = CONFIG_TEXT}; + struct audio_module_template_configuration reconfiguration = { + .sample_rate_hz = 16000, .bit_depth = 8, .module_description = 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_rx0; + mod_parameters.thread.msg_tx = &msg_fifo_tx0; + + 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->module_description, configuration.module_description, + 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.module_description, configuration.module_description, + 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.module_description, + reconfiguration.module_description, 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 = 16, .module_description = 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 = 0; i < TEST_MODULES_NUM - 1; i++) { + ret = audio_module_connect(&handle[i], &handle[i + 1], 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/audio_module_template/testcase.yaml b/tests/subsys/audio/audio_module_template/testcase.yaml new file mode 100644 index 000000000000..8d324ee243e4 --- /dev/null +++ b/tests/subsys/audio/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 ci_tests_subsys_audio_module diff --git a/tests/subsys/audio_module/src/audio_module_test_common.c b/tests/subsys/audio_module/src/audio_module_test_common.c index 6c98b50913bd..d2082a294686 100644 --- a/tests/subsys/audio_module/src/audio_module_test_common.c +++ b/tests/subsys/audio_module/src/audio_module_test_common.c @@ -105,6 +105,7 @@ int test_data_process_function(struct audio_module_handle_private *handle, audio_data_tx->data_size = audio_data_rx->data_size; } else { printk("The input and output data pointers are NULL"); + return -1; } return 0;