Compare commits

...

2 Commits

Author SHA1 Message Date
JP Stringham
3bad1b474f HUGE FIX for frequency setting 2026-02-13 23:08:16 -05:00
JP Stringham
9e862774cb lol I am very dumb saturating add on tick instead of wrapping 2026-02-12 21:23:35 -05:00
4 changed files with 108 additions and 57 deletions

View File

@@ -32,7 +32,7 @@ rustflags = [
# This runner will find a supported SWD debug probe and flash your RP2040 over # This runner will find a supported SWD debug probe and flash your RP2040 over
# SWD: # SWD:
runner = "probe-rs run --chip RP2040 --protocol swd" runner = "probe-rs run --chip RP2040 --protocol swd --speed 150"
[env] [env]
DEFMT_RTT_BUFFER_SIZE = { value = "4096", force = true } DEFMT_RTT_BUFFER_SIZE = { value = "4096", force = true }

4
Cargo.lock generated
View File

@@ -586,9 +586,9 @@ checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.22" version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e"
[[package]] [[package]]
name = "usb-device" name = "usb-device"

View File

@@ -7,7 +7,7 @@ edition = "2024"
cortex-m = { version = "0.7.7", features = [ "critical-section-single-core" ] } cortex-m = { version = "0.7.7", features = [ "critical-section-single-core" ] }
cortex-m-rt = "0.7.5" cortex-m-rt = "0.7.5"
defmt = "1.0.1" defmt = "1.0.1"
defmt-rtt = "1.0.0" defmt-rtt = "1.1.0"
embedded-hal = "1.0.0" embedded-hal = "1.0.0"
panic-probe = { version = "1.0.0", features = [ "print-rtt" ]} panic-probe = { version = "1.0.0", features = [ "print-rtt" ]}
rp2040-boot2 = "0.3.0" rp2040-boot2 = "0.3.0"

View File

@@ -2,33 +2,31 @@
#![no_main] #![no_main]
use cortex_m::prelude::_embedded_hal_PwmPin; use cortex_m::prelude::_embedded_hal_PwmPin;
use defmt::info;
use defmt::{println, write};
use defmt::info;
use defmt::println;
use defmt_rtt as _; use defmt_rtt as _;
use panic_probe as _; use panic_probe as _;
use rp2040_hal::pll::PLLConfig;
use rp2040_hal::pll::common_configs::PLL_USB_48MHZ;
// Alias for our HAL crate // Alias for our HAL crate
use rp2040_hal as hal; use rp2040_hal as hal;
// A shorter alias for the Peripheral Access Crate, which provides low-level
// register access
use hal::fugit::RateExtU32; use hal::fugit::RateExtU32;
use hal::pac; use hal::pac;
// Some traits we need use embedded_hal::digital::InputPin;
use embedded_hal::digital::OutputPin; use embedded_hal::digital::OutputPin;
use embedded_hal::digital::{InputPin, StatefulOutputPin};
use sh1106_pico_rs::graphics::GraphicsBuf; use sh1106_pico_rs::graphics::GraphicsBuf;
use sh1106_pico_rs::sh1106::SH1106Dev; use sh1106_pico_rs::sh1106::SH1106Dev;
/// The linker will place this boot block at the start of our program image. We /// NB if OVERCLOCKING
/// need this to help the ROM bootloader get our code up and running. /// you MUST use a BOOT_LOADER which can tolerate the OC
/// Note: This boot block is not necessary when using a rp-hal based BSP /// the GENERIC_03H one cannot (unsure why) but W25Q080 has been solid for me
/// as the BSPs already perform this step.
#[unsafe(link_section = ".boot_loader")] #[unsafe(link_section = ".boot_loader")]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_GENERIC_03H; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust /// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
/// if your board has a different frequency /// if your board has a different frequency
@@ -41,21 +39,51 @@ fn main() -> ! {
let core = pac::CorePeripherals::take().unwrap(); let core = pac::CorePeripherals::take().unwrap();
// Set up the watchdog driver - needed by the clock setup code // Set up the watchdog driver - needed by the clock setup code
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG); // let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
hal::vreg::set_voltage(
&mut pac.VREG_AND_CHIP_RESET,
pac::vreg_and_chip_reset::vreg::VSEL_A::VOLTAGE1_30,
);
// settle
// cortex_m::asm::delay(3_000_000);
let xosc = hal::xosc::setup_xosc_blocking_custom_delay(pac.XOSC, XTAL_FREQ_HZ.Hz(), 128)
.map_err(|_x| false)
.unwrap();
// watchdog.enable_tick_generation((XTAL_FREQ_HZ / 1_000_000) as u8);
// Configure the clocks // Configure the clocks
let clocks = hal::clocks::init_clocks_and_plls( let mut clocks = hal::clocks::ClocksManager::new(pac.CLOCKS);
XTAL_FREQ_HZ,
pac.XOSC, let pll_usb = rp2040_hal::pll::setup_pll_blocking(
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB, pac.PLL_USB,
xosc.operating_frequency(),
PLL_USB_48MHZ,
&mut clocks,
&mut pac.RESETS, &mut pac.RESETS,
&mut watchdog,
) )
.unwrap(); .unwrap();
let mut delay = cortex_m::delay::Delay::new(core.SYST, 133_000_000u32); let pll_sys = hal::pll::setup_pll_blocking(
pac.PLL_SYS,
xosc.operating_frequency(),
PLLConfig {
vco_freq: 1500.MHz(),
refdiv: 1,
post_div1: 5,
post_div2: 1,
},
&mut clocks,
&mut pac.RESETS,
)
.unwrap();
clocks.init_default(&xosc, &pll_sys, &pll_usb).unwrap();
// let mut delay = cortex_m::delay::Delay::new(core.SYST, 200_000_000);
// The single-cycle I/O block controls our GPIO pins // The single-cycle I/O block controls our GPIO pins
let sio = hal::Sio::new(pac.SIO); let sio = hal::Sio::new(pac.SIO);
@@ -67,14 +95,6 @@ fn main() -> ! {
&mut pac.RESETS, &mut pac.RESETS,
); );
let mut adc = hal::Adc::new(pac.ADC, &mut pac.RESETS);
let mut adc_pin = hal::adc::AdcPin::new(pins.gpio26.into_floating_input()).unwrap();
let mut adc_fifo = adc
.build_fifo()
.set_channel(&mut adc_pin)
.clock_divider(47999, 0)
.start_paused();
let mut led_pin = pins.gpio25.into_push_pull_output(); let mut led_pin = pins.gpio25.into_push_pull_output();
led_pin.set_high(); led_pin.set_high();
@@ -83,11 +103,15 @@ fn main() -> ! {
// Configure PWM0 // Configure PWM0
let pwm0 = &mut pwm_slices.pwm0; let pwm0 = &mut pwm_slices.pwm0;
pwm0.set_ph_correct(); pwm0.clr_ph_correct();
pwm0.set_div_int(1);
pwm0.set_div_frac(0); pwm0.set_div_frac(0);
pwm0.disable(); pwm0.clear_interrupt();
pwm0.enable();
pwm0.channel_a.output_to(pins.gpio16); let mut pwm_pin = pins.gpio16;
pwm_pin.set_drive_strength(rp2040_hal::gpio::OutputDriveStrength::TwelveMilliAmps);
pwm0.channel_a.output_to(pwm_pin);
let mut on_off_input = pins.gpio15.into_pull_up_input(); let mut on_off_input = pins.gpio15.into_pull_up_input();
@@ -99,13 +123,12 @@ fn main() -> ! {
let mut broadcast_on = false; let mut broadcast_on = false;
let mut current_tune = 12; let mut current_tune = 10;
const MAX_TUNE: u16 = 350u16; const MAX_TUNE: u16 = 350u16;
const MIN_TUNE: u16 = 4u16; const MIN_TUNE: u16 = 4u16;
pwm0.set_top(current_tune); set_tune(current_tune, pwm0);
pwm0.channel_a.set_duty(current_tune / 2);
// Create the I²C drive // Create the I²C drive
let mut i2c = hal::I2C::i2c0( let mut i2c = hal::I2C::i2c0(
@@ -117,30 +140,36 @@ fn main() -> ! {
&clocks.system_clock, &clocks.system_clock,
); );
let mut delay = cortex_m::delay::Delay::new(core.SYST, 200_000);
let mut sh1106_dev = SH1106Dev::new(&mut delay, &mut i2c); let mut sh1106_dev = SH1106Dev::new(&mut delay, &mut i2c);
sh1106_dev.set_vertical_flip(&mut i2c, true); sh1106_dev.set_vertical_flip(&mut i2c, true);
let sh1106_dev = sh1106_dev; let sh1106_dev = sh1106_dev;
let mut gfx_buf = GraphicsBuf::new(); let mut gfx_buf = GraphicsBuf::new();
let mut last_gfx_update = 0u32; let mut last_gfx_update = 0u32;
// Infinite loop, fading LED up and down
loop { loop {
tick = tick.saturating_add(1); tick = tick.wrapping_add(1);
if tick.wrapping_sub(last_gfx_update) > 1_000_000 { if tick.wrapping_sub(last_gfx_update) > 500_000 {
gfx_buf.clear(); gfx_buf.clear();
gfx_buf.draw_string(20, 14, "Hello Radio!"); gfx_buf.draw_string(20, 14, "Hello Radio!");
let tuned_freq = 125_000u32 / (current_tune * 2) as u32; let tuned_freq = 300_000 / (current_tune as u32);
let mut tune_str_buf = [0u8; 5]; let mut tune_str_buf = [0u8; 5];
u16_into_str(tuned_freq as u16, &mut tune_str_buf); let len = u32_into_str(tuned_freq, &mut tune_str_buf);
let tune_str = str::from_utf8(&tune_str_buf).unwrap(); let tune_str = str::from_utf8(&tune_str_buf[tune_str_buf.len() - len..]).unwrap();
info!("{}, {}", tune_str, tune_str.len()); // info!("val {}, len {}", tuned_freq, len);
// info!("{}, {}", tune_str, tune_str.len());
gfx_buf.draw_string(20, 28, tune_str); gfx_buf.draw_string(20, 28, tune_str);
gfx_buf.sprites[0].y = match gfx_buf.sprites[0].y {
32 => 33,
_ => 32,
};
u16_into_str(current_tune, &mut tune_str_buf); let len = u32_into_str(current_tune as u32, &mut tune_str_buf);
let tune_str = str::from_utf8(&tune_str_buf).unwrap(); let tune_str = str::from_utf8(&tune_str_buf[tune_str_buf.len() - len..]).unwrap();
// info!("len {}", len);
gfx_buf.draw_string(64, 28, tune_str); gfx_buf.draw_string(64, 28, tune_str);
@@ -159,6 +188,7 @@ fn main() -> ! {
} }
if on_off_input.is_low().unwrap() { if on_off_input.is_low().unwrap() {
info!("Broadcast toggle");
last_input = tick; last_input = tick;
broadcast_on = !broadcast_on; broadcast_on = !broadcast_on;
@@ -170,26 +200,47 @@ fn main() -> ! {
} }
if tune_up_input.is_low().unwrap() { if tune_up_input.is_low().unwrap() {
info!("Tune DOWN");
last_input = tick; last_input = tick;
current_tune = MAX_TUNE.min(current_tune + 2); current_tune = MAX_TUNE.min(current_tune + 2);
pwm0.set_top(current_tune); set_tune(current_tune, pwm0);
pwm0.channel_a.set_duty(current_tune / 2);
continue; continue;
} }
if tune_dn_input.is_low().unwrap() { if tune_dn_input.is_low().unwrap() {
info!("Tune UP");
last_input = tick; last_input = tick;
current_tune = MIN_TUNE.max(current_tune - 2); current_tune = MIN_TUNE.max(current_tune - 2);
pwm0.set_top(current_tune); set_tune(current_tune, pwm0);
pwm0.channel_a.set_duty(current_tune / 2);
} }
} }
} }
fn u16_into_str(mut value: u16, str_buf: &mut [u8; 5]) { fn set_tune(
for i in 0..5 { tune: u16,
str_buf[4 - i] = b'0' + (value % 10) as u8; pwm: &mut rp2040_hal::pwm::Slice<rp2040_hal::pwm::Pwm0, rp2040_hal::pwm::FreeRunning>,
value /= 10; ) {
} pwm.set_top(tune - 1);
info!("utf8 buf {}", str_buf); pwm.channel_a.set_duty(tune / 2);
}
// returns the length of the final str removing leading zeroes
fn u32_into_str(mut value: u32, str_buf: &mut [u8]) -> usize {
let mut len = str_buf.len();
// info!("val {}", value);
for i in 0..len {
// info!("val {}, i {}, digit {}", value, i, value % 10);
str_buf[len - i - 1] = b'0' + (value % 10) as u8;
value /= 10;
if value <= 0 {
// info!("Ran out of digits at {}", i);
len = i + 1;
break;
}
}
// info!("utf8 buf {}, len {}", str_buf, len);
len
} }