diff --git a/.vscode/settings.json b/.vscode/settings.json index bcb7e03..3accdc5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,4 +5,7 @@ "titleBar.activeForeground": "#FCFCFE" }, "rust-analyzer.check.allTargets": false, + "rust-analyzer.cargo.features": [ + "serial" + ], } \ No newline at end of file diff --git a/src/custom_hid.rs b/src/custom_hid.rs index 78f9b21..84e0f3a 100644 --- a/src/custom_hid.rs +++ b/src/custom_hid.rs @@ -1,4 +1,7 @@ -use crate::{serial::Serial, MouseInfoSender}; +use crate::{ + serial::{Commands, Serial}, + MouseInfoSender, +}; use rp_pico as bsp; @@ -7,6 +10,7 @@ use bsp::{ clocks::ClocksManager, pac, pac::{interrupt, Interrupt}, + rom_data::reset_to_usb_boot, usb::UsbBus, }, pac::{RESETS, USBCTRL_DPRAM, USBCTRL_REGS}, @@ -19,12 +23,15 @@ static mut USB_BUS: Option> = None; static mut USB_SERIAL: Option = None; static mut USB_DEVICE: Option> = None; -pub struct CustomHID<'a> { - out_ep: EndpointOut<'a, UsbBus>, - in_ep: EndpointIn<'a, UsbBus>, +pub fn serial() -> &'static mut Serial<'static> { + unsafe { USB_SERIAL.as_mut().unwrap() } } -impl<'a> CustomHID<'a> { +pub struct CustomHID { + c: u32, +} + +impl CustomHID { pub fn new( usbctrl_reg: USBCTRL_REGS, usbctrl_dpram: USBCTRL_DPRAM, @@ -58,20 +65,25 @@ impl<'a> CustomHID<'a> { ); } - let (in_ep, out_ep) = unsafe { + unsafe { pac::NVIC::unmask(Interrupt::USBCTRL_IRQ); - - ( - USB_BUS.as_ref().unwrap().interrupt(64, poll_ms), - USB_BUS.as_ref().unwrap().interrupt(64, poll_ms), - ) + pac::NVIC::unmask(Interrupt::SW0_IRQ); }; - Self { in_ep, out_ep } + Self { c: 0 } + } + + pub fn serial(&mut self, mut f: F) + where + F: FnMut(&mut Serial), + { + critical_section::with(|_| { + f(serial()); + }) } } -impl<'a> MouseInfoSender for CustomHID<'a> { +impl MouseInfoSender for CustomHID { fn send(&mut self, x: i8, y: i8, buttons: u8, wheel: i8, pan: i8) { push_mouse_movement(MouseReport { x, @@ -81,12 +93,24 @@ impl<'a> MouseInfoSender for CustomHID<'a> { pan, }) } + + fn heart_beat(&mut self) { + self.c += 1; + + if self.c == 1_000_000 { + self.c = 0; + + if !(pac::NVIC::is_pending(Interrupt::SW0_IRQ)) { + pac::NVIC::pend(Interrupt::SW0_IRQ); + } + } + } } /// with interrupts disabled, to avoid a race hazard with the USB IRQ. fn push_mouse_movement(report: MouseReport) { - critical_section::with(|_| unsafe { - let serial = USB_SERIAL.as_mut().unwrap(); + critical_section::with(|_| { + let serial = serial(); serial.send_text("x"); serial.send_number(report.x, 10); @@ -101,6 +125,19 @@ fn push_mouse_movement(report: MouseReport) { unsafe fn USBCTRL_IRQ() { // Handle USB request let usb_dev = USB_DEVICE.as_mut().unwrap(); - let usb_hid = USB_SERIAL.as_mut().unwrap(); - usb_dev.poll(&mut [usb_hid]); + let usb_hid = serial(); + + if usb_dev.poll(&mut [usb_hid]) { + if let Some(command) = usb_hid.read() { + match command { + Commands::Reset => reset_to_usb_boot(0, 0), + } + } + } +} + +#[allow(non_snake_case)] +#[interrupt] +unsafe fn SW0_IRQ() { + serial().send_text("heartbeat (IRQ)"); } diff --git a/src/main.rs b/src/main.rs index a7a9521..1224819 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,28 @@ #![no_std] #![no_main] -#[cfg(features = "serial")] +#[cfg(feature = "serial")] mod custom_hid; -#[cfg(not(features = "serial"))] +#[cfg(not(feature = "serial"))] mod mouse_hid; mod mouse_sensor; mod serial; -#[cfg(features = "serial")] +use core::panic::PanicInfo; + +use cortex_m::delay::Delay; +#[cfg(feature = "serial")] use custom_hid::CustomHID; -#[cfg(not(features = "serial"))] +#[cfg(not(feature = "serial"))] use mouse_hid::MouseHID; -// Ensure we halt the program on panic (if we don't mention this crate it won't -// be linked) -use panic_halt as _; +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} use rp_pico as bsp; @@ -32,6 +36,7 @@ use crate::mouse_sensor::MouseSensor; pub trait MouseInfoSender { fn send(&mut self, x: i8, y: i8, buttons: u8, wheel: i8, pan: i8); + fn heart_beat(&mut self); } #[entry] @@ -57,8 +62,9 @@ fn main() -> ! { .unwrap(); let peripheral_clock = clocks.peripheral_clock.freq(); + let delay = Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); - #[cfg(features = "serial")] + #[cfg(feature = "serial")] let mut hid = CustomHID::new( pac.USBCTRL_REGS, pac.USBCTRL_DPRAM, @@ -67,7 +73,7 @@ fn main() -> ! { 10, ); - #[cfg(not(features = "serial"))] + #[cfg(not(feature = "serial"))] let mut hid = MouseHID::new( pac.USBCTRL_REGS, pac.USBCTRL_DPRAM, @@ -87,11 +93,53 @@ fn main() -> ! { &mut pac.RESETS, ); - let mut mouse_sensor = MouseSensor::new(pins, &mut pac.RESETS, pac.SPI0, peripheral_clock); + let mut mouse_sensor = MouseSensor::new( + pins, + &mut pac.RESETS, + pac.SPI0, + peripheral_clock, + delay, + |msg| { + #[cfg(feature = "serial")] + critical_section::with(|_| { + custom_hid::serial().send_text(msg); + }); + }, + ); + + // #[cfg(feature = "serial")] + // { + // hid.serial(|serial| { + // serial.send_number(mouse_sensor.product_id_1(), 10); + // serial.send_number(mouse_sensor.product_id_2(), 10); + // }); + // } + + let mut c = 0; loop { - if let Some((x, y)) = mouse_sensor.read_movement() { - hid.send(x, y, 0, 0, 0); + // if let Some((x, y)) = mouse_sensor.read_movement() { + // hid.send(x, y, 0, 0, 0); + // } + + c += 1; + + if c == 10_000_000 { + c = 0; + + #[cfg(feature = "serial")] + critical_section::with(|_| { + let serial = custom_hid::serial(); + + serial.send_text("---"); + serial.send_number(mouse_sensor.operation_mode(), 10); + serial.send_text(" - "); + serial.send_number(0xB8, 10); + + // custom_hid::serial().send_number(mouse_sensor.product_id_2(), 10); + }); } + + // hid.heart_beat(); } } diff --git a/src/mouse_hid.rs b/src/mouse_hid.rs index c37c215..8eb9af2 100644 --- a/src/mouse_hid.rs +++ b/src/mouse_hid.rs @@ -78,8 +78,6 @@ impl MouseHID { pac::NVIC::unmask(Interrupt::USBCTRL_IRQ); } - let delay = Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); - Self { delay } } } @@ -95,6 +93,10 @@ impl MouseInfoSender for MouseHID { }) .unwrap_or(0); } + + fn heart_beat(&mut self) { + // mouse hid does everything by itself + } } /// with interrupts disabled, to avoid a race hazard with the USB IRQ. diff --git a/src/mouse_sensor.rs b/src/mouse_sensor.rs index 06fbf00..1192a75 100644 --- a/src/mouse_sensor.rs +++ b/src/mouse_sensor.rs @@ -1,14 +1,14 @@ use core::mem; -use cortex_m::prelude::_embedded_hal_spi_FullDuplex; +use cortex_m::{delay::Delay, prelude::_embedded_hal_spi_FullDuplex}; use embedded_hal::digital::v2::OutputPin; -use fugit::HertzU32; +use fugit::{HertzU32, MegahertzU32}; use rp_pico::{ hal::{ gpio::{ self, - bank0::{Gpio2, Gpio3, Gpio4, Gpio5}, - Function, Output, Pin, PushPull, Spi, + bank0::{Gpio2, Gpio25, Gpio3, Gpio4, Gpio5}, + Function, Output, Pin, PushPull, PushPullOutput, Spi, }, spi::{self, Enabled, Spi as SpiDevice}, }, @@ -16,18 +16,29 @@ use rp_pico::{ Pins, }; -pub struct MouseSensor { +pub struct MouseSensor +where + L: FnMut(&str), +{ _sclk: Pin>, _mosi: Pin>, _miso: Pin>, cs: Pin>, + led: Pin, + spi: SpiDevice, + delay: Delay, + + log: L, } -impl MouseSensor { - const READ: u8 = 0x7F; - const WRITE: u8 = 0x80; +impl MouseSensor +where + L: FnMut(&str), +{ + const READ: u8 = 0b0111_1111; + const WRITE: u8 = 0b1000_0000; const REG_PRODUCT_ID1: u8 = 0x00; const REG_PRODUCT_ID2: u8 = 0x01; @@ -54,6 +65,8 @@ impl MouseSensor { resets: &mut RESETS, spio: SPI0, peripheral_clock: impl Into, + mut delay: Delay, + mut log: L, ) -> Self { // These are implicitly used by the spi driver if they are in the correct mode let _sclk = pins.gpio2.into_mode::(); @@ -68,46 +81,95 @@ impl MouseSensor { let spi = spi.init( resets, peripheral_clock, - HertzU32::from_raw(16_000_000u32), - &embedded_hal::spi::MODE_0, + MegahertzU32::from_raw(1).convert(), + &embedded_hal::spi::MODE_2, ); - cs.set_high().unwrap(); + if let Err(_err) = cs.set_low() { + log("cs high failed"); + } - Self { + delay.delay_ms(2); + + if let Err(_err) = cs.set_high() { + log("cs high failed"); + } + + let mut me = Self { _sclk, _mosi, _miso, cs, + led: pins.led.into_push_pull_output(), + spi, + delay, + + log, + }; + + if me.led.set_low().is_err() { + (me.log)("led low failed"); } + + if !me.verify_product_id_1() || !me.verify_product_id_2() { + if me.led.set_high().is_err() { + (me.log)("led high failed"); + } + } + + me } fn access(&mut self, f: F) -> T where F: Fn(&mut Self) -> T, { - self.cs.set_low().unwrap(); + if self.cs.set_low().is_err() { + (self.log)("cs low failed"); + } + + self.delay.delay_us(1); let res = f(self); - self.cs.set_high().unwrap(); + if self.cs.set_high().is_err() { + (self.log)("cs low failed"); + } + + self.delay.delay_us(2); res } pub fn read(&mut self, address: u8) -> u8 { self.access(|me| { - me.spi.send(address & Self::READ).unwrap(); - me.spi.read().unwrap() + if me.spi.send(address & Self::READ).is_err() { + (me.log)("send address (read) failed"); + } + + me.delay.delay_us(50); + + match me.spi.read() { + Ok(res) => res, + Err(_) => { + (me.log)("read failed"); + 0 + } + } }) } pub fn write(&mut self, address: u8, value: u8) { self.access(|me| { - me.spi.send(address | Self::WRITE).unwrap(); - me.spi.send(value).unwrap(); + if me.spi.send(address | Self::WRITE).is_err() { + (me.log)("send address (write) failed"); + } + + if me.spi.send(value).is_err() { + (me.log)("send value (write) failed"); + } }); } @@ -145,4 +207,28 @@ impl MouseSensor { (motion, x_overflow, y_overflow) } + + pub fn product_id_1(&mut self) -> u8 { + self.read(Self::REG_PRODUCT_ID1) + } + + pub fn product_id_2(&mut self) -> u8 { + self.read(Self::REG_PRODUCT_ID2) + } + + pub fn operation_mode(&mut self) -> u8 { + self.read(Self::REG_OPERATION_MODE) + } + + fn verify_product_id_1(&mut self) -> bool { + const DEFAULT_VALUE: u8 = 0x30; + + DEFAULT_VALUE == self.product_id_1() + } + + fn verify_product_id_2(&mut self) -> bool { + const DEFAULT_VALUE: u8 = 0x02; + + DEFAULT_VALUE == self.product_id_2() + } }