Mouse sensor testing

This commit is contained in:
hodasemi 2023-03-25 14:29:35 +01:00
parent 2de4c0638e
commit 273dbaa630
5 changed files with 225 additions and 49 deletions

View file

@ -5,4 +5,7 @@
"titleBar.activeForeground": "#FCFCFE" "titleBar.activeForeground": "#FCFCFE"
}, },
"rust-analyzer.check.allTargets": false, "rust-analyzer.check.allTargets": false,
"rust-analyzer.cargo.features": [
"serial"
],
} }

View file

@ -1,4 +1,7 @@
use crate::{serial::Serial, MouseInfoSender}; use crate::{
serial::{Commands, Serial},
MouseInfoSender,
};
use rp_pico as bsp; use rp_pico as bsp;
@ -7,6 +10,7 @@ use bsp::{
clocks::ClocksManager, clocks::ClocksManager,
pac, pac,
pac::{interrupt, Interrupt}, pac::{interrupt, Interrupt},
rom_data::reset_to_usb_boot,
usb::UsbBus, usb::UsbBus,
}, },
pac::{RESETS, USBCTRL_DPRAM, USBCTRL_REGS}, pac::{RESETS, USBCTRL_DPRAM, USBCTRL_REGS},
@ -19,12 +23,15 @@ static mut USB_BUS: Option<UsbBusAllocator<UsbBus>> = None;
static mut USB_SERIAL: Option<Serial> = None; static mut USB_SERIAL: Option<Serial> = None;
static mut USB_DEVICE: Option<UsbDevice<UsbBus>> = None; static mut USB_DEVICE: Option<UsbDevice<UsbBus>> = None;
pub struct CustomHID<'a> { pub fn serial() -> &'static mut Serial<'static> {
out_ep: EndpointOut<'a, UsbBus>, unsafe { USB_SERIAL.as_mut().unwrap() }
in_ep: EndpointIn<'a, UsbBus>,
} }
impl<'a> CustomHID<'a> { pub struct CustomHID {
c: u32,
}
impl CustomHID {
pub fn new( pub fn new(
usbctrl_reg: USBCTRL_REGS, usbctrl_reg: USBCTRL_REGS,
usbctrl_dpram: USBCTRL_DPRAM, 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); pac::NVIC::unmask(Interrupt::USBCTRL_IRQ);
pac::NVIC::unmask(Interrupt::SW0_IRQ);
(
USB_BUS.as_ref().unwrap().interrupt(64, poll_ms),
USB_BUS.as_ref().unwrap().interrupt(64, poll_ms),
)
}; };
Self { in_ep, out_ep } Self { c: 0 }
}
pub fn serial<F>(&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) { fn send(&mut self, x: i8, y: i8, buttons: u8, wheel: i8, pan: i8) {
push_mouse_movement(MouseReport { push_mouse_movement(MouseReport {
x, x,
@ -81,12 +93,24 @@ impl<'a> MouseInfoSender for CustomHID<'a> {
pan, 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. /// with interrupts disabled, to avoid a race hazard with the USB IRQ.
fn push_mouse_movement(report: MouseReport) { fn push_mouse_movement(report: MouseReport) {
critical_section::with(|_| unsafe { critical_section::with(|_| {
let serial = USB_SERIAL.as_mut().unwrap(); let serial = serial();
serial.send_text("x"); serial.send_text("x");
serial.send_number(report.x, 10); serial.send_number(report.x, 10);
@ -101,6 +125,19 @@ fn push_mouse_movement(report: MouseReport) {
unsafe fn USBCTRL_IRQ() { unsafe fn USBCTRL_IRQ() {
// Handle USB request // Handle USB request
let usb_dev = USB_DEVICE.as_mut().unwrap(); let usb_dev = USB_DEVICE.as_mut().unwrap();
let usb_hid = USB_SERIAL.as_mut().unwrap(); let usb_hid = serial();
usb_dev.poll(&mut [usb_hid]);
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)");
} }

View file

@ -1,24 +1,28 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#[cfg(features = "serial")] #[cfg(feature = "serial")]
mod custom_hid; mod custom_hid;
#[cfg(not(features = "serial"))] #[cfg(not(feature = "serial"))]
mod mouse_hid; mod mouse_hid;
mod mouse_sensor; mod mouse_sensor;
mod serial; mod serial;
#[cfg(features = "serial")] use core::panic::PanicInfo;
use cortex_m::delay::Delay;
#[cfg(feature = "serial")]
use custom_hid::CustomHID; use custom_hid::CustomHID;
#[cfg(not(features = "serial"))] #[cfg(not(feature = "serial"))]
use mouse_hid::MouseHID; use mouse_hid::MouseHID;
// Ensure we halt the program on panic (if we don't mention this crate it won't #[panic_handler]
// be linked) fn panic(_info: &PanicInfo) -> ! {
use panic_halt as _; loop {}
}
use rp_pico as bsp; use rp_pico as bsp;
@ -32,6 +36,7 @@ use crate::mouse_sensor::MouseSensor;
pub trait MouseInfoSender { pub trait MouseInfoSender {
fn send(&mut self, x: i8, y: i8, buttons: u8, wheel: i8, pan: i8); fn send(&mut self, x: i8, y: i8, buttons: u8, wheel: i8, pan: i8);
fn heart_beat(&mut self);
} }
#[entry] #[entry]
@ -57,8 +62,9 @@ fn main() -> ! {
.unwrap(); .unwrap();
let peripheral_clock = clocks.peripheral_clock.freq(); 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( let mut hid = CustomHID::new(
pac.USBCTRL_REGS, pac.USBCTRL_REGS,
pac.USBCTRL_DPRAM, pac.USBCTRL_DPRAM,
@ -67,7 +73,7 @@ fn main() -> ! {
10, 10,
); );
#[cfg(not(features = "serial"))] #[cfg(not(feature = "serial"))]
let mut hid = MouseHID::new( let mut hid = MouseHID::new(
pac.USBCTRL_REGS, pac.USBCTRL_REGS,
pac.USBCTRL_DPRAM, pac.USBCTRL_DPRAM,
@ -87,11 +93,53 @@ fn main() -> ! {
&mut pac.RESETS, &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 { loop {
if let Some((x, y)) = mouse_sensor.read_movement() { // if let Some((x, y)) = mouse_sensor.read_movement() {
hid.send(x, y, 0, 0, 0); // 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();
} }
} }

View file

@ -78,8 +78,6 @@ impl MouseHID {
pac::NVIC::unmask(Interrupt::USBCTRL_IRQ); pac::NVIC::unmask(Interrupt::USBCTRL_IRQ);
} }
let delay = Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());
Self { delay } Self { delay }
} }
} }
@ -95,6 +93,10 @@ impl MouseInfoSender for MouseHID {
}) })
.unwrap_or(0); .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. /// with interrupts disabled, to avoid a race hazard with the USB IRQ.

View file

@ -1,14 +1,14 @@
use core::mem; 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 embedded_hal::digital::v2::OutputPin;
use fugit::HertzU32; use fugit::{HertzU32, MegahertzU32};
use rp_pico::{ use rp_pico::{
hal::{ hal::{
gpio::{ gpio::{
self, self,
bank0::{Gpio2, Gpio3, Gpio4, Gpio5}, bank0::{Gpio2, Gpio25, Gpio3, Gpio4, Gpio5},
Function, Output, Pin, PushPull, Spi, Function, Output, Pin, PushPull, PushPullOutput, Spi,
}, },
spi::{self, Enabled, Spi as SpiDevice}, spi::{self, Enabled, Spi as SpiDevice},
}, },
@ -16,18 +16,29 @@ use rp_pico::{
Pins, Pins,
}; };
pub struct MouseSensor { pub struct MouseSensor<L>
where
L: FnMut(&str),
{
_sclk: Pin<Gpio2, Function<Spi>>, _sclk: Pin<Gpio2, Function<Spi>>,
_mosi: Pin<Gpio3, Function<Spi>>, _mosi: Pin<Gpio3, Function<Spi>>,
_miso: Pin<Gpio4, Function<Spi>>, _miso: Pin<Gpio4, Function<Spi>>,
cs: Pin<Gpio5, Output<PushPull>>, cs: Pin<Gpio5, Output<PushPull>>,
led: Pin<Gpio25, PushPullOutput>,
spi: SpiDevice<Enabled, SPI0, 8>, spi: SpiDevice<Enabled, SPI0, 8>,
delay: Delay,
log: L,
} }
impl MouseSensor { impl<L> MouseSensor<L>
const READ: u8 = 0x7F; where
const WRITE: u8 = 0x80; L: FnMut(&str),
{
const READ: u8 = 0b0111_1111;
const WRITE: u8 = 0b1000_0000;
const REG_PRODUCT_ID1: u8 = 0x00; const REG_PRODUCT_ID1: u8 = 0x00;
const REG_PRODUCT_ID2: u8 = 0x01; const REG_PRODUCT_ID2: u8 = 0x01;
@ -54,6 +65,8 @@ impl MouseSensor {
resets: &mut RESETS, resets: &mut RESETS,
spio: SPI0, spio: SPI0,
peripheral_clock: impl Into<HertzU32>, peripheral_clock: impl Into<HertzU32>,
mut delay: Delay,
mut log: L,
) -> Self { ) -> Self {
// These are implicitly used by the spi driver if they are in the correct mode // These are implicitly used by the spi driver if they are in the correct mode
let _sclk = pins.gpio2.into_mode::<gpio::FunctionSpi>(); let _sclk = pins.gpio2.into_mode::<gpio::FunctionSpi>();
@ -68,46 +81,95 @@ impl MouseSensor {
let spi = spi.init( let spi = spi.init(
resets, resets,
peripheral_clock, peripheral_clock,
HertzU32::from_raw(16_000_000u32), MegahertzU32::from_raw(1).convert(),
&embedded_hal::spi::MODE_0, &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, _sclk,
_mosi, _mosi,
_miso, _miso,
cs, cs,
led: pins.led.into_push_pull_output(),
spi, 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<F, T>(&mut self, f: F) -> T fn access<F, T>(&mut self, f: F) -> T
where where
F: Fn(&mut Self) -> T, 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); 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 res
} }
pub fn read(&mut self, address: u8) -> u8 { pub fn read(&mut self, address: u8) -> u8 {
self.access(|me| { self.access(|me| {
me.spi.send(address & Self::READ).unwrap(); if me.spi.send(address & Self::READ).is_err() {
me.spi.read().unwrap() (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) { pub fn write(&mut self, address: u8, value: u8) {
self.access(|me| { self.access(|me| {
me.spi.send(address | Self::WRITE).unwrap(); if me.spi.send(address | Self::WRITE).is_err() {
me.spi.send(value).unwrap(); (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) (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()
}
} }