Skip to content

Commit

Permalink
Merge pull request #364 from lucianomartin/feature/ffd_i2c_slave
Browse files Browse the repository at this point in the history
Add support for reading intent ID over I2C slave interface for FFD examples
  • Loading branch information
lucianomartin authored Aug 19, 2024
2 parents 895f03c + 31d89fc commit 06bf254
Show file tree
Hide file tree
Showing 33 changed files with 303 additions and 78 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ XCORE-VOICE change log
* ADDED: Support for DFU over I2C for FFVA INT example.
* ADDED: FFD example with I2S audio input to Cyberon speech recognition
engine and model.
* CHANGED: Updated submodule fwk_rtos to version 3.1.0 from 3.0.5.
* ADDED: lib_sw_pll submodule v1.1.0.
* REMOVED: flash settings in .xn files, as they are not required by XMOS
Tools 15.2.x.
* ADDED: Support for reading registers over I2C slave in FFD examples.
* CHANGED: Updated submodule fwk_rtos to version 3.2.0 from 3.0.5.
* ADDED: lib_sw_pll submodule v1.1.0.

2.2.0
-----
Expand Down
63 changes: 57 additions & 6 deletions doc/programming_guide/ffd/deploying/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Configuring the Firmware
========================

The default application performs as described in the :ref:`sln_voice_ffd_overview`. There are numerous compile time options that can be added to change the example design without requiring code changes. To change the options explained in the table below, add the desired configuration variables to the APP_COMPILE_DEFINITIONS cmake variable located `here <https://github.com/xmos/sln_voice/blob/develop/examples/ffd/ffd.cmake>`_.
The default application performs as described in the :ref:`sln_voice_ffd_overview`. There are numerous compile time options that can be added to change the example design without requiring code changes. To change the options explained in the table below, add the desired configuration variables to the APP_COMPILE_DEFINITIONS cmake variable in the ``.cmake`` file located in the ``examples/ffd/`` folder.

If options are changed, the application firmware must be rebuilt.

Expand Down Expand Up @@ -34,9 +34,24 @@ If options are changed, the application firmware must be rebuilt.
* - appconfINTENT_UART_DEBUG_INFO_ENABLED
- Enables/disables the UART intent debug information
- 0
* - appconfINTENT_I2C_OUTPUT_ENABLED
- Enables/disables the |I2C| intent message
* - appconfI2C_MASTER_DAC_ENABLED
- Enables/disables configuring the DAC over |I2C| master
- 1
* - appconfINTENT_I2C_MASTER_OUTPUT_ENABLED
- Enables/disables sending the intent message over |I2C| master
- 1
* - appconfINTENT_I2C_MASTER_DEVICE_ADDR
- Sets the address of the |I2C| device receiving the intent via the |I2C| master interface
- 0x01
* - appconfINTENT_I2C_SLAVE_POLLED_ENABLED
- Enables/disables allowing another device to poll the intent message via |I2C| slave
- 0
* - appconfI2C_SLAVE_DEVICE_ADDR
- Sets the address of the |I2C| device receiving the intent via the |I2C| slave interface
- 0x42
* - appconfINTENT_I2C_REG_ADDRESS
- Sets the address of the |I2C| register to store the intent message, this value can be read via the |I2C| slave interface
- 0x01
* - appconfUART_BAUD_RATE
- Sets the baud rate for the UART tx intent interface
- 9600
Expand All @@ -52,9 +67,6 @@ If options are changed, the application firmware must be rebuilt.
* - appconfRECOVER_MCLK_I2S_APP_PLL
- Enables/disables the recovery of the MCLK from the Software PLL application; this removes the need to use an external MCLK.
- 0
* - appconfINTENT_I2C_OUTPUT_DEVICE_ADDR
- Sets the |I2C| slave address to transmit the intent to
- 0x01
* - appconfINTENT_TRANSPORT_DELAY_MS
- Sets the delay between host wake up requested and |I2C| and UART keyword code transmission
- 50
Expand All @@ -78,3 +90,42 @@ If options are changed, the application firmware must be rebuilt.

The ``example_ffd_i2s_input_cyberon`` has different default values from the ones in the table above.
The list of updated values can be found in the ``APP_COMPILE_DEFINITIONS`` list in ``examples\ffd\ffd_i2s_input_cyberon.cmake``.

Configuring the |I2C| interfaces
--------------------------------

The |I2C| interfaces are used to configure the DAC and to communicate with the host. The |I2C| interface can be configured as a master or a slave.
The DAC must be configured at bootup via the |I2C| master interface.
The |I2C| master is used when the FFD example asynchronously sends intent messages to the host. The |I2C| slave is used when the host wants to read intent messages from the FFD example through polling.

.. note::
The |I2C| interface cannot operate as both master and slave simultaneously. The FFD example design uses the |I2C| master interface to configure the DAC at device initialisation.
However, if the host reads intent messages from the FFD example using the |I2C| slave interface, the |I2C| master interface will be disabled after the DAC configuration is complete.

To send the intent ID via the |I2C| master interface when a command is detected, set the following variables:

- ``appconfINTENT_I2C_MASTER_OUTPUT_ENABLED`` to 1.
- ``appconfINTENT_I2C_MASTER_DEVICE_ADDR`` to the desired address used by the |I2C| slave device.
- ``appconfINTENT_I2C_SLAVE_POLLED_ENABLED`` to 0, this will disable the |I2C| slave interface.

To configure the FFD example so that the host can poll for the intent via the |I2C| slave interface, set the following variables:

- ``appconfINTENT_I2C_SLAVE_POLLED_ENABLED`` to 1.
- ``appconfI2C_SLAVE_DEVICE_ADDR`` to the desired address used by the |I2C| master device.
- ``appconfINTENT_I2C_REG_ADDRESS`` to the desired register read by the |I2C| master device.
- ``appconfINTENT_I2C_MASTER_OUTPUT_ENABLED`` to 0, this will disable the |I2C| master interface after initialization.

The handling of the |I2C| slave registers is done in the ``examples\ffd\src\i2c_reg_handling.c`` file. The variable ``appconfINTENT_I2C_REG_ADDRESS`` is used in the callback function ``read_device_reg()``.

Configuring the |I2S| interface
-------------------------------

The |I2S| interface is used to play the audio command response to the DAC, and/or to receive the audio samples from the host. The |I2S| interface can be configured as either a master or a slave.
To configure the |I2S| interface, set the following variables:

- ``appconfI2S_ENABLED`` to 1.
- ``appconfI2S_MODE`` to the desired mode, either ``appconfI2S_MODE_MASTER`` or ``appconfI2S_MODE_SLAVE``.
- ``appconfI2S_AUDIO_SAMPLE_RATE`` to the desired sample rate, either 16000 or 48000.
- ``appconfRECOVER_MCLK_I2S_APP_PLL`` to 1 if an external MCLK is not available, otherwise set it to 0.
- ``appconfAUDIO_PLAYBACK_ENABLED`` to 1, if the intent audio is to be played back.
- ``appconfUSE_I2S_INPUT`` to 1, if the |I2S| audio source is to be used instead of the microphone array audio source.
7 changes: 7 additions & 0 deletions doc/programming_guide/ffd/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ The examples using the microphone array as the audio source include an audio pip
#. Noise Suppressor (NS)
#. Adaptive Gain Control (AGC)

The FFD examples provide several options to inform the host of a possible intent detected by the intent engine. The device can notify the host by:

- sending the intent ID over a UART interface upon detecting the intent
- sending the intent ID over an |I2C| master interface upon detecting the intent
- allowing the host to poll the last detected intent ID over the |I2C| slave interface
- listening to an audio message over an |I2S| interface

When a wakeword phrase is detected followed by a command phrase, the application will output an audio response and a discrete message over |I2C| and UART.

Sensory's THF and Cyberon's DSpotter™ libraries ship with an expiring development license. The Sensory one will suspend recognition after 11.4 hours or 107 recognition events, and the Cyberon one will suspend recognition after 100 recognition events. After the maximum number of recognitions is reached, a device reset is required to resume normal operation. To perform a reset, either power cycle the device or press the SW2 button.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ If options are changed, the application firmware must be rebuilt.
* - appconfINTENT_UART_OUTPUT_ENABLED
- Enables/disables the UART intent message
- 1
* - appconfINTENT_I2C_OUTPUT_ENABLED
- Enables/disables the |I2C| intent message
* - appconfINTENT_I2C_MASTER_OUTPUT_ENABLED
- Enables/disables sending the intent message over |I2C| master
- 1
* - appconfUART_BAUD_RATE
- Sets the baud rate for the UART tx intent interface
- 9600
* - appconfINTENT_I2C_OUTPUT_DEVICE_ADDR
* - appconfINTENT_I2C_MASTER_DEVICE_ADDR
- Sets the |I2C| slave address to transmit the intent to
- 0x01
* - appconfINTENT_TRANSPORT_DELAY_MS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ rtos_i2c_master_t *i2c_master_ctx = &i2c_master_ctx_s;
static rtos_i2s_t i2s_ctx_s;
rtos_i2s_t *i2s_ctx = &i2s_ctx_s;

static rtos_i2c_slave_t i2c_slave_ctx_s;
rtos_i2c_slave_t *i2c_slave_ctx = &i2c_slave_ctx_s;

static rtos_uart_tx_t uart_tx_ctx_s;
rtos_uart_tx_t *uart_tx_ctx = &uart_tx_ctx_s;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extern "C" {
#include "rtos_qspi_flash.h"
#include "rtos_gpio.h"
#include "rtos_i2c_master.h"
#include "rtos_i2c_slave.h"
#include "rtos_i2s.h"
#include "rtos_uart_tx.h"

Expand All @@ -31,6 +32,7 @@ extern "C" {
/* Tile specifiers */
#define FLASH_TILE_NO 0
#define I2C_TILE_NO 0
#define I2C_CTRL_TILE_NO I2C_TILE_NO
#define MICARRAY_TILE_NO 1
#define I2S_TILE_NO 1
#define UART_TILE_NO 0
Expand Down Expand Up @@ -59,6 +61,7 @@ extern rtos_gpio_t *gpio_ctx_t0;
extern rtos_gpio_t *gpio_ctx_t1;
extern rtos_mic_array_t *mic_array_ctx;
extern rtos_i2c_master_t *i2c_master_ctx;
extern rtos_i2c_slave_t *i2c_slave_ctx;
extern rtos_i2s_t *i2s_ctx;
extern rtos_uart_tx_t *uart_tx_ctx;

Expand Down
14 changes: 13 additions & 1 deletion examples/ffd/bsp_config/XK_VOICE_L71/platform/platform_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@
#define appconfI2S_IO_CORE 2 /* Must be kept off core 0 with the RTOS tick ISR */
#endif /* appconfI2S_IO_CORE */

#ifndef appconfI2C_IO_CORE
#define appconfI2C_IO_CORE 3 /* Must be kept off core 0 with the RTOS tick ISR */
#endif /* appconfI2C_IO_CORE */

#ifndef appconfI2C_INTERRUPT_CORE
#define appconfI2C_INTERRUPT_CORE 0 /* Must be kept off I/O cores. */
#endif /* appconfI2C_INTERRUPT_CORE */

#ifndef appconfPDM_MIC_INTERRUPT_CORE
#define appconfPDM_MIC_INTERRUPT_CORE 3 /* Must be kept off I/O cores. Best kept off core 0 with the tick ISR. */
#endif /* appconfPDM_MIC_INTERRUPT_CORE */
Expand Down Expand Up @@ -81,7 +89,11 @@
/* I/O Task Priorities */
/*****************************************/
#ifndef appconfQSPI_FLASH_TASK_PRIORITY
#define appconfQSPI_FLASH_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define appconfQSPI_FLASH_TASK_PRIORITY (configMAX_PRIORITIES-1)
#endif /* appconfQSPI_FLASH_TASK_PRIORITY */

#ifndef appconfI2C_TASK_PRIORITY
#define appconfI2C_TASK_PRIORITY (configMAX_PRIORITIES/2)
#endif /* appconfI2C_TASK_PRIORITY */

#endif /* PLATFORM_CONF_H_ */
18 changes: 14 additions & 4 deletions examples/ffd/bsp_config/XK_VOICE_L71/platform/platform_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

static void mclk_init(chanend_t other_tile_c)
{
#if ON_TILE(1)
#if ON_TILE(I2S_TILE_NO)
app_pll_init();
#endif
}
Expand Down Expand Up @@ -54,7 +54,7 @@ static void gpio_init(void)
intertile_ctx);
#endif

#if ON_TILE(1)
#if ON_TILE(I2S_TILE_NO)
rtos_gpio_init(gpio_ctx_t1);

rtos_gpio_rpc_client_init(
Expand All @@ -72,6 +72,15 @@ static void gpio_init(void)

static void i2c_init(void)
{
#if appconfINTENT_I2C_SLAVE_POLLED_ENABLED && ON_TILE(I2C_TILE_NO)
rtos_i2c_slave_init(i2c_slave_ctx,
(1 << appconfI2C_IO_CORE),
PORT_I2C_SCL,
PORT_I2C_SDA,
appconfI2C_SLAVE_DEVICE_ADDR);
#endif

#if appconfI2C_MASTER_DAC_ENABLED || appconfINTENT_I2C_MASTER_OUTPUT_ENABLED
static rtos_driver_rpc_t i2c_rpc_config;

#if ON_TILE(I2C_TILE_NO)
Expand All @@ -94,9 +103,10 @@ static void i2c_init(void)
&i2c_rpc_config,
intertile_ctx);
#endif
#endif
}

#if ON_TILE(1) && appconfRECOVER_MCLK_I2S_APP_PLL
#if ON_TILE(I2S_TILE_NO) && appconfRECOVER_MCLK_I2S_APP_PLL
static int *p_lock_status = NULL;
/// @brief Save the pointer to the pll lock_status variable
static void set_pll_lock_status_ptr(int* p)
Expand All @@ -107,7 +117,7 @@ static void set_pll_lock_status_ptr(int* p)

static void platform_sw_pll_init(void)
{
#if ON_TILE(1) && appconfRECOVER_MCLK_I2S_APP_PLL
#if ON_TILE(I2S_TILE_NO) && appconfRECOVER_MCLK_I2S_APP_PLL

port_t p_bclk = PORT_I2S_BCLK;
port_t p_mclk = PORT_MCLK;
Expand Down
25 changes: 24 additions & 1 deletion examples/ffd/bsp_config/XK_VOICE_L71/platform/platform_start.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#include "platform_conf.h"
#include "platform/driver_instances.h"
#include "dac3101.h"
#include "i2c_reg_handling.h"

extern asr_result_t last_asr_result;

extern void i2s_rate_conversion_enable(void);

Expand All @@ -39,16 +42,34 @@ static void flash_start(void)

static void i2c_master_start(void)
{
#if appconfI2C_MASTER_DAC_ENABLED || appconfINTENT_I2C_MASTER_OUTPUT_ENABLED
rtos_i2c_master_rpc_config(i2c_master_ctx, appconfI2C_MASTER_RPC_PORT, appconfI2C_MASTER_RPC_PRIORITY);

#if ON_TILE(I2C_TILE_NO)
rtos_i2c_master_start(i2c_master_ctx);
#endif
#endif
}

static void i2c_slave_start(void)
{
#if appconfINTENT_I2C_SLAVE_POLLED_ENABLED && ON_TILE(I2C_TILE_NO)
rtos_i2c_slave_start(i2c_slave_ctx,
&last_asr_result,
(rtos_i2c_slave_start_cb_t) NULL,
(rtos_i2c_slave_rx_cb_t) write_device_reg,
(rtos_i2c_slave_tx_start_cb_t) read_device_reg,
(rtos_i2c_slave_tx_done_cb_t) NULL,
NULL,
NULL,
appconfI2C_INTERRUPT_CORE,
appconfI2C_TASK_PRIORITY);
#endif
}

static void audio_codec_start(void)
{
#if appconfI2S_ENABLED
#if appconfI2S_ENABLED && appconfI2C_MASTER_DAC_ENABLED
int ret = 0;
#if ON_TILE(I2C_TILE_NO)
if (dac3101_init(appconfI2S_AUDIO_SAMPLE_RATE) != 0) {
Expand Down Expand Up @@ -114,4 +135,6 @@ void platform_start(void)
mics_start();
i2s_start();
uart_start();
// I2C slave can be started only after i2c_master_start() is completed
i2c_slave_start();
}
2 changes: 2 additions & 0 deletions examples/ffd/ffd_cyberon.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ set(APP_COMMON_LINK_LIBRARIES
sln_voice::app::asr::intent_engine
sln_voice::app::asr::intent_handler
sln_voice::app::ffd::xk_voice_l71
lib_src
lib_sw_pll
)

#**********************
Expand Down
5 changes: 4 additions & 1 deletion examples/ffd/ffd_i2s_input_cyberon.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ file(GLOB_RECURSE APP_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/*.c )

set(APP_INCLUDES
${CMAKE_CURRENT_LIST_DIR}/src
${CMAKE_CURRENT_LIST_DIR}/src/control
${CMAKE_CURRENT_LIST_DIR}/src/gpio_ctrl
${CMAKE_CURRENT_LIST_DIR}/src/intent_engine
${CMAKE_CURRENT_LIST_DIR}/src/power
Expand Down Expand Up @@ -79,7 +80,9 @@ set(APP_COMPILE_DEFINITIONS
appconfAUDIO_PLAYBACK_ENABLED=1
appconfI2S_MODE=appconfI2S_MODE_SLAVE
appconfI2S_AUDIO_SAMPLE_RATE=48000
appconfI2S_ENABLED=1
appconfINTENT_I2C_SLAVE_POLLED_ENABLED=1
appconfINTENT_I2C_MASTER_OUTPUT_ENABLED=0
appconfI2C_MASTER_DAC_ENABLED=0
appconfRECOVER_MCLK_I2S_APP_PLL=1
appconfINTENT_UART_DEBUG_INFO_ENABLED=1
appconfAUDIO_PIPELINE_SKIP_IC_AND_VNR=1
Expand Down
2 changes: 2 additions & 0 deletions examples/ffd/ffd_sensory.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ set(APP_COMMON_LINK_LIBRARIES
sln_voice::app::asr::intent_engine
sln_voice::app::asr::intent_handler
sln_voice::app::ffd::xk_voice_l71
lib_src
lib_sw_pll
)

#**********************
Expand Down
Loading

0 comments on commit 06bf254

Please sign in to comment.