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


arduino_daq
Author(s):
autogenerated on Mon Jun 10 2019 12:46:03