Exposed audio to MP, and made it teardown cleanly

feature/galactic_unicorn
ZodiusInfuser 2022-08-11 17:49:57 +01:00 zatwierdzone przez Phil Howard
rodzic 4551c991fb
commit e08ddd9837
6 zmienionych plików z 49 dodań i 23 usunięć

Wyświetl plik

@ -55,7 +55,7 @@ static inline void audio_i2s_program_init(PIO pio, uint sm, uint offset, uint da
uint pin_mask = (1u << data_pin) | (3u << clock_pin_base);
pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask);
pio_sm_set_pins(pio, sm, 0); // clear pins
pio_sm_set_pins_with_mask(pio, sm, 0, pin_mask); // clear pins
pio_sm_exec(pio, sm, pio_encode_jmp(offset + audio_i2s_offset_entry_point));
}

Wyświetl plik

@ -51,6 +51,9 @@ namespace pimoroni {
PIO GalacticUnicorn::bitstream_pio = pio0;
uint GalacticUnicorn::bitstream_sm = 0;
uint GalacticUnicorn::bitstream_sm_offset = 0;
PIO GalacticUnicorn::audio_pio = pio0;
uint GalacticUnicorn::audio_sm = 0;
uint GalacticUnicorn::audio_sm_offset = 0;
// once the dma transfer of the scanline is complete we move to the
// next scanline (or quit if we're finished)
@ -73,11 +76,15 @@ namespace pimoroni {
partial_teardown();
dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly
unicorn = nullptr;
pio_sm_unclaim(bitstream_pio, bitstream_sm);
pio_remove_program(bitstream_pio, &galactic_unicorn_program, bitstream_sm_offset);
irq_remove_handler(DMA_IRQ_0, dma_complete);
dma_channel_unclaim(audio_dma_channel); // This works now the teardown behaves correctly
pio_sm_unclaim(audio_pio, audio_sm);
pio_remove_program(audio_pio, &audio_i2s_program, audio_sm_offset);
unicorn = nullptr;
}
}
@ -91,6 +98,17 @@ namespace pimoroni {
// Abort any in-progress DMA transfer
dma_safe_abort(dma_channel);
// Stop the audio SM
pio_sm_set_enabled(audio_pio, audio_sm, false);
// Reset the I2S pins to avoid popping when audio is suddenly stopped
const uint pins_to_clear = 1 << I2S_DATA | 1 << I2S_BCLK | 1 << I2S_LRCLK;
pio_sm_set_pins_with_mask(audio_pio, audio_sm, 0, pins_to_clear);
// Abort any in-progress DMA transfer
dma_safe_abort(audio_dma_channel);
}
uint16_t GalacticUnicorn::light() {
@ -287,15 +305,13 @@ namespace pimoroni {
irq_set_enabled(DMA_IRQ_0, true);
}
unicorn = this;
next_dma_sequence();
// TODO Made audio tear down cleanly
// setup audio pio program
audio_pio = pio0;
audio_sm = pio_claim_unused_sm(audio_pio, true);
audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program);
if(unicorn == nullptr) {
audio_sm = pio_claim_unused_sm(audio_pio, true);
audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program);
}
pio_gpio_init(audio_pio, I2S_DATA);
pio_gpio_init(audio_pio, I2S_BCLK);
@ -305,8 +321,6 @@ namespace pimoroni {
uint32_t system_clock_frequency = clock_get_hz(clk_sys);
uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow
pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu);
//pio_sm_set_enabled(audio_pio, audio_sm, true); // No need to enable the SM until audio is playing
audio_dma_channel = dma_claim_unused_channel(true);
dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel);
@ -314,8 +328,11 @@ namespace pimoroni {
//channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian
channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true));
dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false);
//dma_channel_set_irq0_enabled(audio_dma_channel, true);
irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);
unicorn = this;
next_dma_sequence();
}
void GalacticUnicorn::clear() {
@ -351,8 +368,8 @@ namespace pimoroni {
pio_sm_set_enabled(audio_pio, audio_sm, false);
// Reset the I2S pins to avoid popping when audio is suddenly stopped
const uint pins_to_set = 1 << I2S_DATA | 1 << I2S_BCLK | 1 << I2S_LRCLK;
pio_sm_set_pins_with_mask(audio_pio, audio_sm, 0, pins_to_set);
const uint pins_to_clear = 1 << I2S_DATA | 1 << I2S_BCLK | 1 << I2S_LRCLK;
pio_sm_set_pins_with_mask(audio_pio, audio_sm, 0, pins_to_clear);
// Abort any in-progress DMA transfer
dma_safe_abort(audio_dma_channel);

Wyświetl plik

@ -56,9 +56,9 @@ namespace pimoroni {
static uint bitstream_sm;
static uint bitstream_sm_offset;
PIO audio_pio = pio0;
uint audio_sm = 0;
uint audio_sm_offset = 0;
static PIO audio_pio;
static uint audio_sm;
static uint audio_sm_offset;
uint16_t brightness = 256;
uint16_t volume = 127;

Wyświetl plik

@ -13,7 +13,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_get_volume_obj, GalacticUnicorn_get_vo
MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_adjust_volume_obj, GalacticUnicorn_adjust_volume);
MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_light_obj, GalacticUnicorn_light);
MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pressed);
//MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_play_sample_obj, 1, GalacticUnicorn_play_sample);
MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_sample_obj, GalacticUnicorn_play_sample);
/***** Binding of Methods *****/
STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = {
@ -28,7 +28,7 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_adjust_volume), MP_ROM_PTR(&GalacticUnicorn_adjust_volume_obj) },
{ MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&GalacticUnicorn_light_obj) },
{ MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&GalacticUnicorn_is_pressed_obj) },
//{ MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) },
{ MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) },
{ MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) },
{ MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) },

Wyświetl plik

@ -145,8 +145,17 @@ extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button) {
return mp_obj_new_bool(self->galactic->is_pressed((uint8_t)mp_obj_get_int(button)));
}
extern mp_obj_t GalacticUnicorn_play_sample(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
//_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t);
extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data) {
_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_RW);
if(bufinfo.len < 1) {
mp_raise_ValueError("Supplied buffer is too small!");
}
self->galactic->play_sample((uint8_t *)bufinfo.buf, bufinfo.len);
return mp_const_none;
}
}

Wyświetl plik

@ -24,4 +24,4 @@ extern mp_obj_t GalacticUnicorn_light(mp_obj_t self_in);
extern mp_obj_t GalacticUnicorn_is_pressed(mp_obj_t self_in, mp_obj_t button);
extern mp_obj_t GalacticUnicorn_play_sample(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data);