diff options
Diffstat (limited to 'sw')
-rw-r--r-- | sw/picardy/src/main.rs | 146 | ||||
-rw-r--r-- | sw/picardy/src/si_clock.rs | 32 | ||||
-rw-r--r-- | sw/pio.txt | 7 |
3 files changed, 136 insertions, 49 deletions
diff --git a/sw/picardy/src/main.rs b/sw/picardy/src/main.rs index 71c8475..b1bcf0f 100644 --- a/sw/picardy/src/main.rs +++ b/sw/picardy/src/main.rs @@ -32,7 +32,8 @@ use panic_semihosting as _; use stm32f1xx_hal::{ prelude::*, pac, - i2c::{BlockingI2c, Mode, DutyCycle}, + i2c, + gpio, delay::Delay, timer::{Timer}, }; @@ -45,8 +46,59 @@ pub mod si_clock; use core::fmt::Write; +enum Mode { + VFO, + BFO, +} +struct State { + mode : Mode, + bfo : u32, + bfo_tune_fail : bool, + vfo : u32, + + transmit : bool, +} + +fn update_disp<T: hd44780_driver::bus::DataBus>(lcd: &mut HD44780<T>, state: &State, delay: &mut Delay) +{ + let mut string = arrayvec::ArrayString::<[_; 16]>::new(); + + match (state.bfo_tune_fail, &state.mode) { + (true, _) => write!(string, "!").unwrap(), + (false, Mode::BFO) => write!(string, ">").unwrap(), + (false, Mode::VFO) => write!(string, " ").unwrap(), + } + write!(string, "{:<10}", state.bfo).unwrap(); + + if state.transmit { + write!(string, " T").unwrap(); + } + else { + write!(string, " R").unwrap(); + } + + lcd.set_cursor_pos(0, delay).unwrap(); + lcd.write_str(&string, delay).unwrap(); + + string.clear(); + match state.mode { + Mode::BFO => write!(string, " {:<10}", state.vfo).unwrap(), + Mode::VFO => write!(string, ">{:<10}", state.vfo).unwrap(), + } + lcd.set_cursor_pos(40, delay).unwrap(); + lcd.write_str(&string, delay).unwrap(); +} + #[cortex_m_rt::entry] fn main() -> ! { + let mut state = State { + mode : Mode::VFO, + bfo : 4_195_210, + bfo_tune_fail : false, + vfo : 23_000_000, + transmit : false, + }; + let cp = cortex_m::Peripherals::take().unwrap(); let dp = pac::Peripherals::take().unwrap(); @@ -58,23 +110,30 @@ fn main() -> ! { .freeze(&mut flash.acr); let mut delay = Delay::new(cp.SYST, clocks); - let adc1 = dp.ADC1; - // Buttons as analog inputs (multi-level) + let mut gpioa = dp.GPIOA.split(&mut rcc.apb2); let mut gpiob = dp.GPIOB.split(&mut rcc.apb2); + let mut gpioc = dp.GPIOC.split(&mut rcc.apb2); + + // Buttons as analog inputs (multi-level) 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 mut gpioc = dp.GPIOC.split(&mut rcc.apb2); 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 gpioa = dp.GPIOA.split(&mut rcc.apb2); // Configure PB14 as output. (LED) let mut led = gpiob.pb14.into_push_pull_output(&mut gpiob.crh); led.set_low().unwrap(); + let (pa15, pb3, pb4) = afio.mapr.disable_jtag(gpioa.pa15, gpiob.pb3, gpiob.pb4); + let _cw_key_n = pa15.into_push_pull_output_with_state(&mut gpioa.crh, gpio::State::High); // TODO output + let mut seq0n = pb3.into_push_pull_output_with_state(&mut gpiob.crl, gpio::State::High); + 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 c1 = gpioa.pa6; let c2 = gpioa.pa7; @@ -85,12 +144,12 @@ fn main() -> ! { 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( + let i2c2 = i2c::BlockingI2c::i2c2( dp.I2C2, (scl2, sda2), - Mode::Fast { + i2c::Mode::Fast { frequency: 400_000.hz(), - duty_cycle: DutyCycle::Ratio2to1, + duty_cycle: i2c::DutyCycle::Ratio2to1, }, clocks, &mut rcc.apb1, @@ -121,16 +180,15 @@ fn main() -> ! { lcd.write_str("Hello, world!", &mut delay).unwrap(); - /* // Configure I2C1 to be used for Si5351 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( + let i2c = i2c::BlockingI2c::i2c1( dp.I2C1, (scl, sda), &mut afio.mapr, - Mode::Standard { + i2c::Mode::Standard { frequency: 100_000.hz(), }, clocks, @@ -141,47 +199,63 @@ fn main() -> ! { /* data_timeout_us */ 1000, ); let i2c_busmanager = shared_bus::CortexMBusManager::new(i2c); - let mut siclock = si_clock::SiClock::new(i2c_busmanager.acquire()); - */ - lcd.set_cursor_pos(0, &mut delay).unwrap(); - lcd.write_str("Clocks set. ", &mut delay).unwrap(); + let mut siclock = si_clock::SiClock::new(i2c_busmanager.acquire(), state.bfo, state.vfo); - hprintln!("Main loop\n").unwrap(); + update_disp(&mut lcd, &state, &mut delay); let mut last_encoder_count = qei.count(); loop { led.toggle().unwrap(); - let mut string = arrayvec::ArrayString::<[_; 16]>::new(); + let mut update_disp_required = false; + let encoder_count = qei.count(); if encoder_count != last_encoder_count { - let freq = 23_000_000 + encoder_count as u32; - - //siclock.set_vfo(freq); - - write!(string, "{:15}", freq).unwrap(); - lcd.set_cursor_pos(40, &mut delay).unwrap(); - lcd.write_str(&string, &mut delay).unwrap(); + let delta = encoder_count.wrapping_sub(last_encoder_count); + let delta = if delta > 0x7FFF { delta as i32 - 0x10000 } else { delta as i32 }; + + match state.mode { + Mode::VFO => { + state.vfo = (state.vfo as i32 + delta * 500) as u32; + siclock.set_vfo(state.vfo); + }, + Mode::BFO => { + state.bfo = (state.bfo as i32 + delta * 50) as u32; + state.bfo_tune_fail = !siclock.set_bfo(state.bfo).is_ok(); + }, + } + + update_disp_required = true; } if let Some(b) = ui.read_buttons() { - let button = match b { - ui::ButtonPress::A => "A", - ui::ButtonPress::B => "B", - ui::ButtonPress::C => "C", - ui::ButtonPress::D => "D", - ui::ButtonPress::E => "E", - ui::ButtonPress::F => "F", - ui::ButtonPress::G => "G", - ui::ButtonPress::ENC => "X", + 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; + + seq0n.set_high().unwrap(); + }, + ui::ButtonPress::F => { + state.transmit = true; + + seq0n.set_low().unwrap(); + }, + ui::ButtonPress::G => {}, + ui::ButtonPress::ENC => {}, }; - lcd.set_cursor_pos(0, &mut delay).unwrap(); - write!(string, "{:15}", button).unwrap(); - lcd.write_str(&string, &mut delay).unwrap(); + update_disp_required = true; } + if update_disp_required { + update_disp(&mut lcd, &state, &mut delay) + }; + last_encoder_count = encoder_count; } } diff --git a/sw/picardy/src/si_clock.rs b/sw/picardy/src/si_clock.rs index 0bce24b..b304461 100644 --- a/sw/picardy/src/si_clock.rs +++ b/sw/picardy/src/si_clock.rs @@ -27,6 +27,7 @@ use si5351::{Si5351, Si5351Device}; use embedded_hal::blocking::i2c::{WriteRead, Write}; const REF_CLOCK : u32 = 25_000_000; +const PLL_A_MULT : u32 = 32; fn gcd(x: u32, y: u32) -> u32 { let mut x = x; @@ -67,6 +68,15 @@ fn clock_settings_with_pll_calculation(freq: u32) -> (u16, u8, u32, u32) { (divider.try_into().unwrap(), mult.try_into().unwrap(), num as u32, denom) } +fn set_bfo(siclock: &mut dyn Si5351, freq: u32) -> Result<(), si5351::Error> +{ + let (a, b, c) = clock_settings_for_pll(freq, PLL_A_MULT * REF_CLOCK); + siclock.setup_multisynth(si5351::Multisynth::MS2, a, b, c, si5351::OutputDivider::Div1)?; + siclock.select_clock_pll(si5351::ClockOutput::Clk2, si5351::PLL::A); + siclock.set_clock_enabled(si5351::ClockOutput::Clk2, true); + siclock.flush_clock_control(si5351::ClockOutput::Clk2) +} + fn set_vfo(siclock: &mut dyn Si5351, freq: u32) { let (div, mult, num, denom) = clock_settings_with_pll_calculation(freq); @@ -86,36 +96,28 @@ impl<I2C, E> SiClock<I2C> where I2C: WriteRead<Error = E> + Write<Error = E>, { - pub fn new(i2c: I2C) -> SiClock<I2C> { + pub fn new(i2c: I2C, bfo: u32, vfo: u32) -> SiClock<I2C> { let mut siclock = Si5351Device::new(i2c, false, REF_CLOCK); siclock.init(si5351::CrystalLoad::_10).unwrap(); // See freqplan.py for Si5351 frequency plan // CLK1 = 116MHz - let pll_a_mult = 32; siclock.setup_pll_int(si5351::PLL::A, 32).unwrap(); { let clk1 = 116_000_000; - let (a, b, c) = clock_settings_for_pll(clk1, pll_a_mult * REF_CLOCK); + let (a, b, c) = clock_settings_for_pll(clk1, PLL_A_MULT * REF_CLOCK); siclock.setup_multisynth(si5351::Multisynth::MS1, a, b, c, si5351::OutputDivider::Div1).unwrap(); siclock.select_clock_pll(si5351::ClockOutput::Clk1, si5351::PLL::A); siclock.set_clock_enabled(si5351::ClockOutput::Clk1, true); siclock.flush_clock_control(si5351::ClockOutput::Clk1).unwrap(); } - { - let clk2 = 4_195_210; - let (a, b, c) = clock_settings_for_pll(clk2, pll_a_mult * REF_CLOCK); - siclock.setup_multisynth(si5351::Multisynth::MS2, a, b, c, si5351::OutputDivider::Div1).unwrap(); - siclock.select_clock_pll(si5351::ClockOutput::Clk2, si5351::PLL::A); - siclock.set_clock_enabled(si5351::ClockOutput::Clk2, true); - siclock.flush_clock_control(si5351::ClockOutput::Clk2).unwrap(); - } + set_bfo(&mut siclock, bfo).unwrap(); siclock.reset_pll(si5351::PLL::A).unwrap(); - set_vfo(&mut siclock, 23_000_000); + set_vfo(&mut siclock, vfo); siclock.reset_pll(si5351::PLL::B).unwrap(); @@ -125,6 +127,10 @@ impl<I2C, E> SiClock<I2C> } pub fn set_vfo(&mut self, freq: u32) { - set_vfo(&mut self.siclock, freq); + set_vfo(&mut self.siclock, freq) + } + + pub fn set_bfo(&mut self, freq: u32) -> Result<(), si5351::Error> { + set_bfo(&mut self.siclock, freq) } } @@ -25,6 +25,13 @@ Microphone switches * SW1 PA3 * SW2 PA4 +## GPIO outputs + + * SEQ0n PB3 + * SEQ1 PB4 + * SEQ2 PB5 + * CW_KEYn PA15 + ## I2C1 for Si5351A-B-GT * SCL PB6 default alternate function |