Skip to content

Commit

Permalink
ports/psoc6/machine_i2s.c: WIP freq ok for TX but 32k and 44.1k.
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 25, 2024
1 parent 87adad3 commit 8c43451
Showing 1 changed file with 54 additions and 26 deletions.
80 changes: 54 additions & 26 deletions ports/psoc6/machine_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/* Clock Settings */
#define AUDIO_SYS_CLOCK_HZ 98000000u /* in Hz (Ideally 98.304 MHz) */
#define AUDIO_SYS_CLOCK_HZ_1 90000000u
#define AUDIO_SYS_CLOCK_HZ_1 90300000u

// uint32_t Audio_sys_clock_fz;
uint32_t Audio_sys_clock_fz = AUDIO_SYS_CLOCK_HZ;
Expand All @@ -30,10 +30,10 @@ cyhal_clock_t hf0_clock;
// TODO: DMA ping-pong buffer size was empirically determined. It is a tradeoff between:
// 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 (64)
#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))
#define SIZEOF_DMA_BUFFER_IN_BYTES (256 * sizeof(uint32_t))
#define SIZEOF_HALF_DMA_BUFFER_IN_BYTES (SIZEOF_DMA_BUFFER_IN_BYTES / 2)

// 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
Expand All @@ -56,6 +56,7 @@ typedef struct _machine_i2s_obj_t {
mp_hal_pin_obj_t sd;
uint16_t mode;
int8_t bits;
uint8_t channel_resolution_bits; // TODO: better name?
format_t format;
int32_t rate;
int32_t ibuf;
Expand Down Expand Up @@ -173,13 +174,28 @@ static inline bool i2s_dma_is_rx_complete(cyhal_i2s_event_t event) {
return 0u != (event & CYHAL_I2S_ASYNC_RX_COMPLETE);
}

uint8_t get_word_byte_size(machine_i2s_obj_t *self) {
uint8_t res_bits = self->channel_resolution_bits;
if (res_bits <= 8) {
return 1;
} else if (res_bits > 8 && res_bits <= 16) {
return 2;
} else if (res_bits > 16 && res_bits <= 24) {
return 3;
} else {
return 4;
}
}

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);
uint16_t dma_half_buff_word_size = SIZEOF_HALF_DMA_BUFFER_IN_BYTES / get_word_byte_size(self);
cy_rslt_t result = cyhal_i2s_read_async(&self->i2s_obj, self->dma_active_buf_p, dma_half_buff_word_size);
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);
uint16_t dma_half_buff_word_size = SIZEOF_HALF_DMA_BUFFER_IN_BYTES / get_word_byte_size(self);
cy_rslt_t result = cyhal_i2s_write_async(&self->i2s_obj, self->dma_active_buf_p, dma_half_buff_word_size);
i2s_assert_raise_val("I2S DMA write configure failed with return code %lx !", result);
}

Expand Down Expand Up @@ -217,12 +233,6 @@ static void i2s_dma_from_ringbuf_to_dmabuf(machine_i2s_obj_t *self) {
ringbuf_pop(&self->ring_buffer, &dma_buffer_p[i]);
}
}
// else {
// memset(dma_buffer_p, 0, SIZEOF_HALF_DMA_BUFFER_IN_BYTES);
// for (uint32_t i = 0; i < SIZEOF_HALF_DMA_BUFFER_IN_BYTES; i++) {
// dma_buffer_p[i] = 0;
// }
// }
}

static inline void i2s_dma_swap_active_dmabuf(machine_i2s_obj_t *self) {
Expand Down Expand Up @@ -276,8 +286,8 @@ static void i2s_init(machine_i2s_obj_t *self, cyhal_clock_t *clock) {
.is_tx_slave = false,
.is_rx_slave = false,
.mclk_hz = 0,
.channel_length = 32,
.word_length = self->bits,
.channel_length = self->bits,
.word_length = self->channel_resolution_bits,
.sample_rate_hz = self->rate
};

Expand Down Expand Up @@ -309,18 +319,16 @@ 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);
i2s_assert_raise_val("I2S DMA read configure failed with return code %lx !", result);
i2s_dma_rx(self);

result = cyhal_i2s_start_rx(&self->i2s_obj);
cy_rslt_t 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);
i2s_assert_raise_val("I2S DMA write configure failed with return code %lx !", result);
i2s_dma_tx(self);

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

Expand Down Expand Up @@ -374,14 +382,27 @@ static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *ar
mp_raise_ValueError(MP_ERROR_TEXT("invalid mode"));
}

// TODO: proper implementation between channel_bits and words_bits. Refactor proper naming.
// is Bits valid?
int8_t i2s_bits = args[ARG_bits].u_int;
if ((i2s_bits != 16) &&
(i2s_bits != 32)
) {
int8_t i2s_bits_resolution = args[ARG_bits].u_int;
if (i2s_bits_resolution < 1 || i2s_bits_resolution > 32) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid bits"));
}

int8_t i2s_bits;
if (i2s_bits_resolution <= 16) {
i2s_bits = 16;
} else {
i2s_bits = 32;
}

// int8_t i2s_bits = args[ARG_bits].u_int;
// if ((i2s_bits != 16) &&
// (i2s_bits != 32)
// ) {
// mp_raise_ValueError(MP_ERROR_TEXT("invalid bits"));
// }

// is Format valid?
format_t i2s_format = args[ARG_format].u_int;
if ((i2s_format != MONO) &&
Expand All @@ -402,12 +423,19 @@ static void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *ar
self->sd = sd;
self->mode = i2s_mode;
self->bits = i2s_bits;
self->channel_resolution_bits = i2s_bits_resolution;
self->format = i2s_format;
self->rate = args[ARG_rate].u_int;
if (self->rate == (8000 || 16000 || 32000 || 48000)) {
if (self->rate == 8000 ||
self->rate == 16000 ||
self->rate == 32000 ||
self->rate == 48000) {
Audio_sys_clock_fz = AUDIO_SYS_CLOCK_HZ;
} else {
} else if (self->rate == 22050 ||
self->rate == 44100) {
Audio_sys_clock_fz = AUDIO_SYS_CLOCK_HZ_1;
} else {
mp_raise_ValueError(MP_ERROR_TEXT("rate not supported"));
}
self->ibuf = ring_buffer_len;

Expand Down

0 comments on commit 8c43451

Please sign in to comment.