#![no_std] #![no_main] use core::char; use arduino_uno::{delay_ms, hal::port::{mode::Output, portb::PB5}, prelude::*}; use panic_halt as _; const SHORT: u16 = 75; const LONG: u16 = SHORT * 3; const SPACE: u16 = SHORT * 7; struct RingBuf { data: [T; N], read_idx: usize, write_idx: usize, } impl RingBuf { pub fn new(initial: T) -> Self { Self { data: [initial; N], read_idx: 0, write_idx: 0, } } pub fn peek(&self) -> Option { if self.write_idx != self.read_idx { Some(self.data[self.read_idx]) } else { None } } pub fn push(&mut self, value: T) { if self.write_idx + 1 != self.read_idx { self.data[self.write_idx] = value; self.write_idx += 1; if self.write_idx == N { self.write_idx = 0; } } } pub fn pop(&mut self) -> Option { if self.write_idx != self.read_idx { let res = Some(self.data[self.read_idx]); self.read_idx += 1; if self.read_idx == N { self.read_idx = 0; } res } else { None } } } #[derive(Clone, Copy)] struct LedInstruction { state: bool, time: u16, left: u16, } impl LedInstruction { pub fn new(state: bool, time: u16) -> Self { Self { state, time, left: time, } } } macro_rules! morse { ( $led:expr, $( $delay:expr ),* ) => { { $( $led.set_high().void_unwrap(); delay_ms($delay); $led.set_low().void_unwrap(); delay_ms(SHORT); )* delay_ms(LONG - SHORT); } }; } macro_rules! push_morse { ( $buf:expr, $( $delay:expr ),* ) => { { $( $buf.push(LedInstruction::new(true, $delay)); $buf.push(LedInstruction::new(false, SHORT)); )* $buf.push(LedInstruction::new(false, LONG - SHORT)); } } } fn push_morse(buf: &mut RingBuf, c: u8) { let c = char::from_u32(c as u32); if let Some(c) = c { match c { 'a' => { buf.push(LedInstruction::new(true, SHORT)); buf.push(LedInstruction::new(false, SHORT)); buf.push(LedInstruction::new(true, LONG)); buf.push(LedInstruction::new(false, SHORT)); buf.push(LedInstruction::new(false, LONG - SHORT)); }, 'b' => push_morse!(buf, LONG, SHORT, SHORT, SHORT), _ => {}, } } } fn blink_morse(led: &mut PB5, c: u8) { let c = char::from_u32(c as u32); if let Some(c) = c { match c { 'a' => morse!(led, SHORT, LONG), 'b' => morse!(led, LONG, SHORT, SHORT, SHORT), 'c' => morse!(led, LONG, SHORT, LONG, SHORT), 'd' => morse!(led, LONG, SHORT, SHORT), 'e' => morse!(led, SHORT), 'f' => morse!(led, SHORT, SHORT, LONG, SHORT), 'g' => morse!(led, LONG, LONG, SHORT), 'h' => morse!(led, SHORT, SHORT, SHORT, SHORT), 'i' => morse!(led, SHORT, SHORT), 'j' => morse!(led, SHORT, LONG, LONG, LONG), 'k' => morse!(led, LONG, SHORT, LONG), 'l' => morse!(led, SHORT, LONG, SHORT, SHORT), 'm' => morse!(led, LONG, LONG), 'n' => morse!(led, LONG, SHORT), 'o' => morse!(led, LONG, LONG, LONG), 'p' => morse!(led, SHORT, LONG, LONG, SHORT), 'q' => morse!(led, LONG, LONG, SHORT, LONG), 'r' => morse!(led, SHORT, LONG, SHORT), 's' => morse!(led, SHORT, SHORT, SHORT), 't' => morse!(led, LONG), 'u' => morse!(led, SHORT, SHORT, LONG), 'v' => morse!(led, SHORT, SHORT, SHORT, LONG), 'w' => morse!(led, SHORT, LONG, LONG), 'x' => morse!(led, LONG, SHORT, SHORT, LONG), 'y' => morse!(led, LONG, SHORT, LONG, LONG), 'z' => morse!(led, LONG, LONG, SHORT, SHORT), '1' => morse!(led, SHORT, LONG, LONG, LONG, LONG), '2' => morse!(led, SHORT, SHORT, LONG, LONG, LONG), '3' => morse!(led, SHORT, SHORT, SHORT, LONG, LONG), '4' => morse!(led, SHORT, SHORT, SHORT, SHORT, LONG), '5' => morse!(led, SHORT, SHORT, SHORT, SHORT, SHORT), '6' => morse!(led, LONG, SHORT, SHORT, SHORT, SHORT), '7' => morse!(led, LONG, LONG, SHORT, SHORT, SHORT), '8' => morse!(led, LONG, LONG, LONG, SHORT, SHORT), '9' => morse!(led, LONG, LONG, LONG, LONG, SHORT), '0' => morse!(led, LONG, LONG, LONG, LONG, LONG), ' ' => delay_ms(SPACE - LONG), _ => {}, } } } #[arduino_uno::entry] fn main() -> ! { let dp = arduino_uno::Peripherals::take().unwrap(); let mut pins = arduino_uno::Pins::new(dp.PORTB, dp.PORTC, dp.PORTD); let mut led = pins.d13.into_output(&mut pins.ddr); led.set_low().void_unwrap(); let mut serial = arduino_uno::Serial::new( dp.USART0, pins.d0, pins.d1.into_output(&mut pins.ddr), 57600.into_baudrate(), ); let mut buf: RingBuf<_, 100> = RingBuf::new(LedInstruction::new(false, 0)); loop { // let b = nb::block!(serial.read()).void_unwrap(); match serial.read() { Ok(b) => push_morse(&mut buf, b), Err(_) => {}, } buf.update(millis()); } }