/*
 * Copyright (c) 2019 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 *
 * @brief Test app to illustrate I2S transmission/reception on Intel S1000 CRB
 *
 * The i2s_cavs driver is being used.
 *
 * In this test app, I2S transmission and reception are tested as follows:
 * I2S port #3 of Intel S1000 is configured for bidirectional mode
 *     i.e., I2S_DIR_TX and I2S_DIR_RX
 * After each frame is received, it is sent/looped back on the same I2S
 * The transmit direction is started after 2 frames are queued. This is done to
 * ensure that there is enough data for the DMA and I2S are available when the
 * start operation is triggered
 */

#include <zephyr/zephyr.h>
#include <zephyr/sys/printk.h>

#include <zephyr/device.h>
#include <zephyr/drivers/i2s.h>

#define I2S_DEV_NAME "I2S_3"
#define NUM_I2S_BUFFERS 4

/* size of stack area used by each thread */
#define STACKSIZE               2048

/* scheduling priority used by each thread */
#define PRIORITY                7

/* delay between greetings (in ms) */
#define SLEEPTIME               K_MSEC(500)

extern struct k_sem thread_sem;

#define NUM_OF_CHANNELS		2
#define FRAME_CLK_FREQ		48000
#define I2S_WORDSIZE		32
#define BLOCK_SIZE		192
#define BLOCK_SIZE_BYTES	(BLOCK_SIZE * sizeof(int32_t))
#define FRAMES_PER_ITERATION	50
#define TIMEOUT			2000

static char __aligned(4) audio_buffers[BLOCK_SIZE_BYTES * NUM_I2S_BUFFERS];
static struct k_mem_slab i2s_mem_slab;

/** Configure I2S bidirectional transfer. */
void test_i2s_bidirectional_transfer_configure(void)
{
	int ret;
	const struct device *dev_i2s;
	struct i2s_config i2s_cfg;

	k_mem_slab_init(&i2s_mem_slab, audio_buffers, BLOCK_SIZE_BYTES,
			NUM_I2S_BUFFERS);

	dev_i2s = device_get_binding(I2S_DEV_NAME);
	if (!dev_i2s) {
		printk("I2S: Device driver not found.\n");
		return;
	}

	/* Configure */
	i2s_cfg.word_size = I2S_WORDSIZE;
	i2s_cfg.channels = NUM_OF_CHANNELS;
	i2s_cfg.format = I2S_FMT_DATA_FORMAT_I2S | I2S_FMT_CLK_NF_NB;
	i2s_cfg.options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER;
	i2s_cfg.frame_clk_freq = FRAME_CLK_FREQ;
	i2s_cfg.block_size = BLOCK_SIZE_BYTES;
	i2s_cfg.mem_slab = &i2s_mem_slab;
	i2s_cfg.timeout = TIMEOUT;

	ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg);
	if (ret != 0) {
		printk("I2S_TX configuration failed with %d error\n", ret);
		return;
	}
	ret = i2s_configure(dev_i2s, I2S_DIR_RX, &i2s_cfg);
	if (ret != 0) {
		printk("I2S_RX configuration failed with %d error\n", ret);
		return;
	}
}

/** @brief Bi-Directional I2S transfer.
 *
 * - TX/RX stream START trigger starts transmission/reception.
 * - TX/RX stream STOP trigger stops the transmission/reception.
 */
void test_i2s_bidirectional_transfer(void)
{
	const struct device *dev_i2s;
	int frames = 0;
	void *buffer;
	size_t size;
	int ret;

	printk("Testing I2S bidirectional transfer\n");
	dev_i2s = device_get_binding(I2S_DEV_NAME);
	if (!dev_i2s) {
		printk("I2S: Device driver not found.\n");
		return;
	}

	/* Start reception */
	ret = i2s_trigger(dev_i2s, I2S_DIR_RX, I2S_TRIGGER_START);
	if (ret != 0) {
		printk("RX Start failed with %d error\n", ret);
		return;
	}

	/* iteratively receive a frame and send it back */
	while (frames++ < FRAMES_PER_ITERATION) {
		ret = i2s_read(dev_i2s, &buffer, &size);
		if (ret != 0) {
			printk("i2s_read failed with %d error\n", ret);
			return;
		}

		/* send the buffer */
		ret = i2s_write(dev_i2s, buffer, size);
		if (ret != 0) {
			printk("i2s_write failed with %d error\n", ret);
			return;
		}

		/* Start transmission after 2 frames are queued */
		if (frames == 2) {
			ret = i2s_trigger(dev_i2s, I2S_DIR_TX,
					I2S_TRIGGER_START);
			if (ret != 0) {
				printk("TX Start failed with %d error\n", ret);
				return;
			}
		}
	}

	/* Stop transmission */
	ret = i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_STOP);
	if (ret != 0) {
		printk("TX Stop failed with %d error\n", ret);
		return;
	}

	/* Stop reception */
	ret = i2s_trigger(dev_i2s, I2S_DIR_RX, I2S_TRIGGER_STOP);
	if (ret != 0) {
		printk("RX Stop failed with %d error\n", ret);
		return;
	}
	printk("Completed %d bidirectional frames on " I2S_DEV_NAME "\n",
			FRAMES_PER_ITERATION);
}

/* i2s_thread is a static thread that is spawned automatically */
void i2s_thread(void *dummy1, void *dummy2, void *dummy3)
{
	ARG_UNUSED(dummy1);
	ARG_UNUSED(dummy2);
	ARG_UNUSED(dummy3);

	test_i2s_bidirectional_transfer_configure();

	while (1) {
		k_sem_take(&thread_sem, K_FOREVER);

		test_i2s_bidirectional_transfer();

		/* let other threads have a turn */
		k_sem_give(&thread_sem);

		/* wait a while */
		k_sleep(SLEEPTIME);
	}
}

K_THREAD_DEFINE(i2s_thread_id, STACKSIZE, i2s_thread, NULL, NULL, NULL,
		PRIORITY, 0, 0);
