aboutsummaryrefslogtreecommitdiffstats
path: root/sw
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2023-03-19 21:21:41 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2023-03-19 21:21:41 +0100
commitd74ecf74a6026d43d2dfe611df14c19833e6cc83 (patch)
treed98d024db7718b84172678dd528b2d09ae56e04f /sw
parente04fec33f079db4c5d42aa412f7b670784ec1b68 (diff)
downloadpicardy-d74ecf74a6026d43d2dfe611df14c19833e6cc83.tar.gz
picardy-d74ecf74a6026d43d2dfe611df14c19833e6cc83.tar.bz2
picardy-d74ecf74a6026d43d2dfe611df14c19833e6cc83.zip
Fix WSPR transmitter, support centihz freq
Diffstat (limited to 'sw')
-rw-r--r--sw/eval-clock-cw-tx/src/main.rs5
-rw-r--r--sw/eval-clock-cw-tx/trigger.py45
-rw-r--r--sw/picardy/src/main.rs4
-rw-r--r--sw/picardy/src/si_clock.rs36
4 files changed, 71 insertions, 19 deletions
diff --git a/sw/eval-clock-cw-tx/src/main.rs b/sw/eval-clock-cw-tx/src/main.rs
index 52193b4..c303416 100644
--- a/sw/eval-clock-cw-tx/src/main.rs
+++ b/sw/eval-clock-cw-tx/src/main.rs
@@ -273,6 +273,11 @@ fn main() -> ! {
}
},
Mode::WSPR => {
+ if let Some(f) = usb.take_frequency() {
+ shared.state.set_vfo(f);
+ update_siclock_required = true;
+ }
+
if shared.state.wspr_freq_offset_updated {
update_siclock_required = true;
}
diff --git a/sw/eval-clock-cw-tx/trigger.py b/sw/eval-clock-cw-tx/trigger.py
new file mode 100644
index 0000000..a2b3657
--- /dev/null
+++ b/sw/eval-clock-cw-tx/trigger.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+import sys
+import requests
+import serial
+import random
+import datetime
+import time
+
+battery_capacity = requests.get("http://wollinuc.local:5000/stats").json()['capa']
+
+def eat(ser):
+ time.sleep(1)
+ received = []
+ while True:
+ dat = ser.read(1)
+ if dat:
+ received.append(dat)
+ else:
+ break
+ return b''.join(received)
+
+now = datetime.datetime.utcnow()
+
+#this script gets called every hour at minutes 13,27,39,53
+
+if battery_capacity < 6000:
+ print(f"Bat cap not enough: {battery_capacity}")
+elif battery_capacity < 10000 and now.minute != 13:
+ print(f"Bat cap not low: {battery_capacity}")
+else:
+ tx_freq = 10138700 + 400 + random.randint(1410, 1490)
+ print(f"TX freq {tx_freq}")
+ serial = serial.Serial("/dev/serial/by-id/usb-HB9EGM_Beep_Machine_1-if00", 115200, timeout=0)
+ serial.write('f{}\n'.format(tx_freq).encode("ascii"))
+ print(f"Answer: {eat(serial)}")
+
+ while True:
+ now = datetime.datetime.utcnow()
+ if now.minute % 2 == 0 and now.second == 00:
+ break
+ time.sleep(0.1)
+
+ print(f"{now} TX")
+ serial.write(b'wspr\n')
+ print(f"Answer: {eat(serial)}")
diff --git a/sw/picardy/src/main.rs b/sw/picardy/src/main.rs
index 3beefee..777b5c5 100644
--- a/sw/picardy/src/main.rs
+++ b/sw/picardy/src/main.rs
@@ -276,7 +276,7 @@ fn main() -> ! {
if require_bfo_update {
bfo_tune_fail = !siclock.set_bfo(state.bfo()).is_ok();
}
- siclock.set_vfo(state.vfo());
+ siclock.set_vfo_centihertz(state.vfo() * 100);
update_disp_required = true;
}
@@ -288,7 +288,7 @@ fn main() -> ! {
let vfo = state.vfo();
if previous_vfo != vfo {
- siclock.set_vfo(vfo);
+ siclock.set_vfo_centihertz(vfo * 100);
}
previous_vfo = vfo;
diff --git a/sw/picardy/src/si_clock.rs b/sw/picardy/src/si_clock.rs
index 6de4c25..4bd2686 100644
--- a/sw/picardy/src/si_clock.rs
+++ b/sw/picardy/src/si_clock.rs
@@ -1,7 +1,7 @@
/*
The MIT License (MIT)
- Copyright (c) 2020 Matthias P. Braendli
+ Copyright (c) 2023 Matthias P. Braendli
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -26,10 +26,10 @@ use core::convert::TryInto;
use si5351::{Si5351, Si5351Device};
use embedded_hal::blocking::i2c::{WriteRead, Write};
-const REF_CLOCK : u32 = 25_000_000;
+const REF_CLOCK_CHZ : u32 = 25_000_000 * 100;
const PLL_A_MULT : u32 = 32;
-fn gcd(x: u32, y: u32) -> u32 {
+fn gcd(x: u64, y: u64) -> u64 {
let mut x = x;
let mut y = y;
while y != 0 {
@@ -40,30 +40,32 @@ fn gcd(x: u32, y: u32) -> u32 {
x
}
-fn clock_settings_for_pll(freq: u32, pll: u32) -> (u16, u32, u32) {
+// All calculations in centihertz
+
+fn clock_settings_for_pll(freq: u64, pll: u64) -> (u16, u32, u32) {
let a = pll / freq;
let b = pll - (a * freq);
let gcd = gcd(b, freq);
let b = b / gcd;
let c = freq / gcd;
- (a.try_into().unwrap(), b, c)
+ (a.try_into().unwrap(), b.try_into().unwrap(), c.try_into().unwrap())
}
-fn clock_settings_with_pll_calculation(freq: u32) -> (u16, u8, u32, u32) {
- let mut divider : u32 = 900_000_000 / freq; // Calculate the division ratio. 900,000,000 is the maximum internal
+fn clock_settings_with_pll_calculation(freq_chz: u32) -> (u16, u8, u32, u32) {
+ let mut divider : u32 = (100*900_000_000u64 / freq_chz as u64).try_into().unwrap(); // Calculate the division ratio. 900,000,000 is the maximum internal
if (divider % 2) == 1 {
divider -= 1 // Ensure an even integer division ratio
}
- let pll_freq = divider * freq;
+ let pll_freq : u128 = divider as u128 * freq_chz as u128;
// mult is an integer that must be in the range 15..90
- let mult = pll_freq / REF_CLOCK;
- let l = pll_freq % REF_CLOCK;
+ let mult = pll_freq / (REF_CLOCK_CHZ as u128);
+ let l : u32 = (pll_freq % (REF_CLOCK_CHZ as u128)).try_into().unwrap();
let denom = 1048575;
- let num = f64::from(l) * f64::from(denom) / f64::from(REF_CLOCK);
+ let num = f64::from(l) * f64::from(denom) / f64::from(REF_CLOCK_CHZ);
(divider.try_into().unwrap(), mult.try_into().unwrap(), num as u32, denom)
}
@@ -74,7 +76,7 @@ fn set_bfo(siclock: &mut dyn Si5351, freq: u32) -> Result<(), si5351::Error>
siclock.set_clock_enabled(si5351::ClockOutput::Clk2, false);
}
else {
- let (a, b, c) = clock_settings_for_pll(freq, PLL_A_MULT * REF_CLOCK);
+ let (a, b, c) = clock_settings_for_pll(freq.into(), PLL_A_MULT as u64 * REF_CLOCK_CHZ as u64);
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);
@@ -82,7 +84,7 @@ fn set_bfo(siclock: &mut dyn Si5351, freq: u32) -> Result<(), si5351::Error>
siclock.flush_clock_control(si5351::ClockOutput::Clk2)
}
-fn set_vfo(siclock: &mut dyn Si5351, freq: u32)
+fn set_vfo_centihertz(siclock: &mut dyn Si5351, freq: u32)
{
if freq == 0 {
siclock.set_clock_enabled(si5351::ClockOutput::Clk0, false);
@@ -107,7 +109,7 @@ impl<I2C, E> SiClock<I2C>
I2C: WriteRead<Error = E> + Write<Error = E>,
{
pub fn new(i2c: I2C, bfo: u32, vfo: u32) -> SiClock<I2C> {
- let mut siclock = Si5351Device::new(i2c, false, REF_CLOCK);
+ let mut siclock = Si5351Device::new(i2c, false);
siclock.init(si5351::CrystalLoad::_10).unwrap();
// See freqplan.py for Si5351 frequency plan
@@ -118,7 +120,7 @@ impl<I2C, E> SiClock<I2C>
siclock.reset_pll(si5351::PLL::A).unwrap();
- set_vfo(&mut siclock, vfo);
+ set_vfo_centihertz(&mut siclock, vfo * 100);
siclock.reset_pll(si5351::PLL::B).unwrap();
@@ -127,8 +129,8 @@ impl<I2C, E> SiClock<I2C>
SiClock{siclock}
}
- pub fn set_vfo(&mut self, freq: u32) {
- set_vfo(&mut self.siclock, freq)
+ pub fn set_vfo_centihertz(&mut self, freq: u32) {
+ set_vfo_centihertz(&mut self.siclock, freq)
}
pub fn set_bfo(&mut self, freq: u32) -> Result<(), si5351::Error> {