-
Notifications
You must be signed in to change notification settings - Fork 1
/
ADC.hpp
150 lines (120 loc) · 4.48 KB
/
ADC.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#pragma once
/*
* File: ADC.h
* Author: Cameron
*
* Created on March 12, 2015, 1:44 PM
*/
#include "bitTypes.hpp"
#include "undefAVR.hpp"
#include <avr/io.h>
// Clear out conflicting Atmel defines
#undef ADC
namespace AVR {
namespace ADC {
using namespace Basic;
enum class Reference : b2 { AREF, AVcc, Reserved, Internal };
typedef union {
struct {
b5 MultiplexerLowBits : 5;
bool LeftAdjust : 1;
Reference ref : 2;
};
u1 byte;
} MUXt;
enum class Prescaler : b3 { D_, D2, D4, D8, D16, D32, D64, D128 };
u1 constexpr divider(Prescaler const p) {
return p == Prescaler::D_ ? 2
: p == Prescaler::D2 ? 2
: p == Prescaler::D4 ? 4
: p == Prescaler::D8 ? 8
: p == Prescaler::D16 ? 16
: p == Prescaler::D32 ? 32
: p == Prescaler::D64 ? 64
: p == Prescaler::D128 ? 128
: 0;
}
constexpr unsigned long operator/(unsigned long f, Prescaler const p) { return f / divider(p); }
// constexpr int value(Prescaler const p) { return (u1)p; }
#ifdef F_CPU
constexpr unsigned long adcFreq(Prescaler const p) { return F_CPU / p; }
constexpr bool isValid(Prescaler const p) { return adcFreq(p) > 50000 && adcFreq(p) < 200000; }
constexpr Prescaler suggestedPrescaler = isValid(Prescaler::D2) ? Prescaler::D2
: isValid(Prescaler::D4) ? Prescaler::D4
: isValid(Prescaler::D8) ? Prescaler::D8
: isValid(Prescaler::D16) ? Prescaler::D16
: isValid(Prescaler::D32) ? Prescaler::D32
: isValid(Prescaler::D64) ? Prescaler::D64
: Prescaler::D128;
#define SUGGESTED = suggestedPrescaler
#else
#define SUGGESTED
#endif
inline void startConversion() { ADCSRA |= 1 << ADSC; }
typedef union SRA {
struct {
Prescaler Prescale : 3;
bool InterruptEnable : 1;
bool InterruptFlag : 1;
bool AutoTriggerEnable : 1;
bool StartConversion : 1;
bool Enable : 1;
};
u1 byte;
SRA(bool interruptEnable, bool autoTrigger = false, Prescaler p SUGGESTED, bool clearFlag = true, bool start = false)
: Prescale(p), InterruptEnable(interruptEnable), InterruptFlag(clearFlag), AutoTriggerEnable(autoTrigger),
StartConversion(start), Enable(true) {}
SRA(bool interruptEnable, Prescaler p SUGGESTED, bool clearFlag = true, bool start = false)
: Prescale(p), InterruptEnable(interruptEnable), InterruptFlag(clearFlag), AutoTriggerEnable(false),
StartConversion(start), Enable(true) {}
SRA(Prescaler p SUGGESTED, bool interruptEnable = false, bool clearFlag = true, bool start = false)
: Prescale(p), InterruptEnable(interruptEnable), InterruptFlag(clearFlag), AutoTriggerEnable(false),
StartConversion(start), Enable(true) {}
} SRAt;
static_assert(sizeof(SRAt) == 1, "Invalid struct");
enum class AutoTriggerSource : b4 {
FreeRunning,
AnalogComparator,
ExternalInterrupt0,
Timer0CompareMatch,
Timer0Overflow,
Timer1CompareMatchB,
Timer1Overflow,
Timer1Capture,
Timer4Overflow,
Timer4CompareMatchA,
Timer4CompareMatchB,
Timer4CompareMatchD
};
typedef union {
struct {
AutoTriggerSource TriggerSource : 4;
bool : 1;
bool MultiplexerBit5 : 1;
bool AnalogComparatorMultiplexerEnable : 1;
bool HighSpeedMode : 1;
};
u1 byte;
} SRBt;
constexpr volatile MUXt *const MUX = (volatile MUXt *const)&ADMUX;
constexpr volatile SRAt *const ControlStatusRegisterA = (volatile SRAt *const)&ADCSRA;
constexpr volatile u1 *const DataRegisterLow = &ADCL;
constexpr volatile u1 *const DataRegisterHigh = &ADCH;
constexpr volatile u2 *const DataRegister = &ADCW;
constexpr volatile SRBt *const ControlStatusRegisterB = (volatile SRBt *const)&ADCSRB;
constexpr volatile u1 *const DigitalInputDisableRegister0 = &DIDR0;
constexpr volatile u1 *const DigitalInputDisableRegister1 = &DIDR1;
constexpr volatile u2 *const DigitalInputDisableRegister = (volatile u2 *const)&DIDR0;
class RegularInput {
const u1 mux;
const bool mux5;
public:
constexpr inline RegularInput(u1 muxValue, Reference ref = Reference::AVcc, bool leftAdjust = false)
: mux((u1)ref << 6 | (u1)leftAdjust << 5 | (muxValue & ((1 << 5) - 1))), mux5(muxValue & (1 << 5)) {}
inline void select() {
MUX->byte = mux;
ControlStatusRegisterB->MultiplexerBit5 = mux5;
}
};
}; // namespace ADC
}; // namespace AVR