1use crate::pac::ADC;
4use core::marker::PhantomData;
5
6pub struct Unsigned32;
8
9pub struct Signed32;
11
12pub struct Unsigned16;
14
15pub struct Signed16;
17
18#[repr(u8)]
20#[derive(Clone, Copy, Debug)]
21pub enum ConversionTrigger {
22 Auto(u8), Cmtu, Timer3, Int0, Manual, }
38
39#[repr(u8)]
41#[derive(Clone, Copy, Debug)]
42pub enum VoltageReference {
43 AvddAvss = 0b000,
45 ExtAvss = 0b001,
47 AvddExt = 0b010,
49 ExtExt = 0b11,
51}
52
53#[derive(Clone, Copy, Debug)]
55pub enum ResultBufferMode {
56 SingleBuffer,
58 DoubleBuffer,
60}
61
62#[derive(Debug)]
64pub enum ConversionClock {
65 Frc,
67 Pb(u8),
69}
70
71#[derive(Clone, Copy, Debug)]
73#[repr(u8)]
74pub enum NegativeInput {
75 Vrefl = 0b0,
77 An1 = 0b1,
79}
80
81#[derive(Debug)]
83pub enum InputScan {
84 Off(u8),
87
88 On(u32),
91}
92
93pub struct AdcConfiguration {
95 conversion_trigger: ConversionTrigger,
96 auto_sample: bool,
97 voltage_reference: VoltageReference,
98 offset_calibration: bool,
99 conversions_per_irq: u8,
100 alt_sample_mode: bool,
101 result_buffer_mode: ResultBufferMode,
102 conversion_clock: ConversionClock,
103}
104
105impl Default for AdcConfiguration {
106 fn default() -> Self {
108 AdcConfiguration {
109 conversion_trigger: ConversionTrigger::Auto(31),
110 auto_sample: false,
111 voltage_reference: VoltageReference::AvddAvss,
112 offset_calibration: false,
113 conversions_per_irq: 1,
114 alt_sample_mode: false,
115 result_buffer_mode: ResultBufferMode::SingleBuffer,
116 conversion_clock: ConversionClock::Frc,
117 }
118 }
119}
120
121impl AdcConfiguration {
122 pub fn conversion_trigger(&mut self, conversion_trigger: ConversionTrigger) -> &mut Self {
125 if let ConversionTrigger::Auto(delay) = conversion_trigger {
126 assert!(delay > 0 && delay <= 31);
127 }
128 self.conversion_trigger = conversion_trigger;
129 self
130 }
131
132 pub fn auto_sample(&mut self, auto_sample: bool) -> &mut Self {
134 self.auto_sample = auto_sample;
135 self
136 }
137 pub fn voltage_reference(&mut self, voltage_reference: VoltageReference) -> &mut Self {
139 self.voltage_reference = voltage_reference;
140 self
141 }
142
143 pub fn offset_calibration(&mut self, offset_calibration: bool) -> &mut Self {
145 self.offset_calibration = offset_calibration;
146 self
147 }
148
149 pub fn conversions_per_irq(&mut self, conversions_per_irq: u8) -> &mut Self {
152 assert!(conversions_per_irq > 0 && conversions_per_irq <= 16);
153 self.conversions_per_irq = conversions_per_irq;
154 self
155 }
156
157 pub fn alt_sample_mode(&mut self, alt_sample_mode: bool) -> &mut Self {
159 self.alt_sample_mode = alt_sample_mode;
160 self
161 }
162
163 pub fn result_buffer_mode(&mut self, result_buffer_mode: ResultBufferMode) -> &mut Self {
165 self.result_buffer_mode = result_buffer_mode;
166 self
167 }
168
169 pub fn conversion_clock(&mut self, conversion_clock: ConversionClock) -> &mut Self {
171 self.conversion_clock = conversion_clock;
172 self
173 }
174}
175
176pub struct Adc<F> {
177 adc: ADC,
178 _format: PhantomData<F>,
179}
180
181impl Adc<Unsigned32> {
182 pub fn new_u32(adc: ADC, fractional: bool) -> Self {
185 let mut adc = Adc {
186 adc,
187 _format: PhantomData,
188 };
189 adc.init(0b100, fractional);
190 adc
191 }
192
193 pub fn read(&self, index: usize) -> u32 {
196 let regs = unsafe { core::slice::from_raw_parts(self.adc.buf0.as_ptr(), 16 * 4) };
197 regs[4 * index]
198 }
199}
200
201impl Adc<Signed32> {
202 pub fn new_i32(adc: ADC, fractional: bool) -> Self {
205 let mut adc = Adc {
206 adc,
207 _format: PhantomData,
208 };
209 adc.init(0b101, fractional);
210 adc
211 }
212
213 pub fn read(&self, index: usize) -> i32 {
216 let regs =
217 unsafe { core::slice::from_raw_parts(self.adc.buf0.as_ptr() as *const i32, 16 * 4) };
218 regs[4 * index]
219 }
220}
221
222impl Adc<Unsigned16> {
223 pub fn new_u16(adc: ADC, fractional: bool) -> Self {
226 let mut adc = Adc {
227 adc,
228 _format: PhantomData,
229 };
230 adc.init(0b000, fractional);
231 adc
232 }
233
234 pub fn read(&self, index: usize) -> u16 {
237 let regs =
238 unsafe { core::slice::from_raw_parts(self.adc.buf0.as_ptr() as *const u16, 16 * 8) };
239 regs[8 * index]
240 }
241}
242
243impl Adc<Signed16> {
244 pub fn new_i16(adc: ADC, fractional: bool) -> Self {
247 let mut adc = Adc {
248 adc,
249 _format: PhantomData,
250 };
251 adc.init(0b001, fractional);
252 adc
253 }
254
255 pub fn read(&self, index: usize) -> i16 {
258 let regs =
259 unsafe { core::slice::from_raw_parts(self.adc.buf0.as_ptr() as *const i16, 16 * 8) };
260 regs[8 * index]
261 }
262}
263
264impl<F> Adc<F> {
265 fn init(&mut self, format: u8, fractional: bool) {
267 let form = if fractional { format | 0b010 } else { format };
268 self.adc
269 .con1
270 .modify(|_, w| unsafe { w.on().clear_bit().form().bits(form) });
271 }
272
273 pub fn configure(&mut self, config: &AdcConfiguration) {
275 let (ssrc, samc) = match config.conversion_trigger {
276 ConversionTrigger::Auto(samc) => (0b111, samc),
277 ConversionTrigger::Cmtu => (0b011, 0),
278 ConversionTrigger::Timer3 => (0b010, 0),
279 ConversionTrigger::Int0 => (0b001, 0),
280 ConversionTrigger::Manual => (0b000, 0),
281 };
282 unsafe {
283 self.adc.con1clr.write_with_zero(|w| w.on().bit(true));
284 }
285 self.adc
286 .con1
287 .modify(|_, w| unsafe { w.ssrc().bits(ssrc).asam().bit(config.auto_sample) });
288 self.adc.con2.modify(|_, w| unsafe {
289 w.vcfg()
290 .bits(config.voltage_reference as u8)
291 .offcal()
292 .bit(config.offset_calibration)
293 .bufm()
294 .bit(config.result_buffer_mode as u8 != 0)
295 .smpi()
296 .bits(config.conversions_per_irq)
297 .alts()
298 .bit(config.alt_sample_mode)
299 });
300 let (adrc, adcs) = match config.conversion_clock {
301 ConversionClock::Pb(adcs) => (false, adcs),
302 ConversionClock::Frc => (true, 0),
303 };
304 self.adc
305 .con3
306 .modify(|_, w| unsafe { w.adrc().bit(adrc).samc().bits(samc).adcs().bits(adcs) });
307 unsafe {
308 self.adc.con1set.write_with_zero(|w| w.on().set_bit());
309 }
310 }
311
312 pub fn select_pos_input(&mut self, input: InputScan) {
314 match input {
315 InputScan::Off(channel) => {
316 self.adc
317 .chs
318 .modify(|_, w| unsafe { w.ch0sa().bits(channel) });
319 unsafe {
320 self.adc.con2clr.write_with_zero(|w| w.cscna().bit(true));
321 }
322 }
323 InputScan::On(mask) => {
324 self.adc.cssl.write(|w| unsafe { w.bits(mask) });
325 unsafe {
326 self.adc.con2set.write_with_zero(|w| w.cscna().bit(true));
327 }
328 }
329 }
330 }
331
332 pub fn select_neg_input(&mut self, input: NegativeInput) {
334 self.adc.chs.modify(|_, w| w.ch0na().bit(input as u8 != 0));
335 }
336
337 pub fn select_pos_alt_input(&mut self, input: u8) {
339 self.adc.chs.modify(|_, w| unsafe { w.ch0sb().bits(input) });
340 }
341
342 pub fn select_neg_alt_input(&mut self, input: NegativeInput) {
344 self.adc.chs.modify(|_, w| w.ch0nb().bit(input as u8 != 0));
345 }
346
347 pub fn start_sampling(&mut self) {
350 self.adc
351 .con1
352 .modify(|_, w| w.samp().set_bit().done().clear_bit());
353 }
354
355 pub fn start_conversion(&mut self) {
358 unsafe {
359 self.adc.con1clr.write_with_zero(|w| w.samp().set_bit());
360 }
361 }
362
363 pub fn done(&self) -> bool {
366 self.adc.con1.read().done().bit()
367 }
368
369 pub fn free(self) -> ADC {
371 self.adc.con1clr.write(|w| w.on().bit(true));
373 self.adc
374 }
375}