Skip to content

Commit

Permalink
Applications: nrf5340_audio: Add display module
Browse files Browse the repository at this point in the history
Adds the nrf5340_audio_dk_display module for the audio application.
This module uses the LVGL library to present information from the
application to the user using an Adafruit touch display. A shield
definition is added so that the Adafruit display shield can be used
with the nrf5340 Audio DK.

Signed-off-by: Philip Fidjeland <philipfidjeland@gmail.com>
Signed-off-by: Andreas Vibeto <andreas.vibeto@nordicsemi.no>
  • Loading branch information
philipfidjeland authored and andvib committed Sep 15, 2023
1 parent f9f5479 commit ddb0b18
Show file tree
Hide file tree
Showing 20 changed files with 1,054 additions and 5 deletions.
2 changes: 1 addition & 1 deletion applications/nrf5340_audio/Kconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ config ZBUS
default y

config ZBUS_RUNTIME_OBSERVERS_POOL_SIZE
default 6
default 7

config SENSOR
default y
Expand Down
18 changes: 18 additions & 0 deletions applications/nrf5340_audio/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,21 @@ tests:
platform_exclude: nrf5340_audio_dk_nrf5340_cpuapp_ns
tags: ci_build
extra_args: CONF_FILE="prj_release.conf" CONFIG_AUDIO_DEV=2 CONFIG_AUDIO_DFU=2
applications.nrf5340_audio.hs_display:
build_only: true
platform_allow: nrf5340_audio_dk_nrf5340_cpuapp
platform_exclude: nrf5340_audio_dk_nrf5340_cpuapp_ns
tags: ci_build
extra_args: CONF_FILE="prj_release.conf"
CONFIG_AUDIO_DEV=1
SHIELD="nrf5340_audio_display"
CONFIG_NRF5340_AUDIO_DK_DISPLAY=y
applications.nrf5340_audio.gw_display:
build_only: true
platform_allow: nrf5340_audio_dk_nrf5340_cpuapp
platform_exclude: nrf5340_audio_dk_nrf5340_cpuapp_ns
tags: ci_build
extra_args: CONF_FILE="prj_release.conf"
CONFIG_AUDIO_DEV=2
SHIELD="nrf5340_audio_display"
CONFIG_NRF5340_AUDIO_DK_DISPLAY=y
8 changes: 8 additions & 0 deletions applications/nrf5340_audio/src/audio/audio_datapath.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ static struct {
bool datapath_initialized;
bool stream_started;
void *decoded_data;
size_t decoded_size;

struct {
struct data_fifo *fifo;
Expand Down Expand Up @@ -861,6 +862,7 @@ void audio_datapath_stream_out(const uint8_t *buf, size_t size, uint32_t sdu_ref
/* Discard frame */
return;
}
ctrl_blk.decoded_size = pcm_size;

/*** Add audio data to FIFO buffer ***/

Expand Down Expand Up @@ -947,6 +949,12 @@ int audio_datapath_init(void)
return 0;
}

void audio_datapath_buffer_ptr_get(void **p_buf, size_t **p_size)
{
*p_buf = ctrl_blk.decoded_data;
*p_size = &ctrl_blk.decoded_size;
}

static int cmd_i2s_tone_play(const struct shell *shell, size_t argc, const char **argv)
{
int ret;
Expand Down
13 changes: 13 additions & 0 deletions applications/nrf5340_audio/src/audio/audio_datapath.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,17 @@ int audio_datapath_stop(void);
*/
int audio_datapath_init(void);

/**
* @brief Get pointers to the decoded audio data frame
*
* @note The decoded audio data frame lives statically in this module, and can be accessed at
* any time after the module has been initialized. The buffer can be updated by other the
* decoder thread at any time, and hence it is never guaranteed that the buffer data is not
* updated while the buffer is being accessed.
*
* @param p_buf Pointer to variable where the audio data buffer pointer will be stored
* @param p_size Pointer to variable where the size of the audio data buffer will be stored
*/
void audio_datapath_buffer_ptr_get(void **p_buf, size_t **p_size);

#endif /* _AUDIO_DATAPATH_H_ */
2 changes: 2 additions & 0 deletions applications/nrf5340_audio/src/modules/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ target_sources(app PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/power_meas.c
${CMAKE_CURRENT_SOURCE_DIR}/sd_card.c
)

add_subdirectory(display)
1 change: 1 addition & 0 deletions applications/nrf5340_audio/src/modules/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#

rsource "Kconfig.defaults"
rsource "display/Kconfig"

menu "Modules"

Expand Down
15 changes: 15 additions & 0 deletions applications/nrf5340_audio/src/modules/display/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

if (CONFIG_NRF5340_AUDIO_DK_DISPLAY)
target_sources(app PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/nrf5340_audio_dk_display.c
${CMAKE_CURRENT_SOURCE_DIR}/tab_menu.c
)
if (CONFIG_NRF5340_AUDIO_DK_DISPLAY_TAB_LOG)
target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tab_log.c)
endif()
endif()
45 changes: 45 additions & 0 deletions applications/nrf5340_audio/src/modules/display/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

menuconfig NRF5340_AUDIO_DK_DISPLAY
bool "Display for nRF5340 Audio DK [EXPERIMENTAL]"
select EXPERIMENTAL
default n

if NRF5340_AUDIO_DK_DISPLAY

rsource "Kconfig.defaults"

module = NRF5340_AUDIO_DK_DISPLAY
module-str = nrf5340_audio_dk_display
source "subsys/logging/Kconfig.template.log_config"

config NRF5340_AUDIO_DK_DISPLAY_TAB_LOG
bool "Enable the log tab on the display"
depends on LOG
default y

if NRF5340_AUDIO_DK_DISPLAY_TAB_LOG

config NRF5340_AUDIO_DK_DISPLAY_TAB_LOG_LEVEL
int "Log level for message displayed on screen"
default 2

config NRF5340_AUDIO_DK_DISPLAY_TAB_LOG_TIMESTAMP
bool "Display timestamp in us in front of log message"
default n

config NRF5340_AUDIO_DK_DISPLAY_TAB_LOG_MAX_LEN
int "Number of messages to be stored"
default 10

endif # NRF5340_AUDIO_DK_DISPLAY_TAB_LOG

config NRF5340_AUDIO_DK_DISPLAY_TAB_MENU_UPDATE_INTERVAL_MS
int "Update interval for the menu tab, in milliseconds"
default 500

endif # NRF5340_AUDIO_DK_DISPLAY
28 changes: 28 additions & 0 deletions applications/nrf5340_audio/src/modules/display/Kconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

config DISPLAY
default y

config LVGL
default y

config LV_Z_MEM_POOL_NUMBER_BLOCKS
int "Number of max size blocks in memory pool"
default 8

config LV_FONT_MONTSERRAT_14
default y

config LV_FONT_MONTSERRAT_48
default y

config LV_FONT_MONTSERRAT_20
default y

config LV_Z_VDB_SIZE
int "Virtual display buffer size"
default 32
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/display.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/zbus/zbus.h>
#include <zephyr/logging/log.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include <lvgl.h>

#include "tab_menu.h"
#include "tab_log.h"
#include "macros_common.h"

#define DISPLAY_THREAD_PRIORITY 5
/* Must have lower priority than LVGL init */
#define DISPLAY_INIT_PRIORITY 91
#define DISPLAY_THREAD_STACK_SIZE 1800

LOG_MODULE_REGISTER(display_log, CONFIG_DISPLAY_LOG_LEVEL);

static struct k_thread display_data;
static k_tid_t display_thread;

ZBUS_CHAN_DECLARE(button_chan);
ZBUS_CHAN_DECLARE(le_audio_chan);

ZBUS_OBS_DECLARE(le_audio_evt_sub_display);

K_THREAD_STACK_DEFINE(display_thread_STACK, DISPLAY_THREAD_STACK_SIZE);

static void nrf5340_audio_dk_display_update_thread(void *arg1, void *arg2, void *arg3)
{
uint64_t prev_tab_update = k_uptime_get();

while (1) {
if ((k_uptime_get() - prev_tab_update) >
CONFIG_NRF5340_AUDIO_DK_DISPLAY_TAB_MENU_UPDATE_INTERVAL_MS) {
tab_menu_update();
prev_tab_update = k_uptime_get();
}

uint32_t time_till_next = lv_timer_handler();

k_sleep(K_MSEC(time_till_next));
}
}

static int nrf5340_audio_dk_display_init(void)
{
int ret;
const struct device *display_dev;
lv_obj_t *tabview;
lv_obj_t *tab_menu;
#ifdef CONFIG_NRF5340_AUDIO_DK_DISPLAY_TAB_LOG
lv_obj_t *tab_log;
#endif /* CONFIG_NRF5340_AUDIO_DK_DISPLAY_TAB_LOG */

display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
if (!device_is_ready(display_dev)) {
LOG_ERR("Display not ready");
return -ENODEV;
}

ret = zbus_chan_add_obs(&le_audio_chan, &le_audio_evt_sub_display, K_MSEC(200));
if (ret) {
LOG_ERR("Failed to add ZBus observer (%d)", ret);
return ret;
}

ret = display_blanking_off(display_dev);
if (ret) {
LOG_ERR("Failed to disable display blanking (%d)", ret);
return ret;
}

tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 50);

tab_menu = lv_tabview_add_tab(tabview, "Menu");
tab_menu_create(tab_menu);

#ifdef CONFIG_NRF5340_AUDIO_DK_DISPLAY_TAB_LOG
tab_log = lv_tabview_add_tab(tabview, "Logging");
tab_log_create(tab_log);
#endif /* CONFIG_NRF5340_AUDIO_DK_DISPLAY_TAB_LOG */

lv_obj_clear_flag(lv_tabview_get_content(tabview), LV_OBJ_FLAG_SCROLLABLE);

display_thread = k_thread_create(&display_data, display_thread_STACK,
K_THREAD_STACK_SIZEOF(display_thread_STACK),
nrf5340_audio_dk_display_update_thread, NULL, NULL, NULL,
K_PRIO_PREEMPT(DISPLAY_THREAD_PRIORITY), 0, K_NO_WAIT);
k_thread_name_set(display_thread, "Nrf5340_audio__dk display thread");

return 0;
}

SYS_INIT(nrf5340_audio_dk_display_init, APPLICATION, DISPLAY_INIT_PRIORITY);
Loading

0 comments on commit ddb0b18

Please sign in to comment.