Fixed issue with tone files not actually being added to the repo in a previous commit
This commit is contained in:
parent
794d078de0
commit
71a1121c9f
|
@ -0,0 +1,194 @@
|
|||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// tone(pin,frequency[,duration]) generate a tone on a given pin
|
||||
//
|
||||
// noTone(pin) switch off the tone on the pin
|
||||
//
|
||||
// setToneTimerChannel(timer,channel) force use of given timer/channel
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <HardwareTimer.h>
|
||||
|
||||
// define default timer and channel
|
||||
#ifndef TONE_TIMER
|
||||
#define TONE_TIMER 4
|
||||
#endif
|
||||
#ifndef TONE_CHANNEL
|
||||
#define TONE_CHANNEL 4
|
||||
#endif
|
||||
|
||||
#define PinTimer(pin) (PIN_MAP[pin].timer_device->clk_id-RCC_TIMER1+1)
|
||||
#define PinChannel(pin) (PIN_MAP[pin].timer_channel)
|
||||
|
||||
// if USE_PIN_TIMER is set, the PWM timer/channel is used for PWM pins
|
||||
#define USE_PIN_TIMER
|
||||
|
||||
// if USE_BSRR is set the tone pin will be written via the fast BSRR register
|
||||
// instead of using the slow digitalWrite() function in the interrupt handler
|
||||
#define USE_BSRR
|
||||
|
||||
// construct static timer array (
|
||||
HardwareTimer TTimer1(1), TTimer2(2), TTimer3(3), TTimer4(4);
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
HardwareTimer TTimer5(5), TTimer6(6), TTimer7(7), TTimer8(8);
|
||||
#endif
|
||||
HardwareTimer *TTimer[4] {
|
||||
&TTimer1,&TTimer2,&TTimer3,&TTimer4
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
,&TTimer5,&TTimer6,&TTimer7,&TTimer8
|
||||
#endif
|
||||
};
|
||||
|
||||
uint8_t tone_force_channel = 0; // forced timer channel
|
||||
uint8_t tone_force_ntimer = 0; // forced timer
|
||||
|
||||
HardwareTimer *tone_timer = TTimer[TONE_TIMER]; // timer used to generate frequency
|
||||
uint8_t tone_channel = TONE_CHANNEL; // timer channel used to generate frequency
|
||||
uint8_t tone_ntimer = TONE_TIMER; // timer used to generate frequency
|
||||
|
||||
bool tone_state = true; // last pin state for toggling
|
||||
short tone_pin = -1; // pin for outputting sound
|
||||
short tone_freq = 444; // tone frequency (0=pause)
|
||||
uint32_t tone_nhw = 0; // tone duration in number of half waves
|
||||
uint16_t tone_tcount = 0; // time between handler calls in 1/36 usec
|
||||
uint16_t tone_ncount = 0; // handler call between toggling
|
||||
uint16_t tone_n = 0; // remaining handler calls before toggling
|
||||
uint32_t tone_next = 0; // counter value of next interrupt
|
||||
|
||||
#ifdef USE_BSRR
|
||||
volatile uint32_t *tone_bsrr; // BSRR set register (lower 16 bits)
|
||||
uint32_t tone_smask=0; // BSRR set bitmask
|
||||
uint32_t tone_rmask=0; // BSRR reset bitmask
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// timer hander for tone with no duration specified,
|
||||
// will keep going until noTone() is called
|
||||
void tone_handler_1(void) {
|
||||
tone_next += tone_tcount; // comparator value for next interrupt
|
||||
tone_timer->setCompare(tone_channel, tone_next); // and install it
|
||||
if(--tone_n == 0){
|
||||
tone_state = !tone_state; // toggle tone output
|
||||
|
||||
#ifdef USE_BSRR
|
||||
if(tone_state)
|
||||
*tone_bsrr = tone_smask;
|
||||
else
|
||||
*tone_bsrr = tone_rmask;
|
||||
#else
|
||||
digitalWrite(tone_pin,tone_state);// and output it
|
||||
#endif
|
||||
|
||||
tone_n = tone_ncount; // reset interrupt counter
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// timer hander for tone with a specified duration,
|
||||
// will stop automatically when duration time is up.
|
||||
void tone_handler_2(void) {
|
||||
tone_next += tone_tcount;
|
||||
tone_timer->setCompare(tone_channel, tone_next);
|
||||
if(--tone_n == 0){
|
||||
if(tone_freq>0){ // toggle pin
|
||||
tone_state = !tone_state;
|
||||
#ifdef USE_BSRR
|
||||
if(tone_state)
|
||||
*tone_bsrr = tone_smask;
|
||||
else
|
||||
*tone_bsrr = tone_rmask;
|
||||
#else
|
||||
digitalWrite(tone_pin,tone_state);// and output it
|
||||
#endif
|
||||
}
|
||||
tone_n = tone_ncount;
|
||||
if(!--tone_nhw){ // check if tone duration has finished
|
||||
tone_timer->pause(); // disable timer
|
||||
pinMode(tone_pin, INPUT); // disable tone pin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// play a tone on given pin with given frequency and optional duration in msec
|
||||
void tone(uint32_t pin, uint32_t freq, uint32_t duration) {
|
||||
tone_pin = pin;
|
||||
|
||||
#ifdef USE_PIN_TIMER
|
||||
// if the pin has a PWM timer/channel, use it (unless the timer/channel are forced)
|
||||
if(PinChannel(tone_pin) && !tone_force_channel){
|
||||
tone_channel = PinChannel(tone_pin);
|
||||
tone_ntimer = PinTimer(tone_pin);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// set timer and channel to default resp values forced with setToneTimerChannel
|
||||
tone_ntimer = tone_force_channel?tone_force_ntimer:TONE_TIMER;
|
||||
tone_channel = tone_force_channel?tone_force_channel:TONE_CHANNEL;
|
||||
}
|
||||
|
||||
tone_timer = TTimer[tone_ntimer-1];
|
||||
tone_freq = freq;
|
||||
tone_nhw = 0;
|
||||
tone_next = 0;
|
||||
|
||||
tone_timer->pause();
|
||||
|
||||
if(freq > 0 || duration >0 ){
|
||||
uint32_t count = 18000000/freq; // timer counts per half wave
|
||||
tone_ncount = tone_n = (count>>16)+1; // number of 16-bit count chunk
|
||||
tone_tcount = count/tone_ncount; // size of count chunk
|
||||
if(duration > 0) // number of half waves to be generated
|
||||
tone_nhw = ((duration*(freq>0?freq:100))/1000)<<1;
|
||||
else // no duration specified, continuous sound until noTone() called
|
||||
tone_nhw = 0;
|
||||
|
||||
pinMode(tone_pin, PWM); // configure output pin
|
||||
pinMode(tone_pin, OUTPUT); // configure output pin
|
||||
|
||||
#ifdef USE_BSRR
|
||||
// Set up BSRR register values for fast ISR
|
||||
tone_bsrr = &((PIN_MAP[tone_pin].gpio_device)->regs->BSRR);
|
||||
tone_smask = (BIT(PIN_MAP[tone_pin].gpio_bit));
|
||||
tone_rmask = tone_smask<<16;
|
||||
#endif
|
||||
|
||||
// Set up an interrupt on given timer and channel
|
||||
tone_next = tone_tcount; // prepare channel compare register
|
||||
tone_timer->setMode(tone_channel,TIMER_OUTPUT_COMPARE);
|
||||
tone_timer->setCompare(tone_channel,tone_next);
|
||||
// attach corresponding handler routine
|
||||
tone_timer->attachInterrupt(tone_channel,tone_nhw?tone_handler_2:tone_handler_1);
|
||||
|
||||
// Refresh the tone timer
|
||||
tone_timer->refresh();
|
||||
|
||||
// Start the timer counting
|
||||
tone_timer->resume();
|
||||
|
||||
} else {
|
||||
|
||||
// detach handler routine
|
||||
tone_timer->detachInterrupt(tone_channel);
|
||||
// disactive pin by configuring it as input
|
||||
pinMode(tone_pin, INPUT);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// disable tone on specified pin, if any
|
||||
void noTone(uint32_t pin){
|
||||
tone(pin,-1); // it's all handled in tone()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// set timer and channel to some different value
|
||||
// must be called before calling tone() or after noTone() was called
|
||||
void setToneTimerChannel(uint8_t ntimer, uint8_t channel){
|
||||
tone_force_ntimer = ntimer;
|
||||
tone_force_channel = channel;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
Copyright (c) 2015 Arduino LLC. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
void tone(uint32_t _pin, uint32_t frequency, uint32_t duration = 0);
|
||||
void noTone(uint32_t _pin);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue