use crate::gpio::gpiob::{PB4, PB5, PB6, PB7};
use crate::gpio::{Alternate, OpenDrain, PushPull};
use crate::rcc::{Enable, Reset, AHB1};
use crate::stm32::TSC;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Event {
MaxCountError,
EndOfAcquisition,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
MaxCountError,
InvalidPin(u32),
}
pub trait SamplePin<TSC> {
const GROUP: u32;
const OFFSET: u32;
}
impl SamplePin<TSC> for PB4<Alternate<OpenDrain, 9>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 0;
}
impl SamplePin<TSC> for PB5<Alternate<OpenDrain, 9>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 1;
}
impl SamplePin<TSC> for PB6<Alternate<OpenDrain, 9>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 2;
}
impl SamplePin<TSC> for PB7<Alternate<OpenDrain, 9>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 3;
}
pub trait ChannelPin<TSC> {
const GROUP: u32;
const OFFSET: u32;
}
impl ChannelPin<TSC> for PB4<Alternate<PushPull, 9>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 0;
}
impl ChannelPin<TSC> for PB5<Alternate<PushPull, 9>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 1;
}
impl ChannelPin<TSC> for PB6<Alternate<PushPull, 9>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 2;
}
impl ChannelPin<TSC> for PB7<Alternate<PushPull, 9>> {
const GROUP: u32 = 2;
const OFFSET: u32 = 3;
}
pub struct Tsc<SPIN> {
sample_pin: SPIN,
tsc: TSC,
}
#[derive(Clone, Copy, Debug, PartialEq)]
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>,
pub spread_spectrum_deviation: Option<u8>,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ClockPrescaler {
Hclk = 0b000,
HclkDiv2 = 0b001,
HclkDiv4 = 0b010,
HclkDiv8 = 0b011,
HclkDiv16 = 0b100,
HclkDiv32 = 0b101,
HclkDiv64 = 0b110,
HclkDiv128 = 0b111,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MaxCountError {
U255 = 0b000,
U511 = 0b001,
U1023 = 0b010,
U2047 = 0b011,
U4095 = 0b100,
U8191 = 0b101,
U16383 = 0b110,
}
#[derive(Clone, Copy, Debug, PartialEq)]
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>,
{
TSC::enable(ahb);
TSC::reset(ahb);
let config = cfg.unwrap_or(Config {
clock_prescale: None,
max_count_error: None,
charge_transfer_high: None,
charge_transfer_low: None,
spread_spectrum_deviation: 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,
)
.pgpsc()
.bits(config.clock_prescale.unwrap_or(ClockPrescaler::Hclk) as u8)
.mcv()
.bits(config.max_count_error.unwrap_or(MaxCountError::U8191) as u8)
.sse()
.bit(config.spread_spectrum_deviation.is_some())
.ssd()
.bits(config.spread_spectrum_deviation.unwrap_or(0u8))
.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, 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)
}
}