summaryrefslogtreecommitdiff
path: root/bsp/avr32/software_framework/drivers/adc/adc.c
blob: 0489b1f2f763ee06e3cb31c1de132e00fd5de148 (plain)
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
/*****************************************************************************
*
* \file
*
* \brief ADC driver for AVR UC3.
*
* This file defines a useful set of functions for ADC on AVR UC3 devices.
*
 * Copyright (c) 2009-2018 Microchip Technology Inc. and its subsidiaries.
*
* \asf_license_start
*
* \page License
*
* Subject to your compliance with these terms, you may use Microchip
* software and any derivatives exclusively with Microchip products.
* It is your responsibility to comply with third party license terms applicable
* to your use of third party software (including open source software) that
* may accompany Microchip software.
*
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
*
* \asf_license_stop
*
*****************************************************************************/
/*
 * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
 */

#include <avr32/io.h>
#include "compiler.h"
#include "adc.h"

/** \brief Configure ADC. Mandatory to call.
 * If not called, ADC channels will have side effects
 *
 * \param *adc Base address of the ADC
 */
void adc_configure(volatile avr32_adc_t *adc)
{
	Assert( adc != NULL );

#ifdef USE_ADC_8_BITS
	adc->mr |= 1 << AVR32_ADC_LOWRES_OFFSET;
#endif

	/* Set Sample/Hold time to max so that the ADC capacitor should be
	 * loaded entirely */
	adc->mr |= 0xF << AVR32_ADC_SHTIM_OFFSET;

	/* Set Startup to max so that the ADC capacitor should be loaded
	 * entirely */
	adc->mr |= 0x1F << AVR32_ADC_STARTUP_OFFSET;
}

/** \brief Start analog to digital conversion
 * \param *adc Base address of the ADC
 */
void adc_start(volatile avr32_adc_t *adc)
{
	Assert( adc != NULL );

	/* start conversion */
	adc->cr = AVR32_ADC_START_MASK;
}

/** \brief Enable channel
 *
 * \param *adc Base address of the ADC
 * \param  channel   channel to enable (0 to 7)
 */
void adc_enable(volatile avr32_adc_t *adc, uint16_t channel)
{
	Assert( adc != NULL );
	Assert( channel <= AVR32_ADC_CHANNELS_MSB ); /* check if channel exist
	                                              **/

	/* enable channel */
	adc->cher = (1 << channel);
}

/** \brief Disable channel
 *
 * \param *adc Base address of the ADC
 * \param  channel   channel to disable (0 to 7)
 */
void adc_disable(volatile avr32_adc_t *adc, uint16_t channel)
{
	Assert( adc != NULL );
	Assert( channel <= AVR32_ADC_CHANNELS_MSB ); /* check if channel exist
	                                              **/

	if (adc_get_status(adc, channel) == true) {
		/* disable channel */
		adc->chdr |= (1 << channel);
	}
}

/** \brief Get channel 0 to 7 status
 *
 * \param *adc Base address of the ADC
 * \param  channel   channel to handle (0 to 7)
 * \return bool      true if channel is enabled
 *                   false if channel is disabled
 */
bool adc_get_status(volatile avr32_adc_t *adc, uint16_t channel)
{
	Assert( adc != NULL );
	Assert( channel <= AVR32_ADC_CHANNELS_MSB ); /* check if channel exist
	                                              **/

	return ((adc->chsr & (1 << channel)) ? true : false);
}

/** \brief Check channel conversion status
 *
 * \param *adc Base address of the ADC
 * \param  channel   channel to check (0 to 7)
 * \return bool      true if conversion not running
 *                   false if conversion running
 */
bool adc_check_eoc(volatile avr32_adc_t *adc, uint16_t channel)
{
	Assert( adc != NULL );
	Assert( channel <= AVR32_ADC_CHANNELS_MSB ); /* check if channel exist
	                                              **/

	/* get SR register : EOC bit for channel */
	return ((adc->sr & (1 << channel)) ? true : false);
}

/** \brief Check channel conversion overrun error
 *
 * \param *adc Base address of the ADC
 * \param  channel   channel to check (0 to 7)
 * \return bool      FAIL if an error occurred
 *                   PASS if no error occurred
 */
bool adc_check_ovr(volatile avr32_adc_t *adc, uint16_t channel)
{
	Assert( adc != NULL );
	Assert( channel <= AVR32_ADC_CHANNELS_MSB ); /* check if channel exist
	                                              **/

	/* get SR register : OVR bit for channel */
	return ((adc->sr & (1 << (channel + 8))) ? FAIL : PASS);
}

/** \brief Get channel value
 *
 * \param *adc Base address of the ADC
 * \param  channel   channel to handle (0 to 7)
 * \return The value acquired (unsigned long)
 */
uint32_t adc_get_value(volatile avr32_adc_t *adc, uint16_t channel)
{
	Assert( adc != NULL );
	Assert( channel <= AVR32_ADC_CHANNELS_MSB );

	/* wait for end of conversion */
	while (adc_check_eoc(adc, channel) != true) {
	}

	return *((uint32_t *)((&(adc->cdr0)) + channel));
}

/** \brief Wait for the next converted data and return its value
 *
 * \param *adc Base address of the ADC
 * \return The latest converted value (unsigned long)
 */
uint32_t adc_get_latest_value(volatile avr32_adc_t *adc)
{
	Assert( adc != NULL );

	/* Wait for the data ready flag */
	while ((adc->sr & AVR32_ADC_DRDY_MASK) != AVR32_ADC_DRDY_MASK) {
	}

	return adc->lcdr;
}