From af5db5d657415a7ea11f50a8a5927d0287b8fdd7 Mon Sep 17 00:00:00 2001 From: fly Date: Wed, 25 Sep 2024 00:56:30 +0200 Subject: [PATCH] Keyboard matrix implementation for PedestalBox Signed-off-by: fly --- .../firmware/descriptor.wara | 4 + .../PedestalConnectBox/firmware/src/device.rs | 10 +- .../PedestalConnectBox/firmware/src/main.rs | 249 +++++++++++------- 3 files changed, 171 insertions(+), 92 deletions(-) diff --git a/Pedestal/PedestalConnectBox/firmware/descriptor.wara b/Pedestal/PedestalConnectBox/firmware/descriptor.wara index c1075cb..cbbbbe7 100644 --- a/Pedestal/PedestalConnectBox/firmware/descriptor.wara +++ b/Pedestal/PedestalConnectBox/firmware/descriptor.wara @@ -54,6 +54,10 @@ logicalValueRange = [0, 65535] usageRange = ['Button', 'Button 1', 'Button 32'] logicalValueRange = [0, 1] +[[applicationCollection.inputReport.variableItem]] +usageRange = ['Button', 'Button 1', 'Button 32'] +logicalValueRange = [0, 1] + [[applicationCollection.outputReport]] [[applicationCollection.outputReport.variableItem]] diff --git a/Pedestal/PedestalConnectBox/firmware/src/device.rs b/Pedestal/PedestalConnectBox/firmware/src/device.rs index 3f02d3a..aa6a30c 100644 --- a/Pedestal/PedestalConnectBox/firmware/src/device.rs +++ b/Pedestal/PedestalConnectBox/firmware/src/device.rs @@ -43,11 +43,15 @@ pub const CUSTOM_DESCRIPTOR: &[u8] = &[ 0x19, 0x01, // UsageIdMin(Button 1[0x0001]) 0x29, 0x20, // UsageIdMax(Button 32[0x0020]) 0x25, 0x01, // LogicalMaximum(1) - 0x95, 0x10, // ReportCount(16) + 0x95, 0x20, // ReportCount(32) 0x75, 0x01, // ReportSize(1) 0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField) + 0x19, 0x01, // UsageIdMin(Button 1[0x0001]) + 0x29, 0x20, // UsageIdMax(Button 32[0x0020]) + 0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField) 0x05, 0x0E, // UsagePage(Haptics[0x000E]) 0x09, 0x21, // UsageId(Manual Trigger[0x0021]) + 0x09, 0x21, // UsageId(Manual Trigger[0x0021]) 0x27, 0x80, 0xBB, 0x00, 0x00, // LogicalMaximum(48,000) 0x95, 0x02, // ReportCount(2) 0x75, 0x10, // ReportSize(16) @@ -62,7 +66,7 @@ pub const CUSTOM_DESCRIPTOR: &[u8] = &[ ]; #[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)] -#[packed_struct(endian = "lsb", size_bytes = "27")] // MUST be <= 64 else we get problem cause InBytes64 or OutBytes64 +#[packed_struct(endian = "lsb", size_bytes = "31")] // MUST be <= 64 else we get problem cause InBytes64 or OutBytes64 pub struct CustomInputReport { #[packed_field] pub report_id: u8, @@ -70,6 +74,8 @@ pub struct CustomInputReport { pub axis: [u16; 11], #[packed_field] pub buttons: u32, + #[packed_field] + pub ecam_buttons: u32, } #[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)] diff --git a/Pedestal/PedestalConnectBox/firmware/src/main.rs b/Pedestal/PedestalConnectBox/firmware/src/main.rs index 6f28c3d..0e2c28d 100644 --- a/Pedestal/PedestalConnectBox/firmware/src/main.rs +++ b/Pedestal/PedestalConnectBox/firmware/src/main.rs @@ -49,23 +49,23 @@ macro_rules! define_output_states { macro_rules! define_ecam_output_states_row { ($index:literal, $pin:ident, $ecam_row:ident, $io_pins:ident) => { - if $ecam_row[$index] == 1 { - $io_pins.$pin.set_high(); - } - else { - $io_pins.$pin.set_low(); - } + if $ecam_row[$index] == 1 { + $io_pins.$pin.set_high(); + } + else { + $io_pins.$pin.set_low(); + } }; } macro_rules! define_ecam_output_states_col { ($index:literal, $pin:ident, $ecam_col:ident, $io_pins:ident) => { - if $ecam_col[$index] == 1 { - $io_pins.$pin.set_high(); - } - else { - $io_pins.$pin.set_low(); - } + if $ecam_col[$index] == 1 { + $io_pins.$pin.set_high(); + } + else { + $io_pins.$pin.set_low(); + } }; } @@ -131,7 +131,20 @@ struct MyPins { pe9: Pin<'E', 9, Output>, // ECAM LEDs Row 3 pe13: Pin<'E', 13, Output>, // ECAM LEDs Row 2 - // TODO ECAM matrix pins + // ECAM matrix read row + pe12: Pin<'E', 12, Input>, // ECAM Keys Row 1 + pe15: Pin<'E', 15, Input>, // ECAM Keys Row 2 + pe11: Pin<'E', 11, Input>, // ECAM Keys Row 3 + pe7: Pin<'E', 7, Input>, // ECAM Keys Row 4 + + // ECAM matrix column select + pd11: Pin<'D', 11, Output>, // ECAM Keys Column 1 + pd12: Pin<'D', 12, Output>, // ECAM Keys Column 2 + pe8: Pin<'E', 8, Output>, // ECAM Keys Column 3 + pb2: Pin<'B', 2, Output>, // ECAM Keys Column 4 + pe10: Pin<'E', 10, Output>, // ECAM Keys Column 5 + pe14: Pin<'E', 14, Output>, // ECAM Keys Column 6 + } #[derive(Pod)] @@ -295,6 +308,21 @@ fn main() -> ! { pe4: gpioe.pe4.into_push_pull_output(&mut gpioe.crl), pe9: gpioe.pe9.into_push_pull_output(&mut gpioe.crh), pe13: gpioe.pe13.into_push_pull_output(&mut gpioe.crh), + + // ECAM matrix read row + pe12: gpioe.pe12.into_pull_down_input(&mut gpioe.crh), + pe15: gpioe.pe15.into_pull_down_input(&mut gpioe.crh), + pe11: gpioe.pe11.into_pull_down_input(&mut gpioe.crh), + pe7: gpioe.pe7.into_pull_down_input(&mut gpioe.crl), + + + // ECAM matrix column select + pd11: gpiod.pd11.into_push_pull_output(&mut gpiod.crh), + pd12: gpiod.pd12.into_push_pull_output(&mut gpiod.crh), + pe8: gpioe.pe8.into_push_pull_output(&mut gpioe.crh), + pb2: gpiob.pb2.into_push_pull_output(&mut gpiob.crl), + pe10: gpioe.pe10.into_push_pull_output(&mut gpioe.crh), + pe14: gpioe.pe14.into_push_pull_output(&mut gpioe.crh), }; // ====================== PWM setup ================= @@ -311,10 +339,127 @@ fn main() -> ! { let mut timer = Timer::syst(cp.SYST, &clocks).counter_hz(); timer.start(1.kHz()).unwrap(); + // ====================== Setup other vars ========== + let mut ecam_col_select: u8 = 0; + let mut ecam_buttons: u32 = 0; // stores the values of the keyboard matrix we can not read out right now + // ====================== Main loop ================= loop { block!(timer.wait()).unwrap(); - let report = get_report(&mut io_pins, &mut adc1, &cal); + // Generate report + // Read axis + let mut values: [u16; 11] = [0; 11]; + values[0] = adc1.read(&mut io_pins.pa2).unwrap(); + values[1] = adc1.read(&mut io_pins.pa3).unwrap(); + values[2] = adc1.read(&mut io_pins.pa5).unwrap(); + values[3] = adc1.read(&mut io_pins.pa6).unwrap(); + values[4] = adc1.read(&mut io_pins.pa7).unwrap(); + values[5] = adc1.read(&mut io_pins.pb0).unwrap(); + values[6] = adc1.read(&mut io_pins.pb1).unwrap(); + values[7] = adc1.read(&mut io_pins.pc0).unwrap(); + values[8] = adc1.read(&mut io_pins.pc1).unwrap(); + values[9] = adc1.read(&mut io_pins.pc2).unwrap(); + values[10] = adc1.read(&mut io_pins.pc3).unwrap(); + + // Apply calibration to axis data + let mut values_norm: [u16; 11] = [0; 11]; + let mut i = 0; + loop { + if values[i] < cal.data[i].min { + values_norm[i] = 0; + } + else if values[i] > cal.data[i].max { + values_norm[i] = CalibrationData::ADC_MAX; + } + else { + values_norm[i] = ((values[i] - cal.data[i].min) as f32 * cal.data[i].factor) as u16; + } + i += 1; + if i == values_norm.len() { + break; + } + } + + // Buttons + let mut buttons: u32 = 0; + if io_pins.pa0.is_high() { buttons += 0x1; } + if io_pins.pa1.is_high() { buttons += 0x2; } + if io_pins.pa4.is_high() { buttons += 0x4; } + if io_pins.pa8.is_high() { buttons += 0x8; } + if io_pins.pa9.is_high() { buttons += 0x10; } + if io_pins.pa10.is_high() { buttons += 0x20; } + if io_pins.pb4.is_high() { buttons += 0x40; } + if io_pins.pb5.is_high() { buttons += 0x80; } + if io_pins.pb8.is_high() { buttons += 0x100; } + if io_pins.pb9.is_high() { buttons += 0x200; } + if io_pins.pc4.is_high() { buttons += 0x400; } + if io_pins.pc5.is_high() { buttons += 0x800; } + if io_pins.pc6.is_high() { buttons += 0x1000; } + if io_pins.pc9.is_high() { buttons += 0x0200; } + if io_pins.pc13.is_high() { buttons += 0x4000; } + if io_pins.pc14.is_high() { buttons += 0x8000; } + if io_pins.pc15.is_high() { buttons += 0x10000; } + if io_pins.pd1.is_high() { buttons += 0x20000; } + if io_pins.pd3.is_high() { buttons += 0x40000; } + if io_pins.pd4.is_high() { buttons += 0x80000; } + if io_pins.pd5.is_high() { buttons += 0x100000; } + if io_pins.pd6.is_high() { buttons += 0x200000; } + if io_pins.pd7.is_high() { buttons += 0x400000; } + if io_pins.pd13.is_high() { buttons += 0x800000; } + if io_pins.pd14.is_high() { buttons += 0x1000000; } + if io_pins.pd15.is_high() { buttons += 0x2000000; } + if io_pins.pe0.is_high() { buttons += 0x4000000; } + if io_pins.pe5.is_high() { buttons += 0x8000000; } + if io_pins.pe6.is_high() { buttons += 0x10000000; } + + // ECAM Keyboard matrix + let mut ecam_buttons_read: u32 = 0; + + if io_pins.pe12.is_high() { ecam_buttons_read += 0x1; } + if io_pins.pe15.is_high() { ecam_buttons_read += 0x2; } + if io_pins.pe11.is_high() { ecam_buttons_read += 0x4; } + if io_pins.pe7.is_high() { ecam_buttons_read += 0x8; } + + ecam_buttons = ecam_buttons & (0xFFFFFFFF - (0xF << (ecam_col_select * 4))); + ecam_buttons += ecam_buttons_read << (ecam_col_select * 4); + + // Pull the next column high for next time coming through in the main loop ~1ms + if ecam_col_select == 0 { + io_pins.pd11.set_high(); + io_pins.pe14.set_low(); + } + else if ecam_col_select == 1 { + io_pins.pd12.set_high(); + io_pins.pd11.set_low(); + } + else if ecam_col_select == 2 { + io_pins.pe8.set_high(); + io_pins.pd12.set_low(); + } + else if ecam_col_select == 3 { + io_pins.pb2.set_high(); + io_pins.pe8.set_low(); + } + else if ecam_col_select == 4 { + io_pins.pe10.set_high(); + io_pins.pb2.set_low(); + } + else if ecam_col_select == 5 { + io_pins.pe14.set_high(); + io_pins.pe10.set_low(); + } + + ecam_col_select += 1; + if ecam_col_select >= 6 { + ecam_col_select = 0 + } + + let report = CustomInputReport { + report_id: 1, + axis: values_norm, + buttons, + ecam_buttons, + }; match consumer.device().write_report(&report) { Err(UsbHidError::WouldBlock) => {} Err(UsbHidError::UsbError(usb_device::UsbError::BufferOverflow)) => { @@ -446,82 +591,6 @@ fn calculate_factor(min: u16, max: u16) -> f32 { return CalibrationData::ADC_MAX as f32 / (CalibrationData::ADC_MAX - min - (CalibrationData::ADC_MAX - max)) as f32; } -// Returns a CustomInputReport from the inputs given -fn get_report(pins: &mut MyPins, adc1: &mut adc::Adc, cal: &Calibration) -> CustomInputReport { - // Read axis - let mut values: [u16; 11] = [0; 11]; - values[0] = adc1.read(&mut pins.pa2).unwrap(); - values[1] = adc1.read(&mut pins.pa3).unwrap(); - values[2] = adc1.read(&mut pins.pa5).unwrap(); - values[3] = adc1.read(&mut pins.pa6).unwrap(); - values[4] = adc1.read(&mut pins.pa7).unwrap(); - values[5] = adc1.read(&mut pins.pb0).unwrap(); - values[6] = adc1.read(&mut pins.pb1).unwrap(); - values[7] = adc1.read(&mut pins.pc0).unwrap(); - values[8] = adc1.read(&mut pins.pc1).unwrap(); - values[9] = adc1.read(&mut pins.pc2).unwrap(); - values[10] = adc1.read(&mut pins.pc3).unwrap(); - - // Apply calibration to axis data - let mut values_norm: [u16; 11] = [0; 11]; - let mut i = 0; - loop { - if values[i] < cal.data[i].min { - values_norm[i] = 0; - } - else if values[i] > cal.data[i].max { - values_norm[i] = CalibrationData::ADC_MAX; - } - else { - values_norm[i] = ((values[i] - cal.data[i].min) as f32 * cal.data[i].factor) as u16; - } - i += 1; - if i == values_norm.len() { - break; - } - } - - // Buttons - let mut buttons: u32 = 0; - if pins.pa0.is_high() { buttons += 0x1; } - if pins.pa1.is_high() { buttons += 0x2; } - if pins.pa4.is_high() { buttons += 0x4; } - if pins.pa8.is_high() { buttons += 0x8; } - if pins.pa9.is_high() { buttons += 0x10; } - if pins.pa10.is_high() { buttons += 0x20; } - if pins.pb4.is_high() { buttons += 0x40; } - if pins.pb5.is_high() { buttons += 0x80; } - if pins.pb8.is_high() { buttons += 0x100; } - if pins.pb9.is_high() { buttons += 0x200; } - if pins.pc4.is_high() { buttons += 0x400; } - if pins.pc5.is_high() { buttons += 0x800; } - if pins.pc6.is_high() { buttons += 0x1000; } - if pins.pc9.is_high() { buttons += 0x0200; } - if pins.pc13.is_high() { buttons += 0x4000; } - if pins.pc14.is_high() { buttons += 0x8000; } - if pins.pc15.is_high() { buttons += 0x10000; } - if pins.pd1.is_high() { buttons += 0x20000; } - if pins.pd3.is_high() { buttons += 0x40000; } - if pins.pd4.is_high() { buttons += 0x80000; } - if pins.pd5.is_high() { buttons += 0x100000; } - if pins.pd6.is_high() { buttons += 0x200000; } - if pins.pd7.is_high() { buttons += 0x400000; } - if pins.pd13.is_high() { buttons += 0x800000; } - if pins.pd14.is_high() { buttons += 0x1000000; } - if pins.pd15.is_high() { buttons += 0x2000000; } - if pins.pe0.is_high() { buttons += 0x4000000; } - if pins.pe5.is_high() { buttons += 0x8000000; } - if pins.pe6.is_high() { buttons += 0x10000000; } - - // ECAM Keyboard matrix - - CustomInputReport { - report_id: 1, - axis: values_norm, - buttons, - } -} - // Save calibration to flash fn save_calibration(flash: &mut FlashWriter, cal: &Calibration) -> bool { let mut data: [u8; 1024] = [0; 1024];