aboutsummaryrefslogtreecommitdiffstats
path: root/sw
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2020-12-24 17:41:49 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2020-12-24 17:41:49 +0100
commit8d45f098b818206d3d91152f92175cbea0b56c8e (patch)
tree192acd925c229ef55815c8fab151c6e69b4883b5 /sw
parentd10cfc09f2a93ce3c85ec94eaee3f14a83e84cad (diff)
downloadpicardy-8d45f098b818206d3d91152f92175cbea0b56c8e.tar.gz
picardy-8d45f098b818206d3d91152f92175cbea0b56c8e.tar.bz2
picardy-8d45f098b818206d3d91152f92175cbea0b56c8e.zip
Add disabled CW, replace sequencer, ticks and set VFO/BFO logic
Diffstat (limited to 'sw')
-rw-r--r--sw/demo1/src/main.rs2
-rw-r--r--sw/picardy/Cargo.toml6
-rw-r--r--sw/picardy/src/cw.rs35
-rw-r--r--sw/picardy/src/main.rs102
-rw-r--r--sw/picardy/src/state.rs9
-rw-r--r--sw/picardy/src/ui.rs8
6 files changed, 112 insertions, 50 deletions
diff --git a/sw/demo1/src/main.rs b/sw/demo1/src/main.rs
index 4e6e5c6..09f51fa 100644
--- a/sw/demo1/src/main.rs
+++ b/sw/demo1/src/main.rs
@@ -34,7 +34,7 @@ use stm32f1xx_hal::{
pac,
i2c::{BlockingI2c, Mode},
delay::Delay,
- timer::{Timer},
+ timer::Timer,
};
use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin};
diff --git a/sw/picardy/Cargo.toml b/sw/picardy/Cargo.toml
index e773d57..e2192f6 100644
--- a/sw/picardy/Cargo.toml
+++ b/sw/picardy/Cargo.toml
@@ -5,6 +5,12 @@ authors = ["Matthias P. Braendli <matthias.braendli@mpb.li>"]
edition = "2018"
license = "MIT"
+[features]
+default = []
+
+# Enable CW transmit
+cw = []
+
[dependencies]
arrayvec = { version = "0.5", default-features = false, features = [] }
# alloc-cortex-m = "0.3" # requires nightly
diff --git a/sw/picardy/src/cw.rs b/sw/picardy/src/cw.rs
new file mode 100644
index 0000000..ce99e39
--- /dev/null
+++ b/sw/picardy/src/cw.rs
@@ -0,0 +1,35 @@
+//! CW output using PWM on PA8, TIM1 CH1
+
+use stm32f1xx_hal::{
+ prelude::*,
+ timer,
+ pac::TIM1,
+ gpio::gpioa::*,
+ gpio::{Alternate, PushPull},
+ afio::MAPR,
+ pwm,
+};
+
+pub struct CWPWM {
+ channel : pwm::PwmChannel<TIM1, pwm::C1>,
+}
+
+impl CWPWM {
+ pub fn new(pa8: PA8<Alternate<PushPull>>, tim1: timer::Timer<TIM1>, mapr: &mut MAPR) -> Self {
+ let pwm = tim1.pwm(pa8, mapr, 400.hz());
+ let mut channel = pwm.split();
+ channel.enable();
+ channel.set_duty(0);
+ CWPWM { channel }
+ }
+
+ pub fn on(&mut self) {
+ let max = self.channel.get_max_duty();
+ self.channel.set_duty(max / 2);
+ }
+
+ pub fn off(&mut self) {
+ self.channel.set_duty(0);
+ }
+}
+
diff --git a/sw/picardy/src/main.rs b/sw/picardy/src/main.rs
index b5efbdd..6d1d803 100644
--- a/sw/picardy/src/main.rs
+++ b/sw/picardy/src/main.rs
@@ -43,20 +43,25 @@ use stm32f1xx_hal::{
};
use embedded_hal::digital::v2::OutputPin;
+#[cfg(feature = "cw")]
+use embedded_hal::digital::v2::InputPin;
use hd44780_driver::{Cursor, CursorBlink, Display, DisplayMode, HD44780};
pub mod ui;
+pub mod cw;
pub mod state;
pub mod si_clock;
pub mod log10f;
use state::*;
+const TICKS_PER_SECOND : u32 = 50;
+
static mut CLOCK_TIMER: MaybeUninit<CountDownTimer<pac::TIM2>> = MaybeUninit::uninit();
-static mut DECISECONDS_COUNTER: MaybeUninit<usize> = MaybeUninit::uninit();
+static mut TICK_COUNTER: MaybeUninit<u32> = MaybeUninit::uninit();
-fn time_now() -> usize {
- cortex_m::interrupt::free(|_cs| unsafe { *DECISECONDS_COUNTER.as_ptr() })
+fn ticks_now() -> u32 {
+ cortex_m::interrupt::free(|_cs| unsafe { *TICK_COUNTER.as_ptr() })
}
#[cortex_m_rt::entry]
@@ -91,6 +96,16 @@ 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);
+
+#[cfg(feature = "cw")]
+ let (mut cwpwm, cw_paddle_tip) = {
+ let pa8 = gpioa.pa8.into_alternate_push_pull(&mut gpioa.crh); // CW PWM output using TIM1 Ch1
+ let tim1 = Timer::tim1(dp.TIM1, &clocks, &mut rcc.apb2);
+ let cwpwm = cw::CWPWM::new(pa8, tim1, &mut afio.mapr);
+ let cw_paddle_tip = gpiob.pb8.into_pull_up_input(&mut gpiob.crh); // CW paddle tip
+ (cwpwm, cw_paddle_tip)
+ };
+
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;
@@ -185,14 +200,14 @@ fn main() -> ! {
let mut last_encoder_count = qei.count();
{
- let deciseconds_counter = unsafe { &mut *DECISECONDS_COUNTER.as_mut_ptr() };
- *deciseconds_counter = 0;
+ let ticks = unsafe { &mut *TICK_COUNTER.as_mut_ptr() };
+ *ticks = 0;
}
{
let timer = unsafe { &mut *CLOCK_TIMER.as_mut_ptr() };
*timer = Timer::tim2(dp.TIM2, &clocks, &mut rcc.apb1)
- .start_count_down(50.hz());
+ .start_count_down(TICKS_PER_SECOND.hz());
timer.listen(Event::Update);
}
@@ -201,6 +216,9 @@ fn main() -> ! {
loop {
let mut update_disp_required = false;
+ let previous_vfo = state.vfo();
+ let previous_bfo = state.bfo();
+
let encoder_count : u16 = qei.count();
if encoder_count != last_encoder_count {
let delta = encoder_count.wrapping_sub(last_encoder_count);
@@ -215,63 +233,63 @@ fn main() -> ! {
let button_result = ui.handle_buttons(&mut state);
- if button_result.bfo_update {
+ if previous_bfo != state.bfo() {
state.bfo_tune_fail = !siclock.set_bfo(state.bfo()).is_ok();
}
+ if previous_vfo != state.vfo() {
+ siclock.set_vfo(state.vfo());
+ }
+
update_disp_required |= button_result.display_update;
let next_state = match state.sequence_state {
SequenceState::Rx => {
led.set_high().unwrap();
+
+ mute_spkr.set_low().unwrap();
+ mute_micn.set_low().unwrap();
+ seq2_switch.set_low().unwrap();
+ seq0n.set_high().unwrap();
+
if button_result.ptt {
- mute_spkr.set_high().unwrap();
- mute_micn.set_high().unwrap();
- seq2_switch.set_high().unwrap();
- SequenceState::ToTxStep1
+ SequenceState::Switching
}
else {
- mute_spkr.set_low().unwrap();
- mute_micn.set_low().unwrap();
SequenceState::Rx
}
},
- SequenceState::ToTxStep1 => {
- led.set_low().unwrap();
+ SequenceState::Switching => {
+ mute_spkr.set_high().unwrap();
+ mute_micn.set_high().unwrap();
+ seq2_switch.set_high().unwrap();
seq0n.set_low().unwrap();
- SequenceState::ToTxStep2
- },
- SequenceState::ToTxStep2 => {
- led.set_high().unwrap();
- seq1_pa.set_high().unwrap();
- SequenceState::Tx
+ seq1_pa.set_low().unwrap();
+
+ if button_result.ptt {
+ SequenceState::Tx
+ }
+ else {
+ SequenceState::Rx
+ }
},
SequenceState::Tx => {
led.set_low().unwrap();
+
+ seq1_pa.set_high().unwrap();
if button_result.ptt {
SequenceState::Tx
}
else {
- seq1_pa.set_low().unwrap();
- SequenceState::ToRxStep1
+ SequenceState::Switching
}
},
- SequenceState::ToRxStep1 => {
- seq0n.set_high().unwrap();
- led.set_high().unwrap();
- SequenceState::ToRxStep2
- },
- SequenceState::ToRxStep2 => {
- led.set_low().unwrap();
- seq2_switch.set_low().unwrap();
- SequenceState::Rx
- }
};
- let t_now = time_now();
+ let t_now = ticks_now();
+ const SWITCHING_DELAY : u32 = TICKS_PER_SECOND * 200 / 1000;
if state.sequence_state != next_state &&
- last_sequence_state_change + 1 <= t_now {
- update_disp_required = true;
+ last_sequence_state_change + SWITCHING_DELAY <= t_now {
state.sequence_state = next_state;
last_sequence_state_change = t_now;
}
@@ -296,6 +314,14 @@ fn main() -> ! {
last_encoder_count = encoder_count;
+#[cfg(feature = "cw")]
+ if cw_paddle_tip.is_low().unwrap() {
+ cwpwm.on();
+ }
+ else {
+ cwpwm.off();
+ }
+
cortex_m::asm::wfi();
}
}
@@ -305,8 +331,8 @@ fn TIM2() {
let timer = unsafe { &mut *CLOCK_TIMER.as_mut_ptr() };
timer.clear_update_interrupt_flag();
- let deciseconds_counter = unsafe { &mut *DECISECONDS_COUNTER.as_mut_ptr() };
- *deciseconds_counter += 1;
+ let ticks = unsafe { &mut *TICK_COUNTER.as_mut_ptr() };
+ *ticks += 1;
}
#[cortex_m_rt::exception]
diff --git a/sw/picardy/src/state.rs b/sw/picardy/src/state.rs
index bfe0212..ed99087 100644
--- a/sw/picardy/src/state.rs
+++ b/sw/picardy/src/state.rs
@@ -34,18 +34,13 @@ pub enum FilterShift {
#[derive(PartialEq, Eq)]
pub enum SequenceState {
Rx,
- ToTxStep1,
- ToTxStep2,
+ Switching,
Tx,
- ToRxStep1,
- ToRxStep2,
}
impl SequenceState {
fn apply_rit(&self) -> bool {
- *self == SequenceState::Rx ||
- *self == SequenceState::ToRxStep1 ||
- *self == SequenceState::ToRxStep2
+ *self == SequenceState::Rx
}
}
diff --git a/sw/picardy/src/ui.rs b/sw/picardy/src/ui.rs
index 0d42f88..1133582 100644
--- a/sw/picardy/src/ui.rs
+++ b/sw/picardy/src/ui.rs
@@ -92,7 +92,6 @@ impl fmt::Display for ButtonState {
#[derive(Default)]
pub struct ButtonResult {
- pub bfo_update : bool,
pub display_update : bool,
pub ptt : bool,
}
@@ -206,7 +205,6 @@ impl UI {
state.ui_sel = new_ui_sel;
state.filter_shift = new_filter_shift;
- result.bfo_update = true;
result.display_update = true;
}
@@ -227,7 +225,6 @@ impl UI {
},
UISelection::IFShift => {
state.filter_shift = FilterShift::USB;
- result.bfo_update = true;
},
}
@@ -273,7 +270,10 @@ pub fn update_disp<T: hd44780_driver::bus::DataBus>(lcd: &mut HD44780<T>, state:
write!(string, "{:<03}.{:<03} ", disp_freq / 1000, disp_freq % 1000).unwrap();
write!(string, "{}{:<03}", if state.rit >= 0 { "+" } else { "-" }, state.rit.abs()/10).unwrap();
- write!(string, "S{:3}", s_meter_value).unwrap();
+ if string.len() <= 16 - 4 {
+ // Avoids crash when frequency is very negative
+ write!(string, "S{:3}", s_meter_value).unwrap();
+ }
lcd.set_cursor_pos(0, delay).unwrap();
lcd.write_str(&string, delay).unwrap();