#![no_std] #![no_main] extern crate alloc; use esp_backtrace as _; use embedded_hal::serial::Read; use hal::{clock::ClockControl, i2c::I2C, peripherals::Peripherals, prelude::*}; use hal::{ ledc::{ channel::{self, ChannelIFace}, timer::{self, TimerIFace}, HighSpeed, LEDC, }, uart, Uart, /*Delay*/ IO, }; use si5351::{Si5351, Si5351Device}; #[entry] fn main() -> ! { let peripherals = Peripherals::take(); //let uart = peripherals.UART0; let mut system = peripherals.DPORT.split(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let clocks = ClockControl::max(system.clock_control).freeze(); //let mut delay = Delay::new(&clocks); let serial = { uart::Uart::new(peripherals.UART0, &mut system.peripheral_clock_control) }; // setup logger // To change the log_level change the env section in .cargo/config.toml // or remove it and set ESP_LOGLEVEL manually before running cargo run // this requires a clean rebuild because of https://github.com/rust-lang/cargo/issues/10358 esp_println::logger::init_logger_from_env(); log::info!("Logger is setup"); //println!("Hello world!"); let i2c = I2C::new( peripherals.I2C0, io.pins.gpio21, io.pins.gpio22, 100u32.kHz(), &mut system.peripheral_clock_control, &clocks, ); log::info!("I2C Initialized"); //i2c.write(0b0110_0000, &[0x64]); let mut clock = Si5351Device::new_adafruit_module(i2c); match clock.init_adafruit_module() { Ok(_) => { log::info!("Si5351 Initialized succesfully"); main_loop(clock, serial); } Err(e) => { match e { si5351::Error::InvalidParameter => { log::warn!("Could not initialize Si5351; Using LedC PWM") } si5351::Error::CommunicationError => { log::info!("Could not find Si5351 device; Using LedC PWM") } } let ledc = LEDC::new( peripherals.LEDC, &clocks, &mut system.peripheral_clock_control, ); let led = io.pins.gpio4.into_push_pull_output(); let mut hstimer0 = ledc.get_timer::(timer::Number::Timer0); hstimer0 .configure(timer::config::Config { duty: timer::config::Duty::Duty5Bit, clock_source: timer::HSClockSource::APBClk, frequency: 1u32.MHz(), }) .unwrap(); let mut channel0 = ledc.get_channel(channel::Number::Channel0, led); channel0 .configure(channel::config::Config { timer: &hstimer0, duty_pct: 50, pin_config: channel::config::PinConfig::PushPull, }) .unwrap(); main_loop(ledc, serial); } } } fn main_loop(mut clock: T, mut serial: Uart<'_, U>) -> ! { loop { let freq = read_freq(&mut serial); log::info!("Got Freq: {}", freq); match clock.set_freq(freq) { Ok(_) => log::info!("Set frequency to {}", freq), Err(_) => log::warn!("Could not set frequency to {}", freq), } } } trait Clockable { fn set_freq(&mut self, freq: u32) -> Result<(), ()>; } impl Clockable for LEDC<'_> { fn set_freq(&mut self, freq: u32) -> Result<(), ()> { let mut hstimer0 = self.get_timer::(timer::Number::Timer0); let res = hstimer0.configure(timer::config::Config { duty: timer::config::Duty::Duty5Bit, clock_source: timer::HSClockSource::APBClk, frequency: freq.Hz(), }); match res { Ok(_) => Ok(()), Err(_) => Err(()), } } } impl Clockable for Si5351Device where Si5351Device: Si5351, { fn set_freq(&mut self, freq: u32) -> Result<(), ()> { match self.set_frequency(si5351::PLL::A, si5351::ClockOutput::Clk0, freq) { Ok(_) => Ok(()), Err(_) => Err(()), } } } struct Dummy; impl Clockable for Dummy { fn set_freq(&mut self, freq: u32) -> Result<(), ()> { log::info!("Dummy set freq: {}", freq); Ok(()) } } // bool inval = false; // char c = serial.read(); // for (;;) { // int freq = 0; // for (;(c >= '0' && c <= '9') || c == '.' || c == ',' || c == '_'; c = serial.read()) // if (c >= '0' && c <= '9') freq = (freq * 10) + (c - '0'); // if (c == 'G' || c=='M' || c=='K') freq = freq * mult(c) // c = serial.read() // for ( ; c != '\n' or '\r'; c = serial.read()) // if (!inval && c != ' ' or '\t') inval = true; // if !inval && freq > 0 {break;} // } // return freq; // fn rf>(serial: &mut T) -> u32 { 0 } fn read_freq(serial: &mut Uart<'_, T>) -> u32 { let mut freq = 0; let mut invalid = false; loop { match nb::block!(serial.read()) { Ok(input) if input >= b'0' && input <= b'9' => { log::debug!("Got char: {}", char::from(input)); freq = (freq * 10) + (input - b'0') as u32; } Ok(input) if invalid && (input == b'\n' || input == b'\r') => { log::debug!("Got bad end: {}", char::from(input)); freq = 0; invalid = false; } Ok(input) if !invalid && (input == b'\n' || input == b'\r') => { log::debug!("Got end: {}", char::from(input)); break; } Ok(input) if input == b'.' || input == b',' || input == b'_' => { log::debug!("Got ignor: {}", char::from(input)); continue; } Ok(input) => { log::debug!("Got inval: {}", char::from(input)); invalid = true; } Err(e) => { log::debug!("Got error: {:?}", e); } } } freq }