Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for reading intent ID over I2C slave interface for FFD examples #364

Merged
merged 36 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
bab1dd3
Add first I2C slave calls
lucianomartin Jul 26, 2024
8a3dccb
Fix I2C defines
lucianomartin Jul 29, 2024
ae76aad
Add entry
lucianomartin Jul 29, 2024
9734daf
Merge branch 'develop' of github.com:xmos/sln_voice into feature/ffd_…
lucianomartin Jul 30, 2024
91ce681
Example with I2C control compiles
lucianomartin Jul 31, 2024
269a430
Commands are receivedintent_servicer_read_cmdfff
lucianomartin Aug 1, 2024
8fb0821
Command working with test ID's and external variables
lucianomartin Aug 1, 2024
989027f
Remove device control code
lucianomartin Aug 2, 2024
4f004e2
Remove USB code
lucianomartin Aug 2, 2024
547d4d2
Move code to new files
lucianomartin Aug 2, 2024
d0546a6
Add comments
lucianomartin Aug 2, 2024
8ed9894
Fix typo
lucianomartin Aug 2, 2024
b290aee
Remove masking
lucianomartin Aug 2, 2024
6770435
Fix defines and make code more generic
lucianomartin Aug 7, 2024
a1f111d
Update documentation
lucianomartin Aug 7, 2024
071a3e4
Update variable
lucianomartin Aug 7, 2024
ea9b924
Update test
lucianomartin Aug 8, 2024
2eec481
Fix ASR builds
lucianomartin Aug 8, 2024
4639dd6
Update fwk_rtos
lucianomartin Aug 8, 2024
3c9a001
Tidy up
lucianomartin Aug 8, 2024
29e620c
Fix format
lucianomartin Aug 8, 2024
434f8f0
Update list
lucianomartin Aug 8, 2024
2bd7deb
Fix comments
lucianomartin Aug 9, 2024
c8e1a26
Fix text
lucianomartin Aug 9, 2024
795ac29
Address some comments
lucianomartin Aug 9, 2024
00c99d2
Update doc/programming_guide/ffd/deploying/configuration.rst
lucianomartin Aug 9, 2024
85f7642
Improve defines for I2C and I2S
lucianomartin Aug 9, 2024
2e9197c
Changes for I2S
lucianomartin Aug 9, 2024
7f1b7e4
Fix builds
lucianomartin Aug 9, 2024
a0c54b7
Fix text
lucianomartin Aug 9, 2024
45c1eee
More changes, FFD cyberon builds work
lucianomartin Aug 12, 2024
78be7a2
Disable DAC for I2S input FFD example
lucianomartin Aug 12, 2024
e30e460
Add more info
lucianomartin Aug 14, 2024
2e4c50e
Add missing articles in doc
lucianomartin Aug 15, 2024
b4f31eb
Merge pull request #1 from lucianomartin/feature/i2c_defines
lucianomartin Aug 15, 2024
31d89fc
Remove unused define
lucianomartin Aug 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
60 changes: 56 additions & 4 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 @@ -37,6 +37,21 @@ If options are changed, the application firmware must be rebuilt.
* - appconfINTENT_I2C_OUTPUT_ENABLED
- Enables/disables the |I2C| intent message
- 1
* - appconfI2C_MASTER_ENABLED
- Enables/disables the |I2C| master mode to configure the DAC and send the intent message
- 1
* - appconfINTENT_I2C_OUTPUT_DEVICE_ADDR
- Sets the address of the |I2C| device receiving the intent via the |I2C| master interface
- 0x01
* - appconfI2C_SLAVE_ENABLED
- Enables/disables the |I2C| slave mode to read the device register with the intent message
- 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,43 @@ 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.

The |I2C| master and slave can be enabled or disabled by setting the ``appconfI2C_MASTER_ENABLED`` and ``appconfI2C_SLAVE_ENABLED`` configuration variables.

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

- ``appconfINTENT_I2C_OUTPUT_ENABLED`` to 1.
- ``appconfI2C_MASTER_ENABLED`` to 1.
- ``appconfINTENT_I2C_OUTPUT_DEVICE_ADDR`` to the desired address used by the |I2C| slave device.
- ``appconfI2C_SLAVE_ENABLED`` to 0.

The retrieve the intent message from the host via the |I2C| slave interface, set the following variables:
lucianomartin marked this conversation as resolved.
Show resolved Hide resolved

- ``appconfI2C_SLAVE_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_OUTPUT_ENABLED`` to 0, this will disable the |I2C| master interface.

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 receive the audio data 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:

- ``appconfUSE_I2S_INPUT`` 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.
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_ */
12 changes: 11 additions & 1 deletion examples/ffd/bsp_config/XK_VOICE_L71/platform/platform_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ static void gpio_init(void)

static void i2c_init(void)
{
#if appconfI2C_SLAVE_ENABLED && ON_TILE(I2C_CTRL_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_ENABLED
static rtos_driver_rpc_t i2c_rpc_config;

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

#if ON_TILE(1) && appconfRECOVER_MCLK_I2S_APP_PLL
Expand Down Expand Up @@ -166,7 +176,7 @@ static void mics_init(void)

static void i2s_init(void)
{
#if appconfI2S_ENABLED
#if appconfUSE_I2S_INPUT
#if appconfI2S_MODE == appconfI2S_MODE_MASTER
static rtos_driver_rpc_t i2s_rpc_config;
#endif
Expand Down
27 changes: 25 additions & 2 deletions 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_ENABLED && appconfI2C_MODE == appconfI2C_MODE_MASTER
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 appconfI2C_SLAVE_ENABLED && ON_TILE(I2C_CTRL_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 appconfUSE_I2S_INPUT && appconfI2C_MASTER_ENABLED
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why && appconfI2C_MASTER_ENABLED has been included on this line. The configuration.rst file instructs the reader to set appconfI2C_MASTER_ENABLED to 1 to 'send the intent ID via the |I2C| master interface' and that file doesn't say what value to give to appconfI2C_MASTER_ENABLED if using the I2C slave interface. However, the note in configuration.rst at lines 101-103 states that the I2C master interface will be disabled after configuring the DAC if using the I2C slave interface. Since the DAC configuration has to happen regardless of the I2C mode, doesn't the call to dac3101_init() have to occur in either case?

int ret = 0;
#if ON_TILE(I2C_TILE_NO)
if (dac3101_init(appconfI2S_AUDIO_SAMPLE_RATE) != 0) {
Expand All @@ -74,7 +95,7 @@ static void mics_start(void)

static void i2s_start(void)
{
#if appconfI2S_ENABLED
#if appconfUSE_I2S_INPUT
#if appconfI2S_MODE == appconfI2S_MODE_MASTER
rtos_i2s_rpc_config(i2s_ctx, appconfI2S_RPC_PORT, appconfI2S_RPC_PRIORITY);
#endif
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();
}
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
appconfI2C_SLAVE_ENABLED=1
appconfI2C_MASTER_ENABLED=0
appconfINTENT_I2C_OUTPUT_ENABLED=0
appconfRECOVER_MCLK_I2S_APP_PLL=1
appconfINTENT_UART_DEBUG_INFO_ENABLED=1
appconfAUDIO_PIPELINE_SKIP_IC_AND_VNR=1
Expand Down
29 changes: 25 additions & 4 deletions examples/ffd/src/app_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@
#define appconfINTENT_I2C_OUTPUT_DEVICE_ADDR 0x01
#endif

/* @brief Address for wakeword register to be read over I2C slave*/
#ifndef appconfINTENT_I2C_REG_ADDRESS
#define appconfINTENT_I2C_REG_ADDRESS 0x01
#endif

#ifndef appconfINTENT_UART_OUTPUT_ENABLED
#define appconfINTENT_UART_OUTPUT_ENABLED 1
#endif
Expand All @@ -91,10 +96,6 @@
#define appconfUART_BAUD_RATE 9600
#endif

#ifndef appconfI2S_ENABLED
#define appconfI2S_ENABLED 1
#endif

#ifndef appconfI2S_MODE_MASTER
#define appconfI2S_MODE_MASTER 0
#endif
Expand All @@ -107,6 +108,26 @@
#define appconfI2S_MODE appconfI2S_MODE_MASTER
#endif

#ifndef appconfI2C_MASTER_ENABLED
#define appconfI2C_MASTER_ENABLED 1
#endif

#ifndef appconfI2C_SLAVE_ENABLED
#define appconfI2C_SLAVE_ENABLED 0
#endif

#ifndef appconfI2C_SLAVE_DEVICE_ADDR
#define appconfI2C_SLAVE_DEVICE_ADDR 0x42
#endif

#if appconfINTENT_I2C_OUTPUT_ENABLED && !appconfI2C_MASTER_ENABLED
lucianomartin marked this conversation as resolved.
Show resolved Hide resolved
#error "I2C master must be enabled for intent I2C output"
#endif

#if appconfI2C_SLAVE_ENABLED && appconfINTENT_I2C_OUTPUT_ENABLED
mbanth marked this conversation as resolved.
Show resolved Hide resolved
#error "I2C slave cannot be enabled when intent I2C output over I2C master is enabled"
lucianomartin marked this conversation as resolved.
Show resolved Hide resolved
#endif

#ifndef appconfAUDIO_PIPELINE_SKIP_IC_AND_VNR
#define appconfAUDIO_PIPELINE_SKIP_IC_AND_VNR 0
#endif
Expand Down
41 changes: 41 additions & 0 deletions examples/ffd/src/i2c_reg_handling.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

#include "i2c_reg_handling.h"

/**
* @brief Minimum length for a write request.
*/
#define WRITE_REQUEST_MIN_LEN 1

RTOS_I2C_SLAVE_CALLBACK_ATTR
size_t read_device_reg(rtos_i2c_slave_t *ctx,
asr_result_t *last_asr_result,
uint8_t **data)
{
#if appconfI2C_SLAVE_ENABLED==1
uint8_t * data_p = *data;
uint8_t reg_addr = data_p[0];
uint8_t reg_value = 0xFF;
if (reg_addr == appconfINTENT_I2C_REG_ADDRESS) {
reg_value = last_asr_result->id;
}
data_p[0] = reg_value;
rtos_printf("Read from register 0x%02X value 0x%02X\n", reg_addr, reg_value);
#endif
return 1;
}

RTOS_I2C_SLAVE_CALLBACK_ATTR
void write_device_reg(rtos_i2c_slave_t *ctx,
void *app_data,
uint8_t *data,
size_t len)
{
#if appconfI2C_SLAVE_ENABLED==1
// If the length is lower than WRITE_REQUEST_MIN_LEN, it is a read request
if (len > WRITE_REQUEST_MIN_LEN) {
rtos_printf("Write to register 0x%02X value 0x%02X (len %d)\n", data[0], data[1], len);
}
#endif
}
Loading
Loading