diff --git a/boards/arm/nucleo_f411re/Kconfig.defconfig b/boards/arm/nucleo_f411re/Kconfig.defconfig index 9cf8ac3c399ae..3950d4e6f6392 100644 --- a/boards/arm/nucleo_f411re/Kconfig.defconfig +++ b/boards/arm/nucleo_f411re/Kconfig.defconfig @@ -34,4 +34,37 @@ config SPI_STM32_INTERRUPT endif # SPI +if I2S + +config I2S_STM32 + default y + +# configure PLLI2S to generate a I2SxCLK=128MHz +config I2S_STM32_USE_PLLI2S_ENABLE + default y + +config I2S_STM32_PLLI2S_PLLM + default 8 + +config I2S_STM32_PLLI2S_PLLN + default 192 + +config I2S_STM32_PLLI2S_PLLR + default 3 + +config I2S_1 + default y + +config USE_STM32_LL_TIM + default y + +endif # I2S + +if DMA + +config DMA_STM32F4X + default y + +endif # DMA + endif # BOARD_NUCLEO_F411RE diff --git a/boards/arm/nucleo_f411re/nucleo_f411re.dts b/boards/arm/nucleo_f411re/nucleo_f411re.dts index 3d22e443f50cc..bf324c63fd883 100644 --- a/boards/arm/nucleo_f411re/nucleo_f411re.dts +++ b/boards/arm/nucleo_f411re/nucleo_f411re.dts @@ -71,6 +71,14 @@ arduino_spi: &spi1 { status = "okay"; }; +arduino_i2s: &i2s1 { + status = "ok"; +}; + +&timers3 { + status = "ok"; +}; + &rtc { status = "okay"; }; diff --git a/boards/arm/nucleo_f411re/pinmux.c b/boards/arm/nucleo_f411re/pinmux.c index ade1a801a48fa..38a6414a00057 100644 --- a/boards/arm/nucleo_f411re/pinmux.c +++ b/boards/arm/nucleo_f411re/pinmux.c @@ -40,6 +40,14 @@ static const struct pin_config pinconf[] = { {STM32_PIN_PA6, STM32F4_PINMUX_FUNC_PA6_SPI1_MISO}, {STM32_PIN_PA7, STM32F4_PINMUX_FUNC_PA7_SPI1_MOSI}, #endif /* CONFIG_SPI_1 */ +#ifdef CONFIG_I2S_1 + {STM32_PIN_PA4, STM32F4_PINMUX_FUNC_PA4_I2S1_WS}, + {STM32_PIN_PA5, STM32F4_PINMUX_FUNC_PA5_I2S1_CK}, + {STM32_PIN_PA7, STM32F4_PINMUX_FUNC_PA7_I2S1_SD}, +#endif /* CONFIG_I2S_1 */ + /* TBD ???? */ + {STM32_PIN_PB4, (STM32_PINMUX_ALT_FUNC_2 | STM32_PUSHPULL_NOPULL | STM32_OSPEEDR_VERY_HIGH_SPEED)}, + {STM32_PIN_PB5, (STM32_PINMUX_ALT_FUNC_2 | STM32_PUSHPULL_NOPULL | STM32_OSPEEDR_VERY_HIGH_SPEED)}, }; static int pinmux_stm32_init(struct device *port) diff --git a/boards/shields/x_nucleo_cca02m1/doc/img/x-nucleo-cca02m1.jpg b/boards/shields/x_nucleo_cca02m1/doc/img/x-nucleo-cca02m1.jpg new file mode 100644 index 0000000000000..0bd3d85e9f410 Binary files /dev/null and b/boards/shields/x_nucleo_cca02m1/doc/img/x-nucleo-cca02m1.jpg differ diff --git a/boards/shields/x_nucleo_cca02m1/doc/index.rst b/boards/shields/x_nucleo_cca02m1/doc/index.rst new file mode 100644 index 0000000000000..9aeaa36b6f9f6 --- /dev/null +++ b/boards/shields/x_nucleo_cca02m1/doc/index.rst @@ -0,0 +1,54 @@ +.. _x-nucleo-cca02m1: + +X-NUCLEO-CCA02M1: Digital MEMS microphones shield for STM32 Nucleo +################################################################## + +Overview +******** +The X-NUCLEO-CCA02M1 is an evaluation board based on digital MEMS microphones +compatible with the ST morpho connector layout. +It has two microphones soldered onto the board and is compatible with digital microphone +coupon boards such as STEVAL-MKI129Vx and STEVAL-MKI155Vx. + +The X-NUCLEO-CCA02M1 allows synchronized acquisition and streaming of up to 4 +microphones through I2S, SPI or DFSDM peripherals. + +.. image:: img/x-nucleo-cca02m1.jpg + :width: 340px + :height: 410px + :align: center + :alt: X-NUCLEO-CCA02M1 + +For more information about the board, see the `X-NUCLEO-CCA02M1 website`_ + +Hardware +******** + +X-NUCLEO-CCA02M1 provides the following key features: + + - 2 x MP34DT01 on-board microphones + - 4 x header (3x2) to connect up to 4 external microphones + - Equipped with ST morpho connector + - Equipped with Arduino UNO R3 connector + - RoHS compliant + + +For more information about this shield, see the `X-NUCLEO-CCA02M1 data brief`_ + +Programming +*********** + +The X-NUCLEO-CCA02M1 can be connected to the SoC through I2S, SPI, or DFSDM peripherals, +but only I2S has been tested in Zephyr using a nucleo_f411re board. + +References +********** + +.. target-notes:: + +.. _X-NUCLEO-CCA02M1 website: + https://www.st.com/en/ecosystems/x-nucleo-cca02m1.html + +.. _X-NUCLEO-CCA02M1 data brief: + https://www.st.com/resource/en/data_brief/x-nucleo-cca02m1.pdf + diff --git a/boards/shields/x_nucleo_cca02m1/x_nucleo_cca02m1.overlay b/boards/shields/x_nucleo_cca02m1/x_nucleo_cca02m1.overlay new file mode 100644 index 0000000000000..9e7338a8ea60c --- /dev/null +++ b/boards/shields/x_nucleo_cca02m1/x_nucleo_cca02m1.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&arduino_i2s { + mp34dt01@0 { + compatible = "st,mpxxdtyy"; + reg = <0>; + label = "MP34DT01"; + }; + + mp34dt01@1 { + compatible = "st,mpxxdtyy"; + reg = <1>; + label = "MP34DT01"; + }; +}; diff --git a/samples/shields/x_nucleo_cca02m1/CMakeLists.txt b/samples/shields/x_nucleo_cca02m1/CMakeLists.txt new file mode 100644 index 0000000000000..9b27d278ac765 --- /dev/null +++ b/samples/shields/x_nucleo_cca02m1/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 +cmake_minimum_required(VERSION 3.13.1) + +# This sample is specific to x_nucleo_cca02m1 shield. Enforce -DSHIELD option +set(SHIELD x_nucleo_cca02m1) + +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(x_nucleo_cca02m1) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/shields/x_nucleo_cca02m1/README.rst b/samples/shields/x_nucleo_cca02m1/README.rst new file mode 100644 index 0000000000000..f0b7f5653a1f7 --- /dev/null +++ b/samples/shields/x_nucleo_cca02m1/README.rst @@ -0,0 +1,141 @@ +.. _x-nucleo-cca02m1-sample: + +X-NUCLEO-CCA02M1: Digital MEMS microphones SHIELD for STM32 Nucleo +################################################################## + +Overview +******** +This sample enables the two digital MEMS microphones on X-NUCLEO-CCA02M1 +shields + +This sample provides an example of how to acquire audio through +the two digital MEMS microphones on X-NUCLEO-CCA02M1 shield. +The microphone generates a PDM stream which is acquired through I2S. +The PDM stream is then converted to PCM using the OpenPDMFilter external +library. + +Requirements +************ + +This sample communicates over I2C with the X-NUCLEO-CCA02M1 shield +stacked on a board with an Arduino connector. The board's I2C must be +configured for the I2C Arduino connector (both for pin muxing +and device tree). See for example the :ref:`nucleo_f411re_board` board +source code: + +- :zephyr_file:`boards/arm/nucleo_f411re/nucleo_f411re.dts` +- :zephyr_file:`boards/arm/nucleo_f411re/pinmux.c` + +References +********** + +- X-NUCLEO-CCA02M1: https://www.st.com/en/ecosystems/x-nucleo-cca02m1.html + +Building and Running +******************** + +This sample runs with X-NUCLEO-CCA02M1 stacked on any board with a matching +Arduino connector. For this example, we use a :ref:`nucleo_f411re_board` board. + +.. zephyr-app-commands:: + :zephyr-app: samples/shields/x_nucleo_cca02m1 + :board: nucleo_f411re + :goals: build + :compact: + +Sample Output +============= + +The example acquires one second of audio and prints out the PCM stream on COM port. +The acquisition starts immediately after the reset button is pressed. + +The characteristics of the PCM audio are hardcoded in the example: + +- 16KHz sample rate +- 16 bits per sample +- 2 channel (stereo) + +One second of acquisition at a 2 channels 16KHz sampling rate yields 32,000 16-bit samples. +The microphone PDM requested clock should lead the MP34DT05 driver to select an +oversampling/decimation factor to result in approximately a 2MHz bit clock. + +See PCM and PDM configuration in file :zephyr_file:`samples/shields/x_nucleo_cca02m1/src/main.c`. + +.. note:: It is possible to change the AUDIO_FREQ to 32000 acquiring only 500 ms. + +At the end of the acquisition the PCM data will be printed on the terminal +emulator in either binary or ASCII format. The output is controlled by the +:c:macro:`PCM_OUTPUT_IN_ASCII` macro, off by default, in +:zephyr_file:`samples/shields/x_nucleo_cca02m1/src/main.c`. + +Binary PCM Output +----------------- + +The Nucleo F411RE board presents itself to the host +as a USB CDC class, and will use ``/dev/ttyACM0`` +device for communication. The ``/dev/ttyACM0`` port +must be configured in raw mode to avoid having +special characters (such as :kbd:`CNTL-Z` or :kbd:`CNTL-D`) +processed or 'cooked' out. + +.. code-block:: console + + stty -F /dev/ttyACM0 115200 raw + cat /dev/ttyACM0 > /tmp/sound.raw + +.. note:: In case the character 0x0a is interpreted as NL and an 0x0d (CR) is added, + you may need to remove it:: + + dos2unix -f /tmp/sound.raw + +ASCII PCM Output +---------------- + +It is also possible to recompile and to have PCM output in ASCII, which needs +to be converted to binary later on. The output format is the following: + +.. code-block:: console + + -- start + 0xfbe0, + 0xfbf0, + 0xfc0c, + 0xfc24, + 0xfc3c, + 0xfc4c, + 0xfc68, + 0xfc48, + + [...] + + 0xfb98, + 0xfb98, + 0xfbb8, + 0xfbac, + 0xfbc4, + 0xfbe8, + 0xfbf4, + -- end + +Play PCM Audio +-------------- + +Now that we have a binary PCM file (say sound.raw), you can use, +for example, the audacity open source editor/player to load and play it. + +Use the 'Import->Raw Data' menu to load the sound.raw file as +signed 16 bit PCM, Little Endian, stereo format @16KHz: + +.. image:: img/audio_import.png + :width: 266px + :height: 287px + :align: center + :alt: audio_import + +After the file is imported you can analyze and play the one second audio file: + +.. image:: img/audio_file.png + :width: 1627px + :height: 505px + :align: center + :alt: audio_file diff --git a/samples/shields/x_nucleo_cca02m1/img/audio_file.png b/samples/shields/x_nucleo_cca02m1/img/audio_file.png new file mode 100644 index 0000000000000..992693f3ea9b5 Binary files /dev/null and b/samples/shields/x_nucleo_cca02m1/img/audio_file.png differ diff --git a/samples/shields/x_nucleo_cca02m1/img/audio_import.png b/samples/shields/x_nucleo_cca02m1/img/audio_import.png new file mode 100644 index 0000000000000..9d35fa5910754 Binary files /dev/null and b/samples/shields/x_nucleo_cca02m1/img/audio_import.png differ diff --git a/samples/shields/x_nucleo_cca02m1/prj.conf b/samples/shields/x_nucleo_cca02m1/prj.conf new file mode 100644 index 0000000000000..72ba1b58e8ed5 --- /dev/null +++ b/samples/shields/x_nucleo_cca02m1/prj.conf @@ -0,0 +1,14 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_PRINTK=y +CONFIG_I2S=y +CONFIG_GPIO=y +CONFIG_AUDIO=y +CONFIG_AUDIO_DMIC=y +CONFIG_AUDIO_MPXXDTYY=y + +# When on-board microphone is used the DMA must run w/o things +# that could slow it down. So DMA logging must be completely +# disabled and DMA interrupts must run at maximum priority. + +CONFIG_DMA=y +CONFIG_DMA_0_IRQ_PRI=0 diff --git a/samples/shields/x_nucleo_cca02m1/sample.yaml b/samples/shields/x_nucleo_cca02m1/sample.yaml new file mode 100644 index 0000000000000..d4c6770b9fb7c --- /dev/null +++ b/samples/shields/x_nucleo_cca02m1/sample.yaml @@ -0,0 +1,7 @@ +sample: + name: X-NUCLEO-CCA02M1 sensor shield +tests: + test: + harness: shield + tags: shield + depends_on: arduino_i2s diff --git a/samples/shields/x_nucleo_cca02m1/src/main.c b/samples/shields/x_nucleo_cca02m1/src/main.c new file mode 100644 index 0000000000000..133a30d48256d --- /dev/null +++ b/samples/shields/x_nucleo_cca02m1/src/main.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2019 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +#include