adc/adc.hpp

98 lines
1.6 KiB
C++

#ifndef ADC_HPP
#define ADC_HPP
#include "config.hpp"
#include "hardware.hpp"
#include <stdint.h>
#include "../io/io.hpp"
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>
class Adc {
public:
static_assert(sizeof(Input) == -1, "Invalid input source selected");
};
template <typename Cfg, io::P pin>
class Adc<Cfg, io::P, pin> : public detail::AdcImpl {
public:
static_assert(detail::supports_adc_v<pin>, "Pin does not support ADC");
};
template <typename Cfg, InputSource src>
class Adc<Cfg, InputSource, src> : public detail::AdcImpl {
};
} // 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