2020-02-01 23:41:18 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
2020-02-09 20:36:25 +01:00
|
|
|
#include "../io/io.hpp"
|
2020-02-01 23:41:18 +01:00
|
|
|
|
|
|
|
namespace adc {
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
|
|
|
|
#if defined(__AVR_ATmega328P__)
|
|
|
|
|
|
|
|
/*
|
|
|
|
The following works in avr-gcc 5.4.0, but is not legal C++, because ptr's are not legal constexpr's:
|
|
|
|
constexpr auto *foo = ptr;
|
|
|
|
|
|
|
|
Workaround is to store the address of the ptr in a uintptr_t and reinterpret_cast it at call site.
|
|
|
|
The _SFR_ADDR macro in sfr_defs.h would give the address, but it does that by taking the address of the dereferenced
|
|
|
|
pointer and casts it to uint16_t, which is still not a legal constexpr.
|
|
|
|
The workaround therefore is to disable the pointer-cast-and-dereference macro _MMIO_BYTE temporarily.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma push_macro("_MMIO_BYTE")
|
|
|
|
#undef _MMIO_BYTE
|
|
|
|
#define _MMIO_BYTE
|
|
|
|
|
|
|
|
struct Registers {
|
|
|
|
static constexpr uintptr_t MUX_SEL_ADDR = ADMUX;
|
|
|
|
static constexpr uintptr_t CTRL_STAT_A_ADDR = ADCSRA;
|
|
|
|
static constexpr uintptr_t DATA_L_ADDR = ADCL;
|
|
|
|
static constexpr uintptr_t DATA_H_ADDR = ADCH;
|
|
|
|
static constexpr uintptr_t CTRL_STAT_B_ADDR = ADCSRB;
|
|
|
|
static constexpr uintptr_t DIG_IN_DIS_ADDR = DIDR0;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class ControlFlagsMUX {
|
|
|
|
CHANNEL_SEL_0 = MUX0,
|
|
|
|
CHANNEL_SEL_1 = MUX1,
|
|
|
|
CHANNEL_SEL_2 = MUX2,
|
|
|
|
CHANNEL_SEL_3 = MUX3,
|
|
|
|
LEFT_ADJ_RES = ADLAR,
|
|
|
|
REF_SEL_0 = REFS0,
|
|
|
|
REF_SEL_1 = REFS1,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class ControlFlagsA {
|
|
|
|
PRESCALER_SEL_0 = ADPS0,
|
|
|
|
PRESCALER_SEL_1 = ADPS1,
|
|
|
|
PRESCALER_SEL_2 = ADPS2,
|
|
|
|
CONV_COMPLETE_INT_ENABLE = ADIE,
|
|
|
|
CONV_COMPLETE = ADIF,
|
|
|
|
AUTO_TRIGGER = ADATE,
|
|
|
|
START_CONV = ADSC,
|
|
|
|
ENABLE = ADEN,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class ControlFlagsB {
|
|
|
|
TRIGGER_SRC_0 = ADTS0,
|
|
|
|
TRIGGER_SRC_1 = ADTS1,
|
|
|
|
TRIGGER_SRC_2 = ADTS2,
|
|
|
|
ANALOG_COMP_MUX_ENABLE = ACME,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class ControlFlagsDigInDis {
|
|
|
|
DIGITAL_INPUT_DISABLE_0 = ADC0D,
|
|
|
|
DIGITAL_INPUT_DISABLE_1 = ADC1D,
|
|
|
|
DIGITAL_INPUT_DISABLE_2 = ADC2D,
|
|
|
|
DIGITAL_INPUT_DISABLE_3 = ADC3D,
|
|
|
|
DIGITAL_INPUT_DISABLE_4 = ADC4D,
|
|
|
|
DIGITAL_INPUT_DISABLE_5 = ADC5D,
|
|
|
|
};
|
|
|
|
|
2020-02-21 21:24:10 +01:00
|
|
|
// clang-format off
|
|
|
|
constexpr int operator<<(const int &lhs, const ControlFlagsMUX &rhs) { return lhs << static_cast<int>(rhs); }
|
|
|
|
constexpr int operator<<(const int &lhs, const ControlFlagsA &rhs) { return lhs << static_cast<int>(rhs); }
|
|
|
|
constexpr int operator<<(const int &lhs, const ControlFlagsB &rhs) { return lhs << static_cast<int>(rhs); }
|
|
|
|
// clang-format on
|
|
|
|
|
2020-02-09 20:36:25 +01:00
|
|
|
template <io::P pin>
|
|
|
|
struct supports_adc {
|
|
|
|
static constexpr auto value = (io::detail::getBus(pin) == io::Bus::C) ? true : false;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <io::P pin>
|
|
|
|
constexpr auto supports_adc_v = supports_adc<pin>::value;
|
|
|
|
|
2020-02-01 23:41:18 +01:00
|
|
|
#pragma pop_macro("_MMIO_BYTE")
|
|
|
|
|
|
|
|
#else
|
|
|
|
#error "This chip is not supported"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
} // namespace adc
|