diff --git a/src/main.rs b/src/main.rs index 26f6bc3..631210b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,16 @@ #![no_std] #![no_main] +#![feature(abi_avr_interrupt)] +use arduino_hal::hal::Atmega; +use arduino_hal::hal::port::{PE0, PE1, PD2, PD3}; +use arduino_hal::port::Pin; +use arduino_hal::port::mode::{Input, Output}; use arduino_hal::Peripherals; use arduino_hal::prelude::*; +use arduino_hal::usart::{UsartOps, Usart}; +use avr_device::atmega2560::{USART0, USART1}; use panic_halt as _; use embedded_hal::serial::Read; @@ -12,47 +19,69 @@ mod webee; use webee::Webee; use crate::webee::SendCmd::{Baudrate, Channel, MAC, PanId, Role, TransmitPower, ZigbeeNetworkKey}; +use webee::BufferErr; +static mut WEBEE: Option, Pin>> = None; +static mut BUFFER_STATUS: Result<(), BufferErr> = Ok(()); + + +#[avr_device::interrupt(atmega2560)] +unsafe fn USART1_RX() { + let mut webee = WEBEE.as_mut().unwrap(); + if let Ok(b) = webee.webee.read() { + if let Err(x) = webee.READ_BUFFER.write(b) { + BUFFER_STATUS = Err(x); + } + } +} #[arduino_hal::entry] fn main() -> ! { let dp = Peripherals::take().unwrap(); let pins = arduino_hal::pins!(dp); - let mut status = pins.d13.into_output(); - let mut serial = arduino_hal::default_serial!(dp, pins, 57600); - + let mut err_led = pins.d13.into_output(); + let mut console = arduino_hal::default_serial!(dp, pins, 57600); unsafe { avr_device::interrupt::enable(); } - let mut webee = Webee::new( - dp.USART1, - pins.d19.forget_imode(), - pins.d18.into_output(), - ); + // let mut webee = Webee::new( + unsafe { + WEBEE = Some(Webee::new( + dp.USART1, + pins.d19.forget_imode(), + pins.d18.into_output(), + )); + } - ufmt::uwriteln!(&mut serial, "Webee initialized.").void_unwrap(); + ufmt::uwriteln!(&mut console, "Webee initialized.").void_unwrap(); // -------------------------------- - let cmd = ZigbeeNetworkKey; - let command_string = cmd.to_str(); - let response = webee.send_cmd(cmd); - - ufmt::uwrite!(&mut serial, "[{}] {}:", response.len(), command_string).void_unwrap(); - for i in 0..response.len() { - // for i in 0..10 { - ufmt::uwrite!(&mut serial, " {:02X}", *response.get(i).unwrap()).void_unwrap(); - } - ufmt::uwriteln!(&mut serial, "").void_unwrap(); + // let cmd = ZigbeeNetworkKey; + // let command_string = cmd.to_str(); + // let response; + // unsafe { + // response = WEBEE.as_mut().unwrap().send_cmd(cmd); + // } + // + // ufmt::uwrite!(&mut serial, "[{}] {}:", response.len(), command_string).void_unwrap(); + // for i in 0..response.len() { + // // for i in 0..10 { + // ufmt::uwrite!(&mut serial, " {:02X}", *response.get(i).unwrap()).void_unwrap(); + // } + // ufmt::uwriteln!(&mut serial, "").void_unwrap(); // for cmd in [Role, Baudrate, PanId, Channel, TransmitPower, MAC, ZigbeeNetworkKey] { // let command_string = cmd.to_str(); - // let response = webee.send_cmd(cmd); + // let response; + // unsafe { + // response = WEBEE.as_mut().unwrap().send_cmd(cmd); + // } // // ufmt::uwrite!(&mut serial, "[{}] {}:", response.len(), command_string).void_unwrap(); // for i in 0..response.len() { - // // for i in 0..10 { + // // for i in 0..10 { // ufmt::uwrite!(&mut serial, " {:02X}", *response.get(i).unwrap()).void_unwrap(); // } // ufmt::uwriteln!(&mut serial, "").void_unwrap(); @@ -60,10 +89,50 @@ fn main() -> ! { // -------------------------------- - loop { - let b = nb::block!(serial.read()).unwrap(); + let webee; + unsafe { + webee = WEBEE.as_mut().unwrap(); + } - ufmt::uwriteln!(&mut serial, "Got {:X}!", b).void_unwrap(); + unsafe { + WEBEE.as_mut().unwrap().void_send_cmd(ZigbeeNetworkKey); + } + + ufmt::uwriteln!(&mut console, "Starting Loop!").void_unwrap(); + + loop { + // Errors + if let Err(err) = unsafe { BUFFER_STATUS } { + err_led.toggle(); + match err { + BufferErr::Full => { + arduino_hal::delay_ms(100); + } + BufferErr::Empty => { + arduino_hal::delay_ms(1000); + } + BufferErr::NotEnoughSpace => { + arduino_hal::delay_ms(5000); + } + } + continue; + } + + // Read a byte from the serial connection and put response in buffer. + if unsafe { webee.READ_BUFFER.has_data() } { + let b = match unsafe { webee.READ_BUFFER.read() } { + Ok(b) => b, + Err(x) => { + unsafe { + BUFFER_STATUS = Err(x); + } + continue; + } + }; + unsafe { + ufmt::uwriteln!(&mut console, "Got {:02X}!\r", b).void_unwrap(); + } + } } } diff --git a/src/webee.rs b/src/webee.rs index ff20d7a..416d643 100644 --- a/src/webee.rs +++ b/src/webee.rs @@ -1,3 +1,5 @@ +mod ring_buffer; + use arduino_hal::delay_ms; use arduino_hal::hal::Atmega; use arduino_hal::port::{Pin, PinOps}; @@ -6,11 +8,13 @@ use arduino_hal::usart::{Usart, UsartOps}; use arduino_hal::prelude::*; use heapless::Vec; +pub use crate::webee::ring_buffer::{RingBuffer, BufferErr}; pub struct Webee, RX, TX> { pub webee: Usart, + pub READ_BUFFER: RingBuffer } #[repr(u8)] @@ -57,10 +61,11 @@ Webee< { pub fn new(device: USART, rx: Pin, tx: Pin) -> Self { let mut interface = Usart::new(device, rx, tx, 38400.into_baudrate()); - // interface.listen(arduino_hal::hal::usart::Event::RxComplete); + interface.listen(arduino_hal::hal::usart::Event::RxComplete); let instance = Self { - webee: interface + webee: interface, + READ_BUFFER: RingBuffer::new() }; delay_ms(1000); @@ -86,6 +91,11 @@ Webee< self.send(&frame) } + pub fn void_send_cmd(&mut self, cmd: SendCmd) { + let frame = [0x5A, 0xAA, cmd as u8]; + self.void_send(frame.as_slice()) + } + pub fn query_parameter(&mut self) {} pub fn recv(&mut self) -> Vec { diff --git a/src/webee/ring_buffer.rs b/src/webee/ring_buffer.rs new file mode 100644 index 0000000..9d641fd --- /dev/null +++ b/src/webee/ring_buffer.rs @@ -0,0 +1,68 @@ + +use arduino_hal::prelude::*; + +use embedded_hal::serial::Read; +use ufmt::uWrite; + +const BUFFER_SIZE: usize = 128; +pub struct RingBuffer { + data: [u8; BUFFER_SIZE], + start: u16, + end: u16, +} + +#[derive(Copy, Clone)] +pub enum BufferErr { + Full, + Empty, + NotEnoughSpace, +} + +impl RingBuffer { + pub const fn new() -> Self { + RingBuffer { + start: 0, + end: 0, + data: [0; BUFFER_SIZE], + } + } + const fn size_remaining(&self) -> u16 { + if self.has_data() { + (self.start + BUFFER_SIZE as u16 - self.end) % BUFFER_SIZE as u16 + } else { + BUFFER_SIZE as u16 + } + } + pub const fn has_data(&self) -> bool { + self.start != self.end + } + pub fn write(&mut self, data: u8) -> Result<(), BufferErr> { + let next = (self.end + 1) % BUFFER_SIZE as u16; + if next == self.start { + return Err(BufferErr::Full); + } + self.data[next as usize] = data; + self.end = next; + Ok(()) + } + pub fn read(&mut self) -> Result { + if !self.has_data() { + return Err(BufferErr::Empty); + } + self.start = (self.start + 1) % BUFFER_SIZE as u16; + Ok(self.data[self.start as usize]) + } +} + +impl uWrite for RingBuffer { + type Error = BufferErr; + fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { + if (self.size_remaining() as usize) < s.len() { + return Err(BufferErr::NotEnoughSpace); + } + for b in s.bytes() { + self.write(b)?; + } + Ok(()) + } +}