1 /******************************************************************************
2 *  Filename:       aux_dac.c
3 *
4 *  Description:    Driver for the AUX Digital-to-Analog Converter interface.
5 *
6 *  Copyright (c) 2015 - 2022, Texas Instruments Incorporated
7 *  All rights reserved.
8 *
9 *  Redistribution and use in source and binary forms, with or without
10 *  modification, are permitted provided that the following conditions are met:
11 *
12 *  1) Redistributions of source code must retain the above copyright notice,
13 *     this list of conditions and the following disclaimer.
14 *
15 *  2) Redistributions in binary form must reproduce the above copyright notice,
16 *     this list of conditions and the following disclaimer in the documentation
17 *     and/or other materials provided with the distribution.
18 *
19 *  3) Neither the name of the ORGANIZATION nor the names of its contributors may
20 *     be used to endorse or promote products derived from this software without
21 *     specific prior written permission.
22 *
23 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 *  POSSIBILITY OF SUCH DAMAGE.
34 *
35 ******************************************************************************/
36 #include "aux_dac.h"
37 
38 
39 //*****************************************************************************
40 //
41 // Sets the DAC's voltage reference
42 //
43 //*****************************************************************************
44 void
AUXDACSetVref(uint8_t refSource)45 AUXDACSetVref(uint8_t refSource)
46 {
47     HWREGB(AUX_ADI4_BASE + ADI_4_AUX_O_MUX2) = refSource;
48 
49     if(refSource == AUXDAC_VREF_SEL_ADCREF)
50     {
51         // Enable the ADC reference module.
52         HWREGB(AUX_ADI4_BASE + ADI_4_AUX_O_ADCREF0) |= ADI_4_AUX_ADCREF0_REF_ON_IDLE | ADI_4_AUX_ADCREF0_EN;
53     }
54 }
55 
56 //*****************************************************************************
57 //
58 // Enables precharge
59 //
60 //*****************************************************************************
61 void
AUXDACEnablePreCharge(void)62 AUXDACEnablePreCharge(void)
63 {
64     HWREG(AUX_ANAIF_BASE + AUX_ANAIF_O_DACCTL) |= AUX_ANAIF_DACCTL_DAC_PRECHARGE_EN;
65 }
66 
67 //*****************************************************************************
68 //
69 // Disables precharge
70 //
71 //*****************************************************************************
72 void
AUXDACDisablePreCharge(void)73 AUXDACDisablePreCharge(void)
74 {
75     HWREG(AUX_ANAIF_BASE + AUX_ANAIF_O_DACCTL) &= ~(0x1 << AUX_ANAIF_DACCTL_DAC_PRECHARGE_EN_S);
76 }
77 
78 //*****************************************************************************
79 //
80 // Returns maximum DAC voltage in uV
81 //
82 //*****************************************************************************
83 uint32_t
AUXDACCalcMax(void)84 AUXDACCalcMax(void)
85 {
86     uint32_t prechargeStatus;
87     uint32_t refSource;
88     uint32_t dacMax;
89 
90     // Depending on the selected DAC voltage reference, obtain calibration value C2 in millivolts.
91     refSource = ((HWREGB(AUX_ADI4_BASE + ADI_4_AUX_O_MUX2) & ADI_4_AUX_MUX2_DAC_VREF_SEL_M) >> ADI_4_AUX_MUX2_DAC_VREF_SEL_S);
92 
93     switch (refSource)
94     {
95         // Nothing connected. Input is floating.
96         case AUXDAC_VREF_SEL_NC:
97 
98             dacMax = 0;
99             break;
100 
101         // Core Voltage Decoupling pin as the DAC's voltage reference source.
102         case AUXDAC_VREF_SEL_DCOUPL:
103 
104             prechargeStatus = ((HWREG( AUX_ANAIF_BASE + AUX_ANAIF_O_DACCTL) & AUX_ANAIF_DACCTL_DAC_PRECHARGE_EN_M) >> AUX_ANAIF_DACCTL_DAC_PRECHARGE_EN_S);
105             dacMax = (prechargeStatus == 0) ? ((HWREG(FCFG1_BASE + FCFG1_O_DAC_CAL0) & FCFG1_DAC_CAL0_SOC_DAC_VOUT_CAL_DECOUPLE_C2_M) >> FCFG1_DAC_CAL0_SOC_DAC_VOUT_CAL_DECOUPLE_C2_S) \
106                                             : ((HWREG(FCFG1_BASE + FCFG1_O_DAC_CAL1) & FCFG1_DAC_CAL1_SOC_DAC_VOUT_CAL_PRECH_C2_M) >> FCFG1_DAC_CAL1_SOC_DAC_VOUT_CAL_PRECH_C2_S);
107             break;
108 
109         // ADC reference voltage as the DAC's voltage reference source.
110         case AUXDAC_VREF_SEL_ADCREF:
111 
112             dacMax = ((HWREG(FCFG1_BASE + FCFG1_O_DAC_CAL2) & FCFG1_DAC_CAL2_SOC_DAC_VOUT_CAL_ADCREF_C2_M) >> FCFG1_DAC_CAL2_SOC_DAC_VOUT_CAL_ADCREF_C2_S);
113             break;
114 
115         // Main supply voltage VDDS as the DAC's voltage reference source.
116         case AUXDAC_VREF_SEL_VDDS:
117 
118             // Note: The calibration value is measured at a VDDS of 3.0V. If VDDS is selected as reference,
119             // measure VDDS and scale the calibration value.
120             dacMax = ((HWREG(FCFG1_BASE + FCFG1_O_DAC_CAL3) & FCFG1_DAC_CAL3_SOC_DAC_VOUT_CAL_VDDS_C2_M) >> FCFG1_DAC_CAL3_SOC_DAC_VOUT_CAL_VDDS_C2_S);
121             break;
122 
123         // Nothing connected. Input is floating.
124         default:
125 
126             dacMax = 0;
127     }
128 
129     return dacMax;
130 }
131 
132 //*****************************************************************************
133 //
134 // Returns minimum DAC voltage in uV
135 //
136 //*****************************************************************************
137 uint32_t
AUXDACCalcMin(void)138 AUXDACCalcMin(void)
139 {
140     uint32_t refSource;
141     uint32_t prechargeStatus;
142     uint32_t dacMin;
143 
144     // Depending on the selected DAC voltage reference, obtain calibration value C1 in millivolts.
145     refSource = ((HWREGB(AUX_ADI4_BASE + ADI_4_AUX_O_MUX2) & ADI_4_AUX_MUX2_DAC_VREF_SEL_M) >> ADI_4_AUX_MUX2_DAC_VREF_SEL_S);
146 
147     switch (refSource)
148     {
149         // Nothing connected. Input is floating.
150         case AUXDAC_VREF_SEL_NC:
151             dacMin = 0;
152             break;
153 
154         // Core Voltage Decoupling pin as the DAC's voltage reference source.
155         case AUXDAC_VREF_SEL_DCOUPL:
156 
157             prechargeStatus = ((HWREG(AUX_ANAIF_BASE + AUX_ANAIF_O_DACCTL) & AUX_ANAIF_DACCTL_DAC_PRECHARGE_EN_M) >> AUX_ANAIF_DACCTL_DAC_PRECHARGE_EN_S);
158             dacMin = (prechargeStatus == 0) ? ((HWREG(FCFG1_BASE + FCFG1_O_DAC_CAL0) & FCFG1_DAC_CAL0_SOC_DAC_VOUT_CAL_DECOUPLE_C1_M) >> FCFG1_DAC_CAL0_SOC_DAC_VOUT_CAL_DECOUPLE_C1_S) \
159                                             : ((HWREG(FCFG1_BASE + FCFG1_O_DAC_CAL1) & FCFG1_DAC_CAL1_SOC_DAC_VOUT_CAL_PRECH_C1_M) >> FCFG1_DAC_CAL1_SOC_DAC_VOUT_CAL_PRECH_C1_S);
160             break;
161 
162         // ADC reference voltage as the DAC's voltage reference source.
163         case AUXDAC_VREF_SEL_ADCREF:
164             dacMin = ((HWREG( FCFG1_BASE + FCFG1_O_DAC_CAL2) & FCFG1_DAC_CAL2_SOC_DAC_VOUT_CAL_ADCREF_C1_M) >> FCFG1_DAC_CAL2_SOC_DAC_VOUT_CAL_ADCREF_C1_S);
165             break;
166 
167         // Main supply voltage VDDS as the DAC's voltage reference source.
168         case AUXDAC_VREF_SEL_VDDS:
169             dacMin = ((HWREG( FCFG1_BASE + FCFG1_O_DAC_CAL3) & FCFG1_DAC_CAL3_SOC_DAC_VOUT_CAL_VDDS_C1_M) >> FCFG1_DAC_CAL3_SOC_DAC_VOUT_CAL_VDDS_C1_S);
170             break;
171 
172         // Nothing connected. Input is floating.
173         default:
174 
175             dacMin = 0;
176     }
177 
178     return dacMin;
179 }
180 
181 //*****************************************************************************
182 //
183 // Returns 8-bit DAC code from requested voltage in (uV)
184 //
185 //*****************************************************************************
186 uint32_t
AUXDACCalcCode(uint32_t uVoltOut,uint32_t uVoltOutMin,uint32_t uVoltOutMax)187 AUXDACCalcCode(uint32_t uVoltOut, uint32_t uVoltOutMin, uint32_t uVoltOutMax)
188 {
189     uint32_t dacCode = 0;
190 
191     if(uVoltOut != 0)
192     {
193         // Rounding (by adding 0.5 before truncating)
194         dacCode = (((254 * (uVoltOut - uVoltOutMin) * 2) / (uVoltOutMax - uVoltOutMin) + 1) / 2) + 1;
195     }
196     return (uint32_t)dacCode;
197 }
198 
199 //*****************************************************************************
200 //
201 // Sets the DAC sample clock
202 //
203 //*****************************************************************************
204 void
AUXDACSetSampleClock(uint8_t dacClkDiv)205 AUXDACSetSampleClock(uint8_t dacClkDiv)
206 {
207 
208     // Set the peripheral operational rate to the AUX bus rate of 24 MHz.
209     HWREGB(AUX_SYSIF_BASE + AUX_SYSIF_O_PEROPRATE) |= AUX_SYSIF_PEROPRATE_ANAIF_DAC_OP_RATE_BUS_RATE;
210 
211     // Set sample clock frequency considering a clock base frequency of 24 MHz and the given clock divider.
212     HWREGB(AUX_ANAIF_BASE + AUX_ANAIF_O_DACSMPLCFG0) = dacClkDiv;
213 }
214 
215 //*****************************************************************************
216 //
217 // Sets the DAC's code
218 //
219 //*****************************************************************************
220 void
AUXDACSetCode(uint8_t dacCode)221 AUXDACSetCode(uint8_t dacCode)
222 {
223     // Update the DAC's output value.
224     HWREGB(AUX_ANAIF_BASE + AUX_ANAIF_O_DACVALUE) = dacCode;
225 }
226 
227 //*****************************************************************************
228 //
229 // Enables the DAC
230 //
231 //*****************************************************************************
232 void
AUXDACEnable(uint8_t dacPinId)233 AUXDACEnable(uint8_t dacPinId)
234 {
235     // Set the operational mode to active
236     HWREG(AUX_SYSIF_BASE + AUX_SYSIF_O_OPMODEREQ) = AUX_SYSIF_OPMODEREQ_REQ_A;
237 
238     // Disable the low power bias control
239     HWREGB(AUX_ANAIF_BASE + AUX_ANAIF_O_LPMBIASCTL) = 0x0;
240 
241     // Enable the DAC sample clock
242     HWREGB(AUX_ANAIF_BASE + AUX_ANAIF_O_DACSMPLCTL) = AUX_ANAIF_DACSMPLCTL_EN;
243 
244     // Enable DAC and buffer and set COMPA_IN
245     HWREGB(AUX_ANAIF_BASE + AUX_ANAIF_O_DACCTL) |= AUX_ANAIF_DACCTL_DAC_EN | AUX_ANAIF_DACCTL_DAC_BUFFER_EN | AUX_ANAIF_DACCTL_DAC_VOUT_SEL_COMPA_IN;
246 
247     // Select COMPA output (0 will disconnect from DIOs)
248     HWREGB(AUX_ADI4_BASE + ADI_4_AUX_O_MUX1) = dacPinId;
249 }
250 
251 //*****************************************************************************
252 //
253 // Disables the DAC
254 //
255 //*****************************************************************************
256 void
AUXDACDisable(void)257 AUXDACDisable(void)
258 {
259     // Disable the DAC sample clock
260     HWREGB(AUX_ANAIF_BASE + AUX_ANAIF_O_DACSMPLCTL) = 0x0;
261 
262     // Disable DAC, the DAC's buffer, and disconnect internally.
263     HWREGB(AUX_ANAIF_BASE + AUX_ANAIF_O_DACCTL) &= ~(0x1 << AUX_ANAIF_DACCTL_DAC_EN_S) &      \
264                                                    ~(0x1 << AUX_ANAIF_DACCTL_DAC_BUFFER_EN_S) &   \
265                                                    ~(AUX_ANAIF_DACCTL_DAC_VOUT_SEL_M << AUX_ANAIF_DACCTL_DAC_VOUT_SEL_S);
266 
267     // Disconnect COMPA_IN from DIOs
268     HWREGB(AUX_ADI4_BASE + ADI_4_AUX_O_MUX1) = 0x0;
269 
270     // Set operational mode to Power-Down
271     HWREG(AUX_SYSIF_BASE + AUX_SYSIF_O_OPMODEREQ) = AUX_SYSIF_OPMODEREQ_REQ_PDA;
272 
273     // Set the peripheral operational rate to the SCE rate
274     HWREGB(AUX_SYSIF_BASE + AUX_SYSIF_O_PEROPRATE) = AUX_SYSIF_PEROPRATE_ANAIF_DAC_OP_RATE_SCE_RATE;
275 }
276