Hi,I have been using NRF5340 Audio DK and I able to get data using SPH0645 using i2s_read function and able to transmit data to amplifier TAS2562 using i2s_write function .But the issue is I am reading a data of 32 bit of each sample ,need to right shift by 16 bit and then I need to pass to amplifier the shifted data i2s_write(),but if i prob the sdout pin i able to see data of 18 bit in oscilloscope(actually mic has 18 bit data precision).I want to know how to shift data and pass to write.I took from sample i2s echo.In case if we need to use function i2s_buf_read/write help me in implementing as no example show how to use it ,wheather it uses memory slab or not as I tried and could'nt achieve to get 16 bit as output.To mention I am using single i2s_rxtx.
&pinctrl { i2c0_default_alt: i2c0_default_alt { group1 { psels = <NRF_PSEL(TWIM_SDA, 1, 2)>, <NRF_PSEL(TWIM_SCL, 1, 3)>; }; }; i2c0_sleep_alt: i2c0_sleep_alt { group1 { psels = <NRF_PSEL(TWIM_SDA, 1, 2)>, <NRF_PSEL(TWIM_SCL, 1, 3)>; low-power-enable; }; }; i2s0_default_alt: i2s0_default_alt { group1 { psels =<NRF_PSEL(I2S_SCK_M, 0, 26)>, <NRF_PSEL(I2S_LRCK_M, 0, 25)>, <NRF_PSEL(I2S_SDOUT, 0, 6)>, <NRF_PSEL(I2S_SDIN, 0, 7)>; }; }; i2s0_sleep_alt: i2s0_sleep_alt { group1 { psels = <NRF_PSEL(I2S_SCK_M, 0, 26)>, <NRF_PSEL(I2S_LRCK_M, 0, 25)>, <NRF_PSEL(I2S_SDOUT, 0, 6)>, <NRF_PSEL(I2S_SDIN, 0, 7)>; }; }; }; &i2c1 { status = "okay"; pinctrl-0 = <&i2c0_default_alt>; pinctrl-1 = <&i2c0_sleep_alt>; pinctrl-names = "default", "sleep"; }; &clock { hfclkaudio-frequency = <11289600>; }; i2s_rxtx: &i2s0 { status = "okay"; pinctrl-0 = <&i2s0_default_alt>; pinctrl-1 = <&i2s0_sleep_alt>; pinctrl-names = "default","sleep"; clock-source = "ACLK"; };
#include <zephyr/kernel.h> //#include "codec.h" #include <zephyr/sys/printk.h> #include <zephyr/drivers/i2s.h> #include <zephyr/drivers/i2c.h> #include <zephyr/drivers/gpio.h> #include <string.h> #include "tas.h" #if DT_NODE_EXISTS(DT_NODELABEL(i2s_rxtx)) #define I2S_RX_NODE DT_NODELABEL(i2s_rxtx) #define I2S_TX_NODE I2S_RX_NODE #else #define I2S_RX_NODE DT_NODELABEL(i2s_rx) #define I2S_TX_NODE DT_NODELABEL(i2s_tx) #endif #define I2C1_NODE DT_NODELABEL(tas2563) #define SAMPLE_FREQUENCY 16000 #define SAMPLE_BIT_WIDTH 32 #define BYTES_PER_SAMPLE sizeof(int32_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 #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 const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C1_NODE); static K_SEM_DEFINE(toggle_transfer, 1, 1); volatile int16_t bellMicData, ancMicData, filterData, ancData=0; int32_t process_block[SAMPLES_PER_BLOCK]; const struct device *const i2s_dev_tx = DEVICE_DT_GET(I2S_TX_NODE); static void i2cInit() { if (!device_is_ready(dev_i2c.bus)) { printk("I2C bus %s is not ready!\n\r", dev_i2c.bus->name); return; } else { printk("I2C bus %s is ready!\n\r", dev_i2c.bus->name); } } static void process_block_data(void *mem_block, uint32_t number_of_samples) { for (int i = 0; i < number_of_samples; ++i) { int32_t *sample = &((int32_t *)mem_block)[i]; mem_block= (*sample)>>16 ; } } static bool configure_streams(const struct device *i2s_dev_rx, const struct device *i2s_dev_tx, const struct i2s_config *config) { int ret; if (i2s_dev_rx == i2s_dev_tx) { ret = i2s_configure(i2s_dev_rx, I2S_DIR_BOTH, config); if (ret == 0) { return true; } /* -ENOSYS means that the RX and TX streams need to be * configured separately. */ if (ret != -ENOSYS) { printk("Failed to configure streams: %d\n", ret); return false; } } ret = i2s_configure(i2s_dev_rx, I2S_DIR_RX, config); if (ret < 0) { printk("Failed to configure RX stream: %d\n", ret); return false; } ret = i2s_configure(i2s_dev_tx, I2S_DIR_TX, config); if (ret < 0) { printk("Failed to configure TX stream: %d\n", ret); return false; } return true; } static bool prepare_transfer(const struct device *i2s_dev_rx, const struct device *i2s_dev_tx) { 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); ret = i2s_write(i2s_dev_tx, mem_block, BLOCK_SIZE); if (ret < 0) { printk("Failed to write block %d: %d\n", i, ret); return false; } } return true; } static bool trigger_command(const struct device *i2s_dev_rx, const struct device *i2s_dev_tx, enum i2s_trigger_cmd cmd) { int ret; if (i2s_dev_rx == i2s_dev_tx) { ret = i2s_trigger(i2s_dev_rx, I2S_DIR_BOTH, cmd); if (ret == 0) { return true; } /* -ENOSYS means that commands for the RX and TX streams need * to be triggered separately. */ if (ret != -ENOSYS) { printk("Failed to trigger command %d: %d\n", cmd, ret); return false; } } 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; } ret = i2s_trigger(i2s_dev_tx, I2S_DIR_TX, cmd); if (ret < 0) { printk("Failed to trigger command %d on TX: %d\n", cmd, ret); return false; } return true; } int main(void) { const struct device *const i2s_dev_rx = DEVICE_DT_GET(I2S_RX_NODE); struct i2s_config config; printk("I2S echo sample\n"); // i2cInit(); // playbackInit(); if (!device_is_ready(i2s_dev_rx)) { printk("%s is not ready\n", i2s_dev_rx->name); return 0; } if (i2s_dev_rx != i2s_dev_tx && !device_is_ready(i2s_dev_tx)) { printk("%s is not ready\n", i2s_dev_tx->name); return 0; } config.word_size = 32; config.channels = NUMBER_OF_CHANNELS; config.format = I2S_FMT_DATA_FORMAT_I2S; config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER; 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, i2s_dev_tx, &config)) { return 0; } for (;;) { k_sem_take(&toggle_transfer, K_FOREVER); if (!prepare_transfer(i2s_dev_rx, i2s_dev_tx)) { return 0; } if (!trigger_command(i2s_dev_rx, i2s_dev_tx, I2S_TRIGGER_START)) { return 0; } printk("Streams started\n"); while (k_sem_take(&toggle_transfer, K_NO_WAIT) != 0) { void *mem_block; size_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 ); ret = i2s_write(i2s_dev_tx,mem_block, block_size); if (ret < 0) { printk("Failed to read data: %d\n", ret); } k_mem_slab_free(&mem_slab, mem_block); } if (!trigger_command(i2s_dev_rx, i2s_dev_tx, I2S_TRIGGER_DROP)) { return 0; } printk("Streams stopped\n"); } }