5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
23 audioQueue::audioQueue()
34 // heartbeat is responsibile for issueing the audio tones and general square waves
35 // it is essentially the life of the class.
36 // it is called every 10ms
37 void audioQueue::heartbeat()
42 if (toneTimeLeft
> 0) {
43 if (toneFreq
== 0) { //pause only events
49 OCR4A
= (5000 / toneFreq
); // sticking with old values approx 20(abs. min) to 90, 60 being the default tone(?).
53 toneFreq
+= toneFreqIncr
;
55 toneTimeLeft
--; //time gets counted down
60 tonePause
--; //time gets counted down
62 else if (t_queueRidx
!= t_queueWidx
) {
63 toneFreq
= queueToneFreq
[t_queueRidx
];
64 toneTimeLeft
= queueToneLength
[t_queueRidx
];
65 toneFreqIncr
= queueToneFreqIncr
[t_queueRidx
];
66 tonePause
= queueTonePause
[t_queueRidx
];
67 if (!queueToneRepeat
[t_queueRidx
]--) {
68 t_queueRidx
= (t_queueRidx
+ 1) & (AUDIO_QUEUE_LENGTH
-1);
72 if (tone2TimeLeft
> 0) {
75 OCR4A
= (5000 / tone2Freq
); // sticking with old values approx 20(abs. min) to 90, 60 being the default tone(?).
81 tone2TimeLeft
--; //time gets counted down
88 #endif // defined(SIMU)
91 inline uint8_t audioQueue::getToneLength(uint8_t tLen
)
93 uint8_t result
= tLen
; // default
94 if (g_eeGeneral
.beepLength
< 0) {
95 result
/= (1-g_eeGeneral
.beepLength
);
97 if (g_eeGeneral
.beepLength
> 0) {
98 result
*= (1+g_eeGeneral
.beepLength
);
103 void audioQueue::pause(uint8_t tLen
)
105 play(0, tLen
, 5); // a pause
108 void audioQueue::play(uint8_t tFreq
, uint8_t tLen
, uint8_t tPause
, uint8_t tFlags
)
110 if (tFlags
& PLAY_BACKGROUND
) {
112 tone2TimeLeft
= tLen
;
115 int8_t tFreqIncr
= (tFlags
>> 6);
116 if (tFreqIncr
== 3) tFreqIncr
= -1;
118 tFreq
+= g_eeGeneral
.speakerPitch
+ BEEP_OFFSET
; // add pitch compensator
119 tLen
= getToneLength(tLen
);
121 if ((tFlags
& PLAY_NOW
) || (!busy() && empty())) {
125 toneFreqIncr
= tFreqIncr
;
126 t_queueWidx
= t_queueRidx
;
134 uint8_t next_queueWidx
= (t_queueWidx
+ 1) & (AUDIO_QUEUE_LENGTH
-1);
135 if (next_queueWidx
!= t_queueRidx
) {
136 queueToneFreq
[t_queueWidx
] = tFreq
;
137 queueToneLength
[t_queueWidx
] = tLen
;
138 queueTonePause
[t_queueWidx
] = tPause
;
139 queueToneRepeat
[t_queueWidx
] = tFlags
- 1;
140 queueToneFreqIncr
[t_queueWidx
] = tFreqIncr
;
141 t_queueWidx
= next_queueWidx
;
147 void audioQueue::event(uint8_t e
)
150 haptic
.event(e
); //do this before audio to help sync timings
153 if (e
<= AU_ERROR
|| (e
>= AU_WARNING1
&& e
< AU_SPECIAL_SOUND_FIRST
)) {
154 if (g_eeGeneral
.alarmsFlash
) {
155 flashCounter
= FLASH_DURATION
;
159 if (g_eeGeneral
.beepMode
>= e_mode_nokeys
|| (g_eeGeneral
.beepMode
>= e_mode_alarms
&& e
<= AU_ERROR
)) {
160 if (e
< AU_SPECIAL_SOUND_FIRST
|| empty()) {
161 // TODO when VOICE enable some cases here are not needed!
164 case AU_TX_BATTERY_LOW
:
166 play(60, 20, 3, PLAY_REPEAT(2)|PLAY_INCREMENT(1));
167 play(80, 20, 3, PLAY_REPEAT(2)|PLAY_INCREMENT(-1));
171 case AU_SPECIAL_SOUND_RING
:
172 play(BEEP_DEFAULT_FREQ
+25, 5, 2, PLAY_REPEAT(10));
173 play(BEEP_DEFAULT_FREQ
+25, 5, 10, PLAY_REPEAT(1));
174 play(BEEP_DEFAULT_FREQ
+25, 5, 2, PLAY_REPEAT(10));
176 case AU_SPECIAL_SOUND_SCIFI
:
177 play(80, 10, 3, PLAY_REPEAT(2)|PLAY_INCREMENT(-1));
178 play(60, 10, 3, PLAY_REPEAT(2)|PLAY_INCREMENT(1));
181 case AU_SPECIAL_SOUND_ROBOT
:
182 play(70, 5, 1, PLAY_REPEAT(1));
183 play(50, 15, 2, PLAY_REPEAT(1));
184 play(80, 15, 2, PLAY_REPEAT(1));
186 case AU_SPECIAL_SOUND_CHIRP
:
187 play(BEEP_DEFAULT_FREQ
+40, 5, 1, PLAY_REPEAT(2));
188 play(BEEP_DEFAULT_FREQ
+54, 5, 1, PLAY_REPEAT(3));
190 case AU_SPECIAL_SOUND_TADA
:
193 play(110, 3, 4, PLAY_REPEAT(2));
195 case AU_SPECIAL_SOUND_CRICKET
:
196 play(80, 5, 10, PLAY_REPEAT(3));
197 play(80, 5, 20, PLAY_REPEAT(1));
198 play(80, 5, 10, PLAY_REPEAT(3));
200 case AU_SPECIAL_SOUND_ALARMC
:
201 play(50, 4, 10, PLAY_REPEAT(2));
202 play(70, 8, 20, PLAY_REPEAT(1));
203 play(50, 8, 10, PLAY_REPEAT(2));
204 play(70, 4, 20, PLAY_REPEAT(1));
208 static const pm_uint8_t singleSounds
[] PROGMEM
= {
209 70, 10, 2, PLAY_REPEAT(2)|PLAY_NOW
, // INACTIVITY
210 BEEP_DEFAULT_FREQ
, 40, 1, PLAY_NOW
, // ERROR
211 BEEP_DEFAULT_FREQ
, 10, 1, PLAY_NOW
, // WARNING1
212 BEEP_DEFAULT_FREQ
, 20, 1, PLAY_NOW
, // WARNING2
213 BEEP_DEFAULT_FREQ
, 30, 1, PLAY_NOW
, // WARNING3
214 60, 10, 2, PLAY_NOW
, // TRIM_MIDDLE
215 BEEP_DEFAULT_FREQ
+ 50, 10, 1, PLAY_NOW
, // POT_STICK_MIDDLE
216 BEEP_DEFAULT_FREQ
+ 50, 6, 0, 0, // MIX_WARNING_1
217 BEEP_DEFAULT_FREQ
+ 52, 6, 3, PLAY_REPEAT(1), // MIX_WARNING_2
218 BEEP_DEFAULT_FREQ
+ 54, 6, 3, PLAY_REPEAT(2), // MIX_WARNING_3
219 BEEP_DEFAULT_FREQ
, 10, 1, 0, // FRSKY_BEEP1
220 BEEP_DEFAULT_FREQ
, 20, 1, 0, // FRSKY_BEEP2
221 BEEP_DEFAULT_FREQ
, 30, 1, 0, // FRSKY_BEEP3
222 BEEP_DEFAULT_FREQ
+20, 15, 5, PLAY_REPEAT(2), // FRSKY_WARN1
223 BEEP_DEFAULT_FREQ
+30, 15, 5, PLAY_REPEAT(2), // FRSKY_WARN2
224 BEEP_DEFAULT_FREQ
+30, 10, 2, PLAY_REPEAT(2)|PLAY_INCREMENT(2), // FRSKY_CHEEP
225 BEEP_DEFAULT_FREQ
+50, 5, 10, PLAY_REPEAT(10), // FRSKY_RATATA
226 BEEP_DEFAULT_FREQ
+50, 5, 50, PLAY_REPEAT(2), // FRSKY_TICK
227 10, 20, 5, PLAY_REPEAT(2)|PLAY_INCREMENT(1), // FRSKY_SIREN
230 const pm_uint8_t
*ptr
= &singleSounds
[(e
-AU_INACTIVITY
)<<2];
231 uint8_t tFreq
= pgm_read_byte(ptr
++);
232 uint8_t tLen
= pgm_read_byte(ptr
++);
233 uint8_t tPause
= pgm_read_byte(ptr
++);
234 uint8_t tFlags
= pgm_read_byte(ptr
);
235 play(tFreq
, tLen
, tPause
, tFlags
);
243 void audioDefevent(uint8_t e
)
251 if (g_eeGeneral
.beepMode
== e_mode_all
) {
252 audio
.play(BEEP_DEFAULT_FREQ
, 10, 1, PLAY_NOW
);
259 if (g_eeGeneral
.hapticMode
== e_mode_all
) {
260 haptic
.play(5, 0, PLAY_NOW
);
265 void audioTrimPress(int16_t value
)
267 if (g_eeGeneral
.beepMode
>= e_mode_nokeys
) {
269 value
= limit
<int16_t>(TRIM_MIN
, value
, TRIM_MAX
);
272 audio
.play(value
, 6, 1, PLAY_NOW
);
280 void audioTimerCountdown(uint8_t timer
, int value
)
286 #if defined(CPUM2560) && (defined(VOICE_WTV20) || defined(VOICE_JQ6500))
287 else if (g_model
.timers
[timer
].countdownBeep
== COUNTDOWN_VOICE
) {
288 if (value
>= 0 && value
<= TIMER_COUNTDOWN_START(timer
)) {
289 playNumber(value
, 0, 0);
291 else if (value
== 30 || value
== 20) {
298 else if (g_model
.timers
[timer
].countdownBeep
== COUNTDOWN_HAPTIC
) {
300 haptic
.play(15, 3, PLAY_NOW
);
302 else if (value
> 0 && value
<= 10) {
303 haptic
.play(5, 0, PLAY_NOW
);
305 else if (value
== 30) {
306 haptic
.play(10, 3, PLAY_REPEAT(2) | PLAY_NOW
);
308 else if (value
== 20) {
309 haptic
.play(10, 3, PLAY_REPEAT(1) | PLAY_NOW
);
316 audio
.play(BEEP_DEFAULT_FREQ
+ 50, 30, 3, PLAY_NOW
);
318 else if (value
> 0 && value
<= 10) {
319 audio
.play(BEEP_DEFAULT_FREQ
+ 50, 15, 3, PLAY_NOW
);
321 else if (value
== 30) {
322 audio
.play(BEEP_DEFAULT_FREQ
+ 50, 15, 3, PLAY_REPEAT(2) | PLAY_NOW
);
324 else if (value
== 20) {
325 audio
.play(BEEP_DEFAULT_FREQ
+ 50, 15, 3, PLAY_REPEAT(1) | PLAY_NOW
);