A320-homecockpit/Pedestal/firmware/src/main.rs

181 lines
4.3 KiB
Rust
Raw Normal View History

#![deny(unsafe_code)]
#![no_main]
#![no_std]
mod device;
use panic_halt as _;
use cortex_m::asm::delay;
use cortex_m_rt::entry;
use stm32f1xx_hal::{
adc,
gpio::{Analog, Pin},
pac,
prelude::*,
timer::{Channel, Tim2NoRemap},
};
use stm32f1xx_hal::usb::{Peripheral, UsbBus};
use usb_device::prelude::*;
use usbd_human_interface_device::prelude::*;
use crate::device::{CustomConfig, CustomInputReport, CustomOutputReport};
use core::cell::OnceCell;
struct MyPins {
pa1: Pin<'A', 1, Analog>,
pa2: Pin<'A', 2, Analog>,
}
struct CalibrationData {
min: u16,
max: u16,
factor: OnceCell<f32>,
}
struct Calibration {
integ_lt: CalibrationData,
flood_lt: CalibrationData,
}
#[entry]
fn main() -> ! {
// ====================== general setup =================
// Acquire peripherals
// let cp = cortex_m::Peripherals::take().unwrap();
let p = pac::Peripherals::take().unwrap();
let mut flash = p.FLASH.constrain();
let rcc = p.RCC.constrain();
// Setup GPIOA
let mut gpioa = p.GPIOA.split();
// configure clock
let clocks = rcc
.cfgr
.use_hse(16.MHz())
.sysclk(48.MHz())
.pclk1(24.MHz())
.freeze(&mut flash.acr);
// ====================== USB setup =================
assert!(clocks.usbclk_valid());
let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh);
usb_dp.set_low();
delay(clocks.sysclk().raw() / 100);
let usb = Peripheral {
usb: p.USB,
pin_dm: gpioa.pa11,
pin_dp: usb_dp.into_floating_input(&mut gpioa.crh),
};
let usb_bus = UsbBus::new(usb);
let mut consumer = UsbHidClassBuilder::new()
.add_device(CustomConfig::default())
.build(&usb_bus);
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("FLC Meow")
.product("Pedestal box")
.serial_number("01189998819991197253")
.build();
// ====================== ADC setup =================
// Setup ADC
let mut adc1 = adc::Adc::adc1(p.ADC1, clocks);
// ====================== Calibration ===============
let cal = Calibration {
integ_lt: CalibrationData {min: 100, max: 4000, factor: OnceCell::new()},
flood_lt: CalibrationData {min: 0, max: 0, factor: OnceCell::new()},
};
// ====================== Pin setup =================
let mut input_pins = MyPins {
pa1: gpioa.pa1.into_analog(&mut gpioa.crl),
pa2: gpioa.pa2.into_analog(&mut gpioa.crl),
};
let mut last = get_report(&mut input_pins, &mut adc1, &cal);
// ====================== PWM setup =================
let mut afio = p.AFIO.constrain();
let c1 = gpioa.pa0.into_alternate_push_pull(&mut gpioa.crl);
let mut pwm = p
.TIM2
.pwm_hz::<Tim2NoRemap, _, _>(c1, &mut afio.mapr, 1.kHz(), &clocks);
pwm.enable(Channel::C1);
let pwm_max = pwm.get_max_duty() as u16; //48000 in our case
// ====================== Main loop =================
loop {
let report = get_report(&mut input_pins, &mut adc1, &cal);
if report != last {
match consumer.device().write_report(&report) {
Err(UsbHidError::WouldBlock) => {}
Ok(_) => {
last = report;
}
Err(e) => {
core::panic!("Failed to write consumer report: {:?}", e)
}
}
}
if usb_dev.poll(&mut [&mut consumer]) {
match consumer.device().read_report() {
Err(UsbHidError::WouldBlock) => {}
Ok(output) => {
let pwm_val: u16;
if output.integ_lt > pwm_max {
pwm_val = pwm_max;
}
else {
pwm_val = output.integ_lt;
}
pwm.set_duty(Channel::C1, pwm_val);
}
Err(e) => {
core::panic!("Failed to write consumer report: {:?}", e)
}
}
}
}
}
// Returns a CustomInputReport from the inputs given
fn get_report(pins: &mut MyPins, adc1: &mut adc::Adc<pac::ADC1>, cal: &Calibration) -> CustomInputReport {
let integ_lt: u16 = adc1.read(&mut pins.pa1).unwrap();
let flood_lt: u16 = adc1.read(&mut pins.pa2).unwrap();
let buttons: u16 = 0;
let integ_lt_norm: u16;
if integ_lt < cal.integ_lt.min {
integ_lt_norm = 0;
}
else if integ_lt > cal.integ_lt.max {
integ_lt_norm = 4095;
}
else {
let factor: f32 = *cal.integ_lt.factor.get_or_init(|| cal.integ_lt.get_scale_factor());
integ_lt_norm = ((integ_lt - cal.integ_lt.min) as f32 * factor) as u16;
}
CustomInputReport {
x: integ_lt_norm.into(),
y: flood_lt.into(),
buttons,
}
}
impl CalibrationData {
const ADC_MAX: u16 = 4095;
fn get_scale_factor (&self) -> f32 {
return (Self::ADC_MAX / (Self::ADC_MAX - self.min - (Self::ADC_MAX - self.max))) as f32;
}
}