1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
//! The ADC Interface
//!
//! The ADC is disabled at startup and must be enabled (by calling
//! [Adc<Disabled>::enable]) before any of its registers can be accessed
//! (read or write). Attempts to access these registers will trigger a hardware
//! generated HardFault, which by default resets the microcontroller.
//!
//! The ADC can be polled for conversion completion with [Adc::is_done].
//! Completion will trigger an ADC Interrupt if enabled. See
//! [Adc::into_interrupt]
//!
//! ## Input Modes
//!
//! The Adc peripheral can operate in either single input or FIFO modes. Single
//! input mode is the mode most commonly thought of when using an ADC. A
//! multiplexer (via Adc::set_channel) is used to connect a single channel to
//! the ADC, and when the conversion is complete the hardware makes the results
//! available in the results register. The software must call
//! [Adc::set_channel] again to either select a new channel or to restart the
//! conversion on the same channel.
//!
//! The FIFO mode sets up a hardware buffer of selectable depth (2-8 channels).
//! Once the buffer is filled the Adc peripheral shoves the buffer contents
//! into the multiplexer channel by channel. Likewise, as each conversion is
//! completed the results are buffered into the result register in the same
//! order as the channel select buffer.
//!
//! Note: FIFO mode is not yet implemented in this HAL
//!
//! ## Conversion Modes
//!
//! The Adc peripheral offers 2 conversion modes, OneShot and Continuous. In
//! OneShot mode, the conversion is started when the channel is selected (or
//! when the channel select buffer is filled in FIFO mode). After completion no
//! new conversion is started until the channel is set again, even if the same
//! channel is used.
//!
//! In Continuous mode a new conversion is started immediately
//! after the previous one is completed. Changing the channel interrupts the
//! conversion and immediately begins conversion on the new channel (unless the
//! new channel is [DummyDisable], then the conversion is allowed to complete,
//! but no new conversion is started). In FIFO mode the input FIFO is reloaded
//! after completion, in other words the same N values are converted on a loop.
//!
//! Note: Continuous mode is not yet implemented in this HAL
//!
//! ## Comparison Mode
//!
//! Note: Comparison mode is not yet implemented in this HAL
//!
//! Comparison mode is a hardware feature of the Adc Peripheral. If set, the
//! conversion result is compared to the comparison value. If the result
//! is greater than or less than (depending on configuration) the comparison
//! value the result is moved into the result register. Otherwise, the result
//! is discarded \[Note: Unsure if the conversion is restarted in OneShot
//! mode\].
//!
//! A common use case for comparison mode is to enter a low power state with
//! the Adc configured to use the asynchronous clock source and to generate an
//! interrupt on completion. When the input channel crosses the comparison
//! threshold the interrupt is triggered, waking the MCU.
//!
//! ## Clocking
//!
//! The ADC requires a clock signal (ADCK), which is generated from the bus
//! clock, the bus clock divided by 2, the output of the OSC peripheral
//! (OSC_OUT), or an internal asynchronous clock, which, when selected,
//! operates in wait and stop modes. With any of these clock sources a
//! multi-value divider is provided to further divide the incoming clock by 1
//! (i.e. 1:1), 2, 4, or 8.
//!
//! The clock frequency must fall within 400kHz to 8MHz (4MHz in low power
//! mode), This is the same for all KEA MCUs. Ideally, the HAL will only
//! present valid options, but that is not yet implemented (pending clocks
//! improvements to output frequencies). For now you are trusted to input the
//! correct frequency.
//!
//! *Note:* When using the FIFO mode with FIFO scan mode disabled, the bus
//! clock must be faster than half the ADC clock (ADCK). Bus clock >= ADCK / 2.
//!
//! ## Pin Control
//!
//! This functionality is implemented in the GPIO module. See [Analog]
//! for details.
//!
//! ## Conversion Width
//!
//! The ADC can be run in 8, 10, or 12 bit modes. These modes are enumerated in
//! [AdcResolution].
//!
//! ## Hardware Trigger
//!
//! The ADC conversions can be started by a hardware trigger. This is not
//! implemented in all KEA chips, so implementation here will be Delayed. Use
//! the PAC. Enable is ADC_SC2\[ADTRG\] = 1, and trigger is the ADHWT source.
//!
//! ## Usage
//!
//! ### AdcConfig struct
//!
//! [AdcConfig] offers public fields to allow for creation in-place. The
//! [AdcConfig::calculate_divisor] method allows the user to specify the
//! desired Adc Clock frequency (given the clock source frequency). The clock
//! divider which gets the closest to that frequency is chosen.
//!
//! The AdcConfig structure also implements the [Default] trait.
//!
//! ```rust
//! let config: AdcConfig = Default::default();
//!
//! config.calculate_divisor(20_u32.MHz(), 2_u32.MHz());
//! assert!(matches!(config.clock_divisor, ClockDivisor::_8));
//! ```

use crate::hal::adc::{Channel, OneShot};
use crate::{pac::ADC, HALExt};
use core::{convert::Infallible, marker::PhantomData};
use embedded_time::rate::*;

/// Error Enumeration for this module
#[derive(Debug)]
pub enum Error {
    /// The Channel has already been moved
    Moved,
}

/// Analog type state for a GPIO pin.
///
/// This mode "gives" the pin to the ADC hardware peripheral.
/// The ADC Peripheral can take the GPIO pins in any state. The Peripheral will
/// reconfigure the pin to turn off any output drivers, disable input buffers
/// (reading the pin after configuring as analog will return a zero), and
/// disable the pullup. Electrically, an Analog pin that is not currently under
/// conversion is effectively HighImpedence.
///
/// Once a pin is released from the ADC, it will return to its previous state.
/// The previous state includes output enabled, input enabled, pullup enabled,
/// and level (for outputs). Note to accomplish this the pin implements the
/// outof_analog method, which is semantically different from the other type
/// states.
///
/// For example, [crate::gpio::gpioa::PTA0] is configured to be a Output that is set high is
/// converted into the analog mode with the [crate::gpio::gpioa::PTA0::into_analog] method.
/// Once measurements from that pin are completed it will be returned to an
/// Output that is set high by calling the [Analog::outof_analog] method.
///
/// ```rust
/// let pta0 = gpioa.pta0.into_push_pull_output();
/// pta0.set_high();
/// let mut pta0 = pta0.into_analog(); // pta0 is hi-Z
/// let value = adc.read(&mut pta0).unwrap_or(0);
/// let pta0 = pta0.outof_analog();  // pta0 is push-pull output, set high.
/// ```
///
/// Note: This is a hardware feature that requires effectively no clock cycles
/// to complete. "Manually" reconfiguring the pins to HighImpedence before
/// calling into_analog() is discouraged, but it would not hurt anything.
pub struct Analog<Pin> {
    pin: Pin,
}

/// Interface for ADC Peripheral.
///
/// Returned by calling [HALExt::split] on the pac [ADC] structure. Holds state
/// of peripheral.
pub struct Adc<State> {
    peripheral: ADC,
    _state: PhantomData<State>,
    /// Contains the On-Chip ADC Channels, like the MCU's temperature sensor.
    pub onchip_channels: OnChipChannels,
}

impl HALExt for ADC {
    type T = Adc<Disabled>;
    fn split(self) -> Adc<Disabled> {
        Adc {
            peripheral: self,
            _state: PhantomData,
            onchip_channels: OnChipChannels {
                vss: Some(Analog {
                    pin: Vss::<Input> { _mode: PhantomData },
                }),
                temp_sense: Some(Analog {
                    pin: TempSense::<Input> { _mode: PhantomData },
                }),
                bandgap: Some(Analog {
                    pin: Bandgap::<Input> { _mode: PhantomData },
                }),
                vref_h: Some(Analog {
                    pin: VrefH::<Input> { _mode: PhantomData },
                }),
                vref_l: Some(Analog {
                    pin: VrefL::<Input> { _mode: PhantomData },
                }),
            },
        }
    }
}

/// Configuration struct for Adc peripheral.
pub struct AdcConfig {
    /// Determines the clock source for the ADC peripheral
    ///
    /// Default is [AdcClocks::Bus]
    pub clock_source: AdcClocks,
    /// Divides the clock source to get the ADC clock into it's usable range of
    /// 400kHz - 8MHz (4MHz in low power mode).
    ///
    /// Default is [ClockDivisor::_1] (no divison)
    pub clock_divisor: ClockDivisor,
    /// Set the resolution of ADC conversion
    ///
    /// Default is [AdcResolution::_8bit]
    pub resolution: AdcResolution,

    /// Set ADC sample time.
    ///
    /// Default is [AdcSampleTime::Short]
    pub sample_time: AdcSampleTime,

    /// Set low power mode
    ///
    /// Default is false.
    pub low_power: bool,
}

impl AdcConfig {
    /// Calculate the ADC clock divisor
    ///
    /// Uses the current clock source and clock frequency to determine
    /// the best divisor to use in order to have minimal error between
    /// the ADC clock rate and the desired ADC clock rate.
    ///
    /// Note: This relies on trustworthy values for source_freq and valid
    /// values for req_adc_freq. In the future this should know or
    /// determine what the current clock frequency is instead of relying
    /// on the user to provide it.
    pub fn calculate_divisor(&mut self, source_freq: Hertz, req_adc_freq: Hertz) {
        let denom: u8 = (source_freq.integer() / req_adc_freq.integer()) as u8;

        let mut output: u8 = 1;
        let mut err: i8 = (denom - output) as i8;
        let mut err_old: i8 = err;
        let max_divisor = match self.clock_source {
            AdcClocks::Bus => 16,
            _ => 8,
        };
        while output < max_divisor {
            err = (denom - (output << 1)) as i8;
            if err.is_negative() {
                err = err.abs();
            }
            if err <= err_old {
                output <<= 1;
                err_old = err;
            } else {
                break;
            }
        }

        // I am of the mind that this assert is okay, at least until the input
        // clock can be known at compile time.
        let ad_clock = source_freq.integer() / output as u32;
        assert!(400_000 <= ad_clock);
        assert!(
            ad_clock
                <= match self.low_power {
                    false => 8_000_000,
                    true => 4_000_000,
                }
        );

        self.clock_divisor = match output {
            1 => ClockDivisor::_1,
            2 => ClockDivisor::_2,
            4 => ClockDivisor::_4,
            8 => ClockDivisor::_8,
            _ => ClockDivisor::_16,
        }
    }

    /// Set the divisor directly. panics if divisor isn't supported by the
    /// clock source.
    ///
    /// TODO: Refactor to remove assert. Add Clock Source as a type state
    pub fn set_divisor(&mut self, divisor: ClockDivisor) {
        // divisor can't be 16 unless using the Bus clock
        assert!(
            !(!matches!(self.clock_source, AdcClocks::Bus) && matches!(divisor, ClockDivisor::_16))
        );
        self.clock_divisor = divisor;
    }

    /// Sets the clock source, panics if divisor isn't supported
    ///
    /// TODO: Refactor to remove assert. Add Clock Source as a type state
    pub fn set_clock_source(&mut self, clock: AdcClocks) {
        // Panic if setting the clock to anything other than Bus if the divisor
        // is set to 16
        assert!(
            !matches!(clock, AdcClocks::Bus) && matches!(self.clock_divisor, ClockDivisor::_16)
        );
        self.clock_source = clock;
    }
}

impl Default for AdcConfig {
    fn default() -> AdcConfig {
        AdcConfig {
            clock_source: AdcClocks::Bus,
            clock_divisor: ClockDivisor::_1,
            resolution: AdcResolution::_12bit,
            sample_time: AdcSampleTime::Short,
            low_power: false,
        }
    }
}

/// Clock types available to the Adc peripheral
///
/// Dividers will be chosen appropriately to suit requested clock rate.
pub enum AdcClocks {
    /// Use the incoming Bus Clock
    Bus,
    /// jkl
    External,
    /// Available in Wait AND Stop Mode
    Async,
}

/// This enum represents the availabe ADC resolutions
///
/// Regardless of resolution chosen, results are always right justified
#[repr(u8)]
pub enum AdcResolution {
    /// 8 bit AD conversion mode
    _8bit = 0,
    /// 10 bit AD conversion mode
    _10bit = 1,
    /// 12 bit AD conversion mode
    _12bit = 2,
}

/// Adc sample time
pub enum AdcSampleTime {
    /// Sample for 3.5 ADC clock (ADCK) cycles.
    Short = 0,

    /// Sample for 23.5 ADC clock (ADCK) cycles.
    ///
    /// Required for high impedence (>2k @ADCK > 4MHz, >5k @ ADCK < 4MHz)
    /// inputs.
    Long = 1,
}

/// Adc Clock Divisors
///
/// Note 1/16 divisor is only usable for the Bus clock
pub enum ClockDivisor {
    /// Source / 1, No divison
    _1 = 0,
    /// Source / 2
    _2 = 1,
    /// Source / 4
    _4 = 2,
    /// Source / 8
    _8 = 3,
    /// Source / 16
    _16 = 4,
}

/// Enabled state
pub struct Enabled;

/// Disabled state
pub struct Disabled;

impl Adc<Enabled> {
    /// Poll to determine if ADC conversion is complete.
    ///
    /// Note: This flag is cleared when the sampling mode is changed,
    /// interrupts are enabled, [Adc::set_channel] is called, and when [Adc::result] is
    /// called (including [Adc::try_result])
    pub fn is_done(&self) -> bool {
        self.peripheral.sc1.read().coco().bit()
    }

    /// Poll to determine if ADC conversion is underway
    pub fn is_converting(&self) -> bool {
        self.peripheral.sc2.read().adact().bit()
    }

    /// Grab the last ADC conversion result.
    pub fn result(&self) -> u16 {
        self.peripheral.r.read().adr().bits()
    }

    /// Poll for conversion completion, if done return the result.
    pub fn try_result(&self) -> Option<u16> {
        if self.is_done() {
            Some(self.result())
        } else {
            None
        }
    }

    /// Set ADC target channel.
    ///
    /// In Single conversion mode (OneShot), setting the channel begins the conversion. In FIFO mode
    /// the channel is added to the FIFO buffer.
    ///
    /// Note: If the channel is changed while a conversion is in progress the
    /// current conversion will be cancelled. If in FIFO mode, conversion will
    /// resume once the FIFO channels are refilled.
    pub fn set_channel<T: Channel<Adc<Enabled>, ID = u8>>(&self, _pin: &T) {
        self.peripheral
            .sc1
            .modify(|_, w| unsafe { w.adch().bits(T::channel()) });
    }

    /// Set the ADC's configuration
    pub fn configure(self, config: AdcConfig) -> Adc<Enabled> {
        self.peripheral.sc3.modify(|_, w| {
            use pac::adc::sc3::{ADICLK_A, ADIV_A, ADLSMP_A, MODE_A};
            w.adiclk()
                .variant(match config.clock_source {
                    AdcClocks::Bus =>
                    // If divisor is 16, use the Bus / 2 clock source, else use
                    // the 1:1 Bus clock source
                    {
                        match config.clock_divisor {
                            ClockDivisor::_16 => ADICLK_A::_01,
                            _ => ADICLK_A::_00,
                        }
                    }
                    AdcClocks::External => ADICLK_A::_10,
                    AdcClocks::Async => ADICLK_A::_11,
                })
                .mode()
                .variant(match config.resolution {
                    AdcResolution::_8bit => MODE_A::_00,
                    AdcResolution::_10bit => MODE_A::_01,
                    AdcResolution::_12bit => MODE_A::_10,
                })
                .adlsmp()
                .variant(match config.sample_time {
                    AdcSampleTime::Short => ADLSMP_A::_0,
                    AdcSampleTime::Long => ADLSMP_A::_1,
                })
                .adiv()
                .variant(match config.clock_divisor {
                    ClockDivisor::_1 => ADIV_A::_00,
                    ClockDivisor::_2 => ADIV_A::_01,
                    ClockDivisor::_4 => ADIV_A::_10,
                    _ => ADIV_A::_11,
                })
                .adlpc()
                .bit(config.low_power)
        });

        // It looks like SCGC has to be set before touching the peripheral
        // at all, else hardfault. Go back later to confirm that if using external clock
        // scgc can be cleared.
        // w.adc().variant(match config.clock_source {
        //     AdcClocks::Bus => ADC_A::_1,
        //     _ => ADC_A::_0,
        // })

        Adc {
            peripheral: self.peripheral,
            _state: PhantomData,
            onchip_channels: self.onchip_channels,
        }
    }
}

impl Adc<Disabled> {
    /// Connects the bus clock to the adc via the SIM peripheral, allowing
    /// read and write access to ADC registers.
    ///
    /// Any attempt to access ADC registers while disabled results in a
    /// HardFault, generated by hardware.
    ///
    /// This also enables the bandgap voltage reference.
    pub fn enable(self) -> Adc<Enabled> {
        cortex_m::interrupt::free(|_| {
            unsafe { &(*pac::SIM::ptr()) }.scgc.modify(|_, w| {
                use pac::sim::scgc::ADC_A;
                w.adc().variant(ADC_A::_1)
            });

            // Don't start a conversion (set channel to DummyDisable)
            self.peripheral.sc1.modify(|_, w| w.adch()._11111());

            // Bandgap. Grab directly, Currently the bandgap isn't implemented
            // in [system::PMC]. We will eventually have to pass in the pmc
            // peripheral handle as a variable.
            unsafe { &(*pac::PMC::ptr()) }
                .spmsc1
                .modify(|_, w| w.bgbe()._1());
        });

        Adc {
            peripheral: self.peripheral,
            _state: PhantomData,
            onchip_channels: self.onchip_channels,
        }
    }

    /// Set the ADC's configuration
    ///
    /// This is a sugar method for calling [Adc<Disabled>::enable] followed by
    /// [Adc<Enabled>::configure]
    pub fn configure(self, config: AdcConfig) -> Adc<Enabled> {
        self.enable().configure(config)
    }
}

impl<Mode> Adc<Mode> {
    /// Not Implemented
    pub fn into_interrupt(self) -> Adc<Mode> {
        unimplemented!("Interrupt is not yet implemented");
        // Adc::<Mode> {
        //     peripheral: self.peripheral,
        //     _state: PhantomData,
        //     onchip_channels: self.onchip_channels,
        // }
    }

    /// Not Implemented
    pub fn into_fifo(self, _depth: u8) -> Adc<Mode> {
        // self.peripheral
        //     .sc4
        //     .modify(|_r, w| w.afdep().bits(depth & 0x7));
        // Adc::<Mode> {
        //     peripheral: self.peripheral,
        //     _state: PhantomData,
        //     onchip_channels: self.onchip_channels,
        // }
        unimplemented!("FIFO is not yet implemented");
    }

    /// Not Implemented
    pub fn into_continuous(self) -> Adc<Mode> {
        unimplemented!("Continuous Conversion mode not yet implemented");
    }
}

impl OnChipChannels {
    /// Request an instance of an on-chip [Vss] channel.
    pub fn vss(&mut self) -> Result<Analog<Vss<Input>>, Error> {
        self.vss.take().ok_or(Error::Moved)
    }

    /// Return the instance of [Vss]
    pub fn return_vss(&mut self, inst: Analog<Vss<Input>>) {
        self.vss.replace(inst);
    }

    /// Try to grab an instance of the onchip [TempSense] channel.
    pub fn tempsense(&mut self) -> Result<Analog<TempSense<Input>>, Error> {
        self.temp_sense.take().ok_or(Error::Moved)
    }

    /// Return the instance of [TempSense]
    pub fn return_tempsense(&mut self, inst: Analog<TempSense<Input>>) {
        self.temp_sense.replace(inst);
    }

    /// Try to grab an instance of the onchip [Bandgap] channel.
    ///
    /// The bandgap reference is a fixed 1.16V (nom, Factory trimmed to +/-
    /// 0.02V at Vdd=5.0 at 125C) signal that is available to the ADC Module.
    /// It can be used as a voltage reference for the ACMP and as an [Analog]
    /// channel that can be used to (roughly) check the VDD voltage
    pub fn bandgap(&mut self) -> Result<Analog<Bandgap<Input>>, Error> {
        self.bandgap.take().ok_or(Error::Moved)
    }

    /// Return the instance of [Bandgap]
    pub fn return_bandgap(&mut self, inst: Analog<Bandgap<Input>>) {
        self.bandgap.replace(inst);
    }

    /// Try to grab an instance of the onchip Voltage Reference High ([VrefH]) channel.
    pub fn vref_h(&mut self) -> Result<Analog<VrefH<Input>>, Error> {
        self.vref_h.take().ok_or(Error::Moved)
    }

    /// Return the instance of [VrefH]
    pub fn return_vref_h(&mut self, inst: Analog<VrefH<Input>>) {
        self.vref_h.replace(inst);
    }

    /// Try to grab an instance of the onchip Voltage Reference Low ([VrefL]) channel.
    pub fn vref_l(&mut self) -> Result<Analog<VrefL<Input>>, Error> {
        self.vref_l.take().ok_or(Error::Moved)
    }

    /// Return the instance of [VrefL]
    pub fn return_vref_l(&mut self, inst: Analog<VrefL<Input>>) {
        self.vref_l.replace(inst);
    }

    /// Grab a [DummyDisable] instance. Multiple Instances possible.
    pub fn dummy_disable(&self) -> Analog<DummyDisable<Input>> {
        Analog {
            pin: DummyDisable::<Input> { _mode: PhantomData },
        }
    }
}

/// Holds On-Chip ADC Channel inputs and provides an interface to grab and return them.
// These have to have the Input dummy type to allow them to have the Channel
// trait.
pub struct OnChipChannels {
    vss: Option<Analog<Vss<Input>>>,
    temp_sense: Option<Analog<TempSense<Input>>>,
    bandgap: Option<Analog<Bandgap<Input>>>,
    vref_h: Option<Analog<VrefH<Input>>>,
    vref_l: Option<Analog<VrefL<Input>>>,
}

/// Dummy type state for on-chip ADC input channels
pub struct Input;

/// Adc Input Channel, measures ground (should be 0?)
pub struct Vss<Input> {
    _mode: PhantomData<Input>,
}

/// Adc Input Channel, measures internal temperature sensor
pub struct TempSense<Input> {
    _mode: PhantomData<Input>,
}

/// Adc Input Channel, Bandgap internal voltage reference
pub struct Bandgap<Input> {
    _mode: PhantomData<Input>,
}

/// Adc Input Channel, Voltage Reference, High
pub struct VrefH<Input> {
    _mode: PhantomData<Input>,
}

/// Adc Input Channel, Voltage Reference, Low
pub struct VrefL<Input> {
    _mode: PhantomData<Input>,
}

/// Dummy Channel that temporarily disables the Adc Module.
pub struct DummyDisable<Input> {
    _mode: PhantomData<Input>,
}
macro_rules! adc_input_channels {
    ( $($Chan:expr => $Pin:ident),+ $(,)*) => {
        $(
            impl<OldMode> Channel<Adc<Enabled>> for Analog<$Pin<OldMode>> {
                type ID = u8;
                fn channel() -> u8 { $Chan }
            }
        )+
    };
}

use crate::gpio::{gpioa::*, gpiob::*};
adc_input_channels! (
    0_u8 => PTA0,
    1_u8 => PTA1,
    2_u8 => PTA6,
    3_u8 => PTA7,
    4_u8 => PTB0,
    5_u8 => PTB1,
    6_u8 => PTB2,
    7_u8 => PTB3,
    8_u8 => PTC0,
    9_u8 => PTC1,
    10_u8 => PTC2,
    11_u8 => PTC3,
    12_u8 => PTF4,
    13_u8 => PTF5,
    14_u8 => PTF6,
    15_u8 => PTF7,
    16_u8 => Vss,
    22_u8 => TempSense,
    23_u8 => Bandgap,
    24_u8 => VrefH,
    25_u8 => VrefL,
    0x1F_u8 => DummyDisable,
);

macro_rules! impl_analog_pin {
    ( $($Chan:expr => $Pin:ident),+ $(,)*) => {
        $(
            impl<OldMode> $Pin<OldMode> {
                /// Convert Pin into the [Analog] state for use by the ADC.
                ///
                /// This implementation provides the GPIO interface a method to
                /// give an eligible pin to the ADC peripheral for conversion
                /// into an Analog pin. This method is only implemented in
                /// eligible pins. The ADC peripheral disables the GPIO and
                /// PORT control over the pin and connects it to the ADC mux
                /// (controlled by [Adc::set_channel].
                ///
                /// Note: The [Analog::outof_analog] method must be used to
                /// return the pin to a normal Input/Output typestate. The pin
                /// will be returned in the same typestate as it was received.
                pub fn into_analog(self) -> Analog<$Pin<OldMode>> {
                    unsafe {
                        (*ADC::ptr())
                            .apctl1
                            .modify(|r, w| w.adpc().bits(r.adpc().bits() | (1 << $Chan)));
                    }
                    Analog { pin: self }
                }
            }

            impl<OldMode> Analog<$Pin<OldMode>> {
                /// Return Analog state Pin to normal GPIO-state interface.
                ///
                /// The Pin will be in the same state that it was when it
                /// entered the Analog type state.
                pub fn outof_analog(self) -> $Pin<OldMode> {
                    let adc = unsafe { &(*ADC::ptr()) };
                    adc.apctl1
                        .modify(|r, w| unsafe { w.adpc().bits(r.adpc().bits() & !(1 << $Chan)) });
                    self.pin
                }
            }
        )+
    };
}

impl_analog_pin!(
    0_u8 => PTA0,
    1_u8 => PTA1,
    2_u8 => PTA6,
    3_u8 => PTA7,
    4_u8 => PTB0,
    5_u8 => PTB1,
    6_u8 => PTB2,
    7_u8 => PTB3,
    8_u8 => PTC0,
    9_u8 => PTC1,
    10_u8 => PTC2,
    11_u8 => PTC3,
    12_u8 => PTF4,
    13_u8 => PTF5,
    14_u8 => PTF6,
    15_u8 => PTF7,
);

impl<Pin> OneShot<Adc<Enabled>, u16, Pin> for Adc<Enabled>
where
    Pin: Channel<Adc<Enabled>, ID = u8>,
{
    type Error = Infallible;

    fn read(&mut self, pin: &mut Pin) -> nb::Result<u16, Self::Error> {
        self.set_channel(pin);
        while !self.is_done() {}
        let ret_val = Ok(self.result());
        let disable = self.onchip_channels.dummy_disable();
        self.set_channel(&disable);
        ret_val
    }
}