aboutsummaryrefslogtreecommitdiffstats
path: root/sw
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2020-12-07 19:55:19 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2020-12-07 19:55:19 +0100
commitc62ada1fe61ab6d5fae4639c9fca1998bf0dce28 (patch)
tree89941c49b3172c53d101d68576af17603d20e2a3 /sw
parente267dc1bc7074daf3689a283a7198e011e7e8945 (diff)
downloadpicardy-c62ada1fe61ab6d5fae4639c9fca1998bf0dce28.tar.gz
picardy-c62ada1fe61ab6d5fae4639c9fca1998bf0dce28.tar.bz2
picardy-c62ada1fe61ab6d5fae4639c9fca1998bf0dce28.zip
Fix PTT, add AGC readout
Diffstat (limited to 'sw')
-rw-r--r--sw/picardy/src/log10f.rs91
-rw-r--r--sw/picardy/src/main.rs41
-rw-r--r--sw/picardy/src/state.rs4
-rw-r--r--sw/picardy/src/ui.rs13
4 files changed, 131 insertions, 18 deletions
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<T: hd44780_driver::bus::DataBus>(lcd: &mut HD44780<T>, state: &State, delay: &mut Delay)
+pub fn update_disp<T: hd44780_driver::bus::DataBus>(lcd: &mut HD44780<T>, state: &State, delay: &mut Delay, s_meter_value : i32)
{
let mut string = arrayvec::ArrayString::<[_; 16]>::new();
@@ -340,7 +342,8 @@ pub fn update_disp<T: hd44780_driver::bus::DataBus>(lcd: &mut HD44780<T>, 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<T: hd44780_driver::bus::DataBus>(lcd: &mut HD44780<T>, 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();