Add music on button press

This commit is contained in:
Edward Shen 2025-05-16 23:53:53 -07:00
parent 9d9adcf7d0
commit ca5867ba36
Signed by: edward
GPG key ID: 19182661E818369F

View file

@ -8,10 +8,10 @@ use defmt::{info, unwrap};
use embassy_executor::Spawner;
use embassy_futures::select::{Either, select};
use embassy_rp::bind_interrupts;
use embassy_rp::config::Config;
use embassy_rp::gpio::{self, Input};
use embassy_rp::peripherals::{DMA_CH0, PIO0};
use embassy_rp::peripherals::{DMA_CH0, PIN_20, PIO0, PWM_SLICE2};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::pwm::{self, Pwm, SetDutyCycle};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::{Channel, Sender};
use embassy_time::{Duration, Instant, Timer};
@ -81,7 +81,7 @@ async fn button(
loop {
info!("Waiting for falling edge");
input.wait_for_falling_edge().await;
sender.send(ChannelMessage::Refilled).await;
let _ = sender.try_send(ChannelMessage::Refilled);
input.wait_for_high().await;
}
}
@ -112,7 +112,7 @@ async fn main(spawner: Spawner) {
// Timer::after_secs(1).await;
// }
let p = embassy_rp::init(Config::default());
let mut p = embassy_rp::init(embassy_rp::config::Config::default());
let fw = include_bytes!("../embassy/cyw43-firmware/43439A0.bin");
let clm = include_bytes!("../embassy/cyw43-firmware/43439A0_clm.bin");
@ -152,10 +152,7 @@ async fn main(spawner: Spawner) {
unwrap!(spawner.spawn(heartbeat(control)));
unwrap!(spawner.spawn(button(
{
let input = Input::new(p.PIN_15, gpio::Pull::Up);
input
},
Input::new(p.PIN_15, gpio::Pull::Up),
CHANNEL.sender()
)));
@ -178,7 +175,10 @@ async fn main(spawner: Spawner) {
info!("Water refilled received");
water_state.refill();
set_leds(water_state, &mut yellow_led, &mut red_led);
play_music(&mut p.PWM_SLICE2, &mut p.PIN_20).await;
timer = water_state.timer();
// only permit one message at a time
CHANNEL.clear();
}
}
}
@ -200,3 +200,103 @@ fn set_leds(water_state: WaterState, yellow_led: &mut Output, red_led: &mut Outp
}
}
}
async fn play_music(slice: &mut PWM_SLICE2, pin: &mut PIN_20) {
const SIXTHTEEN_NOTE_MILLIS: u64 = 100;
#[derive(PartialEq, Eq, Clone, Copy)]
#[repr(u16)]
enum Note {
Rest = 0,
C4 = 262,
D4 = 294,
E4 = 330,
F4 = 349,
G4 = 392,
A5 = 440,
#[allow(dead_code)]
B5 = 494,
C5 = 524,
}
#[expect(clippy::enum_glob_use)]
use Note::*;
#[repr(u8)]
enum Duration {
Sixthteenth = 1,
Eighth = 2,
DottedEighth = 3,
Quarter = 4,
Half = 8,
}
#[expect(clippy::enum_glob_use)]
use Duration::*;
const SONG: [(Note, Duration); 36] = [
(C4, DottedEighth),
(D4, Sixthteenth),
(E4, DottedEighth),
(F4, Sixthteenth),
(G4, Quarter),
(C5, Quarter),
//
(A5, Quarter),
(C5, Quarter),
(G4, Half),
//
(F4, Quarter),
(F4, Eighth),
(G4, Eighth),
(E4, Quarter),
(E4, Quarter),
//
(D4, Quarter),
(D4, Eighth),
(E4, Eighth),
(C4, Half),
//
(C4, DottedEighth),
(D4, Sixthteenth),
(E4, DottedEighth),
(F4, Sixthteenth),
(G4, Quarter),
(C5, Quarter),
//
(A5, Quarter),
(C5, Quarter),
(G4, Half),
//
(C5, Quarter),
(Rest, Eighth),
(A5, Eighth),
(G4, DottedEighth),
(G4, Sixthteenth),
(F4, Quarter),
//
(E4, Quarter),
(D4, Quarter),
(C4, Half),
];
for (note, duration) in SONG {
let clock_freq_hz = embassy_rp::clocks::clk_sys_freq();
let divider = 16;
#[expect(clippy::cast_possible_truncation)]
let period = clock_freq_hz.saturating_div(note as u32 * u32::from(divider)) as u16 - 1;
let mut c = pwm::Config::default();
c.top = period;
c.divider = divider.into();
let mut pwm = Pwm::new_output_a(&mut *slice, &mut *pin, c.clone());
if note == Rest {
let _ = pwm.set_duty_cycle_fully_off();
} else {
let _ = pwm.set_duty_cycle_percent(50);
}
Timer::after_millis(duration as u64 * SIXTHTEEN_NOTE_MILLIS).await;
let _ = pwm.set_duty_cycle_fully_off();
Timer::after_millis(20).await;
}
}