use crate::rcc::AHB1;
use crate::stm32::{TSC};
use crate::gpio::gpiob::{PB4, PB5, PB6, PB7};
use crate::gpio::{AF9, Alternate, Output, OpenDrain, PushPull};
#[derive(Debug, Copy, Clone)]
pub enum Event {
MaxCountError,
EndOfAcquisition
}
#[derive(Debug, Copy, Clone)]
pub enum Error {
MaxCountError,
InvalidPin(u32)
}
pub trait SamplePin<TSC> {
const GROUP: u32;
const OFFSET: u32;
}
impl SamplePin<TSC> for PB4<Alternate<AF9, Output<OpenDrain>>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 0;
}
impl SamplePin<TSC> for PB5<Alternate<AF9, Output<OpenDrain>>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 1;
}
impl SamplePin<TSC> for PB6<Alternate<AF9, Output<OpenDrain>>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 2;
}
impl SamplePin<TSC> for PB7<Alternate<AF9, Output<OpenDrain>>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 3;
}
pub trait ChannelPin<TSC> {
const GROUP: u32;
const OFFSET: u32;
}
impl ChannelPin<TSC> for PB4<Alternate<AF9, Output<PushPull>>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 0;
}
impl ChannelPin<TSC> for PB5<Alternate<AF9, Output<PushPull>>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 1;
}
impl ChannelPin<TSC> for PB6<Alternate<AF9, Output<PushPull>>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 2;
}
impl ChannelPin<TSC> for PB7<Alternate<AF9, Output<PushPull>>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 3;
}
pub struct Tsc<SPIN> {
sample_pin: SPIN,
tsc: TSC
}
#[derive(Debug, Copy, Clone)]
pub struct Config {
pub clock_prescale: Option<ClockPrescaler>,
pub max_count_error: Option<MaxCountError>,
pub charge_transfer_high: Option<ChargeDischargeTime>,
pub charge_transfer_low: Option<ChargeDischargeTime>,
}
#[derive(Debug, Copy, Clone)]
pub enum ClockPrescaler {
Hclk = 0b000,
HclkDiv2 = 0b001,
HclkDiv4 = 0b010,
HclkDiv8 = 0b011,
HclkDiv16 = 0b100,
HclkDiv32 = 0b101,
HclkDiv64 = 0b110,
HclkDiv128 = 0b111,
}
#[derive(Debug, Copy, Clone)]
pub enum MaxCountError {
U255 = 000,
U511 = 001,
U1023 = 010,
U2047 = 011,
U4095 = 100,
U8191 = 101,
U16383 = 110
}
#[derive(Debug, Copy, Clone)]
pub enum ChargeDischargeTime {
C1 = 0b0000,
C2 = 0b0001,
C3 = 0b0010,
C4 = 0b0011,
C5 = 0b0100,
C6 = 0b0101,
C7 = 0b0110,
C8 = 0b0111,
C9 = 0b1000,
C10 = 0b1001,
C11 = 0b1010,
C12 = 0b1011,
C13 = 0b1100,
C14 = 0b1101,
C15 = 0b1110,
C16 = 0b1111,
}
impl<SPIN> Tsc<SPIN> {
pub fn tsc(tsc: TSC, sample_pin: SPIN, ahb: &mut AHB1, cfg: Option<Config>) -> Self
where SPIN: SamplePin<TSC>
{
ahb.enr().modify(|_, w| w.tscen().set_bit());
ahb.rstr().modify(|_, w| w.tscrst().set_bit());
ahb.rstr().modify(|_, w| w.tscrst().clear_bit());
let config = cfg.unwrap_or(Config {
clock_prescale: None,
max_count_error: None,
charge_transfer_high: None,
charge_transfer_low: None
});
tsc.cr.write(|w| unsafe {
w.ctph()
.bits(config.charge_transfer_high.unwrap_or(ChargeDischargeTime::C2) as u8)
.ctpl()
.bits(config.charge_transfer_low.unwrap_or(ChargeDischargeTime::C2) as u8)
.sse()
.set_bit()
.ssd()
.bits(16)
.pgpsc()
.bits(config.clock_prescale.unwrap_or(ClockPrescaler::Hclk) as u8)
.mcv()
.bits(config.max_count_error.unwrap_or(MaxCountError::U8191) as u8)
.tsce()
.set_bit()
});
let bit_pos = SPIN::OFFSET + (4 * (SPIN::GROUP - 1));
tsc.iohcr.write(|w| unsafe {
w.bits(1 << bit_pos)
});
tsc.ioscr.write(|w| unsafe { w.bits(1 << bit_pos) });
tsc.iogcsr.write(|w| { w.g2e().set_bit() });
tsc.icr.write(|w| {
w.eoaic().set_bit()
.mceic().set_bit()
});
Tsc {
tsc: tsc,
sample_pin: sample_pin,
}
}
pub fn start<PIN>(&self, _input: &mut PIN)
where PIN: ChannelPin<TSC>
{
self.clear(Event::EndOfAcquisition);
self.clear(Event::MaxCountError);
self.tsc.cr.modify(|_, w| {
w.iodef().clear_bit()
});
let bit_pos = PIN::OFFSET + (4 * (PIN::GROUP - 1));
self.tsc.ioccr.write(|w| unsafe {
w.bits(1 << bit_pos)
});
self.tsc.cr.modify(|_, w| { w.start().set_bit() });
}
pub fn clear(&self, event: Event) {
match event {
Event::EndOfAcquisition => {
self.tsc.icr.write(|w| { w.eoaic().set_bit() });
},
Event::MaxCountError => {
self.tsc.icr.write(|w| { w.mceic().set_bit() });
},
}
}
pub fn acquire<PIN>(&self, input: &mut PIN) -> Result<u16, Error>
where PIN: ChannelPin<TSC>
{
self.start(input);
let result = loop {
let isr = self.tsc.isr.read();
if isr.eoaf().bit_is_set() {
self.tsc.icr.write(|w| { w.eoaic().set_bit() });
break Ok(self.read_unchecked())
} else if isr.mcef().bit_is_set() {
self.tsc.icr.write(|w| { w.mceic().set_bit() });
break Err(Error::MaxCountError)
}
};
self.tsc.ioccr.write(|w| unsafe { w.bits(0b0) });
result
}
pub fn read<PIN>(&self, _input: &mut PIN) -> Result<u16, Error>
where PIN: ChannelPin<TSC>
{
let bit_pos = PIN::OFFSET + (4 * (PIN::GROUP - 1));
let channel = self.tsc.ioccr.read().bits();
if channel == (1 << bit_pos) {
Ok(self.read_unchecked())
} else {
Err(Error::InvalidPin(channel))
}
}
pub fn read_unchecked(&self) -> u16 {
self.tsc.iog2cr.read().cnt().bits()
}
pub fn in_progress(&mut self) -> bool {
self.tsc.cr.read().start().bit_is_set()
}
pub fn listen(&mut self, event: Event){
match event {
Event::EndOfAcquisition => {
self.tsc.ier.modify(|_, w| w.eoaie().set_bit());
},
Event::MaxCountError => {
self.tsc.ier.modify(|_, w| w.mceie().set_bit());
},
}
}
pub fn unlisten(&self, event: Event) {
match event {
Event::EndOfAcquisition => {
self.tsc.ier.modify(|_, w| w.eoaie().clear_bit());
},
Event::MaxCountError => {
self.tsc.ier.modify(|_, w| w.mceie().clear_bit());
},
}
}
pub fn free(self) -> (TSC, SPIN) {
(self.tsc, self.sample_pin)
}
}