summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustav Sörnäs <gustav@sornas.net>2021-03-14 16:00:27 +0100
committerGustav Sörnäs <gustav@sornas.net>2021-03-14 16:00:27 +0100
commita3989ff74c6c37355c43a1e9ac6d94bb2138d9be (patch)
treec92d0c5ecf5315b1cbe1e32eaffb63cfbee3542b
parent36251ad76afbe22c78fabc2ff1186615aaef0662 (diff)
downloadserial-morse-a3989ff74c6c37355c43a1e9ac6d94bb2138d9be.tar.gz
ringbuf
-rw-r--r--src/main.rs104
1 files changed, 102 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs
index 9bea689..cc1623e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,6 +10,70 @@ const SHORT: u16 = 75;
const LONG: u16 = SHORT * 3;
const SPACE: u16 = SHORT * 7;
+struct RingBuf<T: Copy, const N: usize> {
+ data: [T; N],
+ read_idx: usize,
+ write_idx: usize,
+}
+
+impl<T: Copy, const N: usize> RingBuf<T, N> {
+ pub fn new(initial: T) -> Self {
+ Self {
+ data: [initial; N],
+ read_idx: 0,
+ write_idx: 0,
+ }
+ }
+
+ pub fn peek(&self) -> Option<T> {
+ 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<T> {
+ 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 ),* ) => {
{
@@ -24,6 +88,36 @@ macro_rules! morse {
};
}
+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<const N: usize>(buf: &mut RingBuf<LedInstruction, N>, 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<Output>, c: u8) {
let c = char::from_u32(c as u32);
if let Some(c) = c {
@@ -86,9 +180,15 @@ fn main() -> ! {
57600.into_baudrate(),
);
+ let mut buf: RingBuf<_, 100> = RingBuf::new(LedInstruction::new(false, 0));
+
loop {
- let b = nb::block!(serial.read()).void_unwrap();
+ // let b = nb::block!(serial.read()).void_unwrap();
+ match serial.read() {
+ Ok(b) => push_morse(&mut buf, b),
+ Err(_) => {},
+ }
- blink_morse(&mut led, b);
+ buf.update(millis());
}
}