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

drivers/audio: Add support for the ES8311 codec #9189

Merged
merged 5 commits into from May 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -602,7 +602,7 @@ The ``nxlooper`` application captures data from the audio device with receiving
capabilities (the I2S1 on this example) and forwards the audio data frame to
the audio device with transmitting capabilities (the I2S0 on this example).

After successfully built and flashed, run on the boards's terminal::
After successfully built and flashed, run on the boards' terminal::

nsh> nxlooper
nxlooper> loopback
Expand Down
Expand Up @@ -180,11 +180,41 @@ Configurations
All of the configurations presented below can be tested by running the following commands::

$ ./tools/configure.sh esp32s2-kaluga-1:<config_name>
$ make flash ESPTOOL_PORT=/dev/ttyUSB0 -j
$ make flash ESPTOOL_PORT=/dev/ttyUSB1 -j

Where <config_name> is the name of board configuration you want to use, i.e.: nsh, buttons, wifi...
Then use a serial console terminal like ``picocom`` configured to 115200 8N1.

audio
-----

This configuration uses the I2S peripheral and the ES8311 audio
codec to play an audio file. The easiest way of playing an uncompressed file
is embedding into the firmware. This configuration selects
`romfs example <https://github.com/apache/nuttx-apps/tree/master/examples/romfs>`__
to allow that.

**ROMFS example**

Prepare and build the ``audio`` defconfig::

$ make -j distclean && ./tools/configure.sh esp32s2-kaluga-1:audio && make

This will create a temporary folder in ``apps/examples/romfs/testdir``. Move
a PCM-encoded (``.wav``) audio file with 16 or 24 bits/sample (sampled at 16~48kHz)
to this folder.

.. note:: You can use :download:`this 440 Hz sinusoidal tone <tone.wav>`.
The audio file should be located at ``apps/examples/romfs/testdir/tone.wav``

Build the project again and flash it (make sure not to clean it, just build)

After successfully built and flashed, load the romfs and play it::

nsh> romfs
nsh> nxplayer
nxplayer> play /usr/share/local/tone.wav

buttons
-------

Expand All @@ -210,6 +240,14 @@ the ``buttons`` application and pressing on any of the available board buttons a
Sample = 64
Sample = 0

i2c
---

This configuration can be used to scan and manipulate I2C devices.
You can scan for all I2C devices using the following command::

nsh> i2c dev 0x00 0x7f

lvgl_ili9341
------------

Expand All @@ -219,8 +257,8 @@ driver with the ILI9341 display. You can find LVGL here::
https://www.lvgl.io/
https://github.com/lvgl/lvgl

This configuration uses the LVGL demonstration at `apps/examples/lvgldemo` and
can be executed by running the `lvgldemo` application.
This configuration uses the LVGL demonstration at ``apps/examples/lvgldemo`` and
can be executed by running the ``lvgldemo`` application.

lvgl_st7789
-----------
Expand All @@ -231,11 +269,30 @@ driver with the ST7799 display. You can find LVGL here::
https://www.lvgl.io/
https://github.com/lvgl/lvgl

This configuration uses the LVGL demonstration at `apps/examples/lvgldemo` and
can be executed by running the `lvgldemo` application.
This configuration uses the LVGL demonstration at ``apps/examples/lvgldemo`` and
can be executed by running the ``lvgldemo`` application.

nsh
---

Basic NuttShell configuration (console enabled in UART0, exposed via
USB connection by means of CP2102 converter, at 115200 bps).
USB connection by means of CP2102 converter, at 115200 bps).

nxlooper
--------

The ``nxlooper`` application captures data from the audio device with receiving
capabilities and forwards the audio data frame to the audio device with transmitting
capabilities.

After successfully built and flashed, run on the boards' terminal::

nsh> nxlooper
nxlooper> loopback

.. note:: ``loopback`` command default arguments for the channel configuration,
the data width and the sample rate are, respectively, 2 channels,
16 bits/sample and 48KHz. These arguments can be supplied to select
different audio formats, for instance::

nxlooper> loopback 2 8 44100
45 changes: 35 additions & 10 deletions arch/xtensa/src/esp32/esp32_i2s.c
Expand Up @@ -339,7 +339,9 @@ static void i2s_rx_schedule(struct esp32_i2s_s *priv,

static uint32_t i2s_set_datawidth(struct esp32_i2s_s *priv);
static uint32_t i2s_set_clock(struct esp32_i2s_s *priv);
static uint32_t i2s_mclkfrequency(struct i2s_dev_s *dev, uint32_t frequency);
static uint32_t i2s_getmclkfrequency(struct i2s_dev_s *dev);
static uint32_t i2s_setmclkfrequency(struct i2s_dev_s *dev,
uint32_t frequency);
static int i2s_ioctl(struct i2s_dev_s *dev, int cmd, unsigned long arg);

#ifdef I2S_HAVE_TX
Expand Down Expand Up @@ -385,7 +387,8 @@ static const struct i2s_ops_s g_i2sops =
#endif /* I2S_HAVE_RX */

.i2s_ioctl = i2s_ioctl,
.i2s_mclkfrequency = i2s_mclkfrequency,
.i2s_getmclkfrequency = i2s_getmclkfrequency,
.i2s_setmclkfrequency = i2s_setmclkfrequency,
};

#ifdef CONFIG_ESP32_I2S0
Expand Down Expand Up @@ -1654,7 +1657,7 @@ static void i2s_configure(struct esp32_i2s_s *priv)
* by the number of bytes from a sample, i.e, for 24 bits, the
* multiplier should be divisible by 3. NOTE: the MCLK frequency can
* be adjusted on runtime, so this value remains valid only if the
* upper half does not implement the `i2s_mclkfrequency` method.
* upper half does not implement the `i2s_setmclkfrequency` method.
*/

if (priv->config->data_width == I2S_DATA_BIT_WIDTH_24BIT)
Expand All @@ -1666,8 +1669,8 @@ static void i2s_configure(struct esp32_i2s_s *priv)
priv->mclk_multiple = I2S_MCLK_MULTIPLE_256;
}

i2s_mclkfrequency((struct i2s_dev_s *)priv, (priv->config->rate *
priv->mclk_multiple));
i2s_setmclkfrequency((struct i2s_dev_s *)priv, (priv->config->rate *
priv->mclk_multiple));

priv->rate = priv->config->rate;
i2s_set_clock(priv);
Expand Down Expand Up @@ -1774,7 +1777,7 @@ static void i2s_configure(struct esp32_i2s_s *priv)
* by the number of bytes from a sample, i.e, for 24 bits, the
* multiplier should be divisible by 3. NOTE: the MCLK frequency can
* be adjusted on runtime, so this value remains valid only if the
* upper half does not implement the `i2s_mclkfrequency` method.
* upper half does not implement the `i2s_setmclkfrequency` method.
*/

if (priv->config->data_width == I2S_DATA_BIT_WIDTH_24BIT)
Expand All @@ -1786,8 +1789,8 @@ static void i2s_configure(struct esp32_i2s_s *priv)
priv->mclk_multiple = I2S_MCLK_MULTIPLE_256;
}

i2s_mclkfrequency((struct i2s_dev_s *)priv, (priv->config->rate *
priv->mclk_multiple));
i2s_setmclkfrequency((struct i2s_dev_s *)priv, (priv->config->rate *
priv->mclk_multiple));

priv->rate = priv->config->rate;
i2s_set_clock(priv);
Expand Down Expand Up @@ -2305,7 +2308,28 @@ static int i2s_interrupt(int irq, void *context, void *arg)
}

/****************************************************************************
* Name: i2s_mclkfrequency
* Name: i2s_getmclkfrequency
*
* Description:
* Get the current master clock frequency.
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* Returns the current master clock.
*
****************************************************************************/

static uint32_t i2s_getmclkfrequency(struct i2s_dev_s *dev)
{
struct esp32_i2s_s *priv = (struct esp32_i2s_s *)dev;

return priv->mclk_freq;
}

/****************************************************************************
* Name: i2s_setmclkfrequency
*
* Description:
* Set the master clock frequency. Usually, the MCLK is a multiple of the
Expand All @@ -2321,7 +2345,8 @@ static int i2s_interrupt(int irq, void *context, void *arg)
*
****************************************************************************/

static uint32_t i2s_mclkfrequency(struct i2s_dev_s *dev, uint32_t frequency)
static uint32_t i2s_setmclkfrequency(struct i2s_dev_s *dev,
uint32_t frequency)
{
struct esp32_i2s_s *priv = (struct esp32_i2s_s *)dev;

Expand Down
45 changes: 35 additions & 10 deletions arch/xtensa/src/esp32s2/esp32s2_i2s.c
Expand Up @@ -323,7 +323,9 @@ static void i2s_rx_schedule(struct esp32s2_i2s_s *priv,

static uint32_t i2s_set_datawidth(struct esp32s2_i2s_s *priv);
static uint32_t i2s_set_clock(struct esp32s2_i2s_s *priv);
static uint32_t i2s_mclkfrequency(struct i2s_dev_s *dev, uint32_t frequency);
static uint32_t i2s_getmclkfrequency(struct i2s_dev_s *dev);
static uint32_t i2s_setmclkfrequency(struct i2s_dev_s *dev,
uint32_t frequency);
static int i2s_ioctl(struct i2s_dev_s *dev, int cmd, unsigned long arg);

#ifdef I2S_HAVE_TX
Expand Down Expand Up @@ -369,7 +371,8 @@ static const struct i2s_ops_s g_i2sops =
#endif /* I2S_HAVE_RX */

.i2s_ioctl = i2s_ioctl,
.i2s_mclkfrequency = i2s_mclkfrequency,
.i2s_getmclkfrequency = i2s_getmclkfrequency,
.i2s_setmclkfrequency = i2s_setmclkfrequency,
};

#ifdef CONFIG_ESP32S2_I2S
Expand Down Expand Up @@ -1455,7 +1458,7 @@ static void i2s_configure(struct esp32s2_i2s_s *priv)
* by the number of bytes from a sample, i.e, for 24 bits, the
* multiplier should be divisible by 3. NOTE: the MCLK frequency can
* be adjusted on runtime, so this value remains valid only if the
* upper half does not implement the `i2s_mclkfrequency` method.
* upper half does not implement the `i2s_setmclkfrequency` method.
*/

if (priv->config->data_width == I2S_DATA_BIT_WIDTH_24BIT)
Expand All @@ -1467,8 +1470,8 @@ static void i2s_configure(struct esp32s2_i2s_s *priv)
priv->mclk_multiple = I2S_MCLK_MULTIPLE_256;
}

i2s_mclkfrequency((struct i2s_dev_s *)priv, (priv->config->rate *
priv->mclk_multiple));
i2s_setmclkfrequency((struct i2s_dev_s *)priv, (priv->config->rate *
priv->mclk_multiple));

priv->rate = priv->config->rate;
i2s_set_clock(priv);
Expand Down Expand Up @@ -1556,7 +1559,7 @@ static void i2s_configure(struct esp32s2_i2s_s *priv)
* by the number of bytes from a sample, i.e, for 24 bits, the
* multiplier should be divisible by 3. NOTE: the MCLK frequency can
* be adjusted on runtime, so this value remains valid only if the
* upper half does not implement the `i2s_mclkfrequency` method.
* upper half does not implement the `i2s_setmclkfrequency` method.
*/

if (priv->config->data_width == I2S_DATA_BIT_WIDTH_24BIT)
Expand All @@ -1568,8 +1571,8 @@ static void i2s_configure(struct esp32s2_i2s_s *priv)
priv->mclk_multiple = I2S_MCLK_MULTIPLE_256;
}

i2s_mclkfrequency((struct i2s_dev_s *)priv, (priv->config->rate *
priv->mclk_multiple));
i2s_setmclkfrequency((struct i2s_dev_s *)priv, (priv->config->rate *
priv->mclk_multiple));

priv->rate = priv->config->rate;
i2s_set_clock(priv);
Expand Down Expand Up @@ -2054,7 +2057,28 @@ static int i2s_interrupt(int irq, void *context, void *arg)
}

/****************************************************************************
* Name: i2s_mclkfrequency
* Name: i2s_getmclkfrequency
*
* Description:
* Get the current master clock frequency.
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* Returns the current master clock.
*
****************************************************************************/

static uint32_t i2s_getmclkfrequency(struct i2s_dev_s *dev)
{
struct esp32s2_i2s_s *priv = (struct esp32s2_i2s_s *)dev;

return priv->mclk_freq;
}

/****************************************************************************
* Name: i2s_setmclkfrequency
*
* Description:
* Set the master clock frequency. Usually, the MCLK is a multiple of the
Expand All @@ -2070,7 +2094,8 @@ static int i2s_interrupt(int irq, void *context, void *arg)
*
****************************************************************************/

static uint32_t i2s_mclkfrequency(struct i2s_dev_s *dev, uint32_t frequency)
static uint32_t i2s_setmclkfrequency(struct i2s_dev_s *dev,
uint32_t frequency)
{
struct esp32s2_i2s_s *priv = (struct esp32s2_i2s_s *)dev;

Expand Down
4 changes: 2 additions & 2 deletions arch/xtensa/src/esp32s2/esp32s2_spiram.c
Expand Up @@ -257,8 +257,8 @@ bool esp_spiram_test(void)

if (errct < 4)
{
merr("SPI SRAM error @ %08x:%08x/%08x \n", &spiram[p],
spiram[p], p ^ 0xaaaaaaaa);
merr("SPI SRAM error @ %p:%08x/%08x \n",
&spiram[p], spiram[p], p ^ 0xaaaaaaaa);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions arch/xtensa/src/esp32s2/hardware/esp32s2_soc.h
Expand Up @@ -28,6 +28,7 @@
#include <stdint.h>
#include <stdbool.h>

#include "xtensa.h"
#include "xtensa_attr.h"

/****************************************************************************
Expand Down