Skip to content
Snippets Groups Projects
Commit 66e1bb44 authored by Stephen D's avatar Stephen D
Browse files

basic SPI working

parent 98cd6ac2
No related branches found
No related tags found
1 merge request!4Spi
...@@ -40,6 +40,7 @@ dependencies = [ ...@@ -40,6 +40,7 @@ dependencies = [
"crc", "crc",
"image", "image",
"kiss-tnc", "kiss-tnc",
"rppal",
"serde", "serde",
"serial", "serial",
"sha3", "sha3",
...@@ -687,6 +688,15 @@ dependencies = [ ...@@ -687,6 +688,15 @@ dependencies = [
"bitflags", "bitflags",
] ]
[[package]]
name = "rppal"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "612e1a22e21f08a246657c6433fe52b773ae43d07c9ef88ccfc433cc8683caba"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"
......
...@@ -23,10 +23,10 @@ bitvec = "1.0.1" ...@@ -23,10 +23,10 @@ bitvec = "1.0.1"
crc = "3.0.1" crc = "3.0.1"
image = "0.24.6" image = "0.24.6"
kiss-tnc = "0.2.2" kiss-tnc = "0.2.2"
rppal = "0.14.1"
serde = { version = "1.0.160", features = ["derive"] } serde = { version = "1.0.160", features = ["derive"] }
serial = "0.4.0" serial = "0.4.0"
sha3 = "0.10.7" sha3 = "0.10.7"
subprocess = "0.2.9" subprocess = "0.2.9"
tokio = { version = "1.27.0", features = ["full"] } tokio = { version = "1.27.0", features = ["full"] }
toml = "0.7.3" toml = "0.7.3"
...@@ -11,7 +11,7 @@ use crate::{ ...@@ -11,7 +11,7 @@ use crate::{
config::Config, config::Config,
img::ImgManager, img::ImgManager,
packet::{FecPacket, Packet}, packet::{FecPacket, Packet},
radio::UartRadio, radio::McuRadio,
ssdv::ssdv_encode, ssdv::ssdv_encode,
}; };
...@@ -93,7 +93,7 @@ impl Controller { ...@@ -93,7 +93,7 @@ impl Controller {
telem_rx: Receiver<Packet>, telem_rx: Receiver<Packet>,
) { ) {
let mut radio = loop { let mut radio = loop {
let r = UartRadio::new(&uart); let r = McuRadio::new(&uart);
match r { match r {
Ok(r) => break r, Ok(r) => break r,
...@@ -122,6 +122,9 @@ impl Controller { ...@@ -122,6 +122,9 @@ impl Controller {
eprintln!("Could not send packet: {}", e); eprintln!("Could not send packet: {}", e);
} }
} else { } else {
if let Err(e) = radio.flush() {
eprintln!("Could not flush radio: {}", e);
}
thread::sleep(Duration::from_millis(50)); thread::sleep(Duration::from_millis(50));
} }
......
...@@ -23,16 +23,13 @@ impl Packet { ...@@ -23,16 +23,13 @@ impl Packet {
.iter() .iter()
.chain(b": ".iter()) .chain(b": ".iter())
.chain(msg.as_bytes().iter()); .chain(msg.as_bytes().iter());
let mut len = 0;
for (i, b) in iter.enumerate().take(TEXT_MESSAGE_LEN) { for (i, b) in iter.enumerate().take(TEXT_MESSAGE_LEN) {
out[i] = *b; out[i] = *b;
len += 1;
} }
let len = msg let len = len.min(TEXT_MESSAGE_LEN).try_into().unwrap();
.as_bytes()
.len()
.min(TEXT_MESSAGE_LEN)
.try_into()
.unwrap();
Self::TextMessage(len, out) Self::TextMessage(len, out)
} }
......
use serial::{unix::TTYPort, BaudRate::BaudOther, SerialPort}; use rppal::spi::{Bus, Mode, SlaveSelect, Spi};
use std::{ use std::{thread::sleep, time::Duration};
io::{self, Read, Write},
thread::sleep,
time::Duration,
};
use crate::packet::FecPacket; use crate::packet::FecPacket;
...@@ -11,44 +7,44 @@ const BUFFER_STATUS_CMD: u8 = 0x00; ...@@ -11,44 +7,44 @@ const BUFFER_STATUS_CMD: u8 = 0x00;
const SEND_PACKET_CMD: u8 = 0x01; const SEND_PACKET_CMD: u8 = 0x01;
const GET_TEMP_CMD: u8 = 0x02; const GET_TEMP_CMD: u8 = 0x02;
const SYNC_CMD: u8 = 0x03; const SYNC_CMD: u8 = 0x03;
const NOP_CMD: u8 = 0x55;
const PACKET_SPACE: u8 = 0x02; const PACKET_SPACE: u8 = 0x02;
// Used for talking to an RF4463 via a microcontroller // Used for talking to an RF4463 via a microcontroller
// The microcontroller takes in packet data over UART and sends it to the RF4463 // The microcontroller takes in packet data over SPI and sends it to the RF4463
pub struct UartRadio { pub struct McuRadio {
uart: TTYPort, spi: Spi,
} }
impl UartRadio { // TODO reset mcu on initialization
impl McuRadio {
pub fn new(uart: &str) -> anyhow::Result<Self> { pub fn new(uart: &str) -> anyhow::Result<Self> {
let mut uart = serial::open(uart)?; let spi = Spi::new(Bus::Spi0, SlaveSelect::Ss1, 1_000_000, Mode::Mode0)?;
uart.reconfigure(&|settings| settings.set_baud_rate(BaudOther(921_600)))?;
Ok(Self { uart }) Ok(Self { spi })
} }
pub fn send_packet(&mut self, packet: &FecPacket) -> anyhow::Result<()> { pub fn send_packet(&mut self, packet: &FecPacket) -> anyhow::Result<()> {
self.uart.write_all(&[SEND_PACKET_CMD])?; // wait until we have packet space
self.uart.write_all(&packet.0)?; let mut buf = [0];
self.spi.transfer(&mut buf, &[NOP_CMD])?;
let mut buf = [0; 1];
self.uart.read_exact(&mut buf)?;
// wait until we have space for packets
while buf != [PACKET_SPACE] { while buf != [PACKET_SPACE] {
sleep(Duration::from_millis(10)); sleep(Duration::from_millis(10));
// poll to see if the buffer has emptied yet self.spi.transfer(&mut buf, &[NOP_CMD])?;
self.uart.write_all(&[BUFFER_STATUS_CMD])?;
self.uart.read_exact(&mut buf)?;
} }
self.spi.write(&[SEND_PACKET_CMD])?;
self.spi.write(&packet.0)?;
Ok(()) Ok(())
} }
pub fn get_temp(&mut self) -> anyhow::Result<f32> { pub fn get_temp(&mut self) -> anyhow::Result<f32> {
// todo need to figure this out
/*
self.uart.write_all(&[GET_TEMP_CMD])?; self.uart.write_all(&[GET_TEMP_CMD])?;
let mut buf = [0; 4]; let mut buf = [0; 4];
...@@ -56,46 +52,62 @@ impl UartRadio { ...@@ -56,46 +52,62 @@ impl UartRadio {
let temp = f32::from_le_bytes(buf); let temp = f32::from_le_bytes(buf);
Ok(temp) Ok(temp) */
Ok(12.34)
} }
pub fn sync(&mut self) -> anyhow::Result<()> { pub fn sync(&mut self) -> anyhow::Result<()> {
// clear any pending packets // todo need to figure this out
let mut tries = 0;
let mut buf = [0; 100]; /*
loop {
match self.uart.read(&mut buf) { // clear any pending packets
Ok(0) => break, let mut tries = 0;
Ok(_) => { let mut buf = [0; 100];
tries += 1; loop {
} match self.uart.read(&mut buf) {
Err(e) if matches!(e.kind(), io::ErrorKind::TimedOut) => break, Ok(0) => break,
Err(e) => { Ok(_) => {
return Err(e.into()); 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})"); }
} }
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; Ok(())
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"); // 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(()) Ok(())
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment