diff --git a/outside/src/auth.rs b/outside/src/auth.rs new file mode 100644 index 0000000..5baf355 --- /dev/null +++ b/outside/src/auth.rs @@ -0,0 +1,64 @@ + +use super::MUSIC; + +use embassy_net::{IpEndpoint, Ipv4Address}; +use embassy_time::Duration; + +use embassy_net::tcp::TcpSocket; + +use embassy_rp::clocks::RoscRng; + +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; + +use embassy_sync::channel::Receiver; +use embedded_io_async::Write; +use log::*; +use rand::RngCore; + +#[embassy_executor::task] +pub(crate) 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 mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + info!("attempting conn to inside"); + if let Err(e) = socket.connect(IpEndpoint::new(Ipv4Address::new(169, 254, 1, 1).into_address(), 1234)).await { + warn!("connect error: {:?}", e); + continue; + } + + info!("Connected to {:?}", socket.remote_endpoint()); + + let mut data: [u8;18] = [b'0';18]; + data[0] = b'B'; + data[1] = b' '; + hex::encode_to_slice(&card.to_ne_bytes(), &mut data[2..]).unwrap(); + + let to_print = unsafe { core::str::from_utf8_unchecked(&data) }; + info!("data: {to_print}"); + + //socket.write_all(b"O \r\n").await.unwrap(); + + socket.write_all(&data).await.unwrap(); + info!("wrote to {:?}", socket.remote_endpoint()); + + socket.flush().await.unwrap(); + + socket.close(); + info!("disconnected"); + + MUSIC.send(("a",num as u8)).await; + MUSIC.send((name,num as u8)).await; + } +} diff --git a/outside/src/main.rs b/outside/src/main.rs index fd70b5f..3e63f8b 100644 --- a/outside/src/main.rs +++ b/outside/src/main.rs @@ -15,6 +15,7 @@ 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; @@ -23,28 +24,36 @@ 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, Pwm}; -use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart}; +use embassy_rp::pwm::{self}; +use embassy_rp::uart::{BufferedInterruptHandler}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::channel::{Channel, Receiver}; +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, uart}; +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_20, PIN_21, PIN_22, PIN_26, PIN_27, PIO0, PWM_SLICE5, UART1, USB}; +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::{Duration, Timer}; +use embassy_time::{Timer}; use embedded_io_async::{Read, ReadReady, Write}; +use music::music_manager; use rand::RngCore; use reqwless::response; +use scanner::{data_extractor, spawn_poller}; 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; @@ -76,27 +85,6 @@ async fn net_task(mut runner: embassy_net::Runner<'static, cyw43::NetDriver<'sta runner.run().await } -#[embassy_executor::task] -async fn data_extractor() -> ! { - let mut last_bit = 0; - loop { - Timer::after_millis(75).await; - let card = critical_section::with(|cs| { - READ_CARD.borrow(cs).clone().into_inner() - }); - let bit = BIT.load(core::sync::atomic::Ordering::SeqCst); - if bit == last_bit { - if card !=0 { - info!("read a card: {card:#16x}"); - CHANNEL.send(card).await; - } - critical_section::with(|cs| { - READ_CARD.replace(cs, 0); - }); - } - last_bit = bit; - } -} #[panic_handler] fn panic( info: &PanicInfo) -> ! { @@ -107,11 +95,6 @@ fn panic( info: &PanicInfo) -> ! { #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); - let data_0= Input::new(p.PIN_17, embassy_rp::gpio::Pull::None); - let data_1= Input::new(p.PIN_16, embassy_rp::gpio::Pull::None); - - spawner.spawn(music_manager(p.UART1, Irqs, p.PIN_20, p.PIN_21)).unwrap(); - let mut rng = RoscRng; @@ -172,86 +155,13 @@ async fn main(spawner: Spawner) { } } + spawner.spawn(music_manager(p.UART1, Irqs, p.PIN_20, p.PIN_21)).unwrap(); spawner.spawn(data_extractor()).unwrap(); + spawn_poller(p.CORE1, p.PIN_17, p.PIN_16); + 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(); - let mut partial: u64 = 0; - let mut bit: u8 = 0; - let mut prev: (bool,bool) = (false,false); - - static mut CORE1_STACK: Stack<4096> = Stack::new(); - spawn_core1(p.CORE1, unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, move || { - loop { - let current = (data_0.is_low(), data_1.is_low()); - if current.1 && !prev.1 { - partial |= 1 << bit; - bit += 1; - } - if current.0 && !prev.0 { - partial &= !(1u64).rotate_left(bit as u32); - bit += 1; - } - prev=current; - - critical_section::with(|cs| { - let mut foreign_partial = READ_CARD.borrow_ref_mut(cs); - - // may or may not be sound, should work fine given no noise on the signal - if *foreign_partial != partial && !current.0 && !current.1 { - bit = 0; - partial = *foreign_partial; - } - - *foreign_partial = partial; - }); - - BIT.store(bit, core::sync::atomic::Ordering::SeqCst); - } - }); - - defmt::unwrap!(spawner.spawn(send_badge(CHANNEL.receiver(),stack))); - defmt::unwrap!(spawner.spawn(button_manager(p.PIN_22))); - defmt::unwrap!(spawner.spawn(wiggle_manager(p.PWM_SLICE5, p.PIN_26, p.PIN_27))); - -} - -#[embassy_executor::task] -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 - c.compare_a = 4687; // 1.5ms - c.compare_b = 4687; // 1.5ms - let mut pwm = Pwm::new_output_ab(pwm, head, tail, c.clone()); - - loop { - let mut wags; - loop { - // atomics aren't actually real - wags = WAGS.load(core::sync::atomic::Ordering::SeqCst); - if wags != 0 { - WAGS.store(0, core::sync::atomic::Ordering::SeqCst); - break; - } - - c.compare_b = 6248; - pwm.set_config(&c); - - Timer::after_millis(50).await; - - } - - let positions = [6200,4800,6248,4700, 5500]; - - let mut rng = RoscRng; - for _ in 0..wags { - - let idx = rng.next_u32(); - c.compare_b = positions[idx as usize % positions.len()]; - pwm.set_config(&c); - - Timer::after_millis(idx as u64 % 600).await; - } - } } #[embassy_executor::task] @@ -263,114 +173,3 @@ async fn button_manager(pin: PIN_22) -> ! { Timer::after_millis(800).await; } } - - -#[embassy_executor::task] -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); - - loop { - let song = MUSIC.receive().await; - info!("playing: {}{}.mp3",song.0,song.1); - - 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(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)]) }; - - 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)]) }; - - if let Ok(length) = output.trim().parse::() { - WAGS.store(length as u8, core::sync::atomic::Ordering::SeqCst); - Timer::after_secs(length).await; - } - } -} - -#[embassy_executor::task] -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 mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(Duration::from_secs(10))); - info!("attempting conn to inside"); - if let Err(e) = socket.connect(IpEndpoint::new(Ipv4Address::new(169, 254, 1, 1).into_address(), 1234)).await { - warn!("connect error: {:?}", e); - continue; - } - - info!("Connected to {:?}", socket.remote_endpoint()); - - let mut data: [u8;18] = [b'0';18]; - data[0] = b'B'; - data[1] = b' '; - hex::encode_to_slice(&card.to_ne_bytes(), &mut data[2..]).unwrap(); - - let to_print = unsafe { core::str::from_utf8_unchecked(&data) }; - info!("data: {to_print}"); - - //socket.write_all(b"O \r\n").await.unwrap(); - - socket.write_all(&data).await.unwrap(); - info!("wrote to {:?}", socket.remote_endpoint()); - - socket.flush().await.unwrap(); - - socket.close(); - info!("disconnected"); - - MUSIC.send(("a",num as u8)).await; - MUSIC.send((name,num as u8)).await; - } -} diff --git a/outside/src/music.rs b/outside/src/music.rs new file mode 100644 index 0000000..1c634ab --- /dev/null +++ b/outside/src/music.rs @@ -0,0 +1,81 @@ +use embassy_rp::uart; +use embassy_time::Timer; +use embedded_io_async::Read; +use embedded_io_async::Write; + +use super::WAGS; + +use super::MUSIC; + +use embassy_rp::uart::BufferedUart; + +use embassy_rp::peripherals::PIN_21; + +use embassy_rp::peripherals::PIN_20; + +use super::Irqs; + +use embassy_rp::peripherals::UART1; +use log::*; + +#[embassy_executor::task] +pub(crate) 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); + + loop { + let song = MUSIC.receive().await; + info!("playing: {}{}.mp3",song.0,song.1); + + 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(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)]) }; + + 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)]) }; + + if let Ok(length) = output.trim().parse::() { + WAGS.store(length as u8, core::sync::atomic::Ordering::SeqCst); + Timer::after_secs(length).await; + } + } +} diff --git a/outside/src/scanner.rs b/outside/src/scanner.rs new file mode 100644 index 0000000..f399e6c --- /dev/null +++ b/outside/src/scanner.rs @@ -0,0 +1,76 @@ + +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_time::Timer; +use log::info; + +use super::CHANNEL; + +use super::BIT; + +use super::READ_CARD; + +#[embassy_executor::task] +pub(crate) async fn data_extractor() -> ! { + let mut last_bit = 0; + loop { + Timer::after_millis(75).await; + let card = critical_section::with(|cs| { + READ_CARD.borrow(cs).clone().into_inner() + }); + let bit = BIT.load(core::sync::atomic::Ordering::SeqCst); + if bit == last_bit { + if card !=0 { + info!("read a card: {card:#16x}"); + CHANNEL.send(card).await; + } + critical_section::with(|cs| { + READ_CARD.replace(cs, 0); + }); + } + last_bit = bit; + } +} + +pub fn spawn_poller(core: CORE1, data_0: PIN_17, data_1: PIN_16) { + let data_0= Input::new(data_0, embassy_rp::gpio::Pull::None); + let data_1= Input::new(data_1, embassy_rp::gpio::Pull::None); + + let mut partial: u64 = 0; + let mut bit: u8 = 0; + let mut prev: (bool,bool) = (false,false); + + static mut CORE1_STACK: Stack<4096> = Stack::new(); + spawn_core1(core, unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, move || { + loop { + let current = (data_0.is_low(), data_1.is_low()); + if current.1 && !prev.1 { + partial |= 1 << bit; + bit += 1; + } + if current.0 && !prev.0 { + partial &= !(1u64).rotate_left(bit as u32); + bit += 1; + } + prev=current; + + critical_section::with(|cs| { + let mut foreign_partial = READ_CARD.borrow_ref_mut(cs); + + // may or may not be sound, should work fine given no noise on the signal + if *foreign_partial != partial && !current.0 && !current.1 { + bit = 0; + partial = *foreign_partial; + } + + *foreign_partial = partial; + }); + + BIT.store(bit, core::sync::atomic::Ordering::SeqCst); + } + }); +} diff --git a/outside/src/wiggle.rs b/outside/src/wiggle.rs new file mode 100644 index 0000000..5a3edae --- /dev/null +++ b/outside/src/wiggle.rs @@ -0,0 +1,55 @@ +use embassy_rp::clocks::RoscRng; + +use embassy_rp::pwm; +use embassy_time::Timer; +use rand::RngCore; + +use super::WAGS; + +use embassy_rp::pwm::Pwm; + +use embassy_rp::peripherals::PIN_27; + +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) -> ! { + let mut c: pwm::Config = Default::default(); + c.divider = 40.into(); + c.top = 62_500; // 20ms + c.compare_a = 4687; // 1.5ms + c.compare_b = 4687; // 1.5ms + let mut pwm = Pwm::new_output_ab(pwm, head, tail, c.clone()); + + loop { + let mut wags; + loop { + // atomics aren't actually real + wags = WAGS.load(core::sync::atomic::Ordering::SeqCst); + if wags != 0 { + WAGS.store(0, core::sync::atomic::Ordering::SeqCst); + break; + } + + c.compare_b = 6248; + pwm.set_config(&c); + + Timer::after_millis(50).await; + + } + + let positions = [6200,4800,6248,4700, 5500]; + + let mut rng = RoscRng; + for _ in 0..wags { + + let idx = rng.next_u32(); + c.compare_b = positions[idx as usize % positions.len()]; + pwm.set_config(&c); + + Timer::after_millis(idx as u64 % 600).await; + } + } +}