Skip to main content

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