ARM: split out analog-avr.c from analog.c.
This commit is contained in:
parent
05c7cf067f
commit
56f6b381fd
|
|
@ -0,0 +1,125 @@
|
|||
|
||||
/** \file
|
||||
\brief Analog subsystem, AVR specific part.
|
||||
*/
|
||||
|
||||
#if defined TEACUP_C_INCLUDE && defined __AVR__
|
||||
|
||||
#include "temp.h"
|
||||
#include "pinio.h"
|
||||
#include "memory_barrier.h"
|
||||
|
||||
/* OR-combined mask of all channels */
|
||||
#undef DEFINE_TEMP_SENSOR
|
||||
//! automagically generate analog_mask from DEFINE_TEMP_SENSOR entries in config.h
|
||||
#define DEFINE_TEMP_SENSOR(name, type, pin, additional) \
|
||||
| (((type == TT_THERMISTOR) || (type == TT_AD595)) ? (1 << (pin ## _ADC)) : 0)
|
||||
#ifdef AIO8_PIN
|
||||
static const uint16_t analog_mask = 0
|
||||
#else
|
||||
static const uint8_t analog_mask = 0
|
||||
#endif
|
||||
#include "config_wrapper.h"
|
||||
;
|
||||
#undef DEFINE_TEMP_SENSOR
|
||||
|
||||
static uint8_t adc_counter;
|
||||
static volatile uint16_t BSS adc_result[NUM_TEMP_SENSORS];
|
||||
|
||||
#define DEFINE_TEMP_SENSOR(name, type, pin, additional) \
|
||||
((type == TT_THERMISTOR) || (type == TT_AD595)) ? (pin ## _ADC) : 255,
|
||||
static uint8_t adc_channel[NUM_TEMP_SENSORS] =
|
||||
{
|
||||
#include "config_wrapper.h"
|
||||
};
|
||||
#undef DEFINE_TEMP_SENSOR
|
||||
|
||||
//! Configure all registers, start interrupt loop
|
||||
void analog_init() {
|
||||
if (analog_mask > 0) {
|
||||
// clear ADC bit in power reduction register because of ADC use.
|
||||
#ifdef PRR
|
||||
PRR &= ~MASK(PRADC);
|
||||
#elif defined PRR0
|
||||
PRR0 &= ~MASK(PRADC);
|
||||
#endif
|
||||
|
||||
// select reference signal to use, set right adjusted results and select ADC input 0
|
||||
ADMUX = REFERENCE;
|
||||
|
||||
// ADC frequency must be less than 200khz or we lose precision. At 16MHz system clock, we must use the full prescale value of 128 to get an ADC clock of 125khz.
|
||||
ADCSRA = MASK(ADEN) | MASK(ADPS2) | MASK(ADPS1) | MASK(ADPS0);
|
||||
#ifdef ADCSRB
|
||||
ADCSRB = 0;
|
||||
#endif
|
||||
|
||||
adc_counter = 0;
|
||||
|
||||
// clear analog inputs in the data direction register(s)
|
||||
AIO0_DDR &= ~analog_mask;
|
||||
#ifdef AIO8_DDR
|
||||
AIO8_DDR &= ~(analog_mask >> 8);
|
||||
#endif
|
||||
|
||||
// disable the analog inputs for digital use.
|
||||
DIDR0 = analog_mask & 0xFF;
|
||||
#ifdef DIDR2
|
||||
DIDR2 = (analog_mask >> 8) & 0xFF;
|
||||
#endif
|
||||
|
||||
// now we start the first conversion and leave the rest to the interrupt
|
||||
ADCSRA |= MASK(ADIE) | MASK(ADSC);
|
||||
} /* analog_mask > 0 */
|
||||
}
|
||||
|
||||
/*! Analog Interrupt
|
||||
|
||||
This is where we read our analog value and store it in an array for later retrieval
|
||||
*/
|
||||
ISR(ADC_vect, ISR_NOBLOCK) {
|
||||
// emulate free-running mode but be more deterministic about exactly which result we have, since this project has long-running interrupts
|
||||
if (analog_mask > 0) { // at least one temp sensor uses an analog channel
|
||||
// store next result
|
||||
adc_result[adc_counter] = ADC;
|
||||
|
||||
// next channel
|
||||
do {
|
||||
adc_counter++;
|
||||
if (adc_counter >= sizeof(adc_channel))
|
||||
adc_counter = 0;
|
||||
} while (adc_channel[adc_counter] == 255);
|
||||
|
||||
// start next conversion
|
||||
ADMUX = (adc_channel[adc_counter] & 0x07) | REFERENCE;
|
||||
#ifdef MUX5
|
||||
if (adc_channel[adc_counter] & 0x08)
|
||||
ADCSRB |= MASK(MUX5);
|
||||
else
|
||||
ADCSRB &= ~MASK(MUX5);
|
||||
#endif
|
||||
|
||||
// After the mux has been set, start a new conversion
|
||||
ADCSRA |= MASK(ADSC);
|
||||
}
|
||||
}
|
||||
|
||||
/*! Read analog value from saved result array
|
||||
\param channel Channel to be read
|
||||
\return analog reading, 10-bit right aligned
|
||||
*/
|
||||
uint16_t analog_read(uint8_t index) {
|
||||
if (analog_mask > 0) {
|
||||
uint16_t r;
|
||||
|
||||
ATOMIC_START
|
||||
// atomic 16-bit copy
|
||||
r = adc_result[index];
|
||||
ATOMIC_END
|
||||
|
||||
return r;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined TEACUP_C_INCLUDE && defined __AVR__ */
|
||||
123
analog.c
123
analog.c
|
|
@ -1,124 +1,13 @@
|
|||
#include "analog.h"
|
||||
|
||||
/** \file
|
||||
\brief Analog subsystem
|
||||
*/
|
||||
|
||||
#include "temp.h"
|
||||
#include "analog.h"
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include "pinio.h"
|
||||
#include "memory_barrier.h"
|
||||
#define TEACUP_C_INCLUDE
|
||||
#include "analog-avr.c"
|
||||
//#include "analog-arm.c"
|
||||
#undef TEACUP_C_INCLUDE
|
||||
|
||||
/* OR-combined mask of all channels */
|
||||
#undef DEFINE_TEMP_SENSOR
|
||||
//! automagically generate analog_mask from DEFINE_TEMP_SENSOR entries in config.h
|
||||
#define DEFINE_TEMP_SENSOR(name, type, pin, additional) \
|
||||
| (((type == TT_THERMISTOR) || (type == TT_AD595)) ? (1 << (pin ## _ADC)) : 0)
|
||||
#ifdef AIO8_PIN
|
||||
static const uint16_t analog_mask = 0
|
||||
#else
|
||||
static const uint8_t analog_mask = 0
|
||||
#endif
|
||||
#include "config_wrapper.h"
|
||||
;
|
||||
#undef DEFINE_TEMP_SENSOR
|
||||
|
||||
static uint8_t adc_counter;
|
||||
static volatile uint16_t BSS adc_result[NUM_TEMP_SENSORS];
|
||||
|
||||
#define DEFINE_TEMP_SENSOR(name, type, pin, additional) \
|
||||
((type == TT_THERMISTOR) || (type == TT_AD595)) ? (pin ## _ADC) : 255,
|
||||
static uint8_t adc_channel[NUM_TEMP_SENSORS] =
|
||||
{
|
||||
#include "config_wrapper.h"
|
||||
};
|
||||
#undef DEFINE_TEMP_SENSOR
|
||||
|
||||
//! Configure all registers, start interrupt loop
|
||||
void analog_init() {
|
||||
if (analog_mask > 0) {
|
||||
// clear ADC bit in power reduction register because of ADC use.
|
||||
#ifdef PRR
|
||||
PRR &= ~MASK(PRADC);
|
||||
#elif defined PRR0
|
||||
PRR0 &= ~MASK(PRADC);
|
||||
#endif
|
||||
|
||||
// select reference signal to use, set right adjusted results and select ADC input 0
|
||||
ADMUX = REFERENCE;
|
||||
|
||||
// ADC frequency must be less than 200khz or we lose precision. At 16MHz system clock, we must use the full prescale value of 128 to get an ADC clock of 125khz.
|
||||
ADCSRA = MASK(ADEN) | MASK(ADPS2) | MASK(ADPS1) | MASK(ADPS0);
|
||||
#ifdef ADCSRB
|
||||
ADCSRB = 0;
|
||||
#endif
|
||||
|
||||
adc_counter = 0;
|
||||
|
||||
// clear analog inputs in the data direction register(s)
|
||||
AIO0_DDR &= ~analog_mask;
|
||||
#ifdef AIO8_DDR
|
||||
AIO8_DDR &= ~(analog_mask >> 8);
|
||||
#endif
|
||||
|
||||
// disable the analog inputs for digital use.
|
||||
DIDR0 = analog_mask & 0xFF;
|
||||
#ifdef DIDR2
|
||||
DIDR2 = (analog_mask >> 8) & 0xFF;
|
||||
#endif
|
||||
|
||||
// now we start the first conversion and leave the rest to the interrupt
|
||||
ADCSRA |= MASK(ADIE) | MASK(ADSC);
|
||||
} /* analog_mask > 0 */
|
||||
}
|
||||
|
||||
/*! Analog Interrupt
|
||||
|
||||
This is where we read our analog value and store it in an array for later retrieval
|
||||
*/
|
||||
ISR(ADC_vect, ISR_NOBLOCK) {
|
||||
// emulate free-running mode but be more deterministic about exactly which result we have, since this project has long-running interrupts
|
||||
if (analog_mask > 0) { // at least one temp sensor uses an analog channel
|
||||
// store next result
|
||||
adc_result[adc_counter] = ADC;
|
||||
|
||||
// next channel
|
||||
do {
|
||||
adc_counter++;
|
||||
if (adc_counter >= sizeof(adc_channel))
|
||||
adc_counter = 0;
|
||||
} while (adc_channel[adc_counter] == 255);
|
||||
|
||||
// start next conversion
|
||||
ADMUX = (adc_channel[adc_counter] & 0x07) | REFERENCE;
|
||||
#ifdef MUX5
|
||||
if (adc_channel[adc_counter] & 0x08)
|
||||
ADCSRB |= MASK(MUX5);
|
||||
else
|
||||
ADCSRB &= ~MASK(MUX5);
|
||||
#endif
|
||||
|
||||
// After the mux has been set, start a new conversion
|
||||
ADCSRA |= MASK(ADSC);
|
||||
}
|
||||
}
|
||||
|
||||
/*! Read analog value from saved result array
|
||||
\param channel Channel to be read
|
||||
\return analog reading, 10-bit right aligned
|
||||
*/
|
||||
uint16_t analog_read(uint8_t index) {
|
||||
if (analog_mask > 0) {
|
||||
uint16_t r;
|
||||
|
||||
ATOMIC_START
|
||||
// atomic 16-bit copy
|
||||
r = adc_result[index];
|
||||
ATOMIC_END
|
||||
|
||||
return r;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// No common code so far.
|
||||
|
|
|
|||
6
analog.h
6
analog.h
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __AVR__
|
||||
// TODO: these reference selectors should go away. A nice feature, but
|
||||
// none of the RepRap controllers has use for it.
|
||||
|
||||
/** \def REFERENCE_AREF
|
||||
This compares the voltage to be measured against the voltage on the Aref pin.
|
||||
This also requires a voltage to be actually provided on the Aref pin, which
|
||||
|
|
@ -45,6 +49,8 @@
|
|||
#error REFERENCE undefined. See analog.h on how to choose it.
|
||||
#endif
|
||||
|
||||
#endif /* __AVR__ */
|
||||
|
||||
void analog_init(void);
|
||||
|
||||
uint16_t analog_read(uint8_t index);
|
||||
|
|
|
|||
Loading…
Reference in New Issue