From 59b1601b5c2ce860b19d50908dc02869fc030924 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 28 Aug 2020 16:16:33 +0200 Subject: Continue TX assembly, update versions --- sw/picardy/Cargo.lock | 54 +++++++------------ sw/picardy/Cargo.toml | 6 +-- sw/picardy/src/main.rs | 144 +++++++++++++++++++++++++++++++++++++------------ sw/picardy/src/ui.rs | 101 +++++++++++++++++++++++++++------- sw/pio.txt | 2 + 5 files changed, 215 insertions(+), 92 deletions(-) (limited to 'sw') diff --git a/sw/picardy/Cargo.lock b/sw/picardy/Cargo.lock index 9089792..19f0e2d 100644 --- a/sw/picardy/Cargo.lock +++ b/sw/picardy/Cargo.lock @@ -2,15 +2,9 @@ # It is not intended for manual editing. [[package]] name = "aligned" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39da9b88ae1a81c03c9c082b8db83f1d0e93914126041962af61034ab44c4a5" - -[[package]] -name = "aligned" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1ce8b3382016136ab1d31a1b5ce807144f8b7eb2d5f16b2108f0f07edceb94" +checksum = "c19796bd8d477f1a9d4ac2465b464a8b1359474f06a96bb3cda650b4fca309bf" dependencies = [ "as-slice", ] @@ -62,25 +56,13 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "cortex-m" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0b159a1e8306949579de3698c841dba58058197b65c60807194e4fa1e7a554" -dependencies = [ - "aligned 0.2.0", - "bare-metal", - "cortex-m 0.6.3", - "volatile-register", -] - [[package]] name = "cortex-m" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2be99930c99669a74d986f7fd2162085498b322e6daae8ef63a97cc9ac1dc73c" dependencies = [ - "aligned 0.3.2", + "aligned", "bare-metal", "bitfield", "volatile-register", @@ -113,7 +95,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "113ef0ecffee2b62b58f9380f4469099b30e9f9cbee2804771b4203ba1762cfa" dependencies = [ - "cortex-m 0.6.3", + "cortex-m", ] [[package]] @@ -172,7 +154,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c03864ac862876c16a308f5286f4aa217f1a69ac45df87ad3cd2847f818a642c" dependencies = [ - "cortex-m 0.6.3", + "cortex-m", "cortex-m-semihosting", ] @@ -181,12 +163,12 @@ name = "picardy" version = "0.1.0" dependencies = [ "arrayvec", - "cortex-m 0.6.3", + "cortex-m", "cortex-m-rt", "cortex-m-semihosting", "embedded-hal", "hd44780-driver", - "nb 0.1.3", + "nb 1.0.0", "panic-semihosting", "shared-bus", "si5351", @@ -243,11 +225,11 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "shared-bus" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed792a53f339088822c0cc9d6ebfb950752016a288dc96ed3e302e9592f18ab0" +checksum = "7f42e140835229dea9c0b2498d2c88afe52ed2bd42a7cc6068c95adb5134b541" dependencies = [ - "cortex-m 0.5.10", + "cortex-m", "embedded-hal", ] @@ -267,25 +249,25 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stm32f1" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ce629123831891663402861bdc7140ebfd6a34a464329f9b9ec1cfde72055a" +checksum = "849b1e8d9bcfd792c9d9178cf86165d299a661c26e35d9322ae9382d3f3fe460" dependencies = [ "bare-metal", - "cortex-m 0.6.3", + "cortex-m", "cortex-m-rt", "vcell", ] [[package]] name = "stm32f1xx-hal" -version = "0.5.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455bf444813cdc2498130626c5d0ca42f91de1e8261751f3bdc6e5ad9e2aa128" +checksum = "af9b9e5d7c2901ee39fc9527412327a1fe08f1d84e9d7f4b3497448e655e5098" dependencies = [ "as-slice", "cast", - "cortex-m 0.6.3", + "cortex-m", "cortex-m-rt", "embedded-hal", "nb 0.1.3", @@ -295,9 +277,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.35" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7f4c519df8c117855e19dd8cc851e89eb746fe7a73f0157e0d95fdec5369b0" +checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" dependencies = [ "proc-macro2", "quote", diff --git a/sw/picardy/Cargo.toml b/sw/picardy/Cargo.toml index 2452359..26b794d 100644 --- a/sw/picardy/Cargo.toml +++ b/sw/picardy/Cargo.toml @@ -13,11 +13,11 @@ cortex-m-rt = "0.6" # consider cortex-m-rtfm cortex-m-semihosting = "0.3" panic-semihosting = "0.5" -nb = "0.1" +nb = "1.0" #stm32h7 = { version = "0.9", features = ["stm32h743", "rt"] } -stm32f1xx-hal = { version = "0.5", features = ["rt", "stm32f103"] } +stm32f1xx-hal = { version = "0.6", features = ["rt", "stm32f103"] } embedded-hal = { version = "0.2", features = [] } -shared-bus = { version = "0.1.4", features = ["cortexm"] } +shared-bus = { version = "0.2", features = ["cortex-m"] } hd44780-driver = { path = "../deps/hd44780-driver"} si5351 = { path = "../deps/si5351" } 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(lcd: &mut HD44780, state: &State, delay: &mut Delay) { let mut string = arrayvec::ArrayString::<[_; 16]>::new(); @@ -82,9 +115,16 @@ fn update_disp(lcd: &mut HD44780, 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(lcd: &mut HD44780, 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() }; diff --git a/sw/picardy/src/ui.rs b/sw/picardy/src/ui.rs index 76f89b9..114fe1e 100644 --- a/sw/picardy/src/ui.rs +++ b/sw/picardy/src/ui.rs @@ -22,11 +22,14 @@ SOFTWARE. */ +use core::fmt; + use stm32f1xx_hal::{ prelude::*, adc, rcc::{APB2, Clocks}, stm32::ADC1, + gpio::gpioa::*, gpio::gpiob::*, gpio::gpioc::*, gpio::{Analog, Input, PullUp}, @@ -35,15 +38,44 @@ use stm32f1xx_hal::{ use embedded_hal::digital::v2::InputPin; #[derive(PartialEq, Eq, Clone, Copy)] -pub enum ButtonPress { - A, +enum Btn0Buttons { B, C, D, - E, +} + +#[derive(PartialEq, Eq, Clone, Copy)] +enum Btn1Buttons { + A, F, - G, - ENC, +} + +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct ButtonState { + pub a : bool, + pub b : bool, + pub c : bool, + pub d : bool, + pub e : bool, + pub f : bool, + pub g : bool, + pub enc : bool, + pub ptt : bool, +} + +impl fmt::Display for ButtonState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}{}{}{}{}{}{}{}{}", + if self.a { "A" } else { "a" }, + if self.b { "B" } else { "b" }, + if self.c { "C" } else { "c" }, + if self.d { "D" } else { "d" }, + if self.e { "E" } else { "e" }, + if self.f { "F" } else { "f" }, + if self.g { "G" } else { "g" }, + if self.enc { "X" } else { "x" }, + if self.ptt { "P" } else { "p" }) + } } pub struct UI { @@ -53,6 +85,9 @@ pub struct UI { btn0_ch : PB1, btn1_ch : PB0, + _mic_sw1 : PA3, + mic_sw2 : PA4, + btn2 : PB12>, btn3 : PB13>, @@ -62,7 +97,7 @@ pub struct UI { } impl UI { - pub fn new(pb0: PB0, pb1: PB1, adc1: ADC1, mut apb2: &mut APB2, clocks: &Clocks, pb12: PB12>, pb13: PB13>, pc15 : PC15>) -> UI { + pub fn new(mic_sw1: PA3, mic_sw2: PA4, pb0: PB0, pb1: PB1, adc1: ADC1, mut apb2: &mut APB2, clocks: &Clocks, pb12: PB12>, pb13: PB13>, pc15 : PC15>) -> UI { let adc1 = adc::Adc::adc1(adc1, &mut apb2, *clocks); @@ -75,10 +110,30 @@ impl UI { btn3 : pb13, btn_enc : pc15, adc : adc1, + _mic_sw1 : mic_sw1, + mic_sw2, } } - pub fn read_buttons(&mut self) -> Option { + pub fn read_ptt(&mut self) -> bool { + let _mic_sw1_value: u16 = self.adc.read(&mut self._mic_sw1).unwrap(); + let mic_sw2_value: u16 = self.adc.read(&mut self.mic_sw2).unwrap(); + mic_sw2_value < 500 + } + + pub fn read_buttons(&mut self) -> ButtonState { + let mut buttons = ButtonState { + a : false, + b : false, + c : false, + d : false, + e : false, + f : false, + g : false, + enc : false, + ptt : false, + }; + // Debounce BTN0 let btn0_value: u16 = self.adc.read(&mut self.btn0_ch).unwrap(); @@ -93,18 +148,23 @@ impl UI { None } else if v > 1650 { - Some(ButtonPress::B) + Some(Btn0Buttons::B) } else if v > 675 { - Some(ButtonPress::C) + Some(Btn0Buttons::C) } else { - Some(ButtonPress::D) + Some(Btn0Buttons::D) }; } if btn0.iter().all(|&v| v != None && v == btn0[0]) { - return btn0[0]; + match btn0[0] { + None => {}, + Some(Btn0Buttons::B) => buttons.b = true, + Some(Btn0Buttons::C) => buttons.c = true, + Some(Btn0Buttons::D) => buttons.d = true, + } } @@ -123,29 +183,34 @@ impl UI { None } else if v > 675 { - Some(ButtonPress::F) + Some(Btn1Buttons::F) } else { - Some(ButtonPress::A) + Some(Btn1Buttons::A) }; } if btn1.iter().all(|&v| v != None && v == btn1[0]) { - return btn1[0]; + match btn1[0] { + None => {}, + Some(Btn1Buttons::A) => buttons.a = true, + Some(Btn1Buttons::F) => buttons.f = true, + } } if self.btn2.is_low().unwrap() { - return Some(ButtonPress::E) + buttons.e = true; } if self.btn3.is_low().unwrap() { - return Some(ButtonPress::G) + buttons.g = true; } if self.btn_enc.is_low().unwrap() { - return Some(ButtonPress::ENC) + buttons.enc = true; } - None + cortex_m_semihosting::hprintln!("btn {} {}: {}", btn0_value, btn1_value, buttons).unwrap(); + buttons } } diff --git a/sw/pio.txt b/sw/pio.txt index ef97a1e..c932d08 100644 --- a/sw/pio.txt +++ b/sw/pio.txt @@ -31,6 +31,8 @@ Microphone switches * SEQ1 PB4 * SEQ2 PB5 * CW_KEYn PA15 + * MUTE_SPKR PA2 + * MUTE_MICn PA1 ## I2C1 for Si5351A-B-GT -- cgit v1.2.3