From 93220f99a52dc93f9a2d5b11074f60156ef70210 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sat, 13 Jun 2020 18:38:31 +0200 Subject: Get LCD and Si5351 I2C to work --- sw/demo1/src/main.rs | 134 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 10 deletions(-) (limited to 'sw/demo1/src/main.rs') diff --git a/sw/demo1/src/main.rs b/sw/demo1/src/main.rs index 80e38b9..4f8ce6e 100644 --- a/sw/demo1/src/main.rs +++ b/sw/demo1/src/main.rs @@ -8,13 +8,15 @@ use panic_semihosting as _; use stm32f1xx_hal::{ prelude::*, pac, - timer::Timer, + i2c::{BlockingI2c, Mode}, + delay::Delay, }; use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin}; +use hd44780_driver::{Cursor, CursorBlink, Display, DisplayMode, HD44780}; +use si5351::{Si5351, Si5351Device}; use core::fmt::Write; -use nb::block; fn print(step: usize) -> Result<(), core::fmt::Error> { let mut stdout = match hio::hstdout() { @@ -37,7 +39,9 @@ fn main() -> ! { let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); + let mut afio = dp.AFIO.constrain(&mut rcc.apb2); let clocks = rcc.cfgr.freeze(&mut flash.acr); + let mut delay = Delay::new(cp.SYST, clocks); let mut gpiob = dp.GPIOB.split(&mut rcc.apb2); @@ -45,28 +49,138 @@ fn main() -> ! { let mut led = gpiob.pb14.into_push_pull_output(&mut gpiob.crh); led.set_low().unwrap(); - let mut timer = Timer::syst(cp.SYST, &clocks).start_count_down(1.hz()); + // Configure I2C1 to be used for Si5351 and display + let scl = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl); + let sda = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl); + + let i2c = BlockingI2c::i2c1( + dp.I2C1, + (scl, sda), + &mut afio.mapr, + Mode::Standard { + frequency: 100_000.hz(), + }, + clocks, + &mut rcc.apb1, + /* start_timeout_us */ 1000, + /* start_retries */ 10, + /* addr_timeout_us */ 1000, + /* data_timeout_us */ 1000, + ); + + let i2c_busmanager = shared_bus::CortexMBusManager::new(i2c); + + /* + // Configure I2C2 + let scl2 = gpiob.pb10.into_alternate_open_drain(&mut gpiob.crh); + let sda2 = gpiob.pb11.into_alternate_open_drain(&mut gpiob.crh); + + let i2c2 = BlockingI2c::i2c2( + dp.I2C2, + (scl2, sda2), + Mode::Fast { + frequency: 400_000.hz(), + duty_cycle: DutyCycle::Ratio2to1, + }, + clocks, + &mut rcc.apb1, + /* start_timeout_us */ 1000, + /* start_retries */ 10, + /* addr_timeout_us */ 1000, + /* data_timeout_us */ 1000, + ); + */ + + const I2C_ADDRESS: u8 = 0b010_0000; // MCP23008, depending on solder bridges + let mut lcd = match HD44780::new_i2c_mcp23008(i2c_busmanager.acquire(), I2C_ADDRESS, &mut delay) { + Ok(lcd) => lcd, + Err(_) => panic!("HD44780 init fail"), + }; + + lcd.reset(&mut delay).unwrap(); + lcd.clear(&mut delay).unwrap(); + lcd.set_display_mode( + DisplayMode { + display: Display::On, + cursor_visibility: Cursor::Invisible, + cursor_blink: CursorBlink::Off, + }, + &mut delay).unwrap(); + lcd.set_cursor_pos(0, &mut delay).unwrap(); + lcd.write_str("Hello, world!", &mut delay).unwrap(); + + let ref_clock = 25_000_000; + let mut siclock = Si5351Device::new(i2c_busmanager.acquire(), false, ref_clock); + siclock.init(si5351::CrystalLoad::_10).unwrap(); + siclock.set_frequency(si5351::PLL::B, si5351::ClockOutput::Clk0, 28_000_000 + 4_915_200).unwrap(); + siclock.set_frequency(si5351::PLL::A, si5351::ClockOutput::Clk1, 144_000_000 + 28_000_000).unwrap(); + siclock.set_frequency(si5351::PLL::A, si5351::ClockOutput::Clk2, 4_915_100).unwrap(); + + lcd.set_cursor_pos(0, &mut delay).unwrap(); + lcd.write_str("Clocks set. ", &mut delay).unwrap(); let mut step = 0; print(step).unwrap(); loop { - for _ in 0..5 { - led.toggle().unwrap(); - block!(timer.wait()).ok(); - } + led.toggle().unwrap(); + delay.delay_ms(600u32); + + lcd.set_cursor_pos(40, &mut delay).unwrap(); + let mut string = arrayvec::ArrayString::<[_; 16]>::new(); + write!(string, "Step {} ", step).unwrap(); + lcd.write_str(&string, &mut delay).unwrap(); - print(step).unwrap(); step += 1; } } #[cortex_m_rt::exception] fn HardFault(ef: &ExceptionFrame) -> ! { - panic!("HardFault at {:#?}", ef); + let periph = unsafe { cortex_m::Peripherals::steal() }; + let hfsr = periph.SCB.hfsr.read(); + let cfsr = periph.SCB.cfsr.read(); + + let mut stdout = match hio::hstdout() { + Ok(fd) => fd, + Err(()) => panic!("no stdout"), + }; + + let _ = write!(stdout, "Hardfault {:x} {:x} at {:x}\n", hfsr, cfsr, ef.pc); + cortex_m::asm::bkpt(); + loop { } } #[cortex_m_rt::exception] fn DefaultHandler(irqn: i16) { - panic!("Unhandled exception (IRQn = {})", irqn); + let mut stdout = match hio::hstdout() { + Ok(fd) => fd, + Err(()) => panic!("no stdout"), + }; + + let _ = write!(stdout, "Unhandled exception (IRQn = {})", irqn); + cortex_m::asm::bkpt(); + loop { } } + + + + /* code to discover i2c device address + let mut stdout = hio::hstdout().unwrap(); + + loop { + for addr in 0..127usize { + let bytes = [0u8; 1]; + let mut buffer = [0u8; 1]; + match i2c.write_read(addr as u8, &bytes, &mut buffer) { + Ok(()) => { + write!(stdout, "{}: {}\n", addr, buffer[0]).unwrap(); + }, + Err(_) => { + write!(stdout, "{}: fail\n", addr).unwrap(); + }, + } + } + } + */ + -- cgit v1.2.3