sanguino/cores/arduino/Tone.cpp

changeset 2
b373b0288715
equal deleted inserted replaced
1:b584642d4f58 2:b373b0288715
1 /* 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

mercurial