diff --git a/converter/news_usb/tone.c b/converter/news_usb/tone.c new file mode 100644 index 00000000..687ec75f --- /dev/null +++ b/converter/news_usb/tone.c @@ -0,0 +1,124 @@ +/* + 2023 Based on: + https://github.com/arduino/ArduinoCore-avr/blob/a7edf4d66f66d42ebb7e166762ac7c11cb299a3f/cores/arduino/Tone.cpp + + 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 +*/ +#include + +// Pin for buzzer: PD0 +#define BZ_PIN_PORT PORTD +#define BZ_PIN_DDR DDRD +#define BZ_PIN_MASK (1<<0) + +volatile long toggle_count; + +static void toneBegin(void) +{ + // Timer 1 + //TCCR1A = 0; + //TCCR1B = 0; + + // CTC mode + //TCCR1B |= WGM12; + TCCR1B |= _BV(WGM12); + // No prescaling + //TCCR1B |= CS10; + TCCR1B |= _BV(CS10); + + BZ_PIN_DDR |= BZ_PIN_MASK; + BZ_PIN_PORT |= BZ_PIN_MASK; +} + +// frequency (in hertz) and duration (in milliseconds). +void tone(unsigned int frequency, unsigned long duration) +{ + uint8_t prescalarbits = 0b001; + uint32_t ocr = 0; + + toneBegin(); + + // Set the pinMode as OUTPUT + BZ_PIN_DDR |= BZ_PIN_MASK; + + // two choices for the 16 bit timers: ck/1 or ck/64 + ocr = F_CPU / frequency / 2 - 1; + + prescalarbits = 0b001; // CLKio/1 + if (ocr > 0xffff) { + ocr = F_CPU / frequency / 2 / 64 - 1; + prescalarbits = 0b011; // CLKio/64 + } + TCCR1B = (TCCR1B & 0b11111000) | prescalarbits; + + // Calculate the toggle count + if (duration > 0) { + toggle_count = 2 * frequency * duration / 1000; + } else { + toggle_count = -1; + } + + uint8_t sreg = SREG; + cli(); + OCR1AH = (ocr >> 8) & 0xff; + OCR1AL = ocr & 0xff; + SREG = sreg; + + // enable interrupt + TIMSK1 |= (1< 0) + toggle_count--; + } else { + disableTimer(); + BZ_PIN_PORT &= ~(BZ_PIN_MASK); + } +} +