Menus, pwm, led clock speeds oh my

This commit is contained in:
JP Stringham
2026-03-25 09:56:39 -04:00
parent d1f2bbd25e
commit b4307559e7
3 changed files with 177 additions and 54 deletions

View File

@@ -1,16 +1,12 @@
#![no_std]
#![no_main]
mod menu;
mod onboard_led;
use core::u16::MIN;
use cortex_m::prelude::_embedded_hal_PwmPin;
use defmt::info;
use defmt::println;
use defmt_rtt as _;
use embedded_hal::digital::StatefulOutputPin;
use panic_probe as _;
use rp2040_hal::clocks::ClockSource;
@@ -21,7 +17,6 @@ use rp2040_hal::gpio::FunctionSioOutput;
use rp2040_hal::gpio::Pin;
use rp2040_hal::gpio::PullDown;
use rp2040_hal::gpio::PullNone;
use rp2040_hal::pll;
use rp2040_hal::pll::PLLConfig;
use rp2040_hal::pll::common_configs::PLL_USB_48MHZ;
// Alias for our HAL crate
@@ -35,6 +30,7 @@ use embedded_hal::digital::OutputPin;
use sh1106_pico_rs::graphics::GraphicsBuf;
use sh1106_pico_rs::sh1106::SH1106Dev;
use crate::menu::Menu;
use crate::onboard_led::OnboardLed;
/// NB if OVERCLOCKING
@@ -95,10 +91,10 @@ fn main() -> ! {
pac.PLL_SYS,
xosc.operating_frequency(),
PLLConfig {
vco_freq: 1500.MHz(),
vco_freq: 1600.MHz(),
refdiv: 1,
post_div1: 5,
post_div2: 3,
post_div1: 4,
post_div2: 2,
},
&mut clocks,
&mut pac.RESETS,
@@ -125,21 +121,27 @@ fn main() -> ! {
// Init PWMs
let mut pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
let mut div_int = 1;
// Configure PWM0
let pwm = &mut pwm_slices.pwm7;
pwm.set_ph_correct();
pwm.set_div_int(20);
let pwm = &mut pwm_slices.pwm3;
pwm.clr_ph_correct();
pwm.set_div_int(div_int);
pwm.set_div_frac(0);
pwm.clear_interrupt();
pwm.enable();
// let mut pwm_pin = pins.gpio15;
// pwm_pin.set_drive_strength(rp2040_hal::gpio::OutputDriveStrength::TwelveMilliAmps);
// pwm.channel_b.output_to(pwm_pin);
let mut sink = pins.gpio5.into_push_pull_output();
sink.set_low();
sink.set_drive_strength(rp2040_hal::gpio::OutputDriveStrength::TwelveMilliAmps);
let mut sink = pins.gpio7.into_push_pull_output();
sink.set_low();
sink.set_drive_strength(rp2040_hal::gpio::OutputDriveStrength::TwelveMilliAmps);
let mut pwm_pin = pins.gpio6;
pwm_pin.set_drive_strength(rp2040_hal::gpio::OutputDriveStrength::TwoMilliAmps);
pwm.channel_a.output_to(pwm_pin);
// let mut duty = 0;
// pwm.set_top(50000);
// pwm.channel_a.set_duty(duty);
pwm.set_top(3);
pwm.channel_a.set_duty(2);
// let mut on_off_input = pins.gpio15.into_pull_up_input();
@@ -165,16 +167,25 @@ fn main() -> ! {
let sh1106_dev = sh1106_dev;
let mut gfx_buf = GraphicsBuf::new();
gfx_buf.sprites[0].x = 114;
gfx_buf.sprites[0].y = 40;
gfx_buf.sprites[0].x = 60;
gfx_buf.clear();
gfx_buf.redraw();
let mut str_buf = [0u8; 12];
let str_len = u32_into_str(pll_freq.to_kHz(), &mut str_buf);
let khz_str = str::from_utf8(&str_buf[str_buf.len() - str_len..]).unwrap();
gfx_buf.draw_string(18, 20, "Booted at: ");
gfx_buf.draw_string(78, 20, khz_str);
gfx_buf.draw_string(78 + (6 * str_len as u8), 20, "kHz");
sh1106_dev.blit_framebuffer(&mut i2c, &gfx_buf);
let mut tick: u32 = 0;
let mut led = OnboardLed::new(pins.gpio16.into_push_pull_output().into_dyn_pin());
let mut led = OnboardLed::new(pll_freq, pins.gpio16.into_push_pull_output().into_dyn_pin());
println!("Booted at {}MHz", pll_freq.to_MHz());
println!("PWM at {}Hz", pll_freq.to_Hz() / (20 * 2 * 50000));
@@ -183,48 +194,103 @@ fn main() -> ! {
let mut g = 0u8;
let mut b = 0u8;
const ON_VALUE: u8 = 64;
loop {
if enter_input.is_low().unwrap() {
break;
}
}
let mut menu = Menu::new();
menu.add_item("Int Div Up");
menu.add_item("Int Div Down");
menu.add_item("Chichi");
menu.add_item("Nyaoha");
let menu = menu;
let mut cursor_pos = 0;
let mut cur_selection = 0;
gfx_buf.sprites[1].visible = true;
gfx_buf.sprites[1].x = 10;
gfx_buf.sprites[1].y = 12;
loop {
tick = tick.wrapping_add(1);
let i = (tick % 144) as usize;
// let r = WAVE_TABLE[i] / 2;
// let g = WAVE_TABLE[(i + 48) % 128] / 2;
// let b = WAVE_TABLE[(i + 96) % 128] / 2;
// led.set_color(r, g, b);
// match i {
// ..48 => led.set_color(128, 0, 0),
// 48..96 => led.set_color(0, 128, 0),
// _ => led.set_color(0, 0, 128),
// }
cortex_m::asm::delay(10_000_000);
if left_input.is_low().unwrap() {
r = match r {
ON_VALUE => 0,
_ => ON_VALUE,
}
}
cortex_m::asm::delay(5_000_000);
if right_input.is_low().unwrap() {
g = match g {
ON_VALUE => 0,
_ => ON_VALUE,
cursor_pos -= 1;
if cursor_pos < 0 {
cursor_pos = 3;
}
}
if left_input.is_low().unwrap() {
cursor_pos = (cursor_pos + 1) % 4;
}
if enter_input.is_low().unwrap() {
b = match b {
ON_VALUE => 0,
_ => ON_VALUE,
cur_selection = cursor_pos;
match cur_selection {
0 => {
div_int = 1.max(div_int - 1);
pwm.set_div_int(div_int);
}
1 => {
div_int = div_int.saturating_add(1);
pwm.set_div_int(div_int);
}
_ => (),
}
}
match cur_selection {
0 => {
let i = (tick % 144) as usize;
r = WAVE_TABLE[i % 128] / 8;
g = WAVE_TABLE[(i + 48) % 128] / 8;
b = WAVE_TABLE[(i + 96) % 128] / 8;
}
1 => {
r = 64;
g = 0;
b = 0;
}
2 => {
r = 0;
g = 64;
b = 0;
}
3 => {
r = 0;
g = 0;
b = 64;
}
_ => panic!("Shouldn't be able to select beyond menu"),
}
led.set_color(r, g, b);
gfx_buf.clear();
gfx_buf.redraw();
let mut y = 10;
menu.get_menu_items().for_each(|mi| {
gfx_buf.draw_string(20, y, mi.get_name());
y += 12;
});
gfx_buf.sprites[0].y = cursor_pos * 12 + 10;
gfx_buf.sprites[1].y = cur_selection * 12 + 10;
let cur_menu_item = menu.get_item(cursor_pos as usize).unwrap();
gfx_buf.sprites[0].x = (gfx_buf.get_string_px_length(cur_menu_item.get_name()) + 28) as i32;
sh1106_dev.blit_framebuffer(&mut i2c, &gfx_buf);
// pwm.channel_a.set_duty(duty);
// gfx_buf.clear();

49
src/menu.rs Normal file
View File

@@ -0,0 +1,49 @@
pub struct Menu {
items: [Option<MenuItem>; 8],
}
impl Menu {
pub fn new() -> Self {
Self { items: [None; 8] }
}
pub fn add_item(&mut self, name: &str) {
let Some(empty_slot) = self.items.iter_mut().find(|mi| mi.is_none()) else {
return;
};
*empty_slot = Some(MenuItem::new(name));
}
pub fn get_menu_items(&self) -> impl Iterator<Item = MenuItem> {
self.items.iter().filter_map(|omi| omi.clone())
}
pub fn get_item(&self, index: usize) -> Option<MenuItem> {
self.items[index]
}
}
#[derive(Clone, Copy)]
pub struct MenuItem {
name_buf: [u8; 20],
name_len: usize,
}
impl MenuItem {
pub fn new(name: &str) -> Self {
let mut name_buf = [0u8; 20];
let copy_len = name.len().min(20);
name_buf[0..copy_len].copy_from_slice(&name.as_bytes()[0..copy_len]);
Self {
name_buf,
name_len: copy_len,
}
}
pub fn get_name(&self) -> &str {
str::from_utf8(&self.name_buf[0..self.name_len]).unwrap()
}
}

View File

@@ -1,13 +1,18 @@
use cortex_m::asm::nop;
use embedded_hal::digital::OutputPin;
use rp2040_hal::gpio::{DynPinId, FunctionSioOutput, Pin, PullDown};
use rp2040_hal::{
fugit::HertzU32,
gpio::{DynPinId, FunctionSioOutput, Pin, PullDown},
};
pub struct OnboardLed {
pll_freq: HertzU32,
led_pin: Pin<DynPinId, FunctionSioOutput, PullDown>,
}
impl OnboardLed {
pub fn new(led_pin: Pin<DynPinId, FunctionSioOutput, PullDown>) -> Self {
Self { led_pin }
pub fn new(pll_freq: HertzU32, led_pin: Pin<DynPinId, FunctionSioOutput, PullDown>) -> Self {
Self { pll_freq, led_pin }
}
pub fn set_color(&mut self, r: u8, g: u8, b: u8) {
@@ -20,17 +25,20 @@ impl OnboardLed {
for i in 0..24 {
let bit = color & (0x1 << (23 - i));
let nop_count = self.pll_freq.to_Hz() / 50_000_000;
self.led_pin.set_high().unwrap();
if bit == 0 {
for _ in 0..nop_count {
cortex_m::asm::nop();
cortex_m::asm::nop();
cortex_m::asm::nop();
}
} else {
cortex_m::asm::delay(60);
cortex_m::asm::delay(60 * nop_count);
}
self.led_pin.set_low().unwrap();
cortex_m::asm::delay(35);
cortex_m::asm::delay(35 * nop_count);
}
}
}