-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathBeepController.cpp
127 lines (104 loc) · 2.9 KB
/
BeepController.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
////////////////////////////////////////////////////
// State machine to control the beeper
////////////////////////////////////////////////////
#include <Arduino.h>
#include "BeepController.h"
// =================================================
// Setup my locals
// =================================================
CBeepController::CBeepController(int _pinOut, int _pinGnd)
{
m_freq = 0;
m_onTime = 0;
m_offTime = 0;
m_repeats = 0;
m_alarm = false;
m_beepOutPin = _pinOut;
m_beepGndPin = _pinGnd;
setState(beepIdle);
}
// =================================================
// Prepare to start beeping
// =================================================
void CBeepController::setup()
{
// Set my output pin modes
pinMode(m_beepOutPin, OUTPUT);
digitalWrite(m_beepOutPin, LOW);
// Set a ground for the speaker
if(m_beepGndPin > 0)
{
pinMode(m_beepGndPin, OUTPUT);
digitalWrite(m_beepGndPin, LOW);
}
// Stop the tone (if any)
noTone(m_beepOutPin);
// Terminate the alarm if any
m_alarm = false;
}
void CBeepController::setState(beepStateE _state)
{
m_state = _state;
tick();
}
// =================================================
// Tick beep cycle
// =================================================
void CBeepController::tick()
{
switch(m_state)
{
default:
case beepIdle:
break;
case beepStart:
tone(m_beepOutPin, m_freq, m_onTime); // Start the tone
m_beginningTime = millis();
setState(beepOn);
break;
case beepOn:
/* Following line relies on overflow behavior of unsigned long,
* and requires that m_onTime not be negative. */
if(millis() - m_beginningTime >= m_onTime) // Time expired?
{
/*^^^is noTone() below redundant with 3rd arg to tone() above? */
noTone(m_beepOutPin); // Stop the tone
m_beginningTime = millis();
setState(beepOff); // Go to off-time state
}
break;
case beepOff:
/* Following line relies on overflow behavior of unsigned long,
* and requires that m_offTime not be negative. */
if(millis() - m_beginningTime >= m_offTime) // Off time expired?
{
if(!m_alarm && (m_repeats > 0)) // Decrement the repeat counter?
--m_repeats; // Not if there is an alarm
if(m_repeats > 0) // Repeat the on-off cycle?
setState(beepStart); // Start the cycle again
else
setState(beepIdle); // All done repeating, so go to idle
}
break;
}
}
// =================================================
// Initiate beep cycle
// =================================================
void CBeepController::beep(int _freq, unsigned long _onTime, unsigned long _offTime, int _repeats)
{
// Hold alarm state regardless of other requests
if(m_alarm) return;
// Validate the value
if(_freq < 32) return;
if(_repeats < 1) return;
// Clear the old tone
noTone(m_beepOutPin);
// Remember the values
m_freq = _freq;
m_onTime = _onTime;
m_offTime = _offTime;
m_repeats = _repeats;
// Start the beeping
setState(beepStart);
}