Keyboard matrix implementation for PedestalBox
Signed-off-by: fly <merspieler@alwaysdata.net>
This commit is contained in:
parent
4a301af6ae
commit
af5db5d657
3 changed files with 171 additions and 92 deletions
|
@ -54,6 +54,10 @@ logicalValueRange = [0, 65535]
|
||||||
usageRange = ['Button', 'Button 1', 'Button 32']
|
usageRange = ['Button', 'Button 1', 'Button 32']
|
||||||
logicalValueRange = [0, 1]
|
logicalValueRange = [0, 1]
|
||||||
|
|
||||||
|
[[applicationCollection.inputReport.variableItem]]
|
||||||
|
usageRange = ['Button', 'Button 1', 'Button 32']
|
||||||
|
logicalValueRange = [0, 1]
|
||||||
|
|
||||||
[[applicationCollection.outputReport]]
|
[[applicationCollection.outputReport]]
|
||||||
|
|
||||||
[[applicationCollection.outputReport.variableItem]]
|
[[applicationCollection.outputReport.variableItem]]
|
||||||
|
|
|
@ -43,11 +43,15 @@ pub const CUSTOM_DESCRIPTOR: &[u8] = &[
|
||||||
0x19, 0x01, // UsageIdMin(Button 1[0x0001])
|
0x19, 0x01, // UsageIdMin(Button 1[0x0001])
|
||||||
0x29, 0x20, // UsageIdMax(Button 32[0x0020])
|
0x29, 0x20, // UsageIdMax(Button 32[0x0020])
|
||||||
0x25, 0x01, // LogicalMaximum(1)
|
0x25, 0x01, // LogicalMaximum(1)
|
||||||
0x95, 0x10, // ReportCount(16)
|
0x95, 0x20, // ReportCount(32)
|
||||||
0x75, 0x01, // ReportSize(1)
|
0x75, 0x01, // ReportSize(1)
|
||||||
0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
|
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])
|
0x05, 0x0E, // UsagePage(Haptics[0x000E])
|
||||||
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
|
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
|
||||||
|
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
|
||||||
0x27, 0x80, 0xBB, 0x00, 0x00, // LogicalMaximum(48,000)
|
0x27, 0x80, 0xBB, 0x00, 0x00, // LogicalMaximum(48,000)
|
||||||
0x95, 0x02, // ReportCount(2)
|
0x95, 0x02, // ReportCount(2)
|
||||||
0x75, 0x10, // ReportSize(16)
|
0x75, 0x10, // ReportSize(16)
|
||||||
|
@ -62,7 +66,7 @@ pub const CUSTOM_DESCRIPTOR: &[u8] = &[
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
|
#[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 {
|
pub struct CustomInputReport {
|
||||||
#[packed_field]
|
#[packed_field]
|
||||||
pub report_id: u8,
|
pub report_id: u8,
|
||||||
|
@ -70,6 +74,8 @@ pub struct CustomInputReport {
|
||||||
pub axis: [u16; 11],
|
pub axis: [u16; 11],
|
||||||
#[packed_field]
|
#[packed_field]
|
||||||
pub buttons: u32,
|
pub buttons: u32,
|
||||||
|
#[packed_field]
|
||||||
|
pub ecam_buttons: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
|
||||||
|
|
|
@ -49,23 +49,23 @@ macro_rules! define_output_states {
|
||||||
|
|
||||||
macro_rules! define_ecam_output_states_row {
|
macro_rules! define_ecam_output_states_row {
|
||||||
($index:literal, $pin:ident, $ecam_row:ident, $io_pins:ident) => {
|
($index:literal, $pin:ident, $ecam_row:ident, $io_pins:ident) => {
|
||||||
if $ecam_row[$index] == 1 {
|
if $ecam_row[$index] == 1 {
|
||||||
$io_pins.$pin.set_high();
|
$io_pins.$pin.set_high();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$io_pins.$pin.set_low();
|
$io_pins.$pin.set_low();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! define_ecam_output_states_col {
|
macro_rules! define_ecam_output_states_col {
|
||||||
($index:literal, $pin:ident, $ecam_col:ident, $io_pins:ident) => {
|
($index:literal, $pin:ident, $ecam_col:ident, $io_pins:ident) => {
|
||||||
if $ecam_col[$index] == 1 {
|
if $ecam_col[$index] == 1 {
|
||||||
$io_pins.$pin.set_high();
|
$io_pins.$pin.set_high();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$io_pins.$pin.set_low();
|
$io_pins.$pin.set_low();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,20 @@ struct MyPins {
|
||||||
pe9: Pin<'E', 9, Output<PushPull>>, // ECAM LEDs Row 3
|
pe9: Pin<'E', 9, Output<PushPull>>, // ECAM LEDs Row 3
|
||||||
pe13: Pin<'E', 13, Output<PushPull>>, // ECAM LEDs Row 2
|
pe13: Pin<'E', 13, Output<PushPull>>, // ECAM LEDs Row 2
|
||||||
|
|
||||||
// TODO ECAM matrix pins
|
// ECAM matrix read row
|
||||||
|
pe12: Pin<'E', 12, Input<PullDown>>, // ECAM Keys Row 1
|
||||||
|
pe15: Pin<'E', 15, Input<PullDown>>, // ECAM Keys Row 2
|
||||||
|
pe11: Pin<'E', 11, Input<PullDown>>, // ECAM Keys Row 3
|
||||||
|
pe7: Pin<'E', 7, Input<PullDown>>, // ECAM Keys Row 4
|
||||||
|
|
||||||
|
// ECAM matrix column select
|
||||||
|
pd11: Pin<'D', 11, Output<PushPull>>, // ECAM Keys Column 1
|
||||||
|
pd12: Pin<'D', 12, Output<PushPull>>, // ECAM Keys Column 2
|
||||||
|
pe8: Pin<'E', 8, Output<PushPull>>, // ECAM Keys Column 3
|
||||||
|
pb2: Pin<'B', 2, Output<PushPull>>, // ECAM Keys Column 4
|
||||||
|
pe10: Pin<'E', 10, Output<PushPull>>, // ECAM Keys Column 5
|
||||||
|
pe14: Pin<'E', 14, Output<PushPull>>, // ECAM Keys Column 6
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Pod)]
|
#[derive(Pod)]
|
||||||
|
@ -295,6 +308,21 @@ fn main() -> ! {
|
||||||
pe4: gpioe.pe4.into_push_pull_output(&mut gpioe.crl),
|
pe4: gpioe.pe4.into_push_pull_output(&mut gpioe.crl),
|
||||||
pe9: gpioe.pe9.into_push_pull_output(&mut gpioe.crh),
|
pe9: gpioe.pe9.into_push_pull_output(&mut gpioe.crh),
|
||||||
pe13: gpioe.pe13.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 =================
|
// ====================== PWM setup =================
|
||||||
|
@ -311,10 +339,127 @@ fn main() -> ! {
|
||||||
let mut timer = Timer::syst(cp.SYST, &clocks).counter_hz();
|
let mut timer = Timer::syst(cp.SYST, &clocks).counter_hz();
|
||||||
timer.start(1.kHz()).unwrap();
|
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 =================
|
// ====================== Main loop =================
|
||||||
loop {
|
loop {
|
||||||
block!(timer.wait()).unwrap();
|
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) {
|
match consumer.device().write_report(&report) {
|
||||||
Err(UsbHidError::WouldBlock) => {}
|
Err(UsbHidError::WouldBlock) => {}
|
||||||
Err(UsbHidError::UsbError(usb_device::UsbError::BufferOverflow)) => {
|
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;
|
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<pac::ADC1>, 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
|
// Save calibration to flash
|
||||||
fn save_calibration(flash: &mut FlashWriter, cal: &Calibration) -> bool {
|
fn save_calibration(flash: &mut FlashWriter, cal: &Calibration) -> bool {
|
||||||
let mut data: [u8; 1024] = [0; 1024];
|
let mut data: [u8; 1024] = [0; 1024];
|
||||||
|
|
Loading…
Reference in a new issue