1use ch32v1::ch32v103 as pac;
2use riscv::interrupt::free;
3
4pub trait TimerBaseOp<Tim> {
5 type Result;
6
7 fn new(tim: Tim, config: TimBaseConfig) -> Self;
8 fn enable(&self) -> Self::Result;
9
10 fn disable(&self) -> Self::Result;
11}
12
13pub enum TimerError {
14 EnableFailed,
15 DisableFailed,
16}
17
18#[derive(PartialEq, Eq, Debug, Clone, Copy)]
19pub enum Tim {
20 Tim1,
21 Tim2,
22 Tim3,
23 Tim4,
24}
25
26#[derive(PartialEq, Eq, Debug, Clone, Copy)]
27pub enum CounterMode {
28 Up = 0,
29 Down = 1,
30}
31
32impl CounterMode {
33 pub fn val(&self) -> bool {
34 match self {
35 Self::Up => true,
36 Self::Down => false
37 }
38 }
39}
40
41#[derive(PartialEq, Eq, Debug, Clone, Copy)]
42pub enum ClockDivision {
43 Div1 = 0,
44 Div2 = 1,
45 Div3 = 2,
46}
47
48#[derive(PartialEq, Eq, Debug, Clone, Copy)]
49pub enum PSCReloadMode {
50 Update,
51 Immediate
52}
53
54#[derive(PartialEq, Eq, Debug, Clone, Copy)]
55pub struct TimBaseConfig {
56 pub prescaler: u16,
57 pub counter_mode: CounterMode,
58 pub period: u16,
59 pub clock_division: ClockDivision,
60 pub repetition_counter: u16,
61 pub psc_reload_mode: PSCReloadMode
62}
63
64pub enum ADVTimer {
65 TIM1,
66}
67
68pub struct AdvancedTimer {
69 pub tim: ADVTimer,
70 pub config: TimBaseConfig,
71}
72
73impl TimerBaseOp<ADVTimer> for AdvancedTimer {
74 type Result = nb::Result<(), TimerError>;
75
76 fn new(tim: ADVTimer, config: TimBaseConfig) -> Self {
77 let reg = match tim {
78 ADVTimer::TIM1 => unsafe { &(*(pac::TIM1::ptr())) }
79 };
80 free(|| {
81 unsafe {
82 reg.ctlr1.modify(|_, w| {
83 w.dir().bit(config.counter_mode.val())
85 .ckd().bits(config.clock_division as u8)
87 });
88 reg.atrlr.modify(|_, w| w.bits(config.period));
90 reg.psc.modify(|_, w| w.bits(config.prescaler));
92 reg.rptcr.modify(|_, w| w.bits(config.repetition_counter));
94 reg.swevgr.write(|w| w.bits(config.psc_reload_mode as u16))
96 }
97 });
98
99
100 Self {
101 tim: tim,
102 config: config,
103 }
104
105 }
106
107 #[inline]
108 fn enable(&self) -> Self::Result {
109 let reg = match self.tim {
110 ADVTimer::TIM1 => unsafe { &(*pac::TIM1::ptr()) },
111 };
112
113 free(|| {
114 reg.ctlr1.modify(|r, w| {
115 if r.cen().is_disabled() {
116 w.cen().enabled()
117 } else {
118 w
119 }
120 });
121
122 if reg.ctlr1.read().cen().is_enabled() {
123 Ok(())
124 } else {
125 Err(nb::Error::Other(TimerError::EnableFailed))
126 }
127 })
128 }
129
130 #[inline]
131 fn disable(&self) -> Self::Result {
132 let reg = match self.tim {
133 ADVTimer::TIM1 => unsafe { &(*pac::TIM1::ptr()) },
134 };
135
136 free(|| {
137 reg.ctlr1.modify(|r, w| {
138 if r.cen().is_enabled() {
139 w.cen().disabled()
140 } else {
141 w
142 }
143 });
144
145 if reg.ctlr1.read().cen().is_disabled() {
146 Ok(())
147 } else {
148 Err(nb::Error::Other(TimerError::DisableFailed))
149 }
150 })
151 }
152}