mirror of
https://codeberg.org/mclemens/ubitxv6.git
synced 2025-02-21 06:57:27 -05:00
Add toneAC2 library
This commit is contained in:
parent
2a8ff5e758
commit
0fe54d054f
toneAC2
27
toneAC2/examples/toneAC2_demo/toneAC2_demo.pde
Normal file
27
toneAC2/examples/toneAC2_demo/toneAC2_demo.pde
Normal file
@ -0,0 +1,27 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
// Be sure to include an in-line 100 ohm resistor on one pin as you normally do when connecting a piezo or speaker.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#include <toneAC2.h>
|
||||
|
||||
// Melody liberated from the toneMelody Arduino example sketch by Tom Igoe.
|
||||
int melody[] = { 262, 196, 196, 220, 196, 0, 247, 262 };
|
||||
int noteDurations[] = { 4, 8, 8, 4, 4, 4, 4, 4 };
|
||||
|
||||
void setup() {} // Nothing to setup, just start playing!
|
||||
|
||||
void loop() {
|
||||
for (unsigned long freq = 125; freq <= 15000; freq += 10) {
|
||||
toneAC2(2, 3, freq, 1); // Play the frequency (125 Hz to 15 kHz sweep in 10 Hz steps) for 1ms.
|
||||
}
|
||||
|
||||
delay(1000); // Wait a second.
|
||||
|
||||
for (int thisNote = 0; thisNote < 8; thisNote++) {
|
||||
int noteDuration = 1000/noteDurations[thisNote];
|
||||
toneAC2(2, 3, melody[thisNote], noteDuration, true); // Play thisNote at full volume for noteDuration in the background.
|
||||
delay(noteDuration * 4 / 3); // Wait while the tone plays in the background, plus another 33% delay between notes.
|
||||
}
|
||||
|
||||
while(1); // Stop (so it doesn't repeat forever driving you crazy--you're welcome).
|
||||
}
|
18
toneAC2/keywords.txt
Normal file
18
toneAC2/keywords.txt
Normal file
@ -0,0 +1,18 @@
|
||||
###################################
|
||||
# Syntax Coloring Map For toneAC2
|
||||
###################################
|
||||
|
||||
###################################
|
||||
# Datatypes (KEYWORD1)
|
||||
###################################
|
||||
|
||||
###################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
###################################
|
||||
|
||||
toneAC2 KEYWORD2
|
||||
noToneAC2 KEYWORD2
|
||||
|
||||
###################################
|
||||
# Constants (LITERAL1)
|
||||
###################################
|
64
toneAC2/toneAC2.cpp
Normal file
64
toneAC2/toneAC2.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
// Created by Tim Eckel - teckel@leethost.com
|
||||
// Copyright 2015 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html
|
||||
//
|
||||
// See "toneAC2.h" for purpose, syntax, version history, links, and more.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#include "toneAC2.h"
|
||||
|
||||
unsigned long _tAC2_time; // Used to track end note with timer when playing note in the background.
|
||||
volatile uint8_t *_pinMode1, *_pinMode2; // Pin modes.
|
||||
uint8_t _pinMask1 = 0, _pinMask2 = 0; // Bitmask for pins.
|
||||
volatile uint8_t *_pinOutput1, *_pinOutput2; // Output port registers for each pin.
|
||||
int _tAC2_prescale[] = { 2, 16, 64, 128, 256, 512, 2048 }; // Prescaler.
|
||||
|
||||
void toneAC2(uint8_t pin1, uint8_t pin2, unsigned int frequency, unsigned long length, uint8_t background) {
|
||||
long top;
|
||||
uint8_t prescaler;
|
||||
|
||||
for (prescaler = 1; prescaler < 8; prescaler++) { // Find the appropriate prescaler
|
||||
top = F_CPU / (long) frequency / (long) _tAC2_prescale[prescaler - 1] - 1; // Calculate the top.
|
||||
if (top < 256) break; // Fits, break out of for loop.
|
||||
}
|
||||
if (top > 255) { noToneAC2(); return; } // Frequency is out of range, turn off sound and return.
|
||||
|
||||
if (length > 0) _tAC2_time = millis() + length - 1; else _tAC2_time = 0xFFFFFFFF; // Set when the note should end, or play "forever".
|
||||
|
||||
if (_pinMask1 == 0) { // This gets the port registers and bitmaps for the two pins and sets the pins to output mode.
|
||||
_pinMask1 = digitalPinToBitMask(pin1); // Get the port register bitmask for pin 1.
|
||||
_pinMask2 = digitalPinToBitMask(pin2); // Get the port register bitmask for pin 2.
|
||||
_pinOutput1 = portOutputRegister(digitalPinToPort(pin1)); // Get the output port register for pin 1.
|
||||
_pinOutput2 = portOutputRegister(digitalPinToPort(pin2)); // Get the output port register for pin 2.
|
||||
_pinMode1 = (uint8_t *) portModeRegister(digitalPinToPort(pin1)); // Get the port mode register for pin 1.
|
||||
_pinMode2 = (uint8_t *) portModeRegister(digitalPinToPort(pin2)); // Get the port mode register for pin 2.
|
||||
*_pinMode1 |= _pinMask1; // Set pin 1 to Output mode.
|
||||
*_pinMode2 |= _pinMask2; // Set pin 2 to Output mode.
|
||||
}
|
||||
|
||||
OCR2A = top; // Set the top.
|
||||
if (TCNT2 > top) TCNT2 = top; // Counter over the top, put within range.
|
||||
TCCR2B = _BV(WGM22) | prescaler; // Set Fast PWM and prescaler.
|
||||
TCCR2A = _BV(WGM20) | _BV(WGM21); // Fast PWM and normal port operation, OC2A/OC2B disconnected.
|
||||
TIMSK2 &= ~_BV(OCIE2A); // Stop timer 2 interrupt while we set the pin states.
|
||||
if (*_pinOutput1 & _pinMask1) *_pinOutput2 &= ~_pinMask2; // Be sure pins are reversed.
|
||||
else *_pinOutput2 |= _pinMask2; // Other half of making sure pins are reversed.
|
||||
TIMSK2 |= _BV(OCIE2A); // Activate the timer interrupt.
|
||||
|
||||
if (length > 0 && !background) { delay(length); noToneAC2(); } // Just a simple delay, doesn't return control till finished.
|
||||
}
|
||||
|
||||
void noToneAC2() {
|
||||
TIMSK2 &= ~_BV(OCIE2A); // Remove the timer interrupt.
|
||||
TCCR2B = _BV(CS22); // Default clock prescaler of 64.
|
||||
TCCR2A = _BV(WGM20); // Set to defaults so PWM can work like normal (PWM, phase corrected, 8bit).
|
||||
*_pinMode1 &= ~_pinMask1; // Set pin 1 to INPUT.
|
||||
*_pinMode2 &= ~_pinMask2; // Set pin 2 to INPUT.
|
||||
_pinMask1 = 0; // Flag so we know note is no longer playing.
|
||||
}
|
||||
|
||||
ISR(TIMER2_COMPA_vect) { // Timer interrupt vector.
|
||||
if (millis() > _tAC2_time) noToneAC2(); // Check to see if it's time for the note to end.
|
||||
*_pinOutput1 ^= _pinMask1; // Toggle the pin 1 state.
|
||||
*_pinOutput2 ^= _pinMask2; // Toggle the pin 2 state.
|
||||
}
|
73
toneAC2/toneAC2.h
Normal file
73
toneAC2/toneAC2.h
Normal file
@ -0,0 +1,73 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
// toneAC2 Library - v1.1 - 09/15/2015
|
||||
//
|
||||
// AUTHOR/LICENSE:
|
||||
// Created by Tim Eckel - teckel@leethost.com
|
||||
// Copyright 2015 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html
|
||||
//
|
||||
// LINKS:
|
||||
// Project home: https://bitbucket.org/teckel12/arduino-toneac/wiki/Home
|
||||
// Blog: http://forum.arduino.cc/index.php?topic=142097.0
|
||||
//
|
||||
// DISCLAIMER:
|
||||
// This software is furnished "as is", without technical support, and with no
|
||||
// warranty, express or implied, as to its usefulness for any purpose.
|
||||
//
|
||||
// PURPOSE:
|
||||
// Replacement to the standard tone library with the advantage of nearly twice
|
||||
// the volume, 800 bytes smaller compiled code size, and less stress on the
|
||||
// speaker. This alternate version uses timer 2 and allows for flexible pin
|
||||
// assignment. The primary version (toneAC) allows for higher frequencies,
|
||||
// higher quality, and even smaller code size. However, toneAC is fixed to
|
||||
// using the PWM timer 1 pins unlike toneAC2 which can use any two pins. Both
|
||||
// exclusively use port registers for the fast and smallest code possible.
|
||||
//
|
||||
// USAGE:
|
||||
// Connection is very similar to a piezo or standard speaker. Except, instead
|
||||
// of connecting one speaker wire to ground you connect both speaker wires to
|
||||
// Arduino pins. Unlike toneAC, with toneAC2 you can connect to any two pins.
|
||||
// Just as usual when connecting a speaker, make sure you add an in-line 100
|
||||
// ohm resistor between one of the pins and the speaker wire.
|
||||
//
|
||||
// SYNTAX:
|
||||
// toneAC2( pin1, pin2, frequency [, length [, background ]] ) - Play a note.
|
||||
// Parameters:
|
||||
// * pin1 - Pin to attach one of the speaker wires.
|
||||
// * pin2 - Pin to attach the other speaker wire.
|
||||
// * frequency - Play the specified frequency indefinitely, turn off with noToneAC2().
|
||||
// * length - [optional] Set the length to play in milliseconds. (default: 0 [forever], range: 0 to 2^32-1)
|
||||
// * background - [optional] Play note in background or pause till finished? (default: false, values: true/false)
|
||||
// noToneAC2() - Stop playing.
|
||||
//
|
||||
// HISTORY:
|
||||
// 09/15/2015 v1.1 - Fix a potential race condition with _tAC2_time. Moved
|
||||
// development to Bitbucket.
|
||||
//
|
||||
// 01/27/2013 v1.0 - Initial release.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#ifndef toneAC2_h
|
||||
#define toneAC2_h
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
|
||||
// This doesn't currently work. Would require more work than simply doing this.
|
||||
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
|
||||
#define TCCR2A TCCR2
|
||||
#define TCCR2B TCCR2
|
||||
#define TIMSK2 TIMSK
|
||||
#define COM2A1 COM21
|
||||
#define COM2A0 COM20
|
||||
#define OCIE2A OCIE2
|
||||
#define OCR2A OCR2
|
||||
#define TIMER2_COMPA_vect TIMER2_COMP_vect
|
||||
#endif
|
||||
|
||||
void toneAC2(uint8_t pin1, uint8_t pin2, unsigned int frequency = 0, unsigned long length = 0, uint8_t background = false);
|
||||
void noToneAC2();
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user