new-sonar/firmware/src/main.rs

171 lines
5.2 KiB
Rust

#![no_std]
#![no_main]
// TODO remove
#![allow(unused)]
extern crate panic_halt;
use core::fmt::Write;
use core::{
ptr::{read_volatile, write_volatile},
};
use embedded_hal::prelude::{_embedded_hal_blocking_i2c_Read, _embedded_hal_blocking_i2c_Write};
use mcp4726::Status;
use riscv_rt::entry;
use smoltcp::socket::{self, Socket};
use smoltcp::time::Duration;
use smoltcp::wire::{IpAddress, Ipv4Address};
use smoltcp::{
iface::{SocketSet, SocketStorage},
socket::tcp::Socket as TcpSocket,
socket::tcp::SocketBuffer,
time::Instant,
wire::HardwareAddress,
};
mod command_interface;
mod eth;
mod i2c;
mod logging;
mod mcp4726;
mod proto;
mod uart;
mod sampler;
mod timer;
use timer::millis;
const MAC: [u8; 6] = [0xA0, 0xBB, 0xCC, 0xDD, 0xEE, 0xF0];
// use `main` as the entry point of this application
// `main` is not allowed to return
#[entry]
fn main() -> ! {
//unsafe { eth::init(); }
//let blink_period = unsafe {
// if eth::is_wishbone_correct() {
// 10_000_000
// } else {
// 500_000
// }
//};
let blink_period = 10_000_000u32;
// enable timer
let mut device = unsafe { eth::LiteEthDevice::try_init(0xf000_0800, 0x8000_0000).unwrap() };
use smoltcp::wire::{EthernetAddress, HardwareAddress};
let mut config = smoltcp::iface::Config::default();
config.hardware_addr = Some(HardwareAddress::Ethernet(EthernetAddress::from_bytes(&MAC)));
let mut iface = smoltcp::iface::Interface::new(config, &mut device);
// Set address
iface.update_ip_addrs(|ip_addrs| {
ip_addrs
.push(smoltcp::wire::IpCidr::new(
IpAddress::Ipv4(Ipv4Address::new(192, 168, 88, 69)),
24,
))
.unwrap();
});
iface
.routes_mut()
.add_default_ipv4_route(Ipv4Address::new(192, 168, 88, 1))
.unwrap();
// Create socket set with 4 available
let mut socket_storage = [SocketStorage::EMPTY; 4];
let mut socket_set = SocketSet::new(&mut socket_storage[..]);
let mut tx_storage = [0u8; 64];
let mut rx_storage = [0u8; 64];
let mut tx_buf = SocketBuffer::new(&mut tx_storage[..]);
let mut rx_buf = SocketBuffer::new(&mut rx_storage[..]);
let mut command_socket = socket_set.add(TcpSocket::new(tx_buf, rx_buf));
// Set a keepalive on the socket to handle unexpected client disconnects
{
let mut sock = socket_set.get_mut::<TcpSocket>(command_socket);
// TODO these values are obscene, should fix the underlying bug
sock.set_keep_alive(Some(Duration::from_secs(2)));
sock.set_timeout(Some(Duration::from_secs(10)))
}
let mut data_tx_storage = [0u8; 256];
let mut data_rx_storage = [0u8; 24];
let mut data_tx_buf = SocketBuffer::new(&mut data_tx_storage[..]);
let mut data_rx_buf = SocketBuffer::new(&mut data_rx_storage[..]);
let mut data_socket = socket_set.add(TcpSocket::new(data_tx_buf, data_rx_buf));
{
let mut sock = socket_set.get_mut::<TcpSocket>(data_socket);
// TODO these values are obscene, should fix the underlying bug
sock.set_keep_alive(Some(Duration::from_secs(2)));
sock.set_timeout(Some(Duration::from_secs(10)))
}
let mut last_blink: u32 = 0;
let mut toggle = false;
//defmt::info!("Done setup");
// Set up timer for polling events
timer::init();
let mut cmd = command_interface::CommandInterface::new();
loop {
let now = millis();
iface.poll(Instant::from_millis(now), &mut device, &mut socket_set);
// TODO first connection to a socket takes a while to establish, and can time out, why?
cmd.run(socket_set.get_mut(command_socket));
// TODO the need for the second check screams something is unsound somewhere
if now - last_blink > 1000 && now > last_blink {
last_blink = now;
toggle = !toggle;
write_led(if toggle { 1 } else { 0 });
let mut sock = socket_set.get_mut::<TcpSocket>(data_socket);
if !sock.is_open() {
sock.listen(3000);
}
if toggle {
sampler::clear_buffers();
sampler::start_sampling();
let buf = unsafe {sampler::get_sample_buffer(0) };
let status = sampler::read_status();
let raw_reg: u32 = unsafe { read_reg(0x8040_0004) };
defmt::debug!("Start: len: {}, complete: {}, running: {}, status: {}", buf.len(), status.capture_complete, status.sampling, raw_reg);
} else {
sampler::stop_sampling();
let buf = unsafe {sampler::get_sample_buffer(0) };
defmt::debug!("Stopped, len: {}", buf.len());
}
}
// TODO I think the timer might actually stop until the event is cleared? this may pose
// problems, might explain why moving this above the smoltcp stuff "broke" things
timer::poll();
}
}
fn write_led(val: u32) {
unsafe {
write_reg(0xf000_2000, val);
}
}
unsafe fn write_reg<T>(addr: u32, value: T) {
write_volatile(addr as *mut T, value);
}
unsafe fn read_reg<T>(addr: u32) -> T {
return read_volatile(addr as *mut T);
}