Menus, pwm, led clock speeds oh my
This commit is contained in:
158
src/main.rs
158
src/main.rs
@@ -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);
|
||||
cortex_m::asm::delay(5_000_000);
|
||||
|
||||
// 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,
|
||||
if right_input.is_low().unwrap() {
|
||||
cursor_pos -= 1;
|
||||
if cursor_pos < 0 {
|
||||
cursor_pos = 3;
|
||||
}
|
||||
}
|
||||
|
||||
if right_input.is_low().unwrap() {
|
||||
g = match g {
|
||||
ON_VALUE => 0,
|
||||
_ => ON_VALUE,
|
||||
}
|
||||
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
49
src/menu.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
cortex_m::asm::nop();
|
||||
cortex_m::asm::nop();
|
||||
cortex_m::asm::nop();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user