Merge pull request #8291 from tannewt/i2s_mclk

Add I2S MCLK support to iMX RT
This commit is contained in:
Scott Shawcroft 2023-08-24 15:46:08 -07:00 committed by GitHub
commit ee2207d386
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 124 additions and 11 deletions

View File

@ -98,7 +98,10 @@ void i2sout_reset(void) {
// Caller validates that pins are free.
void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select,
const mcu_pin_obj_t *data, bool left_justified) {
const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, bool left_justified) {
if (main_clock != NULL) {
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_main_clock);
}
uint8_t serializer = 0xff;
uint8_t bc_clock_unit = 0xff;
uint8_t ws_clock_unit = 0xff;

View File

@ -49,8 +49,10 @@
// Caller validates that pins are free.
void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select,
const mcu_pin_obj_t *data, bool left_justified) {
const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, bool left_justified) {
if (main_clock != NULL) {
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_main_clock);
}
port_i2s_allocate_init(&self->peripheral, left_justified);
i2s_pin_config_t i2s_pin_config = {

View File

@ -74,13 +74,22 @@ STATIC void config_periph_pin(const mcu_periph_obj_t *periph) {
// Caller validates that pins are free.
void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select,
const mcu_pin_obj_t *data, bool left_justified) {
const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, bool left_justified) {
int instance = -1;
const mcu_periph_obj_t *bclk_periph = find_pin_function(mcu_i2s_tx_bclk_list, bit_clock, &instance, MP_QSTR_bit_clock);
const mcu_periph_obj_t *sync_periph = find_pin_function(mcu_i2s_tx_sync_list, word_select, &instance, MP_QSTR_word_select);
const mcu_periph_obj_t *data_periph = find_pin_function(mcu_i2s_tx_data0_list, data, &instance, MP_QSTR_data);
if (main_clock != NULL) {
const mcu_periph_obj_t *mclk_periph = find_pin_function(mcu_i2s_mclk_list, main_clock, &instance, MP_QSTR_main_clock);
self->mclk = main_clock;
claim_pin(main_clock);
config_periph_pin(mclk_periph);
IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK << (instance - 1);
}
self->instance = instance;
sai_transceiver_t config;
SAI_GetClassicI2SConfig(&config, 16, kSAI_Stereo, 1);
config.syncMode = kSAI_ModeAsync;
@ -121,6 +130,13 @@ void common_hal_audiobusio_i2sout_deinit(audiobusio_i2sout_obj_t *self) {
common_hal_reset_pin(self->data);
self->data = NULL;
if (self->mclk != NULL) {
IOMUXC_GPR->GPR1 &= ~(IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK << (self->instance - 1));
common_hal_reset_pin(self->mclk);
self->mclk = NULL;
}
}
void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,

View File

@ -39,6 +39,8 @@ typedef struct {
const mcu_pin_obj_t *bit_clock;
const mcu_pin_obj_t *word_select;
const mcu_pin_obj_t *data;
const mcu_pin_obj_t *mclk;
uint8_t instance;
} audiobusio_i2sout_obj_t;
#endif

View File

@ -174,6 +174,12 @@ const mcu_periph_obj_t mcu_i2s_tx_sync_list[2] = {
PERIPH_PIN(3, 1, 0, 0, &pin_GPIO_SD_00),
};
const mcu_periph_obj_t mcu_i2s_mclk_list[2] = {
PERIPH_PIN(1, 0, 0, 0, &pin_GPIO_08),
PERIPH_PIN(3, 1, 0, 0, &pin_GPIO_00),
};
const mcu_periph_obj_t mcu_mqs_left_list[1] = {
PERIPH_PIN(3, 4, 0, 0, &pin_GPIO_AD_01),
};

View File

@ -56,6 +56,7 @@ extern const mcu_periph_obj_t mcu_i2s_rx_sync_list[2];
extern const mcu_periph_obj_t mcu_i2s_tx_bclk_list[2];
extern const mcu_periph_obj_t mcu_i2s_tx_data0_list[2];
extern const mcu_periph_obj_t mcu_i2s_tx_sync_list[2];
extern const mcu_periph_obj_t mcu_i2s_mclk_list[2];
extern const mcu_periph_obj_t mcu_mqs_left_list[1];
extern const mcu_periph_obj_t mcu_mqs_right_list[1];

View File

@ -159,6 +159,16 @@ const mcu_periph_obj_t mcu_i2s_tx_sync_list[4] = {
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_SD_B1_07),
};
const mcu_periph_obj_t mcu_i2s_mclk_list[5] = {
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_EMC_20),
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_AD_B0_03),
PERIPH_PIN(2, 3, 0, 0, &pin_GPIO_EMC_16),
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_17),
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_SD_B1_05),
};
const mcu_periph_obj_t mcu_mqs_left_list[2] = {
PERIPH_PIN(3, 2, 0, 0, &pin_GPIO_EMC_17),
PERIPH_PIN(3, 1, 0, 0, &pin_GPIO_AD_B0_07),

View File

@ -56,6 +56,7 @@ extern const mcu_periph_obj_t mcu_i2s_rx_sync_list[3];
extern const mcu_periph_obj_t mcu_i2s_tx_bclk_list[4];
extern const mcu_periph_obj_t mcu_i2s_tx_data0_list[4];
extern const mcu_periph_obj_t mcu_i2s_tx_sync_list[4];
extern const mcu_periph_obj_t mcu_i2s_mclk_list[5];
extern const mcu_periph_obj_t mcu_mqs_left_list[2];
extern const mcu_periph_obj_t mcu_mqs_right_list[2];

View File

@ -268,6 +268,20 @@ const mcu_periph_obj_t mcu_i2s_tx_sync_list[7] = {
PERIPH_PIN(3, 3, kIOMUXC_SAI3_TX_SYNC_SELECT_INPUT, 1, &pin_GPIO_EMC_34),
};
const mcu_periph_obj_t mcu_i2s_mclk_list[9] = {
PERIPH_PIN(1, 2, kIOMUXC_SAI1_MCLK_SELECT_INPUT, 0, &pin_GPIO_SD_B0_00),
PERIPH_PIN(1, 3, kIOMUXC_SAI1_MCLK_SELECT_INPUT, 1, &pin_GPIO_AD_B0_03),
PERIPH_PIN(1, 3, kIOMUXC_SAI1_MCLK_SELECT_INPUT, 2, &pin_GPIO_AD_B1_00),
PERIPH_PIN(1, 3, kIOMUXC_SAI1_MCLK_SELECT_INPUT, 3, &pin_GPIO_EMC_20),
PERIPH_PIN(2, 3, kIOMUXC_SAI2_MCLK_SELECT_INPUT, 0, &pin_GPIO_SD_B0_00),
PERIPH_PIN(2, 3, kIOMUXC_SAI2_MCLK_SELECT_INPUT, 1, &pin_GPIO_EMC_16),
PERIPH_PIN(3, 3, kIOMUXC_SAI3_MCLK_SELECT_INPUT, 0, &pin_GPIO_SD_B1_05),
PERIPH_PIN(3, 3, kIOMUXC_SAI3_MCLK_SELECT_INPUT, 1, &pin_GPIO_EMC_17),
PERIPH_PIN(3, 3, kIOMUXC_SAI3_MCLK_SELECT_INPUT, 2, &pin_GPIO_EMC_28),
};
const mcu_periph_obj_t mcu_mqs_left_list[3] = {
PERIPH_PIN(3, 2, 0, 0, &pin_GPIO_EMC_17),
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_38),

View File

@ -56,6 +56,7 @@ extern const mcu_periph_obj_t mcu_i2s_rx_sync_list[7];
extern const mcu_periph_obj_t mcu_i2s_tx_bclk_list[7];
extern const mcu_periph_obj_t mcu_i2s_tx_data0_list[7];
extern const mcu_periph_obj_t mcu_i2s_tx_sync_list[7];
extern const mcu_periph_obj_t mcu_i2s_mclk_list[9];
extern const mcu_periph_obj_t mcu_mqs_left_list[3];
extern const mcu_periph_obj_t mcu_mqs_right_list[3];

View File

@ -254,6 +254,17 @@ const mcu_periph_obj_t mcu_i2s_tx_sync_list[6] = {
PERIPH_PIN(3, 8, 0, 0, &pin_GPIO_SD_B1_02),
};
const mcu_periph_obj_t mcu_i2s_mclk_list[6] = {
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_B0_13),
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_SD_B1_03),
PERIPH_PIN(2, 2, 0, 0, &pin_GPIO_EMC_07),
PERIPH_PIN(2, 3, 0, 0, &pin_GPIO_AD_B0_10),
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_37),
PERIPH_PIN(3, 8, 0, 0, &pin_GPIO_SD_B1_04),
};
const mcu_periph_obj_t mcu_mqs_left_list[3] = {
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_14),
PERIPH_PIN(3, 1, 0, 0, &pin_GPIO_AD_B0_05),

View File

@ -56,6 +56,7 @@ extern const mcu_periph_obj_t mcu_i2s_rx_sync_list[6];
extern const mcu_periph_obj_t mcu_i2s_tx_bclk_list[6];
extern const mcu_periph_obj_t mcu_i2s_tx_data0_list[6];
extern const mcu_periph_obj_t mcu_i2s_tx_sync_list[6];
extern const mcu_periph_obj_t mcu_i2s_mclk_list[6];
extern const mcu_periph_obj_t mcu_mqs_left_list[3];
extern const mcu_periph_obj_t mcu_mqs_right_list[3];

View File

@ -267,6 +267,17 @@ const mcu_periph_obj_t mcu_i2s_tx_sync_list[6] = {
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_39),
};
const mcu_periph_obj_t mcu_i2s_mclk_list[6] = {
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_AD_B1_09),
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_B0_13),
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_SD_B1_03),
PERIPH_PIN(2, 2, 0, 0, &pin_GPIO_EMC_07),
PERIPH_PIN(2, 3, 0, 0, &pin_GPIO_AD_B0_10),
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_37),
};
const mcu_periph_obj_t mcu_mqs_left_list[3] = {
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_14),
PERIPH_PIN(3, 1, 0, 0, &pin_GPIO_AD_B0_05),

View File

@ -56,6 +56,7 @@ extern const mcu_periph_obj_t mcu_i2s_rx_sync_list[6];
extern const mcu_periph_obj_t mcu_i2s_tx_bclk_list[6];
extern const mcu_periph_obj_t mcu_i2s_tx_data0_list[6];
extern const mcu_periph_obj_t mcu_i2s_tx_sync_list[6];
extern const mcu_periph_obj_t mcu_i2s_mclk_list[6];
extern const mcu_periph_obj_t mcu_mqs_left_list[3];
extern const mcu_periph_obj_t mcu_mqs_right_list[3];

View File

@ -272,6 +272,18 @@ const mcu_periph_obj_t mcu_i2s_tx_sync_list[7] = {
PERIPH_PIN(3, 8, 0, 0, &pin_GPIO_SD_B1_02),
};
const mcu_periph_obj_t mcu_i2s_mclk_list[7] = {
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_AD_B1_09),
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_B0_13),
PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_SD_B1_03),
PERIPH_PIN(2, 2, 0, 0, &pin_GPIO_EMC_07),
PERIPH_PIN(2, 3, 0, 0, &pin_GPIO_AD_B0_10),
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_37),
PERIPH_PIN(3, 8, 0, 0, &pin_GPIO_SD_B1_04),
};
const mcu_periph_obj_t mcu_mqs_left_list[3] = {
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_14),
PERIPH_PIN(3, 1, 0, 0, &pin_GPIO_AD_B0_05),

View File

@ -56,6 +56,7 @@ extern const mcu_periph_obj_t mcu_i2s_rx_sync_list[7];
extern const mcu_periph_obj_t mcu_i2s_tx_bclk_list[7];
extern const mcu_periph_obj_t mcu_i2s_tx_data0_list[7];
extern const mcu_periph_obj_t mcu_i2s_tx_sync_list[7];
extern const mcu_periph_obj_t mcu_i2s_mclk_list[7];
extern const mcu_periph_obj_t mcu_mqs_left_list[3];
extern const mcu_periph_obj_t mcu_mqs_right_list[3];

View File

@ -237,6 +237,15 @@ const mcu_periph_obj_t mcu_i2s_tx_sync_list[4] = {
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_B2_16),
};
const mcu_periph_obj_t mcu_i2s_mclk_list[4] = {
PERIPH_PIN(1, 0, 0, 0, &pin_GPIO_AD_17),
PERIPH_PIN(1, 4, 0, 0, &pin_GPIO_DISP_B2_03),
PERIPH_PIN(2, 2, 0, 0, &pin_GPIO_EMC_B2_04),
PERIPH_PIN(3, 3, 0, 0, &pin_GPIO_EMC_B2_17),
};
const mcu_periph_obj_t mcu_mqs_left_list[2] = {
PERIPH_PIN(3, 2, 0, 0, &pin_GPIO_EMC_B1_41),
PERIPH_PIN(3, 2, 0, 0, &pin_GPIO_DISP_B2_01),

View File

@ -56,6 +56,7 @@ extern const mcu_periph_obj_t mcu_i2s_rx_sync_list[4];
extern const mcu_periph_obj_t mcu_i2s_tx_bclk_list[4];
extern const mcu_periph_obj_t mcu_i2s_tx_data0_list[4];
extern const mcu_periph_obj_t mcu_i2s_tx_sync_list[4];
extern const mcu_periph_obj_t mcu_i2s_mclk_list[4];
extern const mcu_periph_obj_t mcu_mqs_left_list[2];
extern const mcu_periph_obj_t mcu_mqs_right_list[2];

View File

@ -6,7 +6,7 @@ SIGNALS = {
"LPI2C": ["SDA", "SCL"],
"LPSPI": ["SCK", "SDO", "SDI"],
"LPUART": ["RX", "TX", "RTS", "CTS"],
"I2S": ["RX_DATA0", "RX_SYNC", "TX_BCLK", "TX_DATA0", "TX_SYNC"],
"I2S": ["RX_DATA0", "RX_SYNC", "TX_BCLK", "TX_DATA0", "TX_SYNC", "MCLK"],
"MQS": ["LEFT", "RIGHT"],
}

View File

@ -202,7 +202,10 @@ static void i2s_buffer_fill(audiobusio_i2sout_obj_t *self) {
void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select,
const mcu_pin_obj_t *data, bool left_justified) {
const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, bool left_justified) {
if (main_clock != NULL) {
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_main_clock);
}
if (instance) {
mp_raise_RuntimeError(translate("Device in use"));
}

View File

@ -103,7 +103,10 @@ void i2sout_reset(void) {
// Caller validates that pins are free.
void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select,
const mcu_pin_obj_t *data, bool left_justified) {
const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, bool left_justified) {
if (main_clock != NULL) {
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_main_clock);
}
if (bit_clock->number != word_select->number - 1) {
mp_raise_ValueError(translate("Bit clock and word select must be sequential pins"));
}

View File

@ -44,13 +44,15 @@
//| word_select: microcontroller.Pin,
//| data: microcontroller.Pin,
//| *,
//| left_justified: bool
//| main_clock: Optional[microcontroller.Pin] = None,
//| left_justified: bool = False
//| ) -> None:
//| """Create a I2SOut object associated with the given pins.
//|
//| :param ~microcontroller.Pin bit_clock: The bit clock (or serial clock) pin
//| :param ~microcontroller.Pin word_select: The word select (or left/right clock) pin
//| :param ~microcontroller.Pin data: The data pin
//| :param ~microcontroller.Pin main_clock: The main clock pin
//| :param bool left_justified: True when data bits are aligned with the word select clock. False
//| when they are shifted by one to match classic I2S protocol.
//|
@ -100,11 +102,12 @@ STATIC mp_obj_t audiobusio_i2sout_make_new(const mp_obj_type_t *type, size_t n_a
mp_raise_NotImplementedError_varg(translate("%q"), MP_QSTR_I2SOut);
return NULL; // Not reachable.
#else
enum { ARG_bit_clock, ARG_word_select, ARG_data, ARG_left_justified };
enum { ARG_bit_clock, ARG_word_select, ARG_data, ARG_main_clock, ARG_left_justified };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_bit_clock, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_word_select, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_data, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_main_clock, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
{ MP_QSTR_left_justified, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_bool = false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@ -113,10 +116,11 @@ STATIC mp_obj_t audiobusio_i2sout_make_new(const mp_obj_type_t *type, size_t n_a
const mcu_pin_obj_t *bit_clock = validate_obj_is_free_pin(args[ARG_bit_clock].u_obj, MP_QSTR_bit_clock);
const mcu_pin_obj_t *word_select = validate_obj_is_free_pin(args[ARG_word_select].u_obj, MP_QSTR_word_select);
const mcu_pin_obj_t *data = validate_obj_is_free_pin(args[ARG_data].u_obj, MP_QSTR_data);
const mcu_pin_obj_t *main_clock = validate_obj_is_free_pin_or_none(args[ARG_main_clock].u_obj, MP_QSTR_main_clock);
audiobusio_i2sout_obj_t *self = m_new_obj_with_finaliser(audiobusio_i2sout_obj_t);
self->base.type = &audiobusio_i2sout_type;
common_hal_audiobusio_i2sout_construct(self, bit_clock, word_select, data, args[ARG_left_justified].u_bool);
common_hal_audiobusio_i2sout_construct(self, bit_clock, word_select, data, main_clock, args[ARG_left_justified].u_bool);
return MP_OBJ_FROM_PTR(self);
#endif

View File

@ -37,7 +37,7 @@ extern const mp_obj_type_t audiobusio_i2sout_type;
void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select, const mcu_pin_obj_t *data,
bool left_justified);
const mcu_pin_obj_t *main_clock, bool left_justified);
void common_hal_audiobusio_i2sout_deinit(audiobusio_i2sout_obj_t *self);
bool common_hal_audiobusio_i2sout_deinited(audiobusio_i2sout_obj_t *self);