@@ -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
0 commit comments