From c62ada1fe61ab6d5fae4639c9fca1998bf0dce28 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Mon, 7 Dec 2020 19:55:19 +0100 Subject: Fix PTT, add AGC readout --- sw/picardy/src/log10f.rs | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ sw/picardy/src/main.rs | 41 ++++++++++++++++------ sw/picardy/src/state.rs | 4 +-- sw/picardy/src/ui.rs | 13 ++++--- 4 files changed, 131 insertions(+), 18 deletions(-) create mode 100644 sw/picardy/src/log10f.rs (limited to 'sw') diff --git a/sw/picardy/src/log10f.rs b/sw/picardy/src/log10f.rs new file mode 100644 index 0000000..108dfa8 --- /dev/null +++ b/sw/picardy/src/log10f.rs @@ -0,0 +1,91 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_log10f.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * See comments in log10.c. + */ + +use core::f32; + +const IVLN10HI: f32 = 4.3432617188e-01; /* 0x3ede6000 */ +const IVLN10LO: f32 = -3.1689971365e-05; /* 0xb804ead9 */ +const LOG10_2HI: f32 = 3.0102920532e-01; /* 0x3e9a2080 */ +const LOG10_2LO: f32 = 7.9034151668e-07; /* 0x355427db */ +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +const LG1: f32 = 0.66666662693; /* 0xaaaaaa.0p-24 */ +const LG2: f32 = 0.40000972152; /* 0xccce13.0p-25 */ +const LG3: f32 = 0.28498786688; /* 0x91e9ee.0p-25 */ +const LG4: f32 = 0.24279078841; /* 0xf89e26.0p-26 */ + +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn log10f(mut x: f32) -> f32 { + let x1p25f = f32::from_bits(0x4c000000); // 0x1p25f === 2 ^ 25 + + let mut ui: u32 = x.to_bits(); + let hfsq: f32; + let f: f32; + let s: f32; + let z: f32; + let r: f32; + let w: f32; + let t1: f32; + let t2: f32; + let dk: f32; + let mut hi: f32; + let lo: f32; + let mut ix: u32; + let mut k: i32; + + ix = ui; + k = 0; + if ix < 0x00800000 || (ix >> 31) > 0 { + /* x < 2**-126 */ + if ix << 1 == 0 { + return -1. / (x * x); /* log(+-0)=-inf */ + } + if (ix >> 31) > 0 { + return (x - x) / 0.0; /* log(-#) = NaN */ + } + /* subnormal number, scale up x */ + k -= 25; + x *= x1p25f; + ui = x.to_bits(); + ix = ui; + } else if ix >= 0x7f800000 { + return x; + } else if ix == 0x3f800000 { + return 0.; + } + + /* reduce x into [sqrt(2)/2, sqrt(2)] */ + ix += 0x3f800000 - 0x3f3504f3; + k += (ix >> 23) as i32 - 0x7f; + ix = (ix & 0x007fffff) + 0x3f3504f3; + ui = ix; + x = f32::from_bits(ui); + + f = x - 1.0; + s = f / (2.0 + f); + z = s * s; + w = z * z; + t1 = w * (LG2 + w * LG4); + t2 = z * (LG1 + w * LG3); + r = t2 + t1; + hfsq = 0.5 * f * f; + + hi = f - hfsq; + ui = hi.to_bits(); + ui &= 0xfffff000; + hi = f32::from_bits(ui); + lo = f - hi - hfsq + s * (hfsq + r); + dk = k as f32; + dk * LOG10_2LO + (lo + hi) * IVLN10LO + lo * IVLN10HI + hi * IVLN10HI + dk * LOG10_2HI +} diff --git a/sw/picardy/src/main.rs b/sw/picardy/src/main.rs index ed9d799..0d27f7a 100644 --- a/sw/picardy/src/main.rs +++ b/sw/picardy/src/main.rs @@ -32,6 +32,7 @@ use panic_semihosting as _; use stm32f1xx_hal::{ prelude::*, + adc, pac, pac::interrupt, i2c, @@ -47,6 +48,7 @@ use hd44780_driver::{Cursor, CursorBlink, Display, DisplayMode, HD44780}; pub mod ui; pub mod state; pub mod si_clock; +pub mod log10f; use state::*; @@ -84,6 +86,10 @@ fn main() -> ! { let adc1 = dp.ADC1; let mut ui = ui::UI::new(mic_sw1, mic_sw2, pb0, pb1, adc1, &mut rcc.apb2, &clocks, pb12, pb13, pc15); + let mut s_meter = gpioa.pa5.into_analog(&mut gpioa.crl); + let mut adc2 = adc::Adc::adc2(dp.ADC2, &mut rcc.apb2, clocks); + let mut last_s_meter_update_time = 0; + let mut last_sequence_state_change = 0; // Configure PB14 as output. (LED) let mut led = gpiob.pb14.into_push_pull_output(&mut gpiob.crh); @@ -166,7 +172,8 @@ fn main() -> ! { let mut siclock = si_clock::SiClock::new(i2c_busmanager.acquire_i2c(), state.bfo(), state.vfo()); - ui::update_disp(&mut lcd, &state, &mut delay); + let mut last_s_meter_value = 0; + ui::update_disp(&mut lcd, &state, &mut delay, last_s_meter_value); let mut last_encoder_count = qei.count(); @@ -220,12 +227,12 @@ fn main() -> ! { }, SequenceState::ToTxStep1 => { led.set_low().unwrap(); - seq1_pa.set_high().unwrap(); + seq0n.set_low().unwrap(); SequenceState::ToTxStep2 }, SequenceState::ToTxStep2 => { led.set_high().unwrap(); - seq0n.set_low().unwrap(); + seq1_pa.set_high().unwrap(); SequenceState::Tx }, SequenceState::Tx => { @@ -234,13 +241,13 @@ fn main() -> ! { SequenceState::Tx } else { - seq0n.set_high().unwrap(); + seq1_pa.set_low().unwrap(); SequenceState::ToRxStep1 } }, SequenceState::ToRxStep1 => { + seq0n.set_high().unwrap(); led.set_high().unwrap(); - seq1_pa.set_low().unwrap(); SequenceState::ToRxStep2 }, SequenceState::ToRxStep2 => { @@ -252,21 +259,35 @@ fn main() -> ! { let t_now = unsafe { *DECISECONDS_COUNTER.as_ptr() }; if state.sequence_state != next_state && - state.last_sequence_state_change + 1 <= t_now { + last_sequence_state_change + 1 <= t_now { update_disp_required = true; state.sequence_state = next_state; - state.last_sequence_state_change = t_now; + last_sequence_state_change = t_now; + } + + let s_meter_value: u16 = adc2.read(&mut s_meter).unwrap(); + + // Avoid 0 because of log10 + let s_meter_value = f32::from(if s_meter_value == 0 { 1 } else { s_meter_value }); + + // ADC is 12-bit, convert to dB full-scale + let s_meter_value = 10f32 * log10f::log10f(f32::from(s_meter_value) / 4092f32); + let s_meter_value = s_meter_value as i32; + if last_s_meter_update_time + 10 < t_now { + update_disp_required = s_meter_value != last_s_meter_value; + last_s_meter_value = s_meter_value; + last_s_meter_update_time = t_now; } if update_disp_required { - ui::update_disp(&mut lcd, &state, &mut delay); + ui::update_disp(&mut lcd, &state, &mut delay, s_meter_value); } last_encoder_count = encoder_count; - //delay.delay_ms(20u8); + //delay.delay_ms(5u8); - //cortex_m::asm::wfi(); + cortex_m::asm::wfi(); } } diff --git a/sw/picardy/src/state.rs b/sw/picardy/src/state.rs index 69fda9e..466fd32 100644 --- a/sw/picardy/src/state.rs +++ b/sw/picardy/src/state.rs @@ -1,6 +1,6 @@ pub const VHF_BAND_EDGE : u32 = 144_000_000; pub const VHF_INITIAL_VFO : u32 = 144_300_000; -pub const VHF_LO : u32 = 114_286_000; +pub const VHF_LO : u32 = 114_285_000; pub const BFO_LSB : u32 = 4_915_940; pub const BFO_USB : u32 = 4_914_910; @@ -58,7 +58,6 @@ pub struct State { pub bfo_tune_fail : bool, pub tune_speed : TuneSpeed, pub sequence_state : SequenceState, - pub last_sequence_state_change : usize, } impl State { @@ -73,7 +72,6 @@ impl State { vfo_b : VHF_INITIAL_VFO, tune_speed : TuneSpeed::Mid, sequence_state : SequenceState::Rx, - last_sequence_state_change : 0, } } diff --git a/sw/picardy/src/ui.rs b/sw/picardy/src/ui.rs index 915adec..baaebf0 100644 --- a/sw/picardy/src/ui.rs +++ b/sw/picardy/src/ui.rs @@ -79,7 +79,7 @@ impl ButtonState { f : !old_state.f && self.f, g : !old_state.g && self.g, enc : !old_state.enc && self.enc, - ptt : !old_state.ptt && self.ptt, + ptt : self.ptt, // Don't do edge detection for PTT! } } } @@ -249,6 +249,8 @@ impl UI { let button_updates = button_state.edge_detection(&self.previous_button_state); self.previous_button_state = button_state; + result.ptt = button_updates.ptt; + if button_updates.a { state.vfo_sel = match state.vfo_sel { VFOSelection::A => VFOSelection::B, @@ -332,7 +334,7 @@ impl UI { } } -pub fn update_disp(lcd: &mut HD44780, state: &State, delay: &mut Delay) +pub fn update_disp(lcd: &mut HD44780, state: &State, delay: &mut Delay, s_meter_value : i32) { let mut string = arrayvec::ArrayString::<[_; 16]>::new(); @@ -340,7 +342,8 @@ pub fn update_disp(lcd: &mut HD44780, state: let disp_freq = (state.vhf_qrg() as i32) - (VHF_BAND_EDGE as i32); write!(string, "{:<03}.{:<03} ", disp_freq / 1000, disp_freq % 1000).unwrap(); - write!(string, "{}{:<04} ", if state.rit >= 0 { "+" } else { "-" }, state.rit.abs()).unwrap(); + write!(string, "{}{:<03}", if state.rit >= 0 { "+" } else { "-" }, state.rit.abs()/10).unwrap(); + write!(string, "S{:3}", s_meter_value).unwrap(); lcd.set_cursor_pos(0, delay).unwrap(); lcd.write_str(&string, delay).unwrap(); @@ -349,8 +352,8 @@ pub fn update_disp(lcd: &mut HD44780, state: match (state.bfo_tune_fail, &state.vfo_sel) { (true, _) => write!(string, "VFO!").unwrap(), - (false, VFOSelection::A) => write!(string, "ERRa").unwrap(), - (false, VFOSelection::B) => write!(string, "ERRb").unwrap(), + (false, VFOSelection::A) => write!(string, "VFOa").unwrap(), + (false, VFOSelection::B) => write!(string, "VFOb").unwrap(), } write!(string, "{}", if state.ui_sel == UISelection::RIT { ">RIT" } else { " RIT" }).unwrap(); -- cgit v1.2.3