diff options
Diffstat (limited to 'sw/picardy/src/main.rs')
-rw-r--r-- | sw/picardy/src/main.rs | 144 |
1 files changed, 109 insertions, 35 deletions
diff --git a/sw/picardy/src/main.rs b/sw/picardy/src/main.rs index b1bcf0f..071f4e9 100644 --- a/sw/picardy/src/main.rs +++ b/sw/picardy/src/main.rs @@ -35,10 +35,13 @@ use stm32f1xx_hal::{ i2c, gpio, delay::Delay, - timer::{Timer}, + timer::{Timer, Event}, + qei::QeiOptions, }; -use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin}; +use stm32f1xx_hal::stm32::{/*NVIC, Interrupt,*/ interrupt}; + +use embedded_hal::digital::v2::{OutputPin}; use hd44780_driver::{Cursor, CursorBlink, Display, DisplayMode, HD44780}; pub mod ui; @@ -50,15 +53,45 @@ enum Mode { VFO, BFO, } + +enum TuneSpeed { + Slow, + Mid, + Fast +} + struct State { mode : Mode, bfo : u32, bfo_tune_fail : bool, - vfo : u32, + qrg : u32, + tune_speed : TuneSpeed, transmit : bool, } +impl State { + fn vfo(&self) -> u32 { + self.qrg - self.bfo + } + + fn vfo_incr(&self) -> i32 { + match self.tune_speed { + TuneSpeed::Slow => 10, + TuneSpeed::Mid => 200, + TuneSpeed::Fast => 1000, + } + } + + fn bfo_incr(&self) -> i32 { + match self.tune_speed { + TuneSpeed::Slow => 10, + TuneSpeed::Mid => 50, + TuneSpeed::Fast => 100, + } + } +} + fn update_disp<T: hd44780_driver::bus::DataBus>(lcd: &mut HD44780<T>, state: &State, delay: &mut Delay) { let mut string = arrayvec::ArrayString::<[_; 16]>::new(); @@ -82,9 +115,16 @@ fn update_disp<T: hd44780_driver::bus::DataBus>(lcd: &mut HD44780<T>, state: &St string.clear(); match state.mode { - Mode::BFO => write!(string, " {:<10}", state.vfo).unwrap(), - Mode::VFO => write!(string, ">{:<10}", state.vfo).unwrap(), + Mode::BFO => write!(string, " {:<10}", state.qrg).unwrap(), + Mode::VFO => write!(string, ">{:<10}", state.qrg).unwrap(), + } + + match state.tune_speed { + TuneSpeed::Slow => write!(string, "S").unwrap(), + TuneSpeed::Mid => write!(string, "M").unwrap(), + TuneSpeed::Fast => write!(string, "F").unwrap(), } + lcd.set_cursor_pos(40, delay).unwrap(); lcd.write_str(&string, delay).unwrap(); } @@ -93,9 +133,10 @@ fn update_disp<T: hd44780_driver::bus::DataBus>(lcd: &mut HD44780<T>, state: &St fn main() -> ! { let mut state = State { mode : Mode::VFO, - bfo : 4_195_210, + bfo : 4_916_550, bfo_tune_fail : false, - vfo : 23_000_000, + qrg : 28_000_000, + tune_speed : TuneSpeed::Mid, transmit : false, }; @@ -115,13 +156,15 @@ fn main() -> ! { let mut gpioc = dp.GPIOC.split(&mut rcc.apb2); // Buttons as analog inputs (multi-level) + let mic_sw1 = gpioa.pa3.into_analog(&mut gpioa.crl); + let mic_sw2 = gpioa.pa4.into_analog(&mut gpioa.crl); let pb0 = gpiob.pb0.into_analog(&mut gpiob.crl); let pb1 = gpiob.pb1.into_analog(&mut gpiob.crl); let pb12 = gpiob.pb12.into_pull_up_input(&mut gpiob.crh); let pb13 = gpiob.pb13.into_pull_up_input(&mut gpiob.crh); let pc15 = gpioc.pc15.into_pull_up_input(&mut gpioc.crh); let adc1 = dp.ADC1; - let mut ui = ui::UI::new(pb0, pb1, adc1, &mut rcc.apb2, &clocks, pb12, pb13, pc15); + let mut ui = ui::UI::new(mic_sw1, mic_sw2, pb0, pb1, adc1, &mut rcc.apb2, &clocks, pb12, pb13, pc15); // Configure PB14 as output. (LED) @@ -134,11 +177,14 @@ fn main() -> ! { let mut _seq1 = pb4.into_push_pull_output_with_state(&mut gpiob.crl, gpio::State::Low); let mut _seq2 = gpiob.pb5.into_push_pull_output_with_state(&mut gpiob.crl, gpio::State::Low); + let mut mute_spkr = gpioa.pa2.into_push_pull_output_with_state(&mut gpioa.crl, gpio::State::Low); + let mut mute_micn = gpioa.pa1.into_push_pull_output_with_state(&mut gpioa.crl, gpio::State::Low); + let c1 = gpioa.pa6; let c2 = gpioa.pa7; let qei = Timer::tim3(dp.TIM3, &clocks, &mut rcc.apb1) - .qei((c1, c2), &mut afio.mapr); + .qei((c1, c2), &mut afio.mapr, QeiOptions::default()); // Configure I2C2 for display let scl2 = gpiob.pb10.into_alternate_open_drain(&mut gpiob.crh); @@ -159,10 +205,10 @@ fn main() -> ! { /* data_timeout_us */ 1000, ); - let i2c2_busmanager = shared_bus::CortexMBusManager::new(i2c2); + let i2c2_busmanager = shared_bus::BusManagerSimple::new(i2c2); const I2C_ADDRESS: u8 = 0b010_0000; // MCP23008, depending on solder bridges - let mut lcd = match HD44780::new_i2c_mcp23008(i2c2_busmanager.acquire(), I2C_ADDRESS, &mut delay) { + let mut lcd = match HD44780::new_i2c_mcp23008(i2c2_busmanager.acquire_i2c(), I2C_ADDRESS, &mut delay) { Ok(lcd) => lcd, Err(_) => panic!("HD44780 init fail"), }; @@ -198,16 +244,21 @@ fn main() -> ! { /* addr_timeout_us */ 1000, /* data_timeout_us */ 1000, ); - let i2c_busmanager = shared_bus::CortexMBusManager::new(i2c); + let i2c_busmanager = shared_bus::BusManagerSimple::new(i2c); - let mut siclock = si_clock::SiClock::new(i2c_busmanager.acquire(), state.bfo, state.vfo); + let mut siclock = si_clock::SiClock::new(i2c_busmanager.acquire_i2c(), state.bfo, state.vfo()); update_disp(&mut lcd, &state, &mut delay); let mut last_encoder_count = qei.count(); - loop { - led.toggle().unwrap(); + let mut timer1 = Timer::tim1(dp.TIM1, &clocks, &mut rcc.apb2) + .start_count_down(40.hz()); + timer1.listen(Event::Update); + + //unsafe { NVIC::unmask(Interrupt::TIM1_UP); } + + loop { let mut update_disp_required = false; let encoder_count = qei.count(); @@ -217,49 +268,72 @@ fn main() -> ! { match state.mode { Mode::VFO => { - state.vfo = (state.vfo as i32 + delta * 500) as u32; - siclock.set_vfo(state.vfo); + state.qrg = (state.qrg as i32 + delta * state.vfo_incr()) as u32; }, Mode::BFO => { - state.bfo = (state.bfo as i32 + delta * 50) as u32; + state.bfo = (state.bfo as i32 + delta * state.bfo_incr()) as u32; state.bfo_tune_fail = !siclock.set_bfo(state.bfo).is_ok(); }, } + siclock.set_vfo(state.vfo()); + update_disp_required = true; } - if let Some(b) = ui.read_buttons() { - match b { - ui::ButtonPress::A => { state.mode = Mode::BFO; }, - ui::ButtonPress::B => { state.mode = Mode::VFO; }, - ui::ButtonPress::C => {}, - ui::ButtonPress::D => {}, - ui::ButtonPress::E => { - state.transmit = false; + let button_state = ui.read_buttons(); - seq0n.set_high().unwrap(); - }, - ui::ButtonPress::F => { - state.transmit = true; + if button_state.a { + state.mode = Mode::BFO; + update_disp_required = true; + } + else if button_state.b { + state.mode = Mode::VFO; + update_disp_required = true; + } - seq0n.set_low().unwrap(); - }, - ui::ButtonPress::G => {}, - ui::ButtonPress::ENC => {}, + if button_state.g { + state.tune_speed = match state.tune_speed { + TuneSpeed::Slow => TuneSpeed::Mid, + TuneSpeed::Mid => TuneSpeed::Fast, + TuneSpeed::Fast => TuneSpeed::Slow, }; - update_disp_required = true; } + let ptt = false; //ui.read_ptt(); + update_disp_required |= state.transmit != ptt; + state.transmit = ptt; + + if state.transmit { + mute_spkr.set_high().unwrap(); + mute_micn.set_high().unwrap(); + seq0n.set_low().unwrap(); + led.set_high().unwrap(); + } + else { + mute_spkr.set_low().unwrap(); + mute_micn.set_low().unwrap(); + seq0n.set_high().unwrap(); + led.set_low().unwrap(); + } + if update_disp_required { update_disp(&mut lcd, &state, &mut delay) }; last_encoder_count = encoder_count; + + delay.delay_ms(20u8); + + //cortex_m::asm::wfi(); } } +#[interrupt] +fn TIM1_UP() { +} + #[cortex_m_rt::exception] fn HardFault(ef: &ExceptionFrame) -> ! { let periph = unsafe { cortex_m::Peripherals::steal() }; |