forked from pedvide/ADC
-
Notifications
You must be signed in to change notification settings - Fork 1
/
VREF.h
126 lines (111 loc) · 4.91 KB
/
VREF.h
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
/* Teensy 4.x, 3.x, LC ADC library
* https://github.com/pedvide/ADC
* Copyright (c) 2020 Pedro Villanueva
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ADC_VREF_H
#define ADC_VREF_H
#include <Arduino.h>
#include <atomic.h>
#include <settings_defines.h>
#ifdef ADC_USE_INTERNAL_VREF
//! Controls the Teensy internal voltage reference module (VREFV1)
namespace VREF
{
//! Start the 1.2V internal reference (if present)
/** This is called automatically by ADC_Module::setReference(ADC_REFERENCE::REF_1V2)
* Use it to switch on the internal reference on the VREF_OUT pin.
* You can measure it with adc->analogRead(ADC_INTERNAL_SOURCE::VREF_OUT).
* \param mode can be (these are defined in kinetis.h)
* VREF_SC_MODE_LV_BANDGAPONLY (0) for stand-by
* VREF_SC_MODE_LV_HIGHPOWERBUF (1) for high power buffer and
* VREF_SC_MODE_LV_LOWPOWERBUF (2) for low power buffer.
* \param trim adjusts the reference value, from 0 to 0x3F (63). Default is 32.
*
*/
inline void start(uint8_t mode = VREF_SC_MODE_LV_HIGHPOWERBUF, uint8_t trim = 0x20)
{
VREF_TRM = VREF_TRM_CHOPEN | (trim & 0x3F); // enable module and set the trimmer to medium (max=0x3F=63)
// enable 1.2 volt ref with all compensations in high power mode
VREF_SC = VREF_SC_VREFEN | VREF_SC_REGEN | VREF_SC_ICOMPEN | VREF_SC_MODE_LV(mode);
// "PMC_REGSC[BGEN] bit must be set if the VREF regulator is
// required to remain operating in VLPx modes."
// Also "If the chop oscillator is to be used in very low power modes,
// the system (bandgap) voltage reference must also be enabled."
// enable bandgap, can be read directly with ADC_INTERNAL_SOURCE::BANDGAP
atomic::setBitFlag(PMC_REGSC, PMC_REGSC_BGBE);
}
//! Set the trim
/** Set the trim, the change in the reference is about 0.5 mV per step.
* \param trim adjusts the reference value, from 0 to 0x3F (63).
*/
inline void trim(uint8_t trim)
{
bool chopen = atomic::getBitFlag(VREF_TRM, VREF_TRM_CHOPEN);
VREF_TRM = (chopen ? VREF_TRM_CHOPEN : 0) | (trim & 0x3F);
}
//! Stops the internal reference
/** This is called automatically by ADC_Module::setReference(ref) when ref is any other than REF_1V2
*/
__attribute__((always_inline)) inline void stop()
{
VREF_SC = 0;
atomic::clearBitFlag(PMC_REGSC, PMC_REGSC_BGBE);
}
//! Check if the internal reference has stabilized.
/** NOTE: This is valid only when the chop oscillator is not being used.
* By default the chop oscillator IS used, so wait the maximum start-up time of 35 ms (as per datasheet).
* waitUntilStable waits 35 us.
* This should be polled after enabling the reference after reset, after changing
* its buffer mode from VREF_SC_MODE_LV_BANDGAPONLY to any of the buffered modes, or
* after changing the trim.
*
* \return true if the VREF module is already in a stable condition and can be used.
*/
__attribute__((always_inline)) inline volatile bool isStable()
{
return atomic::getBitFlag(VREF_SC, VREF_SC_VREFST);
}
//! Check if the internal reference is on.
/**
* \return true if the VREF module is switched on.
*/
__attribute__((always_inline)) inline volatile bool isOn()
{
return atomic::getBitFlag(VREF_SC, VREF_SC_VREFEN);
}
//! Wait for the internal reference to stabilize.
/** This function can be called to wait for the internal reference to stabilize.
* It will block until the reference has stabilized, or return immediately if the
* reference is not enabled in the first place.
*/
inline void waitUntilStable()
{
delay(35); // see note in isStable()
while (isOn() && !isStable())
{
yield();
}
}
} // namespace VREF
#endif // ADC_USE_INTERNAL_VREF
#endif // ADC_VREF_H