186 lines
5.7 KiB
Rust
186 lines
5.7 KiB
Rust
use common::Name;
|
|
use embassy_rp::clocks::RoscRng;
|
|
use embassy_rp::uart;
|
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
|
use embassy_sync::channel::Channel;
|
|
use embassy_time::Timer;
|
|
use embedded_io_async::Read;
|
|
use embedded_io_async::Write;
|
|
use rand::RngCore;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
|
|
use crate::server::NAMES;
|
|
use crate::wiggle::WAGS;
|
|
use crate::Irqs;
|
|
|
|
|
|
use embassy_rp::uart::BufferedUart;
|
|
|
|
use embassy_rp::peripherals::PIN_21;
|
|
|
|
use embassy_rp::peripherals::PIN_20;
|
|
|
|
|
|
use embassy_rp::peripherals::UART1;
|
|
use log::*;
|
|
|
|
pub static COMMANDS: Channel<CriticalSectionRawMutex, MusicCommand, 3> = Channel::new();
|
|
|
|
pub trait Tracks {
|
|
fn tracks(&self) -> u8;
|
|
fn prefix(&self) -> &'static str;
|
|
}
|
|
|
|
impl Tracks for Name {
|
|
fn tracks(&self) -> u8 {
|
|
match self {
|
|
Name::Andy => 7,
|
|
Name::Evan => 7,
|
|
Name::Felix => 12,
|
|
Name::Phil => 6,
|
|
Name::Tess => 4,
|
|
Name::Amaia => 5,
|
|
Name::Prueky => 1,
|
|
Name::David => 2,
|
|
Name::Nathaniel => 1,
|
|
Name::Thia => 7,
|
|
Name::Michael => 0,
|
|
Name::Zoey => 1,
|
|
Name::Unknown => 0,
|
|
}
|
|
}
|
|
|
|
fn prefix(&self) -> &'static str {
|
|
match self {
|
|
Name::Andy => "andy",
|
|
Name::Evan => "evan",
|
|
Name::Felix => "felix",
|
|
Name::Phil => "phil",
|
|
Name::Tess => "tess",
|
|
Name::Amaia => "amaia",
|
|
Name::Prueky => "prueky",
|
|
Name::David => "david",
|
|
Name::Nathaniel => "nathaniel1",
|
|
Name::Thia => "thia",
|
|
Name::Michael => "michael",
|
|
Name::Zoey => "zoey",
|
|
Name::Unknown => "",
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static ACCEPTED_SUFFIXABLE: [bool; 6] = [false, false, false, false, false, true];
|
|
static DENIED_SUFFIXABLE: [bool; 6] = [false, false, false, false, false, true];
|
|
|
|
pub enum MusicCommand {
|
|
/// play a random clip for name, accepted if true
|
|
Introduce(Name, bool),
|
|
/// 0-30
|
|
SetVolume(u8),
|
|
Play(&'static str),
|
|
Button(),
|
|
}
|
|
|
|
#[embassy_executor::task]
|
|
pub async fn music_manager(uart: UART1, irqs: Irqs, txp: PIN_20, rxp: PIN_21) -> ! {
|
|
let mut config = uart::Config::default();
|
|
config.baudrate = 115200;
|
|
let mut rx = [0; 2048];
|
|
let mut tx = [0; 2048];
|
|
|
|
let mut uart = BufferedUart::new(uart, irqs, txp, rxp, &mut tx, &mut rx, config);
|
|
|
|
let mut rng = RoscRng;
|
|
|
|
loop {
|
|
let command = COMMANDS.receive().await;
|
|
match command {
|
|
MusicCommand::Introduce(name, accepted) => {
|
|
let call: bool;
|
|
if accepted {
|
|
let index = rng.next_u32() % ACCEPTED_SUFFIXABLE.len() as u32;
|
|
play_song("a", Some((index+1) as u8), &mut uart).await;
|
|
call = ACCEPTED_SUFFIXABLE[index as usize];
|
|
} else {
|
|
let index = rng.next_u32() % DENIED_SUFFIXABLE.len() as u32;
|
|
play_song("d", Some((index+1) as u8), &mut uart).await;
|
|
call = DENIED_SUFFIXABLE[index as usize];
|
|
}
|
|
|
|
if call {
|
|
match name.tracks() {
|
|
0 => {},
|
|
1 => {
|
|
play_song(&name.prefix(), None, &mut uart).await;
|
|
},
|
|
tracks => {
|
|
let index = rng.next_u32() % tracks as u32;
|
|
|
|
play_song(&name.prefix(), Some((index+1) as u8), &mut uart).await;
|
|
}
|
|
}
|
|
}
|
|
|
|
},
|
|
MusicCommand::Button() => {
|
|
let index = rng.next_u32() % 12 as u32;
|
|
play_song("b", Some((index+1) as u8), &mut uart).await;
|
|
},
|
|
MusicCommand::Play(song) => {
|
|
play_song(song, None, &mut uart).await
|
|
},
|
|
MusicCommand::SetVolume(vol) => {
|
|
uart.write_all(b"AT+VOL=").await.unwrap();
|
|
uart.write_all(itoa::Buffer::new().format(vol).as_bytes()).await.unwrap();
|
|
uart.write_all(b"\r\n").await.unwrap();
|
|
let mut buffer = [0;512];
|
|
info!("set volume to {vol}, returned: {}",read_line(&mut buffer, &mut uart).await.trim());
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn play_song<'a>(prefix: &str, index: Option<u8>, uart: &mut BufferedUart<'a, UART1>) {
|
|
info!("playing: {}{}.mp3",prefix,index.unwrap_or(0));
|
|
|
|
uart.write_all(b"AT+PLAYFILE=/").await.unwrap();
|
|
uart.write_all(prefix.as_bytes()).await.unwrap();
|
|
if let Some(index) = index {
|
|
uart.write_all(itoa::Buffer::new().format(index).as_bytes()).await.unwrap();
|
|
}
|
|
uart.write_all(b".mp3\r\n").await.unwrap();
|
|
|
|
let mut buffer = [0;512];
|
|
info!("returned: {}",read_line(&mut buffer, uart).await.trim());
|
|
|
|
uart.write_all(b"AT+QUERY=4\r\n").await.unwrap();
|
|
let mut buffer = [0;512];
|
|
let output = read_line(&mut buffer, uart).await;
|
|
|
|
if let Ok(length) = output.trim().parse::<u64>() {
|
|
WAGS.store((length as u8) * 2 + 1, core::sync::atomic::Ordering::SeqCst);
|
|
Timer::after_secs(length).await;
|
|
}
|
|
}
|
|
|
|
async fn read_line<'a, 'b>(buffer: &'b mut [u8], uart: &mut BufferedUart<'a, UART1>) -> &'b str {
|
|
let mut pos = 0;
|
|
loop {
|
|
if let Ok(len) = uart.read(&mut buffer[pos..]).await {
|
|
let to_print = unsafe { core::str::from_utf8_unchecked(&buffer[..(pos + len)]) };
|
|
|
|
if to_print.contains("\r\n") {
|
|
//info!("{}", to_print);
|
|
pos += len;
|
|
break;
|
|
}
|
|
|
|
pos += len;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return unsafe { core::str::from_utf8_unchecked(&buffer[..(pos)]) };
|
|
}
|