root / arduino-1.0 / hardware / arduino / cores / arduino / Tone.cpp @ 58d82c77
History | View | Annotate | Download (14 KB)
1 | 58d82c77 | Tom Mullins | /* Tone.cpp
|
---|---|---|---|
2 | |||
3 | A Tone Generator Library
|
||
4 | |||
5 | Written by Brett Hagman
|
||
6 | |||
7 | This library is free software; you can redistribute it and/or
|
||
8 | modify it under the terms of the GNU Lesser General Public
|
||
9 | License as published by the Free Software Foundation; either
|
||
10 | version 2.1 of the License, or (at your option) any later version.
|
||
11 | |||
12 | This library is distributed in the hope that it will be useful,
|
||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
15 | Lesser General Public License for more details.
|
||
16 | |||
17 | You should have received a copy of the GNU Lesser General Public
|
||
18 | License along with this library; if not, write to the Free Software
|
||
19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
20 | |||
21 | Version Modified By Date Comments
|
||
22 | ------- ----------- -------- --------
|
||
23 | 0001 B Hagman 09/08/02 Initial coding
|
||
24 | 0002 B Hagman 09/08/18 Multiple pins
|
||
25 | 0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
|
||
26 | 0004 B Hagman 09/09/26 Fixed problems with ATmega8
|
||
27 | 0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
|
||
28 | 09/11/25 Changed pin toggle method to XOR
|
||
29 | 09/11/25 Fixed timer0 from being excluded
|
||
30 | 0006 D Mellis 09/12/29 Replaced objects with functions
|
||
31 | 0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
|
||
32 | *************************************************/
|
||
33 | |||
34 | #include <avr/interrupt.h> |
||
35 | #include <avr/pgmspace.h> |
||
36 | #include "Arduino.h" |
||
37 | #include "pins_arduino.h" |
||
38 | |||
39 | #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
|
||
40 | #define TCCR2A TCCR2
|
||
41 | #define TCCR2B TCCR2
|
||
42 | #define COM2A1 COM21
|
||
43 | #define COM2A0 COM20
|
||
44 | #define OCR2A OCR2
|
||
45 | #define TIMSK2 TIMSK
|
||
46 | #define OCIE2A OCIE2
|
||
47 | #define TIMER2_COMPA_vect TIMER2_COMP_vect
|
||
48 | #define TIMSK1 TIMSK
|
||
49 | #endif
|
||
50 | |||
51 | // timerx_toggle_count:
|
||
52 | // > 0 - duration specified
|
||
53 | // = 0 - stopped
|
||
54 | // < 0 - infinitely (until stop() method called, or new play() called)
|
||
55 | |||
56 | #if !defined(__AVR_ATmega8__)
|
||
57 | volatile long timer0_toggle_count; |
||
58 | volatile uint8_t *timer0_pin_port;
|
||
59 | volatile uint8_t timer0_pin_mask;
|
||
60 | #endif
|
||
61 | |||
62 | volatile long timer1_toggle_count; |
||
63 | volatile uint8_t *timer1_pin_port;
|
||
64 | volatile uint8_t timer1_pin_mask;
|
||
65 | volatile long timer2_toggle_count; |
||
66 | volatile uint8_t *timer2_pin_port;
|
||
67 | volatile uint8_t timer2_pin_mask;
|
||
68 | |||
69 | #if defined(TIMSK3)
|
||
70 | volatile long timer3_toggle_count; |
||
71 | volatile uint8_t *timer3_pin_port;
|
||
72 | volatile uint8_t timer3_pin_mask;
|
||
73 | #endif
|
||
74 | |||
75 | #if defined(TIMSK4)
|
||
76 | volatile long timer4_toggle_count; |
||
77 | volatile uint8_t *timer4_pin_port;
|
||
78 | volatile uint8_t timer4_pin_mask;
|
||
79 | #endif
|
||
80 | |||
81 | #if defined(TIMSK5)
|
||
82 | volatile long timer5_toggle_count; |
||
83 | volatile uint8_t *timer5_pin_port;
|
||
84 | volatile uint8_t timer5_pin_mask;
|
||
85 | #endif
|
||
86 | |||
87 | |||
88 | // MLS: This does not make sense, the 3 options are the same
|
||
89 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||
90 | |||
91 | #define AVAILABLE_TONE_PINS 1 |
||
92 | |||
93 | const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ }; |
||
94 | static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ }; |
||
95 | |||
96 | #elif defined(__AVR_ATmega8__)
|
||
97 | |||
98 | #define AVAILABLE_TONE_PINS 1 |
||
99 | |||
100 | const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; |
||
101 | static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; |
||
102 | |||
103 | #else
|
||
104 | |||
105 | #define AVAILABLE_TONE_PINS 1 |
||
106 | |||
107 | // Leave timer 0 to last.
|
||
108 | const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ }; |
||
109 | static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ }; |
||
110 | |||
111 | #endif
|
||
112 | |||
113 | |||
114 | |||
115 | static int8_t toneBegin(uint8_t _pin)
|
||
116 | { |
||
117 | int8_t _timer = -1;
|
||
118 | |||
119 | // if we're already using the pin, the timer should be configured.
|
||
120 | for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { |
||
121 | if (tone_pins[i] == _pin) {
|
||
122 | return pgm_read_byte(tone_pin_to_timer_PGM + i);
|
||
123 | } |
||
124 | } |
||
125 | |||
126 | // search for an unused timer.
|
||
127 | for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { |
||
128 | if (tone_pins[i] == 255) { |
||
129 | tone_pins[i] = _pin; |
||
130 | _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); |
||
131 | break;
|
||
132 | } |
||
133 | } |
||
134 | |||
135 | if (_timer != -1) |
||
136 | { |
||
137 | // Set timer specific stuff
|
||
138 | // All timers in CTC mode
|
||
139 | // 8 bit timers will require changing prescalar values,
|
||
140 | // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar
|
||
141 | switch (_timer)
|
||
142 | { |
||
143 | #if defined(TCCR0A) && defined(TCCR0B)
|
||
144 | case 0: |
||
145 | // 8 bit timer
|
||
146 | TCCR0A = 0;
|
||
147 | TCCR0B = 0;
|
||
148 | bitWrite(TCCR0A, WGM01, 1);
|
||
149 | bitWrite(TCCR0B, CS00, 1);
|
||
150 | timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); |
||
151 | timer0_pin_mask = digitalPinToBitMask(_pin); |
||
152 | break;
|
||
153 | #endif
|
||
154 | |||
155 | #if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12)
|
||
156 | case 1: |
||
157 | // 16 bit timer
|
||
158 | TCCR1A = 0;
|
||
159 | TCCR1B = 0;
|
||
160 | bitWrite(TCCR1B, WGM12, 1);
|
||
161 | bitWrite(TCCR1B, CS10, 1);
|
||
162 | timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); |
||
163 | timer1_pin_mask = digitalPinToBitMask(_pin); |
||
164 | break;
|
||
165 | #endif
|
||
166 | |||
167 | #if defined(TCCR2A) && defined(TCCR2B)
|
||
168 | case 2: |
||
169 | // 8 bit timer
|
||
170 | TCCR2A = 0;
|
||
171 | TCCR2B = 0;
|
||
172 | bitWrite(TCCR2A, WGM21, 1);
|
||
173 | bitWrite(TCCR2B, CS20, 1);
|
||
174 | timer2_pin_port = portOutputRegister(digitalPinToPort(_pin)); |
||
175 | timer2_pin_mask = digitalPinToBitMask(_pin); |
||
176 | break;
|
||
177 | #endif
|
||
178 | |||
179 | #if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3)
|
||
180 | case 3: |
||
181 | // 16 bit timer
|
||
182 | TCCR3A = 0;
|
||
183 | TCCR3B = 0;
|
||
184 | bitWrite(TCCR3B, WGM32, 1);
|
||
185 | bitWrite(TCCR3B, CS30, 1);
|
||
186 | timer3_pin_port = portOutputRegister(digitalPinToPort(_pin)); |
||
187 | timer3_pin_mask = digitalPinToBitMask(_pin); |
||
188 | break;
|
||
189 | #endif
|
||
190 | |||
191 | #if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4)
|
||
192 | case 4: |
||
193 | // 16 bit timer
|
||
194 | TCCR4A = 0;
|
||
195 | TCCR4B = 0;
|
||
196 | #if defined(WGM42)
|
||
197 | bitWrite(TCCR4B, WGM42, 1);
|
||
198 | #elif defined(CS43)
|
||
199 | #warning this may not be correct |
||
200 | // atmega32u4
|
||
201 | bitWrite(TCCR4B, CS43, 1);
|
||
202 | #endif
|
||
203 | bitWrite(TCCR4B, CS40, 1);
|
||
204 | timer4_pin_port = portOutputRegister(digitalPinToPort(_pin)); |
||
205 | timer4_pin_mask = digitalPinToBitMask(_pin); |
||
206 | break;
|
||
207 | #endif
|
||
208 | |||
209 | #if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5)
|
||
210 | case 5: |
||
211 | // 16 bit timer
|
||
212 | TCCR5A = 0;
|
||
213 | TCCR5B = 0;
|
||
214 | bitWrite(TCCR5B, WGM52, 1);
|
||
215 | bitWrite(TCCR5B, CS50, 1);
|
||
216 | timer5_pin_port = portOutputRegister(digitalPinToPort(_pin)); |
||
217 | timer5_pin_mask = digitalPinToBitMask(_pin); |
||
218 | break;
|
||
219 | #endif
|
||
220 | } |
||
221 | } |
||
222 | |||
223 | return _timer;
|
||
224 | } |
||
225 | |||
226 | |||
227 | |||
228 | // frequency (in hertz) and duration (in milliseconds).
|
||
229 | |||
230 | void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) |
||
231 | { |
||
232 | uint8_t prescalarbits = 0b001;
|
||
233 | long toggle_count = 0; |
||
234 | uint32_t ocr = 0;
|
||
235 | int8_t _timer; |
||
236 | |||
237 | _timer = toneBegin(_pin); |
||
238 | |||
239 | if (_timer >= 0) |
||
240 | { |
||
241 | // Set the pinMode as OUTPUT
|
||
242 | pinMode(_pin, OUTPUT); |
||
243 | |||
244 | // if we are using an 8 bit timer, scan through prescalars to find the best fit
|
||
245 | if (_timer == 0 || _timer == 2) |
||
246 | { |
||
247 | ocr = F_CPU / frequency / 2 - 1; |
||
248 | prescalarbits = 0b001; // ck/1: same for both timers |
||
249 | if (ocr > 255) |
||
250 | { |
||
251 | ocr = F_CPU / frequency / 2 / 8 - 1; |
||
252 | prescalarbits = 0b010; // ck/8: same for both timers |
||
253 | |||
254 | if (_timer == 2 && ocr > 255) |
||
255 | { |
||
256 | ocr = F_CPU / frequency / 2 / 32 - 1; |
||
257 | prescalarbits = 0b011;
|
||
258 | } |
||
259 | |||
260 | if (ocr > 255) |
||
261 | { |
||
262 | ocr = F_CPU / frequency / 2 / 64 - 1; |
||
263 | prescalarbits = _timer == 0 ? 0b011 : 0b100; |
||
264 | |||
265 | if (_timer == 2 && ocr > 255) |
||
266 | { |
||
267 | ocr = F_CPU / frequency / 2 / 128 - 1; |
||
268 | prescalarbits = 0b101;
|
||
269 | } |
||
270 | |||
271 | if (ocr > 255) |
||
272 | { |
||
273 | ocr = F_CPU / frequency / 2 / 256 - 1; |
||
274 | prescalarbits = _timer == 0 ? 0b100 : 0b110; |
||
275 | if (ocr > 255) |
||
276 | { |
||
277 | // can't do any better than /1024
|
||
278 | ocr = F_CPU / frequency / 2 / 1024 - 1; |
||
279 | prescalarbits = _timer == 0 ? 0b101 : 0b111; |
||
280 | } |
||
281 | } |
||
282 | } |
||
283 | } |
||
284 | |||
285 | #if defined(TCCR0B)
|
||
286 | if (_timer == 0) |
||
287 | { |
||
288 | TCCR0B = prescalarbits; |
||
289 | } |
||
290 | else
|
||
291 | #endif
|
||
292 | #if defined(TCCR2B)
|
||
293 | { |
||
294 | TCCR2B = prescalarbits; |
||
295 | } |
||
296 | #else
|
||
297 | { |
||
298 | // dummy place holder to make the above ifdefs work
|
||
299 | } |
||
300 | #endif
|
||
301 | } |
||
302 | else
|
||
303 | { |
||
304 | // two choices for the 16 bit timers: ck/1 or ck/64
|
||
305 | ocr = F_CPU / frequency / 2 - 1; |
||
306 | |||
307 | prescalarbits = 0b001;
|
||
308 | if (ocr > 0xffff) |
||
309 | { |
||
310 | ocr = F_CPU / frequency / 2 / 64 - 1; |
||
311 | prescalarbits = 0b011;
|
||
312 | } |
||
313 | |||
314 | if (_timer == 1) |
||
315 | { |
||
316 | #if defined(TCCR1B)
|
||
317 | TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
|
||
318 | #endif
|
||
319 | } |
||
320 | #if defined(TCCR3B)
|
||
321 | else if (_timer == 3) |
||
322 | TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
|
||
323 | #endif
|
||
324 | #if defined(TCCR4B)
|
||
325 | else if (_timer == 4) |
||
326 | TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
|
||
327 | #endif
|
||
328 | #if defined(TCCR5B)
|
||
329 | else if (_timer == 5) |
||
330 | TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
|
||
331 | #endif
|
||
332 | |||
333 | } |
||
334 | |||
335 | |||
336 | // Calculate the toggle count
|
||
337 | if (duration > 0) |
||
338 | { |
||
339 | toggle_count = 2 * frequency * duration / 1000; |
||
340 | } |
||
341 | else
|
||
342 | { |
||
343 | toggle_count = -1;
|
||
344 | } |
||
345 | |||
346 | // Set the OCR for the given timer,
|
||
347 | // set the toggle count,
|
||
348 | // then turn on the interrupts
|
||
349 | switch (_timer)
|
||
350 | { |
||
351 | |||
352 | #if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A)
|
||
353 | case 0: |
||
354 | OCR0A = ocr; |
||
355 | timer0_toggle_count = toggle_count; |
||
356 | bitWrite(TIMSK0, OCIE0A, 1);
|
||
357 | break;
|
||
358 | #endif
|
||
359 | |||
360 | case 1: |
||
361 | #if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A)
|
||
362 | OCR1A = ocr; |
||
363 | timer1_toggle_count = toggle_count; |
||
364 | bitWrite(TIMSK1, OCIE1A, 1);
|
||
365 | #elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A)
|
||
366 | // this combination is for at least the ATmega32
|
||
367 | OCR1A = ocr; |
||
368 | timer1_toggle_count = toggle_count; |
||
369 | bitWrite(TIMSK, OCIE1A, 1);
|
||
370 | #endif
|
||
371 | break;
|
||
372 | |||
373 | #if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A)
|
||
374 | case 2: |
||
375 | OCR2A = ocr; |
||
376 | timer2_toggle_count = toggle_count; |
||
377 | bitWrite(TIMSK2, OCIE2A, 1);
|
||
378 | break;
|
||
379 | #endif
|
||
380 | |||
381 | #if defined(TIMSK3)
|
||
382 | case 3: |
||
383 | OCR3A = ocr; |
||
384 | timer3_toggle_count = toggle_count; |
||
385 | bitWrite(TIMSK3, OCIE3A, 1);
|
||
386 | break;
|
||
387 | #endif
|
||
388 | |||
389 | #if defined(TIMSK4)
|
||
390 | case 4: |
||
391 | OCR4A = ocr; |
||
392 | timer4_toggle_count = toggle_count; |
||
393 | bitWrite(TIMSK4, OCIE4A, 1);
|
||
394 | break;
|
||
395 | #endif
|
||
396 | |||
397 | #if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A)
|
||
398 | case 5: |
||
399 | OCR5A = ocr; |
||
400 | timer5_toggle_count = toggle_count; |
||
401 | bitWrite(TIMSK5, OCIE5A, 1);
|
||
402 | break;
|
||
403 | #endif
|
||
404 | |||
405 | } |
||
406 | } |
||
407 | } |
||
408 | |||
409 | |||
410 | // XXX: this function only works properly for timer 2 (the only one we use
|
||
411 | // currently). for the others, it should end the tone, but won't restore
|
||
412 | // proper PWM functionality for the timer.
|
||
413 | void disableTimer(uint8_t _timer)
|
||
414 | { |
||
415 | switch (_timer)
|
||
416 | { |
||
417 | case 0: |
||
418 | #if defined(TIMSK0)
|
||
419 | TIMSK0 = 0;
|
||
420 | #elif defined(TIMSK)
|
||
421 | TIMSK = 0; // atmega32 |
||
422 | #endif
|
||
423 | break;
|
||
424 | |||
425 | #if defined(TIMSK1) && defined(OCIE1A)
|
||
426 | case 1: |
||
427 | bitWrite(TIMSK1, OCIE1A, 0);
|
||
428 | break;
|
||
429 | #endif
|
||
430 | |||
431 | case 2: |
||
432 | #if defined(TIMSK2) && defined(OCIE2A)
|
||
433 | bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt |
||
434 | #endif
|
||
435 | #if defined(TCCR2A) && defined(WGM20)
|
||
436 | TCCR2A = (1 << WGM20);
|
||
437 | #endif
|
||
438 | #if defined(TCCR2B) && defined(CS22)
|
||
439 | TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22); |
||
440 | #endif
|
||
441 | #if defined(OCR2A)
|
||
442 | OCR2A = 0;
|
||
443 | #endif
|
||
444 | break;
|
||
445 | |||
446 | #if defined(TIMSK3)
|
||
447 | case 3: |
||
448 | TIMSK3 = 0;
|
||
449 | break;
|
||
450 | #endif
|
||
451 | |||
452 | #if defined(TIMSK4)
|
||
453 | case 4: |
||
454 | TIMSK4 = 0;
|
||
455 | break;
|
||
456 | #endif
|
||
457 | |||
458 | #if defined(TIMSK5)
|
||
459 | case 5: |
||
460 | TIMSK5 = 0;
|
||
461 | break;
|
||
462 | #endif
|
||
463 | } |
||
464 | } |
||
465 | |||
466 | |||
467 | void noTone(uint8_t _pin)
|
||
468 | { |
||
469 | int8_t _timer = -1;
|
||
470 | |||
471 | for (int i = 0; i < AVAILABLE_TONE_PINS; i++) { |
||
472 | if (tone_pins[i] == _pin) {
|
||
473 | _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); |
||
474 | tone_pins[i] = 255;
|
||
475 | } |
||
476 | } |
||
477 | |||
478 | disableTimer(_timer); |
||
479 | |||
480 | digitalWrite(_pin, 0);
|
||
481 | } |
||
482 | |||
483 | #if 0
|
||
484 | #if !defined(__AVR_ATmega8__)
|
||
485 | ISR(TIMER0_COMPA_vect)
|
||
486 | {
|
||
487 | if (timer0_toggle_count != 0)
|
||
488 | {
|
||
489 | // toggle the pin
|
||
490 | *timer0_pin_port ^= timer0_pin_mask;
|
||
491 | |||
492 | if (timer0_toggle_count > 0)
|
||
493 | timer0_toggle_count--;
|
||
494 | }
|
||
495 | else
|
||
496 | {
|
||
497 | disableTimer(0);
|
||
498 | *timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop
|
||
499 | }
|
||
500 | }
|
||
501 | #endif
|
||
502 | |||
503 | |||
504 | ISR(TIMER1_COMPA_vect) |
||
505 | { |
||
506 | if (timer1_toggle_count != 0) |
||
507 | { |
||
508 | // toggle the pin
|
||
509 | *timer1_pin_port ^= timer1_pin_mask; |
||
510 | |||
511 | if (timer1_toggle_count > 0) |
||
512 | timer1_toggle_count--; |
||
513 | } |
||
514 | else
|
||
515 | { |
||
516 | disableTimer(1);
|
||
517 | *timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop
|
||
518 | } |
||
519 | } |
||
520 | #endif
|
||
521 | |||
522 | |||
523 | ISR(TIMER2_COMPA_vect) |
||
524 | { |
||
525 | |||
526 | if (timer2_toggle_count != 0) |
||
527 | { |
||
528 | // toggle the pin
|
||
529 | *timer2_pin_port ^= timer2_pin_mask; |
||
530 | |||
531 | if (timer2_toggle_count > 0) |
||
532 | timer2_toggle_count--; |
||
533 | } |
||
534 | else
|
||
535 | { |
||
536 | // need to call noTone() so that the tone_pins[] entry is reset, so the
|
||
537 | // timer gets initialized next time we call tone().
|
||
538 | // XXX: this assumes timer 2 is always the first one used.
|
||
539 | noTone(tone_pins[0]);
|
||
540 | // disableTimer(2);
|
||
541 | // *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop
|
||
542 | } |
||
543 | } |
||
544 | |||
545 | |||
546 | |||
547 | //#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||
548 | #if 0
|
||
549 | |||
550 | ISR(TIMER3_COMPA_vect)
|
||
551 | {
|
||
552 | if (timer3_toggle_count != 0)
|
||
553 | {
|
||
554 | // toggle the pin
|
||
555 | *timer3_pin_port ^= timer3_pin_mask;
|
||
556 | |||
557 | if (timer3_toggle_count > 0)
|
||
558 | timer3_toggle_count--;
|
||
559 | }
|
||
560 | else
|
||
561 | {
|
||
562 | disableTimer(3);
|
||
563 | *timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop
|
||
564 | }
|
||
565 | }
|
||
566 | |||
567 | ISR(TIMER4_COMPA_vect)
|
||
568 | {
|
||
569 | if (timer4_toggle_count != 0)
|
||
570 | {
|
||
571 | // toggle the pin
|
||
572 | *timer4_pin_port ^= timer4_pin_mask;
|
||
573 | |||
574 | if (timer4_toggle_count > 0)
|
||
575 | timer4_toggle_count--;
|
||
576 | }
|
||
577 | else
|
||
578 | {
|
||
579 | disableTimer(4);
|
||
580 | *timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop
|
||
581 | }
|
||
582 | }
|
||
583 | |||
584 | ISR(TIMER5_COMPA_vect)
|
||
585 | {
|
||
586 | if (timer5_toggle_count != 0)
|
||
587 | {
|
||
588 | // toggle the pin
|
||
589 | *timer5_pin_port ^= timer5_pin_mask;
|
||
590 | |||
591 | if (timer5_toggle_count > 0)
|
||
592 | timer5_toggle_count--;
|
||
593 | }
|
||
594 | else
|
||
595 | {
|
||
596 | disableTimer(5);
|
||
597 | *timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop
|
||
598 | }
|
||
599 | }
|
||
600 | |||
601 | #endif |