Skip to content

Commit 2206661

Browse files
committed
Update available tone pins and properly restore PWM function when disabling the timers
1 parent c8c514c commit 2206661

File tree

1 file changed

+101
-28
lines changed

1 file changed

+101
-28
lines changed

Diff for: cores/arduino/Tone.cpp

+101-28
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Version Modified By Date Comments
3232
0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY
3333
0009 J Reucker 15/04/10 Issue #292 Fixed problems with ATmega8 (thanks to Pete62)
3434
0010 jipp 15/04/13 added additional define check #2923
35+
0011 J Elias 24/12/19 Enabled all timers except timer 0 to make more pins available
3536
*************************************************/
3637

3738
#include <avr/interrupt.h>
@@ -90,36 +91,43 @@ volatile uint8_t timer5_pin_mask;
9091

9192
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
9293

93-
#define AVAILABLE_TONE_PINS 1
94+
#define AVAILABLE_TONE_PINS 5
9495
#define USE_TIMER2
96+
#define USE_TIMER3
97+
#define USE_TIMER4
98+
#define USE_TIMER5
99+
#define USE_TIMER1
95100

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 */ };
101+
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2, 3, 4, 5, 1 /*, 0 */ };
102+
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255, 255, 255, 255, 255 /*, 255 */ };
98103

99104
#elif defined(__AVR_ATmega8__)
100105

101-
#define AVAILABLE_TONE_PINS 1
106+
#define AVAILABLE_TONE_PINS 2
102107
#define USE_TIMER2
108+
#define USE_TIMER1
103109

104-
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ };
105-
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
110+
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2, 1 };
111+
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255, 255 };
106112

107113
#elif defined(__AVR_ATmega32U4__)
108114

109-
#define AVAILABLE_TONE_PINS 1
115+
#define AVAILABLE_TONE_PINS 2
110116
#define USE_TIMER3
117+
#define USE_TIMER1
111118

112-
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ };
113-
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
119+
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3, 1 };
120+
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255, 255 };
114121

115122
#else
116123

117-
#define AVAILABLE_TONE_PINS 1
124+
#define AVAILABLE_TONE_PINS 2
118125
#define USE_TIMER2
126+
#define USE_TIMER1
119127

120128
// 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 */ };
129+
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2, 1 /*, 0 */ };
130+
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255, 255 /*, 255 */ };
123131

124132
#endif
125133

@@ -293,7 +301,7 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
293301
}
294302
}
295303
}
296-
}
304+
}
297305

298306
#if defined(TCCR0B)
299307
if (_timer == 0)
@@ -420,9 +428,8 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
420428
}
421429

422430

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.
431+
// Disable the timer and restore proper PWM function.
432+
// (All timers except timer 0 are set as in init function - wiring.c)
426433
void disableTimer(uint8_t _timer)
427434
{
428435
switch (_timer)
@@ -435,11 +442,34 @@ void disableTimer(uint8_t _timer)
435442
#endif
436443
break;
437444

438-
#if defined(TIMSK1) && defined(OCIE1A)
439445
case 1:
440-
bitWrite(TIMSK1, OCIE1A, 0);
446+
#if defined(TIMSK1) && defined(OCIE1A)
447+
bitWrite(TIMSK1, OCIE1A, 0); // disable interrupt
448+
#endif
449+
450+
#if defined(TCCR1B) && defined(CS11) && defined(CS10)
451+
TCCR1B = 0; // Reset Register
452+
// set timer 1 prescale factor to 64
453+
bitWrite(TCCR1B, CS11, 1);
454+
#if F_CPU >= 8000000L
455+
bitWrite(TCCR1B, CS10, 1);
456+
#endif
457+
#elif defined(TCCR1) && defined(CS11) && defined(CS10)
458+
TCCR1 = 0; // Reset Register
459+
bitWrite(TCCR1, CS11, 1);
460+
#if F_CPU >= 8000000L
461+
bitWrite(TCCR1, CS10, 1);
462+
#endif
463+
#endif
464+
// put timer 1 in 8-bit phase correct pwm mode
465+
#if defined(TCCR1A) && defined(WGM10)
466+
TCCR1A = 0; // Reset Register
467+
bitWrite(TCCR1A, WGM10, 1);
468+
#endif
469+
#if defined(OCR3A)
470+
OCR1A = 0;
471+
#endif
441472
break;
442-
#endif
443473

444474
case 2:
445475
#if defined(TIMSK2) && defined(OCIE2A)
@@ -456,23 +486,66 @@ void disableTimer(uint8_t _timer)
456486
#endif
457487
break;
458488

459-
#if defined(TIMSK3) && defined(OCIE3A)
460489
case 3:
461-
bitWrite(TIMSK3, OCIE3A, 0);
490+
#if defined(TIMSK3) && defined(OCIE3A)
491+
bitWrite(TIMSK3, OCIE3A, 0); // disable interrupt
492+
#endif
493+
#if defined(TCCR3B) && defined(WGM32) && defined(CS30)
494+
TCCR3A = 0; // Reset Register
495+
TCCR3B = 0; // Reset register
496+
bitWrite(TCCR3B, CS31, 1); // set timer 3 prescale factor to 64
497+
bitWrite(TCCR3B, CS30, 1);
498+
bitWrite(TCCR3A, WGM30, 1); // put timer 3 in 8-bit phase correct pwm mode
499+
#endif
500+
#if defined(OCR3A)
501+
OCR3A = 0;
502+
#endif
462503
break;
463-
#endif
464504

465-
#if defined(TIMSK4) && defined(OCIE4A)
466505
case 4:
467-
bitWrite(TIMSK4, OCIE4A, 0);
506+
#if defined(TIMSK4) && defined(OCIE4A)
507+
bitWrite(TIMSK4, OCIE4A, 0); // disable interrupt
508+
#endif
509+
#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */
510+
TCCR4A = 0; // Reset register
511+
TCCR4B = 0; // Reset register
512+
TCCR4C = 0; // Reset register
513+
TCCR4D = 0; // Reset register
514+
bitWrite(TCCR4B, CS42, 1); // set timer4 prescale factor to 64
515+
bitWrite(TCCR4B, CS41, 1);
516+
bitWrite(TCCR4B, CS40, 1);
517+
bitWrite(TCCR4D, WGM40, 1); // put timer 4 in phase- and frequency-correct PWM mode
518+
bitWrite(TCCR4A, PWM4A, 1); // enable PWM mode for comparator OCR4A
519+
bitWrite(TCCR4C, PWM4D, 1); // enable PWM mode for comparator OCR4D
520+
#endif
521+
/* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */
522+
#if defined(TCCR4B) && defined(CS41) && defined(WGM40)
523+
TCCR4A = 0; // Reset register
524+
TCCR4B = 0; // Reset register
525+
bitWrite(TCCR4B, CS41, 1); // set timer 4 prescale factor to 64
526+
bitWrite(TCCR4B, CS40, 1);
527+
bitWrite(TCCR4A, WGM40, 1); // put timer 4 in 8-bit phase correct pwm mode
528+
#endif
529+
#if defined(OCR4A)
530+
OCR4A = 0;
531+
#endif
468532
break;
469-
#endif
470533

471-
#if defined(TIMSK5) && defined(OCIE5A)
472534
case 5:
473-
bitWrite(TIMSK5, OCIE5A, 0);
535+
#if defined(TIMSK5) && defined(OCIE5A)
536+
bitWrite(TIMSK5, OCIE5A, 0); // disable interrupt
537+
#endif
538+
#if defined(TCCR5B) && defined(WGM52) && defined(CS50)
539+
TCCR5A = 0;
540+
TCCR5B = 0;
541+
bitWrite(TCCR5B, CS51, 1); // set timer 5 prescale factor to 64
542+
bitWrite(TCCR5B, CS50, 1);
543+
bitWrite(TCCR5A, WGM50, 1); // put timer 5 in 8-bit phase correct pwm mode
544+
#endif
545+
#if defined(OCR5A)
546+
OCR5A = 0;
547+
#endif
474548
break;
475-
#endif
476549
}
477550
}
478551

0 commit comments

Comments
 (0)