Skip to content

Commit

Permalink
ports/psoc6: I2S module functions.
Browse files Browse the repository at this point in the history
Signed-off-by: IFX-Anusha <[email protected]>
  • Loading branch information
IFX-Anusha committed Aug 24, 2023
1 parent d519141 commit 69cc929
Showing 1 changed file with 158 additions and 73 deletions.
231 changes: 158 additions & 73 deletions ports/psoc6/modules/machine/machine_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,20 @@

#if MICROPY_PY_MACHINE_I2S

/* Note that we are not able to achieve the desired frequency, so we round up
* the frequency values to avoid mismatches */
/* Master Clock (MCLK) Settings */
#define MCLK_FREQ_HZ 4083000u /* in Hz (Ideally 4.096 MHz) */
#define MCLK_DUTY_CYCLE 50.0f /* in % */
/* Clock Settings */
#define AUDIO_SYS_CLOCK_HZ 98000000u /* in Hz (Ideally 98.304 MHz) */
/* PWM MCLK Pin */
#define MCLK_PIN P13_0
/* Debounce delay for the button */
#define DEBOUNCE_DELAY_MS 10u /* in ms */
/* HFCLK1 Clock Divider */
#define HFCLK1_CLK_DIVIDER 4u

#define AUDIO_SYS_CLOCK_HZ 98000000u /* in Hz (Ideally 98.304 MHz) */

void clock_init(void);

cyhal_clock_t audio_clock;
cyhal_clock_t pll_clock;
cyhal_clock_t fll_clock;
cyhal_clock_t system_clock;

#define I2S_RX_FRAME_SIZE_IN_BYTES (8)

typedef enum {
RX,
TX
Expand Down Expand Up @@ -72,6 +65,8 @@ typedef struct _machine_i2s_obj_t {
format_t format;
int32_t rate;
int32_t ibuf;
mp_obj_t callback_for_non_blocking;
io_mode_t io_mode;
} machine_i2s_obj_t;

STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
Expand Down Expand Up @@ -136,6 +131,8 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args,
self->bits = i2s_bits;
self->format = i2s_format;
self->rate = args[ARG_rate].u_int;
self->ibuf = args[ARG_ibuf].u_int;
self->callback_for_non_blocking = MP_OBJ_NULL;

clock_init();
cyhal_system_delay_ms(1);
Expand All @@ -148,8 +145,8 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args,
.is_rx_slave = false,
.mclk_hz = 0,
.channel_length = 32,
.word_length = 32,
.sample_rate_hz = 16000,
.word_length = self->bits,
.sample_rate_hz = self->rate,
};
cy_rslt_t result = cyhal_i2s_init(&self->i2s_obj, &tx_pins, NULL, &config, &audio_clock);
if (result != CY_RSLT_SUCCESS) {
Expand Down Expand Up @@ -210,55 +207,6 @@ STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_pos_arg
}

machine_i2s_obj_t *self = mp_obj_malloc(machine_i2s_obj_t, &machine_i2s_type);

// clock_init();

/* Wait for the MCLK to clock the audio codec */
// cyhal_system_delay_ms(1);

// const cyhal_i2s_pins_t i2s_pins = {
// .sck = P13_1,
// .ws = P13_2,
// .data = P13_3,
// .mclk = NC,
// };
// const cyhal_i2s_config_t i2s_config = {
// .is_tx_slave = false, /* TX is Master */
// .is_rx_slave = false, /* RX not used */
// .mclk_hz = 0, /* External MCLK not used */
// .channel_length = 32, /* In bits */
// .word_length = 32, /* In bits */
// .sample_rate_hz = 16000, /* In Hz */
// };

// /* Initialize the User LED */
// cyhal_gpio_init(CYBSP_USER_LED, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, CYBSP_LED_STATE_OFF);

// /* Initialize the User Button */
// cyhal_gpio_init(CYBSP_USER_BTN, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_PULLUP, CYBSP_BTN_OFF);

// /* Initialize the I2S */
// cy_rslt_t result=cyhal_i2s_init(&self->i2s_obj, &i2s_pins, NULL, &i2s_config, &audio_clock);
// if(result==CY_RSLT_SUCCESS)
// {
// printf("I2S initialisation succes\r\n");
// cyhal_gpio_write(CYBSP_USER_LED, CYBSP_LED_STATE_ON);
// }
// else
// {
// printf("fail\r\n");
// printf("%lx\r\n",result);
// }

// machine_i2s_obj_t *self;
// if (MP_STATE_PORT(machine_i2s_obj[i2s_id]) == NULL) {
// self = mp_obj_malloc(machine_i2s_obj_t, &machine_i2s_type);
// MP_STATE_PORT(machine_i2s_obj[i2s_id]) = self;
// self->i2s_id = i2s_id;
// } else {
// self = MP_STATE_PORT(machine_i2s_obj[i2s_id]);
// machine_i2s_deinit(MP_OBJ_FROM_PTR(self));
// }
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args);
machine_i2s_init_helper(self, n_pos_args - 1, args + 1, &kw_args);
Expand All @@ -274,6 +222,150 @@ STATIC mp_obj_t machine_i2s_init(size_t n_pos_args, const mp_obj_t *pos_args, mp
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2s_init_obj, 1, machine_i2s_init);

STATIC mp_obj_t machine_i2s_readinto(mp_obj_t self_in, mp_obj_t buf_in) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
cy_rslt_t result;
if (self->mode != RX) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2S operation not supported"));
}
// get the buffer to write from
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);

if (self->io_mode == NON_BLOCKING) {
result = cyhal_i2s_read_async(&self->i2s_obj,bufinfo.buf, bufinfo.len);
if(result != CY_RSLT_SUCCESS)
{
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2S read failed with return code %lx !"), result);
}
}
else { // blocking or asyncio mode(asyncio - yet to implement)
result = cyhal_i2s_read(&self->i2s_obj,bufinfo.buf, &bufinfo.len);
if(result != CY_RSLT_SUCCESS)
{
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2S read failed with return code %lx !"), result);
}
}
return MP_OBJ_NEW_SMALL_INT(bufinfo.len);
}
MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_readinto_obj, machine_i2s_readinto);

STATIC mp_obj_t machine_i2s_write(mp_obj_t self_in, mp_obj_t buf_in) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);

if (self->mode != TX) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2S operation not supported"));
}

// get the buffer to write from
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);

if (self->io_mode == NON_BLOCKING) {


} else { // blocking or asyncio mode

}
return MP_OBJ_NEW_SMALL_INT(bufinfo.len);
}
MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_write_obj, machine_i2s_write);

STATIC mp_obj_t machine_i2s_irq(mp_obj_t self_in, mp_obj_t handler) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (handler != mp_const_none && !mp_obj_is_callable(handler)) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid callback"));
}

if (handler != mp_const_none) {
self->io_mode = NON_BLOCKING;
if(self->mode == RX)
{
/* 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_receive, &i2s);
/* Subscribe to the async complete event so that we can queue up another transfer when this one completes */
//cyhal_i2s_enable_event(&i2s, CYHAL_I2S_ASYNC_RX_COMPLETE, CYHAL_ISR_PRIORITY_DEFAULT, true);
/* Configure asynchronous transfers to use DMA to free up the CPU during transfers */
//cyhal_i2s_set_async_mode(&i2s, CYHAL_ASYNC_DMA, CYHAL_DMA_PRIORITY_DEFAULT);
}
else
{

}

} else {
self->io_mode = BLOCKING;
}

self->callback_for_non_blocking = handler;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_irq_obj, machine_i2s_irq);

// Shift() is typically used as a volume control.
// shift=1 increases volume by 6dB, shift=-1 decreases volume by 6dB
STATIC mp_obj_t machine_i2s_shift(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buf, ARG_bits, ARG_shift};
static const mp_arg_t allowed_args[] = {
// { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_bits, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_shift, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};

// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);

mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_RW);

int16_t *buf_16 = bufinfo.buf;
int32_t *buf_32 = bufinfo.buf;

uint8_t bits = args[ARG_bits].u_int;
int8_t shift = args[ARG_shift].u_int;

uint32_t num_audio_samples;
switch (bits) {
case 16:
num_audio_samples = bufinfo.len / sizeof(uint16_t);
break;

case 32:
num_audio_samples = bufinfo.len / sizeof(uint32_t);
break;

default:
mp_raise_ValueError(MP_ERROR_TEXT("invalid bits"));
break;
}

for (uint32_t i = 0; i < num_audio_samples; i++) {
switch (bits) {
case 16:
if (shift >= 0) {
buf_16[i] = buf_16[i] << shift;
} else {
buf_16[i] = buf_16[i] >> abs(shift);
}
break;
case 32:
if (shift >= 0) {
buf_32[i] = buf_32[i] << shift;
} else {
buf_32[i] = buf_32[i] >> abs(shift);
}
break;
}
}

return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2s_shift_fun_obj, 0, machine_i2s_shift);
STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(machine_i2s_shift_obj, MP_ROM_PTR(&machine_i2s_shift_fun_obj));

void clock_init(void) {
/* Initialize the PLL */
cyhal_clock_reserve(&pll_clock, &CYHAL_CLOCK_PLL[0]);
Expand Down Expand Up @@ -301,13 +393,13 @@ void clock_init(void) {
STATIC const mp_rom_map_elem_t machine_i2s_locals_dict_table[] = {
// Methods
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2s_init_obj) },
// { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
// { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_i2s_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2s_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2s_deinit_obj) },
// { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_i2s_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_i2s_irq_obj) },

// Static method
// { MP_ROM_QSTR(MP_QSTR_shift), MP_ROM_PTR(&machine_i2s_shift_obj) },
{ MP_ROM_QSTR(MP_QSTR_shift), MP_ROM_PTR(&machine_i2s_shift_obj) },

// Constants
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_INT(RX) },
Expand All @@ -317,20 +409,13 @@ STATIC const mp_rom_map_elem_t machine_i2s_locals_dict_table[] = {
};
MP_DEFINE_CONST_DICT(machine_i2s_locals_dict, machine_i2s_locals_dict_table);

STATIC const mp_stream_p_t i2s_stream_p = {
// .read = machine_i2s_stream_read,
// .write = machine_i2s_stream_write,
// .ioctl = machine_i2s_ioctl,
.is_text = false,
};

MP_DEFINE_CONST_OBJ_TYPE(
machine_i2s_type,
MP_QSTR_I2S,
MP_TYPE_FLAG_ITER_IS_STREAM,
make_new, machine_i2s_make_new,
print, machine_i2s_print,
protocol, &i2s_stream_p,
locals_dict, &machine_i2s_locals_dict
);

Expand Down

0 comments on commit 69cc929

Please sign in to comment.