aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarun <[email protected]>2024-04-22 10:22:04 -0400
committerKarun <[email protected]>2024-05-02 17:17:38 -0400
commit0febc24de73f8cf2bd0e3a7e7409f19aeaf00b1c (patch)
tree29ea68b20ecb64f45a1c6fbcec521457276c3470
parent45a2abc392df91ce6963ac0956f48f22bfa1489b (diff)
Initial fill out of driver without IO considerations
-rw-r--r--embassy-stm32/build.rs32
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/tsc/enums.rs100
-rw-r--r--embassy-stm32/src/tsc/mod.rs357
4 files changed, 491 insertions, 0 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index ba118f338..a84af258e 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -1030,6 +1030,38 @@ fn main() {
1030 (("octospi", "NCS"), quote!(crate::ospi::NSSPin)), 1030 (("octospi", "NCS"), quote!(crate::ospi::NSSPin)),
1031 (("octospi", "CLK"), quote!(crate::ospi::SckPin)), 1031 (("octospi", "CLK"), quote!(crate::ospi::SckPin)),
1032 (("octospi", "NCLK"), quote!(crate::ospi::NckPin)), 1032 (("octospi", "NCLK"), quote!(crate::ospi::NckPin)),
1033 (("tsc", "G1_IO1"), quote!(crate::ospi::G1IO1Pin)),
1034 (("tsc", "G1_IO2"), quote!(crate::ospi::G1IO2Pin)),
1035 (("tsc", "G1_IO3"), quote!(crate::ospi::G1IO3Pin)),
1036 (("tsc", "G1_IO4"), quote!(crate::ospi::G1IO4Pin)),
1037 (("tsc", "G2_IO1"), quote!(crate::ospi::G2IO1Pin)),
1038 (("tsc", "G2_IO2"), quote!(crate::ospi::G2IO2Pin)),
1039 (("tsc", "G2_IO3"), quote!(crate::ospi::G2IO3Pin)),
1040 (("tsc", "G2_IO4"), quote!(crate::ospi::G2IO4Pin)),
1041 (("tsc", "G3_IO1"), quote!(crate::ospi::G3IO1Pin)),
1042 (("tsc", "G3_IO2"), quote!(crate::ospi::G3IO2Pin)),
1043 (("tsc", "G3_IO3"), quote!(crate::ospi::G3IO3Pin)),
1044 (("tsc", "G3_IO4"), quote!(crate::ospi::G3IO4Pin)),
1045 (("tsc", "G4_IO1"), quote!(crate::ospi::G4IO1Pin)),
1046 (("tsc", "G4_IO2"), quote!(crate::ospi::G4IO2Pin)),
1047 (("tsc", "G4_IO3"), quote!(crate::ospi::G4IO3Pin)),
1048 (("tsc", "G4_IO4"), quote!(crate::ospi::G4IO4Pin)),
1049 (("tsc", "G5_IO1"), quote!(crate::ospi::G5IO1Pin)),
1050 (("tsc", "G5_IO2"), quote!(crate::ospi::G5IO2Pin)),
1051 (("tsc", "G5_IO3"), quote!(crate::ospi::G5IO3Pin)),
1052 (("tsc", "G5_IO4"), quote!(crate::ospi::G5IO4Pin)),
1053 (("tsc", "G6_IO1"), quote!(crate::ospi::G6IO1Pin)),
1054 (("tsc", "G6_IO2"), quote!(crate::ospi::G6IO2Pin)),
1055 (("tsc", "G6_IO3"), quote!(crate::ospi::G6IO3Pin)),
1056 (("tsc", "G6_IO4"), quote!(crate::ospi::G6IO4Pin)),
1057 (("tsc", "G7_IO1"), quote!(crate::ospi::G7IO1Pin)),
1058 (("tsc", "G7_IO2"), quote!(crate::ospi::G7IO2Pin)),
1059 (("tsc", "G7_IO3"), quote!(crate::ospi::G7IO3Pin)),
1060 (("tsc", "G7_IO4"), quote!(crate::ospi::G7IO4Pin)),
1061 (("tsc", "G8_IO1"), quote!(crate::ospi::G8IO1Pin)),
1062 (("tsc", "G8_IO2"), quote!(crate::ospi::G8IO2Pin)),
1063 (("tsc", "G8_IO3"), quote!(crate::ospi::G8IO3Pin)),
1064 (("tsc", "G8_IO4"), quote!(crate::ospi::G8IO4Pin)),
1033 ].into(); 1065 ].into();
1034 1066
1035 for p in METADATA.peripherals { 1067 for p in METADATA.peripherals {
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 1f4e9ab1e..dd89618ef 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -103,6 +103,8 @@ pub mod sdmmc;
103pub mod spi; 103pub mod spi;
104#[cfg(ucpd)] 104#[cfg(ucpd)]
105pub mod ucpd; 105pub mod ucpd;
106#[cfg(tsc)]
107pub mod tsc;
106#[cfg(uid)] 108#[cfg(uid)]
107pub mod uid; 109pub mod uid;
108#[cfg(usart)] 110#[cfg(usart)]
diff --git a/embassy-stm32/src/tsc/enums.rs b/embassy-stm32/src/tsc/enums.rs
new file mode 100644
index 000000000..6dfc8709c
--- /dev/null
+++ b/embassy-stm32/src/tsc/enums.rs
@@ -0,0 +1,100 @@
1/// Charge transfer pulse cycles
2#[allow(missing_docs)]
3#[derive(Copy, Clone)]
4pub enum ChargeTransferPulseCycle {
5 _1,
6 _2,
7 _3,
8 _4,
9 _5,
10 _6,
11 _7,
12 _8,
13 _9,
14 _10,
15 _11,
16 _12,
17 _13,
18 _14,
19 _15,
20 _16,
21}
22
23impl Into<u8> for ChargeTransferPulseCycle {
24 fn into(self) -> u8 {
25 match self {
26 ChargeTransferPulseCycle::_1 => 0,
27 ChargeTransferPulseCycle::_2 => 1,
28 ChargeTransferPulseCycle::_3 => 2,
29 ChargeTransferPulseCycle::_4 => 3,
30 ChargeTransferPulseCycle::_5 => 4,
31 ChargeTransferPulseCycle::_6 => 5,
32 ChargeTransferPulseCycle::_7 => 6,
33 ChargeTransferPulseCycle::_8 => 7,
34 ChargeTransferPulseCycle::_9 => 8,
35 ChargeTransferPulseCycle::_10 => 9,
36 ChargeTransferPulseCycle::_11 => 10,
37 ChargeTransferPulseCycle::_12 => 11,
38 ChargeTransferPulseCycle::_13 => 12,
39 ChargeTransferPulseCycle::_14 => 13,
40 ChargeTransferPulseCycle::_15 => 14,
41 ChargeTransferPulseCycle::_16 => 15,
42 }
43 }
44}
45
46/// Prescaler divider
47#[allow(missing_docs)]
48#[derive(Copy, Clone)]
49pub enum PGPrescalerDivider {
50 _1,
51 _2,
52 _4,
53 _8,
54 _16,
55 _32,
56 _64,
57 _128,
58}
59
60impl Into<u8> for PGPrescalerDivider {
61 fn into(self) -> u8 {
62 match self {
63 PGPrescalerDivider::_1 => 0,
64 PGPrescalerDivider::_2 => 1,
65 PGPrescalerDivider::_4 => 2,
66 PGPrescalerDivider::_8 => 3,
67 PGPrescalerDivider::_16 => 4,
68 PGPrescalerDivider::_32 => 5,
69 PGPrescalerDivider::_64 => 6,
70 PGPrescalerDivider::_128 => 7,
71 }
72 }
73}
74
75/// Max count
76#[allow(missing_docs)]
77#[derive(Copy, Clone)]
78pub enum MaxCount {
79 _255,
80 _511,
81 _1023,
82 _2047,
83 _4095,
84 _8191,
85 _16383,
86}
87
88impl Into<u8> for MaxCount {
89 fn into(self) -> u8 {
90 match self {
91 MaxCount::_255 => 0,
92 MaxCount::_511 => 1,
93 MaxCount::_1023 => 2,
94 MaxCount::_2047 => 3,
95 MaxCount::_4095 => 4,
96 MaxCount::_8191 => 5,
97 MaxCount::_16383 => 6,
98 }
99 }
100}
diff --git a/embassy-stm32/src/tsc/mod.rs b/embassy-stm32/src/tsc/mod.rs
new file mode 100644
index 000000000..6bff642fa
--- /dev/null
+++ b/embassy-stm32/src/tsc/mod.rs
@@ -0,0 +1,357 @@
1//! TSC Peripheral Interface
2
3#![macro_use]
4
5pub mod enums;
6
7use crate::gpio::AnyPin;
8use crate::{pac::tsc::Tsc as Regs, rcc::RccPeripheral};
9use crate::{peripherals, Peripheral};
10use embassy_hal_internal::{into_ref, PeripheralRef};
11
12pub use enums::*;
13
14#[derive(Debug)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum Error {
17 /// Test error for TSC
18 Test,
19}
20
21pub enum PinType {
22 Channel,
23 Sample,
24 Shield,
25}
26
27pub struct TscGroup {}
28
29pub enum State {
30 Reset,
31 Ready,
32 Busy,
33 Error,
34}
35
36pub enum GroupStatus {
37 Ongoing,
38 Complete,
39}
40
41pub enum Group {
42 One,
43 Two,
44 Three,
45 Four,
46 Five,
47 Six,
48 Seven,
49 Eight,
50}
51
52impl Into<usize> for Group {
53 fn into(self) -> usize {
54 match self {
55 Group::One => 0,
56 Group::Two => 1,
57 Group::Three => 2,
58 Group::Four => 3,
59 Group::Five => 4,
60 Group::Six => 5,
61 Group::Seven => 6,
62 Group::Eight => 7,
63 }
64 }
65}
66
67pub struct Config {
68 pub ct_pulse_high_length: ChargeTransferPulseCycle,
69 pub ct_pulse_low_length: ChargeTransferPulseCycle,
70 pub spread_spectrum: bool,
71 pub spread_spectrum_deviation: u8,
72 pub spread_spectrum_prescaler: bool,
73 pub pulse_generator_prescaler: PGPrescalerDivider,
74 pub max_count_value: u8,
75 pub io_default_mode: bool,
76 pub synchro_pin_polarity: bool,
77 pub acquisition_mode: bool,
78 pub max_count_interrupt: bool,
79 pub channel_ios: u32,
80 pub shield_ios: u32,
81 pub sampling_ios: u32,
82}
83
84pub struct TSC<'d, T: Instance> {
85 _peri: PeripheralRef<'d, T>,
86 state: State,
87 config: Config,
88}
89
90impl<'d, T: Instance> TSC<'d, T> {
91 pub fn new(peri: impl Peripheral<P = T> + 'd, config: Config) -> Self {
92 into_ref!(peri);
93
94 // Need to check valid pin configuration input
95 // Need to configure pin
96 Self::new_inner(peri, config)
97 }
98
99 fn new_inner(peri: impl Peripheral<P = T> + 'd, config: Config) -> Self {
100 into_ref!(peri);
101
102 T::enable_and_reset();
103
104 T::REGS.cr().modify(|w| {
105 w.set_tsce(true);
106 w.set_ctph(config.ct_pulse_high_length.into());
107 w.set_ctpl(config.ct_pulse_low_length.into());
108 w.set_sse(config.spread_spectrum);
109 w.set_ssd(config.spread_spectrum_deviation);
110 w.set_sspsc(config.spread_spectrum_prescaler);
111 w.set_pgpsc(config.pulse_generator_prescaler.into());
112 w.set_mcv(config.max_count_value);
113 w.set_syncpol(config.synchro_pin_polarity);
114 w.set_am(config.acquisition_mode)
115 });
116
117 // Set IO configuration
118 // Disable Schmitt trigger hysteresis on all used TSC IOs
119 // T::REGS.iohcr().modify(|w| {
120 // w.
121 // });
122
123 // Set channel and shield IOs
124 // T::REGS.ioccr().modify(|w| {});
125
126 // Set sampling IOs
127 // T::REGS.ioscr().modify(|w| {
128 // w.set_g1_io1(val)
129 // });
130
131 // Set the groups to be acquired
132 // T::REGS.iogcsr().modify(|w| {
133 // w.set_g1e(val);
134 // });
135
136 // Disable interrupts
137 T::REGS.ier().modify(|w| {
138 w.set_eoaie(false);
139 w.set_mceie(false);
140 });
141
142 // Clear flags
143 T::REGS.icr().modify(|w| {
144 w.set_eoaic(true);
145 w.set_mceic(true);
146 });
147
148 Self {
149 _peri: peri,
150 state: State::Ready,
151 config,
152 }
153 }
154
155 pub fn start(&mut self) {
156 self.state = State::Busy;
157
158 // Disable interrupts
159 T::REGS.ier().modify(|w| {
160 w.set_eoaie(false);
161 w.set_mceie(false);
162 });
163
164 // Clear flags
165 T::REGS.icr().modify(|w| {
166 w.set_eoaic(true);
167 w.set_mceic(true);
168 });
169
170 // Set the touch sensing IOs not acquired to the default mode
171 T::REGS.cr().modify(|w| {
172 w.set_iodef(self.config.io_default_mode);
173 });
174
175 // Start the acquisition
176 T::REGS.cr().modify(|w| {
177 w.set_start(true);
178 });
179 }
180
181 pub fn start_it(&mut self) {
182 self.state = State::Busy;
183
184 // Enable interrupts
185 T::REGS.ier().modify(|w| {
186 w.set_eoaie(true);
187 w.set_mceie(self.config.max_count_interrupt);
188 });
189
190 // Clear flags
191 T::REGS.icr().modify(|w| {
192 w.set_eoaic(true);
193 w.set_mceic(true);
194 });
195
196 // Set the touch sensing IOs not acquired to the default mode
197 T::REGS.cr().modify(|w| {
198 w.set_iodef(self.config.io_default_mode);
199 });
200
201 // Start the acquisition
202 T::REGS.cr().modify(|w| {
203 w.set_start(true);
204 });
205 }
206
207 pub fn stop(&mut self) {
208 T::REGS.cr().modify(|w| {
209 w.set_start(false);
210 });
211
212 // Set the touch sensing IOs in low power mode
213 T::REGS.cr().modify(|w| {
214 w.set_iodef(false);
215 });
216
217 // Clear flags
218 T::REGS.icr().modify(|w| {
219 w.set_eoaic(true);
220 w.set_mceic(true);
221 });
222
223 self.state = State::Ready;
224 }
225
226 pub fn stop_it(&mut self) {
227 T::REGS.cr().modify(|w| {
228 w.set_start(false);
229 });
230
231 // Set the touch sensing IOs in low power mode
232 T::REGS.cr().modify(|w| {
233 w.set_iodef(false);
234 });
235
236 // Disable interrupts
237 T::REGS.ier().modify(|w| {
238 w.set_eoaie(false);
239 w.set_mceie(false);
240 });
241
242 // Clear flags
243 T::REGS.icr().modify(|w| {
244 w.set_eoaic(true);
245 w.set_mceic(true);
246 });
247
248 self.state = State::Ready;
249 }
250
251 pub fn poll_for_acquisition(&mut self) {
252 while self.get_state() == State::Busy {}
253 }
254
255 pub fn get_state(&mut self) -> State {
256 if self.state == State::Busy {
257 if T::REGS.isr().read().eoaf() {
258 if T::REGS.isr().read().mcef() {
259 self.state = State::Error
260 } else {
261 self.state = State::Ready
262 }
263 }
264 }
265 self.state
266 }
267
268 pub fn group_get_status(&mut self, index: Group) -> GroupStatus {
269 // Status bits are set by hardware when the acquisition on the corresponding
270 // enabled analog IO group is complete, cleared when new acquisition is started
271 let status = match index {
272 Group::One => T::REGS.iogcsr().read().g1s(),
273 Group::Two => T::REGS.iogcsr().read().g2s(),
274 Group::Three => T::REGS.iogcsr().read().g3s(),
275 Group::Four => T::REGS.iogcsr().read().g4s(),
276 Group::Five => T::REGS.iogcsr().read().g5s(),
277 Group::Six => T::REGS.iogcsr().read().g6s(),
278 Group::Seven => T::REGS.iogcsr().read().g7s(),
279 Group::Eight => T::REGS.iogcsr().read().g8s(),
280 };
281 match status {
282 true => GroupStatus::Complete,
283 false => GroupStatus::Ongoing,
284 }
285 }
286
287 pub fn group_get_value(&mut self, index: Group) -> u16 {
288 T::REGS.iogcr(index.into()).read().cnt()
289 }
290
291 // pub fn configure_io()
292
293 pub fn discharge_io(&mut self, status: bool) {
294 // Set the touch sensing IOs in low power mode
295 T::REGS.cr().modify(|w| {
296 w.set_iodef(!status);
297 });
298 }
299}
300
301impl<'d, T: Instance> Drop for TSC<'d, T> {
302 fn drop(&mut self) {
303 // Need to figure out what to do with the IOs
304 T::disable();
305 }
306}
307
308pub(crate) trait SealedInstance {
309 const REGS: Regs;
310}
311
312/// TSC instance trait
313#[allow(private_bounds)]
314pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
315
316foreach_peripheral!(
317 (tsc, $inst:ident) => {
318 impl SealedInstance for peripherals::$inst {
319 const REGS: Regs = crate::pac::$inst;
320 }
321
322 impl Instance for peripherals::$inst {}
323 };
324);
325
326pin_trait!(G1IO1Pin, Instance);
327pin_trait!(G1IO2Pin, Instance);
328pin_trait!(G1IO3Pin, Instance);
329pin_trait!(G1IO4Pin, Instance);
330pin_trait!(G2IO1Pin, Instance);
331pin_trait!(G2IO2Pin, Instance);
332pin_trait!(G2IO3Pin, Instance);
333pin_trait!(G2IO4Pin, Instance);
334pin_trait!(G3IO1Pin, Instance);
335pin_trait!(G3IO2Pin, Instance);
336pin_trait!(G3IO3Pin, Instance);
337pin_trait!(G3IO4Pin, Instance);
338pin_trait!(G4IO1Pin, Instance);
339pin_trait!(G4IO2Pin, Instance);
340pin_trait!(G4IO3Pin, Instance);
341pin_trait!(G4IO4Pin, Instance);
342pin_trait!(G5IO1Pin, Instance);
343pin_trait!(G5IO2Pin, Instance);
344pin_trait!(G5IO3Pin, Instance);
345pin_trait!(G5IO4Pin, Instance);
346pin_trait!(G6IO1Pin, Instance);
347pin_trait!(G6IO2Pin, Instance);
348pin_trait!(G6IO3Pin, Instance);
349pin_trait!(G6IO4Pin, Instance);
350pin_trait!(G7IO1Pin, Instance);
351pin_trait!(G7IO2Pin, Instance);
352pin_trait!(G7IO3Pin, Instance);
353pin_trait!(G7IO4Pin, Instance);
354pin_trait!(G8IO1Pin, Instance);
355pin_trait!(G8IO2Pin, Instance);
356pin_trait!(G8IO3Pin, Instance);
357pin_trait!(G8IO4Pin, Instance);