Hi. I have a new project using zephyr 3.5.0 and ZMK, so I don't think NCS SDK is an option.
I am using pca10056/nrf52840dk
I am trying to configure I2S, and the examples I'm seeing for the above toolchain are inconsistent.
For starters I just want to see MCK, SCK, LRCK and SDOUT on the logic analyzer before managing buffering.
I am obviously not a zephyr pro, I've used it twice before for brief projects.
1) the overlay file uses pinctrl, not 'mck-pin' or 'sck-pin' inside &i2s0 definition.
2) Certain pins on pca10056 are not functioning as intended.
eg - I try the following, but I only see LRCK and SDOUT on the logic analyzer.
I had MCK working at one point but have lost that configuration with trial and error.
i2s0_default: i2s0_default { group1 { psels = <NRF_PSEL(I2S_MCK, 0, 28)>, <NRF_PSEL(I2S_SCK_M, 0, 30)>, <NRF_PSEL(I2S_LRCK_M, 0, 29)>, <NRF_PSEL(I2S_SDOUT, 0, 31)>; }; };

Is there something simple I can do to achieve this?
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/i2s.h>
#include <zephyr/devicetree.h>
#include <zephyr/logging/log.h>
#include <math.h>
LOG_MODULE_REGISTER(i2s_sine, LOG_LEVEL_INF);
#define M_PI 3.14159265358979323846
#define I2S_NODE DT_NODELABEL(i2s0)
#define SAMPLE_RATE 48000
#define CHANNELS 1
#define BITS_PER_SAMPLE 16
#define FREQUENCY_HZ 60
#define SINE_WAVE_BUFFER_SIZE (SAMPLE_RATE / FREQUENCY_HZ)
#define BLOCK_SIZE (SINE_WAVE_BUFFER_SIZE * CHANNELS * (BITS_PER_SAMPLE / 8))
// Pre-computed sine wave data buffer
int16_t sine_wave_buffer[SINE_WAVE_BUFFER_SIZE];
// Memory slab for I2S DMA buffers
K_MEM_SLAB_DEFINE(mem_slab_tx, BLOCK_SIZE, 4, 1);
static const struct device *i2s_dev = DEVICE_DT_GET(I2S_NODE);
static void generate_sine_wave(void) {
double freq = FREQUENCY_HZ;
double amplitude = 32767.0; // Full-scale for 16-bit signed audio
for (int i = 0; i < SINE_WAVE_BUFFER_SIZE; i++) {
double t = (double)i / SAMPLE_RATE;
double value = amplitude * sin(2.0 * M_PI * freq * t);
sine_wave_buffer[i] = (int16_t)value;
}
}
int main(void) {
int ret;
struct i2s_config i2s_cfg;
void *mem_block_tx;
if (!device_is_ready(i2s_dev)) {
LOG_ERR("I2S device is not ready.");
return 0;
}
// Generate the 60 Hz sine wave data
generate_sine_wave();
// I2S configuration structure
i2s_cfg.word_size = BITS_PER_SAMPLE;
i2s_cfg.channels = CHANNELS;
i2s_cfg.format = I2S_FMT_DATA_FORMAT_I2S; // Standard I2S format
i2s_cfg.options = I2S_OPT_FRAME_CLK_MASTER;
i2s_cfg.frame_clk_freq = SAMPLE_RATE;
i2s_cfg.mem_slab = &mem_slab_tx;
i2s_cfg.block_size = BLOCK_SIZE;
i2s_cfg.timeout = 100;
ret = i2s_configure(i2s_dev, I2S_DIR_TX, &i2s_cfg);
if (ret < 0) {
LOG_ERR("I2S config failed: %d", ret);
return 0;
}
// Trigger start of transmission
ret = i2s_trigger(i2s_dev, I2S_DIR_TX, I2S_TRIGGER_START);
if (ret < 0) {
LOG_ERR("I2S trigger start failed: %d", ret);
return 0;
}
while (1) {
// Allocate a memory block from the slab
ret = k_mem_slab_alloc(&mem_slab_tx, &mem_block_tx, K_FOREVER);
if (ret < 0) {
LOG_ERR("Failed to allocate memory block: %d", ret);
continue;
}
// Copy the sine wave data to the allocated buffer
memcpy(mem_block_tx, sine_wave_buffer, BLOCK_SIZE);
// Write the filled buffer to the I2S TX queue
ret = i2s_write(i2s_dev, mem_block_tx, BLOCK_SIZE);
if (ret < 0) {
LOG_ERR("I2S write failed: %d", ret);
k_mem_slab_free(&mem_slab_tx, mem_block_tx);
}
}
return 0;
}


