Compare commits

...

8 commits

18 changed files with 1090 additions and 161 deletions

1
common/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
target

65
common/Cargo.lock generated Normal file
View file

@ -0,0 +1,65 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "common"
version = "0.1.0"
dependencies = [
"serde",
]
[[package]]
name = "proc-macro2"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "2.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"

7
common/Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[package]
name = "common"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1.0.203", default-features = false, features = ["derive"] }

30
common/src/lib.rs Normal file
View file

@ -0,0 +1,30 @@
#![no_std]
use serde::Deserialize;
use serde::Serialize;
#[derive(Serialize, Deserialize)]
pub enum Request {
RecentBadge,
SetRecentBadge(Name),
SetVolume(u8),
}
#[derive(Clone, Copy, Serialize, Deserialize)]
#[repr(u8)]
pub enum Name {
Andy,
Evan,
Felix,
Phil,
Tess,
Amaia,
Prueky,
David,
Nathaniel,
Thia,
Michael,
Zoey,
Coke,
Unknown,
}

91
outside/Cargo.lock generated
View file

@ -126,12 +126,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.7"
@ -250,6 +244,12 @@ dependencies = [
"inout",
]
[[package]]
name = "cobs"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "codespan-reporting"
version = "0.11.1"
@ -261,10 +261,11 @@ dependencies = [
]
[[package]]
name = "const-default"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa"
name = "common"
version = "0.1.0"
dependencies = [
"serde",
]
[[package]]
name = "const-oid"
@ -813,18 +814,6 @@ dependencies = [
"log",
]
[[package]]
name = "embedded-alloc"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd"
dependencies = [
"const-default",
"critical-section",
"linked_list_allocator",
"rlsf",
]
[[package]]
name = "embedded-graphics"
version = "0.7.1"
@ -1300,6 +1289,7 @@ dependencies = [
"atomic-polyfill",
"hash32 0.2.1",
"rustc_version 0.4.1",
"serde",
"spin",
"stable_deref_trait",
]
@ -1449,12 +1439,6 @@ dependencies = [
"libc",
]
[[package]]
name = "linked_list_allocator"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
[[package]]
name = "litrs"
version = "0.4.1"
@ -1579,6 +1563,7 @@ dependencies = [
"assign-resources",
"bt-hci",
"byte-slice-cast 1.2.2",
"common",
"cortex-m",
"cortex-m-rt",
"critical-section",
@ -1597,7 +1582,6 @@ dependencies = [
"embassy-time",
"embassy-usb",
"embassy-usb-logger",
"embedded-alloc",
"embedded-graphics",
"embedded-hal 1.0.0",
"embedded-hal-async",
@ -1615,6 +1599,7 @@ dependencies = [
"pio",
"pio-proc",
"portable-atomic",
"postcard",
"rand",
"reqwless",
"serde",
@ -1622,7 +1607,6 @@ dependencies = [
"smart-leds",
"st7789",
"static_cell",
"talc",
"usbd-hid",
]
@ -1767,6 +1751,17 @@ dependencies = [
"critical-section",
]
[[package]]
name = "postcard"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8"
dependencies = [
"cobs",
"heapless 0.7.17",
"serde",
]
[[package]]
name = "ppv-lite86"
version = "0.2.20"
@ -1919,7 +1914,7 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66584b58c3b0cd8cfea750408a932fe86df79ee05ccc87ee745a8e6be4a1abe0"
dependencies = [
"base64 0.21.7",
"base64",
"buffered-io",
"defmt",
"embedded-io",
@ -1943,18 +1938,6 @@ dependencies = [
"bytemuck",
]
[[package]]
name = "rlsf"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "222fb240c3286247ecdee6fa5341e7cdad0ffdf8e7e401d9937f2d58482a20bf"
dependencies = [
"cfg-if",
"const-default",
"libc",
"svgbobdoc",
]
[[package]]
name = "rp-pac"
version = "6.0.0"
@ -2206,19 +2189,6 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "svgbobdoc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50"
dependencies = [
"base64 0.13.1",
"proc-macro2",
"quote",
"syn 1.0.109",
"unicode-width",
]
[[package]]
name = "syn"
version = "1.0.109"
@ -2241,15 +2211,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "talc"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fcad3be1cfe36eb7d716a04791eba36a197da9d9b6ea1e28e64ac569da3701d"
dependencies = [
"lock_api",
]
[[package]]
name = "term"
version = "0.7.0"

View file

@ -61,8 +61,8 @@ embedded-sdmmc = "0.7.0"
bt-hci = { version = "0.1.0", default-features = false, features = ["defmt"] }
hex = { version = "0.4.3", default-features=false}
itoa = "1.0.14"
embedded-alloc = "0.6.0"
talc = "4.4.2"
postcard = "1.0.0"
common = {path = "../common"}
[profile.release]
debug = 2

58
outside/src/arraymap.rs Normal file
View file

@ -0,0 +1,58 @@
/// no_std, no_alloc map
pub struct ArrayMap<const N: usize, K,V> {
keys: [Option<K>; N],
values: [Option<V>; N],
index: usize,
}
impl<const N: usize, K, V> ArrayMap<N, K, V> where K: Eq {
pub const fn new() -> Self {
Self { keys: [const { None };N], values: [const { None };N], index: 0 }
}
pub fn insert(&mut self, key: K, value: V) {
match self.keys[..self.index].iter().enumerate()
.find(|k| k.1.as_ref().is_some_and(|v| *v == key)) {
Some((index, _)) => {
self.keys[index] = Some(key);
self.values[index] = Some(value);
},
None => {
self.keys[self.index] = Some(key);
self.values[self.index] = Some(value);
self.index += 1;
if self.index > N {
self.index = 0;
log::error!("arraymap is full, overwriting");
}
},
}
}
pub fn get(&self, key: K) -> Option<&V> {
match self.keys[..self.index].iter().enumerate()
.find(|k| k.1.as_ref().is_some_and(|v| *v == key)) {
Some((index, _)) => {
self.values[index].as_ref()
},
None => {
None
},
}
}
}
#[cfg(test)]
mod test {
use super::ArrayMap;
fn get() {
let mut map: ArrayMap<2, i32, &str> = ArrayMap::new();
map.insert(3, "fogey");
map.insert(4, "bogey");
assert_eq!(map.get(3), Some(&"fogey"));
assert_eq!(map.get(5), None);
}
}

View file

@ -1,6 +1,7 @@
use crate::music::{MusicCommand, COMMANDS};
use crate::server::NAMES;
use super::MUSIC;
use common::Name;
use embassy_net::{IpEndpoint, Ipv4Address};
use embassy_time::Duration;
@ -13,22 +14,49 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Receiver;
use embedded_io_async::Write;
use log::*;
use rand::RngCore;
trait Authorized {
/// allowed to open door
fn authorized(&self) -> bool;
async fn from_badge(badge: u64) -> Self;
}
impl Authorized for Name {
fn authorized(&self) -> bool {
match self {
Name::Andy => true,
Name::Evan => true,
Name::Michael => true,
_ => false,
}
}
async fn from_badge(badge: u64) -> Self {
match badge {
badge => {
if let Some(name) = NAMES.lock().await.borrow().get(badge) {
*name
} else {
Name::Unknown
}
},
}
}
}
#[embassy_executor::task]
pub(crate) async fn send_badge(channel: Receiver<'static,CriticalSectionRawMutex,u64,1>,stack: embassy_net::Stack<'static>) -> ! {
pub async fn send_badge(channel: Receiver<'static,CriticalSectionRawMutex,u64,1>,stack: embassy_net::Stack<'static>) -> ! {
let mut rx_buffer = [0; 4096];
let mut tx_buffer = [0; 4096];
loop {
let card = channel.receive().await;
let mut rng = RoscRng;
let num = (RoscRng::next_u32(&mut rng) % 5) + 1;
let name = match card {
0x2c55dc3f5 => "evan",
0x3161dc3f7 => "andy",
_ => "d",
};
let name = Name::from_badge(card).await;
COMMANDS.send(MusicCommand::Introduce(name, name.authorized())).await;
// this is also checked on the backend (TODO)
if !name.authorized() {
continue;
}
let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
socket.set_timeout(Some(Duration::from_secs(10)));
@ -57,8 +85,5 @@ pub(crate) async fn send_badge(channel: Receiver<'static,CriticalSectionRawMutex
socket.close();
info!("disconnected");
MUSIC.send(("a",num as u8)).await;
MUSIC.send((name,num as u8)).await;
}
}

62
outside/src/lib.rs Normal file
View file

@ -0,0 +1,62 @@
#![no_std]
#![no_main]
#![allow(async_fn_in_trait)]
use core::array;
use core::borrow::BorrowMut;
use core::cell::RefCell;
use core::fmt::Formatter;
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::panic::PanicInfo;
use core::str::from_utf8;
use core::sync::atomic::{AtomicU8};
use auth::send_badge;
use bt_hci::cmd::info;
use critical_section::Mutex;
use cyw43::JoinOptions;
use cyw43_pio::PioSpi;
use embassy_futures::join::join;
use embassy_futures::yield_now;
use embassy_rp::interrupt::typelevel::{Handler, Interrupt, IO_IRQ_BANK0};
use embassy_rp::multicore::{spawn_core1, Stack};
use embassy_rp::pwm::{self};
use embassy_rp::uart::{BufferedInterruptHandler};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::{Channel};
use fixed::FixedU16;
use log::*;
//use embassy_rp::i2c::InterruptHandler;
use embassy_executor::{InterruptExecutor, Spawner};
use embassy_net::tcp::TcpSocket;
use embassy_net::{Config, IpEndpoint, Ipv4Address, StackResources};
use embassy_rp::{bind_interrupts, interrupt};
use embassy_rp::clocks::RoscRng;
use embassy_rp::gpio::{AnyPin, Input, InterruptTrigger, Level, Output};
use embassy_rp::peripherals::{DMA_CH0, PIN_22, PIO0, UART1, USB};
use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::usb::Driver;
use embassy_time::{Timer};
use embedded_io_async::{Read, ReadReady, Write};
use music::{music_manager, COMMANDS};
use rand::RngCore;
use reqwless::response;
use scanner::{data_extractor, spawn_poller};
use server::server_task;
use static_cell::StaticCell;
use defmt_rtt as _;
use wiggle::wiggle_manager;
pub mod wiggle;
pub mod music;
pub mod scanner;
pub mod auth;
pub mod arraymap;
pub mod server;
bind_interrupts!(pub struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
USBCTRL_IRQ => embassy_rp::usb::InterruptHandler<USB>;
UART1_IRQ => BufferedInterruptHandler<UART1>;
});

View file

@ -15,7 +15,7 @@ use core::panic::PanicInfo;
use core::str::from_utf8;
use core::sync::atomic::{AtomicU8};
use auth::send_badge;
use outside::auth::send_badge;
use bt_hci::cmd::info;
use critical_section::Mutex;
use cyw43::JoinOptions;
@ -42,33 +42,15 @@ use embassy_rp::pio::{InterruptHandler, Pio};
use embassy_rp::usb::Driver;
use embassy_time::{Timer};
use embedded_io_async::{Read, ReadReady, Write};
use music::music_manager;
use outside::music::{self, music_manager, COMMANDS};
use rand::RngCore;
use reqwless::response;
use scanner::{data_extractor, spawn_poller};
use outside::scanner::{data_extractor, spawn_poller, CHANNEL};
use outside::server::server_task;
use static_cell::StaticCell;
use defmt_rtt as _;
use wiggle::wiggle_manager;
mod wiggle;
mod music;
mod scanner;
mod auth;
bind_interrupts!(struct Irqs {
PIO0_IRQ_0 => InterruptHandler<PIO0>;
USBCTRL_IRQ => embassy_rp::usb::InterruptHandler<USB>;
UART1_IRQ => BufferedInterruptHandler<UART1>;
});
static READ_CARD: Mutex<RefCell<u64>> =
Mutex::new(RefCell::new(0));
static BIT: AtomicU8 = AtomicU8::new(0);
static CHANNEL: Channel<CriticalSectionRawMutex, u64, 1> = Channel::new();
static MUSIC: Channel<CriticalSectionRawMutex, (&'static str, u8), 3> = Channel::new();
static WAGS: AtomicU8 = AtomicU8::new(0);
use outside::wiggle::wiggle_manager;
use outside::Irqs;
#[embassy_executor::task]
async fn logger_task(driver: Driver<'static, USB>) {
@ -161,6 +143,7 @@ async fn main(spawner: Spawner) {
spawner.spawn(send_badge(CHANNEL.receiver(),stack)).unwrap();
spawner.spawn(button_manager(p.PIN_22)).unwrap();
spawner.spawn(wiggle_manager(p.PWM_SLICE5, p.PIN_26, p.PIN_27)).unwrap();
spawner.spawn(server_task(stack)).unwrap();
}
@ -169,7 +152,7 @@ async fn button_manager(pin: PIN_22) -> ! {
let mut button = Input::new(pin, embassy_rp::gpio::Pull::Up);
loop {
button.wait_for_rising_edge().await;
MUSIC.send(("d",5)).await;
COMMANDS.send(music::MusicCommand::Play("d5")).await; // TODO: record
Timer::after_millis(800).await;
}
}

View file

@ -1,11 +1,19 @@
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 super::WAGS;
use crate::server::NAMES;
use crate::wiggle::WAGS;
use crate::Irqs;
use super::MUSIC;
use embassy_rp::uart::BufferedUart;
@ -13,13 +21,71 @@ use embassy_rp::peripherals::PIN_21;
use embassy_rp::peripherals::PIN_20;
use super::Irqs;
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::Coke => todo!(),
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::Coke => "button",
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),
}
#[embassy_executor::task]
pub(crate) async fn music_manager(uart: UART1, irqs: Irqs, txp: PIN_20, rxp: PIN_21) -> ! {
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];
@ -27,55 +93,91 @@ pub(crate) async fn music_manager(uart: UART1, irqs: Irqs, txp: PIN_20, rxp: PIN
let mut uart = BufferedUart::new(uart, irqs, txp, rxp, &mut tx, &mut rx, config);
let mut rng = RoscRng;
loop {
let song = MUSIC.receive().await;
info!("playing: {}{}.mp3",song.0,song.1);
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::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(song.0.as_bytes()).await.unwrap();
uart.write_all(itoa::Buffer::new().format(song.1).as_bytes()).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];
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)]) };
info!("returned: {}",read_line(&mut buffer, uart).await.trim());
if to_print.contains("\r\n") {
info!("{}", to_print);
break;
}
pos += len;
} else {
break;
}
}
uart.write_all(b"AT+QUERY=4\r\n").await.unwrap();
let mut buffer = [0;512];
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;
}
}
let output = unsafe { core::str::from_utf8_unchecked(&buffer[..(pos)]) };
let output = read_line(&mut buffer, uart).await;
if let Ok(length) = output.trim().parse::<u64>() {
WAGS.store(length as u8, 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)]) };
}

View file

@ -1,21 +1,31 @@
use core::cell::RefCell;
use core::sync::atomic::AtomicBool;
use embassy_rp::gpio::Input;
use embassy_rp::multicore::spawn_core1;
use embassy_rp::multicore::Stack;
use embassy_rp::peripherals::CORE1;
use embassy_rp::peripherals::PIN_16;
use embassy_rp::peripherals::PIN_17;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;
use embassy_time::Timer;
use log::info;
use critical_section::Mutex;
use core::sync::atomic::{AtomicU8};
use super::CHANNEL;
pub static READ_CARD: Mutex<RefCell<u64>> =
Mutex::new(RefCell::new(0));
static BIT: AtomicU8 = AtomicU8::new(0);
use super::BIT;
pub static CHANNEL: Channel<CriticalSectionRawMutex, u64, 1> = Channel::new();
use super::READ_CARD;
/// disable scanner when doing emf heavy operations
pub static LOCKOUT: AtomicBool = AtomicBool::new(false);
#[embassy_executor::task]
pub(crate) async fn data_extractor() -> ! {
pub async fn data_extractor() -> ! {
let mut last_bit = 0;
loop {
Timer::after_millis(75).await;
@ -26,7 +36,12 @@ pub(crate) async fn data_extractor() -> ! {
if bit == last_bit {
if card !=0 {
info!("read a card: {card:#16x}");
if LOCKOUT.load(core::sync::atomic::Ordering::Relaxed) {
info!("scanner disabled");
} else {
CHANNEL.send(card).await;
}
}
critical_section::with(|cs| {
READ_CARD.replace(cs, 0);

95
outside/src/server.rs Normal file
View file

@ -0,0 +1,95 @@
use core::{cell::RefCell, str::from_utf8};
use common::{Name, Request};
use embassy_net::tcp::TcpSocket;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
use embassy_time::Duration;
use embedded_io_async::Write;
use log::*;
use postcard::from_bytes;
use serde::{Deserialize, Serialize};
use crate::{arraymap::ArrayMap, music::{COMMANDS}, scanner::READ_CARD};
pub static NAMES: Mutex<CriticalSectionRawMutex, RefCell<ArrayMap<64, u64, Name>>> =
Mutex::new(RefCell::new(ArrayMap::new()));
#[embassy_executor::task]
pub async fn server_task(stack: embassy_net::Stack<'static>) {
let mut rx_buffer = [0; 4096];
let mut tx_buffer = [0; 4096];
let mut buf = [0; 4096];
loop {
let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
socket.set_timeout(Some(Duration::from_secs(3)));
info!("Listening on TCP:1234...");
if let Err(e) = socket.accept(1234).await {
warn!("accept error: {:?}", e);
continue;
}
info!("Received connection from {:?}", socket.remote_endpoint());
loop {
let n = match socket.read(&mut buf).await {
Ok(0) => {
warn!("read EOF");
break;
}
Ok(n) => n,
Err(e) => {
warn!("read error: {:?}", e);
break;
}
};
match from_bytes::<Request>(&buf[..n]) {
Ok(Request::RecentBadge) => {
let card = critical_section::with(|cs| {
READ_CARD.borrow(cs).clone().into_inner()
});
socket.write_all(itoa::Buffer::new().format(card).as_bytes()).await.unwrap();
},
Ok(Request::SetRecentBadge(name)) => {
let card = critical_section::with(|cs| {
READ_CARD.borrow(cs).clone().into_inner()
});
NAMES.lock().await.borrow_mut().insert(card, name);
}
Ok(Request::SetVolume(vol)) => {
COMMANDS.send(crate::music::MusicCommand::SetVolume(vol)).await;
}
Err(e) => { info!("parse error: {e}") }
}
info!("rxd {}", from_utf8(&buf[..n]).unwrap());
/*let mut segs = buf[..n].trim_ascii().split(|c| *c == ' ' as u8);
match char::from_u32(segs.next().unwrap()[0] as u32).unwrap() {
'B' => {
let card = critical_section::with(|cs| {
READ_CARD.borrow(cs).clone().into_inner()
});
socket.write_all(itoa::Buffer::new().format(card).as_bytes()).await.unwrap();
},
'R' => {
let card = critical_section::with(|cs| {
READ_CARD.borrow(cs).clone().into_inner()
});
NAMES.lock().await.borrow_mut().insert(card, Name::Unknown);
},
_ => {}
}
*/
}
}
}

View file

@ -1,10 +1,14 @@
use core::sync::atomic::AtomicU8;
use embassy_rp::clocks::RoscRng;
use embassy_rp::pwm;
use embassy_time::Timer;
use rand::RngCore;
use super::WAGS;
use crate::scanner::LOCKOUT;
pub static WAGS: AtomicU8 = AtomicU8::new(0);
use embassy_rp::pwm::Pwm;
@ -15,7 +19,7 @@ use embassy_rp::peripherals::PIN_26;
use embassy_rp::peripherals::PWM_SLICE5;
#[embassy_executor::task]
pub(crate) async fn wiggle_manager(pwm: PWM_SLICE5, head: PIN_26, tail: PIN_27) -> ! {
pub async fn wiggle_manager(pwm: PWM_SLICE5, head: PIN_26, tail: PIN_27) -> ! {
let mut c: pwm::Config = Default::default();
c.divider = 40.into();
c.top = 62_500; // 20ms
@ -30,6 +34,7 @@ pub(crate) async fn wiggle_manager(pwm: PWM_SLICE5, head: PIN_26, tail: PIN_27)
wags = WAGS.load(core::sync::atomic::Ordering::SeqCst);
if wags != 0 {
WAGS.store(0, core::sync::atomic::Ordering::SeqCst);
LOCKOUT.store(true, core::sync::atomic::Ordering::SeqCst);
break;
}
@ -37,7 +42,7 @@ pub(crate) async fn wiggle_manager(pwm: PWM_SLICE5, head: PIN_26, tail: PIN_27)
pwm.set_config(&c);
Timer::after_millis(50).await;
LOCKOUT.store(false, core::sync::atomic::Ordering::SeqCst);
}
let positions = [6200,4800,6248,4700, 5500];

1
server/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
target

481
server/Cargo.lock generated Normal file
View file

@ -0,0 +1,481 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "addr2line"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"gimli",
]
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "anyhow"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "backtrace"
version = "0.3.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-targets",
]
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cobs"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "common"
version = "0.1.0"
dependencies = [
"serde",
]
[[package]]
name = "critical-section"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "embedded-io"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
[[package]]
name = "embedded-io"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "gimli"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"byteorder",
]
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32",
"rustc_version",
"serde",
"spin",
"stable_deref_trait",
]
[[package]]
name = "libc"
version = "0.2.167"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
[[package]]
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
dependencies = [
"adler2",
]
[[package]]
name = "mio"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [
"libc",
"wasi",
"windows-sys",
]
[[package]]
name = "object"
version = "0.36.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
dependencies = [
"memchr",
]
[[package]]
name = "parking_lot"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "pin-project-lite"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
[[package]]
name = "postcard"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8"
dependencies = [
"cobs",
"embedded-io 0.4.0",
"embedded-io 0.6.1",
"heapless",
"serde",
]
[[package]]
name = "proc-macro2"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "serde"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "server"
version = "0.1.0"
dependencies = [
"anyhow",
"common",
"postcard",
"serde",
"tokio",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "2.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tokio"
version = "1.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
]
[[package]]
name = "tokio-macros"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

11
server/Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "server"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.94"
common = {path = "../common"}
postcard = {version = "1.0.0", features = ["alloc"]}
serde = "*"
tokio = { version = "1.42.0", features = ["full"] }

27
server/src/main.rs Normal file
View file

@ -0,0 +1,27 @@
use common::Request;
use postcard::{to_allocvec, to_vec};
use tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::TcpStream};
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()>{
println!("Hello, world!");
let mut conn = TcpStream::connect("169.254.2.1:1234").await?;
let req = Request::RecentBadge;
conn.write_all(&to_allocvec(&req)?).await?;
let req = Request::SetVolume(23);
println!("{:?}", to_allocvec(&req).unwrap());
conn.write_all(&to_allocvec(&req)?).await?;
conn.flush().await?;
let mut buf = String::new();
conn.read_to_string(&mut buf).await?;
println!("recv: {}", buf.trim());
Ok(())
}