Index

auto-plow / 4f44ee4

A wheelchair motor-propelled battery-powered ESP32-driven remote control snow plow.

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
630 Nov 2018 18:364a63c8cInclude Arduino core filesJoshua16190N

Blob @ auto-plow / include / arduino / Tone.cpp

text/plain15022 bytesdownload raw
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
21Version Modified By Date Comments
22------- ----------- -------- --------
230001 B Hagman 09/08/02 Initial coding
240002 B Hagman 09/08/18 Multiple pins
250003 B Hagman 09/08/18 Moved initialization from constructor to begin()
260004 B Hagman 09/09/26 Fixed problems with ATmega8
270005 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
300006 D Mellis 09/12/29 Replaced objects with functions
310007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
320008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY
330009 J Reucker 15/04/10 Issue #292 Fixed problems with ATmega8 (thanks to Pete62)
340010 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__)
60volatile long timer0_toggle_count;
61volatile uint8_t *timer0_pin_port;
62volatile uint8_t timer0_pin_mask;
63#endif
64
65volatile long timer1_toggle_count;
66volatile uint8_t *timer1_pin_port;
67volatile uint8_t timer1_pin_mask;
68volatile long timer2_toggle_count;
69volatile uint8_t *timer2_pin_port;
70volatile uint8_t timer2_pin_mask;
71
72#if defined(TIMSK3)
73volatile long timer3_toggle_count;
74volatile uint8_t *timer3_pin_port;
75volatile uint8_t timer3_pin_mask;
76#endif
77
78#if defined(TIMSK4)
79volatile long timer4_toggle_count;
80volatile uint8_t *timer4_pin_port;
81volatile uint8_t timer4_pin_mask;
82#endif
83
84#if defined(TIMSK5)
85volatile long timer5_toggle_count;
86volatile uint8_t *timer5_pin_port;
87volatile 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
96const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ };
97static 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
104const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ };
105static 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
112const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ };
113static 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.
121const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ };
122static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ };
123
124#endif
125
126
127
128static 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);
163 timer0_pin_port = portOutputRegister(digitalPinToPort(_pin));
164 timer0_pin_mask = digitalPinToBitMask(_pin);
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);
175 timer1_pin_port = portOutputRegister(digitalPinToPort(_pin));
176 timer1_pin_mask = digitalPinToBitMask(_pin);
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);
187 timer2_pin_port = portOutputRegister(digitalPinToPort(_pin));
188 timer2_pin_mask = digitalPinToBitMask(_pin);
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
243void 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.
426void 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
480void 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
498ISR(TIMER0_COMPA_vect)
499{
500 if (timer0_toggle_count != 0)
501 {
502 // toggle the pin
503 *timer0_pin_port ^= timer0_pin_mask;
504
505 if (timer0_toggle_count > 0)
506 timer0_toggle_count--;
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
518ISR(TIMER1_COMPA_vect)
519{
520 if (timer1_toggle_count != 0)
521 {
522 // toggle the pin
523 *timer1_pin_port ^= timer1_pin_mask;
524
525 if (timer1_toggle_count > 0)
526 timer1_toggle_count--;
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
538ISR(TIMER2_COMPA_vect)
539{
540
541 if (timer2_toggle_count != 0)
542 {
543 // toggle the pin
544 *timer2_pin_port ^= timer2_pin_mask;
545
546 if (timer2_toggle_count > 0)
547 timer2_toggle_count--;
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
563ISR(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
583ISR(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
603ISR(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
620