@@ -67,26 +67,25 @@ static volatile int8_t Channel[_Nbr_16timers]; // counter for the s
6767/* *********** static functions common to all instances ***********************/
6868
6969static 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
8281 }
8382 else {
8483 // 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
9089 }
9190}
9291
@@ -123,91 +122,102 @@ static inline void handle_interrupts(const timer16_Sequence_t timer, volatile ui
123122
124123/* ***************** end of static functions ******************************/
125124
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
192137 #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
194141 #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
202156 #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
204162 #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 ;
207217 }
208218 #else // !WIRING
209219 // For arduino - in future: call here to a currently undefined function to reset the timer
210- UNUSED (timer );
220+ UNUSED (timer_index );
211221 #endif
212222}
213223
0 commit comments