Good day! My code is adapted from the i2s echo example. I removed all the code regarding the button click and codec because it is not needed in my application. Below is the code. When i run the code, i get errors on configuring the Rx stream.
/* * Copyright (c) 2021 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include <zephyr/kernel.h> #include <zephyr/sys/printk.h> #include <zephyr/drivers/i2s.h> #include <zephyr/drivers/gpio.h> #include <string.h> #include <zephyr/drivers/pwm.h> #define I2S_RX_NODE DT_NODELABEL(i2s_rx) #define SAMPLE_FREQUENCY 62500 #define SAMPLE_BIT_WIDTH 32 #define BYTES_PER_SAMPLE sizeof(int16_t) #define NUMBER_OF_CHANNELS 2 /* Such block length provides an echo with the delay of 100 ms. */ #define SAMPLES_PER_BLOCK ((SAMPLE_FREQUENCY / 10) * NUMBER_OF_CHANNELS) #define INITIAL_BLOCKS 2 #define TIMEOUT 1000 // PWM DEFINES static const struct pwm_dt_spec pwm_led0 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led0)); static const struct pwm_dt_spec pwm_led1 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led1)); #define BITCLK PWM_KHZ(4000U) #define WORD_S PWM_HZ(62500U) #define BLOCK_SIZE (BYTES_PER_SAMPLE * SAMPLES_PER_BLOCK) #define BLOCK_COUNT (INITIAL_BLOCKS + 2) K_MEM_SLAB_DEFINE_STATIC(mem_slab, BLOCK_SIZE, BLOCK_COUNT, 4); static int16_t echo_block[SAMPLES_PER_BLOCK]; static volatile bool echo_enabled = true; static K_SEM_DEFINE(toggle_transfer, 1, 1); static void process_block_data(void *mem_block, uint32_t number_of_samples) { static bool clear_echo_block; if (echo_enabled) { for (int i = 0; i < number_of_samples; ++i) { int16_t *sample = &((int16_t *)mem_block)[i]; *sample += echo_block[i]; echo_block[i] = (*sample) / 2; } clear_echo_block = true; } else if (clear_echo_block) { clear_echo_block = false; memset(echo_block, 0, sizeof(echo_block)); } } static bool configure_streams(const struct device *i2s_dev_rx, const struct i2s_config *config) { int ret; ret = i2s_configure(i2s_dev_rx, I2S_DIR_RX, config); if (ret < 0) { printk("Failed to configure RX stream: %d\n", ret); return false; } return true; } static bool prepare_transfer(const struct device *i2s_dev_rx) { int ret; for (int i = 0; i < INITIAL_BLOCKS; ++i) { void *mem_block; ret = k_mem_slab_alloc(&mem_slab, &mem_block, K_NO_WAIT); if (ret < 0) { printk("Failed to allocate TX block %d: %d\n", i, ret); return false; } memset(mem_block, 0, BLOCK_SIZE); } return true; } static bool trigger_command(const struct device *i2s_dev_rx, enum i2s_trigger_cmd cmd) { int ret; ret = i2s_trigger(i2s_dev_rx, I2S_DIR_RX, cmd); if (ret < 0) { printk("Failed to trigger command %d on RX: %d\n", cmd, ret); return false; } return true; } int main(void) { uint32_t bclk_period; uint32_t ws_period; int ret1; int ret2; printk("Starting main thread\n\r"); printk("PWM-based blinky\n"); if (!pwm_is_ready_dt(&pwm_led0)) { printk("Error: PWM device %s is not ready\n", pwm_led0.dev->name); return 0; } if (!pwm_is_ready_dt(&pwm_led1)) { printk("Error: PWM device %s is not ready\n", pwm_led0.dev->name); return 0; } /* * In case the default MAX_PERIOD value cannot be set for * some PWM hardware, decrease its value until it can. * * Keep its value at least MIN_PERIOD * 4 to make sure * the sample changes frequency at least once. */ bclk_period = BITCLK; while (pwm_set_dt(&pwm_led0, bclk_period, bclk_period / 2U)) { bclk_period /= 2U; printk("half bclk"); } ws_period = WORD_S; while (pwm_set_dt(&pwm_led1, ws_period, ws_period / 2U)) { ws_period /= 2U; printk("half ws"); } ws_period = WORD_S; bclk_period = BITCLK; const struct device *const i2s_dev_rx = DEVICE_DT_GET(I2S_RX_NODE); struct i2s_config config; printk("I2S echo sample\n"); if (!device_is_ready(i2s_dev_rx)) { printk("%s is not ready\n", i2s_dev_rx->name); return 0; } config.word_size = SAMPLE_BIT_WIDTH; config.channels = NUMBER_OF_CHANNELS; config.format = I2S_FMT_DATA_FORMAT_I2S; config.options = I2S_OPT_BIT_CLK_SLAVE | I2S_OPT_FRAME_CLK_SLAVE; config.frame_clk_freq = SAMPLE_FREQUENCY; config.mem_slab = &mem_slab; config.block_size = BLOCK_SIZE; config.timeout = TIMEOUT; if (!configure_streams(i2s_dev_rx, &config)) { return 0; } for (;;) { k_sem_take(&toggle_transfer, K_FOREVER); if (!prepare_transfer(i2s_dev_rx)) { return 0; } if (!trigger_command(i2s_dev_rx, I2S_TRIGGER_START)) { return 0; } printk("Streams started\n"); while (k_sem_take(&toggle_transfer, K_NO_WAIT) != 0) { void *mem_block; uint32_t block_size; int ret; ret = i2s_read(i2s_dev_rx, &mem_block, &block_size); if (ret < 0) { printk("Failed to read data: %d\n", ret); break; } process_block_data(mem_block, SAMPLES_PER_BLOCK); } if (!trigger_command(i2s_dev_rx, I2S_TRIGGER_DROP)) { return 0; } printk("Streams stopped\n"); } while (1) { ret1 = pwm_set_dt(&pwm_led0, bclk_period, bclk_period / 2U); if (ret1) { printk("Error %d: failed to set pulse width\n", ret1); return 0; } ret2 = pwm_set_dt(&pwm_led1, ws_period, ws_period / 2U); if (ret2) { printk("Error %d: failed to set pulse width\n", ret2); return 0; } } }
overlay
/* * Copyright (c) 2021 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ &pinctrl { pwm0_custom: pwm0_custom { group1 { psels = <NRF_PSEL(PWM_OUT0, 0, 3)>; nordic,invert; }; }; pwm0_csleep: pwm0_csleep { group1 { psels = <NRF_PSEL(PWM_OUT0, 0, 3)>; low-power-enable; }; }; pwm1_custom: pwm1_custom { group1 { psels = <NRF_PSEL(PWM_OUT0, 0, 28)>; nordic,invert; }; }; pwm1_csleep: pwm1_csleep { group1 { psels = <NRF_PSEL(PWM_OUT0, 0, 28)>; low-power-enable; }; }; i2s0_default_alt: i2s0_default_alt { group1 { psels = <NRF_PSEL(I2S_SDIN, 0, 29)>; }; }; i2s0_sleep: i2s0_sleep { group1 { psels = <NRF_PSEL(I2S_SDIN, 0, 29)>; low-power-enable; }; }; }; i2s_rx: &i2s0 { status = "okay"; pinctrl-0 = <&i2s0_default_alt>; pinctrl-names = "default"; }; &pwm0 { status = "okay"; pinctrl-0 = <&pwm0_custom>; pinctrl-1 = <&pwm0_csleep>; pinctrl-names = "default", "sleep"; }; &pwm1 { status = "okay"; pinctrl-0 = <&pwm1_custom>; pinctrl-1 = <&pwm1_csleep>; pinctrl-names = "default", "sleep"; }; /{ pwmleds { compatible = "pwm-leds"; pwm_led0: pwm_led_0 { pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; }; pwm_led1: pwm_led_1 { pwms = <&pwm1 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; }; }; aliases { pwm-led0 = &pwm_led0; pwm-led1 = &pwm_led1; }; };