From 66e1bb44e733e0cced3eaeed535bef796504c10b Mon Sep 17 00:00:00 2001
From: Stephen D <webmaster@scd31.com>
Date: Sat, 8 Jul 2023 15:28:57 -0300
Subject: [PATCH] basic SPI working

---
 Cargo.lock     |  10 ++++
 Cargo.toml     |   2 +-
 src/control.rs |   7 ++-
 src/packet.rs  |   9 ++--
 src/radio.rs   | 130 +++++++++++++++++++++++++++----------------------
 5 files changed, 90 insertions(+), 68 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 350ec80..96fec44 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -40,6 +40,7 @@ dependencies = [
  "crc",
  "image",
  "kiss-tnc",
+ "rppal",
  "serde",
  "serial",
  "sha3",
@@ -687,6 +688,15 @@ dependencies = [
  "bitflags",
 ]
 
+[[package]]
+name = "rppal"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "612e1a22e21f08a246657c6433fe52b773ae43d07c9ef88ccfc433cc8683caba"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
diff --git a/Cargo.toml b/Cargo.toml
index a78d03c..6783760 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,10 +23,10 @@ bitvec = "1.0.1"
 crc = "3.0.1"
 image = "0.24.6"
 kiss-tnc = "0.2.2"
+rppal = "0.14.1"
 serde = { version = "1.0.160", features = ["derive"] }
 serial = "0.4.0"
 sha3 = "0.10.7"
 subprocess = "0.2.9"
 tokio = { version = "1.27.0", features = ["full"] }
 toml = "0.7.3"
-
diff --git a/src/control.rs b/src/control.rs
index 761d59f..e48b27e 100644
--- a/src/control.rs
+++ b/src/control.rs
@@ -11,7 +11,7 @@ use crate::{
     config::Config,
     img::ImgManager,
     packet::{FecPacket, Packet},
-    radio::UartRadio,
+    radio::McuRadio,
     ssdv::ssdv_encode,
 };
 
@@ -93,7 +93,7 @@ impl Controller {
         telem_rx: Receiver<Packet>,
     ) {
         let mut radio = loop {
-            let r = UartRadio::new(&uart);
+            let r = McuRadio::new(&uart);
 
             match r {
                 Ok(r) => break r,
@@ -122,6 +122,9 @@ impl Controller {
                     eprintln!("Could not send packet: {}", e);
                 }
             } else {
+                if let Err(e) = radio.flush() {
+                    eprintln!("Could not flush radio: {}", e);
+                }
                 thread::sleep(Duration::from_millis(50));
             }
 
diff --git a/src/packet.rs b/src/packet.rs
index 8bd7b63..1d52ce6 100644
--- a/src/packet.rs
+++ b/src/packet.rs
@@ -23,16 +23,13 @@ impl Packet {
             .iter()
             .chain(b": ".iter())
             .chain(msg.as_bytes().iter());
+        let mut len = 0;
         for (i, b) in iter.enumerate().take(TEXT_MESSAGE_LEN) {
             out[i] = *b;
+            len += 1;
         }
 
-        let len = msg
-            .as_bytes()
-            .len()
-            .min(TEXT_MESSAGE_LEN)
-            .try_into()
-            .unwrap();
+        let len = len.min(TEXT_MESSAGE_LEN).try_into().unwrap();
 
         Self::TextMessage(len, out)
     }
diff --git a/src/radio.rs b/src/radio.rs
index 8c33842..9da61cc 100644
--- a/src/radio.rs
+++ b/src/radio.rs
@@ -1,9 +1,5 @@
-use serial::{unix::TTYPort, BaudRate::BaudOther, SerialPort};
-use std::{
-    io::{self, Read, Write},
-    thread::sleep,
-    time::Duration,
-};
+use rppal::spi::{Bus, Mode, SlaveSelect, Spi};
+use std::{thread::sleep, time::Duration};
 
 use crate::packet::FecPacket;
 
@@ -11,44 +7,44 @@ const BUFFER_STATUS_CMD: u8 = 0x00;
 const SEND_PACKET_CMD: u8 = 0x01;
 const GET_TEMP_CMD: u8 = 0x02;
 const SYNC_CMD: u8 = 0x03;
+const NOP_CMD: u8 = 0x55;
 
 const PACKET_SPACE: u8 = 0x02;
 
 // Used for talking to an RF4463 via a microcontroller
-// The microcontroller takes in packet data over UART and sends it to the RF4463
-pub struct UartRadio {
-    uart: TTYPort,
+// The microcontroller takes in packet data over SPI and sends it to the RF4463
+pub struct McuRadio {
+    spi: Spi,
 }
 
-impl UartRadio {
+// TODO reset mcu on initialization
+impl McuRadio {
     pub fn new(uart: &str) -> anyhow::Result<Self> {
-        let mut uart = serial::open(uart)?;
-        uart.reconfigure(&|settings| settings.set_baud_rate(BaudOther(921_600)))?;
+        let spi = Spi::new(Bus::Spi0, SlaveSelect::Ss1, 1_000_000, Mode::Mode0)?;
 
-        Ok(Self { uart })
+        Ok(Self { spi })
     }
 
     pub fn send_packet(&mut self, packet: &FecPacket) -> anyhow::Result<()> {
-        self.uart.write_all(&[SEND_PACKET_CMD])?;
-        self.uart.write_all(&packet.0)?;
-
-        let mut buf = [0; 1];
-        self.uart.read_exact(&mut buf)?;
-
-        // wait until we have space for packets
+        // wait until we have packet space
+        let mut buf = [0];
+        self.spi.transfer(&mut buf, &[NOP_CMD])?;
         while buf != [PACKET_SPACE] {
             sleep(Duration::from_millis(10));
 
-            // poll to see if the buffer has emptied yet
-            self.uart.write_all(&[BUFFER_STATUS_CMD])?;
-
-            self.uart.read_exact(&mut buf)?;
+            self.spi.transfer(&mut buf, &[NOP_CMD])?;
         }
 
+        self.spi.write(&[SEND_PACKET_CMD])?;
+        self.spi.write(&packet.0)?;
+
         Ok(())
     }
 
     pub fn get_temp(&mut self) -> anyhow::Result<f32> {
+        // todo need to figure this out
+
+        /*
         self.uart.write_all(&[GET_TEMP_CMD])?;
 
         let mut buf = [0; 4];
@@ -56,46 +52,62 @@ impl UartRadio {
 
         let temp = f32::from_le_bytes(buf);
 
-        Ok(temp)
+        Ok(temp) */
+
+        Ok(12.34)
     }
 
     pub fn sync(&mut self) -> anyhow::Result<()> {
-        // clear any pending packets
-        let mut tries = 0;
-        let mut buf = [0; 100];
-        loop {
-            match self.uart.read(&mut buf) {
-                Ok(0) => break,
-                Ok(_) => {
-                    tries += 1;
-                }
-                Err(e) if matches!(e.kind(), io::ErrorKind::TimedOut) => break,
-                Err(e) => {
-                    return Err(e.into());
-                }
-            }
-        }
-
-        if tries > 0 {
-            eprintln!("[WARN] Sync had pending packets(tries={tries})");
-        }
+        // todo need to figure this out
+
+        /*
+
+           // clear any pending packets
+           let mut tries = 0;
+           let mut buf = [0; 100];
+           loop {
+               match self.uart.read(&mut buf) {
+                   Ok(0) => break,
+                   Ok(_) => {
+                       tries += 1;
+                   }
+                   Err(e) if matches!(e.kind(), io::ErrorKind::TimedOut) => break,
+                   Err(e) => {
+                       return Err(e.into());
+                   }
+               }
+           }
+
+           if tries > 0 {
+               eprintln!("[WARN] Sync had pending packets(tries={tries})");
+           }
+
+           tries = 0;
+           let mut buf = [0; 10];
+           loop {
+               self.uart.write_all(&[SYNC_CMD; 10])?;
+               match self.uart.read_exact(&mut buf) {
+                   Ok(()) => break,
+                   Err(e) if matches!(e.kind(), io::ErrorKind::TimedOut) => {
+                       tries += 1;
+                   }
+                   Err(e) => {
+                       return Err(e.into());
+                   }
+               }
+           }
+
+           eprintln!("Synced in {tries} tries");
+
+           Ok(())
+        */
 
-        tries = 0;
-        let mut buf = [0; 10];
-        loop {
-            self.uart.write_all(&[SYNC_CMD; 10])?;
-            match self.uart.read_exact(&mut buf) {
-                Ok(()) => break,
-                Err(e) if matches!(e.kind(), io::ErrorKind::TimedOut) => {
-                    tries += 1;
-                }
-                Err(e) => {
-                    return Err(e.into());
-                }
-            }
-        }
+        Ok(())
+    }
 
-        eprintln!("Synced in {tries} tries");
+    // sends a bunch of nops over SPI to clear out its DMA buffer
+    pub fn flush(&mut self) -> anyhow::Result<()> {
+        self.spi.write(&[NOP_CMD; 256])?;
 
         Ok(())
     }
-- 
GitLab