From e17cc27cbb58ce91c7cb659d9ad000bc7510aff8 Mon Sep 17 00:00:00 2001 From: occheung Date: Thu, 24 Sep 2020 17:32:53 +0800 Subject: [PATCH] main: functioning --- examples/mqtt_client.rs | 3 +- src/attenuator.rs | 2 +- src/config_register.rs | 2 +- src/cpld.rs | 2 +- src/dds.rs | 2 +- src/lib.rs | 300 ----------------------------------- src/main.rs | 335 ++++++++++++++++++++++++---------------- src/mqtt_mux.rs | 6 +- src/spi_slave.rs | 2 +- 9 files changed, 216 insertions(+), 438 deletions(-) delete mode 100644 src/lib.rs diff --git a/examples/mqtt_client.rs b/examples/mqtt_client.rs index ab2557d..038ab67 100644 --- a/examples/mqtt_client.rs +++ b/examples/mqtt_client.rs @@ -222,9 +222,10 @@ fn main() -> ! { client.network_stack.update(time); } + // Process MQTT messages about Urukul/Control let connection = client .poll(|_client, topic, message, _properties| { - info!("On '{:?}', received: {:?}", topic, message); + info!("On {:?}, received: {:?}", topic, message); // Why is topic a string while message is a slice? mqtt_mux.process_mqtt(topic, message); }).is_ok(); diff --git a/src/attenuator.rs b/src/attenuator.rs index 266303e..9350bc0 100644 --- a/src/attenuator.rs +++ b/src/attenuator.rs @@ -1,7 +1,7 @@ use embedded_hal::blocking::spi::Transfer; use core::assert; -use crate::Error; +use crate::urukul::Error; pub struct Attenuator { spi: SPI, diff --git a/src/config_register.rs b/src/config_register.rs index 324fb3e..d6ff0f4 100644 --- a/src/config_register.rs +++ b/src/config_register.rs @@ -1,5 +1,5 @@ use embedded_hal::blocking::spi::Transfer; -use crate::Error; +use crate::urukul::Error; use core::mem::size_of; // Bitmasks for CFG diff --git a/src/cpld.rs b/src/cpld.rs index 2a19124..8fe4f9c 100644 --- a/src/cpld.rs +++ b/src/cpld.rs @@ -1,4 +1,4 @@ -use crate::Error; +use crate::urukul::Error; use crate::spi_slave::Parts; use embedded_hal::{ diff --git a/src/dds.rs b/src/dds.rs index 6414ecb..9a27ce6 100644 --- a/src/dds.rs +++ b/src/dds.rs @@ -1,5 +1,5 @@ use embedded_hal::blocking::spi::Transfer; -use crate::Error; +use crate::urukul::Error; use core::mem::size_of; use core::convert::TryInto; use heapless::Vec; diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index dd6db45..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,300 +0,0 @@ -#![no_std] -#![feature(str_strip)] -extern crate embedded_hal; -use embedded_hal::{ - blocking::spi::Transfer, -}; - -#[macro_use] -pub mod bitmask_macro; -pub mod spi_slave; -pub mod cpld; - -pub mod config_register; -use crate::config_register::ConfigRegister; -use crate::config_register::CFGMask; -use crate::config_register::StatusMask; - -pub mod attenuator; -use crate::attenuator::Attenuator; - -pub mod dds; -use crate::dds::DDS; - -// pub mod scpi; -// pub mod translation; -pub mod nal_tcp_client; -pub mod flash; - -pub mod mqtt_mux; - -/* - * Enum for structuring error - */ -#[derive(Debug)] -pub enum Error { - SPI(E), - CSError, - GetRefMutDataError, - AttenuatorError, - IOUpdateError, - DDSError, - ConfigRegisterError, - DDSCLKError, - DDSRAMError, - ParameterError, - MqttTopicError, - MqttCommandError, -} - -#[derive(Debug, Clone)] -pub enum ClockSource { - OSC, - SMA, - MMCX, -} - -/* - * Struct for Urukul master device - */ -pub struct Urukul { - config_register: ConfigRegister, - attenuator: Attenuator, - dds: [DDS; 4], - f_master_clk: f64, -} - -impl Urukul -where - SPI: Transfer, -{ - /* - * Master constructor for the entire Urukul device - * Supply 7 SPI channels to Urukul and 4 reference clock frequencies - */ - pub fn new(spi1: SPI, spi2: SPI, spi3: SPI, spi4: SPI, spi5: SPI, spi6: SPI, spi7: SPI) -> Self { - // Construct Urukul - Urukul { - config_register: ConfigRegister::new(spi1), - attenuator: Attenuator::new(spi2), - // Create 4 DDS instances with fixed 25MHz clock - // Counter-intuitive to assign urukul clock before having a urukul - dds: [ - DDS::new(spi4, 25_000_000.0), - DDS::new(spi5, 25_000_000.0), - DDS::new(spi6, 25_000_000.0), - DDS::new(spi7, 25_000_000.0), - ], - // Default clock selection: OSC, fixed 100MHz speed - f_master_clk: 100_000_000.0, - } - } - - /* - * Reset method. To be invoked by initialization and manual reset. - * Only Urukul struct provides reset method. - * DDS reset is controlled by Urukul (RST). - * Attenuators only have shift register reset, which does not affect its data - * CPLD only has a "all-zero" default state. - */ - pub fn reset(&mut self) -> Result<(), Error> { - // Reset DDS and attenuators - self.config_register.set_configurations(&mut [ - (CFGMask::RST, 1), - (CFGMask::IO_RST, 1), - (CFGMask::IO_UPDATE, 0) - ])?; - // Set 0 to all fields on configuration register. - self.config_register.set_configurations(&mut [ - (CFGMask::RF_SW, 0), - (CFGMask::LED, 0), - (CFGMask::PROFILE, 0), - (CFGMask::IO_UPDATE, 0), - (CFGMask::MASK_NU, 0), - (CFGMask::CLK_SEL0, 0), - (CFGMask::SYNC_SEL, 0), - (CFGMask::RST, 0), - (CFGMask::IO_RST, 0), - (CFGMask::CLK_SEL1, 0), - (CFGMask::DIV, 0), - ])?; - // Init all DDS chips. Configure SDIO as input only. - for chip_no in 0..4 { - self.dds[chip_no].init()?; - } - // Clock tree reset. OSC clock source by default - self.f_master_clk = 100_000_000.0; - // CPLD divides clock frequency by 4 by default. - for chip_no in 0..4 { - self.dds[chip_no].set_ref_clk_frequency(self.f_master_clk / 4.0)?; - } - Ok(()) - } - - /* - * Test method fo Urukul. - * Return the number of test failed. - */ - pub fn test(&mut self) -> Result> { - let mut count = self.config_register.test()?; - count += self.attenuator.test()?; - for chip_no in 0..4 { - count += self.dds[chip_no].test()?; - } - Ok(count) - } -} - -impl Urukul -where - SPI: Transfer -{ - - fn get_channel_switch_status(&mut self, channel: u32) -> Result> { - if channel < 4 { - self.config_register.get_status(StatusMask::RF_SW).map(|val| (val & (1 << channel)) != 0) - } else { - Err(Error::ParameterError) - } - } - - fn set_channel_switch(&mut self, channel: u32, status: bool) -> Result<(), Error> { - if channel < 4 { - let prev = u32::from(self.config_register.get_status(StatusMask::RF_SW)?); - let next = { - if status { - prev | (1 << channel) - } else { - prev & (!(1 << channel)) - } - }; - self.config_register.set_configurations(&mut [ - (CFGMask::RF_SW, next), - ]).map(|_| ()) - } else { - Err(Error::ParameterError) - } - } - - fn set_clock(&mut self, source: ClockSource, frequency: f64, division: u8) -> Result<(), Error> { - // Change clock source through configuration register - self.set_clock_source(source)?; - - // Modify the master clock frequency - // Prevent redundunt call to change f_ref_clk - self.f_master_clk = frequency; - - self.set_clock_division(division) - } - - fn set_clock_source(&mut self, source: ClockSource) -> Result<(), Error> { - // Change clock source through configuration register - match source { - ClockSource::OSC => self.config_register.set_configurations(&mut [ - (CFGMask::CLK_SEL0, 0), - (CFGMask::CLK_SEL1, 0), - ]), - ClockSource::MMCX => self.config_register.set_configurations(&mut [ - (CFGMask::CLK_SEL0, 0), - (CFGMask::CLK_SEL1, 1), - ]), - ClockSource::SMA => self.config_register.set_configurations(&mut [ - (CFGMask::CLK_SEL0, 1), - ]), - }.map(|_| ()) - } - - fn set_clock_frequency(&mut self, frequency: f64) -> Result<(), Error> { - // Update master clock frequency - self.f_master_clk = frequency; - - // Update all DDS f_ref_clk - self.set_dds_ref_clk() - } - - fn set_clock_division(&mut self, division: u8) -> Result<(), Error> { - match division { - 1 => self.config_register.set_configurations(&mut [ - (CFGMask::DIV, 1), - ]), - 2 => self.config_register.set_configurations(&mut [ - (CFGMask::DIV, 2), - ]), - 4 => self.config_register.set_configurations(&mut [ - (CFGMask::DIV, 3), - ]), - _ => Err(Error::ParameterError), - }?; - - self.set_dds_ref_clk() - } - - fn set_dds_ref_clk(&mut self) -> Result<(), Error> { - // Calculate reference clock frequency after clock division from configuration register - let f_ref_clk = self.f_master_clk / (self.get_master_clock_division() as f64); - - // Update all DDS chips on reference clock frequency - for dds_channel in 0..4 { - self.dds[dds_channel].set_ref_clk_frequency(f_ref_clk)?; - } - Ok(()) - } - - fn get_master_clock_division(&mut self) -> u8 { - match self.config_register.get_configuration(CFGMask::DIV) { - 0 | 3 => 4, - 1 => 1, - 2 => 2, - _ => panic!("Divisor out of range, when reading configuration register (CPLD)."), - } - } - - fn set_channel_attenuation(&mut self, channel: u8, attenuation: f32) -> Result<(), Error> { - if channel >= 4 || attenuation < 0.0 || attenuation > 31.5 { - return Err(Error::ParameterError); - } - self.attenuator.set_channel_attenuation(channel, attenuation) - } - - fn set_profile(&mut self, profile: u8) -> Result<(), Error> { - if profile >= 8 { - return Err(Error::ParameterError); - } - self.config_register.set_configurations(&mut [ - (CFGMask::PROFILE, profile.into()) - ]).map(|_| ()) - } - - fn set_channel_single_tone_profile(&mut self, channel: u8, profile: u8, frequency: f64, phase: f64, amplitude: f64) -> Result<(), Error> { - if channel >= 4 || profile >= 8 || frequency < 0.0 || phase >= 360.0 || - phase < 0.0 || amplitude < 0.0 || amplitude > 1.0 { - return Err(Error::ParameterError); - } - self.dds[usize::from(channel)].set_single_tone_profile(profile, frequency, phase, amplitude) - } - - fn set_channel_single_tone_profile_frequency(&mut self, channel: u8, profile: u8, frequency: f64)-> Result<(), Error> { - if channel >= 4 || profile >= 8 || frequency < 0.0 { - return Err(Error::ParameterError); - } - self.dds[usize::from(channel)].set_single_tone_profile_frequency(profile, frequency) - } - - fn set_channel_single_tone_profile_phase(&mut self, channel: u8, profile: u8, phase: f64)-> Result<(), Error> { - if channel >= 4 || profile >= 8 || phase >= 360.0 || phase < 0.0 { - return Err(Error::ParameterError); - } - self.dds[usize::from(channel)].set_single_tone_profile_phase(profile, phase) - } - - fn set_channel_single_tone_profile_amplitude(&mut self, channel: u8, profile: u8, amplitude: f64)-> Result<(), Error> { - if channel >= 4 || profile >= 8 || amplitude < 0.0 || amplitude > 1.0 { - return Err(Error::ParameterError); - } - self.dds[usize::from(channel)].set_single_tone_profile_amplitude(profile, amplitude) - } - - fn set_channel_sys_clk(&mut self, channel: u8, f_sys_clk: f64) -> Result<(), Error> { - self.dds[usize::from(channel)].set_sys_clk_frequency(f_sys_clk) - } -} diff --git a/src/main.rs b/src/main.rs index 76be76f..2f96fad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,46 +1,89 @@ #![no_main] #![no_std] - -#[macro_use] -extern crate log; - -use log::{trace, debug, info, warn}; - -use stm32h7xx_hal::hal::digital::v2::{ - InputPin, - OutputPin, -}; +#![feature(str_strip)] +use log::{ trace, debug, info, warn }; +use stm32h7xx_hal::hal::digital::v2::InputPin; +use stm32h7xx_hal::gpio::Speed; use stm32h7xx_hal::{pac, prelude::*, spi}; +use stm32h7xx_hal::ethernet; + +use smoltcp as net; +use minimq::{ + embedded_nal::{IpAddr, Ipv4Addr, TcpStack}, + MqttClient, QoS +}; use cortex_m; use cortex_m_rt::entry; +use rtic::cyccnt::{Instant, U32Ext}; -use firmware; -use firmware::{ - attenuator::Attenuator, - config_register::{ - ConfigRegister, - CFGMask, - StatusMask, - }, - dds::{ - DDS, - DDSCFRMask, - }, - cpld::{ - CPLD, - } -}; +use heapless::Vec; +use heapless::consts; + +#[macro_use] +pub mod bitmask_macro; +pub mod spi_slave; +pub mod cpld; +use crate::cpld::CPLD; +pub mod config_register; +pub mod attenuator; +pub mod dds; +pub mod nal_tcp_client; +use crate::nal_tcp_client::{ NetStorage, NetworkStack }; +pub mod flash; +use crate::flash::flash_ice40_fpga; +pub mod mqtt_mux; +use crate::mqtt_mux::MqttMux; +pub mod urukul; +use crate::urukul::Urukul; #[path = "../examples/util/logger.rs"] mod logger; +static mut NET_STORE: NetStorage = NetStorage { + // Placeholder for the real IP address, which is initialized at runtime. + ip_addrs: [net::wire::IpCidr::Ipv6( + net::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX, + )], + neighbor_cache: [None; 8], + routes_cache: [None; 8], +}; + +#[link_section = ".sram3.eth"] +static mut DES_RING: ethernet::DesRing = ethernet::DesRing::new(); + +macro_rules! add_socket { + ($sockets:ident, $tx_storage:ident, $rx_storage:ident) => { + let mut $rx_storage = [0; 4096]; + let mut $tx_storage = [0; 4096]; + + let tcp_socket = { + let tx_buffer = net::socket::TcpSocketBuffer::new(&mut $tx_storage[..]); + let rx_buffer = net::socket::TcpSocketBuffer::new(&mut $rx_storage[..]); + + net::socket::TcpSocket::new(tx_buffer, rx_buffer) + }; + + let _handle = $sockets.add(tcp_socket); + }; +} + #[entry] fn main() -> ! { let mut cp = cortex_m::Peripherals::take().unwrap(); let dp = pac::Peripherals::take().unwrap(); + cp.DWT.enable_cycle_counter(); + + // Enable SRAM3 for the descriptor ring. + dp.RCC.ahb2enr.modify(|_, w| w.sram3en().set_bit()); + // Reset RCC clock + dp.RCC.rsr.write(|w| w.rmvf().set_bit()); + + cp.SCB.invalidate_icache(); + cp.SCB.enable_icache(); + let pwr = dp.PWR.constrain(); let vos = pwr.freeze(); @@ -48,6 +91,7 @@ fn main() -> ! { let ccdr = rcc .use_hse(8.mhz()) .sys_ck(400.mhz()) + .hclk(200.mhz()) .pll1_q_ck(48.mhz()) .pll1_r_ck(400.mhz()) .freeze(vos, &dp.SYSCFG); @@ -65,29 +109,88 @@ fn main() -> ! { let gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD); let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE); let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF); + let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG); - // Setup CDONE for checking + trace!("Flashing configuration bitstream to iCE40 HX8K on Humpback."); + delay.delay_ms(1000_u16); + + // Using SPI_1 alternate functions (af5) + let fpga_sck = gpiob.pb3.into_alternate_af5(); + let fpga_sdo = gpiob.pb4.into_alternate_af5(); + let fpga_sdi = gpiob.pb5.into_alternate_af5(); + + // Setup SPI_SS_B and CRESET_B + let fpga_ss = gpioa.pa4.into_push_pull_output(); + let fpga_creset = gpiof.pf3.into_open_drain_output(); + + // Setup CDONE let fpga_cdone = gpiod.pd15.into_pull_up_input(); - match fpga_cdone.is_high() { - Ok(true) => info!("FPGA is ready."), - Ok(_) => info!("FPGA is in reset state."), - Err(_) => info!("Error: Cannot read C_DONE"), - }; + // Setup SPI interface + let fpga_cfg_spi = dp.SPI1.spi( + (fpga_sck, fpga_sdo, fpga_sdi), + spi::MODE_3, + 12.mhz(), + ccdr.peripheral.SPI1, + &ccdr.clocks, + ); + + flash_ice40_fpga(fpga_cfg_spi, fpga_ss, fpga_creset, fpga_cdone, delay).unwrap(); + + // Configure ethernet IO + { + let _rmii_refclk = gpioa.pa1.into_alternate_af11().set_speed(Speed::VeryHigh); + let _rmii_mdio = gpioa.pa2.into_alternate_af11().set_speed(Speed::VeryHigh); + let _rmii_mdc = gpioc.pc1.into_alternate_af11().set_speed(Speed::VeryHigh); + let _rmii_crs_dv = gpioa.pa7.into_alternate_af11().set_speed(Speed::VeryHigh); + let _rmii_rxd0 = gpioc.pc4.into_alternate_af11().set_speed(Speed::VeryHigh); + let _rmii_rxd1 = gpioc.pc5.into_alternate_af11().set_speed(Speed::VeryHigh); + let _rmii_tx_en = gpiog.pg11.into_alternate_af11().set_speed(Speed::VeryHigh); + let _rmii_txd0 = gpiog.pg13.into_alternate_af11().set_speed(Speed::VeryHigh); + let _rmii_txd1 = gpiob.pb13.into_alternate_af11().set_speed(Speed::VeryHigh); + } + + // Configure ethernet + let mac_addr = net::wire::EthernetAddress([0xAC, 0x6F, 0x7A, 0xDE, 0xD6, 0xC8]); + let (eth_dma, mut eth_mac) = unsafe { + ethernet::new_unchecked( + dp.ETHERNET_MAC, + dp.ETHERNET_MTL, + dp.ETHERNET_DMA, + &mut DES_RING, + mac_addr.clone(), + ) + }; + + unsafe { ethernet::enable_interrupt() } + + let store = unsafe { &mut NET_STORE }; + + store.ip_addrs[0] = net::wire::IpCidr::new(net::wire::IpAddress::v4(192, 168, 1, 200), 24); + + let neighbor_cache = net::iface::NeighborCache::new(&mut store.neighbor_cache[..]); + + let mut routes = net::iface::Routes::new(&mut store.routes_cache[..]); + let default_v4_gw = net::wire::Ipv4Address::new(192, 168, 1, 1); + routes.add_default_ipv4_route(default_v4_gw).unwrap(); + + let mut net_interface = net::iface::EthernetInterfaceBuilder::new(eth_dma) + .ethernet_addr(mac_addr) + .neighbor_cache(neighbor_cache) + .ip_addrs(&mut store.ip_addrs[..]) + .routes(routes) + .finalize(); /* - * Using SPI1, AF5 - * SCLK -> PA5 - * MOSI -> PB5 - * MISO -> PA6 + * Using SPI6 + * SCLK -> PA5 (af8) + * MOSI -> PG14 (af5) + * MISO -> PA6 (af8) * CS -> 0: PB12, 1: PA15, 2: PC7 */ - - let sclk = gpioa.pa5.into_alternate_af5(); - let mosi = gpiob.pb5.into_alternate_af5(); - let miso = gpioa.pa6.into_alternate_af5(); - - + let sclk = gpioa.pa5.into_alternate_af8().set_speed(Speed::VeryHigh); + let mosi = gpiog.pg14.into_alternate_af5().set_speed(Speed::VeryHigh); + let miso = gpioa.pa6.into_alternate_af8().set_speed(Speed::VeryHigh); let (cs0, cs1, cs2) = ( gpiob.pb12.into_push_pull_output(), gpioa.pa15.into_push_pull_output(), @@ -99,112 +202,86 @@ fn main() -> ! { */ let io_update = gpiob.pb15.into_push_pull_output(); - let spi = dp.SPI1.spi( + let spi = dp.SPI6.spi( (sclk, miso, mosi), spi::MODE_0, - 3.mhz(), - ccdr.peripheral.SPI1, + 2.mhz(), + ccdr.peripheral.SPI6, &ccdr.clocks, ); let switch = CPLD::new(spi, (cs0, cs1, cs2), io_update); let parts = switch.split(); - let mut config = ConfigRegister::new(parts.spi1); - let mut att = Attenuator::new(parts.spi2); - let mut dds0 = DDS::new(parts.spi4, 25_000_000.0); + let mut urukul = Urukul::new( + parts.spi1, parts.spi2, parts.spi3, parts.spi4, parts.spi5, parts.spi6, parts.spi7 + ); - // Reset all DDS, set CLK_SEL to 0 - config.set_configurations(&mut [ - (CFGMask::RST, 1), - (CFGMask::IO_RST, 1), - (CFGMask::IO_UPDATE, 0) - ]).unwrap(); + urukul.reset().unwrap(); + info!("Test value: {}", urukul.test().unwrap()); - config.set_configurations(&mut [ - (CFGMask::IO_RST, 0), - (CFGMask::RST, 0), - (CFGMask::RF_SW, 13), - (CFGMask::DIV, 3) - ]).unwrap(); + let mut mqtt_mux = MqttMux::new(urukul); - dds0.init().unwrap(); + // Time unit in ms + let mut time: u32 = 0; - dds0.set_configurations(&mut [ - (DDSCFRMask::PDCLK_ENABLE, 0), - (DDSCFRMask::READ_EFFECTIVE_FTW, 1), - ]).unwrap(); + // Cycle counter for 1 ms + // This effectively provides a conversion from rtic unit to ms + let mut next_ms = Instant::now(); + next_ms += 400_000.cycles(); - dds0.set_sys_clk_frequency(1_000_000_000.0).unwrap(); + let mut socket_set_entries: [_; 8] = Default::default(); + let mut sockets = net::socket::SocketSet::new(&mut socket_set_entries[..]); + add_socket!(sockets, rx_storage, tx_storage); - // Attenuator - att.set_attenuation([ - 5.0, 31.5, 24.0, 0.0 - ]).unwrap(); + let tcp_stack = NetworkStack::new(&mut net_interface, sockets); - dds0.set_single_tone_profile(1, 10_000_000.0, 0.0, 0.5).unwrap(); - config.set_configurations(&mut [ - (CFGMask::PROFILE, 1), - ]).unwrap(); + // Case dealt: Ethernet connection break down, neither side has timeout + // Limitation: Timeout inequality will cause TCP socket state to desync + // Probably fixed in latest smoltcp commit + let mut client = MqttClient::::new( + IpAddr::V4(Ipv4Addr::new(192, 168, 1, 125)), + "Nucleo", + tcp_stack, + ) + .unwrap(); - // // Setup RAM configuration - // dds0.set_configurations(&mut [ - // (DDSCFRMask::RAM_ENABLE, 1), - // (DDSCFRMask::RAM_PLAYBACK_DST, 2), - // ]).unwrap(); + let mut tick = false; + let mut has_subscribed = false; - // // Configure RAM profile 0 - // dds0.write_register(0x0E, &mut [ - // 0x00, // Open - // 0x09, 0xC4, // Address step rate (2500) - // 0xFF, 0xC0, // End at address 1023 - // 0x00, 0x00, // Start at address 0 - // 0x04, // Recirculate mode - // ]).unwrap(); + loop { + // Update time accumulator in ms + // Tick once every ms + if Instant::now() > next_ms { + tick = true; + time += 1; + next_ms += 400_000.cycles(); + } - // debug!("{:#X?}", dds0.read_register(0x0E, &mut[ - // 0x00, 0x00, 0x00, 0x00, - // 0x00, 0x00, 0x00, 0x00, - // ]).unwrap()); + // eth Poll if necessary + // Do not poll if eth link is down + if tick && client.network_stack.update_delay(time) == 0 && eth_mac.phy_poll_link() { + client.network_stack.update(time); + } - // // Choose profile 0 - // config.set_configurations(&mut [ - // (CFGMask::PROFILE, 0), - // ]).unwrap(); + // Process MQTT messages about Urukul/Control + let connection = client + .poll(|_client, topic, message, _properties| { + info!("On {:?}, received: {:?}", topic, message); + // Why is topic a string while message is a slice? + mqtt_mux.process_mqtt(topic, message); + }).is_ok(); + + if connection && !has_subscribed && tick { + match client.subscribe("Urukul/Control/#", &[]) { + Ok(()) => has_subscribed = true, + Err(minimq::Error::NotReady) => {}, + e => warn!("{:?}", e), + }; + } - // // Set RAM to be amplitudes, disable RAM momentarily - // dds0.set_configurations(&mut [ - // (DDSCFRMask::RAM_PLAYBACK_DST, 0), - // (DDSCFRMask::RAM_ENABLE, 0), - // ]).unwrap(); - - // let mut ram_data: [u8; ((1024 * 4) + 1)] = [0; (1024 * 4) + 1]; - // ram_data[0] = 0x16; - // for index in 0..1024 { - // if index % 2 == 1 { - // ram_data[(index * 4) + 1] = 0x3F; - // ram_data[(index * 4) + 2] = 0xFF; - // } else { - // ram_data[(index * 4) + 1] = 0x00; - // ram_data[(index * 4) + 2] = 0x00; - // } - // // ram_data[(index * 4) + 1] = ((index >> 2) & 0xFF) as u8; - // // ram_data[(index * 4) + 2] = ((index & 0x03) << 6) as u8; - // } - // dds0.transfer(&mut ram_data).unwrap(); - - // config.set_configurations(&mut [ - // (CFGMask::PROFILE, 1), - // ]).unwrap(); - - // config.set_configurations(&mut [ - // (CFGMask::PROFILE, 0), - // ]).unwrap(); - - // dds0.set_configurations(&mut [ - // (DDSCFRMask::RAM_ENABLE, 1), - // ]).unwrap(); - - loop {} + // Reset tick flag + tick = false; + } } diff --git a/src/mqtt_mux.rs b/src/mqtt_mux.rs index 8b08171..ff36a75 100644 --- a/src/mqtt_mux.rs +++ b/src/mqtt_mux.rs @@ -10,9 +10,9 @@ use nom::number::complete::{float, double}; use embedded_hal::blocking::spi::Transfer; use core::convert::TryInto; -use crate::ClockSource as UrukulClockSource; -use crate::Urukul; -use crate::Error; +use crate::urukul::ClockSource as UrukulClockSource; +use crate::urukul::Urukul; +use crate::urukul::Error; #[derive(Debug, Clone)] pub enum MqttTopic { diff --git a/src/spi_slave.rs b/src/spi_slave.rs index ddeef0b..03d5627 100644 --- a/src/spi_slave.rs +++ b/src/spi_slave.rs @@ -3,7 +3,7 @@ use embedded_hal::{ digital::v2::OutputPin, }; use crate::cpld::CPLD; -use crate::Error; +use crate::urukul::Error; pub struct SPISlave<'a, SPI, CS0, CS1, CS2, GPIO> ( // SPI device to be multiplexed