|
@@ -1,515 +0,0 @@
|
|
-
|
|
|
|
-
|
|
|
|
- A Tone Generator Library
|
|
|
|
-
|
|
|
|
- Written by Brett Hagman
|
|
|
|
-
|
|
|
|
- This library is free software; you can redistribute it and/or
|
|
|
|
- modify it under the terms of the GNU Lesser General Public
|
|
|
|
- License as published by the Free Software Foundation; either
|
|
|
|
- version 2.1 of the License, or (at your option) any later version.
|
|
|
|
-
|
|
|
|
- This library is distributed in the hope that it will be useful,
|
|
|
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
- Lesser General Public License for more details.
|
|
|
|
-
|
|
|
|
- You should have received a copy of the GNU Lesser General Public
|
|
|
|
- License along with this library; if not, write to the Free Software
|
|
|
|
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
-
|
|
|
|
-Version Modified By Date Comments
|
|
|
|
-------- ----------- -------- --------
|
|
|
|
-0001 B Hagman 09/08/02 Initial coding
|
|
|
|
-0002 B Hagman 09/08/18 Multiple pins
|
|
|
|
-0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
|
|
|
|
-0004 B Hagman 09/09/26 Fixed problems with ATmega8
|
|
|
|
-0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
|
|
|
|
- 09/11/25 Changed pin toggle method to XOR
|
|
|
|
- 09/11/25 Fixed timer0 from being excluded
|
|
|
|
-0006 D Mellis 09/12/29 Replaced objects with functions
|
|
|
|
-
|
|
|
|
-*************************************************/
|
|
|
|
-
|
|
|
|
-#include <avr/interrupt.h>
|
|
|
|
-#include <avr/pgmspace.h>
|
|
|
|
-#include <wiring.h>
|
|
|
|
-#include <pins_arduino.h>
|
|
|
|
-
|
|
|
|
-#if defined(__AVR_ATmega8__)
|
|
|
|
-#define TCCR2A TCCR2
|
|
|
|
-#define TCCR2B TCCR2
|
|
|
|
-#define COM2A1 COM21
|
|
|
|
-#define COM2A0 COM20
|
|
|
|
-#define OCR2A OCR2
|
|
|
|
-#define TIMSK2 TIMSK
|
|
|
|
-#define OCIE2A OCIE2
|
|
|
|
-#define TIMER2_COMPA_vect TIMER2_COMP_vect
|
|
|
|
-#define TIMSK1 TIMSK
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-#if !defined(__AVR_ATmega8__)
|
|
|
|
-volatile long timer0_toggle_count;
|
|
|
|
-volatile uint8_t *timer0_pin_port;
|
|
|
|
-volatile uint8_t timer0_pin_mask;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-volatile long timer1_toggle_count;
|
|
|
|
-volatile uint8_t *timer1_pin_port;
|
|
|
|
-volatile uint8_t timer1_pin_mask;
|
|
|
|
-volatile long timer2_toggle_count;
|
|
|
|
-volatile uint8_t *timer2_pin_port;
|
|
|
|
-volatile uint8_t timer2_pin_mask;
|
|
|
|
-
|
|
|
|
-#if defined(__AVR_ATmega1280__)
|
|
|
|
-volatile long timer3_toggle_count;
|
|
|
|
-volatile uint8_t *timer3_pin_port;
|
|
|
|
-volatile uint8_t timer3_pin_mask;
|
|
|
|
-volatile long timer4_toggle_count;
|
|
|
|
-volatile uint8_t *timer4_pin_port;
|
|
|
|
-volatile uint8_t timer4_pin_mask;
|
|
|
|
-volatile long timer5_toggle_count;
|
|
|
|
-volatile uint8_t *timer5_pin_port;
|
|
|
|
-volatile uint8_t timer5_pin_mask;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-#if defined(__AVR_ATmega1280__)
|
|
|
|
-
|
|
|
|
-#define AVAILABLE_TONE_PINS 1
|
|
|
|
-
|
|
|
|
-const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 };
|
|
|
|
-static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 };
|
|
|
|
-
|
|
|
|
-#elif defined(__AVR_ATmega8__)
|
|
|
|
-
|
|
|
|
-#define AVAILABLE_TONE_PINS 1
|
|
|
|
-
|
|
|
|
-const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 };
|
|
|
|
-static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 };
|
|
|
|
-
|
|
|
|
-#else
|
|
|
|
-
|
|
|
|
-#define AVAILABLE_TONE_PINS 1
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 };
|
|
|
|
-static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 };
|
|
|
|
-
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-static int8_t toneBegin(uint8_t _pin)
|
|
|
|
-{
|
|
|
|
- int8_t _timer = -1;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
|
|
|
|
- if (tone_pins[i] == _pin) {
|
|
|
|
- return pgm_read_byte(tone_pin_to_timer_PGM + i);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
|
|
|
|
- if (tone_pins[i] == 255) {
|
|
|
|
- tone_pins[i] = _pin;
|
|
|
|
- _timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (_timer != -1)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- switch (_timer)
|
|
|
|
- {
|
|
|
|
-#if !defined(__AVR_ATmega8__)
|
|
|
|
- case 0:
|
|
|
|
-
|
|
|
|
- TCCR0A = 0;
|
|
|
|
- TCCR0B = 0;
|
|
|
|
- bitWrite(TCCR0A, WGM01, 1);
|
|
|
|
- bitWrite(TCCR0B, CS00, 1);
|
|
|
|
- timer0_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
|
|
|
- timer0_pin_mask = digitalPinToBitMask(_pin);
|
|
|
|
- break;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- case 1:
|
|
|
|
-
|
|
|
|
- TCCR1A = 0;
|
|
|
|
- TCCR1B = 0;
|
|
|
|
- bitWrite(TCCR1B, WGM12, 1);
|
|
|
|
- bitWrite(TCCR1B, CS10, 1);
|
|
|
|
- timer1_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
|
|
|
- timer1_pin_mask = digitalPinToBitMask(_pin);
|
|
|
|
- break;
|
|
|
|
- case 2:
|
|
|
|
-
|
|
|
|
- TCCR2A = 0;
|
|
|
|
- TCCR2B = 0;
|
|
|
|
- bitWrite(TCCR2A, WGM21, 1);
|
|
|
|
- bitWrite(TCCR2B, CS20, 1);
|
|
|
|
- timer2_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
|
|
|
- timer2_pin_mask = digitalPinToBitMask(_pin);
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
-#if defined(__AVR_ATmega1280__)
|
|
|
|
- case 3:
|
|
|
|
-
|
|
|
|
- TCCR3A = 0;
|
|
|
|
- TCCR3B = 0;
|
|
|
|
- bitWrite(TCCR3B, WGM32, 1);
|
|
|
|
- bitWrite(TCCR3B, CS30, 1);
|
|
|
|
- timer3_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
|
|
|
- timer3_pin_mask = digitalPinToBitMask(_pin);
|
|
|
|
- break;
|
|
|
|
- case 4:
|
|
|
|
-
|
|
|
|
- TCCR4A = 0;
|
|
|
|
- TCCR4B = 0;
|
|
|
|
- bitWrite(TCCR4B, WGM42, 1);
|
|
|
|
- bitWrite(TCCR4B, CS40, 1);
|
|
|
|
- timer4_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
|
|
|
- timer4_pin_mask = digitalPinToBitMask(_pin);
|
|
|
|
- break;
|
|
|
|
- case 5:
|
|
|
|
-
|
|
|
|
- TCCR5A = 0;
|
|
|
|
- TCCR5B = 0;
|
|
|
|
- bitWrite(TCCR5B, WGM52, 1);
|
|
|
|
- bitWrite(TCCR5B, CS50, 1);
|
|
|
|
- timer5_pin_port = portOutputRegister(digitalPinToPort(_pin));
|
|
|
|
- timer5_pin_mask = digitalPinToBitMask(_pin);
|
|
|
|
- break;
|
|
|
|
-#endif
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return _timer;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
|
|
|
|
-{
|
|
|
|
- uint8_t prescalarbits = 0b001;
|
|
|
|
- long toggle_count = 0;
|
|
|
|
- uint32_t ocr = 0;
|
|
|
|
- int8_t _timer;
|
|
|
|
-
|
|
|
|
- _timer = toneBegin(_pin);
|
|
|
|
-
|
|
|
|
- if (_timer >= 0)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- pinMode(_pin, OUTPUT);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- if (_timer == 0 || _timer == 2)
|
|
|
|
- {
|
|
|
|
- ocr = F_CPU / frequency / 2 - 1;
|
|
|
|
- prescalarbits = 0b001;
|
|
|
|
- if (ocr > 255)
|
|
|
|
- {
|
|
|
|
- ocr = F_CPU / frequency / 2 / 8 - 1;
|
|
|
|
- prescalarbits = 0b010;
|
|
|
|
-
|
|
|
|
- if (_timer == 2 && ocr > 255)
|
|
|
|
- {
|
|
|
|
- ocr = F_CPU / frequency / 2 / 32 - 1;
|
|
|
|
- prescalarbits = 0b011;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (ocr > 255)
|
|
|
|
- {
|
|
|
|
- ocr = F_CPU / frequency / 2 / 64 - 1;
|
|
|
|
- prescalarbits = _timer == 0 ? 0b011 : 0b100;
|
|
|
|
-
|
|
|
|
- if (_timer == 2 && ocr > 255)
|
|
|
|
- {
|
|
|
|
- ocr = F_CPU / frequency / 2 / 128 - 1;
|
|
|
|
- prescalarbits = 0b101;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (ocr > 255)
|
|
|
|
- {
|
|
|
|
- ocr = F_CPU / frequency / 2 / 256 - 1;
|
|
|
|
- prescalarbits = _timer == 0 ? 0b100 : 0b110;
|
|
|
|
- if (ocr > 255)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- ocr = F_CPU / frequency / 2 / 1024 - 1;
|
|
|
|
- prescalarbits = _timer == 0 ? 0b101 : 0b111;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-#if !defined(__AVR_ATmega8__)
|
|
|
|
- if (_timer == 0)
|
|
|
|
- TCCR0B = prescalarbits;
|
|
|
|
- else
|
|
|
|
-#endif
|
|
|
|
- TCCR2B = prescalarbits;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- ocr = F_CPU / frequency / 2 - 1;
|
|
|
|
-
|
|
|
|
- prescalarbits = 0b001;
|
|
|
|
- if (ocr > 0xffff)
|
|
|
|
- {
|
|
|
|
- ocr = F_CPU / frequency / 2 / 64 - 1;
|
|
|
|
- prescalarbits = 0b011;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (_timer == 1)
|
|
|
|
- TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
|
|
|
|
-#if defined(__AVR_ATmega1280__)
|
|
|
|
- else if (_timer == 3)
|
|
|
|
- TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
|
|
|
|
- else if (_timer == 4)
|
|
|
|
- TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
|
|
|
|
- else if (_timer == 5)
|
|
|
|
- TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- if (duration > 0)
|
|
|
|
- {
|
|
|
|
- toggle_count = 2 * frequency * duration / 1000;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- toggle_count = -1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- switch (_timer)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
-#if !defined(__AVR_ATmega8__)
|
|
|
|
- case 0:
|
|
|
|
- OCR0A = ocr;
|
|
|
|
- timer0_toggle_count = toggle_count;
|
|
|
|
- bitWrite(TIMSK0, OCIE0A, 1);
|
|
|
|
- break;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- case 1:
|
|
|
|
- OCR1A = ocr;
|
|
|
|
- timer1_toggle_count = toggle_count;
|
|
|
|
- bitWrite(TIMSK1, OCIE1A, 1);
|
|
|
|
- break;
|
|
|
|
- case 2:
|
|
|
|
- OCR2A = ocr;
|
|
|
|
- timer2_toggle_count = toggle_count;
|
|
|
|
- bitWrite(TIMSK2, OCIE2A, 1);
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
-#if defined(__AVR_ATmega1280__)
|
|
|
|
- case 3:
|
|
|
|
- OCR3A = ocr;
|
|
|
|
- timer3_toggle_count = toggle_count;
|
|
|
|
- bitWrite(TIMSK3, OCIE3A, 1);
|
|
|
|
- break;
|
|
|
|
- case 4:
|
|
|
|
- OCR4A = ocr;
|
|
|
|
- timer4_toggle_count = toggle_count;
|
|
|
|
- bitWrite(TIMSK4, OCIE4A, 1);
|
|
|
|
- break;
|
|
|
|
- case 5:
|
|
|
|
- OCR5A = ocr;
|
|
|
|
- timer5_toggle_count = toggle_count;
|
|
|
|
- bitWrite(TIMSK5, OCIE5A, 1);
|
|
|
|
- break;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-void noTone(uint8_t _pin)
|
|
|
|
-{
|
|
|
|
- int8_t _timer = -1;
|
|
|
|
-
|
|
|
|
- for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
|
|
|
|
- if (tone_pins[i] == _pin) {
|
|
|
|
- _timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
|
|
|
|
- tone_pins[i] = 255;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- switch (_timer)
|
|
|
|
- {
|
|
|
|
-#if defined(__AVR_ATmega8__)
|
|
|
|
- case 1:
|
|
|
|
- bitWrite(TIMSK1, OCIE1A, 0);
|
|
|
|
- break;
|
|
|
|
- case 2:
|
|
|
|
- bitWrite(TIMSK2, OCIE2A, 0);
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
-#else
|
|
|
|
- case 0:
|
|
|
|
- TIMSK0 = 0;
|
|
|
|
- break;
|
|
|
|
- case 1:
|
|
|
|
- TIMSK1 = 0;
|
|
|
|
- break;
|
|
|
|
- case 2:
|
|
|
|
- TIMSK2 = 0;
|
|
|
|
- break;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-#if defined(__AVR_ATmega1280__)
|
|
|
|
- case 3:
|
|
|
|
- TIMSK3 = 0;
|
|
|
|
- break;
|
|
|
|
- case 4:
|
|
|
|
- TIMSK4 = 0;
|
|
|
|
- break;
|
|
|
|
- case 5:
|
|
|
|
- TIMSK5 = 0;
|
|
|
|
- break;
|
|
|
|
-#endif
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- digitalWrite(_pin, 0);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#if 0
|
|
|
|
-#if !defined(__AVR_ATmega8__)
|
|
|
|
-ISR(TIMER0_COMPA_vect)
|
|
|
|
-{
|
|
|
|
- if (timer0_toggle_count != 0)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- *timer0_pin_port ^= timer0_pin_mask;
|
|
|
|
-
|
|
|
|
- if (timer0_toggle_count > 0)
|
|
|
|
- timer0_toggle_count--;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- TIMSK0 = 0;
|
|
|
|
- *timer0_pin_port &= ~(timer0_pin_mask);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-ISR(TIMER1_COMPA_vect)
|
|
|
|
-{
|
|
|
|
- if (timer1_toggle_count != 0)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- *timer1_pin_port ^= timer1_pin_mask;
|
|
|
|
-
|
|
|
|
- if (timer1_toggle_count > 0)
|
|
|
|
- timer1_toggle_count--;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- TIMSK1 = 0;
|
|
|
|
- *timer1_pin_port &= ~(timer1_pin_mask);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-ISR(TIMER2_COMPA_vect)
|
|
|
|
-{
|
|
|
|
-
|
|
|
|
- if (timer2_toggle_count != 0)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- *timer2_pin_port ^= timer2_pin_mask;
|
|
|
|
-
|
|
|
|
- if (timer2_toggle_count > 0)
|
|
|
|
- timer2_toggle_count--;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- TIMSK2 = 0;
|
|
|
|
- *timer2_pin_port &= ~(timer2_pin_mask);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-#if 0
|
|
|
|
-
|
|
|
|
-ISR(TIMER3_COMPA_vect)
|
|
|
|
-{
|
|
|
|
- if (timer3_toggle_count != 0)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- *timer3_pin_port ^= timer3_pin_mask;
|
|
|
|
-
|
|
|
|
- if (timer3_toggle_count > 0)
|
|
|
|
- timer3_toggle_count--;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- TIMSK3 = 0;
|
|
|
|
- *timer3_pin_port &= ~(timer3_pin_mask);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-ISR(TIMER4_COMPA_vect)
|
|
|
|
-{
|
|
|
|
- if (timer4_toggle_count != 0)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- *timer4_pin_port ^= timer4_pin_mask;
|
|
|
|
-
|
|
|
|
- if (timer4_toggle_count > 0)
|
|
|
|
- timer4_toggle_count--;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- TIMSK4 = 0;
|
|
|
|
- *timer4_pin_port &= ~(timer4_pin_mask);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-ISR(TIMER5_COMPA_vect)
|
|
|
|
-{
|
|
|
|
- if (timer5_toggle_count != 0)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- *timer5_pin_port ^= timer5_pin_mask;
|
|
|
|
-
|
|
|
|
- if (timer5_toggle_count > 0)
|
|
|
|
- timer5_toggle_count--;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- TIMSK5 = 0;
|
|
|
|
- *timer5_pin_port &= ~(timer5_pin_mask);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#endif
|
|
|