PedestalBox Outputs
Signed-off-by: fly <merspieler@alwaysdata.net>
This commit is contained in:
parent
6449f537fb
commit
8febf32910
4 changed files with 188 additions and 63 deletions
|
@ -1,4 +1,38 @@
|
||||||
# Pedestal Connect Box
|
# Pedestal Connect Box
|
||||||
|
## USB HID
|
||||||
|
### Input
|
||||||
|
25 Bytes of input, consisting of
|
||||||
|
* 1 Byte reportId (always value 1)
|
||||||
|
* 22 Bytes for 11 axis (each axis is 2 bytes and has a range of 0 - 4095)
|
||||||
|
* 2 Bytes for buttons
|
||||||
|
|
||||||
|
Inputs report usually via USB HID so you only have to map them.
|
||||||
|
|
||||||
|
### Output
|
||||||
|
9 Byte output, consisting of
|
||||||
|
* 1 Byte for the reportId (always value 1)
|
||||||
|
* 2 Bytes for the brightness of the integrated lighting (range 0-48000)
|
||||||
|
* 2 Bytes for generic controls (such as calibration)
|
||||||
|
* 4 Bytes for indicator LEDs, each bit controls one item:
|
||||||
|
* 0x00000001: ECAM CLR
|
||||||
|
* 0x00000002: ECAM APU
|
||||||
|
* 0x00000004: ECAM ENG
|
||||||
|
* 0x00000008: ECAM COND
|
||||||
|
* 0x00000010: ECAM BLEED
|
||||||
|
* 0x00000020: ECAM STS
|
||||||
|
* 0x00000040: ECAM DOOR
|
||||||
|
* 0x00000080: ECAM PRESS
|
||||||
|
* 0x00000100: ECAM WHEEL
|
||||||
|
* 0x00000200: ECAM ELEC
|
||||||
|
* 0x00000400: ECAM F/CTL
|
||||||
|
* 0x00000800: ECAM HYD
|
||||||
|
* 0x00001000: ECAM FUEL
|
||||||
|
* 0x00002000: DOOR OPEN
|
||||||
|
* 0x00004000: DOOR FAULT
|
||||||
|
* 0x00008000: ENG 1 FAULT
|
||||||
|
* 0x00010000: ENG 1 FIRE
|
||||||
|
* 0x00020000: ENG 2 FAULT
|
||||||
|
* 0x00040000: ENG 2 FIRE
|
||||||
## Pinout
|
## Pinout
|
||||||
### General pins
|
### General pins
|
||||||
PA15|Backlight PWM
|
PA15|Backlight PWM
|
||||||
|
|
|
@ -7,24 +7,43 @@ usage = ['Generic Desktop', 'Joystick']
|
||||||
usage = ['Generic Desktop', 'Pointer']
|
usage = ['Generic Desktop', 'Pointer']
|
||||||
|
|
||||||
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
usage = ['Generic Desktop', 'X']
|
usage = ['Generic Desktop', 'Z']
|
||||||
logicalValueRange = [0, 65535]
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
usage = ['Generic Desktop', 'Z']
|
usage = ['Generic Desktop', 'Z']
|
||||||
logicalValueRange = [0, 65535]
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
[[applicationCollection.inputReport.variableItem]]
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
usageRange = ['Button', 'Button 1', 'Button 16']
|
usage = ['Generic Desktop', 'Z']
|
||||||
logicalValueRange = [0, 1]
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
[[applicationCollection.inputReport]]
|
|
||||||
|
|
||||||
[[applicationCollection.inputReport.physicalCollection]]
|
|
||||||
usage = ['Generic Desktop', 'Pointer']
|
|
||||||
|
|
||||||
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
usage = ['Generic Desktop', 'X']
|
usage = ['Generic Desktop', 'Z']
|
||||||
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
|
usage = ['Generic Desktop', 'Z']
|
||||||
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
|
usage = ['Generic Desktop', 'Z']
|
||||||
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
|
usage = ['Generic Desktop', 'Z']
|
||||||
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
|
usage = ['Generic Desktop', 'Z']
|
||||||
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
|
usage = ['Generic Desktop', 'Z']
|
||||||
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
|
usage = ['Generic Desktop', 'Z']
|
||||||
logicalValueRange = [0, 65535]
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
[[applicationCollection.inputReport.physicalCollection.variableItem]]
|
||||||
|
@ -44,3 +63,11 @@ logicalValueRange = [0, 48000]
|
||||||
[[applicationCollection.outputReport.variableItem]]
|
[[applicationCollection.outputReport.variableItem]]
|
||||||
usage = ['Haptics', 'Manual Trigger']
|
usage = ['Haptics', 'Manual Trigger']
|
||||||
logicalValueRange = [0, 65535]
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
|
[[applicationCollection.outputReport.variableItem]]
|
||||||
|
usage = ['Haptics', 'Manual Trigger']
|
||||||
|
logicalValueRange = [0, 65535]
|
||||||
|
|
||||||
|
[[applicationCollection.outputReport.variableItem]]
|
||||||
|
usage = ['Haptics', 'Manual Trigger']
|
||||||
|
logicalValueRange = [0, 65535]
|
||||||
|
|
|
@ -22,12 +22,20 @@ pub const CUSTOM_DESCRIPTOR: &[u8] = &[
|
||||||
0x85, 0x01, // ReportId(1)
|
0x85, 0x01, // ReportId(1)
|
||||||
0x09, 0x01, // UsageId(Pointer[0x0001])
|
0x09, 0x01, // UsageId(Pointer[0x0001])
|
||||||
0xA1, 0x00, // Collection(Physical)
|
0xA1, 0x00, // Collection(Physical)
|
||||||
0x09, 0x30, // UsageId(X[0x0030])
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
0x09, 0x31, // UsageId(Y[0x0031])
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
0x09, 0x32, // UsageId(Z[0x0032])
|
0x09, 0x32, // UsageId(Z[0x0032])
|
||||||
0x15, 0x00, // LogicalMinimum(0)
|
0x15, 0x00, // LogicalMinimum(0)
|
||||||
0x26, 0xFF, 0x0F, // LogicalMaximum(4,095)
|
0x27, 0xFF, 0xFF, 0x00, 0x00, // LogicalMaximum(65,535)
|
||||||
0x95, 0x03, // ReportCount(3)
|
0x95, 0x0B, // ReportCount(11)
|
||||||
0x75, 0x10, // ReportSize(16)
|
0x75, 0x10, // ReportSize(16)
|
||||||
0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
|
0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
|
||||||
0xC0, // EndCollection()
|
0xC0, // EndCollection()
|
||||||
|
@ -38,42 +46,41 @@ pub const CUSTOM_DESCRIPTOR: &[u8] = &[
|
||||||
0x95, 0x10, // ReportCount(16)
|
0x95, 0x10, // ReportCount(16)
|
||||||
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)
|
||||||
0x85, 0x02, // ReportId(2)
|
0x05, 0x0E, // UsagePage(Haptics[0x000E])
|
||||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
|
||||||
0x09, 0x01, // Usage (0x01)
|
|
||||||
0x27, 0x80, 0xBB, 0x00, 0x00, // LogicalMaximum(48,000)
|
0x27, 0x80, 0xBB, 0x00, 0x00, // LogicalMaximum(48,000)
|
||||||
0x95, 0x01, // ReportCount(1)
|
0x95, 0x01, // ReportCount(1)
|
||||||
0x75, 0x10, // ReportSize(16)
|
0x75, 0x10, // ReportSize(16)
|
||||||
0x91, 0x02, // Output(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
0x91, 0x02, // Output(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
||||||
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
|
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
|
||||||
0x27, 0xFF, 0xFF, 0x00, 0x00, // LogicalMaximum(65,535)
|
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
|
||||||
0x91, 0x02, // Output(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
|
||||||
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
|
0x09, 0x21, // UsageId(Manual Trigger[0x0021])
|
||||||
0x27, 0xFF, 0xFF, 0x00, 0x00, // LogicalMaximum(65,535)
|
0x27, 0xFF, 0xFF, 0x00, 0x00, // LogicalMaximum(65,535)
|
||||||
|
0x95, 0x03, // ReportCount(3)
|
||||||
0x91, 0x02, // Output(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
0x91, 0x02, // Output(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
|
||||||
0xC0, // EndCollection()
|
0xC0, // EndCollection()
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
|
||||||
#[packed_struct(endian = "lsb", size_bytes = "9")] // MUST be <= 64 else we get problem cause InBytes64 or OutBytes64
|
#[packed_struct(endian = "lsb", size_bytes = "25")] // 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,
|
||||||
#[packed_field]
|
#[packed_field]
|
||||||
pub axis: [u16; 3],
|
pub axis: [u16; 11],
|
||||||
#[packed_field]
|
#[packed_field]
|
||||||
pub buttons: u16,
|
pub buttons: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default, PackedStruct)]
|
||||||
#[packed_struct(endian = "lsb", size_bytes = "7")]
|
#[packed_struct(endian = "lsb", size_bytes = "9")]
|
||||||
pub struct CustomOutputReport {
|
pub struct CustomOutputReport {
|
||||||
#[packed_field]
|
#[packed_field]
|
||||||
pub report_id: u8,
|
pub report_id: u8,
|
||||||
#[packed_field]
|
#[packed_field]
|
||||||
pub integ_lt: u16,
|
pub integ_lt: u16,
|
||||||
pub generic: u16,
|
pub generic: u16,
|
||||||
pub leds: u16,
|
pub leds: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CustomDevice<'a, B: UsbBus> {
|
pub struct CustomDevice<'a, B: UsbBus> {
|
||||||
|
@ -90,7 +97,7 @@ impl<'a, B: UsbBus> CustomDevice<'a, B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_report(&mut self) -> Result<CustomOutputReport, UsbHidError> {
|
pub fn read_report(&mut self) -> Result<CustomOutputReport, UsbHidError> {
|
||||||
let mut data = [0; 7];
|
let mut data = [0; 9];
|
||||||
self.interface
|
self.interface
|
||||||
.read_report(&mut data[..])
|
.read_report(&mut data[..])
|
||||||
.map(|_| CustomOutputReport::unpack(&data).unwrap())
|
.map(|_| CustomOutputReport::unpack(&data).unwrap())
|
||||||
|
|
|
@ -32,10 +32,44 @@ use bytemuck::{bytes_of, bytes_of_mut, try_from_bytes, Pod, Zeroable};
|
||||||
// Set layout version
|
// Set layout version
|
||||||
const FLASH_LAYOUT_VERSION: u16 = 0;
|
const FLASH_LAYOUT_VERSION: u16 = 0;
|
||||||
|
|
||||||
|
macro_rules! define_output_states {
|
||||||
|
($bit:literal, $pin:ident, $output:ident, $io_pins:ident) => {
|
||||||
|
if $output.leds & $bit == $bit {
|
||||||
|
$io_pins.$pin.set_high();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$io_pins.$pin.set_low();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct MyPins {
|
struct MyPins {
|
||||||
pa1: Pin<'A', 1, Analog>,
|
pa1: Pin<'A', 1, Analog>,
|
||||||
pa2: Pin<'A', 2, Analog>,
|
pa2: Pin<'A', 2, Analog>,
|
||||||
pb0: Pin<'B', 0, Output<PushPull>>,
|
pb0: Pin<'B', 0, Output<PushPull>>,
|
||||||
|
pb12: Pin<'B', 12, Output<PushPull>>,
|
||||||
pc1: Pin<'C', 1, Input<PullDown>>,
|
pc1: Pin<'C', 1, Input<PullDown>>,
|
||||||
pc3: Pin<'C', 3, Analog>,
|
pc3: Pin<'C', 3, Analog>,
|
||||||
pc15: Pin<'C', 15, Input<PullDown>>,
|
pc15: Pin<'C', 15, Input<PullDown>>,
|
||||||
|
@ -65,7 +99,7 @@ impl CalibrationData {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[derive(Zeroable)]
|
#[derive(Zeroable)]
|
||||||
struct Calibration {
|
struct Calibration {
|
||||||
data: [CalibrationData; 3],
|
data: [CalibrationData; 11],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Calibration {
|
impl Calibration {
|
||||||
|
@ -75,7 +109,7 @@ impl Calibration {
|
||||||
};
|
};
|
||||||
fn new () -> Calibration {
|
fn new () -> Calibration {
|
||||||
return Calibration {
|
return Calibration {
|
||||||
data: [CalibrationData::new(0, CalibrationData::ADC_MAX); 3],
|
data: [CalibrationData::new(0, CalibrationData::ADC_MAX); 11],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,6 +127,8 @@ fn main() -> ! {
|
||||||
let mut gpioa = p.GPIOA.split();
|
let mut gpioa = p.GPIOA.split();
|
||||||
let mut gpiob = p.GPIOB.split();
|
let mut gpiob = p.GPIOB.split();
|
||||||
let mut gpioc = p.GPIOC.split();
|
let mut gpioc = p.GPIOC.split();
|
||||||
|
let mut gpiod = p.GPIOD.split();
|
||||||
|
let mut gpioe = p.GPIOE.split();
|
||||||
|
|
||||||
// configure clock
|
// configure clock
|
||||||
let clocks = rcc
|
let clocks = rcc
|
||||||
|
@ -135,25 +171,32 @@ fn main() -> ! {
|
||||||
let mut cal = load_calibration(&mut flash_writer);
|
let mut cal = load_calibration(&mut flash_writer);
|
||||||
|
|
||||||
// ====================== Pin setup =================
|
// ====================== Pin setup =================
|
||||||
let mut input_pins = MyPins {
|
let mut io_pins = MyPins {
|
||||||
pa1: gpioa.pa1.into_analog(&mut gpioa.crl),
|
pa1: gpioa.pa1.into_analog(&mut gpioa.crl),
|
||||||
pa2: gpioa.pa2.into_analog(&mut gpioa.crl),
|
pa2: gpioa.pa2.into_analog(&mut gpioa.crl),
|
||||||
pb0: gpiob.pb0.into_push_pull_output(&mut gpiob.crl),
|
pb0: gpiob.pb0.into_push_pull_output(&mut gpiob.crl),
|
||||||
|
pb12: gpiob.pb12.into_push_pull_output(&mut gpiob.crh),
|
||||||
pc1: gpioc.pc1.into_pull_down_input(&mut gpioc.crl),
|
pc1: gpioc.pc1.into_pull_down_input(&mut gpioc.crl),
|
||||||
pc3: gpioc.pc3.into_analog(&mut gpioc.crl),
|
pc3: gpioc.pc3.into_analog(&mut gpioc.crl),
|
||||||
pc15: gpioc.pc15.into_pull_down_input(&mut gpioc.crh),
|
pc15: gpioc.pc15.into_pull_down_input(&mut gpioc.crh),
|
||||||
};
|
};
|
||||||
|
|
||||||
// let mut last = get_report(&mut input_pins, &mut adc1, &cal);
|
// let mut last = get_report(&mut io_pins, &mut adc1, &cal);
|
||||||
|
|
||||||
// ====================== PWM setup =================
|
// ====================== PWM setup =================
|
||||||
let mut afio = p.AFIO.constrain();
|
let mut afio = p.AFIO.constrain();
|
||||||
let c1 = gpioa.pa0.into_alternate_push_pull(&mut gpioa.crl);
|
let c1 = gpioa.pa0.into_alternate_push_pull(&mut gpioa.crl);
|
||||||
let mut pwm = p
|
let mut integ_lt_pwm = p
|
||||||
.TIM2
|
.TIM2
|
||||||
.pwm_hz::<Tim2NoRemap, _, _>(c1, &mut afio.mapr, 1.kHz(), &clocks);
|
.pwm_hz::<Tim2NoRemap, _, _>(c1, &mut afio.mapr, 1.kHz(), &clocks);
|
||||||
pwm.enable(Channel::C1);
|
integ_lt_pwm.enable(Channel::C1);
|
||||||
let pwm_max = pwm.get_max_duty(); //48000 in our case
|
//TODO
|
||||||
|
// let c3 = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh);
|
||||||
|
// let mut rudder_trim_display_pwm = p
|
||||||
|
// .TIM2
|
||||||
|
// .pwm_hz::<Tim2NoRemap, _, _>(c3, &mut afio.mapr, 1.kHz(), &clocks);
|
||||||
|
// rudder_trim_display_pwm.enable(Channel::C3);
|
||||||
|
let pwm_max = integ_lt_pwm.get_max_duty(); //48000 in our case
|
||||||
|
|
||||||
// ====================== Timer setup ===============
|
// ====================== Timer setup ===============
|
||||||
// let timer = Instant;
|
// let timer = Instant;
|
||||||
|
@ -161,20 +204,21 @@ fn main() -> ! {
|
||||||
|
|
||||||
// ====================== Main loop =================
|
// ====================== Main loop =================
|
||||||
loop {
|
loop {
|
||||||
let report = get_report(&mut input_pins, &mut adc1, &cal);
|
let report = get_report(&mut io_pins, &mut adc1, &cal);
|
||||||
// TODO figure out timer and only send in like 1ms intervals or on change
|
// TODO figure out timer and only send in like 1ms intervals or on change
|
||||||
// if report != last {
|
// if report != last {
|
||||||
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)) => {
|
||||||
core::panic!("Failed to write consumer report, report is too big: {:?}", e)
|
core::panic!("Failed to write consumer report, report is too big")
|
||||||
}
|
}
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
// last = report;
|
// last = report;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// TODO use a suitable pin once we know the pinout
|
// set as indicator that this has happened
|
||||||
// input_pins.pb0.set_high(); // set as indicator that this has happened
|
// io_pins.pe1.set_high();
|
||||||
|
// io_pins.pe4.set_high();
|
||||||
core::panic!("Failed to write consumer report: {:?}", e)
|
core::panic!("Failed to write consumer report: {:?}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,31 +236,54 @@ fn main() -> ! {
|
||||||
else {
|
else {
|
||||||
pwm_val = output.integ_lt;
|
pwm_val = output.integ_lt;
|
||||||
}
|
}
|
||||||
pwm.set_duty(Channel::C1, pwm_val);
|
integ_lt_pwm.set_duty(Channel::C1, pwm_val);
|
||||||
|
|
||||||
// LED outputs
|
// LED outputs
|
||||||
if output.leds & 0x1 == 0x1 {
|
// ECAM
|
||||||
input_pins.pb0.set_high();
|
let mut ecam_row = [0; 3];
|
||||||
}
|
let mut ecam_col = [0; 6];
|
||||||
else {
|
// Match row and col
|
||||||
input_pins.pb0.set_low();
|
if output.leds & 0x54A != 0 { ecam_row[0] = 1; }
|
||||||
}
|
if output.leds & 0x1A94 != 0 { ecam_row[1] = 1; }
|
||||||
|
if output.leds & 0x21 != 0 { ecam_row[2] = 1; }
|
||||||
|
if output.leds & 0x6 != 0 { ecam_col[0] = 1; }
|
||||||
|
if output.leds & 0x18 != 0 { ecam_col[1] = 1; }
|
||||||
|
if output.leds & 0xE0 != 0 { ecam_col[2] = 1; }
|
||||||
|
if output.leds & 0x300 != 0 { ecam_col[3] = 1; }
|
||||||
|
if output.leds & 0xC00 != 0 { ecam_col[4] = 1; }
|
||||||
|
if output.leds & 0x1001 != 0 { ecam_col[5] = 1; }
|
||||||
|
// Set ECAM Out
|
||||||
|
define_ecam_output_states_row!(0, pb12, ecam_row, io_pins); // Row 1
|
||||||
|
// define_ecam_output_states_row!(1, pe13, ecam_row, io_pins); // Row 2
|
||||||
|
// define_ecam_output_states_row!(2, pe9, ecam_row, io_pins); // Row 3
|
||||||
|
// define_ecam_output_states_col!(0, pd9, ecam_row, io_pins); // Col 1
|
||||||
|
// define_ecam_output_states_col!(1, pc7, ecam_row, io_pins); // Col 2
|
||||||
|
// define_ecam_output_states_col!(2, pc8, ecam_row, io_pins); // Col 3
|
||||||
|
// define_ecam_output_states_col!(3, pd10, ecam_row, io_pins); // Col 4
|
||||||
|
// define_ecam_output_states_col!(4, pd8, ecam_row, io_pins); // Col 5
|
||||||
|
// define_ecam_output_states_col!(5, pb11, ecam_row, io_pins); // Col 6
|
||||||
|
// Other Indicators
|
||||||
|
// define_output_states!(0x2000, pb7, output, io_pins); // DOOR OPEN
|
||||||
|
// define_output_states!(0x4000, pb6, output, io_pins); // DOOR FAULT
|
||||||
|
// define_output_states!(0x8000, pe2, output, io_pins); // ENG 1 FAULT
|
||||||
|
// define_output_states!(0x10000, pe1, output, io_pins); // ENG 1 FIRE
|
||||||
|
// define_output_states!(0x20000, pe3, output, io_pins); // ENG 2 FAULT
|
||||||
|
|
||||||
// Check generic input field
|
// Check generic input field
|
||||||
// Calibration bit
|
// Calibration bit
|
||||||
if output.generic & 0x1 == 0x1 {
|
if output.generic & 0x1 == 0x1 {
|
||||||
calibration_active = true;
|
calibration_active = true;
|
||||||
if !calibration_min_done && output.generic & 0x2 == 0x2 {
|
if !calibration_min_done && output.generic & 0x2 == 0x2 {
|
||||||
cal.data[0].min = adc1.read(&mut input_pins.pa1).unwrap();
|
cal.data[0].min = adc1.read(&mut io_pins.pa1).unwrap();
|
||||||
cal.data[1].min = adc1.read(&mut input_pins.pa2).unwrap();
|
cal.data[1].min = adc1.read(&mut io_pins.pa2).unwrap();
|
||||||
calibration_min_done = true;
|
calibration_min_done = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if calibration_active {
|
if calibration_active {
|
||||||
let mut values: [u16; 2] = [0; 2];
|
let mut values: [u16; 2] = [0; 2];
|
||||||
values[0] = adc1.read(&mut input_pins.pa1).unwrap();
|
values[0] = adc1.read(&mut io_pins.pa1).unwrap();
|
||||||
values[1] = adc1.read(&mut input_pins.pa2).unwrap();
|
values[1] = adc1.read(&mut io_pins.pa2).unwrap();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
if values[i] > cal.data[i].min {
|
if values[i] > cal.data[i].min {
|
||||||
|
@ -233,7 +300,7 @@ fn main() -> ! {
|
||||||
}
|
}
|
||||||
let save_success = save_calibration(&mut flash_writer, &cal);
|
let save_success = save_calibration(&mut flash_writer, &cal);
|
||||||
if save_success {
|
if save_success {
|
||||||
pwm.set_duty(Channel::C1, pwm_max);
|
integ_lt_pwm.set_duty(Channel::C1, pwm_max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
calibration_active = false;
|
calibration_active = false;
|
||||||
|
@ -256,13 +323,13 @@ fn calculate_factor(min: u16, max: u16) -> f32 {
|
||||||
|
|
||||||
// Returns a CustomInputReport from the inputs given
|
// Returns a CustomInputReport from the inputs given
|
||||||
fn get_report(pins: &mut MyPins, adc1: &mut adc::Adc<pac::ADC1>, cal: &Calibration) -> CustomInputReport {
|
fn get_report(pins: &mut MyPins, adc1: &mut adc::Adc<pac::ADC1>, cal: &Calibration) -> CustomInputReport {
|
||||||
let mut values: [u16; 3] = [0; 3];
|
// Read axis
|
||||||
|
let mut values: [u16; 11] = [0; 11];
|
||||||
values[0] = adc1.read(&mut pins.pa1).unwrap();
|
values[0] = adc1.read(&mut pins.pa1).unwrap();
|
||||||
values[1] = adc1.read(&mut pins.pc3).unwrap();
|
values[1] = adc1.read(&mut pins.pc3).unwrap();
|
||||||
let mut buttons: u16 = 0;
|
|
||||||
|
|
||||||
// Axis
|
// Apply calibration to axis data
|
||||||
let mut values_norm: [u16; 3] = [0; 3];
|
let mut values_norm: [u16; 11] = [0; 11];
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
if values[i] < cal.data[i].min {
|
if values[i] < cal.data[i].min {
|
||||||
|
@ -281,18 +348,8 @@ fn get_report(pins: &mut MyPins, adc1: &mut adc::Adc<pac::ADC1>, cal: &Calibrati
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
// if pins.pb0.is_high() {
|
let mut buttons: u16 = 0;
|
||||||
// buttons += 0x01;
|
// if pins.pb0.is_high() { buttons += 0x1; }
|
||||||
// }
|
|
||||||
if pins.pc1.is_high() {
|
|
||||||
buttons += 0x02;
|
|
||||||
}
|
|
||||||
// if pins.pc3.is_high() {
|
|
||||||
// buttons += 0x04;
|
|
||||||
// }
|
|
||||||
if pins.pc15.is_high() {
|
|
||||||
buttons += 0x08;
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomInputReport {
|
CustomInputReport {
|
||||||
report_id: 1,
|
report_id: 1,
|
||||||
|
|
Loading…
Reference in a new issue