#![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::(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::(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::(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(addr: u32, value: T) { write_volatile(addr as *mut T, value); } unsafe fn read_reg(addr: u32) -> T { return read_volatile(addr as *mut T); }