1use core::cell::Cell;
8use core::cmp;
9use core::ptr::addr_of;
10use kernel::hil;
11use kernel::utilities::cells::{OptionalCell, TakeCell, VolatileCell};
12use kernel::utilities::registers::interfaces::{Readable, Writeable};
13use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
14use kernel::utilities::StaticRef;
15use kernel::ErrorCode;
16
17#[repr(C)]
18struct AdcRegisters {
19 tasks_start: WriteOnly<u32, TASK::Register>,
21 tasks_sample: WriteOnly<u32, TASK::Register>,
23 tasks_stop: WriteOnly<u32, TASK::Register>,
25 tasks_calibrateoffset: WriteOnly<u32, TASK::Register>,
27 _reserved0: [u8; 240],
28 events_started: ReadWrite<u32, EVENT::Register>,
30 events_end: ReadWrite<u32, EVENT::Register>,
32 events_done: ReadWrite<u32, EVENT::Register>,
34 events_resultdone: ReadWrite<u32, EVENT::Register>,
36 events_calibratedone: ReadWrite<u32, EVENT::Register>,
38 events_stopped: ReadWrite<u32, EVENT::Register>,
40 events_ch: [AdcEventChRegisters; 8],
42 _reserved1: [u8; 424],
43 inten: ReadWrite<u32, INTEN::Register>,
45 intenset: ReadWrite<u32, INTEN::Register>,
47 intenclr: ReadWrite<u32, INTEN::Register>,
49 _reserved2: [u8; 244],
50 status: ReadOnly<u32>,
52 _reserved3: [u8; 252],
53 enable: ReadWrite<u32, ENABLE::Register>,
55 _reserved4: [u8; 12],
56 ch: [AdcChRegisters; 8],
57 _reserved5: [u8; 96],
58 resolution: ReadWrite<u32, RESOLUTION::Register>,
60 oversample: ReadWrite<u32>,
62 samplerate: ReadWrite<u32, SAMPLERATE::Register>,
64 _reserved6: [u8; 48],
65 result_ptr: VolatileCell<*const u16>,
67 result_maxcnt: ReadWrite<u32, RESULT_MAXCNT::Register>,
69 result_amount: ReadWrite<u32, RESULT_AMOUNT::Register>,
71}
72
73#[repr(C)]
74struct AdcEventChRegisters {
75 limith: ReadWrite<u32, EVENT::Register>,
76 limitl: ReadWrite<u32, EVENT::Register>,
77}
78
79#[repr(C)]
80struct AdcChRegisters {
81 pselp: ReadWrite<u32, PSEL::Register>,
82 pseln: ReadWrite<u32, PSEL::Register>,
83 config: ReadWrite<u32, CONFIG::Register>,
84 limit: ReadWrite<u32, LIMIT::Register>,
85}
86
87register_bitfields![u32,
88 INTEN [
89 STARTED 0,
91 END 1,
93 DONE 2,
95 RESULTDONE 3,
97 CALIBRATEDONE 4,
99 STOPPED 5,
101 CH0LIMITH 6,
103 CH0LIMITL 7,
105 CH1LIMITH 8,
107 CH1LIMITL 9,
109 CH2LIMITH 10,
111 CH2LIMITL 11,
113 CH3LIMITH 12,
115 CH3LIMITL 13,
117 CH4LIMITH 14,
119 CH4LIMITL 15,
121 CH5LIMITH 16,
123 CH5LIMITL 17,
125 CH6LIMITH 18,
127 CH6LIMITL 19,
129 CH7LIMITH 20,
131 CH7LIMITL 21
133 ],
134 ENABLE [
135 ENABLE 0
136 ],
137 SAMPLERATE [
138 CC OFFSET(0) NUMBITS(11) [],
140 MODE OFFSET(12) NUMBITS(1) [
142 Task = 0,
144 Timers = 1
146 ]
147 ],
148 EVENT [
149 EVENT 0
150 ],
151 TASK [
152 TASK 0
153 ],
154 PSEL [
155 PSEL OFFSET(0) NUMBITS(5) [
156 NotConnected = 0,
157 AnalogInput0 = 1,
158 AnalogInput1 = 2,
159 AnalogInput2 = 3,
160 AnalogInput3 = 4,
161 AnalogInput4 = 5,
162 AnalogInput5 = 6,
163 AnalogInput6 = 7,
164 AnalogInput7 = 8,
165 VDD = 9,
166 VDDHDIV5 = 0xD
167 ]
168 ],
169 CONFIG [
170 RESP OFFSET(0) NUMBITS(2) [
171 Bypass = 0,
172 Pulldown = 1,
173 Pullup = 2,
174 VDD1_2 = 3
175 ],
176 RESN OFFSET(4) NUMBITS(2) [
177 Bypass = 0,
178 Pulldown = 1,
179 Pullup = 2,
180 VDD1_2 = 3
181 ],
182 GAIN OFFSET(8) NUMBITS(3) [
183 Gain1_6 = 0,
184 Gain1_5 = 1,
185 Gain1_4 = 2,
186 Gain1_3 = 3,
187 Gain1_2 = 4,
188 Gain1 = 5,
189 Gain2 = 6,
190 Gain4 = 7
191 ],
192 REFSEL OFFSET(12) NUMBITS(1) [
193 Internal = 0,
194 VDD1_4 = 1
195 ],
196 TACQ OFFSET(16) NUMBITS(3) [
197 us3 = 0,
198 us5 = 1,
199 us10 = 2,
200 us15 = 3,
201 us20 = 4,
202 us40 = 5
203 ],
204 MODE OFFSET(20) NUMBITS(1) [
205 SE = 0,
206 Diff = 1
207 ],
208 BURST OFFSET(24) NUMBITS(1) [
209 Disable = 0,
210 Enable = 1
211 ]
212 ],
213 LIMIT [
214 LOW OFFSET(0) NUMBITS(16) [],
215 HIGH OFFSET(16) NUMBITS(16) []
216 ],
217 RESOLUTION [
218 VAL OFFSET(0) NUMBITS(3) [
219 bit8 = 0,
220 bit10 = 1,
221 bit12 = 2,
222 bit14 = 3
223 ]
224 ],
225 RESULT_MAXCNT [
226 MAXCNT OFFSET(0) NUMBITS(16) []
227 ],
228 RESULT_AMOUNT [
229 AMOUNT OFFSET(0) NUMBITS(16) []
230 ]
231];
232
233#[derive(Copy, Clone, Debug, PartialEq)]
234pub enum AdcChannel {
235 AnalogInput0 = 1,
236 AnalogInput1 = 2,
237 AnalogInput2 = 3,
238 AnalogInput3 = 4,
239 AnalogInput4 = 5,
240 AnalogInput5 = 6,
241 AnalogInput6 = 7,
242 AnalogInput7 = 8,
243 VDD = 9,
244 VDDHDIV5 = 0xD,
245}
246
247const SAADC_BASE: StaticRef<AdcRegisters> =
248 unsafe { StaticRef::new(0x40007000 as *const AdcRegisters) };
249
250static mut SAMPLE: [u16; 1] = [0; 1];
252
253#[repr(u8)]
254#[derive(Copy, Clone, Debug)]
255pub enum AdcChannelGain {
256 Gain1_6 = 0,
257 Gain1_5 = 1,
258 Gain1_4 = 2,
259 Gain1_3 = 3,
260 Gain1_2 = 4,
261 Gain1 = 5,
262 Gain2 = 6,
263 Gain4 = 7,
264}
265
266#[repr(u8)]
267#[derive(Copy, Clone, Debug)]
268pub enum AdcChannelResistor {
269 Bypass = 0,
270 Pulldown = 1,
271 Pullup = 2,
272 VDD1_2 = 3,
273}
274
275#[allow(non_camel_case_types)]
276#[repr(u8)]
277#[derive(Clone, Copy, Debug)]
278pub enum AdcChannelSamplingTime {
279 us3 = 0,
280 us5 = 1,
281 us10 = 2,
282 us15 = 3,
283 us20 = 4,
284 us40 = 5,
285}
286
287#[derive(Copy, Clone, Debug)]
288pub struct AdcChannelSetup {
289 channel: AdcChannel,
290 gain: AdcChannelGain,
291 resp: AdcChannelResistor,
292 resn: AdcChannelResistor,
293 sampling_time: AdcChannelSamplingTime,
294}
295
296impl PartialEq for AdcChannelSetup {
297 fn eq(&self, other: &Self) -> bool {
298 self.channel == other.channel
299 }
300}
301
302impl AdcChannelSetup {
303 pub fn new(channel: AdcChannel) -> AdcChannelSetup {
304 AdcChannelSetup {
305 channel,
306 gain: AdcChannelGain::Gain1_4,
307 resp: AdcChannelResistor::Bypass,
308 resn: AdcChannelResistor::Pulldown,
309 sampling_time: AdcChannelSamplingTime::us10,
310 }
311 }
312
313 pub fn setup(
314 channel: AdcChannel,
315 gain: AdcChannelGain,
316 resp: AdcChannelResistor,
317 resn: AdcChannelResistor,
318 sampling_time: AdcChannelSamplingTime,
319 ) -> AdcChannelSetup {
320 AdcChannelSetup {
321 channel,
322 gain,
323 resp,
324 resn,
325 sampling_time,
326 }
327 }
328}
329
330#[derive(Clone, Copy)]
331enum AdcMode {
332 Idle,
333 Calibrate,
334 Single,
335 HighSpeed,
336}
337
338pub struct Adc<'a> {
339 registers: StaticRef<AdcRegisters>,
340 reference: Cell<usize>,
341 mode: Cell<AdcMode>,
342 client: OptionalCell<&'a dyn hil::adc::Client>,
343 highspeed_client: OptionalCell<&'a dyn hil::adc::HighSpeedClient>,
344
345 buffer: TakeCell<'static, [u16]>,
346 length: Cell<usize>,
347 next_buffer: TakeCell<'static, [u16]>,
348 next_length: Cell<usize>,
349}
350
351impl Adc<'_> {
352 pub const fn new(voltage_reference_in_mv: usize) -> Self {
353 Self {
354 registers: SAADC_BASE,
355 reference: Cell::new(voltage_reference_in_mv),
356 mode: Cell::new(AdcMode::Idle),
357 client: OptionalCell::empty(),
358 highspeed_client: OptionalCell::empty(),
359 buffer: TakeCell::empty(),
360 length: Cell::new(0),
361 next_buffer: TakeCell::empty(),
362 next_length: Cell::new(0),
363 }
364 }
365
366 pub fn calibrate(&self) {
368 self.mode.set(AdcMode::Calibrate);
369
370 self.registers.enable.write(ENABLE::ENABLE::SET);
372 self.registers.inten.write(INTEN::CALIBRATEDONE::SET);
373 self.registers.tasks_calibrateoffset.write(TASK::TASK::SET);
374 }
375
376 pub fn handle_interrupt(&self) {
377 match self.mode.get() {
378 AdcMode::Calibrate => {
379 if self.registers.events_calibratedone.is_set(EVENT::EVENT) {
380 self.registers
381 .events_calibratedone
382 .write(EVENT::EVENT::CLEAR);
383
384 self.registers.ch[0].pselp.write(PSEL::PSEL::VDD);
386 self.registers.ch[0].pseln.write(PSEL::PSEL::NotConnected);
387
388 self.registers.ch[0].config.write(
390 CONFIG::GAIN::Gain1_6
391 + CONFIG::REFSEL::Internal
392 + CONFIG::TACQ::us10
393 + CONFIG::RESP::Bypass
394 + CONFIG::RESN::Bypass
395 + CONFIG::MODE::SE,
396 );
397
398 self.setup_resolution();
399 self.setup_sample_count(1);
400
401 self.registers.result_ptr.set(addr_of!(SAMPLE) as *const _);
403
404 self.registers.samplerate.write(SAMPLERATE::MODE::Task);
406
407 self.registers.enable.write(ENABLE::ENABLE::SET);
409
410 self.registers
412 .inten
413 .write(INTEN::STARTED::SET + INTEN::END::SET + INTEN::STOPPED::SET);
414
415 self.registers.tasks_start.write(TASK::TASK::SET);
416
417 } else if self.registers.events_started.is_set(EVENT::EVENT) {
419 self.registers.events_started.write(EVENT::EVENT::CLEAR);
420 self.registers.tasks_sample.write(TASK::TASK::SET);
422 } else if self.registers.events_end.is_set(EVENT::EVENT) {
423 self.registers.events_end.write(EVENT::EVENT::CLEAR);
424 self.registers.tasks_stop.write(TASK::TASK::SET);
426 } else if self.registers.events_stopped.is_set(EVENT::EVENT) {
427 self.registers.events_stopped.write(EVENT::EVENT::CLEAR);
428 self.registers.enable.write(ENABLE::ENABLE::CLEAR);
430
431 let reading = unsafe { SAMPLE[0] as i16 } as usize;
432
433 let val = (reading * 3600) / (1 << 12);
438
439 if val > 1000 && val < 5100 {
442 self.reference.set(val);
443 }
444 }
445 }
446
447 AdcMode::Single => {
448 if self.registers.events_calibratedone.is_set(EVENT::EVENT) {
450 self.registers
451 .events_calibratedone
452 .write(EVENT::EVENT::CLEAR);
453 self.registers.enable.write(ENABLE::ENABLE::CLEAR);
454 } else if self.registers.events_started.is_set(EVENT::EVENT) {
455 self.registers.events_started.write(EVENT::EVENT::CLEAR);
456 self.registers.tasks_sample.write(TASK::TASK::SET);
458 } else if self.registers.events_end.is_set(EVENT::EVENT) {
459 self.registers.events_end.write(EVENT::EVENT::CLEAR);
460 self.registers.tasks_stop.write(TASK::TASK::SET);
462 } else if self.registers.events_stopped.is_set(EVENT::EVENT) {
463 self.registers.events_stopped.write(EVENT::EVENT::CLEAR);
464 self.registers.enable.write(ENABLE::ENABLE::CLEAR);
466
467 let val = unsafe { SAMPLE[0] as i16 };
468 self.client.map(|client| {
469 client.sample_ready(if val < 0 { 0 } else { val << 4 } as u16);
471 });
472 }
473 }
474
475 AdcMode::HighSpeed => {
476 if self.registers.events_started.is_set(EVENT::EVENT) {
477 self.registers.events_started.write(EVENT::EVENT::CLEAR);
478
479 self.next_buffer.map(|buf| {
482 let dma_len = cmp::min(buf.len(), self.next_length.get());
484 if dma_len > 0 {
485 self.registers.result_ptr.set(buf.as_ptr());
486 }
487 });
488
489 self.registers.tasks_sample.write(TASK::TASK::SET);
491 } else if self.registers.events_end.is_set(EVENT::EVENT) {
492 self.registers.events_end.write(EVENT::EVENT::CLEAR);
493
494 let ret_buf = self.buffer.take().unwrap();
495
496 let length = self.length.get();
500 for i in 0..length {
501 ret_buf[i] <<= 4;
502 }
503
504 self.highspeed_client.map(|client| {
505 client.samples_ready(ret_buf, length);
506 });
507
508 let length2 = self.next_length.get();
511 if length2 > 0 {
512 self.length.set(length2);
513 self.buffer.put(self.next_buffer.take());
514 self.registers
515 .result_maxcnt
516 .write(RESULT_MAXCNT::MAXCNT.val(length2 as u32));
517 kernel::debug!("len2 {}", length2);
518
519 self.registers.tasks_start.write(TASK::TASK::SET);
521 }
522 } else if self.registers.events_stopped.is_set(EVENT::EVENT) {
523 self.registers.events_stopped.write(EVENT::EVENT::CLEAR);
524 }
525 }
526
527 AdcMode::Idle => {}
528 }
529 }
530
531 fn setup_channel(&self, channel: &AdcChannelSetup) {
532 self.registers.ch[0]
534 .pselp
535 .write(PSEL::PSEL.val(channel.channel as u32));
536 self.registers.ch[0].pseln.write(PSEL::PSEL::NotConnected);
537
538 self.registers.ch[0].config.write(
540 CONFIG::GAIN.val(channel.gain as u32)
541 + CONFIG::REFSEL::VDD1_4
542 + CONFIG::TACQ.val(channel.sampling_time as u32)
543 + CONFIG::RESP.val(channel.resp as u32)
544 + CONFIG::RESN.val(channel.resn as u32)
545 + CONFIG::MODE::SE,
546 );
547 }
548
549 fn setup_resolution(&self) {
550 self.registers.resolution.write(RESOLUTION::VAL::bit12);
552 }
553
554 fn setup_sample_count(&self, count: usize) {
555 self.registers
556 .result_maxcnt
557 .write(RESULT_MAXCNT::MAXCNT.val(count as u32));
558 }
559
560 fn setup_frequency(&self, frequency: u32) {
561 let raw_cc = 16000000 / frequency;
562 let cc = raw_cc.clamp(80, 2047);
563
564 self.registers
565 .samplerate
566 .write(SAMPLERATE::MODE::Timers + SAMPLERATE::CC.val(cc));
567 }
568}
569
570impl<'a> hil::adc::Adc<'a> for Adc<'a> {
572 type Channel = AdcChannelSetup;
573
574 fn sample(&self, channel: &Self::Channel) -> Result<(), ErrorCode> {
575 self.setup_channel(channel);
576 self.setup_resolution();
577
578 self.registers
580 .result_maxcnt
581 .write(RESULT_MAXCNT::MAXCNT.val(1));
582 self.registers.result_ptr.set(addr_of!(SAMPLE) as *const _);
584
585 self.registers.samplerate.write(SAMPLERATE::MODE::Task);
587
588 self.registers.enable.write(ENABLE::ENABLE::SET);
590
591 self.registers
593 .inten
594 .write(INTEN::STARTED::SET + INTEN::END::SET + INTEN::STOPPED::SET);
595
596 self.mode.set(AdcMode::Single);
597
598 self.registers.tasks_start.write(TASK::TASK::SET);
600
601 Ok(())
602 }
603
604 fn sample_continuous(
605 &self,
606 _channel: &Self::Channel,
607 _frequency: u32,
608 ) -> Result<(), ErrorCode> {
609 Err(ErrorCode::FAIL)
610 }
611
612 fn stop_sampling(&self) -> Result<(), ErrorCode> {
613 self.registers.tasks_stop.write(TASK::TASK::SET);
614 Ok(())
615 }
616
617 fn get_resolution_bits(&self) -> usize {
618 12
619 }
620
621 fn get_voltage_reference_mv(&self) -> Option<usize> {
622 Some(self.reference.get())
623 }
624
625 fn set_client(&self, client: &'a dyn hil::adc::Client) {
626 self.client.set(client);
627 }
628}
629
630impl<'a> hil::adc::AdcHighSpeed<'a> for Adc<'a> {
631 fn sample_highspeed(
632 &self,
633 channel: &Self::Channel,
634 frequency: u32,
635 buffer1: &'static mut [u16],
636 length1: usize,
637 buffer2: &'static mut [u16],
638 length2: usize,
639 ) -> Result<(), (ErrorCode, &'static mut [u16], &'static mut [u16])> {
640 if length1 == 0 {
641 Err((ErrorCode::INVAL, buffer1, buffer2))
643 } else {
644 self.next_buffer.replace(buffer2);
646 self.next_length.set(length2);
647
648 self.setup_channel(channel);
649 self.setup_resolution();
650
651 self.registers.result_ptr.set(buffer1.as_ptr());
653
654 self.buffer.replace(buffer1);
656 self.length.set(length1);
657
658 self.setup_sample_count(length1);
660
661 self.setup_frequency(frequency);
663
664 self.registers.enable.write(ENABLE::ENABLE::SET);
666
667 self.registers
669 .inten
670 .write(INTEN::STARTED::SET + INTEN::END::SET + INTEN::STOPPED::SET);
671
672 self.mode.set(AdcMode::HighSpeed);
673
674 self.registers.tasks_start.write(TASK::TASK::SET);
676
677 Ok(())
678 }
679 }
680
681 fn provide_buffer(
682 &self,
683 buf: &'static mut [u16],
684 length: usize,
685 ) -> Result<(), (ErrorCode, &'static mut [u16])> {
686 if self.next_buffer.is_some() {
687 Err((ErrorCode::BUSY, buf))
689 } else {
690 self.next_buffer.replace(buf);
692 self.next_length.set(length);
693
694 Ok(())
695 }
696 }
697
698 fn retrieve_buffers(
699 &self,
700 ) -> Result<(Option<&'static mut [u16]>, Option<&'static mut [u16]>), ErrorCode> {
701 Ok((self.buffer.take(), self.next_buffer.take()))
702 }
703
704 fn set_highspeed_client(&self, client: &'a dyn hil::adc::HighSpeedClient) {
705 self.highspeed_client.set(client);
706 }
707}