commit ae808e41dd0ef79ede4e04690c15a9c4272edc03
parent 5976f6e92cf330e5597cf07913f70786bdeaabee
Author: Bradley Gannon <bradley@bradleygannon.com>
Date: Wed, 11 Feb 2026 17:21:27 -0500
Refine sender state logic and generalize to multi-byte messages
Diffstat:
| M | src/main.rs | | | 122 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
1 file changed, 85 insertions(+), 37 deletions(-)
diff --git a/src/main.rs b/src/main.rs
@@ -17,15 +17,13 @@ static SINE_TABLE: [u8; 32] = [
1, 2, 4, 7, 9, 12,
];
-// ASCII letter B with three idle bits, one start bit, eight data bits, and one stop bit (8N1)
-static MESSAGE: [bool; 13] = [
- true, true, true, false, false, true, false, false, false, false, true, false, true,
-];
+static MESSAGE: [u8; 16] = *b"Bradley Gannon\r\n";
static SENDER: Mutex<RefCell<Sender>> = Mutex::new(RefCell::new(Sender {
counter: 0,
increment: 0,
- message_index: 0,
+ byte_index: 0,
+ state: SenderState::Idle { index: 0 },
dac_0: None,
dac_1: None,
dac_2: None,
@@ -36,10 +34,21 @@ static SENDER: Mutex<RefCell<Sender>> = Mutex::new(RefCell::new(Sender {
const MARK_INCREMENT: u16 = 2100;
const SPACE_INCREMENT: u16 = 3838;
+const IDLE_DELAY: usize = 128;
+
+enum SenderState {
+ Off,
+ Idle { index: usize },
+ Start,
+ Data { bit_index: usize },
+ Stop { end_message: bool },
+}
+
struct Sender {
counter: u16,
increment: u16,
- message_index: usize,
+ byte_index: usize,
+ state: SenderState,
dac_0: Option<Pin<Output, PD2>>,
dac_1: Option<Pin<Output, PD3>>,
dac_2: Option<Pin<Output, PD4>>,
@@ -47,6 +56,59 @@ struct Sender {
dac_4: Option<Pin<Output, PD6>>,
}
+impl Sender {
+ fn update(&mut self) {
+ match self.state {
+ SenderState::Off => (),
+ SenderState::Idle { ref mut index } => {
+ if *index >= IDLE_DELAY {
+ self.state = SenderState::Start;
+ } else {
+ *index += 1;
+ }
+ }
+ SenderState::Start => {
+ self.state = SenderState::Data { bit_index: 0 };
+ }
+ SenderState::Data { ref mut bit_index } => {
+ *bit_index += 1;
+ if *bit_index >= 8 {
+ self.byte_index += 1;
+ self.state = SenderState::Stop {
+ end_message: self.byte_index >= MESSAGE.len(),
+ };
+ }
+ }
+ SenderState::Stop { end_message } => {
+ if end_message {
+ self.state = SenderState::Idle { index: 0 };
+ self.byte_index = 0;
+ } else {
+ self.state = SenderState::Start;
+ }
+ }
+ }
+ self.increment = match self.state {
+ SenderState::Off => 0,
+ SenderState::Idle { .. } => MARK_INCREMENT,
+ SenderState::Start => SPACE_INCREMENT,
+ SenderState::Data { bit_index } => {
+ if let Some(&byte) = MESSAGE.get(self.byte_index) {
+ let bit = ((byte >> bit_index) & 1) != 0;
+ if bit {
+ MARK_INCREMENT
+ } else {
+ SPACE_INCREMENT
+ }
+ } else {
+ 0
+ }
+ }
+ SenderState::Stop { .. } => MARK_INCREMENT,
+ };
+ }
+}
+
#[avr_device::interrupt(atmega328p)]
fn TIMER0_COMPA() {
interrupt::free(|cs| {
@@ -54,31 +116,21 @@ fn TIMER0_COMPA() {
sender.counter = sender.counter.wrapping_add(sender.increment);
let sine_index = ((sender.counter >> 11) as usize).clamp(0, SINE_TABLE.len());
if let Some(sine_value) = SINE_TABLE.get(sine_index) {
- let _ = sender
- .dac_0
- .as_mut()
- .unwrap()
- .set_state((sine_value & 0b10000 != 0).into());
- let _ = sender
- .dac_1
- .as_mut()
- .unwrap()
- .set_state((sine_value & 0b01000 != 0).into());
- let _ = sender
- .dac_2
- .as_mut()
- .unwrap()
- .set_state((sine_value & 0b00100 != 0).into());
- let _ = sender
- .dac_3
- .as_mut()
- .unwrap()
- .set_state((sine_value & 0b00010 != 0).into());
- let _ = sender
- .dac_4
- .as_mut()
- .unwrap()
- .set_state((sine_value & 0b00001 != 0).into());
+ if let Some(ref mut dac_0) = sender.dac_0 {
+ let _ = dac_0.set_state((sine_value & 0b10000 != 0).into());
+ };
+ if let Some(ref mut dac_1) = sender.dac_1 {
+ let _ = dac_1.set_state((sine_value & 0b01000 != 0).into());
+ };
+ if let Some(ref mut dac_2) = sender.dac_2 {
+ let _ = dac_2.set_state((sine_value & 0b00100 != 0).into());
+ };
+ if let Some(ref mut dac_3) = sender.dac_3 {
+ let _ = dac_3.set_state((sine_value & 0b00010 != 0).into());
+ };
+ if let Some(ref mut dac_4) = sender.dac_4 {
+ let _ = dac_4.set_state((sine_value & 0b00001 != 0).into());
+ };
}
});
}
@@ -87,11 +139,7 @@ fn TIMER0_COMPA() {
fn TIMER1_COMPA() {
interrupt::free(|cs| {
let mut sender = SENDER.borrow(cs).borrow_mut();
- match MESSAGE.get(sender.message_index).unwrap() {
- true => sender.increment = MARK_INCREMENT,
- false => sender.increment = SPACE_INCREMENT,
- }
- sender.message_index = (sender.message_index + 1) % MESSAGE.len();
+ sender.update();
});
}
@@ -126,7 +174,7 @@ fn main() -> ! {
.write(|w| w.wgm1().set(0b01).cs1().direct());
// this should theoretically be 13_333 cycles, but in practice we have to go a little faster to
// account for overhead; this value seems to work well
- symbol_timer.ocr1a().write(|w| w.set(12_750));
+ symbol_timer.ocr1a().write(|w| w.set(13_250));
symbol_timer.timsk1().write(|w| w.ocie1a().set_bit());
loop {}