commit 382327e9290576dc00ec52edfac3f52837f184ea
parent e9cb5427a754e3b47c3897d7a71168cbc6f549de
Author: Bradley Gannon <bradley@bradleygannon.com>
Date: Thu, 12 Feb 2026 21:02:02 -0500
Add basic KISS command handling
Diffstat:
| M | src/main.rs | | | 82 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
1 file changed, 73 insertions(+), 9 deletions(-)
diff --git a/src/main.rs b/src/main.rs
@@ -3,6 +3,7 @@
#![feature(abi_avr_interrupt)]
use core::cell::RefCell;
+use core::hint::spin_loop;
use arduino_hal::hal::usart::Event;
use arduino_hal::prelude::*;
@@ -28,12 +29,11 @@ static SINE_TABLE: [u8; 32] = [
1, 2, 4, 7, 9, 12,
];
-static SERIAL: Mutex<
- RefCell<Option<Usart<Periph<RegisterBlock, 192>, Pin<Input, PD0>, Pin<Output, PD1>>>>,
-> = Mutex::new(RefCell::new(None));
+type Usart0 = Usart<Periph<RegisterBlock, 192>, Pin<Input, PD0>, Pin<Output, PD1>>;
+static SERIAL: Mutex<RefCell<Option<Usart0>>> = Mutex::new(RefCell::new(None));
static MESSAGE: Mutex<RefCell<Vec<u8, 512>>> = Mutex::new(RefCell::new(Vec::new()));
-
+static KISS: Mutex<RefCell<KissState>> = Mutex::new(RefCell::new(KissState::Idle));
static SENDER: Mutex<RefCell<Sender>> = Mutex::new(RefCell::new(Sender {
counter: 0,
increment: 0,
@@ -51,6 +51,55 @@ const SPACE_INCREMENT: u16 = 3838;
const IDLE_DELAY: usize = 128;
+enum KissState {
+ Idle,
+ Fend { send: bool },
+ Command,
+ Data(u8),
+ Fesc,
+}
+
+impl KissState {
+ const FEND: u8 = 0xc0;
+ const FESC: u8 = 0xdb;
+ const TFEND: u8 = 0xdc;
+ const TFESC: u8 = 0xdd;
+ const COMMAND_DATA: u8 = 0x00;
+
+ fn update(&mut self, byte: u8) {
+ *self = match (&self, byte) {
+ // FEND after data means the frame is complete and ready to send
+ (KissState::Data(_), Self::FEND) => KissState::Fend { send: true },
+
+ // FEND anywhere else means the frame is incomplete and should not be sent, but a new
+ // frame is beginning
+ (_, Self::FEND) => KissState::Fend { send: false },
+
+ // Idle state waits for FEND
+ (KissState::Idle, _) => KissState::Idle,
+
+ // Command byte follows FEND
+ (KissState::Fend { .. }, Self::COMMAND_DATA) => KissState::Command,
+ (KissState::Fend { .. }, _) => KissState::Command,
+
+ // FESC can follow command or data
+ (KissState::Command, Self::FESC) => KissState::Fesc,
+ (KissState::Data(_), Self::FESC) => KissState::Fesc,
+
+ // Data follows command byte
+ (KissState::Command, b) => KissState::Data(b),
+
+ // Handle escaped bytes
+ (KissState::Fesc, Self::TFEND) => KissState::Data(Self::FEND),
+ (KissState::Fesc, Self::TFESC) => KissState::Data(Self::FESC),
+ (KissState::Fesc, b) => KissState::Data(b),
+
+ // Data follows data
+ (KissState::Data(_), b) => KissState::Data(b),
+ }
+ }
+}
+
enum SenderState {
Off,
Idle { index: usize },
@@ -165,10 +214,23 @@ fn USART_RX() {
interrupt::free(|cs| {
if let Some(ref mut serial) = SERIAL.borrow(cs).borrow_mut().as_mut() {
if let Ok(b) = serial.read() {
- if b == b'\n' {
- SENDER.borrow(cs).borrow_mut().state = SenderState::Idle { index: 0 };
- }
- let _ = MESSAGE.borrow(cs).borrow_mut().push(b);
+ let mut kiss_state = KISS.borrow(cs).borrow_mut();
+ kiss_state.update(b);
+ match *kiss_state {
+ KissState::Fend { send } if send => {
+ let mut sender = SENDER.borrow(cs).borrow_mut();
+ if let SenderState::Off = sender.state {
+ sender.state = SenderState::Idle { index: 0 };
+ }
+ }
+ KissState::Data(d) => {
+ let _ = MESSAGE.borrow(cs).borrow_mut().push(d);
+ }
+ KissState::Idle
+ | KissState::Command
+ | KissState::Fend { .. }
+ | KissState::Fesc => (),
+ };
}
}
});
@@ -210,5 +272,7 @@ fn main() -> ! {
unsafe { avr_device::interrupt::enable() };
- loop {}
+ loop {
+ spin_loop();
+ }
}