Skip to content

Commit

Permalink
add st7789 driver, still a bit slow
Browse files Browse the repository at this point in the history
  • Loading branch information
NotQuiteApex committed Nov 19, 2024
1 parent 615f193 commit 5c00eb0
Show file tree
Hide file tree
Showing 9 changed files with 426 additions and 106 deletions.
2 changes: 2 additions & 0 deletions firmware/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion firmware/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ defmt-rtt = "0.4"
panic-probe = { version = "0.3", features = ["print-defmt"] }
rp-pico = "0.9"
usb-device = "0.3.2"
# usbd-hid = "0.8.2"
usbd-human-interface-device = { version = "0.5.0" }
usbd-serial = "0.2.2"
rp2040-flash = "0.5.1"
Expand All @@ -22,6 +21,8 @@ smart-leds = "0.4.0"
smart-leds-trait = "0.2.1"
itertools = { version = "0.13.0", default-features = false }
ringbuffer = { version = "0.15.0", default-features = false }
pio = "0.2.1"
nb = "1.1.0"


# cargo build/run
Expand Down
33 changes: 33 additions & 0 deletions firmware/src/color.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
pub fn hsv2rgb(hue: f32, sat: f32, val: f32) -> (u8, u8, u8) {
let c = val * sat;
let v = (hue / 60.0) % 2.0 - 1.0;
let v = if v < 0.0 { -v } else { v };
let x = c * (1.0 - v);
let m = val - c;
let (r, g, b) = if hue < 60.0 {
(c, x, 0.0)
} else if hue < 120.0 {
(x, c, 0.0)
} else if hue < 180.0 {
(0.0, c, x)
} else if hue < 240.0 {
(0.0, x, c)
} else if hue < 300.0 {
(x, 0.0, c)
} else {
(c, 0.0, x)
};

let r = ((r + m) * 255.0) as u8;
let g = ((g + m) * 255.0) as u8;
let b = ((b + m) * 255.0) as u8;

(r, g, b)
}

pub fn rgb565(r: u8, g: u8, b: u8) -> u16 {
let r = ((r as u16) & 0b11111000) << 8;
let g = ((g as u16) & 0b11111100) << 3;
let b = (b as u16) >> 3;
r | g | b
}
153 changes: 87 additions & 66 deletions firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
#![no_std]
#![no_main]

mod color;
mod mutex;
mod peripheral;
mod pins;
mod st7789;
mod uid;
mod modules {
pub mod keyboard;
Expand Down Expand Up @@ -35,6 +37,7 @@ use rp_pico::hal::{
Clock, Timer,
};
use rp_pico::{entry, Pins};
use st7789::St7789;
use ws2812_pio::Ws2812;

use usb_device::{class_prelude::*, prelude::*};
Expand All @@ -50,7 +53,7 @@ use usbd_serial::SerialPort;
use defmt::*;
use defmt_rtt as _;

static mut CORE1_STACK: Stack<2048> = Stack::new();
static mut CORE1_STACK: Stack<8192> = Stack::new();

// inter-core mutexes
static CONNECTED_PERIPHERALS: Mutex<0, JBPeripherals> = Mutex::new(JBPeripherals::default());
Expand Down Expand Up @@ -117,84 +120,102 @@ fn main() -> ! {
let mut serial_mod = serial::SerialMod::new(timer.count_down());

// core 1 event loop (GPIO)
let _ = core1.spawn(unsafe { &mut CORE1_STACK.mem }, move || {
let mut pac = unsafe { Peripherals::steal() };
let pins = Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
core1
.spawn(unsafe { &mut CORE1_STACK.mem }, move || {
let mut pac = unsafe { Peripherals::steal() };
let pins = Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);

// set up GPIO
let (kb_col_pins, kb_row_pins, led_pin, rgb_pin) = pins::configure_gpio(pins);
// set up GPIO
let (kb_col_pins, kb_row_pins, led_pin, rgb_pin, screen_pins) =
pins::configure_gpio(pins);

let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
let ws = Ws2812::new(
rgb_pin,
&mut pio,
sm0,
clocks.peripheral_clock.freq(),
timer.count_down(),
);
let (mut pio0, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
let ws = Ws2812::new(
rgb_pin,
&mut pio0,
sm0,
clocks.peripheral_clock.freq(),
timer.count_down(),
);

// set up modules
let mut keyboard_mod =
keyboard::KeyboardMod::new(kb_col_pins, kb_row_pins, timer.count_down());
let (mut pio1, _, sm1, _, _) = pac.PIO1.split(&mut pac.RESETS);
let mut st = St7789::new(
&mut pio1,
sm1,
screen_pins.0,
screen_pins.1,
screen_pins.2,
screen_pins.3,
screen_pins.4,
screen_pins.5,
timer.count_down(),
);
st.init();

let mut led_mod = led::LedMod::new(led_pin, timer.count_down());
let mut rgb_mod = rgb::RgbMod::new(ws, timer.count_down());
let mut screen_mod = screen::ScreenMod::new(timer.count_down());
// set up modules
let mut keyboard_mod =
keyboard::KeyboardMod::new(kb_col_pins, kb_row_pins, timer.count_down());

loop {
// update input devices
keyboard_mod.update();
let mut led_mod = led::LedMod::new(led_pin, timer.count_down());
let mut rgb_mod = rgb::RgbMod::new(ws, timer.count_down());
let mut screen_mod = screen::ScreenMod::new(st, timer.count_down());

// update mutexes
CONNECTED_PERIPHERALS.with_mut_lock(|c| {
c.keyboard = Connection::Connected;
});
PERIPHERAL_INPUTS.with_mut_lock(|i| {
let keys = keyboard_mod.get_pressed_keys();
i.keyboard.key1 = keys[0].into();
i.keyboard.key2 = keys[1].into();
i.keyboard.key3 = keys[2].into();
i.keyboard.key4 = keys[3].into();
i.keyboard.key5 = keys[4].into();
i.keyboard.key6 = keys[5].into();
i.keyboard.key7 = keys[6].into();
i.keyboard.key8 = keys[7].into();
i.keyboard.key9 = keys[8].into();
i.keyboard.key10 = keys[9].into();
i.keyboard.key11 = keys[10].into();
i.keyboard.key12 = keys[11].into();
});
loop {
// update input devices
keyboard_mod.update();

// check if we need to shutdown "cleanly" for update
UPDATE_TRIGGER.with_lock(|u| {
if *u {
led_mod.clear();
rgb_mod.clear();
screen_mod.clear();
// update mutexes
CONNECTED_PERIPHERALS.with_mut_lock(|c| {
c.keyboard = Connection::Connected;
});
PERIPHERAL_INPUTS.with_mut_lock(|i| {
let keys = keyboard_mod.get_pressed_keys();
i.keyboard.key1 = keys[0].into();
i.keyboard.key2 = keys[1].into();
i.keyboard.key3 = keys[2].into();
i.keyboard.key4 = keys[3].into();
i.keyboard.key5 = keys[4].into();
i.keyboard.key6 = keys[5].into();
i.keyboard.key7 = keys[6].into();
i.keyboard.key8 = keys[7].into();
i.keyboard.key9 = keys[8].into();
i.keyboard.key10 = keys[9].into();
i.keyboard.key11 = keys[10].into();
i.keyboard.key12 = keys[11].into();
});

// wait a few cycles for the IO to finish
for _ in 0..100 {
cortex_m::asm::nop();
}
// check if we need to shutdown "cleanly" for update
UPDATE_TRIGGER.with_lock(|u| {
if *u {
led_mod.clear();
rgb_mod.clear();
screen_mod.clear();

reset_to_usb_boot(0, 0);
}
});
// wait a few cycles for the IO to finish
for _ in 0..200 {
cortex_m::asm::nop();
}

// update accessories
led_mod.update();
rgb_mod.update(timer.get_counter());
screen_mod.update();
}
});
reset_to_usb_boot(0, 0);
}
});

// update accessories
led_mod.update();
rgb_mod.update(timer.get_counter());
screen_mod.update(timer.get_counter(), &timer);
}
})
.expect("failed to start core1");

// main event loop (USB comms)
loop {
// info!("help 0");
// tick for hid devices
if hid_tick.wait().is_ok() {
// handle keyboard
Expand Down
35 changes: 5 additions & 30 deletions firmware/src/modules/rgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ use smart_leds::brightness;
use smart_leds_trait::{SmartLedsWrite, RGB8};
use ws2812_pio::Ws2812;

use crate::color::hsv2rgb;

const RGB_LEN: usize = 12;
const FRAME_TIME: u32 = 33;

pub struct RgbMod<'timer> {
ws: Ws2812<PIO0, SM0, CountDown<'timer>, Pin<DynPinId, FunctionPio0, PullDown>>,
brightness: u8,
buffer: [RGB8; RGB_LEN],
frame_timer: CountDown<'timer>,
timer: CountDown<'timer>,
}

impl<'timer> RgbMod<'timer> {
Expand All @@ -35,7 +37,7 @@ impl<'timer> RgbMod<'timer> {
ws: ws,
brightness: 10,
buffer: [(0, 0, 0).into(); RGB_LEN],
frame_timer: count_down,
timer: count_down,
}
}

Expand All @@ -48,7 +50,7 @@ impl<'timer> RgbMod<'timer> {
}

pub fn update(&mut self, t: Instant) {
if !self.frame_timer.wait().is_ok() {
if !self.timer.wait().is_ok() {
return;
}

Expand All @@ -63,30 +65,3 @@ impl<'timer> RgbMod<'timer> {
.unwrap();
}
}

pub fn hsv2rgb(hue: f32, sat: f32, val: f32) -> (u8, u8, u8) {
let c = val * sat;
let v = (hue / 60.0) % 2.0 - 1.0;
let v = if v < 0.0 { -v } else { v };
let x = c * (1.0 - v);
let m = val - c;
let (r, g, b) = if hue < 60.0 {
(c, x, 0.0)
} else if hue < 120.0 {
(x, c, 0.0)
} else if hue < 180.0 {
(0.0, c, x)
} else if hue < 240.0 {
(0.0, x, c)
} else if hue < 300.0 {
(x, 0.0, c)
} else {
(c, 0.0, x)
};

let r = ((r + m) * 255.0) as u8;
let g = ((g + m) * 255.0) as u8;
let b = ((b + m) * 255.0) as u8;

(r, g, b)
}
56 changes: 50 additions & 6 deletions firmware/src/modules/screen.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,66 @@
//! Screen for fun graphics
use defmt::info;
use embedded_hal::timer::CountDown as _;
use rp_pico::hal::{fugit::ExtU32, timer::CountDown};
use rp_pico::{
hal::{
fugit::ExtU32,
gpio::{DynPinId, FunctionPio1, Pin, PullDown},
pio::SM1,
timer::{CountDown, Instant},
Timer,
},
pac::PIO1,
};

const REFRESH_RATE: u32 = 33;
use crate::{
color::{hsv2rgb, rgb565},
st7789::St7789,
};

const REFRESH_RATE: u32 = 50;

pub struct ScreenMod<'timer> {
st: St7789<'timer, PIO1, SM1, Pin<DynPinId, FunctionPio1, PullDown>>,
timer: CountDown<'timer>,
}

impl<'timer> ScreenMod<'timer> {
pub fn new(mut count_down: CountDown<'timer>) -> Self {
pub fn new(
st: St7789<'timer, PIO1, SM1, Pin<DynPinId, FunctionPio1, PullDown>>,
mut count_down: CountDown<'timer>,
) -> Self {
count_down.start(REFRESH_RATE.millis());

ScreenMod { timer: count_down }
ScreenMod {
st: st,
timer: count_down,
}
}

pub fn clear(&mut self) {
self.st.clear_framebuffer();
self.st.push_framebuffer();
self.st.backlight_off();
}

pub fn clear(&mut self) {}
pub fn update(&mut self, t: Instant, timer: &Timer) {
if !self.timer.wait().is_ok() {
return;
}

let t = ((t.duration_since_epoch().ticks() >> 15) % 360) as f32;
let rgb = hsv2rgb(t, 1.0, 1.0);
let rgb = rgb565(rgb.0, rgb.1, rgb.2);

pub fn update(&mut self) {}
// let time_start = timer.get_counter();
self.st.fill_framebuffer(rgb);
// let elapse1 = (timer.get_counter() - time_start).to_micros();

// let time_start = timer.get_counter();
self.st.push_framebuffer();
// let elapse2 = (timer.get_counter() - time_start).to_micros();

// info!("times: fill-fb={}us, write-fb={}us", elapse1, elapse2);
}
}
Loading

0 comments on commit 5c00eb0

Please sign in to comment.