Skip to content

Commit 71a1121

Browse files
Fixed issue with tone files not actually being added to the repo in a previous commit
1 parent 794d078 commit 71a1121

File tree

2 files changed

+222
-0
lines changed

2 files changed

+222
-0
lines changed

STM32F1/cores/maple/tone.cpp

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
///////////////////////////////////////////////////////////////////////
2+
//
3+
// tone(pin,frequency[,duration]) generate a tone on a given pin
4+
//
5+
// noTone(pin) switch off the tone on the pin
6+
//
7+
// setToneTimerChannel(timer,channel) force use of given timer/channel
8+
//
9+
///////////////////////////////////////////////////////////////////////
10+
11+
#include "Arduino.h"
12+
#include <HardwareTimer.h>
13+
14+
// define default timer and channel
15+
#ifndef TONE_TIMER
16+
#define TONE_TIMER 4
17+
#endif
18+
#ifndef TONE_CHANNEL
19+
#define TONE_CHANNEL 4
20+
#endif
21+
22+
#define PinTimer(pin) (PIN_MAP[pin].timer_device->clk_id-RCC_TIMER1+1)
23+
#define PinChannel(pin) (PIN_MAP[pin].timer_channel)
24+
25+
// if USE_PIN_TIMER is set, the PWM timer/channel is used for PWM pins
26+
#define USE_PIN_TIMER
27+
28+
// if USE_BSRR is set the tone pin will be written via the fast BSRR register
29+
// instead of using the slow digitalWrite() function in the interrupt handler
30+
#define USE_BSRR
31+
32+
// construct static timer array (
33+
HardwareTimer TTimer1(1), TTimer2(2), TTimer3(3), TTimer4(4);
34+
#ifdef STM32_HIGH_DENSITY
35+
HardwareTimer TTimer5(5), TTimer6(6), TTimer7(7), TTimer8(8);
36+
#endif
37+
HardwareTimer *TTimer[4] {
38+
&TTimer1,&TTimer2,&TTimer3,&TTimer4
39+
#ifdef STM32_HIGH_DENSITY
40+
,&TTimer5,&TTimer6,&TTimer7,&TTimer8
41+
#endif
42+
};
43+
44+
uint8_t tone_force_channel = 0; // forced timer channel
45+
uint8_t tone_force_ntimer = 0; // forced timer
46+
47+
HardwareTimer *tone_timer = TTimer[TONE_TIMER]; // timer used to generate frequency
48+
uint8_t tone_channel = TONE_CHANNEL; // timer channel used to generate frequency
49+
uint8_t tone_ntimer = TONE_TIMER; // timer used to generate frequency
50+
51+
bool tone_state = true; // last pin state for toggling
52+
short tone_pin = -1; // pin for outputting sound
53+
short tone_freq = 444; // tone frequency (0=pause)
54+
uint32_t tone_nhw = 0; // tone duration in number of half waves
55+
uint16_t tone_tcount = 0; // time between handler calls in 1/36 usec
56+
uint16_t tone_ncount = 0; // handler call between toggling
57+
uint16_t tone_n = 0; // remaining handler calls before toggling
58+
uint32_t tone_next = 0; // counter value of next interrupt
59+
60+
#ifdef USE_BSRR
61+
volatile uint32_t *tone_bsrr; // BSRR set register (lower 16 bits)
62+
uint32_t tone_smask=0; // BSRR set bitmask
63+
uint32_t tone_rmask=0; // BSRR reset bitmask
64+
#endif
65+
66+
67+
////////////////////////////////////////////////////////////////////////////////
68+
// timer hander for tone with no duration specified,
69+
// will keep going until noTone() is called
70+
void tone_handler_1(void) {
71+
tone_next += tone_tcount; // comparator value for next interrupt
72+
tone_timer->setCompare(tone_channel, tone_next); // and install it
73+
if(--tone_n == 0){
74+
tone_state = !tone_state; // toggle tone output
75+
76+
#ifdef USE_BSRR
77+
if(tone_state)
78+
*tone_bsrr = tone_smask;
79+
else
80+
*tone_bsrr = tone_rmask;
81+
#else
82+
digitalWrite(tone_pin,tone_state);// and output it
83+
#endif
84+
85+
tone_n = tone_ncount; // reset interrupt counter
86+
}
87+
}
88+
89+
////////////////////////////////////////////////////////////////////////////////
90+
// timer hander for tone with a specified duration,
91+
// will stop automatically when duration time is up.
92+
void tone_handler_2(void) {
93+
tone_next += tone_tcount;
94+
tone_timer->setCompare(tone_channel, tone_next);
95+
if(--tone_n == 0){
96+
if(tone_freq>0){ // toggle pin
97+
tone_state = !tone_state;
98+
#ifdef USE_BSRR
99+
if(tone_state)
100+
*tone_bsrr = tone_smask;
101+
else
102+
*tone_bsrr = tone_rmask;
103+
#else
104+
digitalWrite(tone_pin,tone_state);// and output it
105+
#endif
106+
}
107+
tone_n = tone_ncount;
108+
if(!--tone_nhw){ // check if tone duration has finished
109+
tone_timer->pause(); // disable timer
110+
pinMode(tone_pin, INPUT); // disable tone pin
111+
}
112+
}
113+
}
114+
115+
////////////////////////////////////////////////////////////////////////////////
116+
// play a tone on given pin with given frequency and optional duration in msec
117+
void tone(uint32_t pin, uint32_t freq, uint32_t duration) {
118+
tone_pin = pin;
119+
120+
#ifdef USE_PIN_TIMER
121+
// if the pin has a PWM timer/channel, use it (unless the timer/channel are forced)
122+
if(PinChannel(tone_pin) && !tone_force_channel){
123+
tone_channel = PinChannel(tone_pin);
124+
tone_ntimer = PinTimer(tone_pin);
125+
} else
126+
#endif
127+
{
128+
// set timer and channel to default resp values forced with setToneTimerChannel
129+
tone_ntimer = tone_force_channel?tone_force_ntimer:TONE_TIMER;
130+
tone_channel = tone_force_channel?tone_force_channel:TONE_CHANNEL;
131+
}
132+
133+
tone_timer = TTimer[tone_ntimer-1];
134+
tone_freq = freq;
135+
tone_nhw = 0;
136+
tone_next = 0;
137+
138+
tone_timer->pause();
139+
140+
if(freq > 0 || duration >0 ){
141+
uint32_t count = 18000000/freq; // timer counts per half wave
142+
tone_ncount = tone_n = (count>>16)+1; // number of 16-bit count chunk
143+
tone_tcount = count/tone_ncount; // size of count chunk
144+
if(duration > 0) // number of half waves to be generated
145+
tone_nhw = ((duration*(freq>0?freq:100))/1000)<<1;
146+
else // no duration specified, continuous sound until noTone() called
147+
tone_nhw = 0;
148+
149+
pinMode(tone_pin, PWM); // configure output pin
150+
pinMode(tone_pin, OUTPUT); // configure output pin
151+
152+
#ifdef USE_BSRR
153+
// Set up BSRR register values for fast ISR
154+
tone_bsrr = &((PIN_MAP[tone_pin].gpio_device)->regs->BSRR);
155+
tone_smask = (BIT(PIN_MAP[tone_pin].gpio_bit));
156+
tone_rmask = tone_smask<<16;
157+
#endif
158+
159+
// Set up an interrupt on given timer and channel
160+
tone_next = tone_tcount; // prepare channel compare register
161+
tone_timer->setMode(tone_channel,TIMER_OUTPUT_COMPARE);
162+
tone_timer->setCompare(tone_channel,tone_next);
163+
// attach corresponding handler routine
164+
tone_timer->attachInterrupt(tone_channel,tone_nhw?tone_handler_2:tone_handler_1);
165+
166+
// Refresh the tone timer
167+
tone_timer->refresh();
168+
169+
// Start the timer counting
170+
tone_timer->resume();
171+
172+
} else {
173+
174+
// detach handler routine
175+
tone_timer->detachInterrupt(tone_channel);
176+
// disactive pin by configuring it as input
177+
pinMode(tone_pin, INPUT);
178+
179+
}
180+
}
181+
182+
////////////////////////////////////////////////////////////////////////////////
183+
// disable tone on specified pin, if any
184+
void noTone(uint32_t pin){
185+
tone(pin,-1); // it's all handled in tone()
186+
}
187+
188+
////////////////////////////////////////////////////////////////////////////////
189+
// set timer and channel to some different value
190+
// must be called before calling tone() or after noTone() was called
191+
void setToneTimerChannel(uint8_t ntimer, uint8_t channel){
192+
tone_force_ntimer = ntimer;
193+
tone_force_channel = channel;
194+
}

STM32F1/cores/maple/tone.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
Copyright (c) 2015 Arduino LLC. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
#pragma once
20+
21+
#ifdef __cplusplus
22+
23+
#include "Arduino.h"
24+
25+
void tone(uint32_t _pin, uint32_t frequency, uint32_t duration = 0);
26+
void noTone(uint32_t _pin);
27+
28+
#endif

0 commit comments

Comments
 (0)