Skip to content

Commit c6bc9c4

Browse files
committed
mimxrt10xx: implement i2sout
tested on metro m7 (green prototype version) with max98357a i2s amplifier and the following test code: ```py import board import time import digitalio from audiobusio import I2SOut from audiocore import RawSample from microcontroller import pin from ulab import numpy as np n = np.array(np.sin(np.linspace(0, np.pi*2, 218, endpoint=False)) * 200, dtype=np.int16) print(n) r = RawSample(n, sample_rate=8000, channel_count=2) def main(): with digitalio.DigitalInOut(board.LED) as l: l.switch_to_output(True) value = False while True: with I2SOut(pin.GPIO_06, pin.GPIO_07, pin.GPIO_04) as i: time.sleep(.01) l.value = value = not value i.play(r, loop=True) print(i.playing) time.sleep(.5) i.stop() print("STOPPED") print(i.playing) time.sleep(.5) i.play(r, loop=True) print(i.playing) print("PLAY AGAIN") time.sleep(.5) time.sleep(1) ``` Only stereo, 16-bit, raw samples were tested; the sample rate is actually fixed at 48kHz in the core right now. There is more to do, but the basics work. # Conflicts: # ports/mimxrt10xx/Makefile # ports/mimxrt10xx/mpconfigport.mk
1 parent 1e1172b commit c6bc9c4

File tree

20 files changed

+878
-21
lines changed

20 files changed

+878
-21
lines changed

ports/mimxrt10xx/Makefile

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ SRC_SDK := \
119119
drivers/lpuart/fsl_lpuart.c \
120120
drivers/ocotp/fsl_ocotp.c \
121121
drivers/pwm/fsl_pwm.c \
122+
drivers/sai/fsl_sai.c \
122123
drivers/snvs_hp/fsl_snvs_hp.c \
123124
drivers/snvs_lp/fsl_snvs_lp.c \
124125
drivers/tempmon/fsl_tempmon.c \
@@ -146,11 +147,6 @@ SRC_C += \
146147

147148
endif
148149

149-
# TODO
150-
#ifeq ($(CIRCUITPY_AUDIOBUSIO),1)
151-
#SRC_C += peripherals/samd/i2s.c peripherals/samd/$(CHIP_FAMILY)/i2s.c
152-
#endif
153-
#
154150
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
155151
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
156152
$(addprefix common-hal/, $(SRC_COMMON_HAL))

ports/mimxrt10xx/background.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ void PLACE_IN_ITCM(port_background_task)(void) {
3535
}
3636

3737
void port_background_tick(void) {
38-
#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
39-
audio_dma_background();
40-
#endif
4138
}
4239

4340
void port_start_background_task(void) {

ports/mimxrt10xx/boards/metro_m7_1011/pins.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,9 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
5656
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) },
5757
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
5858
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
59+
60+
{ MP_ROM_QSTR(MP_QSTR_I2S_WSEL), MP_ROM_PTR(&pin_GPIO_06) }, // D10
61+
{ MP_ROM_QSTR(MP_QSTR_I2S_BCLK), MP_ROM_PTR(&pin_GPIO_07) }, // D9
62+
{ MP_ROM_QSTR(MP_QSTR_I2S_DOUT), MP_ROM_PTR(&pin_GPIO_04) }, // D12
5963
};
6064
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <stdint.h>
28+
#include <string.h>
29+
30+
#include "mpconfigport.h"
31+
32+
// Some boards don't implement I2SOut, so suppress any routines from here.
33+
#if CIRCUITPY_AUDIOBUSIO_I2SOUT
34+
35+
#include "py/gc.h"
36+
#include "py/mperrno.h"
37+
#include "py/runtime.h"
38+
#include "common-hal/audiobusio/I2SOut.h"
39+
#include "shared-bindings/audiobusio/I2SOut.h"
40+
#include "shared-bindings/audiocore/RawSample.h"
41+
#include "shared-bindings/microcontroller/Pin.h"
42+
#include "supervisor/shared/translate/translate.h"
43+
#include "supervisor/shared/tick.h"
44+
45+
// Where required we use identifier names that are required by NXP's
46+
// API, even though they do not conform to the naming standards that Adafruit
47+
// strives to adhere to. https://www.adafruit.com/blacklivesmatter
48+
#include "sdk/drivers/sai/fsl_sai.h"
49+
50+
STATIC void config_periph_pin(const mcu_periph_obj_t *periph) {
51+
if (!periph) {
52+
return;
53+
}
54+
if (periph->pin->mux_reg) {
55+
IOMUXC_SetPinMux(
56+
periph->pin->mux_reg, periph->mux_mode,
57+
periph->input_reg, periph->input_idx,
58+
0,
59+
1);
60+
}
61+
62+
IOMUXC_SetPinConfig(0, 0, 0, 0,
63+
periph->pin->cfg_reg,
64+
IOMUXC_SW_PAD_CTL_PAD_HYS(0)
65+
| IOMUXC_SW_PAD_CTL_PAD_PUS(0)
66+
| IOMUXC_SW_PAD_CTL_PAD_PUE(0)
67+
| IOMUXC_SW_PAD_CTL_PAD_PKE(1)
68+
| IOMUXC_SW_PAD_CTL_PAD_ODE(0)
69+
| IOMUXC_SW_PAD_CTL_PAD_SPEED(2)
70+
| IOMUXC_SW_PAD_CTL_PAD_DSE(4)
71+
| IOMUXC_SW_PAD_CTL_PAD_SRE(0));
72+
}
73+
74+
// Caller validates that pins are free.
75+
void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
76+
const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select,
77+
const mcu_pin_obj_t *data, bool left_justified) {
78+
79+
int instance = -1;
80+
const mcu_periph_obj_t *bclk_periph = find_pin_function(mcu_sai_tx_bclk_list, bit_clock, &instance, MP_QSTR_bit_clock);
81+
const mcu_periph_obj_t *sync_periph = find_pin_function(mcu_sai_tx_sync_list, word_select, &instance, MP_QSTR_word_select);
82+
const mcu_periph_obj_t *data_periph = find_pin_function(mcu_sai_tx_data0_list, data, &instance, MP_QSTR_data);
83+
84+
sai_transceiver_t config;
85+
SAI_GetClassicI2SConfig(&config, 16, kSAI_Stereo, 1);
86+
config.syncMode = kSAI_ModeAsync;
87+
config.fifo.fifoPacking = kSAI_FifoPackingDisabled;
88+
// These identifier names are required by NXP's API, even though they do
89+
// not conform to the naming standards that Adafruit strives to adhere to.
90+
// https://www.adafruit.com/blacklivesmatter
91+
config.masterSlave = kSAI_Master;
92+
port_i2s_initialize(&self->i2s, instance, &config);
93+
94+
self->bit_clock = bit_clock;
95+
self->word_select = word_select;
96+
self->data = data;
97+
claim_pin(bit_clock);
98+
claim_pin(word_select);
99+
claim_pin(data);
100+
config_periph_pin(data_periph);
101+
config_periph_pin(sync_periph);
102+
config_periph_pin(bclk_periph);
103+
}
104+
105+
bool common_hal_audiobusio_i2sout_deinited(audiobusio_i2sout_obj_t *self) {
106+
return port_i2s_deinited(&self->i2s);
107+
}
108+
109+
void common_hal_audiobusio_i2sout_deinit(audiobusio_i2sout_obj_t *self) {
110+
if (common_hal_audiobusio_i2sout_deinited(self)) {
111+
return;
112+
}
113+
114+
port_i2s_deinit(&self->i2s);
115+
116+
common_hal_reset_pin(self->bit_clock);
117+
self->bit_clock = NULL;
118+
119+
common_hal_reset_pin(self->word_select);
120+
self->word_select = NULL;
121+
122+
common_hal_reset_pin(self->data);
123+
self->data = NULL;
124+
}
125+
126+
void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
127+
mp_obj_t sample, bool loop) {
128+
if (common_hal_audiobusio_i2sout_get_playing(self)) {
129+
common_hal_audiobusio_i2sout_stop(self);
130+
}
131+
port_i2s_play(&self->i2s, sample, loop);
132+
}
133+
134+
void common_hal_audiobusio_i2sout_pause(audiobusio_i2sout_obj_t *self) {
135+
port_i2s_pause(&self->i2s);
136+
}
137+
138+
void common_hal_audiobusio_i2sout_resume(audiobusio_i2sout_obj_t *self) {
139+
port_i2s_resume(&self->i2s);
140+
}
141+
142+
bool common_hal_audiobusio_i2sout_get_paused(audiobusio_i2sout_obj_t *self) {
143+
return port_i2s_get_paused(&self->i2s);
144+
}
145+
146+
void common_hal_audiobusio_i2sout_stop(audiobusio_i2sout_obj_t *self) {
147+
port_i2s_stop(&self->i2s);
148+
}
149+
150+
bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t *self) {
151+
return port_i2s_get_playing(&self->i2s);
152+
}
153+
154+
#endif // CIRCUITPY_AUDIOBUSIO_I2SOUT
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#pragma once
28+
29+
#include "supervisor/background_callback.h"
30+
#include "common-hal/microcontroller/Pin.h"
31+
32+
#include "common-hal/audiobusio/__init__.h"
33+
34+
// Some boards don't implement I2SOut, so suppress any routines from here.
35+
#if CIRCUITPY_AUDIOBUSIO_I2SOUT
36+
37+
#include "sdk/drivers/sai/fsl_sai.h"
38+
39+
typedef struct {
40+
mp_obj_base_t base;
41+
i2s_t i2s;
42+
const mcu_pin_obj_t *bit_clock;
43+
const mcu_pin_obj_t *word_select;
44+
const mcu_pin_obj_t *data;
45+
} audiobusio_i2sout_obj_t;
46+
47+
#endif

ports/mimxrt10xx/common-hal/audiobusio/PDMIn.c

Whitespace-only changes.

ports/mimxrt10xx/common-hal/audiobusio/PDMIn.h

Whitespace-only changes.

0 commit comments

Comments
 (0)