I2S Zephyr SDOUT not working

I am trying to get I2S communication up and running but am unable to produce a signal on my SDOUT pin. MCLK, LRCLK and SCLK work as intended but trying to send any data does not work. I did notice that the TXD.PTR register is empty. I have tried multiple pins for my SDOUT and have nrf SDK 1.8.0 installed, using VScode. Any help would be appreciated.

#include <zephyr.h>
#include <drivers/gpio.h>
#include <init.h>
#include <nrf.h>
#include <nrfx.h>
#include <nrfx_gpiote.h>
#include <drivers/i2s.h>
#include "nrfx_i2s.h"
#include <errno.h>
#include <string.h>
#include <logging/log.h>

LOG_MODULE_REGISTER(Main);

#define AUDIO_SAMPLE_FREQ (44100)
#define AUDIO_NUM_CHANNELS (1)
#define AUDIO_SAMPLE_BIT_WIDTH (16)
#define AUDIO_SAMPLES_PER_CH_PER_FRAME (128)
#define AUDIO_SAMPLES_PER_FRAME (AUDIO_SAMPLES_PER_CH_PER_FRAME * AUDIO_NUM_CHANNELS)
#define AUDIO_SAMPLE_BYTES (sizeof(uint16_t))
#define AUDIO_FRAME_BUF_BYTES (AUDIO_SAMPLES_PER_FRAME * AUDIO_SAMPLE_BYTES)
#define I2S_PLAY_BUF_COUNT (500)

static const struct device *host_i2s_tx_dev;
static struct k_mem_slab i2s_tx_mem_slab;
static char tx_buffer[AUDIO_FRAME_BUF_BYTES * I2S_PLAY_BUF_COUNT];
static struct i2s_config config;
volatile int ret;

static void init(void)
{
	/*configure tx device*/
	host_i2s_tx_dev = device_get_binding("I2S_0");

	k_mem_slab_init(&i2s_tx_mem_slab, tx_buffer, AUDIO_FRAME_BUF_BYTES, I2S_PLAY_BUF_COUNT);

	/* configure i2s for audio playback */
	config.word_size = AUDIO_SAMPLE_BIT_WIDTH;
	config.channels = AUDIO_NUM_CHANNELS;
	config.format = I2S_FMT_DATA_FORMAT_I2S;
	config.options = (I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER);
	config.frame_clk_freq = AUDIO_SAMPLE_FREQ;
	config.block_size = AUDIO_FRAME_BUF_BYTES;
	config.mem_slab = &i2s_tx_mem_slab;
	config.timeout = -1;
	ret = i2s_configure(host_i2s_tx_dev, I2S_DIR_TX, &config);
	if (ret < 0)
	{
		LOG_INF("tx config:%d", ret);
	}
}

void main(void)
{
	init();

	uint16_t buf[128];
	volatile size_t size = sizeof(buf);

	int i = 0;
	for (i = 0; i < size; i++)
	{
		if (i <= size / 4)
		{
			buf[i] = i;
		}
		else if (i > size / 4)
		{
			buf[i] = size / 2 - i;
		}
	}

	void *tx_mem_block;

	ret = i2s_trigger(host_i2s_tx_dev, I2S_DIR_TX, I2S_TRIGGER_START);

	while (1)
	{
		ret = k_mem_slab_alloc(&i2s_tx_mem_slab, &tx_mem_block, K_NO_WAIT);
		memcpy(tx_mem_block, &buf, size);
		ret = i2s_write(host_i2s_tx_dev, tx_mem_block, size);
		k_mem_slab_free(&i2s_tx_mem_slab, &tx_mem_block);
	}
}
# CONFIG_MULTITHREADING=n
# CONFIG_KERNEL_MEM_POOL=n
# CONFIG_NUM_PREEMPT_PRIORITIES=0
# CONFIG_SYS_CLOCK_EXISTS=n
# CONFIG_ARM_MPU=n
# CONFIG_SIZE_OPTIMIZATIONS=y
CONFIG_I2S=y
CONFIG_NRFX_I2S=y
# CONFIG_WATCHDOG=n
CONFIG_GPIO=y
# CONFIG_PINMUX=n
# CONFIG_SPI=n
# CONFIG_SERIAL=n
# CONFIG_FLASH=n
# CONFIG_PM=n
# CONFIG_DYNAMIC_INTERRUPTS=n
# CONFIG_IRQ_OFFLOAD=n
# CONFIG_THREAD_STACK_INFO=n
# CONFIG_THREAD_CUSTOM_DATA=n
# CONFIG_BOOT_BANNER=n
# CONFIG_BOOT_DELAY=0
# CONFIG_CONSOLE=n
# CONFIG_UART_CONSOLE=n
# CONFIG_STDOUT_CONSOLE=n
# CONFIG_EARLY_CONSOLE=n
CONFIG_BOARD_ENABLE_CPUNET=n
CONFIG_NRF_RTC_TIMER=n
CONFIG_CORTEX_M_SYSTICK=y
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=64000000
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000000
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=y

Parents
  • Hello,

    What pins were you origninally use when the SDOUT didn't work? I know you say you have tried multiple pins, but perhaps you were unlucky. 

    Have you tried printing the tx_mem_block before you pass it on in i2s_write? Is it properly populated? Are you sure you need the "&" on "&buf" when buf is an array? Try without. 

    How did you check the TXD.PTR register and decide that it was empty?

    Best regards,

    Edvin

Reply
  • Hello,

    What pins were you origninally use when the SDOUT didn't work? I know you say you have tried multiple pins, but perhaps you were unlucky. 

    Have you tried printing the tx_mem_block before you pass it on in i2s_write? Is it properly populated? Are you sure you need the "&" on "&buf" when buf is an array? Try without. 

    How did you check the TXD.PTR register and decide that it was empty?

    Best regards,

    Edvin

Children
No Data
Related