|
@@ -67,26 +67,25 @@ static volatile int8_t Channel[_Nbr_16timers]; // counter for the s
|
67
|
67
|
/************ static functions common to all instances ***********************/
|
68
|
68
|
|
69
|
69
|
static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
|
70
|
|
- if (Channel[timer] < 0)
|
71
|
|
- *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
|
72
|
|
- else {
|
73
|
|
- if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
|
74
|
|
- extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
|
75
|
|
- }
|
76
|
|
-
|
77
|
|
- Channel[timer]++; // increment to the next channel
|
78
|
|
- if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
|
79
|
|
- *OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
|
80
|
|
- if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated
|
81
|
|
- extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
|
|
70
|
+ int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
|
|
71
|
+ if (cho < 0) // Channel -1 indicates the refresh interval completed...
|
|
72
|
+ *TCNTn = 0; // ...so reset the timer
|
|
73
|
+ else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
|
|
74
|
+ extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
|
|
75
|
+
|
|
76
|
+ Channel[timer] = ++cho; // Handle the next channel (or 0)
|
|
77
|
+ if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
|
|
78
|
+ *OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration
|
|
79
|
+ if (SERVO(timer, cho).Pin.isActive) // activated?
|
|
80
|
+ extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
|
82
|
81
|
}
|
83
|
82
|
else {
|
84
|
83
|
// finished all channels so wait for the refresh period to expire before starting over
|
85
|
|
- if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
|
86
|
|
- *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
|
87
|
|
- else
|
88
|
|
- *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
|
89
|
|
- Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
|
|
84
|
+ const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed
|
|
85
|
+ ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
|
|
86
|
+ *OCRnA = max(cval, ival);
|
|
87
|
+
|
|
88
|
+ Channel[timer] = -1; // reset the timer counter to 0 on the next call
|
90
|
89
|
}
|
91
|
90
|
}
|
92
|
91
|
|
|
@@ -123,91 +122,102 @@ static inline void handle_interrupts(const timer16_Sequence_t timer, volatile ui
|
123
|
122
|
|
124
|
123
|
/****************** end of static functions ******************************/
|
125
|
124
|
|
126
|
|
-void initISR(timer16_Sequence_t timer) {
|
127
|
|
- #ifdef _useTimer1
|
128
|
|
- if (timer == _timer1) {
|
129
|
|
- TCCR1A = 0; // normal counting mode
|
130
|
|
- TCCR1B = _BV(CS11); // set prescaler of 8
|
131
|
|
- TCNT1 = 0; // clear the timer count
|
132
|
|
- #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
|
133
|
|
- SBI(TIFR, OCF1A); // clear any pending interrupts;
|
134
|
|
- SBI(TIMSK, OCIE1A); // enable the output compare interrupt
|
135
|
|
- #else
|
136
|
|
- // here if not ATmega8 or ATmega128
|
137
|
|
- SBI(TIFR1, OCF1A); // clear any pending interrupts;
|
138
|
|
- SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
|
139
|
|
- #endif
|
140
|
|
- #ifdef WIRING
|
141
|
|
- timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
|
142
|
|
- #endif
|
143
|
|
- }
|
144
|
|
- #endif
|
145
|
|
-
|
146
|
|
- #ifdef _useTimer3
|
147
|
|
- if (timer == _timer3) {
|
148
|
|
- TCCR3A = 0; // normal counting mode
|
149
|
|
- TCCR3B = _BV(CS31); // set prescaler of 8
|
150
|
|
- TCNT3 = 0; // clear the timer count
|
151
|
|
- #ifdef __AVR_ATmega128__
|
152
|
|
- SBI(TIFR, OCF3A); // clear any pending interrupts;
|
153
|
|
- SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
|
154
|
|
- #else
|
155
|
|
- SBI(TIFR3, OCF3A); // clear any pending interrupts;
|
156
|
|
- SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
|
157
|
|
- #endif
|
158
|
|
- #ifdef WIRING
|
159
|
|
- timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
|
160
|
|
- #endif
|
161
|
|
- }
|
162
|
|
- #endif
|
163
|
|
-
|
164
|
|
- #ifdef _useTimer4
|
165
|
|
- if (timer == _timer4) {
|
166
|
|
- TCCR4A = 0; // normal counting mode
|
167
|
|
- TCCR4B = _BV(CS41); // set prescaler of 8
|
168
|
|
- TCNT4 = 0; // clear the timer count
|
169
|
|
- TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
170
|
|
- TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
|
171
|
|
- }
|
172
|
|
- #endif
|
173
|
|
-
|
174
|
|
- #ifdef _useTimer5
|
175
|
|
- if (timer == _timer5) {
|
176
|
|
- TCCR5A = 0; // normal counting mode
|
177
|
|
- TCCR5B = _BV(CS51); // set prescaler of 8
|
178
|
|
- TCNT5 = 0; // clear the timer count
|
179
|
|
- TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
180
|
|
- TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
|
181
|
|
- }
|
182
|
|
- #endif
|
183
|
|
-}
|
184
|
|
-
|
185
|
|
-void finISR(timer16_Sequence_t timer) {
|
186
|
|
- // Disable use of the given timer
|
187
|
|
- #ifdef WIRING
|
188
|
|
- if (timer == _timer1) {
|
189
|
|
- CBI(
|
190
|
|
- #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
191
|
|
- TIMSK1
|
|
125
|
+void initISR(const timer16_Sequence_t timer_index) {
|
|
126
|
+ switch (timer_index) {
|
|
127
|
+ default: break;
|
|
128
|
+
|
|
129
|
+ #ifdef _useTimer1
|
|
130
|
+ case _timer1:
|
|
131
|
+ TCCR1A = 0; // normal counting mode
|
|
132
|
+ TCCR1B = _BV(CS11); // set prescaler of 8
|
|
133
|
+ TCNT1 = 0; // clear the timer count
|
|
134
|
+ #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
|
|
135
|
+ SBI(TIFR, OCF1A); // clear any pending interrupts;
|
|
136
|
+ SBI(TIMSK, OCIE1A); // enable the output compare interrupt
|
192
|
137
|
#else
|
193
|
|
- TIMSK
|
|
138
|
+ // here if not ATmega8 or ATmega128
|
|
139
|
+ SBI(TIFR1, OCF1A); // clear any pending interrupts;
|
|
140
|
+ SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
|
194
|
141
|
#endif
|
195
|
|
- , OCIE1A); // disable timer 1 output compare interrupt
|
196
|
|
- timerDetach(TIMER1OUTCOMPAREA_INT);
|
197
|
|
- }
|
198
|
|
- else if (timer == _timer3) {
|
199
|
|
- CBI(
|
200
|
|
- #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
201
|
|
- TIMSK3
|
|
142
|
+ #ifdef WIRING
|
|
143
|
+ timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
|
|
144
|
+ #endif
|
|
145
|
+ break;
|
|
146
|
+ #endif
|
|
147
|
+
|
|
148
|
+ #ifdef _useTimer3
|
|
149
|
+ case _timer3:
|
|
150
|
+ TCCR3A = 0; // normal counting mode
|
|
151
|
+ TCCR3B = _BV(CS31); // set prescaler of 8
|
|
152
|
+ TCNT3 = 0; // clear the timer count
|
|
153
|
+ #ifdef __AVR_ATmega128__
|
|
154
|
+ SBI(TIFR, OCF3A); // clear any pending interrupts;
|
|
155
|
+ SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
|
202
|
156
|
#else
|
203
|
|
- ETIMSK
|
|
157
|
+ SBI(TIFR3, OCF3A); // clear any pending interrupts;
|
|
158
|
+ SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
|
|
159
|
+ #endif
|
|
160
|
+ #ifdef WIRING
|
|
161
|
+ timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
|
204
|
162
|
#endif
|
205
|
|
- , OCIE3A); // disable the timer3 output compare A interrupt
|
206
|
|
- timerDetach(TIMER3OUTCOMPAREA_INT);
|
|
163
|
+ break;
|
|
164
|
+ #endif
|
|
165
|
+
|
|
166
|
+ #ifdef _useTimer4
|
|
167
|
+ case _timer4:
|
|
168
|
+ TCCR4A = 0; // normal counting mode
|
|
169
|
+ TCCR4B = _BV(CS41); // set prescaler of 8
|
|
170
|
+ TCNT4 = 0; // clear the timer count
|
|
171
|
+ TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
|
172
|
+ TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
|
|
173
|
+ break;
|
|
174
|
+ #endif
|
|
175
|
+
|
|
176
|
+ #ifdef _useTimer5
|
|
177
|
+ case _timer5:
|
|
178
|
+ TCCR5A = 0; // normal counting mode
|
|
179
|
+ TCCR5B = _BV(CS51); // set prescaler of 8
|
|
180
|
+ TCNT5 = 0; // clear the timer count
|
|
181
|
+ TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
|
182
|
+ TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
|
|
183
|
+ break;
|
|
184
|
+ #endif
|
|
185
|
+ }
|
|
186
|
+}
|
|
187
|
+
|
|
188
|
+void finISR(const timer16_Sequence_t timer_index) {
|
|
189
|
+ // Disable use of the given timer
|
|
190
|
+ #ifdef WIRING
|
|
191
|
+ switch (timer_index) {
|
|
192
|
+ default: break;
|
|
193
|
+
|
|
194
|
+ case _timer1:
|
|
195
|
+ CBI(
|
|
196
|
+ #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
|
197
|
+ TIMSK1
|
|
198
|
+ #else
|
|
199
|
+ TIMSK
|
|
200
|
+ #endif
|
|
201
|
+ , OCIE1A // disable timer 1 output compare interrupt
|
|
202
|
+ );
|
|
203
|
+ timerDetach(TIMER1OUTCOMPAREA_INT);
|
|
204
|
+ break;
|
|
205
|
+
|
|
206
|
+ case _timer3:
|
|
207
|
+ CBI(
|
|
208
|
+ #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
|
209
|
+ TIMSK3
|
|
210
|
+ #else
|
|
211
|
+ ETIMSK
|
|
212
|
+ #endif
|
|
213
|
+ , OCIE3A // disable the timer3 output compare A interrupt
|
|
214
|
+ );
|
|
215
|
+ timerDetach(TIMER3OUTCOMPAREA_INT);
|
|
216
|
+ break;
|
207
|
217
|
}
|
208
|
218
|
#else // !WIRING
|
209
|
219
|
// For arduino - in future: call here to a currently undefined function to reset the timer
|
210
|
|
- UNUSED(timer);
|
|
220
|
+ UNUSED(timer_index);
|
211
|
221
|
#endif
|
212
|
222
|
}
|
213
|
223
|
|