mirror of
https://github.com/LegitCamper/picocalc-os-rs.git
synced 2025-12-27 07:45:28 +00:00
fix audio blips when should be silent
This commit is contained in:
@@ -24,6 +24,14 @@ pub static mut AUDIO_BUFFER: [u8; AUDIO_BUFFER_SAMPLES * 2] = [SILENCE; AUDIO_BU
|
|||||||
static mut AUDIO_BUFFER_1: [u8; AUDIO_BUFFER_SAMPLES * 2] = [SILENCE; AUDIO_BUFFER_SAMPLES * 2];
|
static mut AUDIO_BUFFER_1: [u8; AUDIO_BUFFER_SAMPLES * 2] = [SILENCE; AUDIO_BUFFER_SAMPLES * 2];
|
||||||
|
|
||||||
pub static AUDIO_BUFFER_READY: AtomicBool = AtomicBool::new(true);
|
pub static AUDIO_BUFFER_READY: AtomicBool = AtomicBool::new(true);
|
||||||
|
pub static AUDIO_BUFFER_WRITTEN: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
pub fn clear_audio_buffers() {
|
||||||
|
unsafe {
|
||||||
|
AUDIO_BUFFER.fill(SILENCE);
|
||||||
|
AUDIO_BUFFER_1.fill(SILENCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
pub async fn audio_handler(mut audio: Audio) {
|
pub async fn audio_handler(mut audio: Audio) {
|
||||||
@@ -35,14 +43,14 @@ pub async fn audio_handler(mut audio: Audio) {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
unsafe {
|
unsafe {
|
||||||
// if AUDIO_BUFFER.iter().any(|s| *s != SILENCE) {
|
if AUDIO_BUFFER_WRITTEN.load(Ordering::Acquire) {
|
||||||
write_samples(&mut pwm_pio_left, &mut pwm_pio_right, &AUDIO_BUFFER_1).await;
|
write_samples(&mut pwm_pio_left, &mut pwm_pio_right, &AUDIO_BUFFER_1).await;
|
||||||
AUDIO_BUFFER_1.fill(SILENCE);
|
AUDIO_BUFFER_1.fill(SILENCE);
|
||||||
core::mem::swap(&mut AUDIO_BUFFER, &mut AUDIO_BUFFER_1);
|
core::mem::swap(&mut AUDIO_BUFFER, &mut AUDIO_BUFFER_1);
|
||||||
AUDIO_BUFFER_READY.store(true, Ordering::Release)
|
AUDIO_BUFFER_READY.store(true, Ordering::Release)
|
||||||
// } else {
|
} else {
|
||||||
// yield_now().await;
|
yield_now().await;
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,29 +61,31 @@ async fn write_samples<PIO: Instance>(
|
|||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
) {
|
) {
|
||||||
// pack two samples per word
|
// pack two samples per word
|
||||||
let mut packed_buf_left: [u32; AUDIO_BUFFER_SAMPLES / 2] = [0; AUDIO_BUFFER_SAMPLES / 2];
|
static mut PACKED_BUF_L: [u32; AUDIO_BUFFER_SAMPLES / 2] = [0; AUDIO_BUFFER_SAMPLES / 2];
|
||||||
let mut packed_buf_right: [u32; AUDIO_BUFFER_SAMPLES / 2] = [0; AUDIO_BUFFER_SAMPLES / 2];
|
static mut PACKED_BUF_R: [u32; AUDIO_BUFFER_SAMPLES / 2] = [0; AUDIO_BUFFER_SAMPLES / 2];
|
||||||
|
|
||||||
for ((pl, pr), sample) in packed_buf_left
|
unsafe {
|
||||||
.iter_mut()
|
for ((pl, pr), sample) in PACKED_BUF_L
|
||||||
.zip(packed_buf_right.iter_mut())
|
.iter_mut()
|
||||||
.zip(buf.chunks(4))
|
.zip(PACKED_BUF_R.iter_mut())
|
||||||
{
|
.zip(buf.chunks(4))
|
||||||
*pl = pack_u8_samples(sample[0], sample[2]);
|
{
|
||||||
*pr = pack_u8_samples(sample[1], sample[3]);
|
*pl = pack_u8_samples(sample[0], sample[2]);
|
||||||
|
*pr = pack_u8_samples(sample[1], sample[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let left_fut = left
|
||||||
|
.sm
|
||||||
|
.tx()
|
||||||
|
.dma_push(left.dma.reborrow(), &PACKED_BUF_L, false);
|
||||||
|
|
||||||
|
let right_fut = right
|
||||||
|
.sm
|
||||||
|
.tx()
|
||||||
|
.dma_push(right.dma.reborrow(), &PACKED_BUF_R, false);
|
||||||
|
|
||||||
|
join(left_fut, right_fut).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let left_fut = left
|
|
||||||
.sm
|
|
||||||
.tx()
|
|
||||||
.dma_push(left.dma.reborrow(), &packed_buf_left, false);
|
|
||||||
|
|
||||||
let right_fut = right
|
|
||||||
.sm
|
|
||||||
.tx()
|
|
||||||
.dma_push(right.dma.reborrow(), &packed_buf_right, false);
|
|
||||||
|
|
||||||
join(left_fut, right_fut).await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PioPwmAudioProgram8Bit<'d, PIO: Instance>(LoadedProgram<'d, PIO>);
|
struct PioPwmAudioProgram8Bit<'d, PIO: Instance>(LoadedProgram<'d, PIO>);
|
||||||
@@ -88,22 +98,24 @@ impl<'d, PIO: Instance> PioPwmAudioProgram8Bit<'d, PIO> {
|
|||||||
let prg = pio_asm!(
|
let prg = pio_asm!(
|
||||||
".side_set 1",
|
".side_set 1",
|
||||||
|
|
||||||
|
"set x, 0 side 1",
|
||||||
|
"set y, 0 side 0",
|
||||||
|
".wrap_target",
|
||||||
|
|
||||||
"check:",
|
"check:",
|
||||||
// "set x, 0 side 1",
|
|
||||||
// "set y, 0 side 0",
|
|
||||||
"pull ifempty noblock side 1", // gets new osr or loads 0 into x, gets second sample if osr not empty
|
"pull ifempty noblock side 1", // gets new osr or loads 0 into x, gets second sample if osr not empty
|
||||||
"out x, 8 side 0", // pwm high time
|
"out x, 8 side 0", // pwm high time
|
||||||
"out y, 8 side 1", // pwm low time
|
"out y, 8 side 1", // pwm low time
|
||||||
"jmp x!=y play_sample side 0", // x & y are never equal unless osr was empty
|
"jmp x!=y play_sample side 0", // x & y are never equal unless osr was empty
|
||||||
// play silence for 10 cycles
|
"set x, 1 side 1",
|
||||||
"set x, 5 side 1",
|
"set y, 1 side 0",
|
||||||
"set y, 5 side 0",
|
|
||||||
|
|
||||||
"play_sample:"
|
"play_sample:"
|
||||||
"loop_high:",
|
"loop_high:",
|
||||||
"jmp x-- loop_high side 1", // keep pwm high, decrement X until 0
|
"jmp x-- loop_high side 1", // keep pwm high, decrement X until 0
|
||||||
"loop_low:",
|
"loop_low:",
|
||||||
"jmp y-- loop_low side 0", // keep pwm low, decrement Y until 0
|
"jmp y-- loop_low side 0", // keep pwm low, decrement Y until 0
|
||||||
|
".wrap"
|
||||||
);
|
);
|
||||||
|
|
||||||
let prg = common.load_program(&prg.program);
|
let prg = common.load_program(&prg.program);
|
||||||
@@ -130,7 +142,6 @@ impl<'d, PIO: Instance, const SM: usize> PioPwmAudio<'d, PIO, SM> {
|
|||||||
sm.set_pin_dirs(Direction::Out, &[&pin]);
|
sm.set_pin_dirs(Direction::Out, &[&pin]);
|
||||||
|
|
||||||
let mut cfg = Config::default();
|
let mut cfg = Config::default();
|
||||||
cfg.set_set_pins(&[&pin]);
|
|
||||||
cfg.fifo_join = FifoJoin::TxOnly;
|
cfg.fifo_join = FifoJoin::TxOnly;
|
||||||
let shift_cfg = ShiftConfig {
|
let shift_cfg = ShiftConfig {
|
||||||
auto_fill: false,
|
auto_fill: false,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ mod psram;
|
|||||||
use crate::{heap::init_qmi_psram_heap, psram::init_psram_qmi};
|
use crate::{heap::init_qmi_psram_heap, psram::init_psram_qmi};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
audio::audio_handler,
|
audio::{AUDIO_BUFFER_WRITTEN, audio_handler, clear_audio_buffers},
|
||||||
display::{FRAMEBUFFER, display_handler, init_display},
|
display::{FRAMEBUFFER, display_handler, init_display},
|
||||||
peripherals::{conf_peripherals, keyboard::read_keyboard_fifo},
|
peripherals::{conf_peripherals, keyboard::read_keyboard_fifo},
|
||||||
scsi::MSC_SHUTDOWN,
|
scsi::MSC_SHUTDOWN,
|
||||||
@@ -226,6 +226,9 @@ async fn userland_task() {
|
|||||||
|
|
||||||
// enable kernel ui
|
// enable kernel ui
|
||||||
{
|
{
|
||||||
|
AUDIO_BUFFER_WRITTEN.store(false, Ordering::Release);
|
||||||
|
clear_audio_buffers();
|
||||||
|
|
||||||
ENABLE_UI.store(true, Ordering::Release);
|
ENABLE_UI.store(true, Ordering::Release);
|
||||||
UI_CHANGE.signal(());
|
UI_CHANGE.signal(());
|
||||||
unsafe { FRAMEBUFFER.as_mut().unwrap().clear(Rgb565::BLACK).unwrap() };
|
unsafe { FRAMEBUFFER.as_mut().unwrap().clear(Rgb565::BLACK).unwrap() };
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use crate::heap::HEAP;
|
|||||||
use core::alloc::GlobalAlloc;
|
use core::alloc::GlobalAlloc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
audio::{AUDIO_BUFFER, AUDIO_BUFFER_READY},
|
audio::{AUDIO_BUFFER, AUDIO_BUFFER_READY, AUDIO_BUFFER_WRITTEN},
|
||||||
display::FRAMEBUFFER,
|
display::FRAMEBUFFER,
|
||||||
framebuffer::FB_PAUSED,
|
framebuffer::FB_PAUSED,
|
||||||
storage::{Dir, File, SDCARD},
|
storage::{Dir, File, SDCARD},
|
||||||
@@ -350,6 +350,7 @@ pub extern "C" fn send_audio_buffer(ptr: *const u8, len: usize) {
|
|||||||
if buf.len() == AUDIO_BUFFER_SAMPLES * 2 {
|
if buf.len() == AUDIO_BUFFER_SAMPLES * 2 {
|
||||||
AUDIO_BUFFER_READY.store(false, Ordering::Release);
|
AUDIO_BUFFER_READY.store(false, Ordering::Release);
|
||||||
unsafe { AUDIO_BUFFER.copy_from_slice(buf) };
|
unsafe { AUDIO_BUFFER.copy_from_slice(buf) };
|
||||||
|
AUDIO_BUFFER_WRITTEN.store(true, Ordering::Release);
|
||||||
} else {
|
} else {
|
||||||
#[cfg(feature = "defmt")]
|
#[cfg(feature = "defmt")]
|
||||||
defmt::warn!(
|
defmt::warn!(
|
||||||
|
|||||||
Reference in New Issue
Block a user