-
Notifications
You must be signed in to change notification settings - Fork 2.1k
cpu/atmega_common: add adc driver #7227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@mali would you mind to close #6616 and help reviewing this PR instead? As you can see, it already contains your commits and your code. We currently have the capacity to take this one over, let's use it :-)! @mali can you give a quick hint about the arduino pin map |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick review and found some inconsistencies.
@@ -104,6 +104,24 @@ extern "C" { | |||
#define MEGA_PRR PRR0 /* Power Reduction Register */ | |||
/** @} */ | |||
|
|||
/** | |||
* @brief ADC configuration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be @name
@@ -104,6 +104,24 @@ extern "C" { | |||
#define MEGA_PRR PRR0 /* Power Reduction Register */ | |||
/** @} */ | |||
|
|||
/** | |||
* @brief ADC configuration | |||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line can be removed
cpu/atmega_common/periph/adc.c
Outdated
*/ | ||
|
||
/** | ||
* @ingroup driver_periph |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be drivers_periph
#define A4 4 | ||
#define A5 5 | ||
#ifdef CPU_ATMEGA2560 | ||
#define A6 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are the defines for A6
to A9
correct, 'cause they are the same as A0
to A3
and would reuse same ADC channels?
@@ -156,6 +156,26 @@ extern "C" { | |||
#define ARDUINO_PIN_A15 ARDUINO_PIN_69 | |||
#endif | |||
|
|||
/* arduino ADC notation compatibility */ | |||
#define A0 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't define macros with short names like this, it has the potential to create some very hard to track down problems later on when users try to use A0 etc as a variable name.
I have adapted this Pull Request to your comments. Please review the new commit. |
Looks good to me at first look, I should have time to test it between 5 and 11 July. |
#define ADC12 12 | ||
#define ADC13 13 | ||
#define ADC14 14 | ||
#define ADC15 15 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to stick with the existing naming see e.g. boards/arduino-due/arduino_pinmap.h
. Also the ADC lines should be defined using the ADC_LINE(x)
macro:
#define ARDUINO_A0 ADC_LINE(a)
#define ARDUINO_A1 ADC_LINE(b)
#define ARDUINO_A2 ADC_LINE(c)
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Further this ifdef jungle looks pretty ugly -> why not define these things directly once for each specific board in the corresponding boards source tree?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove the ifdef jungle, by removing the superfluous MCU. So I think, that the ADC defines can be remain in "boards/arduino-atmega-common/in clude/arduino_pinmap", because it includes already pin mapping of these MCU's.
#endif | ||
#ifdef CPU_ATMEGA1281 | ||
#define ADC_NUMOF (8) | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this has nothing to do with the boards, but is CPU specific. So this belongs into the CPU code tree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but all periphery of these MCU's (e.g. SPI, UART) is defined in "boards/arduino-atmega-common/include/periph_conf.h". So I think, that the ADC defines can be remain there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then this would have to be restructured everything?
#define ADC_PIN_5 5 | ||
#define ADC_PIN_6 6 | ||
#define ADC_PIN_7 7 | ||
/** @} */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, use ARDUINO_Ax ADC_LINE(x)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is no Arduino board. So I will remove ADC channel configuration.
sys/arduino/base.cpp
Outdated
int analogRead(int pin) | ||
{ | ||
adc_init((adc_t)pin); | ||
return adc_sample((adc_t)pin, (adc_res_t)0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't think the simple cast of pin
to adc_t
will suffice here. IMHO this functions needs
- check, if the given pin is a analog pin
- map the analog pin number to a RIOT ADC_LINE, possibly something like
ADC_LINE(pin - SOME_OFFSET?)
The Pull Request is adapted to additional comments. |
sys/arduino/base.cpp
Outdated
* 0: Not initialized | ||
* 1: Successfully initialized | ||
*/ | ||
static int adc_state[ADC_NUMOF]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for style reasons, I would prefer to define this variable outside of the function, its easier to read that way...
Also: IMHO it does not make sense to waste a lot of memory here by allocating a full int
for each ADC line. How about a bitfield instead? Using a uint16_t
should be ok, uint32_t
would be pretty safe, or even better the type could be defined depending on the value ADC_NUMOF
...
sys/arduino/base.cpp
Outdated
|
||
/* Initialization of given ADC channel */ | ||
if (adc_state[adc_pin] == 0) { | ||
if (adc_init(ADC_LINE(adc_pin)) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not correct: it is not guaranteed, that the RIOT ADC lines is mapped 'in order' to the Ardunio ADC pins (see boards/ardunio-due/include/arduino-pinmap.h
as example... The solution here is the same as done for the Arduino digital pins: we need to define a mapping between Ardunio analog pin numbers to actual RIOT ADC lines (as in boards/arduino-due/include/arduino-board.h
):
static const adc_t arduino_analog_pinmap[] = {
ARDUINO_A0,
....
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As memo for a follow-up PR: we might as well generalize the .../arduino-board.h
files to a central location and use ifdefs
to create the actual pin mapping arrays...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The mapping of the RIOT ADC lines to the Arduino ADC pins is in the adc_init() funktion. Therefore, I only adapted the Arduino pin numbers to the ADC lines through a subtraction of ADC_PIN_OFFSET.
found one more issue with the pin mapping |
it seems we have a misunderstanding here, the changes introduced with the last commit do not quite fix the issue at hand... I try to explain in the inline comments below. |
sys/arduino/base.cpp
Outdated
*/ | ||
static uint16_t adc_state; | ||
|
||
int analogRead(int arduino_pin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to make sure we are on the same page: arduino ADC pins (the value of arduion_pin
) are handled as unsigned integers starting from 0 for ARDUINO_A0 to x. To quote from here:
Syntax
analogRead(pin)
Parameters
pin: the number of the analog input pin to read from (0 to 5 on most boards, 0 to 7 on the Mini and Nano, 0 to 15 on the Mega)
sys/arduino/base.cpp
Outdated
int adc_value; | ||
|
||
/* Map the arduino pin number to the ADC line */ | ||
uint16_t adc_line_ = (uint16_t) (arduino_pin - ADC_PIN_OFFSET); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so given that ardunio_pin
is a number from [0:x]
with x
being the available analog ports on that board, this line is broken when substracting ADC_PIN_OFFSET
from such a value...
@@ -155,7 +155,6 @@ extern "C" { | |||
#define ARDUINO_PIN_A14 ARDUINO_PIN_68 | |||
#define ARDUINO_PIN_A15 ARDUINO_PIN_69 | |||
#endif | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you shoud re-add the ARDUINO_Ax
defines!
So to sketch the solution I had in mind: in
in
...
/**
* @brief Look-up table for analog Arduino pins
*/
static const adc_t arduino_analog_map[] = {
ARDUINO_A0,
ARDUINO_A1,
ARDUINO_A2,
ARDUINO_A3,
...
}; and finally in #define ANALOG_PIN_NUMOF (sizeof(arduino_analog_map) / sizeof(arduino_analog_map[0]))
static uint16_t adc_state = 0;
int analogRead(int arduino_pin) // remember, a value from [0 to number of analog Arduino pins]
{
int adc_value;
/* make sure the given pin is valid - TODO: better return error value?! */
assert((arduino_pin >= 0) && (arduino_pin < ANALOG_PIN_NUMOF);
/* Initialization of given ADC channel */
if (!(adc_state & (1 << arduino_pin))) {
if (adc_init(arduino_analog_map[arduino_pin] == 0)) {
adc_state |= (1 << arduino_pin);
}
else {
return -1; /* TODO: handle error as expected by ARDUNIO API */
}
}
/* Read the ADC channel */
adc_value = adc_sample(ADC_LINE(arduino_analog_map[arduino_pin]), ADC_RES_10BIT);
return adc_value;
} that should be it... |
@haukepetersen okay to squash? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some comments, still need to test.
sys/arduino/base.cpp
Outdated
/* Check the result of ADC */ | ||
if (adc_value == -2) { | ||
/* The resolution is not valid */ | ||
return -2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this if
is not needed, as you return adc_value
unchanged anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right ;)
sys/arduino/base.cpp
Outdated
|
||
/* Initialization of given ADC channel */ | ||
if (!(adc_line_state & (1 << arduino_pin))) { | ||
if (adc_init(ADC_LINE(arduino_analog_map[arduino_pin])) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO simpler version:
if (adc_init(ADC_LINE(arduino_analog_map[arduino_pin])) != 0) {
return -1;
}
/* The ADC channel is initialized */
adc_line_state |= 1 << arduino_pin;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also: drop the ADC_LINE
here! arduino_analog_map
already consists of entries of type adc_t
...
sys/arduino/base.cpp
Outdated
* 0: Not initialized | ||
* 1: Successfully initialized | ||
*/ | ||
static uint16_t adc_line_state = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove leading whitespace, btw. could use util function from bitfield.h
here
* @param[in] pin pin to read | ||
* | ||
* @return a value between 0 to 1023 that is proportionnal | ||
* to the voltage applied to the pin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
according the above, it may also return -1
or -2
on error
prep(); | ||
|
||
/* Disable corresponding Digital input */ | ||
#if defined (CPU_ATMEGA328P) || defined (CPU_ATMEGA1281) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indention if of by one tab for all #if
statements following
cpu/atmega_common/periph/adc.c
Outdated
PORTC &= ~(1 << line); | ||
#endif | ||
#ifdef CPU_ATMEGA2560 | ||
if (line < 8) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe move upward to previous matching if else
simplifies preprocessor stuff a bit
cpu/atmega_common/periph/adc.c
Outdated
ADCSRA |= (1 << ADSC); | ||
|
||
/* Wait until the conversion is complete */ | ||
while(ADCSRA & (1 << ADSC)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
coding style (space before parentheses and braces instead of semi-colon) should be while (ADCSRA & (1 << ADSC)) {}
ADMUX |= line; | ||
#endif | ||
#ifdef CPU_ATMEGA2560 | ||
if(line < 8) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
coding style, missing space after if
#define ARDUINO_A2 ADC_LINE(2) | ||
#define ARDUINO_A3 ADC_LINE(3) | ||
#define ARDUINO_A4 ADC_LINE(4) | ||
#define ARDUINO_A5 ADC_LINE(5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code duplication here. You can omit the #ifdef CPU_ATMEGA328P
above and define A0-A5 for all boards and then you optionally add A6-A15 for the mega2560...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Atmega328p (arduino nano) has also lines A6 and A7, please move the following #ifdef
two lines below
#ifdef CPU_ATMEGA2560 | ||
#define ADC_NUMOF (16) | ||
#define ADC_PIN_OFFSET 54 | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#if defined(CPU_ATMEGA328P)
#define ADC_NUMOF (5)
#define ADC_PIN_OFFSET 14
#elif defined(CPU_ATMEGA2560)
#define ADC_NUMOF (16)
#define ADC_PIN_OFFSET 54
#endif
would be a little more compact...
#ifdef CPU_ATMEGA2560 | ||
#define ADC_NUMOF (16) | ||
#define ADC_PIN_OFFSET 54 | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#if defined(CPU_ATMEGA328P)
#define ADC_NUMOF (5)
#define ADC_PIN_OFFSET 14
#elif defined(CPU_ATMEGA2560)
#define ADC_NUMOF (16)
#define ADC_PIN_OFFSET 54
#endif
would be a little more compact...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And also: do I see it correctly, that ADC_PIN_OFFSET
is not used anywhere anymore?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right ;)
cpu/atmega_common/periph/adc.c
Outdated
if(line < 8) | ||
DIDR0 |= (1 << line); | ||
else | ||
DIDR2 |= (1 << (line-8)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spaces missing: (line - 8)
/* check if the line is valid */ | ||
if (line >= ADC_NUMOF) { | ||
return -1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the line should be checked using assert
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@haukepetersen actually not, the documentation states "@return -1 on invalid ADC line"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true, never mind.
cpu/atmega_common/periph/adc.c
Outdated
|
||
/* check if resolution is applicable */ | ||
if (res != ADC_RES_10BIT) { | ||
return -2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the API doc states: @return -1 if resolution is not applicable
...
ADMUX &= 0xf0; | ||
ADMUX |= line; | ||
#endif | ||
#ifdef CPU_ATMEGA2560 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not use a straight forward #elif defined(CPU_ATMEGA2560)
here? This would be IMHO a little easier to read...
sys/arduino/base.cpp
Outdated
|
||
/* Initialization of given ADC channel */ | ||
if (!(adc_line_state & (1 << arduino_pin))) { | ||
if (adc_init(ADC_LINE(arduino_analog_map[arduino_pin])) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also: drop the ADC_LINE
here! arduino_analog_map
already consists of entries of type adc_t
...
sys/arduino/base.cpp
Outdated
} | ||
|
||
/* Read the ADC channel */ | ||
adc_value = adc_sample(ADC_LINE(arduino_analog_map[arduino_pin]), ADC_RES_10BIT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drop ADC_LINE
here as well
Just tested with mega2560, and it works fine. Please address latest comments by @haukepetersen and me, otherwise pre-ACK. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be a bit more flexible. Init function should do nothing but initialise pin and disable the digital buffer (DIR0 and DIR1). Adc sample should do the rest. Implementing it using the interrupt rather than a busy wait could be useful too :-)
#define ARDUINO_A2 ADC_LINE(2) | ||
#define ARDUINO_A3 ADC_LINE(3) | ||
#define ARDUINO_A4 ADC_LINE(4) | ||
#define ARDUINO_A5 ADC_LINE(5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Atmega328p (arduino nano) has also lines A6 and A7, please move the following #ifdef
two lines below
* @{ | ||
*/ | ||
#if defined (CPU_ATMEGA328P) | ||
#define ADC_NUMOF (5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to set it to 8. For a project I remapped the software interrupt to another pin since it's easily doable. I also think the 1281 does not have lines over 7, maybe you can turn the defines around to simplify the code
#ifdef 2560
16
#else
8
#endif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@smlng what do you think about it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/* check if the line is valid */ | ||
if (line >= ADC_NUMOF) { | ||
return -1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@haukepetersen actually not, the documentation states "@return -1 on invalid ADC line"
int sample = 0; | ||
|
||
/* check if resolution is applicable */ | ||
assert(res == ADC_RES_10BIT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a return. Documentation states:
@return -1 if resolution is not applicable
return -1; | ||
} | ||
|
||
prep(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ADC doesn't need to be enabled here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it must be locked
PORTF &= ~(1 << line); | ||
#endif | ||
|
||
/* set clock prescaler to get the maximal possible ADC clock value */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idea: since prescalers just depends in the coreclock, can be set by the pre-processor
/* sampling freq must be between 200kHz and 50kHz */
#if CLOCK_CORECLOCK > 12800000
#define PRESCALER 0x07 /* 128 */
#elif CLOCK_CORECLOCK > 6400000
#define PRESCALER 0x06 /* 64 */
#elif CLOCK_CORECLOCK > 3200000
#define PRESCALER 0x05 /* 32 */
#elif CLOCK_CORECLOCK > 1600000
#define PRESCALER 0x04 /* 16 */
#elif CLOCK_CORECLOCK > 800000
#define PRESCALER 0x03 /* 8 */
#elif CLOCK_CORECLOCK > 100000
#define PRESCALER 0x01 /* 2 */
#else
#error CLOCK must be at least 100kHz to use ADC
#endif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in #7502 its the other way around, in general I'd say the compiler should optimise that out anyway. But to be sure, you could make a size comparison.
However, I would leave as is for now.
ADCSRA |= clk_div; | ||
|
||
/* Ref Voltage is Vcc(5V) */ | ||
ADMUX |= (1 << REFS0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't force it to 5V, it' might be interesting to have VREF as reference voltage. Plus in the 1281/2560 it can be set to differential measurements which might be quite useful.
I suggest introduce a configuration struct, which allows to configure it for each channel. Then set the reference when doing the triggering the sample.
typedef struct {
gpio_t pin;
adc_ref_t ref;
uint8_t ch;
} adc_conf_t;
...
static const adc_conf_t adc_conf[] = {
{ GPIO_PIN(ADC_PORT, 0), ADC_REF_AVCC, 0 },
{ GPIO_PIN(ADC_PORT, 1), ADC_REF_AVCC, 1 },
{ GPIO_PIN(ADC_PORT, 2), ADC_REF_AVCC, 2 },
...
}
This also simplifies the adc_init
and adc_sample
code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general a good idea, specifically to have the reference voltage configurable. What I don't like is the duplication in pin
and ch
because they have a direct dependency and ADC_PORT is fixed for all anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but maybe we should get general ADC support first and fix this later on. A first step could also be to make the ref voltage configurable via define macro (though it applies to all pins then).
/* check if resolution is applicable */ | ||
assert(res == ADC_RES_10BIT); | ||
|
||
prep(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it has to be enabled after setting the other registers otherwise some of the registers of the 328p can't be written
ARDUINO_A3, | ||
ARDUINO_A4, | ||
ARDUINO_A5, | ||
#ifdef CPU_ATMEGA2560 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move down two lines (see my comments below)
while(ADCSRA & (1 << ADSC)) {} | ||
|
||
/* Get conversion result */ | ||
sample = ADC; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Result is 10 bits, you need to read two registers (in the correct order to get the result)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both registers (ADCL, ADCH) are read out via ADC register
@PeterKietzmann how do we proceed here? I could overtake this one, shouldn't be that much work - still need some to review and ack afterwards :) |
closing as discussed, replaced by #7954 |
This PR is the reworked version of PR #6616 (Atmega adc support). It contains the ADC driver for Atmega-Common and Waspmote Pro board. The ADC driver covers now atmega328p, atmega2560 and atmega1281.