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 21, 2024
1 parent dcc56a9 commit d159aa1
Showing 1 changed file with 26 additions and 26 deletions.
52 changes: 26 additions & 26 deletions ports/psoc6/machine_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ cyhal_clock_t hf0_clock;
// 1. memory use (smaller buffer size desirable to reduce memory footprint)
// 2. interrupt frequency (larger buffer size desirable to reduce interrupt frequency)
// The sizeof 1/2 of the DMA buffer must be evenly divisible by the cache line size of 32 bytes.
#define SIZEOF_DMA_BUFFER_IN_BYTES (256)
#define SIZEOF_HALF_DMA_BUFFER_IN_BYTES (SIZEOF_DMA_BUFFER_IN_BYTES / 2)
#define SIZEOF_DMA_BUFFER (256)
#define SIZEOF_HALF_DMA_BUFFER (SIZEOF_DMA_BUFFER / 2)
#define SIZEOF_HALF_DMA_BUFFER_IN_BYTES (SIZEOF_HALF_DMA_BUFFER * sizeof(uint32_t))

// TODO: For non-blocking mode, to avoid underflow/overflow, sample data is written/read to/from the ring buffer at a rate faster
// than the DMA transfer rate
#define NON_BLOCKING_RATE_MULTIPLIER (4)
#define SIZEOF_NON_BLOCKING_COPY_IN_BYTES (SIZEOF_HALF_DMA_BUFFER_IN_BYTES * NON_BLOCKING_RATE_MULTIPLIER)
#define SIZEOF_NON_BLOCKING_COPY_IN_BYTES (SIZEOF_HALF_DMA_BUFFER * NON_BLOCKING_RATE_MULTIPLIER)

typedef enum {
RX,
Expand All @@ -60,7 +61,7 @@ typedef struct _machine_i2s_obj_t {
int32_t ibuf;
mp_obj_t callback_for_non_blocking;
io_mode_t io_mode;
uint32_t dma_buffer[SIZEOF_DMA_BUFFER_IN_BYTES];
uint32_t dma_buffer[SIZEOF_DMA_BUFFER];
uint32_t *dma_active_buf_p;
uint32_t *dma_idle_buf_p;
ring_buf_t ring_buffer;
Expand Down Expand Up @@ -173,12 +174,12 @@ static inline bool i2s_dma_is_rx_complete(cyhal_i2s_event_t event) {
}

static inline void i2s_dma_rx(machine_i2s_obj_t *self) {
cy_rslt_t result = cyhal_i2s_read_async(&self->i2s_obj, self->dma_active_buf_p, SIZEOF_HALF_DMA_BUFFER_IN_BYTES);
cy_rslt_t result = cyhal_i2s_read_async(&self->i2s_obj, self->dma_active_buf_p, SIZEOF_HALF_DMA_BUFFER);
i2s_assert_raise_val("I2S DMA read failed with return code %lx !", result);
}

static inline void i2s_dma_tx(machine_i2s_obj_t *self) {
cy_rslt_t result = cyhal_i2s_write_async(&self->i2s_obj, self->dma_active_buf_p, SIZEOF_HALF_DMA_BUFFER_IN_BYTES);
cy_rslt_t result = cyhal_i2s_write_async(&self->i2s_obj, self->dma_active_buf_p, SIZEOF_HALF_DMA_BUFFER);
i2s_assert_raise_val("I2S DMA write configure failed with return code %lx !", result);
}

Expand All @@ -189,12 +190,12 @@ static void i2s_dma_from_dmabuf_to_ringbuf(machine_i2s_obj_t *self) {

uint8_t dma_sample_size_in_bytes = (self->bits == 16? 2 : 4) * (self->format == STEREO ? 2: 1);
uint8_t *dma_buff_p = (uint8_t *)self->dma_idle_buf_p;
uint32_t num_bytes_needed_from_ringbuf = SIZEOF_HALF_DMA_BUFFER_IN_BYTES * (I2S_RX_FRAME_SIZE_IN_BYTES / dma_sample_size_in_bytes);
uint32_t num_bytes_needed_from_ringbuf = SIZEOF_HALF_DMA_BUFFER * (I2S_RX_FRAME_SIZE_IN_BYTES / dma_sample_size_in_bytes);

// when space exists, copy samples into ring buffer
if (ringbuf_available_space(&self->ring_buffer) >= num_bytes_needed_from_ringbuf) {
uint8_t f_index = get_frame_mapping_index(self->bits, self->format);
for (uint32_t i = 0; i < SIZEOF_HALF_DMA_BUFFER_IN_BYTES; i += dma_sample_size_in_bytes) {
for (uint32_t i = 0; i < SIZEOF_HALF_DMA_BUFFER; i += dma_sample_size_in_bytes) {
for (uint8_t j = 0; I2S_RX_FRAME_SIZE_IN_BYTES; j++) {
int8_t r_to_a_mapping = i2s_frame_map[f_index][i];
if (r_to_a_mapping != -1) {
Expand All @@ -212,24 +213,24 @@ static void i2s_dma_from_ringbuf_to_dmabuf(machine_i2s_obj_t *self) {
if (ringbuf_available_data(&self->ring_buffer) >= SIZEOF_HALF_DMA_BUFFER_IN_BYTES) {
uint8_t *dma_buffer_p = (uint8_t *)self->dma_idle_buf_p;
// Mono samples duplicate the sample in the right channel
if (self->mode == MONO) {
uint8_t bytes_per_sample = (self->bits == 16? 2 : 4);
for (uint32_t i = 0; i < SIZEOF_HALF_DMA_BUFFER_IN_BYTES * sizeof(uint32_t); i += (2 * bytes_per_sample)) {
for (uint8_t b = 0; b < bytes_per_sample; b++) {
ringbuf_pop(&self->ring_buffer, &dma_buffer_p[i + b]);
dma_buffer_p[i + b + 2 * bytes_per_sample] = dma_buffer_p[i + b];
}
}
} else if (self->mode == STEREO) {
for (uint32_t i = 0; i < SIZEOF_HALF_DMA_BUFFER_IN_BYTES * sizeof(uint32_t); i++) {
ringbuf_pop(&self->ring_buffer, &dma_buffer_p[i]);
}
// if (self->mode == MONO) {
// uint8_t bytes_per_sample = (self->bits == 16? 2 : 4);
// for (uint32_t i = 0; i < SIZEOF_HALF_DMA_BUFFER * sizeof(uint32_t); i += (2 * bytes_per_sample)) {
// for (uint8_t b = 0; b < bytes_per_sample; b++) {
// ringbuf_pop(&self->ring_buffer, &dma_buffer_p[i + b]);
// dma_buffer_p[i + b + 2 * bytes_per_sample] = dma_buffer_p[i + b];
// }
// }
// } else if (self->mode == STEREO) {
for (uint32_t i = 0; i < SIZEOF_HALF_DMA_BUFFER_IN_BYTES; i++) {
ringbuf_pop(&self->ring_buffer, &dma_buffer_p[i]);
}
// }
}
}

static void fill_app_buffer(machine_i2s_obj_t *self) {
for (uint16_t i = 0; i < SIZEOF_HALF_DMA_BUFFER_IN_BYTES; i++)
for (uint16_t i = 0; i < SIZEOF_HALF_DMA_BUFFER; i++)
{
// uint32_t value = i | (i + 1) << 8 | (i + 2) << 16 | (i + 3) << 24;
// self->dma_idle_buf_p[i] = value;
Expand Down Expand Up @@ -324,15 +325,15 @@ static void i2s_dma_irq_configure(machine_i2s_obj_t *self) {
}

static void i2s_dma_rx_init(machine_i2s_obj_t *self) {
cy_rslt_t result = cyhal_i2s_read_async(&self->i2s_obj, self->dma_active_buf_p, SIZEOF_HALF_DMA_BUFFER_IN_BYTES);
cy_rslt_t result = cyhal_i2s_read_async(&self->i2s_obj, self->dma_active_buf_p, SIZEOF_HALF_DMA_BUFFER);
i2s_assert_raise_val("I2S DMA read configure failed with return code %lx !", result);

result = cyhal_i2s_start_rx(&self->i2s_obj);
i2s_assert_raise_val("I2S rx start failed with return code %lx !", result);
}

static void i2s_dma_tx_init(machine_i2s_obj_t *self) {
cy_rslt_t result = cyhal_i2s_write_async(&self->i2s_obj, self->dma_active_buf_p, SIZEOF_HALF_DMA_BUFFER_IN_BYTES);
cy_rslt_t result = cyhal_i2s_write_async(&self->i2s_obj, self->dma_active_buf_p, SIZEOF_HALF_DMA_BUFFER);
i2s_assert_raise_val("I2S DMA write configure failed with return code %lx !", result);

result = cyhal_i2s_start_tx(&self->i2s_obj);
Expand All @@ -341,7 +342,7 @@ static void i2s_dma_tx_init(machine_i2s_obj_t *self) {

static inline void i2s_dma_init_buff(machine_i2s_obj_t *self) {
self->dma_active_buf_p = self->dma_buffer;
self->dma_idle_buf_p = &self->dma_buffer[SIZEOF_HALF_DMA_BUFFER_IN_BYTES];
self->dma_idle_buf_p = &self->dma_buffer[SIZEOF_HALF_DMA_BUFFER];
}

static void i2s_dma_init(machine_i2s_obj_t *self) {
Expand Down Expand Up @@ -424,6 +425,7 @@ static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *ar
self->callback_for_non_blocking = MP_OBJ_NULL;
self->io_mode = BLOCKING;

// // i2s_clock_configure(); //Need to be in synch with user configurable clocks
if (clock_set == 0) {
clock_init();
cyhal_system_delay_ms(1);
Expand All @@ -432,8 +434,6 @@ static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *ar
// // TODO: with all inputs validated make the objects of the i2s object.
// // TODO: then make the i2s object

// // i2s_clock_configure();

i2s_init(self, &audio_clock);
i2s_dma_irq_configure(self);
i2s_dma_init(self);
Expand Down

0 comments on commit d159aa1

Please sign in to comment.