freeshipping-controller/src/main.rs

172 lines
4.9 KiB
Rust

//! Blinks an LED
//!
//! This assumes that a LED is connected to pc13 as is the case on the blue pill board.
//!
//! Note: Without additional hardware, PC13 should not be used to drive an LED, see page 5.1.2 of
//! the reference manaual for an explanation. This is not an issue on the blue pill.
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_std]
#![no_main]
extern crate panic_halt;
extern crate cortex_m_semihosting;
use nb::block;
use stm32f1xx_hal::{
prelude::*,
pac,
timer::Timer,
serial::Serial,
};
use cortex_m_rt::entry;
//use cortex_m_semihosting::hprintln;
use stm32f1xx_hal::adc;
extern crate byteorder;
use byteorder::{ByteOrder, LittleEndian};
struct RangeConverter {
// Input specifics
left: u16,
center: u16,
right: u16,
deadzone: u16,
// Output range
min: i16,
max: i16,
}
impl RangeConverter {
fn convert(&self, value: u16) -> i16 {
if value <= self.left {
return self.min
}
if value >= self.right {
return self.max
}
let cd: u16 = if value > self.center {
value - self.center
} else {
self.center - value
};
if cd <= self.deadzone {
return 0;
}
// Value outside of deadzone.
let cv: i16 = (cd - self.deadzone) as i16;
if value > self.center {
let md: i32 = ((self.right - self.center) - self.deadzone) as i32;
let val: i32 = (self.max as i32) * (cv as i32) / md;
return val as i16;
} else {
let md: i32 = ((self.center - self.left) - self.deadzone) as i32;
let val: i32 = (self.min as i32) * (cv as i32) / md;
return val as i16;
}
}
}
#[entry]
fn main() -> ! {
// Get access to the core peripherals from the cortex-m crate
let cp = cortex_m::Peripherals::take().unwrap();
// Get access to the device specific peripherals from the peripheral access crate
let dp = pac::Peripherals::take().unwrap();
// Take ownership over the raw flash and rcc devices and convert them into the corresponding
// HAL structs
let mut flash = dp.FLASH.constrain();
let mut rcc = dp.RCC.constrain();
let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
// Freeze the configuration of all the clocks in the system and store the frozen frequencies in
// `clocks`
let clocks = rcc.cfgr.adcclk(2.mhz()).freeze(&mut flash.acr);
//hprintln!("adc freq: {}", clocks.adcclk().0).unwrap();
// Acquire the GPIOC peripheral
let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
// Configure gpio C pin 13 as a push-pull output. The `crh` register is passed to the function
// in order to configure the port. For pins 0-7, crl should be passed instead.
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
// Configure the syst timer to trigger an update every second
let mut timer = Timer::syst(cp.SYST, 30.hz(), clocks);
let mut adc1 = adc::Adc::adc1(dp.ADC1, &mut rcc.apb2);
let mut ch0 = gpiob.pb0.into_analog(&mut gpiob.crl);
let mut ch1 = gpiob.pb1.into_analog(&mut gpiob.crl);
let mut ch2 = gpioa.pa0.into_analog(&mut gpioa.crl);
let fire = gpioc.pc14.into_pull_up_input(&mut gpioc.crh);
let tx = gpioa.pa2.into_alternate_push_pull(&mut gpioa.crl);
let rx = gpioa.pa3;
let serial = Serial::usart2(
dp.USART2,
(tx, rx),
&mut afio.mapr,
19_200.bps(),
clocks,
&mut rcc.apb1,
);
let (mut tx, mut _rx) = serial.split();
let rcx = RangeConverter{
left: 2064,
center: 3026,
right: 4096,
deadzone: 300,
min: -1000,
max: 1000,
};
let rcy = RangeConverter{
left: 2250,
center: 3000,
right: 4096,
deadzone: 100,
min: -1000,
max: 1000,
};
// Wait for the timer to trigger an update and change the state of the LED
loop {
block!(timer.wait()).unwrap();
led.set_high();
block!(timer.wait()).unwrap();
led.set_low();
let data0: u16 = adc1.read(&mut ch0).unwrap();
let data1: u16 = adc1.read(&mut ch1).unwrap();
let _data2: u16 = adc1.read(&mut ch2).unwrap();
let x: i16 = -rcx.convert(data0);
let y: i16 = rcy.convert(data1);
let mut bufx = [0, 0];
let mut bufy = [0, 0];
if fire.is_low() {
LittleEndian::write_i16(&mut bufx, x);
LittleEndian::write_i16(&mut bufy, y);
} else {
LittleEndian::write_i16(&mut bufx, 0);
LittleEndian::write_i16(&mut bufy, 0);
};
block!(tx.write(bufx[0])).ok();
block!(tx.write(bufx[1])).ok();
block!(tx.write(bufy[0])).ok();
block!(tx.write(bufy[1])).ok();
}
}