Skip to content

Commit

Permalink
ports/psoc6/machine_i2s.c: WIP starting from mtb examples snippets.
Browse files Browse the repository at this point in the history
Signed-off-by: enriquezgarc <enriquezgarcia.external@infineon.com>
  • Loading branch information
jaenrig-ifx committed Mar 20, 2024
1 parent 14cd44c commit d2d1af8
Showing 1 changed file with 140 additions and 81 deletions.
221 changes: 140 additions & 81 deletions ports/psoc6/machine_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
#define AUDIO_SYS_CLOCK_HZ 98000000u /* in Hz (Ideally 98.304 MHz) */
#define AUDIO_SYS_CLOCK_HZ_1 90000000u

uint32_t Audio_sys_clock_fz;
// uint32_t Audio_sys_clock_fz;
uint32_t Audio_sys_clock_fz = AUDIO_SYS_CLOCK_HZ;
uint8_t clock_set;

cyhal_clock_t audio_clock;
Expand Down Expand Up @@ -66,9 +67,118 @@ typedef struct _machine_i2s_obj_t {
non_blocking_descriptor_t non_blocking_descriptor;
} machine_i2s_obj_t;

/******************************************************************************************/

/* Data to transmit, defined e.g. an array stored in flash */
#define I2S_TX_LEN 2000
uint32_t tx_buffer0[I2S_TX_LEN];
uint32_t tx_buffer1[I2S_TX_LEN];
uint32_t *dma_tx_buffer;
uint32_t *app_tx_buffer;

const size_t tx_buffer_len = I2S_TX_LEN;
void mtb_tx_buff_init() {
for (uint16_t i = 0; i < I2S_TX_LEN; i++)
{
tx_buffer0[i] = i;
tx_buffer1[i] = I2S_TX_LEN - 1 - i;
}
}

cyhal_i2s_t mtb_i2s;

static void i2s_event_handler_transmit_streaming(void *arg, cyhal_i2s_event_t event) {
/* When we registered the callback, we set 'arg' to point to the i2s object */
cyhal_i2s_t *i2s__ = (cyhal_i2s_t *)arg;
if (0u != (event & CYHAL_I2S_ASYNC_TX_COMPLETE)) {
/* Flip the active and the next tx buffers */
uint32_t *temp = dma_tx_buffer;
dma_tx_buffer = app_tx_buffer;
app_tx_buffer = temp;
/* Start writing the next buffer while the just-freed one is repopulated */
cy_rslt_t result = cyhal_i2s_write_async(i2s__, dma_tx_buffer, I2S_TX_LEN);
if (CY_RSLT_SUCCESS == result) {

static uint32_t factor = 0x100;
for (uint16_t i = 0; i < I2S_TX_LEN; i++)
{
*(app_tx_buffer + i) = i + factor;
}
factor = factor + 0x900;
}
}
}

static void mtb_i2s_init(machine_i2s_obj_t *self, cyhal_clock_t *clock) {
cyhal_i2s_pins_t tx_pins = { .sck = P13_1, .ws = P13_2, .data = P13_3, .mclk = NC };
cyhal_i2s_config_t config =
{
.is_tx_slave = false,
.is_rx_slave = false,
.mclk_hz = 0,
.channel_length = 32,
.word_length = 32,
.sample_rate_hz = 8000
};

cy_rslt_t result = cyhal_i2s_init(&mtb_i2s, &tx_pins, NULL, &config, &audio_clock);
if (CY_RSLT_SUCCESS != result) {
// printf("i2s init error \r\n");
}

// printf("TRACE 1 \r\n");
/* Register a callback and set the callback argument to be a pointer to the I2S object,
* so that we can easily reference it from the callback handler.
*/
// cyhal_i2s_register_callback(&i2s, &i2s_event_handler_transmit_one_shot, &i2s);
cyhal_i2s_register_callback(&mtb_i2s, &i2s_event_handler_transmit_streaming, &mtb_i2s);

// printf("TRACE 2 \r\n");

// /* Subscribe to the TX Empty event so that we can stop the interface when the transfer is complete */
// cyhal_i2s_enable_event(&i2s, CYHAL_I2S_ASYNC_TX_COMPLETE, CYHAL_ISR_PRIORITY_DEFAULT, true);

// printf("TRACE 3\r\n");
}

void mtb_i2s_async_tx_stream() {
// /* Subscribe to the async complete event so that we can queue up another transfer when this one completes */
cyhal_i2s_enable_event(&mtb_i2s, CYHAL_I2S_ASYNC_TX_COMPLETE, CYHAL_ISR_PRIORITY_DEFAULT, true);
/* Configure asynchronous transfers to use DMA to free up the CPU during transfers */
cy_rslt_t result = cyhal_i2s_set_async_mode(&mtb_i2s, CYHAL_ASYNC_DMA, CYHAL_DMA_PRIORITY_DEFAULT);
if (CY_RSLT_SUCCESS == result) {
/* Populate initial data in the two tx buffers (e.g. by streaming over the network) */
dma_tx_buffer = tx_buffer0;
app_tx_buffer = tx_buffer1;
result = cyhal_i2s_write_async(&mtb_i2s, dma_tx_buffer, tx_buffer_len);
}
if (CY_RSLT_SUCCESS == result) {
result = cyhal_i2s_start_tx(&mtb_i2s);
}

}

/********************************************************************************************************/

// TODO: The frame map is used with the readinto() method to transform the audio sample data coming
// from DMA memory (32-bit stereo) to the format specified
// in the I2S constructor. e.g. 16-bit mono

// //if stereo
// // //if word_bits = 8 bits
// // 0, -1, -1, -1, 1, -1, -1, -1
// //if 16 bits
// 0, 1, -1, -1, 2, 3, -1, -1
// //if 32 bits
// 0, 1, 2, 3, 4, 5, 6, 7
// //if mono
// // //if 8 bits
// // 0, -1, -1, -1, -1, -1, -1, -1
// //if 16 bits
// 0, 1, -1, -1, -1, -1, -1, -1
// //if 32 bits
// 0, 1, 2, 3, -1, -1, -1 -1

static const int8_t i2s_frame_map[NUM_I2S_USER_FORMATS][I2S_RX_FRAME_SIZE_IN_BYTES] = {
{ 0, 1, -1, -1, -1, -1, -1, -1 }, // Mono, 16-bits
{ 0, 1, 2, 3, -1, -1, -1, -1 }, // Mono, 32-bits
Expand Down Expand Up @@ -188,20 +298,6 @@ static void i2s_dma_from_dmabuf_to_ringbuf(machine_i2s_obj_t *self) {
// little-endian but consider the channel width in bits, and the word bits (sample resolution)

uint8_t dma_sample_size_in_bytes = (self->bits == 16? 2 : 4) * (self->format == STEREO ? 2: 1);
// //if stereo
// // //if word_bits = 8 bits
// // 0, -1, -1, -1, 1, -1, -1, -1
// //if 16 bits
// 0, 1, -1, -1, 2, 3, -1, -1
// //if 32 bits
// 0, 1, 2, 3, 4, 5, 6, 7
// //if mono
// // //if 8 bits
// // 0, -1, -1, -1, -1, -1, -1, -1
// //if 16 bits
// 0, 1, -1, -1, -1, -1, -1, -1
// //if 32 bits
// 0, 1, 2, 3, -1, -1, -1 -1
uint8_t *dma_buff_p = i2s_get_dma_idle_buffer(self);
uint32_t num_bytes_needed_from_ringbuf = SIZEOF_HALF_DMA_BUFFER_IN_BYTES * (I2S_RX_FRAME_SIZE_IN_BYTES / dma_sample_size_in_bytes);

Expand Down Expand Up @@ -268,7 +364,7 @@ static void i2s_dma_rx_event_process(machine_i2s_obj_t *self, cyhal_i2s_event_t

static void i2s_dma_irq_handler(void *arg, cyhal_i2s_event_t event) {
machine_i2s_obj_t *self = (machine_i2s_obj_t *)arg;

// i2s_assert_raise_val("i2s_dma_irq_handler: %lx !", -1);
void (*i2s_dma_event_process_func)(machine_i2s_obj_t *, cyhal_i2s_event_t);
if (self->mode == TX) {
i2s_dma_event_process_func = i2s_dma_tx_event_process;
Expand All @@ -277,69 +373,13 @@ static void i2s_dma_irq_handler(void *arg, cyhal_i2s_event_t event) {
}

i2s_dma_event_process_func(self, event);

// // for non-blocking operation handle the write() method requests.

// i2s_dma_tx_event_process(event)
// // TX
// if (i2s_dma_is_tx_complete(event))
// {
// i2s_dma_swap_active_dmabuf();
// i2s_dma_from_ringbuf_to_dmabuf();

// // }
// // if (0u != (event & CYHAL_I2S_ASYNC_TX_COMPLETE)) {

// // // Swap the active buffer half where the dma transfers
// // if (self->dma_active_half_index == 0) {
// // self->dma_active_half_index = SIZEOF_HALF_DMA_BUFFER_IN_BYTES;
// // } else if (self->dma_active_half_index == SIZEOF_HALF_DMA_BUFFER_IN_BYTES) {
// // self->dma_active_half_index = 0;
// // }

// // dma has emptied the tx buffer
// // update the ringbuffer pos where to keep writing

// // for non_blocking we feed the ringbuffer first
// // feed_dma()
// } else if (1 /*&& event*/) {
// // RX
// // dma has filled the rx buffer
// // update the ringbuffer pos where to keep reading
// // empty_dma()
// // if (i2s_dma_is_rx_complete_event())
// // {
// // uint8_t dma_rx_filled_index_p = i2s_dma_get_filled_dmabuf_index();
// // i2s_dma_swap_active_dmabuf();
// // i2s_dma_from_dmabuf_to_ringbuf();
// // }
// if (0u != (event & CYHAL_I2S_ASYNC_RX_COMPLETE)) {
// // uint8_t dma_rx_filled_index_p = self->dma_active_half_index;
// // Swap the active buffer half where the dma transfers
// if (self->dma_active_half_index == 0) {
// self->dma_active_half_index = SIZEOF_HALF_DMA_BUFFER_IN_BYTES;
// } else if (self->dma_active_half_index == SIZEOF_HALF_DMA_BUFFER_IN_BYTES) {
// self->dma_active_half_index = 0;
// }

// cy_rslt_t result = cyhal_i2s_read_async(&self->i2s_obj, self->dma_buffer + self->dma_active_half_index, SIZEOF_HALF_DMA_BUFFER_IN_BYTES);
// i2s_assert_raise_val("I2S DMA read configure failed with return code %lx !", result);
// }

// i2s_dma_rx_empty(self);
// // for non_blocking we already feed the app_buff
// // for non-blocking operation handle the readinto() method requests.
// if ((self->io_mode == NON_BLOCKING) && (self->non_blocking_descriptor.copy_in_progress)) {
// fill_appbuf_from_ringbuf_non_blocking(self);
// }
// }
}

static void i2s_init(machine_i2s_obj_t *self, cyhal_clock_t *clock) {
cyhal_i2s_pins_t pins = { .sck = self->sck, .ws = self->ws, .data = self->sd, .mclk = NC };
cyhal_i2s_config_t config =
{
.is_tx_slave = true,
.is_tx_slave = false,
.is_rx_slave = false,
.mclk_hz = 0,
.channel_length = 32, // TODO: which channel length shall we use? This needs to be calculated based on reading formats
Expand Down Expand Up @@ -443,6 +483,14 @@ static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *ar
mp_raise_ValueError(MP_ERROR_TEXT("invalid format"));
}

int32_t ring_buffer_len = args[ARG_ibuf].u_int;
if (ring_buffer_len > 0) {
self->ring_buffer_storage = m_new(uint8_t, ring_buffer_len);
ringbuf_init(&self->ring_buffer, self->ring_buffer_storage, ring_buffer_len);
} else {
mp_raise_ValueError(MP_ERROR_TEXT("invalid ibuf"));
}

self->sck = sck;
self->ws = ws;
self->sd = sd;
Expand All @@ -455,7 +503,9 @@ static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *ar
} else {
Audio_sys_clock_fz = AUDIO_SYS_CLOCK_HZ_1;
}
self->ibuf = args[ARG_ibuf].u_int;
self->ibuf = ring_buffer_len;


self->callback_for_non_blocking = MP_OBJ_NULL;
self->io_mode = BLOCKING;

Expand All @@ -464,15 +514,24 @@ static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *ar
cyhal_system_delay_ms(1);
}

// TODO: with all inputs validated make the objects of the i2s object.
// TODO: then make the i2s object
// // TODO: with all inputs validated make the objects of the i2s object.
// // TODO: then make the i2s object

// // i2s_clock_configure();

// for(uint8_t i = 0; i < SIZEOF_HALF_DMA_BUFFER_IN_BYTES; i++){
// self->dma_buffer[i] = i;
// }

// i2s_init(self, &audio_clock);
// i2s_dma_irq_configure(self);
// i2s_dma_init(self);


// i2s_clock_configure();
mtb_tx_buff_init();
mtb_i2s_init(self, &audio_clock);
mtb_i2s_async_tx_stream();

i2s_init(self, &audio_clock);
// init_ring_buffer(); with the value passed by the user. !!
i2s_dma_irq_configure(self);
i2s_dma_init(self);
}

static void mp_machine_i2s_deinit(machine_i2s_obj_t *self) {
Expand Down

0 comments on commit d2d1af8

Please sign in to comment.