diff --git a/adc.hpp b/adc.hpp index 4b9ce97..8595264 100644 --- a/adc.hpp +++ b/adc.hpp @@ -27,13 +27,25 @@ class AdcImpl { public: static uint16_t read() { - return 0; + *getRegPtr() |= 1 << ControlFlagsA::START_CONV; + while (*getRegPtr() & (1 << ControlFlagsA::START_CONV)) + ; + + uint16_t adcSample = *getRegPtr(); + adcSample |= *getRegPtr() << 8; + return adcSample; } protected: static void init(uint8_t muxVal) { *getRegPtr() = muxVal | calcRef(); + + auto ctrlStatA = calcCtrlStatA(detail::fnAdcIntHandler != nullptr); + *getRegPtr() = ctrlStatA; + + constexpr auto ctrlStatB = calcCtrlStatB(); + *getRegPtr() = ctrlStatB; } static constexpr auto calcRef() @@ -48,6 +60,59 @@ class AdcImpl { return muxVal; } + + static constexpr uint8_t calcPrescaler() + { + constexpr auto validPrescaler = Cfg::PRESCALER == 2 || Cfg::PRESCALER == 4 || Cfg::PRESCALER == 8 || + Cfg::PRESCALER == 16 || Cfg::PRESCALER == 32 || Cfg::PRESCALER == 64 || + Cfg::PRESCALER == 128; + static_assert(validPrescaler, "Invalid prescaler"); + + // clang-format off + switch (Cfg::PRESCALER) { + case 2: return 1; + case 4: return 2; + case 8: return 3; + case 16: return 4; + case 32: return 5; + case 64: return 6; + case 128: return 7; + } + // clang-format on + } + + static auto calcCtrlStatA(bool interruptEnable) + { + uint8_t ctrlStatA = 1 << ControlFlagsA::ENABLE; + + if constexpr (Cfg::MODE == Mode::AUTO) { + ctrlStatA |= 1 << ControlFlagsA::AUTO_TRIGGER; + } else if (interruptEnable) { + ctrlStatA |= 1 << ControlFlagsA::CONV_COMPLETE_INT_ENABLE; + } + + return ctrlStatA | calcPrescaler(); + } + + static constexpr uint8_t calcCtrlStatB() + { + if constexpr (Cfg::MODE == Mode::AUTO) { + // clang-format off + switch (Cfg::TRIGGER_SRC) { + case TriggerSource::FREE_RUNNING: return 0; + case TriggerSource::ANALOG_COMP: return 1; + case TriggerSource::EXTERNAL_INT_0: return 2; + case TriggerSource::TIMER0_COMP_A: return 3; + case TriggerSource::TIMER0_OVERFLOW: return 4; + case TriggerSource::TIMER1_COMP_B: return 5; + case TriggerSource::TIMER1_OVERFLOW: return 6; + case TriggerSource::TIMER1_CAPTURE: return 7; + } + // clang-format on + } + + return 0; + } }; } // namespace detail