Last active
December 29, 2023 07:17
-
-
Save P1n3appl3/9211f13325fcb11d80c039c3d631bf5c to your computer and use it in GitHub Desktop.
pi-pico screen latency tester
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "pi-pico-keyboard" | |
version = "0.1.0" | |
edition = "2021" | |
[dependencies] | |
usb-device = "0.2" | |
usbd-hid = "0.6" | |
critical-section = "1" | |
cortex-m = "0.7" | |
cortex-m-rt = "0.7" | |
embedded-hal = "0.2" | |
panic-halt = "0.2" | |
rp-pico = "0.8" | |
rp2040-hal = "0.9" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[build] | |
target = "thumbv6m-none-eabi" | |
rustflags = ["-Clink-arg=--nmagic", "-Clink-arg=-Tlink.x"] | |
[target.thumbv6m-none-eabi] | |
runner = "elf2uf2-rs -d" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![no_std] | |
#![no_main] | |
use embedded_hal::digital::v2::OutputPin; | |
use hal::{ | |
clocks::UsbClock, | |
gpio, | |
pac::{self, interrupt, Interrupt, RESETS}, | |
prelude::*, | |
usb::UsbBus, | |
}; | |
use panic_halt as _; | |
use rp_pico::hal; | |
use usb_device::{class_prelude::*, prelude::*}; | |
use usbd_hid::{ | |
descriptor::{generator_prelude::*, KeyboardReport}, | |
hid_class::HIDClass, | |
}; | |
static mut USB_DEVICE: Option<UsbDevice<UsbBus>> = None; | |
static mut USB_BUS: Option<UsbBusAllocator<UsbBus>> = None; | |
static mut USB_HID: Option<HIDClass<UsbBus>> = None; | |
// safety: must call with interrupts disabled | |
unsafe fn init_usb( | |
ctrl: pac::USBCTRL_REGS, | |
dpram: pac::USBCTRL_DPRAM, | |
usb_clock: UsbClock, | |
resets: &mut RESETS, | |
) { | |
let usb_bus = UsbBusAllocator::new(UsbBus::new(ctrl, dpram, usb_clock, true, resets)); | |
// safety: we can mutate global statics since interrupts aren't enabled yet | |
let bus_ref = unsafe { | |
USB_BUS = Some(usb_bus); | |
USB_BUS.as_ref().unwrap() | |
}; | |
let usb_hid = HIDClass::new(bus_ref, KeyboardReport::desc(), 60); | |
// safety: interrupts still arent enabled | |
unsafe { | |
USB_HID = Some(usb_hid); | |
} | |
let usb_dev = UsbDeviceBuilder::new(bus_ref, UsbVidPid(0x03f0, 0x020c)) | |
.manufacturer("Pineapple") | |
.product("Press F") | |
.serial_number("TEST") | |
.device_class(0) | |
.build(); | |
// safety: interrupts still arent enabled | |
unsafe { | |
USB_DEVICE = Some(usb_dev); | |
} | |
} | |
type LedPin = gpio::bank0::Gpio25; | |
fn init_led( | |
sio: pac::SIO, | |
io_bank0: pac::IO_BANK0, | |
pads_bank0: pac::PADS_BANK0, | |
resets: &mut RESETS, | |
) -> gpio::Pin< | |
LedPin, | |
gpio::FunctionSio<gpio::SioOutput>, | |
<LedPin as gpio::DefaultTypeState>::PullType, | |
> { | |
let pins = | |
rp_pico::Pins::new(io_bank0, pads_bank0, hal::Sio::new(sio).gpio_bank0, resets); | |
pins.led.into_push_pull_output() | |
} | |
#[rp_pico::entry] | |
fn main() -> ! { | |
let mut periph = pac::Peripherals::take().unwrap(); | |
let mut watchdog = hal::Watchdog::new(periph.WATCHDOG); | |
let clocks = hal::clocks::init_clocks_and_plls( | |
rp_pico::XOSC_CRYSTAL_FREQ, | |
periph.XOSC, | |
periph.CLOCKS, | |
periph.PLL_SYS, | |
periph.PLL_USB, | |
&mut periph.RESETS, | |
&mut watchdog, | |
) | |
.ok() | |
.unwrap(); | |
// safety: after initializing the usb stuff nothing will mutate those statics outside of a | |
// critical section | |
unsafe { | |
init_usb( | |
periph.USBCTRL_REGS, | |
periph.USBCTRL_DPRAM, | |
clocks.usb_clock, | |
&mut periph.RESETS, | |
); | |
pac::NVIC::unmask(Interrupt::USBCTRL_IRQ); | |
} | |
let mut led_pin = | |
init_led(periph.SIO, periph.IO_BANK0, periph.PADS_BANK0, &mut periph.RESETS); | |
let core = pac::CorePeripherals::take().unwrap(); | |
let mut delay = | |
cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); | |
loop { | |
delay.delay_ms(400); | |
let _ = send_key(Some(b'F')); | |
led_pin.set_high().unwrap(); | |
delay.delay_ms(100); | |
let _ = send_key(None); | |
led_pin.set_low().unwrap(); | |
} | |
} | |
const fn single_key(key: u8, modifiers: u8) -> KeyboardReport { | |
KeyboardReport { | |
modifier: modifiers, | |
reserved: 0, | |
leds: 0, | |
keycodes: [key, 0, 0, 0, 0, 0], | |
} | |
} | |
const fn keypress(key: u8) -> KeyboardReport { | |
match key { | |
b'a'..=b'z' => single_key(key - b'a' + 4, 0), | |
b'A'..=b'Z' => single_key(key - b'A' + 4, 0x02), | |
b'0'..=b'9' => single_key(key - b'0' + 30, 0), | |
_ => panic!("Unhandled key"), | |
} | |
} | |
fn send_key(key: Option<u8>) -> Result<usize, UsbError> { | |
let report = key.map(keypress).unwrap_or(single_key(0, 0)); | |
critical_section::with(|_| unsafe { | |
USB_HID.as_mut().map(|hid| hid.push_input(&report)) | |
}) | |
.unwrap() | |
} | |
#[allow(non_snake_case)] | |
#[interrupt] | |
unsafe fn USBCTRL_IRQ() { | |
let usb_dev = USB_DEVICE.as_mut().unwrap(); | |
let usb_hid = USB_HID.as_mut().unwrap(); | |
usb_dev.poll(&mut [usb_hid]); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MEMORY { | |
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 | |
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 | |
RAM : ORIGIN = 0x20000000, LENGTH = 256K | |
} | |
EXTERN(BOOT2_FIRMWARE) | |
SECTIONS { | |
/* ### Boot loader */ | |
.boot2 ORIGIN(BOOT2) : | |
{ | |
KEEP(*(.boot2)); | |
} > BOOT2 | |
} INSERT BEFORE .text; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment