diff --git a/amy/constants.py b/amy/constants.py index e1be32b5..976537e2 100644 --- a/amy/constants.py +++ b/amy/constants.py @@ -19,6 +19,7 @@ AMY_BUS_AUDIO_IN=2 AMY_MAX_CORES=2 AMY_MAX_CHANNELS=2 +AMY_NCHANS=1 AMY_NCHANS=2 AMY_CORES=2 AMY_CORES=1 diff --git a/src/amy.h b/src/amy.h index 071a280b..ab5bb81e 100644 --- a/src/amy.h +++ b/src/amy.h @@ -70,12 +70,14 @@ extern const uint32_t pcm_wavetable_len; #define BLOCK_SIZE_BITS 8 // log2 of BLOCK_SIZE #endif +#ifndef AMY_SAMPLE_RATE #ifdef AMY_DAISY #define AMY_SAMPLE_RATE 48000 #elif defined __EMSCRIPTEN__ #define AMY_SAMPLE_RATE 48000 #else -#define AMY_SAMPLE_RATE 44100 +#define AMY_SAMPLE_RATE 44100 +#endif #endif #define PCM_AMY_SAMPLE_RATE 22050 @@ -105,8 +107,16 @@ extern const uint32_t pcm_wavetable_len; #define AMY_MAX_CORES 2 #define AMY_MAX_CHANNELS 2 -// Always use 2 channels. Clients that want mono can deinterleave +// Default to 2 channels. Constrained MCUs (e.g. ESP32-C3, single-core RISC-V) +// default to mono; override with -DAMY_NCHANS=N. +// Note: i2s.c picks the I2S slot mode based on this value. +#ifndef AMY_NCHANS +#if defined(CONFIG_IDF_TARGET_ESP32C3) +#define AMY_NCHANS 1 +#else #define AMY_NCHANS 2 +#endif +#endif // Use dual cores on supported platforms diff --git a/src/i2s.c b/src/i2s.c index ac5797f7..73c2b206 100644 --- a/src/i2s.c +++ b/src/i2s.c @@ -14,6 +14,13 @@ #ifdef ESP_PLATFORM #include +// I2S slot mode follows AMY_NCHANS so a mono build produces a mono I2S frame. +#if AMY_NCHANS == 1 +#define AMY_I2S_SLOT_MODE I2S_SLOT_MODE_MONO +#else +#define AMY_I2S_SLOT_MODE I2S_SLOT_MODE_STEREO +#endif + /////////////////////////////////////////////////////////////// // ESP32, S3, P4 (maybe others) @@ -79,7 +86,7 @@ amy_err_t esp32_setup_i2s(void) { #ifdef I2S_32BIT i2s_std_config_t std_cfg = { .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(AMY_SAMPLE_RATE), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO), + .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, AMY_I2S_SLOT_MODE), .gpio_cfg = { .mclk = (amy_global.config.i2s_mclk == -1)? I2S_GPIO_UNUSED : amy_global.config.i2s_mclk, .bclk = amy_global.config.i2s_bclk, @@ -96,7 +103,7 @@ amy_err_t esp32_setup_i2s(void) { #else // 16 bit I2S i2s_std_config_t std_cfg = { .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(AMY_SAMPLE_RATE), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), + .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, AMY_I2S_SLOT_MODE), .gpio_cfg = { .mclk = (amy_global.config.i2s_mclk == -1)? I2S_GPIO_UNUSED : amy_global.config.i2s_mclk, .bclk = amy_global.config.i2s_bclk, @@ -138,7 +145,7 @@ amy_err_t esp32_setup_i2s(void) { .slot_cfg = { .data_bit_width = I2S_DATA_BIT_WIDTH_32BIT, .slot_bit_width = I2S_SLOT_BIT_WIDTH_32BIT, - .slot_mode = I2S_SLOT_MODE_STEREO, + .slot_mode = AMY_I2S_SLOT_MODE, .slot_mask = I2S_STD_SLOT_BOTH, .ws_width = 32, .ws_pol = false, // false in STD_PHILIPS macro