msp432/
ref_module.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//! Reference Module (REF)
6
7use core::cell::Cell;
8use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
9use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
10use kernel::utilities::StaticRef;
11
12register_structs! {
13    /// REF
14    RefRegisters {
15        /// REF Control Register 0
16        (0x000 => ctl0: ReadWrite<u16, CTL0::Register>),
17        (0x002 => @END),
18    }
19}
20register_bitfields![u16,
21    CTL0 [
22        /// Reference enable
23        REFON OFFSET(0) NUMBITS(1) [
24            /// Disables reference if no other reference requests are pending
25            DisablesReferenceIfNoOtherReferenceRequestsArePending = 0,
26            /// Enables reference in static mode
27            EnablesReferenceInStaticMode = 1
28        ],
29        /// Reference output buffer
30        REFOUT OFFSET(1) NUMBITS(1) [
31            /// Reference output not available externally
32            ReferenceOutputNotAvailableExternally = 0,
33            /// Reference output available externally. If ADC14REFBURST = 0, output is available
34            REFOUT_1 = 1
35        ],
36        /// Temperature sensor disabled
37        REFTCOFF OFFSET(3) NUMBITS(1) [
38            /// Temperature sensor enabled
39            TemperatureSensorEnabled = 0,
40            /// Temperature sensor disabled to save power
41            TemperatureSensorDisabledToSavePower = 1
42        ],
43        /// Reference voltage level select
44        REFVSEL OFFSET(4) NUMBITS(2) [
45            /// 1.2 V available when reference requested or REFON = 1
46            _12VAvailableWhenReferenceRequestedOrREFON1 = 0,
47            /// 1.45 V available when reference requested or REFON = 1
48            _145VAvailableWhenReferenceRequestedOrREFON1 = 1,
49            /// 2.5 V available when reference requested or REFON = 1
50            _25VAvailableWhenReferenceRequestedOrREFON1 = 3
51        ],
52        /// Reference generator one-time trigger
53        REFGENOT OFFSET(6) NUMBITS(1) [
54            /// No trigger
55            NoTrigger = 0,
56            /// Generation of the reference voltage is started by writing 1 or by a hardware tri
57            GenerationOfTheReferenceVoltageIsStartedByWriting1OrByAHardwareTrigger = 1
58        ],
59        /// Bandgap and bandgap buffer one-time trigger
60        REFBGOT OFFSET(7) NUMBITS(1) [
61            /// No trigger
62            NoTrigger = 0,
63            /// Generation of the bandgap voltage is started by writing 1 or by a hardware trigg
64            GenerationOfTheBandgapVoltageIsStartedByWriting1OrByAHardwareTrigger = 1
65        ],
66        /// Reference generator active
67        REFGENACT OFFSET(8) NUMBITS(1) [
68            /// Reference generator not active
69            ReferenceGeneratorNotActive = 0,
70            /// Reference generator active
71            ReferenceGeneratorActive = 1
72        ],
73        /// Reference bandgap active
74        REFBGACT OFFSET(9) NUMBITS(1) [
75            /// Reference bandgap buffer not active
76            ReferenceBandgapBufferNotActive = 0,
77            /// Reference bandgap buffer active
78            ReferenceBandgapBufferActive = 1
79        ],
80        /// Reference generator busy
81        REFGENBUSY OFFSET(10) NUMBITS(1) [
82            /// Reference generator not busy
83            ReferenceGeneratorNotBusy = 0,
84            /// Reference generator busy
85            ReferenceGeneratorBusy = 1
86        ],
87        /// Bandgap mode
88        BGMODE OFFSET(11) NUMBITS(1) [
89            /// Static mode
90            StaticMode = 0,
91            /// Sampled mode
92            SampledMode = 1
93        ],
94        /// Variable reference voltage ready status
95        REFGENRDY OFFSET(12) NUMBITS(1) [
96            /// Reference voltage output is not ready to be used
97            ReferenceVoltageOutputIsNotReadyToBeUsed = 0,
98            /// Reference voltage output is ready to be used
99            ReferenceVoltageOutputIsReadyToBeUsed = 1
100        ],
101        /// Buffered bandgap voltage ready status
102        REFBGRDY OFFSET(13) NUMBITS(1) [
103            /// Buffered bandgap voltage is not ready to be used
104            BufferedBandgapVoltageIsNotReadyToBeUsed = 0,
105            /// Buffered bandgap voltage is ready to be used
106            BufferedBandgapVoltageIsReadyToBeUsed = 1
107        ]
108    ]
109];
110
111const REF_BASE: StaticRef<RefRegisters> =
112    unsafe { StaticRef::new(0x4000_3000 as *const RefRegisters) };
113
114pub struct Ref {
115    registers: StaticRef<RefRegisters>,
116    ref_voltage: Cell<ReferenceVoltage>,
117}
118
119#[repr(u16)]
120#[derive(Copy, Clone, PartialEq)]
121pub enum ReferenceVoltage {
122    Volt1_2 = 0,
123    Volt1_45 = 1,
124    Volt2_5 = 3,
125}
126
127pub trait AnalogReference {
128    /// Return the configured reference voltage in mV
129    fn ref_voltage_mv(&self) -> usize;
130}
131
132impl Ref {
133    pub const fn new() -> Ref {
134        Ref {
135            registers: REF_BASE,
136            ref_voltage: Cell::new(ReferenceVoltage::Volt1_2),
137        }
138    }
139
140    /// Set the reference voltage of this module which will be used in the ADC and DAC modules.
141    /// The default voltage is 1.2V.
142    pub fn select_ref_voltage(&self, ref_voltage: ReferenceVoltage) {
143        self.ref_voltage.set(ref_voltage);
144        while self.registers.ctl0.is_set(CTL0::REFGENBUSY) {}
145        self.registers
146            .ctl0
147            .modify(CTL0::REFVSEL.val(ref_voltage as u16));
148    }
149
150    /// Enable or disable the internal temperature sensor.
151    /// The default-setting is enabled.
152    pub fn enable_temp_sensor(&self, enable: bool) {
153        while self.registers.ctl0.is_set(CTL0::REFGENBUSY) {}
154        // Enable the temperature sensor
155        // Enable the reference module, otherwise the temperature sensor doesn't work
156        self.registers
157            .ctl0
158            .modify(CTL0::REFTCOFF.val((!enable) as u16) + CTL0::REFON::SET);
159    }
160}
161
162impl AnalogReference for Ref {
163    fn ref_voltage_mv(&self) -> usize {
164        match self.ref_voltage.get() {
165            ReferenceVoltage::Volt1_2 => 1200,
166            ReferenceVoltage::Volt1_45 => 1450,
167            ReferenceVoltage::Volt2_5 => 2500,
168        }
169    }
170}