sam4l/
adc.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Implementation of the SAM4L ADCIFE.
6//!
7//! This is an implementation of the SAM4L analog to digital converter. It is
8//! bare-bones because it provides little flexibility on how samples are taken.
9//! Currently, all samples:
10//!
11//! - are 12 bits
12//! - use the ground pad as the negative reference
13//! - use a VCC/2 positive reference
14//! - use a gain of 0.5x
15//! - are left justified
16//!
17//! Samples can either be collected individually or continuously at a specified
18//! frequency.
19//!
20//! - Author: Philip Levis <pal@cs.stanford.edu>, Branden Ghena <brghena@umich.edu>
21//! - Updated: May 1, 2017
22
23use crate::dma;
24use crate::pm::{self, Clock, PBAClock};
25use crate::scif;
26use core::cell::Cell;
27use core::{cmp, mem, slice};
28use kernel::hil;
29use kernel::utilities::cells::{OptionalCell, TakeCell};
30use kernel::utilities::math;
31use kernel::utilities::registers::interfaces::{Readable, Writeable};
32use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
33use kernel::utilities::StaticRef;
34use kernel::ErrorCode;
35
36/// Representation of an ADC channel on the SAM4L.
37#[derive(PartialEq)]
38pub struct AdcChannel {
39    chan_num: u32,
40    internal: u32,
41}
42
43/// SAM4L ADC channels.
44#[derive(Copy, Clone, Debug)]
45#[repr(u8)]
46pub enum Channel {
47    AD0 = 0x00,
48    AD1 = 0x01,
49    AD2 = 0x02,
50    AD3 = 0x03,
51    AD4 = 0x04,
52    AD5 = 0x05,
53    AD6 = 0x06,
54    AD7 = 0x07,
55    AD8 = 0x08,
56    AD9 = 0x09,
57    AD10 = 0x0A,
58    AD11 = 0x0B,
59    AD12 = 0x0C,
60    AD13 = 0x0D,
61    AD14 = 0x0E,
62    Bandgap = 0x0F,
63    ScaledVCC = 0x12,
64    DAC = 0x13,
65    Vsingle = 0x16,
66    ReferenceGround = 0x17,
67}
68
69/// Initialization of an ADC channel.
70impl AdcChannel {
71    /// Create a new ADC channel.
72    ///
73    /// - `channel`: Channel enum representing the channel number and whether it
74    ///   is internal
75    pub const fn new(channel: Channel) -> AdcChannel {
76        AdcChannel {
77            chan_num: ((channel as u8) & 0x0F) as u32,
78            internal: (((channel as u8) >> 4) & 0x01) as u32,
79        }
80    }
81}
82
83/// ADC driver code for the SAM4L.
84pub struct Adc<'a> {
85    registers: StaticRef<AdcRegisters>,
86
87    // state tracking for the ADC
88    enabled: Cell<bool>,
89    adc_clk_freq: Cell<u32>,
90    active: Cell<bool>,
91    continuous: Cell<bool>,
92    dma_running: Cell<bool>,
93    cpu_clock: Cell<bool>,
94
95    // timer fire counting for slow sampling rates
96    timer_repeats: Cell<u8>,
97    timer_counts: Cell<u8>,
98
99    // DMA peripheral, buffers, and length
100    rx_dma: OptionalCell<&'static dma::DMAChannel>,
101    rx_dma_peripheral: dma::DMAPeripheral,
102    rx_length: Cell<usize>,
103    next_dma_buffer: TakeCell<'static, [u16]>,
104    next_dma_length: Cell<usize>,
105    stopped_buffer: TakeCell<'static, [u16]>,
106
107    // ADC client to send sample complete notifications to
108    client: OptionalCell<&'a dyn hil::adc::Client>,
109    highspeed_client: OptionalCell<&'a dyn hil::adc::HighSpeedClient>,
110    pm: &'static pm::PowerManager,
111}
112
113/// Memory mapped registers for the ADC.
114#[repr(C)]
115pub struct AdcRegisters {
116    // From page 1005 of SAM4L manual
117    cr: WriteOnly<u32, Control::Register>,
118    cfg: ReadWrite<u32, Configuration::Register>,
119    sr: ReadOnly<u32, Status::Register>,
120    scr: WriteOnly<u32, Interrupt::Register>,
121    _reserved0: u32,
122    seqcfg: ReadWrite<u32, SequencerConfig::Register>,
123    cdma: WriteOnly<u32>,
124    tim: ReadWrite<u32, TimingConfiguration::Register>,
125    itimer: ReadWrite<u32, InternalTimer::Register>,
126    wcfg: ReadWrite<u32, WindowMonitorConfiguration::Register>,
127    wth: ReadWrite<u32, WindowMonitorThresholdConfiguration::Register>,
128    lcv: ReadOnly<u32, SequencerLastConvertedValue::Register>,
129    ier: WriteOnly<u32, Interrupt::Register>,
130    idr: WriteOnly<u32, Interrupt::Register>,
131    imr: ReadOnly<u32, Interrupt::Register>,
132    calib: ReadWrite<u32>,
133}
134
135register_bitfields![u32,
136    Control [
137        /// Bandgap buffer request disable
138        BGREQDIS 11,
139        /// Bandgap buffer request enable
140        BGREQEN 10,
141        /// ADCIFE disable
142        DIS 9,
143        /// ADCIFE enable
144        EN 8,
145        /// Reference buffer disable
146        REFBUFDIS 5,
147        /// Reference buffer enable
148        REFBUFEN 4,
149        /// Sequence trigger
150        STRIG 3,
151        /// Internal timer start bit
152        TSTART 2,
153        /// Internal timer stop bit
154        TSTOP 1,
155        /// Software reset
156        SWRST 0
157    ],
158
159    Configuration [
160        /// Prescaler Rate Selection
161        PRESCAL OFFSET(8) NUMBITS(3) [
162            DIV4 = 0,
163            DIV8 = 1,
164            DIV16 = 2,
165            DIV32 = 3,
166            DIV64 = 4,
167            DIV128 = 5,
168            DIV256 = 6,
169            DIV512 = 7
170        ],
171        /// Clock Selection for sequencer/ADC cell
172        CLKSEL OFFSET(6) NUMBITS(1) [
173            GenericClock = 0,
174            ApbClock = 1
175        ],
176        /// ADC current reduction
177        SPEED OFFSET(4) NUMBITS(2) [
178            ksps300 = 0,
179            ksps225 = 1,
180            ksps150 = 2,
181            ksps75 = 3
182        ],
183        /// ADC Reference selection
184        REFSEL OFFSET(1) NUMBITS(3) [
185            Internal1V = 0,
186            VccX0p625 = 1,
187            ExternalRef1 = 2,
188            ExternalRef2 = 3,
189            VccX0p5 = 4
190        ]
191    ],
192
193    Status [
194        /// Bandgap buffer request Status
195        BGREQ 30,
196        /// Reference Buffer Status
197        REFBUF 28,
198        /// Conversion busy
199        CBUSY 27,
200        /// Sequencer busy
201        SBUSY 26,
202        /// Timer busy
203        TBUSY 25,
204        /// Enable Status
205        EN 24,
206        /// Timer time out
207        TTO 5,
208        /// Sequencer missed trigger event
209        SMTRG 3,
210        /// Window monitor
211        WM 2,
212        /// Sequencer last converted value overrun
213        LOVR 1,
214        /// Sequencer end of conversion
215        SEOC 0
216    ],
217
218    Interrupt [
219        /// Timer time out
220        TTO 5,
221        /// Sequencer missed trigger event
222        SMTRG 3,
223        /// Window monitor
224        WM 2,
225        /// Sequencer last converted value overrun
226        LOVR 1,
227        /// Sequencer end of conversion
228        SEOC 0
229    ],
230
231    SequencerConfig [
232        /// Zoom shift/unipolar reference source selection
233        ZOOMRANGE OFFSET(28) NUMBITS(3) [],
234        /// MUX selection on Negative ADC input channel
235        MUXNEG OFFSET(20) NUMBITS(3) [],
236        /// MUS selection of Positive ADC input channel
237        MUXPOS OFFSET(16) NUMBITS(4) [],
238        /// Internal Voltage Sources Selection
239        INTERNAL OFFSET(14) NUMBITS(2) [],
240        /// Resolution
241        RES OFFSET(12) NUMBITS(1) [
242            Bits12 = 0,
243            Bits8 = 1
244        ],
245        /// Trigger selection
246        TRGSEL OFFSET(8) NUMBITS(3) [
247            Software = 0,
248            InternalAdcTimer = 1,
249            InternalTriggerSource = 2,
250            ContinuousMode = 3,
251            ExternalTriggerPinRising = 4,
252            ExternalTriggerPinFalling = 5,
253            ExternalTriggerPinBoth = 6
254        ],
255        /// Gain Compensation
256        GCOMP OFFSET(7) NUMBITS(1) [
257            Disable = 0,
258            Enable = 1
259        ],
260        /// Gain factor
261        GAIN OFFSET(4) NUMBITS(3) [
262            Gain1x = 0,
263            Gain2x = 1,
264            Gain4x = 2,
265            Gain8x = 3,
266            Gain16x = 4,
267            Gain32x = 5,
268            Gain64x = 6,
269            Gain0p5x = 7
270        ],
271        /// Bipolar Mode
272        BIPOLAR OFFSET(2) NUMBITS(1) [
273            Disable = 0,
274            Enable = 1
275        ],
276        /// Half Word Left Adjust
277        HWLA OFFSET(0) NUMBITS(1) [
278            Disable = 0,
279            Enable = 1
280        ]
281    ],
282
283    TimingConfiguration [
284        /// Enable Startup
285        ENSTUP OFFSET(8) NUMBITS(1) [
286            Disable = 0,
287            Enable = 1
288        ],
289        /// Startup time
290        STARTUP OFFSET(0) NUMBITS(5) []
291    ],
292
293    InternalTimer [
294        /// Internal Timer Max Counter
295        ITMC OFFSET(0) NUMBITS(16) []
296    ],
297
298    WindowMonitorConfiguration [
299        /// Window Monitor Mode
300        WM OFFSET(12) NUMBITS(3) []
301    ],
302
303    WindowMonitorThresholdConfiguration [
304        /// High Threshold
305        HT OFFSET(16) NUMBITS(12) [],
306        /// Low Threshold
307        LT OFFSET(0) NUMBITS(12) []
308    ],
309
310    SequencerLastConvertedValue [
311        /// Last converted negative channel
312        LCNC OFFSET(20) NUMBITS(3) [],
313        /// Last converted positive channel
314        LCPC OFFSET(16) NUMBITS(4) [],
315        /// Last converted value
316        LCV OFFSET(0) NUMBITS(16) []
317    ]
318];
319
320// Page 59 of SAM4L data sheet
321const BASE_ADDRESS: StaticRef<AdcRegisters> =
322    unsafe { StaticRef::new(0x40038000 as *const AdcRegisters) };
323
324/// Functions for initializing the ADC.
325impl Adc<'_> {
326    /// Create a new ADC driver.
327    ///
328    /// - `rx_dma_peripheral`: type used for DMA transactions
329    pub fn new(rx_dma_peripheral: dma::DMAPeripheral, pm: &'static pm::PowerManager) -> Self {
330        Self {
331            // pointer to memory mapped I/O registers
332            registers: BASE_ADDRESS,
333
334            // status of the ADC peripheral
335            enabled: Cell::new(false),
336            adc_clk_freq: Cell::new(0),
337            active: Cell::new(false),
338            continuous: Cell::new(false),
339            dma_running: Cell::new(false),
340            cpu_clock: Cell::new(false),
341
342            // timer repeating state for slow sampling rates
343            timer_repeats: Cell::new(0),
344            timer_counts: Cell::new(0),
345
346            // DMA status and stuff
347            rx_dma: OptionalCell::empty(),
348            rx_dma_peripheral,
349            rx_length: Cell::new(0),
350            next_dma_buffer: TakeCell::empty(),
351            next_dma_length: Cell::new(0),
352            stopped_buffer: TakeCell::empty(),
353
354            // higher layer to send responses to
355            client: OptionalCell::empty(),
356            highspeed_client: OptionalCell::empty(),
357            pm,
358        }
359    }
360
361    /// Sets the DMA channel for this driver.
362    ///
363    /// - `rx_dma`: reference to the DMA channel the ADC should use
364    pub fn set_dma(&self, rx_dma: &'static dma::DMAChannel) {
365        self.rx_dma.set(rx_dma);
366    }
367
368    /// Interrupt handler for the ADC.
369    pub fn handle_interrupt(&self) {
370        let status = self.registers.sr.is_set(Status::SEOC);
371
372        if self.enabled.get() && self.active.get() {
373            if status {
374                // sample complete interrupt
375
376                // should we deal with this sample now, or wait for the next
377                // one?
378                if self.timer_counts.get() >= self.timer_repeats.get() {
379                    // we actually care about this sample
380
381                    // single sample complete. Send value to client
382                    let val = self.registers.lcv.read(SequencerLastConvertedValue::LCV) as u16;
383                    self.client.map(|client| {
384                        client.sample_ready(val);
385                    });
386
387                    // clean up state
388                    if self.continuous.get() {
389                        // continuous sampling, reset counts and keep going
390                        self.timer_counts.set(0);
391                    } else {
392                        // single sampling, disable interrupt and set inactive
393                        self.active.set(false);
394                        self.registers.idr.write(Interrupt::SEOC::SET);
395                    }
396                } else {
397                    // increment count and wait for next sample
398                    self.timer_counts.set(self.timer_counts.get() + 1);
399                }
400
401                // clear status
402                self.registers.scr.write(Interrupt::SEOC::SET);
403            }
404        } else {
405            // we are inactive, why did we get an interrupt?
406            // disable all interrupts, clear status, and just ignore it
407            self.registers.idr.write(
408                Interrupt::TTO::SET
409                    + Interrupt::SMTRG::SET
410                    + Interrupt::WM::SET
411                    + Interrupt::LOVR::SET
412                    + Interrupt::SEOC::SET,
413            );
414            self.clear_status();
415        }
416    }
417
418    /// Clear all status bits using the status clear register.
419    fn clear_status(&self) {
420        self.registers.scr.write(
421            Interrupt::TTO::SET
422                + Interrupt::SMTRG::SET
423                + Interrupt::WM::SET
424                + Interrupt::LOVR::SET
425                + Interrupt::SEOC::SET,
426        );
427    }
428
429    // Configures the ADC with the slowest clock that can provide continuous sampling at
430    // the desired frequency and enables the ADC. Subsequent calls with the same frequency
431    // value have no effect. Using the slowest clock also ensures efficient discrete
432    // sampling.
433    fn config_and_enable(&self, frequency: u32) -> Result<(), ErrorCode> {
434        if self.active.get() {
435            // disallow reconfiguration during sampling
436            Err(ErrorCode::BUSY)
437        } else if frequency == self.adc_clk_freq.get() {
438            // already configured to work on this frequency
439            Ok(())
440        } else {
441            // disabling the ADC before switching clocks is necessary to avoid
442            // leaving it in undefined state
443            self.registers.cr.write(Control::DIS::SET);
444
445            // wait until status is disabled
446            let mut timeout = 10000;
447            while self.registers.sr.is_set(Status::EN) {
448                timeout -= 1;
449                if timeout == 0 {
450                    // ADC never disabled
451                    return Err(ErrorCode::FAIL);
452                }
453            }
454
455            self.enabled.set(true);
456
457            // configure the ADC max speed and reference select
458            let mut cfg_val = Configuration::SPEED::ksps300 + Configuration::REFSEL::VccX0p5;
459
460            // First, enable the clocks
461            // Both the ADCIFE clock and GCLK10 are needed,
462            // but the GCLK10 source depends on the requested sampling frequency
463
464            // turn on ADCIFE bus clock. Already set to the same frequency
465            // as the CPU clock
466            pm::enable_clock(Clock::PBA(PBAClock::ADCIFE));
467
468            // Now, determine the prescalar.
469            // The maximum sampling frequency with the RC clocks is 1/32th of their clock
470            // frequency. This is because of the minimum PRESCAL by a factor of 4 and the
471            // 7+1 cycles needed for conversion in continuous mode. Hence, 4*(7+1)=32.
472            if frequency <= 113600 / 32 {
473                // RC oscillator
474                self.cpu_clock.set(false);
475                let max_freq: u32 = if frequency <= 32000 / 32 {
476                    // frequency of the RC32K is 32KHz.
477                    scif::generic_clock_enable(
478                        scif::GenericClock::GCLK10,
479                        scif::ClockSource::RC32K,
480                    );
481                    32000 / 32
482                } else {
483                    // frequency of the RCSYS is 115KHz.
484                    scif::generic_clock_enable(
485                        scif::GenericClock::GCLK10,
486                        scif::ClockSource::RCSYS,
487                    );
488                    113600 / 32
489                };
490                let divisor = (frequency + max_freq - 1) / frequency; // ceiling of division
491                let divisor_pow2 = math::closest_power_of_two(divisor);
492                let clock_divisor = cmp::min(math::log_base_two(divisor_pow2), 7);
493                self.adc_clk_freq.set(max_freq / (1 << (clock_divisor)));
494                cfg_val += Configuration::PRESCAL.val(clock_divisor);
495            } else {
496                // CPU clock
497                self.cpu_clock.set(true);
498                scif::generic_clock_enable(scif::GenericClock::GCLK10, scif::ClockSource::CLK_CPU);
499                // determine clock divider
500                // we need the ADC_CLK to be a maximum of 1.5 MHz in frequency,
501                // so we need to find the PRESCAL value that will make this
502                // happen.
503                // Formula: f(ADC_CLK) = f(CLK_CPU)/2^(N+2) <= 1.5 MHz
504                // and we solve for N
505                // becomes: N <= ceil(log_2(f(CLK_CPU)/1500000)) - 2
506                let cpu_frequency = self.pm.get_system_frequency();
507                let divisor = cpu_frequency.div_ceil(1500000);
508                let divisor_pow2 = math::closest_power_of_two(divisor);
509                let clock_divisor = cmp::min(math::log_base_two(divisor_pow2).saturating_sub(2), 7);
510                self.adc_clk_freq
511                    .set(cpu_frequency / (1 << (clock_divisor + 2)));
512                cfg_val += Configuration::PRESCAL.val(clock_divisor);
513            }
514
515            if self.cpu_clock.get() {
516                cfg_val += Configuration::CLKSEL::ApbClock
517            } else {
518                cfg_val += Configuration::CLKSEL::GenericClock
519            }
520
521            self.registers.cfg.write(cfg_val);
522
523            // set startup to wait 24 cycles
524            self.registers.tim.write(
525                TimingConfiguration::ENSTUP::Enable + TimingConfiguration::STARTUP.val(0x17),
526            );
527
528            // software reset (does not clear registers)
529            self.registers.cr.write(Control::SWRST::SET);
530
531            // enable ADC
532            self.registers.cr.write(Control::EN::SET);
533
534            // wait until status is enabled
535            let mut timeout = 10000;
536            while !self.registers.sr.is_set(Status::EN) {
537                timeout -= 1;
538                if timeout == 0 {
539                    // ADC never enabled
540                    return Err(ErrorCode::FAIL);
541                }
542            }
543
544            // enable Bandgap buffer and Reference buffer. I don't actually
545            // know what these do, but you need to turn them on
546            self.registers
547                .cr
548                .write(Control::BGREQEN::SET + Control::REFBUFEN::SET);
549
550            // wait until buffers are enabled
551            timeout = 100000;
552            while !self
553                .registers
554                .sr
555                .matches_all(Status::BGREQ::SET + Status::REFBUF::SET + Status::EN::SET)
556            {
557                timeout -= 1;
558                if timeout == 0 {
559                    // ADC buffers never enabled
560                    return Err(ErrorCode::FAIL);
561                }
562            }
563
564            Ok(())
565        }
566    }
567
568    /// Disables the ADC so that the chip can return to deep sleep
569    fn disable(&self) {
570        // disable ADC
571        self.registers.cr.write(Control::DIS::SET);
572
573        // wait until status is disabled
574        let mut timeout = 10000;
575        while self.registers.sr.is_set(Status::EN) {
576            timeout -= 1;
577            if timeout == 0 {
578                // ADC never disabled
579                return;
580            }
581        }
582
583        // disable bandgap and reference buffers
584        self.registers
585            .cr
586            .write(Control::BGREQDIS::SET + Control::REFBUFDIS::SET);
587
588        self.enabled.set(false);
589        scif::generic_clock_disable(scif::GenericClock::GCLK10);
590        pm::disable_clock(Clock::PBA(PBAClock::ADCIFE));
591    }
592}
593
594/// Implements an ADC capable reading ADC samples on any channel.
595impl<'a> hil::adc::Adc<'a> for Adc<'a> {
596    type Channel = AdcChannel;
597
598    /// Capture a single analog sample, calling the client when complete.
599    /// Returns an error if the ADC is already sampling.
600    ///
601    /// - `channel`: the ADC channel to sample
602    fn sample(&self, channel: &Self::Channel) -> Result<(), ErrorCode> {
603        // always configure to 1KHz to get the slowest clock with single sampling
604        let res = self.config_and_enable(1000);
605
606        if res != Ok(()) {
607            res
608        } else if !self.enabled.get() {
609            Err(ErrorCode::OFF)
610        } else if self.active.get() {
611            // only one operation at a time
612            Err(ErrorCode::BUSY)
613        } else {
614            self.active.set(true);
615            self.continuous.set(false);
616            self.timer_repeats.set(0);
617            self.timer_counts.set(0);
618
619            // MUXNEG.val(0x7) -> ground pad
620            let cfg = SequencerConfig::MUXNEG.val(0x7)
621                + SequencerConfig::MUXPOS.val(channel.chan_num)
622                + SequencerConfig::INTERNAL.val(0x2 | channel.internal)
623                + SequencerConfig::RES::Bits12
624                + SequencerConfig::TRGSEL::Software
625                + SequencerConfig::GCOMP::Disable
626                + SequencerConfig::GAIN::Gain0p5x
627                + SequencerConfig::BIPOLAR::Disable
628                + SequencerConfig::HWLA::Enable;
629            self.registers.seqcfg.write(cfg);
630
631            // clear any current status
632            self.clear_status();
633
634            // enable end of conversion interrupt
635            self.registers.ier.write(Interrupt::SEOC::SET);
636
637            // initiate conversion
638            self.registers.cr.write(Control::STRIG::SET);
639
640            Ok(())
641        }
642    }
643
644    /// Request repeated analog samples on a particular channel, calling after
645    /// each sample. In order to not unacceptably slow down the system
646    /// collecting samples, this interface is limited to one sample every 100
647    /// microseconds (10000 samples per second). To sample faster, use the
648    /// sample_highspeed function.
649    ///
650    /// - `channel`: the ADC channel to sample
651    /// - `frequency`: the number of samples per second to collect
652    fn sample_continuous(&self, channel: &Self::Channel, frequency: u32) -> Result<(), ErrorCode> {
653        let res = self.config_and_enable(frequency);
654
655        if res != Ok(()) {
656            res
657        } else if !self.enabled.get() {
658            Err(ErrorCode::OFF)
659        } else if self.active.get() {
660            // only one sample at a time
661            Err(ErrorCode::BUSY)
662        } else if frequency == 0 || frequency > 10000 {
663            // limit sampling frequencies to a valid range
664            Err(ErrorCode::INVAL)
665        } else {
666            self.active.set(true);
667            self.continuous.set(true);
668
669            // adc sequencer configuration
670            // MUXNEG.val(0x7) -> ground pad
671            let mut cfg = SequencerConfig::MUXNEG.val(0x7)
672                + SequencerConfig::MUXPOS.val(channel.chan_num)
673                + SequencerConfig::INTERNAL.val(0x2 | channel.internal)
674                + SequencerConfig::RES::Bits12
675                + SequencerConfig::GCOMP::Disable
676                + SequencerConfig::GAIN::Gain0p5x
677                + SequencerConfig::BIPOLAR::Disable
678                + SequencerConfig::HWLA::Enable;
679            // set trigger based on how good our clock is
680            if self.cpu_clock.get() {
681                cfg += SequencerConfig::TRGSEL::InternalAdcTimer;
682            } else {
683                cfg += SequencerConfig::TRGSEL::ContinuousMode;
684            }
685            self.registers.seqcfg.write(cfg);
686
687            // stop timer if running
688            self.registers.cr.write(Control::TSTOP::SET);
689
690            if self.cpu_clock.get() {
691                // This logic only applies for sampling off the CPU
692                // setup timer for low-frequency samples. Based on the ADC clock,
693                // the minimum timer frequency is:
694                // 1500000 / (0xFFFF + 1) = 22.888 Hz.
695                // So for any frequency less than 23 Hz, we will keep our own
696                // counter in addition and only actually perform a callback every N
697                // timer fires. This is important to enable low-jitter sampling in
698                // the 1-22 Hz range.
699                let timer_frequency = if frequency < 23 {
700                    // set a number of timer repeats before the callback is
701                    // performed. 60 here is an arbitrary number which limits the
702                    // actual itimer frequency to between 42 and 60 in the desired
703                    // range of 1-22 Hz, which seems slow enough to keep the system
704                    // from getting bogged down with interrupts
705                    let counts = 60 / frequency;
706                    self.timer_repeats.set(counts as u8);
707                    self.timer_counts.set(0);
708                    frequency * counts
709                } else {
710                    // we can sample at this frequency directly with the timer
711                    self.timer_repeats.set(0);
712                    self.timer_counts.set(0);
713                    frequency
714                };
715
716                // set timer, limit to bounds
717                // f(timer) = f(adc) / (counter + 1)
718                let mut counter = (self.adc_clk_freq.get() / timer_frequency) - 1;
719                counter = cmp::max(cmp::min(counter, 0xFFFF), 0);
720                self.registers
721                    .itimer
722                    .write(InternalTimer::ITMC.val(counter));
723            } else {
724                // we can sample at this frequency directly with the timer
725                self.timer_repeats.set(0);
726                self.timer_counts.set(0);
727            }
728
729            // clear any current status
730            self.clear_status();
731
732            // enable end of conversion interrupt
733            self.registers.ier.write(Interrupt::SEOC::SET);
734
735            // start timer
736            self.registers.cr.write(Control::TSTART::SET);
737
738            Ok(())
739        }
740    }
741
742    /// Stop continuously sampling the ADC.
743    /// This is expected to be called to stop continuous sampling operations,
744    /// but can be called to abort any currently running operation. The buffer,
745    /// if any, will be returned via the `samples_ready` callback.
746    fn stop_sampling(&self) -> Result<(), ErrorCode> {
747        if !self.enabled.get() {
748            Err(ErrorCode::OFF)
749        } else if !self.active.get() {
750            // cannot cancel sampling that isn't running
751            Err(ErrorCode::INVAL)
752        } else {
753            // clean up state
754            self.active.set(false);
755            self.continuous.set(false);
756            self.dma_running.set(false);
757
758            // stop internal timer
759            self.registers.cr.write(Control::TSTOP::SET);
760
761            // disable sample interrupts
762            self.registers.idr.write(Interrupt::SEOC::SET);
763
764            // reset the ADC peripheral
765            self.registers.cr.write(Control::SWRST::SET);
766
767            // disable the ADC
768            self.disable();
769
770            // stop DMA transfer if going. This should safely return a None if
771            // the DMA was not being used
772            let dma_buffer = self.rx_dma.map_or(None, |rx_dma| {
773                let dma_buf = rx_dma.abort_transfer();
774                rx_dma.disable();
775                dma_buf
776            });
777            self.rx_length.set(0);
778
779            // store the buffer if it exists
780            dma_buffer.map(|dma_buf| {
781                // change buffer back into a [u16]
782                // the buffer was originally a [u16] so this should be okay
783                let buf_ptr = unsafe { mem::transmute::<*mut u8, *mut u16>(dma_buf.as_mut_ptr()) };
784                let buf = unsafe { slice::from_raw_parts_mut(buf_ptr, dma_buf.len() / 2) };
785
786                // we'll place it here so we can return it to the higher level
787                // later in a `retrieve_buffers` call
788                self.stopped_buffer.replace(buf);
789            });
790
791            Ok(())
792        }
793    }
794
795    /// Resolution of the reading.
796    fn get_resolution_bits(&self) -> usize {
797        12
798    }
799
800    /// Voltage reference is VCC/2, we assume VCC is 3.3 V, and we use a gain
801    /// of 0.5.
802    fn get_voltage_reference_mv(&self) -> Option<usize> {
803        Some(3300)
804    }
805
806    /// Sets the client for this driver.
807    ///
808    /// - `client`: reference to capsule which handles responses
809    fn set_client(&self, client: &'a dyn hil::adc::Client) {
810        self.client.set(client);
811    }
812}
813
814/// Implements an ADC capable of continuous sampling
815impl<'a> hil::adc::AdcHighSpeed<'a> for Adc<'a> {
816    /// Capture buffered samples from the ADC continuously at a given
817    /// frequency, calling the client whenever a buffer fills up. The client is
818    /// then expected to either stop sampling or provide an additional buffer
819    /// to sample into. Note that due to hardware constraints the maximum
820    /// frequency range of the ADC is from 187 kHz to 23 Hz (although its
821    /// precision is limited at higher frequencies due to aliasing).
822    ///
823    /// - `channel`: the ADC channel to sample
824    /// - `frequency`: frequency to sample at
825    /// - `buffer1`: first buffer to fill with samples
826    /// - `length1`: number of samples to collect (up to buffer length)
827    /// - `buffer2`: second buffer to fill once the first is full
828    /// - `length2`: number of samples to collect (up to buffer length)
829    fn sample_highspeed(
830        &self,
831        channel: &Self::Channel,
832        frequency: u32,
833        buffer1: &'static mut [u16],
834        length1: usize,
835        buffer2: &'static mut [u16],
836        length2: usize,
837    ) -> Result<(), (ErrorCode, &'static mut [u16], &'static mut [u16])> {
838        let res = self.config_and_enable(frequency);
839
840        if res != Ok(()) {
841            Err((res.unwrap_err(), buffer1, buffer2))
842        } else if !self.enabled.get() {
843            Err((ErrorCode::OFF, buffer1, buffer2))
844        } else if self.active.get() {
845            // only one sample at a time
846            Err((ErrorCode::BUSY, buffer1, buffer2))
847        } else if frequency <= (self.adc_clk_freq.get() / (0xFFFF + 1)) || frequency > 250000 {
848            // can't sample faster than the max sampling frequency or slower
849            // than the timer can be set to
850            Err((ErrorCode::INVAL, buffer1, buffer2))
851        } else if length1 == 0 {
852            // at least need a valid length for the for the first buffer full of
853            // samples. Otherwise, what are we doing here?
854            Err((ErrorCode::INVAL, buffer1, buffer2))
855        } else {
856            self.active.set(true);
857            self.continuous.set(true);
858
859            // store the second buffer for later use
860            self.next_dma_buffer.replace(buffer2);
861            self.next_dma_length.set(length2);
862
863            // adc sequencer configuration
864            // MUXNEG.val(0x7) -> ground pad
865            let mut cfg = SequencerConfig::MUXNEG.val(0x7)
866                + SequencerConfig::MUXPOS.val(channel.chan_num)
867                + SequencerConfig::INTERNAL.val(0x2 | channel.internal)
868                + SequencerConfig::RES::Bits12
869                + SequencerConfig::GCOMP::Disable
870                + SequencerConfig::GAIN::Gain0p5x
871                + SequencerConfig::BIPOLAR::Disable
872                + SequencerConfig::HWLA::Enable;
873            // set trigger based on how good our clock is
874            if self.cpu_clock.get() {
875                cfg += SequencerConfig::TRGSEL::InternalAdcTimer;
876            } else {
877                cfg += SequencerConfig::TRGSEL::ContinuousMode;
878            }
879            self.registers.seqcfg.write(cfg);
880
881            // stop timer if running
882            self.registers.cr.write(Control::TSTOP::SET);
883
884            if self.cpu_clock.get() {
885                // set timer, limit to bounds
886                // f(timer) = f(adc) / (counter + 1)
887                let mut counter = (self.adc_clk_freq.get() / frequency) - 1;
888                counter = cmp::max(cmp::min(counter, 0xFFFF), 0);
889                self.registers
890                    .itimer
891                    .write(InternalTimer::ITMC.val(counter));
892            }
893
894            // clear any current status
895            self.clear_status();
896
897            // receive up to the buffer's length samples
898            let dma_len = cmp::min(buffer1.len(), length1);
899
900            // change buffer into a [u8]
901            // this is unsafe but acceptable for the following reasons
902            //  * the buffer is aligned based on 16-bit boundary, so the 8-bit
903            //    alignment is fine
904            //  * the DMA is doing checking based on our expected data width to
905            //    make sure we don't go past dma_buf.len()/width
906            //  * we will transmute the array back to a [u16] after the DMA
907            //    transfer is complete
908            let dma_buf_ptr = unsafe { mem::transmute::<*mut u16, *mut u8>(buffer1.as_mut_ptr()) };
909            let dma_buf = unsafe { slice::from_raw_parts_mut(dma_buf_ptr, buffer1.len() * 2) };
910
911            // set up the DMA
912            self.rx_dma.map(move |dma| {
913                self.dma_running.set(true);
914                dma.enable();
915                self.rx_length.set(dma_len);
916                dma.do_transfer(self.rx_dma_peripheral, dma_buf, dma_len);
917            });
918
919            // start timer
920            self.registers.cr.write(Control::TSTART::SET);
921
922            Ok(())
923        }
924    }
925
926    /// Provide a new buffer to send on-going buffered continuous samples to.
927    /// This is expected to be called after the `samples_ready` callback.
928    ///
929    /// - `buf`: buffer to fill with samples
930    /// - `length`: number of samples to collect (up to buffer length)
931    fn provide_buffer(
932        &self,
933        buf: &'static mut [u16],
934        length: usize,
935    ) -> Result<(), (ErrorCode, &'static mut [u16])> {
936        if !self.enabled.get() {
937            Err((ErrorCode::OFF, buf))
938        } else if !self.active.get() {
939            // cannot continue sampling that isn't running
940            Err((ErrorCode::INVAL, buf))
941        } else if !self.continuous.get() {
942            // cannot continue a single sample operation
943            Err((ErrorCode::INVAL, buf))
944        } else if self.next_dma_buffer.is_some() {
945            // we've already got a second buffer, we don't need a third yet
946            Err((ErrorCode::BUSY, buf))
947        } else {
948            // store the buffer for later use
949            self.next_dma_buffer.replace(buf);
950            self.next_dma_length.set(length);
951
952            Ok(())
953        }
954    }
955
956    /// Reclaim buffers after the ADC is stopped.
957    /// This is expected to be called after `stop_sampling`.
958    fn retrieve_buffers(
959        &self,
960    ) -> Result<(Option<&'static mut [u16]>, Option<&'static mut [u16]>), ErrorCode> {
961        if self.active.get() {
962            // cannot return buffers while running
963            Err(ErrorCode::INVAL)
964        } else {
965            // we're not running, so give back whatever we've got
966            Ok((self.next_dma_buffer.take(), self.stopped_buffer.take()))
967        }
968    }
969
970    fn set_highspeed_client(&self, client: &'a dyn hil::adc::HighSpeedClient) {
971        self.highspeed_client.set(client);
972    }
973}
974
975/// Implements a client of a DMA.
976impl dma::DMAClient for Adc<'_> {
977    /// Handler for DMA transfer completion.
978    ///
979    /// - `pid`: the DMA peripheral that is complete
980    fn transfer_done(&self, pid: dma::DMAPeripheral) {
981        // check if this was an RX transfer
982        if pid == self.rx_dma_peripheral {
983            // RX transfer was completed
984
985            // get buffer filled with samples from DMA
986            let dma_buffer = self.rx_dma.map_or(None, |rx_dma| {
987                self.dma_running.set(false);
988                let dma_buf = rx_dma.abort_transfer();
989                rx_dma.disable();
990                dma_buf
991            });
992
993            // get length of received buffer
994            let length = self.rx_length.get();
995
996            // start a new transfer with the next buffer
997            // we need to do this quickly in order to keep from missing samples.
998            // At 175000 Hz, we only have 5.8 us (~274 cycles) to do so
999            self.next_dma_buffer.take().map(|buf| {
1000                // first determine the buffer's length in samples
1001                let dma_len = cmp::min(buf.len(), self.next_dma_length.get());
1002
1003                // only continue with a nonzero length. If we were given a
1004                // zero-length buffer or length field, assume that the user knew
1005                // what was going on, and just don't use the buffer
1006                if dma_len > 0 {
1007                    // change buffer into a [u8]
1008                    // this is unsafe but acceptable for the following reasons
1009                    //  * the buffer is aligned based on 16-bit boundary, so the
1010                    //    8-bit alignment is fine
1011                    //  * the DMA is doing checking based on our expected data
1012                    //    width to make sure we don't go past
1013                    //    dma_buf.len()/width
1014                    //  * we will transmute the array back to a [u16] after the
1015                    //    DMA transfer is complete
1016                    let dma_buf_ptr =
1017                        unsafe { mem::transmute::<*mut u16, *mut u8>(buf.as_mut_ptr()) };
1018                    let dma_buf = unsafe { slice::from_raw_parts_mut(dma_buf_ptr, buf.len() * 2) };
1019
1020                    // set up the DMA
1021                    self.rx_dma.map(move |dma| {
1022                        self.dma_running.set(true);
1023                        dma.enable();
1024                        self.rx_length.set(dma_len);
1025                        dma.do_transfer(self.rx_dma_peripheral, dma_buf, dma_len);
1026                    });
1027                } else {
1028                    // if length was zero, just keep the buffer in the takecell
1029                    // so we can return it when `stop_sampling` is called
1030                    self.next_dma_buffer.replace(buf);
1031                }
1032            });
1033
1034            // alert client
1035            self.highspeed_client.map(|client| {
1036                dma_buffer.map(|dma_buf| {
1037                    // change buffer back into a [u16]
1038                    // the buffer was originally a [u16] so this should be okay
1039                    let buf_ptr =
1040                        unsafe { mem::transmute::<*mut u8, *mut u16>(dma_buf.as_mut_ptr()) };
1041                    let buf = unsafe { slice::from_raw_parts_mut(buf_ptr, dma_buf.len() / 2) };
1042
1043                    // pass the buffer up to the next layer. It will then either
1044                    // send down another buffer to continue sampling, or stop
1045                    // sampling
1046                    client.samples_ready(buf, length);
1047                });
1048            });
1049        }
1050    }
1051}