Implemented different configs and refactored implementation into Impl class

This commit is contained in:
BlackMark 2020-02-21 20:38:32 +01:00
parent 045efedd45
commit c1eadf4cb1
2 changed files with 94 additions and 33 deletions

105
adc.hpp
View File

@ -1,4 +1,5 @@
#pragma once #ifndef ADC_HPP
#define ADC_HPP
#include "config.hpp" #include "config.hpp"
#include "hardware.hpp" #include "hardware.hpp"
@ -9,6 +10,30 @@
namespace adc { namespace adc {
namespace detail {
extern void (*fnAdcIntHandler)(uint16_t);
class AdcImpl {
private:
using callback_t = void (*)(uint16_t);
public:
static void init(callback_t callback)
{
detail::fnAdcIntHandler = callback;
}
static void init() {}
static uint16_t read()
{
return 0;
}
};
} // namespace detail
template <typename Cfg, typename Input, Input src> template <typename Cfg, typename Input, Input src>
class Adc { class Adc {
public: public:
@ -16,43 +41,57 @@ class Adc {
}; };
template <typename Cfg, io::P pin> template <typename Cfg, io::P pin>
class Adc<Cfg, io::P, pin> { class Adc<Cfg, io::P, pin> : public detail::AdcImpl {
private:
using callback_t = void (*)(uint16_t);
public: public:
static_assert(detail::supports_adc_v<pin>, "Pin does not support ADC"); static_assert(detail::supports_adc_v<pin>, "Pin does not support ADC");
Adc() {}
Adc(callback_t callback) : m_callback(callback) {}
uint16_t read()
{
return 0;
}
private:
const callback_t m_callback = nullptr;
}; };
template <typename Cfg, InputSource src> template <typename Cfg, InputSource src>
class Adc<Cfg, InputSource, src> { class Adc<Cfg, InputSource, src> : public detail::AdcImpl {
private:
using callback_t = void (*)(uint16_t);
public:
Adc() {}
Adc(callback_t callback) : m_callback(callback) {}
uint16_t read()
{
return 0;
}
private:
const callback_t m_callback = nullptr;
}; };
} // namespace adc } // namespace adc
#endif
//////////////////////////////////////////////////////////////////////////
#ifdef ADC_INT_VECTOR
#include <stdint.h>
#include <avr/interrupt.h>
namespace adc {
namespace detail {
#if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega328P__)
void (*fnAdcIntHandler)(uint16_t) = nullptr;
using reg_ptr_t = volatile uint8_t *;
template <uintptr_t Address>
static inline reg_ptr_t getRegPtr()
{
return reinterpret_cast<reg_ptr_t>(Address);
}
ISR(ADC_vect)
{
if (fnAdcIntHandler) {
const auto adcSample = *getRegPtr<Registers::DATA_L_ADDR>() | (*getRegPtr<Registers::DATA_H_ADDR>() << 8);
fnAdcIntHandler(adcSample);
}
}
#else
#error "This chip is not supported"
#endif
} // namespace detail
} // namespace adc
#undef ADC_INT_VECTORS
#endif

View File

@ -4,12 +4,16 @@
namespace adc { namespace adc {
namespace detail {
enum class Mode { enum class Mode {
SINGLE, SINGLE,
AUTO, AUTO,
FREE_RUNNING, FREE_RUNNING,
}; };
} // namespace detail
enum class TriggerSource { enum class TriggerSource {
FREE_RUNNING, FREE_RUNNING,
ANALOG_COMP, ANALOG_COMP,
@ -46,6 +50,24 @@ enum class InputSource {
template <class Mode, VoltageRef vref = VoltageRef::AVCC, uint8_t prescaler = 128> template <class Mode, VoltageRef vref = VoltageRef::AVCC, uint8_t prescaler = 128>
struct Config { struct Config {
static constexpr auto MODE = detail::Mode::AUTO;
static constexpr auto TRIGGER_SRC = Mode::SRC;
static constexpr auto VREF = vref;
static constexpr auto PRESCALER = prescaler;
};
template <VoltageRef vref, uint8_t prescaler>
struct Config<FreeRunningMode, vref, prescaler> {
static constexpr auto MODE = detail::Mode::FREE_RUNNING;
static constexpr auto VREF = vref;
static constexpr auto PRESCALER = prescaler;
};
template <VoltageRef vref, uint8_t prescaler>
struct Config<SingleMode, vref, prescaler> {
static constexpr auto MODE = detail::Mode::SINGLE;
static constexpr auto VREF = vref;
static constexpr auto PRESCALER = prescaler;
}; };
} // namespace adc } // namespace adc