nrf52/
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//! ADC driver for the nRF52. Uses the SAADC peripheral.
6
7use 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    /// Start the ADC and prepare the result buffer in RAM
20    tasks_start: WriteOnly<u32, TASK::Register>,
21    /// Take one ADC sample, if scan is enabled all channels are sampled
22    tasks_sample: WriteOnly<u32, TASK::Register>,
23    /// Stop the ADC and terminate any on-going conversion
24    tasks_stop: WriteOnly<u32, TASK::Register>,
25    /// Starts offset auto-calibration
26    tasks_calibrateoffset: WriteOnly<u32, TASK::Register>,
27    _reserved0: [u8; 240],
28    /// The ADC has started
29    events_started: ReadWrite<u32, EVENT::Register>,
30    /// The ADC has filled up the Result buffer
31    events_end: ReadWrite<u32, EVENT::Register>,
32    /// A conversion task has been completed. Depending on the mode, multiple conversion
33    events_done: ReadWrite<u32, EVENT::Register>,
34    /// A result is ready to get transferred to RAM
35    events_resultdone: ReadWrite<u32, EVENT::Register>,
36    /// Calibration is complete
37    events_calibratedone: ReadWrite<u32, EVENT::Register>,
38    /// The ADC has stopped
39    events_stopped: ReadWrite<u32, EVENT::Register>,
40    /// Last result is equal or above `CH[X].LIMIT`
41    events_ch: [AdcEventChRegisters; 8],
42    _reserved1: [u8; 424],
43    /// Enable or disable interrupt
44    inten: ReadWrite<u32, INTEN::Register>,
45    /// Enable interrupt
46    intenset: ReadWrite<u32, INTEN::Register>,
47    /// Disable interrupt
48    intenclr: ReadWrite<u32, INTEN::Register>,
49    _reserved2: [u8; 244],
50    /// Status
51    status: ReadOnly<u32>,
52    _reserved3: [u8; 252],
53    /// Enable or disable ADC
54    enable: ReadWrite<u32, ENABLE::Register>,
55    _reserved4: [u8; 12],
56    ch: [AdcChRegisters; 8],
57    _reserved5: [u8; 96],
58    /// Resolution configuration
59    resolution: ReadWrite<u32, RESOLUTION::Register>,
60    /// Oversampling configuration. OVERSAMPLE should not be combined with SCAN. The RES
61    oversample: ReadWrite<u32>,
62    /// Controls normal or continuous sample rate
63    samplerate: ReadWrite<u32, SAMPLERATE::Register>,
64    _reserved6: [u8; 48],
65    /// Pointer to store samples to
66    result_ptr: VolatileCell<*const u16>,
67    /// Number of 16 bit samples to save in RAM
68    result_maxcnt: ReadWrite<u32, RESULT_MAXCNT::Register>,
69    /// Number of 16 bit samples recorded to RAM
70    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        /// Enable or disable interrupt on EVENTS_STARTED event
90        STARTED 0,
91        /// Enable or disable interrupt on EVENTS_END event
92        END 1,
93        /// Enable or disable interrupt on EVENTS_DONE event
94        DONE 2,
95        /// Enable or disable interrupt on EVENTS_RESULTDONE event
96        RESULTDONE 3,
97        /// Enable or disable interrupt on EVENTS_CALIBRATEDONE event
98        CALIBRATEDONE 4,
99        /// Enable or disable interrupt on EVENTS_STOPPED event
100        STOPPED 5,
101        /// Enable or disable interrupt on EVENTS_CH[0].LIMITH event
102        CH0LIMITH 6,
103        /// Enable or disable interrupt on EVENTS_CH[0].LIMITL event
104        CH0LIMITL 7,
105        /// Enable or disable interrupt on EVENTS_CH[1].LIMITH event
106        CH1LIMITH 8,
107        /// Enable or disable interrupt on EVENTS_CH[1].LIMITL event
108        CH1LIMITL 9,
109        /// Enable or disable interrupt on EVENTS_CH[2].LIMITH event
110        CH2LIMITH 10,
111        /// Enable or disable interrupt on EVENTS_CH[2].LIMITL event
112        CH2LIMITL 11,
113        /// Enable or disable interrupt on EVENTS_CH[3].LIMITH event
114        CH3LIMITH 12,
115        /// Enable or disable interrupt on EVENTS_CH[3].LIMITL event
116        CH3LIMITL 13,
117        /// Enable or disable interrupt on EVENTS_CH[4].LIMITH event
118        CH4LIMITH 14,
119        /// Enable or disable interrupt on EVENTS_CH[4].LIMITL event
120        CH4LIMITL 15,
121        /// Enable or disable interrupt on EVENTS_CH[5].LIMITH event
122        CH5LIMITH 16,
123        /// Enable or disable interrupt on EVENTS_CH[5].LIMITL event
124        CH5LIMITL 17,
125        /// Enable or disable interrupt on EVENTS_CH[6].LIMITH event
126        CH6LIMITH 18,
127        /// Enable or disable interrupt on EVENTS_CH[6].LIMITL event
128        CH6LIMITL 19,
129        /// Enable or disable interrupt on EVENTS_CH[7].LIMITH event
130        CH7LIMITH 20,
131        /// Enable or disable interrupt on EVENTS_CH[7].LIMITL event
132        CH7LIMITL 21
133    ],
134    ENABLE [
135        ENABLE 0
136    ],
137    SAMPLERATE [
138        /// Capture and compare value. Sample rate is 16 MHz/CC
139        CC OFFSET(0) NUMBITS(11) [],
140        /// Select mode for sample rate control
141        MODE OFFSET(12) NUMBITS(1) [
142            /// Rate is controlled from SAMPLE task
143            Task = 0,
144            /// Rate is controlled from local timer (use CC to control the rate)
145            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
250// Buffer to save completed sample to.
251static 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    // Calibrate and measure the actual VDD of the board.
367    pub fn calibrate(&self) {
368        self.mode.set(AdcMode::Calibrate);
369
370        // Enable the ADC
371        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                    // After calibration, read VDD to set our voltage reference.
385                    self.registers.ch[0].pselp.write(PSEL::PSEL::VDD);
386                    self.registers.ch[0].pseln.write(PSEL::PSEL::NotConnected);
387
388                    // Configure the ADC for a single read.
389                    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                    // Where to put the reading.
402                    self.registers.result_ptr.set(addr_of!(SAMPLE) as *const _);
403
404                    // No automatic sampling, will trigger manually.
405                    self.registers.samplerate.write(SAMPLERATE::MODE::Task);
406
407                    // Enable the ADC
408                    self.registers.enable.write(ENABLE::ENABLE::SET);
409
410                    // Enable started, sample end, and stopped interrupts.
411                    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                    // self.registers.enable.write(ENABLE::ENABLE::CLEAR);
418                } else if self.registers.events_started.is_set(EVENT::EVENT) {
419                    self.registers.events_started.write(EVENT::EVENT::CLEAR);
420                    // ADC has started, now issue the sample.
421                    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                    // Reading finished. Turn off the ADC.
425                    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                    // ADC is stopped. Disable and return value.
429                    self.registers.enable.write(ENABLE::ENABLE::CLEAR);
430
431                    let reading = unsafe { SAMPLE[0] as i16 } as usize;
432
433                    // reading = val * (gain/ref) * 2^12
434                    //         = val * ((1/6)/0.6 V) * 2^12
435                    //         = val * 1/3600 mV * 2^12
436                    // val = (reading * 3600 mV) / 2^12
437                    let val = (reading * 3600) / (1 << 12);
438
439                    // If the reading looks like it exists in a reasonable range
440                    // than save this as the reference.
441                    if val > 1000 && val < 5100 {
442                        self.reference.set(val);
443                    }
444                }
445            }
446
447            AdcMode::Single => {
448                // Determine what event occurred.
449                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                    // ADC has started, now issue the sample.
457                    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                    // Reading finished. Turn off the ADC.
461                    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                    // ADC is stopped. Disable and return value.
465                    self.registers.enable.write(ENABLE::ENABLE::CLEAR);
466
467                    let val = unsafe { SAMPLE[0] as i16 };
468                    self.client.map(|client| {
469                        // shift left to meet the ADC HIL requirement
470                        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                    // According to PS1.7 Section 6.23.4, we can set the new
480                    // buffer address after we get the start event.
481                    self.next_buffer.map(|buf| {
482                        // First determine the buffer's length in samples.
483                        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                    // Trigger sample task to start taking samples.
490                    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                    // Left shift all samples to the MSB. This handles
497                    // differences in resolution between ADC chips and meets the
498                    // ADC HIL requirement.
499                    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                    // Optionally setup to continue reading. We already
509                    // configured the address if valid.
510                    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_sample.write(TASK::TASK::SET);
520                        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        // Positive goes to the channel passed in, negative not connected.
533        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        // Configure the ADC for a single read.
539        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        // Set max resolution (with oversampling).
551        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 = if raw_cc > 2047 {
563            2047
564        } else if raw_cc < 80 {
565            80
566        } else {
567            raw_cc
568        };
569
570        self.registers
571            .samplerate
572            .write(SAMPLERATE::MODE::Timers + SAMPLERATE::CC.val(cc));
573    }
574}
575
576/// Implements an ADC capable reading ADC samples on any channel.
577impl<'a> hil::adc::Adc<'a> for Adc<'a> {
578    type Channel = AdcChannelSetup;
579
580    fn sample(&self, channel: &Self::Channel) -> Result<(), ErrorCode> {
581        self.setup_channel(channel);
582        self.setup_resolution();
583
584        // Do one measurement.
585        self.registers
586            .result_maxcnt
587            .write(RESULT_MAXCNT::MAXCNT.val(1));
588        // Where to put the reading.
589        self.registers.result_ptr.set(addr_of!(SAMPLE) as *const _);
590
591        // No automatic sampling, will trigger manually.
592        self.registers.samplerate.write(SAMPLERATE::MODE::Task);
593
594        // Enable the ADC
595        self.registers.enable.write(ENABLE::ENABLE::SET);
596
597        // Enable started, sample end, and stopped interrupts.
598        self.registers
599            .inten
600            .write(INTEN::STARTED::SET + INTEN::END::SET + INTEN::STOPPED::SET);
601
602        self.mode.set(AdcMode::Single);
603
604        // Start the SAADC and wait for the started interrupt.
605        self.registers.tasks_start.write(TASK::TASK::SET);
606
607        Ok(())
608    }
609
610    fn sample_continuous(
611        &self,
612        _channel: &Self::Channel,
613        _frequency: u32,
614    ) -> Result<(), ErrorCode> {
615        Err(ErrorCode::FAIL)
616    }
617
618    fn stop_sampling(&self) -> Result<(), ErrorCode> {
619        self.registers.tasks_stop.write(TASK::TASK::SET);
620        Ok(())
621    }
622
623    fn get_resolution_bits(&self) -> usize {
624        12
625    }
626
627    fn get_voltage_reference_mv(&self) -> Option<usize> {
628        Some(self.reference.get())
629    }
630
631    fn set_client(&self, client: &'a dyn hil::adc::Client) {
632        self.client.set(client);
633    }
634}
635
636impl<'a> hil::adc::AdcHighSpeed<'a> for Adc<'a> {
637    fn sample_highspeed(
638        &self,
639        channel: &Self::Channel,
640        frequency: u32,
641        buffer1: &'static mut [u16],
642        length1: usize,
643        buffer2: &'static mut [u16],
644        length2: usize,
645    ) -> Result<(), (ErrorCode, &'static mut [u16], &'static mut [u16])> {
646        if length1 == 0 {
647            // At least need to take one sample.
648            Err((ErrorCode::INVAL, buffer1, buffer2))
649        } else {
650            // Store the second buffer for later use
651            self.next_buffer.replace(buffer2);
652            self.next_length.set(length2);
653
654            self.setup_channel(channel);
655            self.setup_resolution();
656
657            // Use EasyDMA to save the samples to our buffer.
658            self.registers.result_ptr.set(buffer1.as_ptr());
659
660            // Also need to save these to return to the caller.
661            self.buffer.replace(buffer1);
662            self.length.set(length1);
663
664            // Number of measurements.
665            self.setup_sample_count(length1);
666
667            // Set the frequency best we can.
668            self.setup_frequency(frequency);
669
670            // Enable the ADC
671            self.registers.enable.write(ENABLE::ENABLE::SET);
672
673            // Enable started, sample end, and stopped interrupts.
674            self.registers
675                .inten
676                .write(INTEN::STARTED::SET + INTEN::END::SET + INTEN::STOPPED::SET);
677
678            self.mode.set(AdcMode::HighSpeed);
679
680            // Start the SAADC and wait for the started interrupt.
681            self.registers.tasks_start.write(TASK::TASK::SET);
682
683            Ok(())
684        }
685    }
686
687    fn provide_buffer(
688        &self,
689        buf: &'static mut [u16],
690        length: usize,
691    ) -> Result<(), (ErrorCode, &'static mut [u16])> {
692        if self.next_buffer.is_some() {
693            // we've already got a second buffer, we don't need a third yet
694            Err((ErrorCode::BUSY, buf))
695        } else {
696            // store the buffer for later use
697            self.next_buffer.replace(buf);
698            self.next_length.set(length);
699
700            Ok(())
701        }
702    }
703
704    fn retrieve_buffers(
705        &self,
706    ) -> Result<(Option<&'static mut [u16]>, Option<&'static mut [u16]>), ErrorCode> {
707        Ok((self.buffer.take(), self.next_buffer.take()))
708    }
709
710    fn set_highspeed_client(&self, client: &'a dyn hil::adc::HighSpeedClient) {
711        self.highspeed_client.set(client);
712    }
713}