|
@@ -34,6 +34,24 @@ struct Timer {
|
34
|
34
|
uint8_t q; // the timer output [0->2] (A->C)
|
35
|
35
|
};
|
36
|
36
|
|
|
37
|
+// Macros for the Timer structure
|
|
38
|
+#define _SET_WGMnQ(TCCRnQ, V) do{ \
|
|
39
|
+ *(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
|
|
40
|
+ *(TCCRnQ)[1] = (*(TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
|
|
41
|
+ }while(0)
|
|
42
|
+
|
|
43
|
+// Set TCCR CS bits
|
|
44
|
+#define _SET_CSn(TCCRnQ, V) (*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0))
|
|
45
|
+
|
|
46
|
+// Set TCCR COM bits
|
|
47
|
+#define _SET_COMnQ(TCCRnQ, Q, V) (*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q))))
|
|
48
|
+
|
|
49
|
+// Set OCRnQ register
|
|
50
|
+#define _SET_OCRnQ(OCRnQ, Q, V) (*(OCRnQ)[Q] = int(V) & 0xFFFF)
|
|
51
|
+
|
|
52
|
+// Set ICRn register (one per timer)
|
|
53
|
+#define _SET_ICRn(ICRn, V) (*(ICRn) = int(V) & 0xFFFF)
|
|
54
|
+
|
37
|
55
|
/**
|
38
|
56
|
* get_pwm_timer
|
39
|
57
|
* Get the timer information and register of the provided pin.
|
|
@@ -42,115 +60,119 @@ struct Timer {
|
42
|
60
|
*/
|
43
|
61
|
Timer get_pwm_timer(const pin_t pin) {
|
44
|
62
|
uint8_t q = 0;
|
|
63
|
+
|
45
|
64
|
switch (digitalPinToTimer(pin)) {
|
46
|
65
|
// Protect reserved timers (TIMER0 & TIMER1)
|
47
|
66
|
#ifdef TCCR0A
|
48
|
|
- #if !AVR_AT90USB1286_FAMILY
|
49
|
|
- case TIMER0A:
|
50
|
|
- #endif
|
|
67
|
+ IF_DISABLED(AVR_AT90USB1286_FAMILY, case TIMER0A:)
|
51
|
68
|
case TIMER0B:
|
52
|
69
|
#endif
|
53
|
70
|
#ifdef TCCR1A
|
54
|
71
|
case TIMER1A: case TIMER1B:
|
55
|
72
|
#endif
|
56
|
|
- break;
|
57
|
|
- #if HAS_TCCR2 || defined(TCCR2A)
|
58
|
|
- #if HAS_TCCR2
|
59
|
|
- case TIMER2: {
|
|
73
|
+
|
|
74
|
+ break;
|
|
75
|
+
|
|
76
|
+ #if HAS_TCCR2
|
|
77
|
+ case TIMER2: {
|
|
78
|
+ Timer timer = {
|
|
79
|
+ { &TCCR2, nullptr, nullptr },
|
|
80
|
+ { (uint16_t*)&OCR2, nullptr, nullptr },
|
|
81
|
+ nullptr,
|
|
82
|
+ 2, 0
|
|
83
|
+ };
|
|
84
|
+ return timer;
|
|
85
|
+ }
|
|
86
|
+ #elif defined(TCCR2A)
|
|
87
|
+ #if ENABLED(USE_OCR2A_AS_TOP)
|
|
88
|
+ case TIMER2A: break; // protect TIMER2A
|
|
89
|
+ case TIMER2B: {
|
60
|
90
|
Timer timer = {
|
61
|
|
- /*TCCRnQ*/ { &TCCR2, nullptr, nullptr },
|
62
|
|
- /*OCRnQ*/ { (uint16_t*)&OCR2, nullptr, nullptr },
|
63
|
|
- /*ICRn*/ nullptr,
|
64
|
|
- /*n, q*/ 2, 0
|
|
91
|
+ { &TCCR2A, &TCCR2B, nullptr },
|
|
92
|
+ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
|
|
93
|
+ nullptr,
|
|
94
|
+ 2, 1
|
65
|
95
|
};
|
|
96
|
+ return timer;
|
|
97
|
+ }
|
|
98
|
+ #else
|
|
99
|
+ case TIMER2B: ++q;
|
|
100
|
+ case TIMER2A: {
|
|
101
|
+ Timer timer = {
|
|
102
|
+ { &TCCR2A, &TCCR2B, nullptr },
|
|
103
|
+ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
|
|
104
|
+ nullptr,
|
|
105
|
+ 2, q
|
|
106
|
+ };
|
|
107
|
+ return timer;
|
66
|
108
|
}
|
67
|
|
- #elif defined(TCCR2A)
|
68
|
|
- #if ENABLED(USE_OCR2A_AS_TOP)
|
69
|
|
- case TIMER2A: break; // protect TIMER2A
|
70
|
|
- case TIMER2B: {
|
71
|
|
- Timer timer = {
|
72
|
|
- /*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr },
|
73
|
|
- /*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
|
74
|
|
- /*ICRn*/ nullptr,
|
75
|
|
- /*n, q*/ 2, 1
|
76
|
|
- };
|
77
|
|
- return timer;
|
78
|
|
- }
|
79
|
|
- #else
|
80
|
|
- case TIMER2B: ++q;
|
81
|
|
- case TIMER2A: {
|
82
|
|
- Timer timer = {
|
83
|
|
- /*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr },
|
84
|
|
- /*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
|
85
|
|
- /*ICRn*/ nullptr,
|
86
|
|
- 2, q
|
87
|
|
- };
|
88
|
|
- return timer;
|
89
|
|
- }
|
90
|
|
- #endif
|
91
|
109
|
#endif
|
92
|
110
|
#endif
|
|
111
|
+
|
93
|
112
|
#ifdef OCR3C
|
94
|
|
- case TIMER3C: ++q;
|
95
|
|
- case TIMER3B: ++q;
|
|
113
|
+ case TIMER3C: ++q;
|
|
114
|
+ case TIMER3B: ++q;
|
96
|
115
|
case TIMER3A: {
|
97
|
116
|
Timer timer = {
|
98
|
|
- /*TCCRnQ*/ { &TCCR3A, &TCCR3B, &TCCR3C },
|
99
|
|
- /*OCRnQ*/ { &OCR3A, &OCR3B, &OCR3C },
|
100
|
|
- /*ICRn*/ &ICR3,
|
101
|
|
- /*n, q*/ 3, q
|
|
117
|
+ { &TCCR3A, &TCCR3B, &TCCR3C },
|
|
118
|
+ { &OCR3A, &OCR3B, &OCR3C },
|
|
119
|
+ &ICR3,
|
|
120
|
+ 3, q
|
102
|
121
|
};
|
103
|
122
|
return timer;
|
104
|
123
|
}
|
105
|
124
|
#elif defined(OCR3B)
|
106
|
|
- case TIMER3B: ++q;
|
|
125
|
+ case TIMER3B: ++q;
|
107
|
126
|
case TIMER3A: {
|
108
|
127
|
Timer timer = {
|
109
|
|
- /*TCCRnQ*/ { &TCCR3A, &TCCR3B, nullptr },
|
110
|
|
- /*OCRnQ*/ { &OCR3A, &OCR3B, nullptr },
|
111
|
|
- /*ICRn*/ &ICR3,
|
112
|
|
- /*n, q*/ 3, q
|
|
128
|
+ { &TCCR3A, &TCCR3B, nullptr },
|
|
129
|
+ { &OCR3A, &OCR3B, nullptr },
|
|
130
|
+ &ICR3,
|
|
131
|
+ 3, q
|
113
|
132
|
};
|
114
|
133
|
return timer;
|
115
|
134
|
}
|
116
|
135
|
#endif
|
|
136
|
+
|
117
|
137
|
#ifdef TCCR4A
|
118
|
|
- case TIMER4C: ++q;
|
119
|
|
- case TIMER4B: ++q;
|
|
138
|
+ case TIMER4C: ++q;
|
|
139
|
+ case TIMER4B: ++q;
|
120
|
140
|
case TIMER4A: {
|
121
|
141
|
Timer timer = {
|
122
|
|
- /*TCCRnQ*/ { &TCCR4A, &TCCR4B, &TCCR4C },
|
123
|
|
- /*OCRnQ*/ { &OCR4A, &OCR4B, &OCR4C },
|
124
|
|
- /*ICRn*/ &ICR4,
|
125
|
|
- /*n, q*/ 4, q
|
|
142
|
+ { &TCCR4A, &TCCR4B, &TCCR4C },
|
|
143
|
+ { &OCR4A, &OCR4B, &OCR4C },
|
|
144
|
+ &ICR4,
|
|
145
|
+ 4, q
|
126
|
146
|
};
|
127
|
147
|
return timer;
|
128
|
148
|
}
|
129
|
149
|
#endif
|
|
150
|
+
|
130
|
151
|
#ifdef TCCR5A
|
131
|
|
- case TIMER5C: ++q;
|
132
|
|
- case TIMER5B: ++q;
|
|
152
|
+ case TIMER5C: ++q;
|
|
153
|
+ case TIMER5B: ++q;
|
133
|
154
|
case TIMER5A: {
|
134
|
155
|
Timer timer = {
|
135
|
|
- /*TCCRnQ*/ { &TCCR5A, &TCCR5B, &TCCR5C },
|
136
|
|
- /*OCRnQ*/ { &OCR5A, &OCR5B, &OCR5C },
|
137
|
|
- /*ICRn*/ &ICR5,
|
138
|
|
- /*n, q*/ 5, q
|
|
156
|
+ { &TCCR5A, &TCCR5B, &TCCR5C },
|
|
157
|
+ { &OCR5A, &OCR5B, &OCR5C },
|
|
158
|
+ &ICR5,
|
|
159
|
+ 5, q
|
139
|
160
|
};
|
140
|
161
|
return timer;
|
141
|
162
|
}
|
142
|
163
|
#endif
|
143
|
164
|
}
|
|
165
|
+
|
144
|
166
|
Timer timer = {
|
145
|
|
- /*TCCRnQ*/ { nullptr, nullptr, nullptr },
|
146
|
|
- /*OCRnQ*/ { nullptr, nullptr, nullptr },
|
147
|
|
- /*ICRn*/ nullptr,
|
148
|
|
- 0, 0
|
|
167
|
+ { nullptr, nullptr, nullptr },
|
|
168
|
+ { nullptr, nullptr, nullptr },
|
|
169
|
+ nullptr,
|
|
170
|
+ 0, 0
|
149
|
171
|
};
|
150
|
172
|
return timer;
|
151
|
173
|
}
|
152
|
174
|
|
153
|
|
-void set_pwm_frequency(const pin_t pin, int f_desired) {
|
|
175
|
+void set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
|
154
|
176
|
Timer timer = get_pwm_timer(pin);
|
155
|
177
|
if (timer.n == 0) return; // Don't proceed if protected timer or not recognized
|
156
|
178
|
uint16_t size;
|