Skip to content

INITIAL: I2S support in C33 #256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions cores/arduino/IRQManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define ADC_PRIORITY 12
#define CAN_PRIORITY 12
#define CANFD_PRIORITY 12
#define I2S_PRIORITY 12
#define FIRST_INT_SLOT_FREE 0

IRQManager::IRQManager() : last_interrupt_index{0} {
Expand Down Expand Up @@ -930,6 +931,41 @@ bool IRQManager::addPeripheral(Peripheral_t p, void *cfg) {
}
}
#endif

#if I2S_HOWMANY > 0
/* **********************************************************************
I2S
********************************************************************** */
else if(p == IRQ_I2S && cfg != NULL) {
i2s_cfg_t *i2s_cfg = (i2s_cfg_t *)cfg;

if(i2s_cfg->txi_irq == FSP_INVALID_VECTOR) {
i2s_cfg->txi_irq = (IRQn_Type)last_interrupt_index;
i2s_cfg->txi_ipl = I2S_PRIORITY;
*(irq_ptr + last_interrupt_index) = (uint32_t)ssi_txi_isr;
R_ICU->IELSR[last_interrupt_index] = BSP_PRV_IELS_ENUM(EVENT_SSI0_TXI);
R_FSP_IsrContextSet(i2s_cfg->txi_irq, (void*)i2s_cfg->p_context);
last_interrupt_index++;
}
if(i2s_cfg->rxi_irq == FSP_INVALID_VECTOR) {
i2s_cfg->rxi_irq = (IRQn_Type)last_interrupt_index;
i2s_cfg->rxi_ipl = I2S_PRIORITY;
*(irq_ptr + last_interrupt_index) = (uint32_t)ssi_rxi_isr;
R_ICU->IELSR[last_interrupt_index] = BSP_PRV_IELS_ENUM(EVENT_SSI0_RXI);
R_FSP_IsrContextSet(i2s_cfg->rxi_irq, (void*)i2s_cfg->p_context);
last_interrupt_index++;
}
if(i2s_cfg->int_irq == FSP_INVALID_VECTOR) {
i2s_cfg->int_irq = (IRQn_Type)last_interrupt_index;
i2s_cfg->idle_err_ipl = I2S_PRIORITY;
*(irq_ptr + last_interrupt_index) = (uint32_t)ssi_int_isr;
R_ICU->IELSR[last_interrupt_index] = BSP_PRV_IELS_ENUM(EVENT_SSI0_INT);
R_FSP_IsrContextSet(i2s_cfg->int_irq, (void*)i2s_cfg->p_context);
last_interrupt_index++;
}
}
#endif

else {
rv = false;
}
Expand Down
12 changes: 11 additions & 1 deletion cores/arduino/IRQManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
#include "r_external_irq_api.h"
#endif

#if I2S_HOWMANY > 0
#include "r_ssi.h"
extern "C" {
void ssi_txi_isr(void);
void ssi_rxi_isr(void);
void ssi_int_isr(void);
}
#endif

#include "r_timer_api.h"

#ifdef ELC_EVENT_DMAC0_INT
Expand All @@ -43,7 +52,8 @@ typedef enum {
IRQ_CAN,
IRQ_ETHERNET,
IRQ_CANFD,
IRQ_SDCARD
IRQ_SDCARD,
IRQ_I2S
} Peripheral_t;

#if SDCARD_HOWMANY > 0
Expand Down
4 changes: 4 additions & 0 deletions cores/arduino/cm_backtrace/fault_handler/gcc/cmb_fault.S
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
* Created on: 2016-12-16
*/

#ifdef BACKTRACE_SUPPORT

.syntax unified
.thumb
.text
Expand All @@ -41,3 +43,5 @@ HardFault_Handler:

Fault_Loop:
BL Fault_Loop /* while(1) */

#endif
77 changes: 77 additions & 0 deletions libraries/I2S/I2S.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include "I2S.h"

#define BUFF_SIZE 1024
static volatile i2s_event_t g_i2s_event = I2S_EVENT_TX_EMPTY; //an actual event updates in callback

extern "C" ssi_instance_ctrl_t g_i2s0_ctrl;
extern "C" i2s_cfg_t g_i2s0_cfg;

static volatile int32_t g_dest_buff[BUFF_SIZE] __attribute__((aligned(4)));
static volatile int16_t g_final[BUFF_SIZE / 2] __attribute__((aligned(4)));

bool I2SClass::begin() {

IRQManager::getInstance().addPeripheral(IRQ_I2S, &g_i2s0_cfg);
auto err = R_SSI_Open(&g_i2s0_ctrl, &g_i2s0_cfg);

if (err != FSP_SUCCESS) {
return false;
}

// Need to find the timer connected to GPT_TIMER 2A for internal clock
auto pwm = new PwmOut(64);
pwm->begin(100, 50, true);

pinPeripheral(BSP_IO_PORT_01_PIN_12, (uint32_t) (IOPORT_CFG_PERIPHERAL_PIN | IOPORT_PERIPHERAL_SSI));
pinPeripheral(BSP_IO_PORT_01_PIN_13, (uint32_t) (IOPORT_CFG_PERIPHERAL_PIN | IOPORT_PERIPHERAL_SSI));
pinPeripheral(BSP_IO_PORT_01_PIN_14, (uint32_t) (IOPORT_CFG_PERIPHERAL_PIN | IOPORT_PERIPHERAL_SSI));
pinPeripheral(BSP_IO_PORT_01_PIN_15, (uint32_t) (IOPORT_CFG_PERIPHERAL_PIN | IOPORT_PERIPHERAL_SSI));

err = R_SSI_Read(&g_i2s0_ctrl, (void*)g_dest_buff, BUFF_SIZE * sizeof(g_dest_buff[0]));

if (err != FSP_SUCCESS) {
return false;
}
return true;
}

static volatile bool hasData = false;
extern "C" void i2s_callback(i2s_callback_args_t *p_args)
{
if ( NULL != p_args)
{
/* capture callback event for validating the i2s transfer event*/
g_i2s_event = p_args->event;
if (g_i2s_event == I2S_EVENT_RX_FULL) {
hasData = true;
}
if (g_i2s_event == I2S_EVENT_IDLE) {
R_SSI_Read(&g_i2s0_ctrl, (void*)g_dest_buff, BUFF_SIZE * sizeof(g_dest_buff[0]));
}
}
}

bool I2SClass::available() {
return hasData;
}

size_t I2SClass::read(int16_t* buf) {

while (hasData == false) {
delayMicroseconds(1);
}

for (int i = 0; i < BUFF_SIZE; i += 2) {
if (g_dest_buff[i] != 0) {
g_final[i / 2] = (int16_t)((((int32_t)((g_dest_buff[i] << 14))) / (1 << 14)) + 0x1C00);
} else {
g_final[i / 2] = 0;
}
}

memcpy(buf, (void*)g_final, BUFF_SIZE);
hasData = false;
return BUFF_SIZE;
}

I2SClass I2S;
16 changes: 16 additions & 0 deletions libraries/I2S/I2S.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "r_i2s_api.h"
#include "r_ssi.h"
#include "pwm.h"

class I2SClass {
public:
I2SClass() {}
bool begin();
bool start() {}
bool stop() {}
bool available();
size_t read(int16_t* buf);
size_t write(int32_t* buf, size_t len) {}
};

extern I2SClass I2S;
71 changes: 71 additions & 0 deletions libraries/I2S/config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "r_i2s_api.h"
#include "r_ssi.h"
#include "r_dtc.h"

void i2s_callback(i2s_callback_args_t *p_args);

dtc_instance_ctrl_t g_transfer0_ctrl;

transfer_info_t g_transfer0_info =
{ .transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_FIXED,
.transfer_settings_word_b.repeat_area = TRANSFER_REPEAT_AREA_SOURCE,
.transfer_settings_word_b.irq = TRANSFER_IRQ_END,
.transfer_settings_word_b.chain_mode = TRANSFER_CHAIN_MODE_DISABLED,
.transfer_settings_word_b.src_addr_mode = TRANSFER_ADDR_MODE_INCREMENTED,
.transfer_settings_word_b.size = TRANSFER_SIZE_4_BYTE,
.transfer_settings_word_b.mode = TRANSFER_MODE_BLOCK,
.p_dest = (void*) NULL,
.p_src = (void const*) NULL,
.num_blocks = 0,
.length = 0, };

const dtc_extended_cfg_t g_transfer0_cfg_extend =
{ .activation_source = VECTOR_NUMBER_SSI0_TXI, };

const transfer_cfg_t g_transfer0_cfg =
{
.p_info = &g_transfer0_info,
.p_extend = &g_transfer0_cfg_extend
};

/* Instance structure to use this module. */
const transfer_instance_t g_transfer0 =
{
.p_ctrl = &g_transfer0_ctrl,
.p_cfg = &g_transfer0_cfg,
.p_api = &g_transfer_on_dtc
};
ssi_instance_ctrl_t g_i2s0_ctrl;

/** SSI instance configuration */
const ssi_extended_cfg_t g_i2s0_cfg_extend =
{
.audio_clock = SSI_AUDIO_CLOCK_INTERNAL,
.bit_clock_div = SSI_CLOCK_DIV_1
};

/** I2S interface configuration */
const i2s_cfg_t g_i2s0_cfg =
{
.channel = 0,
.pcm_width = I2S_PCM_WIDTH_18_BITS,
//.pcm_width = I2S_PCM_WIDTH_32_BITS,
.operating_mode = I2S_MODE_MASTER,
.word_length = I2S_WORD_LENGTH_32_BITS,
.ws_continue = I2S_WS_CONTINUE_ON,
.p_callback = i2s_callback,
.p_context = &g_i2s0_ctrl,
.p_extend = &g_i2s0_cfg_extend,
.txi_irq = FSP_INVALID_VECTOR,
.rxi_irq = FSP_INVALID_VECTOR,
.int_irq = FSP_INVALID_VECTOR,
.txi_ipl = (2),
.rxi_ipl = (2),
.idle_err_ipl = (2),
.p_transfer_tx = NULL, // MAY be null
.p_transfer_rx = NULL,
};

/* Instance structure to use this module. */
const i2s_instance_t g_i2s0 =
{ .p_ctrl = &g_i2s0_ctrl, .p_cfg = &g_i2s0_cfg, .p_api = &g_i2s_on_ssi };
14 changes: 14 additions & 0 deletions libraries/I2S/examples/RecordAndStream/RecordAndStream.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "I2S.h"

int16_t buffer[1024];

void setup() {
Serial.begin(2000000);
I2S.begin();
}

void loop() {
while (!I2S.available()) {}
auto howMany = I2S.read(buffer);
Serial.write((uint8_t*)buffer, howMany);
}
1 change: 1 addition & 0 deletions variants/PORTENTA_C33/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ static const uint8_t SS = PIN_SPI_CS;
/****** SDCARD CORE DEFINES *******/
#define SDCARD_HOWMANY 1

#define I2S_HOWMANY 1

#define EXT_INTERRUPTS_HOWMANY 8

Expand Down