diff --git a/adc.hpp b/adc.hpp index 6f70f09..23598c6 100644 --- a/adc.hpp +++ b/adc.hpp @@ -1 +1,21 @@ #pragma once + +#include "hardware.hpp" + +#include "../io/io.hpp" + +namespace adc { + +template +struct Config { +}; + +template +class Adc { + public: + void read() {} + + private: +}; + +} // namespace adc diff --git a/hardware.hpp b/hardware.hpp new file mode 100644 index 0000000..5cba31d --- /dev/null +++ b/hardware.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include + +#include + +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, +}; + +#pragma pop_macro("_MMIO_BYTE") + +#else +#error "This chip is not supported" +#endif + +} // namespace detail + +} // namespace adc