Compare commits
1 Commits
main
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
| 93e9aea368 |
@@ -2,7 +2,8 @@
|
|||||||
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
|
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
|
||||||
|
|
||||||
import _audiocore
|
import _audiocore
|
||||||
from asyncio import ThreadSafeFlag
|
import asyncio
|
||||||
|
from asyncio import Lock, ThreadSafeFlag
|
||||||
from utils import get_pin_index
|
from utils import get_pin_index
|
||||||
|
|
||||||
|
|
||||||
@@ -11,19 +12,34 @@ class Audiocore:
|
|||||||
# PIO requires sideset pins to be adjacent
|
# PIO requires sideset pins to be adjacent
|
||||||
assert get_pin_index(lrclk) == get_pin_index(dclk)+1 or get_pin_index(lrclk) == get_pin_index(dclk)-1
|
assert get_pin_index(lrclk) == get_pin_index(dclk)+1 or get_pin_index(lrclk) == get_pin_index(dclk)-1
|
||||||
self.notify = ThreadSafeFlag()
|
self.notify = ThreadSafeFlag()
|
||||||
|
self.audiocore_lock = Lock()
|
||||||
self._audiocore = _audiocore.Audiocore(din, dclk, lrclk, self._interrupt)
|
self._audiocore = _audiocore.Audiocore(din, dclk, lrclk, self._interrupt)
|
||||||
|
|
||||||
def deinit(self):
|
def deinit(self):
|
||||||
|
assert not self.audiocore_lock.locked()
|
||||||
self._audiocore.deinit()
|
self._audiocore.deinit()
|
||||||
|
|
||||||
def _interrupt(self, _):
|
def _interrupt(self, _):
|
||||||
self.notify.set()
|
self.notify.set()
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
|
assert not self.audiocore_lock.locked()
|
||||||
self._audiocore.flush()
|
self._audiocore.flush()
|
||||||
|
|
||||||
|
async def async_flush(self):
|
||||||
|
async with self.audiocore_lock:
|
||||||
|
self._audiocore.flush(False)
|
||||||
|
while True:
|
||||||
|
if self._audiocore.get_async_result() is not None:
|
||||||
|
return
|
||||||
|
await self.notify.wait()
|
||||||
|
|
||||||
|
async def async_set_volume(self, volume):
|
||||||
|
async with self.audiocore_lock:
|
||||||
|
self._audiocore.set_volume(volume)
|
||||||
|
|
||||||
def set_volume(self, volume):
|
def set_volume(self, volume):
|
||||||
self._audiocore.set_volume(volume)
|
asyncio.create_task(self.async_set_volume(volume))
|
||||||
|
|
||||||
def put(self, buffer, blocking=False):
|
def put(self, buffer, blocking=False):
|
||||||
pos = 0
|
pos = 0
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
// Include MicroPython API.
|
// Include MicroPython API.
|
||||||
#include "py/mperrno.h"
|
#include "py/mperrno.h"
|
||||||
|
#include "py/obj.h"
|
||||||
|
#include "py/persistentcode.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "shared/runtime/mpirq.h"
|
#include "shared/runtime/mpirq.h"
|
||||||
|
|
||||||
@@ -61,6 +63,20 @@ static uint32_t get_fifo_read_value_blocking(struct audiocore_obj *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool get_fifo_read_value(struct audiocore_obj *obj, uint32_t *result)
|
||||||
|
{
|
||||||
|
const long flags = save_and_disable_interrupts();
|
||||||
|
const uint32_t value = obj->fifo_read_value;
|
||||||
|
obj->fifo_read_value = 0;
|
||||||
|
if (value & AUDIOCORE_FIFO_DATA_FLAG) {
|
||||||
|
restore_interrupts(flags);
|
||||||
|
*result = value & ~AUDIOCORE_FIFO_DATA_FLAG;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
restore_interrupts(flags);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* audiocore.Context.deinit(self)
|
* audiocore.Context.deinit(self)
|
||||||
*
|
*
|
||||||
@@ -125,15 +141,31 @@ static MP_DEFINE_CONST_FUN_OBJ_2(audiocore_put_obj, audiocore_put);
|
|||||||
* Tells the audiocore to stop playback as soon as all MP3 frames still in the buffer have been decoded.
|
* Tells the audiocore to stop playback as soon as all MP3 frames still in the buffer have been decoded.
|
||||||
* This function blocks until playback has ended.
|
* This function blocks until playback has ended.
|
||||||
*/
|
*/
|
||||||
static mp_obj_t audiocore_flush(mp_obj_t self_in)
|
static mp_obj_t audiocore_flush(size_t n_args, const mp_obj_t *args)
|
||||||
{
|
{
|
||||||
struct audiocore_obj *self = MP_OBJ_TO_PTR(self_in);
|
struct audiocore_obj *self = MP_OBJ_TO_PTR(args[0]);
|
||||||
|
mp_obj_t blocking = MP_ROM_TRUE;
|
||||||
|
if (n_args == 2) {
|
||||||
|
blocking = args[1];
|
||||||
|
}
|
||||||
multicore_fifo_push_blocking(AUDIOCORE_CMD_FLUSH);
|
multicore_fifo_push_blocking(AUDIOCORE_CMD_FLUSH);
|
||||||
wake_core1();
|
wake_core1();
|
||||||
get_fifo_read_value_blocking(self);
|
if (mp_obj_is_true(blocking))
|
||||||
|
get_fifo_read_value_blocking(self);
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
static MP_DEFINE_CONST_FUN_OBJ_1(audiocore_flush_obj, audiocore_flush);
|
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiocore_flush_obj, 1, 2, audiocore_flush);
|
||||||
|
|
||||||
|
static mp_obj_t audiocore_get_async_result(mp_obj_t self_in)
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
struct audiocore_obj *self = MP_OBJ_TO_PTR(self_in);
|
||||||
|
if (get_fifo_read_value(self, &result)) {
|
||||||
|
return mp_obj_new_int(result);
|
||||||
|
}
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(audiocore_get_async_result_obj, audiocore_get_async_result);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* audiocore.set_volume(self, volume)
|
* audiocore.set_volume(self, volume)
|
||||||
@@ -240,6 +272,7 @@ static const mp_rom_map_elem_t audiocore_locals_dict_table[] = {
|
|||||||
{MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiocore_deinit_obj)},
|
{MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiocore_deinit_obj)},
|
||||||
{MP_ROM_QSTR(MP_QSTR_put), MP_ROM_PTR(&audiocore_put_obj)},
|
{MP_ROM_QSTR(MP_QSTR_put), MP_ROM_PTR(&audiocore_put_obj)},
|
||||||
{MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&audiocore_flush_obj)},
|
{MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&audiocore_flush_obj)},
|
||||||
|
{MP_ROM_QSTR(MP_QSTR_get_async_result), MP_ROM_PTR(&audiocore_get_async_result_obj)},
|
||||||
{MP_ROM_QSTR(MP_QSTR_set_volume), MP_ROM_PTR(&audiocore_set_volume_obj)},
|
{MP_ROM_QSTR(MP_QSTR_set_volume), MP_ROM_PTR(&audiocore_set_volume_obj)},
|
||||||
};
|
};
|
||||||
static MP_DEFINE_CONST_DICT(audiocore_locals_dict, audiocore_locals_dict_table);
|
static MP_DEFINE_CONST_DICT(audiocore_locals_dict, audiocore_locals_dict_table);
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class MP3Player:
|
|||||||
# Call onPlaybackDone after flush
|
# Call onPlaybackDone after flush
|
||||||
send_done = True
|
send_done = True
|
||||||
finally:
|
finally:
|
||||||
self.audiocore.flush()
|
await self.audiocore.async_flush()
|
||||||
if send_done:
|
if send_done:
|
||||||
# Only call onPlaybackDone if exit due to end of stream
|
# Only call onPlaybackDone if exit due to end of stream
|
||||||
# Use timer with time 0 to call callback "immediately" but from a different task
|
# Use timer with time 0 to call callback "immediately" but from a different task
|
||||||
|
|||||||
Reference in New Issue
Block a user