forked from esp8266/Arduino
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTone.cpp
136 lines (112 loc) · 3.33 KB
/
Tone.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
Tone.cpp
A Tone Generator Library for the ESP8266
Copyright (c) 2016 Ben Pirt. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
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 "Arduino.h"
#include "pins_arduino.h"
#define AVAILABLE_TONE_PINS 1
const uint8_t tone_timers[] = { 1 };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255, };
static long toggle_counts[AVAILABLE_TONE_PINS] = { 0, };
#define T1INDEX 0
void t1IntHandler();
static int8_t toneBegin(uint8_t _pin) {
int8_t _index = -1;
// if we're already using the pin, reuse it.
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == _pin) {
return i;
}
}
// search for an unused timer.
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == 255) {
tone_pins[i] = _pin;
_index = i;
break;
}
}
return _index;
}
// frequency (in hertz) and duration (in milliseconds).
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) {
int8_t _index;
_index = toneBegin(_pin);
if (_index >= 0) {
// Set the pinMode as OUTPUT
pinMode(_pin, OUTPUT);
// Alternate handling of zero freqency to avoid divide by zero errors
if (frequency == 0)
{
noTone(_pin);
return;
}
// Calculate the toggle count
if (duration > 0) {
toggle_counts[_index] = 2 * frequency * duration / 1000;
} else {
toggle_counts[_index] = -1;
}
// set up the interrupt frequency
switch (tone_timers[_index]) {
case 0:
// Not currently supported
break;
case 1:
timer1_disable();
timer1_isr_init();
timer1_attachInterrupt(t1IntHandler);
timer1_enable(TIM_DIV1, TIM_EDGE, TIM_LOOP);
timer1_write((clockCyclesPerMicrosecond() * 500000) / frequency);
break;
}
}
}
void disableTimer(uint8_t _index) {
tone_pins[_index] = 255;
switch (tone_timers[_index]) {
case 0:
// Not currently supported
break;
case 1:
timer1_disable();
break;
}
}
void noTone(uint8_t _pin) {
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == _pin) {
tone_pins[i] = 255;
disableTimer(i);
break;
}
}
digitalWrite(_pin, LOW);
}
ICACHE_RAM_ATTR void t1IntHandler() {
if (toggle_counts[T1INDEX] != 0){
// toggle the pin
digitalWrite(tone_pins[T1INDEX], toggle_counts[T1INDEX] % 2);
toggle_counts[T1INDEX]--;
// handle the case of indefinite duration
if (toggle_counts[T1INDEX] < -2){
toggle_counts[T1INDEX] = -1;
}
}else{
disableTimer(T1INDEX);
digitalWrite(tone_pins[T1INDEX], LOW);
}
}