Compare commits

..

5 Commits

Author SHA1 Message Date
edd1c53401 Adapt to changed callback signature 2020-04-13 00:03:32 +02:00
cec0ec6299 Updated adc submodule 2020-04-05 03:40:25 +02:00
74b337804b Implemented example usage 2020-02-21 21:54:12 +01:00
4f79d1d1d8 Added basic interface test 2020-02-01 23:41:55 +01:00
060da11a75 Added adc project solution 2020-02-01 22:47:53 +01:00
9 changed files with 297 additions and 392 deletions

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "adc/adc"]
path = adc/adc
url = git@git.blackmark.me:avr/adc.git
[submodule "adc/io"]
path = adc/io
url = git@git.blackmark.me:avr/io.git

22
adc.atsln Normal file
View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Atmel Studio Solution File, Format Version 11.00
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "adc", "adc\adc.cppproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|AVR = Debug|AVR
Release|AVR = Release|AVR
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.ActiveCfg = Debug|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.Build.0 = Debug|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.ActiveCfg = Release|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.Build.0 = Release|AVR
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

224
adc.hpp
View File

@ -1,224 +0,0 @@
#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)(const uint16_t &);
using reg_ptr_t = volatile uint8_t *;
template <uintptr_t Address>
static inline reg_ptr_t getRegPtr()
{
return reinterpret_cast<reg_ptr_t>(Address);
}
template <typename Cfg>
class AdcImpl {
public:
static uint16_t read()
{
*getRegPtr<Registers::CTRL_STAT_A_ADDR>() |= 1 << ControlFlagsA::START_CONV;
while (*getRegPtr<Registers::CTRL_STAT_A_ADDR>() & (1 << ControlFlagsA::START_CONV))
;
uint16_t adcSample = *getRegPtr<Registers::DATA_L_ADDR>();
adcSample |= *getRegPtr<Registers::DATA_H_ADDR>() << 8;
return adcSample;
}
protected:
static void init(uint8_t muxVal)
{
*getRegPtr<Registers::MUX_SEL_ADDR>() = muxVal | calcRef();
auto ctrlStatA = calcCtrlStatA(detail::fnAdcIntHandler != nullptr);
*getRegPtr<Registers::CTRL_STAT_A_ADDR>() = ctrlStatA;
constexpr auto ctrlStatB = calcCtrlStatB();
*getRegPtr<Registers::CTRL_STAT_B_ADDR>() = ctrlStatB;
if constexpr (Cfg::MODE == Mode::FREE_RUNNING) {
*getRegPtr<Registers::CTRL_STAT_A_ADDR>() |= 1 << ControlFlagsA::START_CONV;
}
}
static constexpr auto calcRef()
{
uint8_t muxVal = 0;
if constexpr (Cfg::VREF == VoltageRef::AVCC) {
muxVal |= 1 << ControlFlagsMUX::REF_SEL_0;
} else if constexpr (Cfg::VREF == VoltageRef::INTERNAL) {
muxVal |= (1 << ControlFlagsMUX::REF_SEL_0) | (1 << ControlFlagsMUX::REF_SEL_1);
}
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 || Cfg::MODE == Mode::FREE_RUNNING) {
ctrlStatA |= 1 << ControlFlagsA::AUTO_TRIGGER;
}
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
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<Cfg> {
using callback_t = void (*)(const uint16_t &);
public:
static_assert(detail::supports_adc_v<pin>, "Pin does not support ADC");
static void init(callback_t callback)
{
detail::fnAdcIntHandler = callback;
init();
}
static void init()
{
constexpr auto muxVal = calcChannel();
detail::AdcImpl<Cfg>::init(muxVal);
}
private:
static constexpr auto calcChannel()
{
return static_cast<uint8_t>(pin) - static_cast<uint8_t>(io::P::C0);
}
};
template <typename Cfg, InputSource src>
class Adc<Cfg, InputSource, src> : public detail::AdcImpl<Cfg> {
using callback_t = void (*)(const uint16_t &);
public:
static void init(callback_t callback)
{
detail::fnAdcIntHandler = callback;
init();
}
static void init()
{
constexpr auto muxVal = calcChannel();
detail::AdcImpl<Cfg>::init(muxVal);
}
private:
static constexpr auto calcChannel()
{
using mx = detail::ControlFlagsMUX;
// clang-format off
switch (src) {
case InputSource::TEMP: return 1 << mx::CHANNEL_SEL_3;
case InputSource::VBG: return (1 << mx::CHANNEL_SEL_3) | (1 << mx::CHANNEL_SEL_2) | (1 << mx::CHANNEL_SEL_1);
case InputSource::GND: return (1 << mx::CHANNEL_SEL_3) | (1 << mx::CHANNEL_SEL_2) | (1 << mx::CHANNEL_SEL_1) | (1 << mx::CHANNEL_SEL_0);
}
// clang-format on
}
};
} // 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)(const uint16_t &) = nullptr;
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

1
adc/adc Submodule

@ -0,0 +1 @@
Subproject commit 5e9dac872aac65a7dbcc300430efe1d95e7b15fc

215
adc/adc.cppproj Normal file
View File

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<ProjectVersion>7.0</ProjectVersion>
<ToolchainName>com.Atmel.AVRGCC8.CPP</ToolchainName>
<ProjectGuid>dce6c7e3-ee26-4d79-826b-08594b9ad897</ProjectGuid>
<avrdevice>ATmega328P</avrdevice>
<avrdeviceseries>none</avrdeviceseries>
<OutputType>Executable</OutputType>
<Language>CPP</Language>
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
<AssemblyName>adc</AssemblyName>
<Name>adc</Name>
<RootNamespace>adc</RootNamespace>
<ToolchainFlavour>avr-g++-9.1.0</ToolchainFlavour>
<KeepTimersRunning>true</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor>
<CacheFlash>true</CacheFlash>
<ProgFlashFromRam>true</ProgFlashFromRam>
<RamSnippetAddress>0x20000000</RamSnippetAddress>
<UncachedRange />
<preserveEEPROM>true</preserveEEPROM>
<OverrideVtorValue>exception_table</OverrideVtorValue>
<BootSegment>2</BootSegment>
<ResetRule>0</ResetRule>
<eraseonlaunchrule>0</eraseonlaunchrule>
<EraseKey />
<avrtool>com.atmel.avrdbg.tool.stk500</avrtool>
<avrtoolserialnumber />
<avrdeviceexpectedsignature>0x1E950F</avrdeviceexpectedsignature>
<com_atmel_avrdbg_tool_stk500>
<ToolOptions>
<InterfaceProperties>
<IspClock>125000</IspClock>
</InterfaceProperties>
<InterfaceName>ISP</InterfaceName>
</ToolOptions>
<ToolType>com.atmel.avrdbg.tool.stk500</ToolType>
<ToolNumber>
</ToolNumber>
<ToolName>STK500</ToolName>
</com_atmel_avrdbg_tool_stk500>
<avrtoolinterface>ISP</avrtoolinterface>
<avrtoolinterfaceclock>125000</avrtoolinterfaceclock>
<AsfFrameworkConfig>
<framework-data xmlns="">
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.47.0" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
<AAFDebugger>
<AAFDebugFiles xmlns="">
<DebugFile>
<path>\Debug\adc.lss</path>
<AAFSetting>
<Label>Lss Files</Label>
<Extention>.lss</Extention>
<Regex>^\s*(?&lt;address&gt;[a-f0-9]*):\s*.*$</Regex>
<DebugEnabled>true</DebugEnabled>
<RegexGroups>address</RegexGroups>
<DebuggerExpression>$pc</DebuggerExpression>
</AAFSetting>
</DebugFile>
</AAFDebugFiles>
</AAFDebugger>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.warnings.ExtraWarnings>True</avrgcc.compiler.warnings.ExtraWarnings>
<avrgcc.compiler.warnings.Pedantic>True</avrgcc.compiler.warnings.Pedantic>
<avrgcc.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -std=c11</avrgcc.compiler.miscellaneous.OtherFlags>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -Wextra -std=c++17</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.warnings.ExtraWarnings>True</avrgcc.compiler.warnings.ExtraWarnings>
<avrgcc.compiler.warnings.Pedantic>True</avrgcc.compiler.warnings.Pedantic>
<avrgcc.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -std=c11</avrgcc.compiler.miscellaneous.OtherFlags>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -Wextra -std=c++17</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.DebugLevel>Maximum (-g3)</avrgcc.compiler.optimization.DebugLevel>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.optimization.level>Optimize (-O1)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.DebugLevel>Maximum (-g3)</avrgcccpp.compiler.optimization.DebugLevel>
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<ItemGroup>
<Compile Include="adc\adc.hpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="adc\config.hpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="adc\hardware.hpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="io\io.hpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="main.cpp">
<SubType>compile</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="adc" />
<Folder Include="io" />
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
</Project>

1
adc/io Submodule

@ -0,0 +1 @@
Subproject commit 80de36ee7ee3e6b0842d5eaee81d54062cb496b2

52
adc/main.cpp Normal file
View File

@ -0,0 +1,52 @@
#define ADC_INT_VECTOR
#include "adc/adc.hpp"
static void adcReadCallback(const uint16_t &adcSample)
{
static_cast<void>(adcSample);
}
void adcTest1()
{
using namespace adc;
using mode = AutoMode<TriggerSource::TIMER0_COMP_A>;
using adc_conf = Config<mode>;
Adc<adc_conf, io::P, io::P::C5> adcPin;
adcPin.init(adcReadCallback);
}
void adcTest2()
{
using namespace adc;
using mode = FreeRunningMode;
using adc_conf = Config<mode>;
Adc<adc_conf, InputSource, InputSource::VBG> adcPin;
adcPin.init(adcReadCallback);
}
void adcTest3()
{
using namespace adc;
using mode = SingleMode;
using adc_conf = Config<mode>;
Adc<adc_conf, InputSource, InputSource::VBG> adcPin;
adcPin.init();
auto adcSample = adcPin.read();
static_cast<void>(adcSample);
}
int main()
{
adcTest1();
adcTest2();
adcTest3();
return 0;
}

View File

@ -1,73 +0,0 @@
#pragma once
#include <stdint.h>
namespace adc {
namespace detail {
enum class Mode {
SINGLE,
AUTO,
FREE_RUNNING,
};
} // namespace detail
enum class TriggerSource {
FREE_RUNNING,
ANALOG_COMP,
EXTERNAL_INT_0,
TIMER0_COMP_A,
TIMER0_OVERFLOW,
TIMER1_COMP_B,
TIMER1_OVERFLOW,
TIMER1_CAPTURE,
};
template <TriggerSource src = TriggerSource::FREE_RUNNING>
struct AutoMode {
static constexpr auto SRC = src;
};
struct FreeRunningMode {
};
struct SingleMode {
};
enum class VoltageRef {
EXTERNAL,
AVCC,
INTERNAL,
};
enum class InputSource {
TEMP,
VBG,
GND,
};
template <class Mode, VoltageRef vref = VoltageRef::AVCC, uint8_t prescaler = 128>
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

View File

@ -1,95 +0,0 @@
#pragma once
#include <stdint.h>
#include "../io/io.hpp"
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,
};
// 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
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;
#pragma pop_macro("_MMIO_BYTE")
#else
#error "This chip is not supported"
#endif
} // namespace detail
} // namespace adc