aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md13
-rw-r--r--kicad/control.sch1
-rw-r--r--kicad/picardy.sch8
-rw-r--r--kicad/power.sch6
-rw-r--r--sw/picardy/src/main.rs146
-rw-r--r--sw/picardy/src/si_clock.rs32
-rw-r--r--sw/pio.txt7
7 files changed, 158 insertions, 55 deletions
diff --git a/README.md b/README.md
index 29946d9..e551148 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,19 @@ Open questions
* Put sidetone volume setting before RV303?
* Hook up to LM375 BYPASS?
+Issues
+======
+
+* SEQ0 is used in inverted-logic in baseband, and noninverted for power relay
+ * Due to inconsistent naming
+ * Ugly fix on K603 side, use SEQ0n, SEQ1, SEQ2
+* G6K-2F-RF all have the Y footprint, not the equidistant one.
+ * And they have additional GND flaps too, which are not in the Kicad footprint library
+ * Can be kludged-in
+* 5V jumper is less useful as hoped
+ * Intention: disable VHF stuff
+ * Unintended effect: removes LCD backlight
+
PCB Assembly Plan
=================
diff --git a/kicad/control.sch b/kicad/control.sch
index b3c9b1e..fe73b31 100644
--- a/kicad/control.sch
+++ b/kicad/control.sch
@@ -717,6 +717,7 @@ F 0 "U201" H 5850 2661 50 0000 C CNN
F 1 "STM32F103C8Tx" H 5850 2570 50 0000 C CNN
F 2 "Package_QFP:LQFP-48_7x7mm_P0.5mm" H 5300 2850 50 0001 R CNN
F 3 "http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00161566.pdf" H 5900 4250 50 0001 C CNN
+F 4 "STM32F103C8T6" H 5900 4250 50 0001 C CNN "MPN"
1 5900 4250
1 0 0 -1
$EndComp
diff --git a/kicad/picardy.sch b/kicad/picardy.sch
index 431a9b1..b1d41b6 100644
--- a/kicad/picardy.sch
+++ b/kicad/picardy.sch
@@ -20,8 +20,8 @@ F0 "Control" 50
F1 "control.sch" 50
F2 "CW_TONE" O R 4700 1450 50
F3 "SEQ0n" O R 4700 1700 50
-F4 "SEQ1n" O R 4700 1800 50
-F5 "SEQ2n" O R 4700 1900 50
+F4 "SEQ1" O R 4700 1800 50
+F5 "SEQ2" O R 4700 1900 50
F6 "MIC" O R 4700 2300 50
F7 "MUTE_SPKR" O R 4700 2200 50
F8 "S_METER" I L 3450 2400 50
@@ -464,8 +464,8 @@ F1 "power.sch" 50
F2 "IN_+12V" I L 1400 1550 50
F3 "IN_GND" I L 1400 1650 50
F4 "SWITCH_5V_8V_TXn" I L 1400 2050 50
-F5 "SWITCH_EXTn" I L 1400 2250 50
-F6 "SWITCH_EXT_PAn" I L 1400 2150 50
+F5 "SWITCH_EXT" I L 1400 2250 50
+F6 "SWITCH_EXT_PA" I L 1400 2150 50
$EndSheet
$Comp
L power:GND #PWR?
diff --git a/kicad/power.sch b/kicad/power.sch
index 8cc81bd..33ed745 100644
--- a/kicad/power.sch
+++ b/kicad/power.sch
@@ -811,7 +811,7 @@ F 4 "0" H 1900 5100 50 0001 C CNN "Need_order"
-1 0 0 1
$EndComp
Text HLabel 1850 4900 0 50 Input ~ 0
-SWITCH_EXTn
+SWITCH_EXT
$Comp
L Device:R R?
U 1 1 5E66CC07
@@ -842,7 +842,7 @@ F 3 "" H 3700 5600 50 0001 C CNN
0 1 1 0
$EndComp
Text HLabel 3850 4900 0 50 Input ~ 0
-SWITCH_EXT_PAn
+SWITCH_EXT_PA
Text Notes 5650 6400 0 50 ~ 0
Can switch\n2A
$Comp
@@ -1121,4 +1121,6 @@ F 3 "" H 8900 1850 50 0001 C CNN
1 8900 1850
1 0 0 -1
$EndComp
+Text Notes 6650 3650 0 50 ~ 0
+PCB 07.2020 assembled with\nugly fix to invert like for K301
$EndSCHEMATC
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)
}
}
diff --git a/sw/pio.txt b/sw/pio.txt
index e8c85e8..ef97a1e 100644
--- a/sw/pio.txt
+++ b/sw/pio.txt
@@ -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