mirror of
https://github.com/opentx/opentx.git
synced 2025-07-21 15:25:17 +03:00
Split Haptic from Audio
Vario from Max added Tests needed on all boards!
This commit is contained in:
parent
b0ee619d0a
commit
6afc680d93
20 changed files with 1123 additions and 506 deletions
11
src/Makefile
11
src/Makefile
|
@ -292,19 +292,18 @@ ifeq ($(PCB), ARM)
|
|||
# ersky9x/ff.c ersky9x/diskio_sam3s.c ersky9x/Media.c ersky9x/ccsbcs.c ersky9x/sdcard.c ersky9x/MEDSdcard.c
|
||||
EEPROMSRC = eeprom_arm.cpp
|
||||
PULSESSRC = pulses_arm.cpp
|
||||
CPPSRC += audio.cpp
|
||||
CPPSRC += ersky9x/sound.cpp
|
||||
CPPSRC += ersky9x/audio.cpp ersky9x/sound.cpp haptic.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(PCB), V4)
|
||||
# V4 PCB, so ...
|
||||
OPT = 2
|
||||
CPPDEFS += -DPCBV4 -DAUDIO -DHAPTIC -DROTARY_ENCODERS
|
||||
EXTRAINCDIRS += gruvin9x
|
||||
EXTRAINCDIRS += gruvin9x stock
|
||||
BOARDSRC += board_gruvin9x.cpp
|
||||
EEPROMSRC = eeprom_avr.cpp
|
||||
PULSESSRC = pulses_avr.cpp
|
||||
CPPSRC += audio.cpp
|
||||
CPPSRC += stock/audio.cpp haptic.cpp
|
||||
CPPSRC += gruvin9x/gtime.cpp
|
||||
CPPSRC += gruvin9x/rtc.cpp
|
||||
CPPSRC += gruvin9x/ff.cpp
|
||||
|
@ -336,6 +335,7 @@ endif
|
|||
ifeq ($(PCB), STD)
|
||||
# STD PCB, so ...
|
||||
OPT = s
|
||||
EXTRAINCDIRS += stock
|
||||
CPPDEFS += -DPCBSTD
|
||||
BOARDSRC = board_stock.cpp
|
||||
EEPROMSRC = eeprom_avr.cpp
|
||||
|
@ -343,13 +343,14 @@ ifeq ($(PCB), STD)
|
|||
|
||||
ifeq ($(AUDIO), YES)
|
||||
CPPDEFS += -DAUDIO
|
||||
CPPSRC += audio.cpp
|
||||
CPPSRC += stock/audio.cpp
|
||||
else
|
||||
CPPSRC += beeper.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(HAPTIC), YES)
|
||||
CPPDEFS += -DHAPTIC
|
||||
CPPSRC += haptic.cpp
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
381
src/audio.cpp
381
src/audio.cpp
|
@ -1,381 +0,0 @@
|
|||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "open9x.h"
|
||||
|
||||
audioQueue::audioQueue()
|
||||
{
|
||||
toneTimeLeft = 0;
|
||||
tonePause = 0;
|
||||
|
||||
t_queueRidx = 0;
|
||||
t_queueWidx = 0;
|
||||
|
||||
#ifdef HAPTIC
|
||||
hapticTick = 0;
|
||||
hapticSpinUpTime = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool audioQueue::freeslots(uint8_t slots)
|
||||
{
|
||||
return AUDIO_QUEUE_LENGTH - ((t_queueWidx + AUDIO_QUEUE_LENGTH - t_queueRidx) % AUDIO_QUEUE_LENGTH) >= slots;
|
||||
}
|
||||
#endif
|
||||
|
||||
// heartbeat is responsibile for issueing the audio tones and general square waves
|
||||
// it is essentially the life of the class.
|
||||
// it is called every 10ms
|
||||
void audioQueue::heartbeat()
|
||||
{
|
||||
#if defined(SIMU)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if defined(PCBARM)
|
||||
if (toneTimeLeft) {
|
||||
|
||||
if (queueTone(toneFreq * 61 / 2, toneTimeLeft * 10,
|
||||
toneFreqIncr * 61 / 2)) {
|
||||
toneTimeLeft = 0; //time gets counted down
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAPTIC)
|
||||
|
||||
if (toneHaptic) {
|
||||
hapticOn((g_eeGeneral.hapticStrength * 2) * 10);
|
||||
hapticSpinUpTime = HAPTIC_SPINUP; //min time haptic runs for. Might be worth a config option in system prefs to allow user to set to suit motor?
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
||||
#if defined(HAPTIC)
|
||||
if(hapticSpinUpTime > 0){
|
||||
hapticSpinUpTime--;
|
||||
} else {
|
||||
hapticOff();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tonePause) {
|
||||
if (queueTone(0, tonePause * 10, 0)) {
|
||||
tonePause = 0; //time gets counted down
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (t_queueRidx != t_queueWidx) {
|
||||
toneFreq = queueToneFreq[t_queueRidx];
|
||||
toneTimeLeft = queueToneLength[t_queueRidx];
|
||||
toneFreqIncr = queueToneFreqIncr[t_queueRidx];
|
||||
tonePause = queueTonePause[t_queueRidx];
|
||||
toneHaptic = queueToneHaptic[t_queueRidx];
|
||||
hapticTick = 0;
|
||||
if (!queueToneRepeat[t_queueRidx]--) {
|
||||
t_queueRidx = (t_queueRidx + 1) % AUDIO_QUEUE_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (toneTimeLeft > 0) {
|
||||
#if defined(PCBV4)
|
||||
if (toneFreq) {
|
||||
OCR0A = (5000 / toneFreq); // sticking with old values approx 20(abs. min) to 90, 60 being the default tone(?).
|
||||
SPEAKER_ON;
|
||||
}
|
||||
#endif
|
||||
toneTimeLeft--; //time gets counted down
|
||||
toneFreq += toneFreqIncr;
|
||||
|
||||
#if defined(HAPTIC)
|
||||
if (toneHaptic){
|
||||
if (hapticTick-- > 0) {
|
||||
HAPTIC_ON; // haptic output 'high'
|
||||
}
|
||||
else {
|
||||
HAPTIC_OFF; // haptic output 'low'
|
||||
hapticTick = g_eeGeneral.hapticStrength;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
SPEAKER_OFF;
|
||||
HAPTIC_OFF;
|
||||
|
||||
if (tonePause > 0) {
|
||||
tonePause--;
|
||||
}
|
||||
else if (t_queueRidx != t_queueWidx) {
|
||||
toneFreq = queueToneFreq[t_queueRidx];
|
||||
toneTimeLeft = queueToneLength[t_queueRidx];
|
||||
toneFreqIncr = queueToneFreqIncr[t_queueRidx];
|
||||
tonePause = queueTonePause[t_queueRidx];
|
||||
#if defined(HAPTIC)
|
||||
toneHaptic = queueToneHaptic[t_queueRidx];
|
||||
#endif
|
||||
if (!queueToneRepeat[t_queueRidx]--) {
|
||||
t_queueRidx = (t_queueRidx + 1) % AUDIO_QUEUE_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint8_t audioQueue::getToneLength(uint8_t tLen)
|
||||
{
|
||||
uint8_t result = tLen; // default
|
||||
if (g_eeGeneral.beeperLength < 0) {
|
||||
result /= (1-g_eeGeneral.beeperLength);
|
||||
}
|
||||
if (g_eeGeneral.beeperLength > 0) {
|
||||
result *= (1+g_eeGeneral.beeperLength);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool s_beeper;
|
||||
#if defined(HAPTIC)
|
||||
bool s_haptic;
|
||||
#endif
|
||||
|
||||
void audioQueue::playNow(uint8_t tFreq, uint8_t tLen, uint8_t tPause,
|
||||
uint8_t tRepeat, uint8_t tHaptic, int8_t tFreqIncr)
|
||||
{
|
||||
toneFreq = ((s_beeper && tFreq) ? tFreq + g_eeGeneral.speakerPitch + BEEP_OFFSET : 0); // add pitch compensator
|
||||
toneTimeLeft = getToneLength(tLen);
|
||||
tonePause = tPause;
|
||||
#if defined(HAPTIC)
|
||||
toneHaptic = s_haptic ? tHaptic : 0;
|
||||
#endif
|
||||
toneFreqIncr = tFreqIncr;
|
||||
t_queueWidx = t_queueRidx;
|
||||
|
||||
if (tRepeat) {
|
||||
playASAP(tFreq, tLen, tPause, tRepeat-1, tHaptic, tFreqIncr);
|
||||
}
|
||||
}
|
||||
|
||||
void audioQueue::playASAP(uint8_t tFreq, uint8_t tLen, uint8_t tPause,
|
||||
uint8_t tRepeat, uint8_t tHaptic, int8_t tFreqIncr)
|
||||
{
|
||||
uint8_t next_queueWidx = (t_queueWidx + 1) % AUDIO_QUEUE_LENGTH;
|
||||
if (next_queueWidx != t_queueRidx) {
|
||||
queueToneFreq[t_queueWidx] = ((s_beeper && tFreq) ? tFreq + g_eeGeneral.speakerPitch + BEEP_OFFSET : 0); // add pitch compensator
|
||||
queueToneLength[t_queueWidx] = getToneLength(tLen);
|
||||
queueTonePause[t_queueWidx] = tPause;
|
||||
#if defined(HAPTIC)
|
||||
queueToneHaptic[t_queueWidx] = s_haptic ? tHaptic : 0;
|
||||
#endif
|
||||
queueToneRepeat[t_queueWidx] = tRepeat;
|
||||
queueToneFreqIncr[t_queueWidx] = tFreqIncr;
|
||||
t_queueWidx = next_queueWidx;
|
||||
}
|
||||
}
|
||||
|
||||
void audioQueue::event(uint8_t e, uint8_t f)
|
||||
{
|
||||
s_beeper = (g_eeGeneral.beeperMode>0 || (g_eeGeneral.beeperMode==0 && e>=AU_WARNING1) || (g_eeGeneral.beeperMode>=-1 && e<=AU_ERROR));
|
||||
#if defined(HAPTIC)
|
||||
s_haptic = (g_eeGeneral.hapticMode>0 || (g_eeGeneral.hapticMode==0 && e>=AU_WARNING1) || (g_eeGeneral.hapticMode>=-1 && e<=AU_ERROR));
|
||||
#endif
|
||||
if (g_eeGeneral.flashBeep && (e <= AU_ERROR || e >= AU_WARNING1)) g_LightOffCounter = FLASH_DURATION; // we got an event do we need to flash the display ?
|
||||
if (e < AU_FRSKY_FIRST || empty()) {
|
||||
switch (e) {
|
||||
// inactivity timer alert
|
||||
case AU_INACTIVITY:
|
||||
playNow(70, 10, 2, 2);
|
||||
break;
|
||||
// low battery in tx
|
||||
case AU_TX_BATTERY_LOW:
|
||||
if (empty()) {
|
||||
playASAP(60, 20, 3, 2, 0, 1);
|
||||
playASAP(80, 20, 3, 2, 1, -1);
|
||||
}
|
||||
break;
|
||||
// error
|
||||
case AU_ERROR:
|
||||
playNow(BEEP_DEFAULT_FREQ, 40, 1, 0, 1);
|
||||
break;
|
||||
// keypad up (seems to be used when going left/right through system menu options. 0-100 scales etc)
|
||||
case AU_KEYPAD_UP:
|
||||
playNow(BEEP_KEY_UP_FREQ, 10, 1, 0, 1);
|
||||
break;
|
||||
// keypad down (seems to be used when going left/right through system menu options. 0-100 scales etc)
|
||||
case AU_KEYPAD_DOWN:
|
||||
playNow(BEEP_KEY_DOWN_FREQ, 10, 1, 0, 1);
|
||||
break;
|
||||
// menu display (also used by a few generic beeps)
|
||||
case AU_MENUS:
|
||||
playNow(BEEP_DEFAULT_FREQ, 10, 2, 0, 1);
|
||||
break;
|
||||
// trim move
|
||||
case AU_TRIM_MOVE:
|
||||
playNow(f, 6, 1);
|
||||
break;
|
||||
// trim center
|
||||
case AU_TRIM_MIDDLE:
|
||||
playNow(BEEP_DEFAULT_FREQ, 10, 2, 0, 1);
|
||||
break;
|
||||
// warning one
|
||||
case AU_WARNING1:
|
||||
playNow(BEEP_DEFAULT_FREQ, 10, 1, 0, 1);
|
||||
break;
|
||||
// warning two
|
||||
case AU_WARNING2:
|
||||
playNow(BEEP_DEFAULT_FREQ, 20, 1, 0, 1);
|
||||
break;
|
||||
// warning three
|
||||
case AU_WARNING3:
|
||||
playNow(BEEP_DEFAULT_FREQ, 30, 1, 0, 1);
|
||||
break;
|
||||
// startup tune
|
||||
case AU_TADA:
|
||||
playASAP(50, 10, 5);
|
||||
playASAP(90, 10, 5);
|
||||
playASAP(110, 5, 4, 2);
|
||||
break;
|
||||
// pot/stick center
|
||||
case AU_POT_STICK_MIDDLE:
|
||||
playNow(BEEP_DEFAULT_FREQ + 50, 10, 1, 0, 0);
|
||||
break;
|
||||
// mix warning 1
|
||||
case AU_MIX_WARNING_1:
|
||||
playNow(BEEP_DEFAULT_FREQ + 50, 6, 0, 0, 1);
|
||||
break;
|
||||
// mix warning 2
|
||||
case AU_MIX_WARNING_2:
|
||||
playNow(BEEP_DEFAULT_FREQ + 52, 6, 0, 0, 1);
|
||||
break;
|
||||
// mix warning 3
|
||||
case AU_MIX_WARNING_3:
|
||||
playNow(BEEP_DEFAULT_FREQ + 54, 6, 0, 0, 1);
|
||||
break;
|
||||
// time 30 seconds left
|
||||
case AU_TIMER_30:
|
||||
playNow(BEEP_DEFAULT_FREQ + 50, 15, 3, 2, 1);
|
||||
break;
|
||||
// time 20 seconds left
|
||||
case AU_TIMER_20:
|
||||
playNow(BEEP_DEFAULT_FREQ + 50, 15, 3, 1, 1);
|
||||
break;
|
||||
// time 10 seconds left
|
||||
case AU_TIMER_10:
|
||||
playNow(BEEP_DEFAULT_FREQ + 50, 15, 3, 0, 1);
|
||||
break;
|
||||
// time <3 seconds left
|
||||
case AU_TIMER_LT3:
|
||||
playNow(BEEP_DEFAULT_FREQ, 20, 25, 1, 1);
|
||||
break;
|
||||
case AU_FRSKY_WARN1:
|
||||
playASAP(BEEP_DEFAULT_FREQ+20,15,5,2,1);
|
||||
break;
|
||||
case AU_FRSKY_WARN2:
|
||||
playASAP(BEEP_DEFAULT_FREQ+30,15,5,2,1);
|
||||
break;
|
||||
case AU_FRSKY_CHEEP:
|
||||
playASAP(BEEP_DEFAULT_FREQ+30,10,2,2,1,2);
|
||||
break;
|
||||
case AU_FRSKY_RING:
|
||||
playASAP(BEEP_DEFAULT_FREQ+25,5,2,10,1);
|
||||
playASAP(BEEP_DEFAULT_FREQ+25,5,10,1,1);
|
||||
playASAP(BEEP_DEFAULT_FREQ+25,5,2,10,1);
|
||||
break;
|
||||
case AU_FRSKY_SCIFI:
|
||||
playASAP(80,10,3,2,0,-1);
|
||||
playASAP(60,10,3,2,0,1);
|
||||
playASAP(70,10,1,0,2);
|
||||
break;
|
||||
case AU_FRSKY_ROBOT:
|
||||
playASAP(70,5,1,1,1);
|
||||
playASAP(50,15,2,1,1);
|
||||
playASAP(80,15,2,1,1);
|
||||
break;
|
||||
case AU_FRSKY_CHIRP:
|
||||
playASAP(BEEP_DEFAULT_FREQ+40,5,1,2,1);
|
||||
playASAP(BEEP_DEFAULT_FREQ+54,5,1,3,1);
|
||||
break;
|
||||
case AU_FRSKY_TADA:
|
||||
playASAP(50,5,5);
|
||||
playASAP(90,5,5);
|
||||
playASAP(110,3,4,2);
|
||||
break;
|
||||
case AU_FRSKY_CRICKET:
|
||||
playASAP(80,5,10,3,1);
|
||||
playASAP(80,5,20,1,1);
|
||||
playASAP(80,5,10,3,1);
|
||||
break;
|
||||
case AU_FRSKY_SIREN:
|
||||
playASAP(10,20,5,2,1,1);
|
||||
break;
|
||||
case AU_FRSKY_ALARMC:
|
||||
playASAP(50,4,10,2,1);
|
||||
playASAP(70,8,20,1,1);
|
||||
playASAP(50,8,10,2,1);
|
||||
playASAP(70,4,20,1,1);
|
||||
break;
|
||||
case AU_FRSKY_RATATA:
|
||||
playASAP(BEEP_DEFAULT_FREQ+50,5,10,10,1);
|
||||
break;
|
||||
case AU_FRSKY_TICK:
|
||||
playASAP(BEEP_DEFAULT_FREQ+50,5,50,2,1);
|
||||
break;
|
||||
#ifdef HAPTIC
|
||||
case AU_FRSKY_HAPTIC1:
|
||||
playASAP(0,30,10,0,1);
|
||||
playASAP(0,10,50,0,1);
|
||||
break;
|
||||
case AU_FRSKY_HAPTIC2:
|
||||
playASAP(0,30,10,0,1);
|
||||
playASAP(0,10,10,0,1);
|
||||
playASAP(0,10,30,0,1);
|
||||
break;
|
||||
case AU_FRSKY_HAPTIC3:
|
||||
playASAP(0,30,10,0,1);
|
||||
playASAP(0,10,10,2,1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audioDefevent(uint8_t e)
|
||||
{
|
||||
audio.event(e, BEEP_DEFAULT_FREQ);
|
||||
}
|
|
@ -39,9 +39,6 @@ uint8_t beepAgainOrig = 0;
|
|||
uint8_t beepOn = false;
|
||||
bool warble = false;
|
||||
bool warbleC;
|
||||
#if defined(HAPTIC)
|
||||
uint8_t hapticTick = 0;
|
||||
#endif
|
||||
|
||||
// The various "beep" tone lengths
|
||||
static const pm_uint8_t beepTab[] PROGMEM = {
|
||||
|
@ -55,6 +52,10 @@ static const pm_uint8_t beepTab[] PROGMEM = {
|
|||
|
||||
void beep(uint8_t val)
|
||||
{
|
||||
#if defined(HAPTIC)
|
||||
haptic.event(val==0 ? 0 : AU_TIMER_10+beepAgain);
|
||||
#endif
|
||||
|
||||
if(g_eeGeneral.flashBeep && val > 1) g_LightOffCounter = FLASH_DURATION;
|
||||
|
||||
if (g_eeGeneral.beeperMode>0 || (g_eeGeneral.beeperMode==0 && val!=0) || (g_eeGeneral.beeperMode==-1 && val>=3)) {
|
||||
|
|
10
src/beeper.h
10
src/beeper.h
|
@ -111,19 +111,9 @@ FORCEINLINE void AUDIO_HEARTBEAT()
|
|||
BUZZER_OFF;
|
||||
else
|
||||
BUZZER_ON;
|
||||
#if defined(HAPTIC)
|
||||
if (hapticTick-- > 0) {
|
||||
HAPTIC_ON; // haptic output 'high'
|
||||
}
|
||||
else {
|
||||
HAPTIC_OFF; // haptic output 'low'
|
||||
hapticTick = g_eeGeneral.hapticStrength;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
BUZZER_OFF;
|
||||
HAPTIC_OFF;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "ersky9x/AT91SAM3S4.h"
|
||||
#endif
|
||||
|
||||
#include "ersky9x/sound.h"
|
||||
|
||||
#define PIN_ENABLE 0x001
|
||||
#define PIN_PERIPHERAL 0x000
|
||||
#define PIN_INPUT 0x002
|
||||
|
|
320
src/ersky9x/audio.cpp
Normal file
320
src/ersky9x/audio.cpp
Normal file
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "open9x.h"
|
||||
|
||||
audioQueue::audioQueue()
|
||||
{
|
||||
toneTimeLeft = 0;
|
||||
tonePause = 0;
|
||||
|
||||
t_queueRidx = 0;
|
||||
t_queueWidx = 0;
|
||||
}
|
||||
|
||||
|
||||
#define QUEUE_TONE(tf,ttl,tfi) queueTone(tf * 61 / 2, ttl * 10, tfi * 61 / 2)
|
||||
|
||||
|
||||
// heartbeat is responsibile for issueing the audio tones and general square waves
|
||||
// it is essentially the life of the class.
|
||||
// it is called every 10ms
|
||||
void audioQueue::heartbeat()
|
||||
{
|
||||
#if defined(SIMU)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (toneTimeLeft == 0) {
|
||||
if (tonePause == 0) {
|
||||
if (t_queueRidx != t_queueWidx) {
|
||||
toneFreq = queueToneFreq[t_queueRidx];
|
||||
toneTimeLeft = queueToneLength[t_queueRidx];
|
||||
toneFreqIncr = queueToneFreqIncr[t_queueRidx];
|
||||
tonePause = queueTonePause[t_queueRidx];
|
||||
if ((toneFreq == 0) || (toneTimeLeft == 0)) {
|
||||
//SPEAKER_OFF;
|
||||
}
|
||||
if (!queueToneRepeat[t_queueRidx]--) {
|
||||
t_queueRidx = (t_queueRidx + 1) % AUDIO_QUEUE_LENGTH;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((tone2Freq == 0) & (tone2TimeLeft == 0)) {
|
||||
//SPEAKER_OFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((toneFreq > 0) & (toneTimeLeft > 0)) {
|
||||
QUEUE_TONE(toneFreq, toneTimeLeft, toneFreqIncr);
|
||||
}
|
||||
else if (((tone2Freq > 0) & (tone2TimeLeft > 0)) & (tonePause == 0)) {
|
||||
//second flow tone here, priority on 1st, pause of 1st not allow to start second
|
||||
QUEUE_TONE(tone2Freq, tone2TimeLeft, 0);
|
||||
}
|
||||
|
||||
if (toneTimeLeft > 0) {
|
||||
toneTimeLeft--; //time gets counted down
|
||||
toneFreq += toneFreqIncr;
|
||||
}
|
||||
else {
|
||||
if (tonePause > 0) {
|
||||
// SPEAKER_OFF;
|
||||
tonePause--; //time gets counted down
|
||||
}
|
||||
}
|
||||
|
||||
if (tone2TimeLeft > 0) {
|
||||
tone2TimeLeft--; //time gets counted down
|
||||
}
|
||||
else {
|
||||
if (toneTimeLeft == 0) {
|
||||
//SPEAKER_OFF;
|
||||
}
|
||||
if (tone2Pause > 0) {
|
||||
tone2Pause--; //time gets counted down
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline uint8_t audioQueue::getToneLength(uint8_t tLen)
|
||||
{
|
||||
uint8_t result = tLen; // default
|
||||
if (g_eeGeneral.beeperLength < 0) {
|
||||
result /= (1-g_eeGeneral.beeperLength);
|
||||
}
|
||||
if (g_eeGeneral.beeperLength > 0) {
|
||||
result *= (1+g_eeGeneral.beeperLength);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void audioQueue::play(uint8_t tFreq, uint8_t tLen, uint8_t tPause,
|
||||
uint8_t tFlags, int8_t tFreqIncr)
|
||||
{
|
||||
if (tFlags & PLAY_SOUND_VARIO) {
|
||||
tone2Freq = tFreq;
|
||||
tone2TimeLeft = tLen;
|
||||
tone2Pause = tPause;
|
||||
}
|
||||
else {
|
||||
tFreq += g_eeGeneral.speakerPitch + BEEP_OFFSET; // add pitch compensator
|
||||
tLen = getToneLength(tLen);
|
||||
if (tFlags & PLAY_NOW || (!busy() && empty())) {
|
||||
toneFreq = tFreq;
|
||||
toneTimeLeft = tLen;
|
||||
tonePause = tPause;
|
||||
toneFreqIncr = tFreqIncr;
|
||||
t_queueWidx = t_queueRidx;
|
||||
}
|
||||
else {
|
||||
tFlags++;
|
||||
}
|
||||
|
||||
tFlags &= 0x0f;
|
||||
if (tFlags) {
|
||||
uint8_t next_queueWidx = (t_queueWidx + 1) % AUDIO_QUEUE_LENGTH;
|
||||
if (next_queueWidx != t_queueRidx) {
|
||||
queueToneFreq[t_queueWidx] = tFreq;
|
||||
queueToneLength[t_queueWidx] = tLen;
|
||||
queueTonePause[t_queueWidx] = tPause;
|
||||
queueToneRepeat[t_queueWidx] = tFlags - 1;
|
||||
queueToneFreqIncr[t_queueWidx] = tFreqIncr;
|
||||
t_queueWidx = next_queueWidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audioQueue::event(uint8_t e, uint8_t f)
|
||||
{
|
||||
if (g_eeGeneral.flashBeep && (e <= AU_ERROR || e >= AU_WARNING1))
|
||||
g_LightOffCounter = FLASH_DURATION;
|
||||
|
||||
if (g_eeGeneral.beeperMode>0 || (g_eeGeneral.beeperMode==0 && e>=AU_WARNING1) || (g_eeGeneral.beeperMode>=-1 && e<=AU_ERROR)) {
|
||||
if (e < AU_FRSKY_FIRST || empty()) {
|
||||
switch (e) {
|
||||
// inactivity timer alert
|
||||
case AU_INACTIVITY:
|
||||
play(70, 10, 2, 2|PLAY_NOW);
|
||||
break;
|
||||
// low battery in tx
|
||||
case AU_TX_BATTERY_LOW:
|
||||
if (empty()) {
|
||||
play(60, 20, 3, 2, 1);
|
||||
play(80, 20, 3, 2, -1);
|
||||
}
|
||||
break;
|
||||
// error
|
||||
case AU_ERROR:
|
||||
play(BEEP_DEFAULT_FREQ, 40, 1, PLAY_NOW);
|
||||
break;
|
||||
// keypad up (seems to be used when going left/right through system menu options. 0-100 scales etc)
|
||||
case AU_KEYPAD_UP:
|
||||
play(BEEP_KEY_UP_FREQ, 10, 1, PLAY_NOW);
|
||||
break;
|
||||
// keypad down (seems to be used when going left/right through system menu options. 0-100 scales etc)
|
||||
case AU_KEYPAD_DOWN:
|
||||
play(BEEP_KEY_DOWN_FREQ, 10, 1, PLAY_NOW);
|
||||
break;
|
||||
// menu display (also used by a few generic beeps)
|
||||
case AU_MENUS:
|
||||
play(BEEP_DEFAULT_FREQ, 10, 2, PLAY_NOW);
|
||||
break;
|
||||
// trim move
|
||||
case AU_TRIM_MOVE:
|
||||
play(f, 6, 1, PLAY_NOW);
|
||||
break;
|
||||
// trim center
|
||||
case AU_TRIM_MIDDLE:
|
||||
play(BEEP_DEFAULT_FREQ, 10, 2, PLAY_NOW);
|
||||
break;
|
||||
// warning one
|
||||
case AU_WARNING1:
|
||||
play(BEEP_DEFAULT_FREQ, 10, 1, PLAY_NOW);
|
||||
break;
|
||||
// warning two
|
||||
case AU_WARNING2:
|
||||
play(BEEP_DEFAULT_FREQ, 20, 1, PLAY_NOW);
|
||||
break;
|
||||
// warning three
|
||||
case AU_WARNING3:
|
||||
play(BEEP_DEFAULT_FREQ, 30, 1, PLAY_NOW);
|
||||
break;
|
||||
// startup tune
|
||||
case AU_TADA:
|
||||
play(50, 10, 5);
|
||||
play(90, 10, 5);
|
||||
play(110, 5, 4, 2);
|
||||
break;
|
||||
// pot/stick center
|
||||
case AU_POT_STICK_MIDDLE:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 10, 1, PLAY_NOW);
|
||||
break;
|
||||
// mix warning 1
|
||||
case AU_MIX_WARNING_1:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 6, 0, PLAY_NOW);
|
||||
break;
|
||||
// mix warning 2
|
||||
case AU_MIX_WARNING_2:
|
||||
play(BEEP_DEFAULT_FREQ + 52, 6, 0, PLAY_NOW);
|
||||
break;
|
||||
// mix warning 3
|
||||
case AU_MIX_WARNING_3:
|
||||
play(BEEP_DEFAULT_FREQ + 54, 6, 0, PLAY_NOW);
|
||||
break;
|
||||
// time 30 seconds left
|
||||
case AU_TIMER_30:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 15, 3, 2|PLAY_NOW);
|
||||
break;
|
||||
// time 20 seconds left
|
||||
case AU_TIMER_20:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 15, 3, 1|PLAY_NOW);
|
||||
break;
|
||||
// time 10 seconds left
|
||||
case AU_TIMER_10:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 15, 3, PLAY_NOW);
|
||||
break;
|
||||
// time <3 seconds left
|
||||
case AU_TIMER_LT3:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 15, 3, PLAY_NOW);
|
||||
break;
|
||||
case AU_FRSKY_WARN1:
|
||||
play(BEEP_DEFAULT_FREQ+20,15,5,2);
|
||||
break;
|
||||
case AU_FRSKY_WARN2:
|
||||
play(BEEP_DEFAULT_FREQ+30,15,5,2);
|
||||
break;
|
||||
case AU_FRSKY_CHEEP:
|
||||
play(BEEP_DEFAULT_FREQ+30,10,2,2,2);
|
||||
break;
|
||||
case AU_FRSKY_RING:
|
||||
play(BEEP_DEFAULT_FREQ+25,5,2,10);
|
||||
play(BEEP_DEFAULT_FREQ+25,5,10,1);
|
||||
play(BEEP_DEFAULT_FREQ+25,5,2,10);
|
||||
break;
|
||||
case AU_FRSKY_SCIFI:
|
||||
play(80,10,3,2,-1);
|
||||
play(60,10,3,2,1);
|
||||
play(70,10,1,0);
|
||||
break;
|
||||
case AU_FRSKY_ROBOT:
|
||||
play(70,5,1,1);
|
||||
play(50,15,2,1);
|
||||
play(80,15,2,1);
|
||||
break;
|
||||
case AU_FRSKY_CHIRP:
|
||||
play(BEEP_DEFAULT_FREQ+40,5,1,2);
|
||||
play(BEEP_DEFAULT_FREQ+54,5,1,3);
|
||||
break;
|
||||
case AU_FRSKY_TADA:
|
||||
play(50,5,5);
|
||||
play(90,5,5);
|
||||
play(110,3,4,2);
|
||||
break;
|
||||
case AU_FRSKY_CRICKET:
|
||||
play(80,5,10,3);
|
||||
play(80,5,20,1);
|
||||
play(80,5,10,3);
|
||||
break;
|
||||
case AU_FRSKY_SIREN:
|
||||
play(10,20,5,2,1);
|
||||
break;
|
||||
case AU_FRSKY_ALARMC:
|
||||
play(50,4,10,2);
|
||||
play(70,8,20,1);
|
||||
play(50,8,10,2);
|
||||
play(70,4,20,1);
|
||||
break;
|
||||
case AU_FRSKY_RATATA:
|
||||
play(BEEP_DEFAULT_FREQ+50,5,10,10);
|
||||
break;
|
||||
case AU_FRSKY_TICK:
|
||||
play(BEEP_DEFAULT_FREQ+50,5,50,2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audioDefevent(uint8_t e)
|
||||
{
|
||||
#ifdef HAPTIC
|
||||
haptic.event(e); //do this before audio to help sync timings
|
||||
#endif
|
||||
audio.event(e, BEEP_DEFAULT_FREQ);
|
||||
}
|
127
src/ersky9x/audio.h
Normal file
127
src/ersky9x/audio.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef audio_h
|
||||
#define audio_h
|
||||
|
||||
#define AUDIO_QUEUE_LENGTH (20)
|
||||
#define BEEP_DEFAULT_FREQ (70)
|
||||
#define BEEP_OFFSET (10)
|
||||
#define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+5)
|
||||
#define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-5)
|
||||
|
||||
class audioQueue
|
||||
{
|
||||
public:
|
||||
|
||||
audioQueue();
|
||||
|
||||
|
||||
void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlags=0, int8_t tFreqIncr=0);
|
||||
|
||||
inline bool busy() {
|
||||
return (toneTimeLeft > 0);
|
||||
}
|
||||
|
||||
void event(uint8_t e, uint8_t f=BEEP_DEFAULT_FREQ);
|
||||
|
||||
// heartbeat is responsibile for issueing the audio tones and general square waves
|
||||
// it is essentially the life of the class.
|
||||
void heartbeat();
|
||||
|
||||
// bool freeslots(uint8_t slots);
|
||||
|
||||
inline bool empty() {
|
||||
return (t_queueRidx == t_queueWidx);
|
||||
}
|
||||
|
||||
protected:
|
||||
inline uint8_t getToneLength(uint8_t tLen);
|
||||
|
||||
private:
|
||||
uint8_t t_queueRidx;
|
||||
uint8_t t_queueWidx;
|
||||
|
||||
uint8_t toneFreq;
|
||||
int8_t toneFreqIncr;
|
||||
uint8_t toneTimeLeft;
|
||||
uint8_t tonePause;
|
||||
|
||||
// vario
|
||||
uint8_t tone2Freq;
|
||||
uint8_t tone2TimeLeft;
|
||||
uint8_t tone2Pause;
|
||||
|
||||
// queue arrays
|
||||
uint8_t queueToneFreq[AUDIO_QUEUE_LENGTH];
|
||||
int8_t queueToneFreqIncr[AUDIO_QUEUE_LENGTH];
|
||||
uint8_t queueToneLength[AUDIO_QUEUE_LENGTH];
|
||||
uint8_t queueTonePause[AUDIO_QUEUE_LENGTH];
|
||||
uint8_t queueToneRepeat[AUDIO_QUEUE_LENGTH];
|
||||
|
||||
};
|
||||
|
||||
//wrapper function - dirty but results in a space saving!!!
|
||||
extern audioQueue audio;
|
||||
|
||||
void audioDefevent(uint8_t e);
|
||||
|
||||
#define AUDIO_KEYPAD_UP() audioDefevent(AU_KEYPAD_UP)
|
||||
#define AUDIO_KEYPAD_DOWN() audioDefevent(AU_KEYPAD_DOWN)
|
||||
#define AUDIO_MENUS() audioDefevent(AU_MENUS)
|
||||
#define AUDIO_WARNING1() audioDefevent(AU_WARNING1)
|
||||
#define AUDIO_WARNING2() audioDefevent(AU_WARNING2)
|
||||
#define AUDIO_ERROR() audioDefevent(AU_ERROR)
|
||||
|
||||
|
||||
#define IS_AUDIO_BUSY() audio.busy()
|
||||
|
||||
#define AUDIO_TIMER_30() audioDefevent(AU_TIMER_30)
|
||||
#define AUDIO_TIMER_20() audioDefevent(AU_TIMER_20)
|
||||
#define AUDIO_TIMER_10() audioDefevent(AU_TIMER_10)
|
||||
#define AUDIO_TIMER_LT3() audioDefevent(AU_TIMER_LT3)
|
||||
#define AUDIO_MINUTE_BEEP() audioDefevent(AU_WARNING1)
|
||||
#define AUDIO_INACTIVITY() audioDefevent(AU_INACTIVITY)
|
||||
#define AUDIO_MIX_WARNING_1() audioDefevent(AU_MIX_WARNING_1)
|
||||
#define AUDIO_MIX_WARNING_2() audioDefevent(AU_MIX_WARNING_2)
|
||||
#define AUDIO_MIX_WARNING_3() audioDefevent(AU_MIX_WARNING_3)
|
||||
#define AUDIO_POT_STICK_MIDDLE() audioDefevent(AU_POT_STICK_MIDDLE)
|
||||
#define AUDIO_VARIO_UP() audioDefevent(AU_KEYPAD_UP)
|
||||
#define AUDIO_VARIO_DOWN() audioDefevent(AU_KEYPAD_DOWN)
|
||||
#define AUDIO_TRIM_MIDDLE() audioDefevent(AU_TRIM_MIDDLE)
|
||||
#define AUDIO_TELEMETRY_ALARM() audioDefevent(AU_WARNING1)
|
||||
|
||||
#define AUDIO_HEARTBEAT() audio.heartbeat()
|
||||
|
||||
#endif
|
|
@ -641,11 +641,45 @@ void check_frsky()
|
|||
|
||||
#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
|
||||
static uint16_t s_varioTmr = 0;
|
||||
|
||||
if (isFunctionActive(FUNC_VARIO)) {
|
||||
#if defined(AUDIO)
|
||||
uint8_t warble = 0;
|
||||
#endif
|
||||
int16_t verticalSpeed = 0;
|
||||
//vertical speed in 0.01m/s now
|
||||
//not baro vario only has additional resolution
|
||||
//A1/A2 need conversion there
|
||||
//GPS source need precision to be set, my gps gives 0.1m resolution
|
||||
/*if (g_model.varioSource == BARO_SOURCE_BARO)*/
|
||||
verticalSpeed = limit((int16_t)(-VARIO_SPEED_LIMIT*100), (int16_t)frskyHubData.varioSpeed, (int16_t)(+VARIO_SPEED_LIMIT*100));
|
||||
/*else
|
||||
verticalSpeed = limit((int16_t)-VARIO_SPEED_LIMIT, (int16_t)(frskyHubData.varioSpeed), (int16_t)+VARIO_SPEED_LIMIT)*100;*/
|
||||
|
||||
uint8_t SoundAltBeepNextFreq = 0;
|
||||
uint8_t SoundAltBeepNextTime = 0;
|
||||
static uint8_t SoundAltBeepFreq = 0;
|
||||
static uint8_t SoundAltBeepTime = 0;
|
||||
if ((verticalSpeed < g_model.varioSpeedUpMin*VARIO_SPEED_LIMIT_MUL) && (verticalSpeed > (255 - g_model.varioSpeedDownMin)*(-VARIO_SPEED_LIMIT_MUL))) { //check thresholds here in cm/s
|
||||
SoundAltBeepNextFreq = (0);
|
||||
SoundAltBeepNextTime = (0);
|
||||
}
|
||||
else {
|
||||
SoundAltBeepNextFreq = (verticalSpeed * 10 + 16000) >> 8;
|
||||
SoundAltBeepNextTime = (1600 - verticalSpeed) / 100;
|
||||
if (verticalSpeed > 0) {
|
||||
if ((int16_t)(g_tmr10ms - s_varioTmr) > (int16_t)((int16_t)SoundAltBeepTime*2)) {
|
||||
s_varioTmr = g_tmr10ms;
|
||||
SoundAltBeepTime = SoundAltBeepNextTime;
|
||||
SoundAltBeepFreq = SoundAltBeepNextFreq;
|
||||
audio.play(SoundAltBeepFreq, SoundAltBeepTime, 0, PLAY_SOUND_VARIO);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// negative vertical speed gives sound without pauses
|
||||
SoundAltBeepTime = SoundAltBeepNextTime;
|
||||
SoundAltBeepFreq = SoundAltBeepNextFreq;
|
||||
audio.play(SoundAltBeepFreq, 1, 0, PLAY_SOUND_VARIO);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int8_t verticalSpeed = limit((int16_t)-100, (int16_t)(frskyHubData.varioSpeed/10), (int16_t)+100);
|
||||
|
||||
uint16_t interval;
|
||||
|
@ -666,6 +700,7 @@ void check_frsky()
|
|||
else
|
||||
AUDIO_VARIO_UP();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ enum menuProcSetupItems {
|
|||
#endif
|
||||
#if defined(HAPTIC)
|
||||
ITEM_SETUP_HAPTIC_MODE,
|
||||
ITEM_SETUP_HAPTIC_LENGTH,
|
||||
ITEM_SETUP_HAPTIC_STRENGTH,
|
||||
#endif
|
||||
#if defined(PCBARM)
|
||||
|
@ -217,6 +218,10 @@ void menuProcSetup(uint8_t event)
|
|||
g_eeGeneral.hapticMode = selectMenuItem(y, STR_HAPTICMODE, STR_VBEEPMODE, g_eeGeneral.hapticMode, -2, 1, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_HAPTIC_LENGTH:
|
||||
g_eeGeneral.hapticLength = selectMenuItem(y, STR_HAPTICLENGTH, STR_VBEEPLEN, g_eeGeneral.hapticLength, -2, 2, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_HAPTIC_STRENGTH:
|
||||
lcd_putsLeft( y, STR_HAPTICSTRENGTH);
|
||||
lcd_outdezAtt(GENERAL_PARAM_OFS, y, g_eeGeneral.hapticStrength, attr|LEFT);
|
||||
|
|
127
src/haptic.cpp
Normal file
127
src/haptic.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "open9x.h"
|
||||
|
||||
hapticQueue::hapticQueue()
|
||||
{
|
||||
buzzTimeLeft = 0;
|
||||
buzzPause = 0;
|
||||
|
||||
t_queueRidx = 0;
|
||||
t_queueWidx = 0;
|
||||
|
||||
hapticTick = 0;
|
||||
}
|
||||
|
||||
void hapticQueue::heartbeat()
|
||||
{
|
||||
#if defined(SIMU)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (buzzTimeLeft > 0) {
|
||||
buzzTimeLeft--; // time gets counted down
|
||||
#if defined(PCBARM)
|
||||
hapticOn(g_eeGeneral.hapticStrength * 20);
|
||||
#else
|
||||
if (hapticTick-- > 0) {
|
||||
HAPTIC_ON; // haptic output 'high'
|
||||
}
|
||||
else {
|
||||
HAPTIC_OFF; // haptic output 'high'
|
||||
hapticTick = g_eeGeneral.hapticStrength;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
HAPTIC_OFF; // haptic output 'high'
|
||||
if (buzzPause > 0) {
|
||||
buzzPause--;
|
||||
}
|
||||
else if (t_queueRidx != t_queueWidx) {
|
||||
buzzTimeLeft = queueHapticLength[t_queueRidx];
|
||||
buzzPause = queueHapticPause[t_queueRidx];
|
||||
if (!queueHapticRepeat[t_queueRidx]--) {
|
||||
t_queueRidx = (t_queueRidx + 1) % HAPTIC_QUEUE_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hapticQueue::play(uint8_t tLen, uint8_t tPause, uint8_t tFlags)
|
||||
{
|
||||
tLen = getHapticLength(tLen);
|
||||
|
||||
if (tFlags & PLAY_NOW || (!busy() && empty())) {
|
||||
buzzTimeLeft = tLen;
|
||||
buzzPause = tPause;
|
||||
t_queueWidx = t_queueRidx;
|
||||
}
|
||||
else {
|
||||
tFlags += 1;
|
||||
}
|
||||
|
||||
tFlags &= 0x0f;
|
||||
if (tFlags) {
|
||||
uint8_t next_queueWidx = (t_queueWidx + 1) % HAPTIC_QUEUE_LENGTH;
|
||||
if (next_queueWidx != t_queueRidx) {
|
||||
queueHapticLength[t_queueWidx] = tLen;
|
||||
queueHapticPause[t_queueWidx] = tPause;
|
||||
queueHapticRepeat[t_queueWidx] = tFlags-1;
|
||||
t_queueWidx = next_queueWidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hapticQueue::event(uint8_t e)
|
||||
{
|
||||
if (g_eeGeneral.hapticMode>0 || (g_eeGeneral.hapticMode==0 && e>=AU_WARNING1) || (g_eeGeneral.hapticMode>=-1 && e<=AU_ERROR)) {
|
||||
switch (e) {
|
||||
case 0: // very little buzz for keys / trims
|
||||
play(5, 0, PLAY_NOW);
|
||||
break;
|
||||
case AU_TIMER_20: // two buzz
|
||||
play(10,2,1);
|
||||
break;
|
||||
case AU_TIMER_30: // three buzz
|
||||
play(10,2,2);
|
||||
break;
|
||||
default:
|
||||
play(10,2,0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hapticQueue haptic;
|
90
src/haptic.h
Normal file
90
src/haptic.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef haptic_h
|
||||
#define haptic_h
|
||||
|
||||
#define HAPTIC_QUEUE_LENGTH 3
|
||||
|
||||
class hapticQueue
|
||||
{
|
||||
public:
|
||||
|
||||
hapticQueue();
|
||||
|
||||
// only difference between these two functions is that one does the
|
||||
// interupt queue (Now) and the other queues for playing ASAP.
|
||||
void play(uint8_t tLen, uint8_t tPause, uint8_t tRepeat=0);
|
||||
|
||||
inline bool busy() { return (buzzTimeLeft > 0); }
|
||||
|
||||
void event(uint8_t e);
|
||||
|
||||
// heartbeat is responsibile for issueing the haptic buzzs and general square waves
|
||||
// it is essentially the life of the class.
|
||||
void heartbeat();
|
||||
|
||||
// bool freeslots(uint8_t slots);
|
||||
|
||||
inline bool empty() {
|
||||
return (t_queueRidx == t_queueWidx);
|
||||
}
|
||||
|
||||
protected:
|
||||
inline uint8_t getHapticLength(uint8_t tLen) {
|
||||
return ((g_eeGeneral.hapticLength * 2) + tLen) * 2;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t t_queueRidx;
|
||||
uint8_t t_queueWidx;
|
||||
|
||||
uint8_t buzzTimeLeft;
|
||||
uint8_t buzzPause;
|
||||
|
||||
uint8_t hapticTick;
|
||||
|
||||
// queue arrays
|
||||
uint8_t queueHapticLength[HAPTIC_QUEUE_LENGTH];
|
||||
uint8_t queueHapticPause[HAPTIC_QUEUE_LENGTH];
|
||||
uint8_t queueHapticRepeat[HAPTIC_QUEUE_LENGTH];
|
||||
};
|
||||
|
||||
//wrapper function - dirty but results in a space saving!!!
|
||||
extern hapticQueue haptic;
|
||||
|
||||
#define IS_HAPTIC_BUSY() haptic.busy()
|
||||
#define HAPTIC_HEARTBEAT() haptic.heartbeat()
|
||||
|
||||
|
||||
#endif // haptic_h
|
|
@ -2102,6 +2102,12 @@ void menuProcFunctionSwitches(uint8_t event)
|
|||
break;
|
||||
#endif
|
||||
}
|
||||
#if defined(HAPTIC)
|
||||
else if (sd->func == FUNC_HAPTIC) {
|
||||
val_max = 3;
|
||||
lcd_outdezAtt(21*FW, y, val_displayed, attr);
|
||||
}
|
||||
#endif
|
||||
#if defined(SOMO)
|
||||
else if (sd->func == FUNC_PLAY_SOMO) {
|
||||
lcd_outdezAtt(21*FW, y, val_displayed, attr);
|
||||
|
|
|
@ -286,6 +286,9 @@ enum Functions {
|
|||
FUNC_TRAINER_AIL,
|
||||
FUNC_INSTANT_TRIM,
|
||||
FUNC_PLAY_SOUND,
|
||||
#ifdef HAPTIC
|
||||
FUNC_HAPTIC,
|
||||
#endif
|
||||
#ifdef SOMO
|
||||
FUNC_PLAY_SOMO,
|
||||
#endif
|
||||
|
|
|
@ -1429,6 +1429,13 @@ void evalFunctions()
|
|||
beep(3);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(HAPTIC)
|
||||
if (sd->func == FUNC_HAPTIC) {
|
||||
haptic.event(sd->param);
|
||||
}
|
||||
#endif
|
||||
|
||||
active_functions |= mask;
|
||||
}
|
||||
else {
|
||||
|
@ -2085,6 +2092,7 @@ void perMain()
|
|||
}
|
||||
|
||||
#if defined(PCBARM)
|
||||
HAPTIC_HEARTBEAT();
|
||||
AUDIO_HEARTBEAT(); // the queue processing
|
||||
#endif
|
||||
|
||||
|
@ -2156,6 +2164,10 @@ ISR(TIMER0_COMP_vect, ISR_NOBLOCK) //10ms timer
|
|||
|
||||
AUDIO_HEARTBEAT();
|
||||
|
||||
#ifdef HAPTIC
|
||||
HAPTIC_HEARTBEAT();
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
// Record start time from TCNT1 to record excution time
|
||||
cli();
|
||||
|
|
50
src/open9x.h
50
src/open9x.h
|
@ -621,7 +621,9 @@ void read_9_adc(void ) ;
|
|||
#define BUZZER_OFF PORTE &= ~(1 << OUT_E_BUZZER)
|
||||
|
||||
#if defined(HAPTIC)
|
||||
#if defined(PCBV4)
|
||||
#if defined(PCBARM)
|
||||
#define HAPTIC_OFF hapticOff()
|
||||
#elif defined(PCBV4)
|
||||
#define HAPTIC_ON PORTD &= ~(1 << INP_D_HAPTIC)
|
||||
#define HAPTIC_OFF PORTD |= (1 << INP_D_HAPTIC)
|
||||
#else
|
||||
|
@ -821,6 +823,48 @@ extern uint16_t jeti_keys;
|
|||
#include "mavlink.h"
|
||||
#endif
|
||||
|
||||
// REPEAT uses 0x01 to 0x0f
|
||||
#define PLAY_NOW 0x10
|
||||
#define PLAY_SOUND_VARIO 0x20
|
||||
|
||||
/* make sure the defines below always go in numeric order */
|
||||
enum AUDIO_SOUNDS {
|
||||
AU_INACTIVITY,
|
||||
AU_TX_BATTERY_LOW,
|
||||
AU_ERROR,
|
||||
AU_KEYPAD_UP,
|
||||
AU_KEYPAD_DOWN,
|
||||
AU_MENUS,
|
||||
AU_TRIM_MOVE,
|
||||
AU_WARNING1,
|
||||
AU_WARNING2,
|
||||
AU_WARNING3,
|
||||
AU_TRIM_MIDDLE,
|
||||
AU_TADA,
|
||||
AU_POT_STICK_MIDDLE,
|
||||
AU_MIX_WARNING_1,
|
||||
AU_MIX_WARNING_2,
|
||||
AU_MIX_WARNING_3,
|
||||
AU_TIMER_30,
|
||||
AU_TIMER_20,
|
||||
AU_TIMER_10,
|
||||
AU_TIMER_LT3,
|
||||
AU_FRSKY_FIRST,
|
||||
AU_FRSKY_WARN1 = AU_FRSKY_FIRST,
|
||||
AU_FRSKY_WARN2,
|
||||
AU_FRSKY_CHEEP,
|
||||
AU_FRSKY_RING,
|
||||
AU_FRSKY_SCIFI,
|
||||
AU_FRSKY_ROBOT,
|
||||
AU_FRSKY_CHIRP,
|
||||
AU_FRSKY_TADA,
|
||||
AU_FRSKY_CRICKET,
|
||||
AU_FRSKY_SIREN,
|
||||
AU_FRSKY_ALARMC,
|
||||
AU_FRSKY_RATATA,
|
||||
AU_FRSKY_TICK,
|
||||
AU_FRSKY_LAST,
|
||||
};
|
||||
#if defined(AUDIO)
|
||||
//audio settungs are external to keep out clutter!
|
||||
// TODO english learning for me... what does mean "keep out clutter"?
|
||||
|
@ -829,6 +873,10 @@ extern uint16_t jeti_keys;
|
|||
#include "beeper.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAPTIC)
|
||||
#include "haptic.h"
|
||||
#endif
|
||||
|
||||
#if defined(SDCARD)
|
||||
#include "sdcard.h"
|
||||
#endif
|
||||
|
|
307
src/stock/audio.cpp
Normal file
307
src/stock/audio.cpp
Normal file
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny <shadow@privy.de>
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - Thomas Husterer
|
||||
*
|
||||
* open9x is based on code named
|
||||
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
|
||||
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
|
||||
* and the original (and ongoing) project by
|
||||
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "open9x.h"
|
||||
|
||||
audioQueue::audioQueue()
|
||||
{
|
||||
toneTimeLeft = 0;
|
||||
tonePause = 0;
|
||||
|
||||
t_queueRidx = 0;
|
||||
t_queueWidx = 0;
|
||||
}
|
||||
|
||||
|
||||
// heartbeat is responsibile for issueing the audio tones and general square waves
|
||||
// it is essentially the life of the class.
|
||||
// it is called every 10ms
|
||||
void audioQueue::heartbeat()
|
||||
{
|
||||
#if defined(SIMU)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (toneTimeLeft > 0) {
|
||||
#if defined(PCBV4)
|
||||
if (toneFreq) {
|
||||
OCR0A = (5000 / toneFreq); // sticking with old values approx 20(abs. min) to 90, 60 being the default tone(?).
|
||||
SPEAKER_ON;
|
||||
}
|
||||
#endif
|
||||
toneTimeLeft--; //time gets counted down
|
||||
toneFreq += toneFreqIncr;
|
||||
}
|
||||
else {
|
||||
if (tonePause > 0) {
|
||||
SPEAKER_OFF;
|
||||
tonePause--; //time gets counted down
|
||||
}
|
||||
else if (t_queueRidx != t_queueWidx) {
|
||||
toneFreq = queueToneFreq[t_queueRidx];
|
||||
toneTimeLeft = queueToneLength[t_queueRidx];
|
||||
toneFreqIncr = queueToneFreqIncr[t_queueRidx];
|
||||
tonePause = queueTonePause[t_queueRidx];
|
||||
if (!queueToneRepeat[t_queueRidx]--) {
|
||||
t_queueRidx = (t_queueRidx + 1) % AUDIO_QUEUE_LENGTH;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tone2TimeLeft > 0) {
|
||||
#if defined(PCBV4)
|
||||
if (tone2Freq) {
|
||||
OCR0A = (5000 / tone2Freq); // sticking with old values approx 20(abs. min) to 90, 60 being the default tone(?).
|
||||
SPEAKER_ON;
|
||||
}
|
||||
#else
|
||||
toneFreq = tone2Freq;
|
||||
#endif
|
||||
tone2TimeLeft--; //time gets counted down
|
||||
}
|
||||
else {
|
||||
SPEAKER_OFF;
|
||||
if (tone2Pause > 0) {
|
||||
tone2Pause--; //time gets counted down
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline uint8_t audioQueue::getToneLength(uint8_t tLen)
|
||||
{
|
||||
uint8_t result = tLen; // default
|
||||
if (g_eeGeneral.beeperLength < 0) {
|
||||
result /= (1-g_eeGeneral.beeperLength);
|
||||
}
|
||||
if (g_eeGeneral.beeperLength > 0) {
|
||||
result *= (1+g_eeGeneral.beeperLength);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void audioQueue::play(uint8_t tFreq, uint8_t tLen, uint8_t tPause,
|
||||
uint8_t tFlags, int8_t tFreqIncr)
|
||||
{
|
||||
if (tFlags & PLAY_SOUND_VARIO) {
|
||||
tone2Freq = tFreq;
|
||||
tone2TimeLeft = tLen;
|
||||
tone2Pause = tPause;
|
||||
}
|
||||
else {
|
||||
tFreq += g_eeGeneral.speakerPitch + BEEP_OFFSET; // add pitch compensator
|
||||
tLen = getToneLength(tLen);
|
||||
if (tFlags & PLAY_NOW || (!busy() && empty())) {
|
||||
toneFreq = tFreq;
|
||||
toneTimeLeft = tLen;
|
||||
tonePause = tPause;
|
||||
toneFreqIncr = tFreqIncr;
|
||||
t_queueWidx = t_queueRidx;
|
||||
}
|
||||
else {
|
||||
tFlags++;
|
||||
}
|
||||
|
||||
tFlags &= 0x0f;
|
||||
if (tFlags) {
|
||||
uint8_t next_queueWidx = (t_queueWidx + 1) % AUDIO_QUEUE_LENGTH;
|
||||
if (next_queueWidx != t_queueRidx) {
|
||||
queueToneFreq[t_queueWidx] = tFreq;
|
||||
queueToneLength[t_queueWidx] = tLen;
|
||||
queueTonePause[t_queueWidx] = tPause;
|
||||
queueToneRepeat[t_queueWidx] = tFlags - 1;
|
||||
queueToneFreqIncr[t_queueWidx] = tFreqIncr;
|
||||
t_queueWidx = next_queueWidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audioQueue::event(uint8_t e, uint8_t f)
|
||||
{
|
||||
if (g_eeGeneral.flashBeep && (e <= AU_ERROR || e >= AU_WARNING1))
|
||||
g_LightOffCounter = FLASH_DURATION;
|
||||
|
||||
if (g_eeGeneral.beeperMode>0 || (g_eeGeneral.beeperMode==0 && e>=AU_WARNING1) || (g_eeGeneral.beeperMode>=-1 && e<=AU_ERROR)) {
|
||||
if (e < AU_FRSKY_FIRST || empty()) {
|
||||
switch (e) {
|
||||
// inactivity timer alert
|
||||
case AU_INACTIVITY:
|
||||
play(70, 10, 2, 2|PLAY_NOW);
|
||||
break;
|
||||
// low battery in tx
|
||||
case AU_TX_BATTERY_LOW:
|
||||
if (empty()) {
|
||||
play(60, 20, 3, 2, 1);
|
||||
play(80, 20, 3, 2, -1);
|
||||
}
|
||||
break;
|
||||
// error
|
||||
case AU_ERROR:
|
||||
play(BEEP_DEFAULT_FREQ, 40, 1, PLAY_NOW);
|
||||
break;
|
||||
// keypad up (seems to be used when going left/right through system menu options. 0-100 scales etc)
|
||||
case AU_KEYPAD_UP:
|
||||
play(BEEP_KEY_UP_FREQ, 10, 1, PLAY_NOW);
|
||||
break;
|
||||
// keypad down (seems to be used when going left/right through system menu options. 0-100 scales etc)
|
||||
case AU_KEYPAD_DOWN:
|
||||
play(BEEP_KEY_DOWN_FREQ, 10, 1, PLAY_NOW);
|
||||
break;
|
||||
// menu display (also used by a few generic beeps)
|
||||
case AU_MENUS:
|
||||
play(BEEP_DEFAULT_FREQ, 10, 2, PLAY_NOW);
|
||||
break;
|
||||
// trim move
|
||||
case AU_TRIM_MOVE:
|
||||
play(f, 6, 1, PLAY_NOW);
|
||||
break;
|
||||
// trim center
|
||||
case AU_TRIM_MIDDLE:
|
||||
play(BEEP_DEFAULT_FREQ, 10, 2, PLAY_NOW);
|
||||
break;
|
||||
// warning one
|
||||
case AU_WARNING1:
|
||||
play(BEEP_DEFAULT_FREQ, 10, 1, PLAY_NOW);
|
||||
break;
|
||||
// warning two
|
||||
case AU_WARNING2:
|
||||
play(BEEP_DEFAULT_FREQ, 20, 1, PLAY_NOW);
|
||||
break;
|
||||
// warning three
|
||||
case AU_WARNING3:
|
||||
play(BEEP_DEFAULT_FREQ, 30, 1, PLAY_NOW);
|
||||
break;
|
||||
// startup tune
|
||||
case AU_TADA:
|
||||
play(50, 10, 5);
|
||||
play(90, 10, 5);
|
||||
play(110, 5, 4, 2);
|
||||
break;
|
||||
// pot/stick center
|
||||
case AU_POT_STICK_MIDDLE:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 10, 1, PLAY_NOW);
|
||||
break;
|
||||
// mix warning 1
|
||||
case AU_MIX_WARNING_1:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 6, 0, PLAY_NOW);
|
||||
break;
|
||||
// mix warning 2
|
||||
case AU_MIX_WARNING_2:
|
||||
play(BEEP_DEFAULT_FREQ + 52, 6, 0, PLAY_NOW);
|
||||
break;
|
||||
// mix warning 3
|
||||
case AU_MIX_WARNING_3:
|
||||
play(BEEP_DEFAULT_FREQ + 54, 6, 0, PLAY_NOW);
|
||||
break;
|
||||
// time 30 seconds left
|
||||
case AU_TIMER_30:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 15, 3, 2|PLAY_NOW);
|
||||
break;
|
||||
// time 20 seconds left
|
||||
case AU_TIMER_20:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 15, 3, 1|PLAY_NOW);
|
||||
break;
|
||||
// time 10 seconds left
|
||||
case AU_TIMER_10:
|
||||
// time <3 seconds left
|
||||
case AU_TIMER_LT3:
|
||||
play(BEEP_DEFAULT_FREQ + 50, 15, 3, PLAY_NOW);
|
||||
break;
|
||||
case AU_FRSKY_WARN1:
|
||||
play(BEEP_DEFAULT_FREQ+20,15,5,2);
|
||||
break;
|
||||
case AU_FRSKY_WARN2:
|
||||
play(BEEP_DEFAULT_FREQ+30,15,5,2);
|
||||
break;
|
||||
case AU_FRSKY_CHEEP:
|
||||
play(BEEP_DEFAULT_FREQ+30,10,2,2,2);
|
||||
break;
|
||||
case AU_FRSKY_RING:
|
||||
play(BEEP_DEFAULT_FREQ+25,5,2,10);
|
||||
play(BEEP_DEFAULT_FREQ+25,5,10,1);
|
||||
play(BEEP_DEFAULT_FREQ+25,5,2,10);
|
||||
break;
|
||||
case AU_FRSKY_SCIFI:
|
||||
play(80,10,3,2,-1);
|
||||
play(60,10,3,2,1);
|
||||
play(70,10,1,0);
|
||||
break;
|
||||
case AU_FRSKY_ROBOT:
|
||||
play(70,5,1,1);
|
||||
play(50,15,2,1);
|
||||
play(80,15,2,1);
|
||||
break;
|
||||
case AU_FRSKY_CHIRP:
|
||||
play(BEEP_DEFAULT_FREQ+40,5,1,2);
|
||||
play(BEEP_DEFAULT_FREQ+54,5,1,3);
|
||||
break;
|
||||
case AU_FRSKY_TADA:
|
||||
play(50,5,5);
|
||||
play(90,5,5);
|
||||
play(110,3,4,2);
|
||||
break;
|
||||
case AU_FRSKY_CRICKET:
|
||||
play(80,5,10,3);
|
||||
play(80,5,20,1);
|
||||
play(80,5,10,3);
|
||||
break;
|
||||
case AU_FRSKY_SIREN:
|
||||
play(10,20,5,2,1);
|
||||
break;
|
||||
case AU_FRSKY_ALARMC:
|
||||
play(50,4,10,2);
|
||||
play(70,8,20,1);
|
||||
play(50,8,10,2);
|
||||
play(70,4,20,1);
|
||||
break;
|
||||
case AU_FRSKY_RATATA:
|
||||
play(BEEP_DEFAULT_FREQ+50,5,10,10);
|
||||
break;
|
||||
case AU_FRSKY_TICK:
|
||||
play(BEEP_DEFAULT_FREQ+50,5,50,2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audioDefevent(uint8_t e)
|
||||
{
|
||||
#ifdef HAPTIC
|
||||
haptic.event(e); //do this before audio to help sync timings
|
||||
#endif
|
||||
audio.event(e);
|
||||
}
|
|
@ -31,9 +31,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef audio_h
|
||||
#define audio_h
|
||||
|
||||
#if defined(PCBARM)
|
||||
#include "ersky9x/sound.h"
|
||||
#endif
|
||||
|
@ -50,93 +47,18 @@
|
|||
#define BEEP_KEY_UP_FREQ (BEEP_DEFAULT_FREQ+5)
|
||||
#define BEEP_KEY_DOWN_FREQ (BEEP_DEFAULT_FREQ-5)
|
||||
|
||||
/* make sure the defines below always go in numeric order */
|
||||
enum AUDIO_SOUNDS {
|
||||
AU_INACTIVITY,
|
||||
AU_TX_BATTERY_LOW,
|
||||
AU_ERROR,
|
||||
AU_KEYPAD_UP,
|
||||
AU_KEYPAD_DOWN,
|
||||
AU_MENUS,
|
||||
AU_TRIM_MOVE,
|
||||
AU_WARNING1,
|
||||
AU_WARNING2,
|
||||
AU_WARNING3,
|
||||
AU_TRIM_MIDDLE,
|
||||
AU_TADA,
|
||||
AU_POT_STICK_MIDDLE,
|
||||
AU_MIX_WARNING_1,
|
||||
AU_MIX_WARNING_2,
|
||||
AU_MIX_WARNING_3,
|
||||
AU_TIMER_30,
|
||||
AU_TIMER_20,
|
||||
AU_TIMER_10,
|
||||
AU_TIMER_LT3,
|
||||
AU_FRSKY_FIRST,
|
||||
AU_FRSKY_WARN1 = AU_FRSKY_FIRST,
|
||||
AU_FRSKY_WARN2,
|
||||
AU_FRSKY_CHEEP,
|
||||
AU_FRSKY_RING,
|
||||
AU_FRSKY_SCIFI,
|
||||
AU_FRSKY_ROBOT,
|
||||
AU_FRSKY_CHIRP,
|
||||
AU_FRSKY_TADA,
|
||||
AU_FRSKY_CRICKET,
|
||||
AU_FRSKY_SIREN,
|
||||
AU_FRSKY_ALARMC,
|
||||
AU_FRSKY_RATATA,
|
||||
AU_FRSKY_TICK,
|
||||
#ifdef HAPTIC
|
||||
AU_FRSKY_HAPTIC1,
|
||||
AU_FRSKY_HAPTIC2,
|
||||
AU_FRSKY_HAPTIC3,
|
||||
#endif
|
||||
AU_FRSKY_LAST,
|
||||
};
|
||||
|
||||
class audioQueue
|
||||
{
|
||||
public:
|
||||
|
||||
audioQueue();
|
||||
|
||||
// only difference between these two functions is that one does the
|
||||
// interupt queue (Now) and the other queues for playing ASAP.
|
||||
void playNow(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tRepeat=0, uint8_t tHaptic=0, int8_t tFreqIncr=0);
|
||||
|
||||
void playASAP(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tRepeat=0, uint8_t tHaptic=0, int8_t tFreqIncr=0);
|
||||
void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlags=0, int8_t tFreqIncr=0);
|
||||
|
||||
inline bool busy() { return (toneTimeLeft > 0); }
|
||||
|
||||
void event(uint8_t e, uint8_t f=BEEP_DEFAULT_FREQ);
|
||||
|
||||
#if defined(ISER9X)
|
||||
inline void driver() {
|
||||
if (toneTimeLeft > 0) {
|
||||
switch (g_eeGeneral.speakerMode) {
|
||||
case 0:
|
||||
// stock beeper. simply turn port on for x time!
|
||||
if (toneTimeLeft > 0){
|
||||
PORTE |= (1<<OUT_E_BUZZER); // speaker output 'high'
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
static uint8_t toneCounter;
|
||||
toneCounter += toneFreq;
|
||||
if ((toneCounter & 0x80) == 0x80) {
|
||||
PORTE |= (1 << OUT_E_BUZZER);
|
||||
}
|
||||
else {
|
||||
PORTE &= ~(1 << OUT_E_BUZZER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PORTE &= ~(1<<OUT_E_BUZZER); // speaker output 'low'
|
||||
}
|
||||
}
|
||||
#elif defined(PCBSTD)
|
||||
inline void driver() {
|
||||
if (toneFreq && toneTimeLeft > 0) {
|
||||
toneCounter += toneFreq;
|
||||
|
@ -146,7 +68,6 @@ class audioQueue
|
|||
BUZZER_OFF;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// heartbeat is responsibile for issueing the audio tones and general square waves
|
||||
// it is essentially the life of the class.
|
||||
|
@ -170,6 +91,11 @@ class audioQueue
|
|||
uint8_t toneTimeLeft;
|
||||
uint8_t tonePause;
|
||||
|
||||
// vario has less priority
|
||||
uint8_t tone2Freq;
|
||||
uint8_t tone2TimeLeft;
|
||||
uint8_t tone2Pause;
|
||||
|
||||
// queue arrays
|
||||
uint8_t queueToneFreq[AUDIO_QUEUE_LENGTH];
|
||||
int8_t queueToneFreqIncr[AUDIO_QUEUE_LENGTH];
|
||||
|
@ -177,35 +103,21 @@ class audioQueue
|
|||
uint8_t queueTonePause[AUDIO_QUEUE_LENGTH];
|
||||
uint8_t queueToneRepeat[AUDIO_QUEUE_LENGTH];
|
||||
|
||||
#ifdef HAPTIC
|
||||
uint8_t toneHaptic;
|
||||
uint8_t hapticTick;
|
||||
uint8_t queueToneHaptic[AUDIO_QUEUE_LENGTH];
|
||||
uint8_t hapticSpinUpTime;
|
||||
#endif
|
||||
|
||||
#if defined(PCBSTD)
|
||||
uint8_t toneCounter;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
//wrapper function - dirty but results in a space saving!!!
|
||||
|
||||
extern audioQueue audio;
|
||||
|
||||
void audioDefevent(uint8_t e);
|
||||
|
||||
#define HAPTIC_SPINUP (10);
|
||||
|
||||
#define AUDIO_KEYPAD_UP() audioDefevent(AU_KEYPAD_UP)
|
||||
#define AUDIO_KEYPAD_DOWN() audioDefevent(AU_KEYPAD_DOWN)
|
||||
#define AUDIO_MENUS() audioDefevent(AU_MENUS)
|
||||
#define AUDIO_WARNING1() audioDefevent(AU_WARNING1)
|
||||
#define AUDIO_WARNING2() audioDefevent(AU_WARNING2)
|
||||
#define AUDIO_ERROR() audioDefevent(AU_ERROR)
|
||||
|
||||
|
||||
#define IS_AUDIO_BUSY() audio.busy()
|
||||
|
||||
#define AUDIO_TIMER_30() audioDefevent(AU_TIMER_30)
|
||||
#define AUDIO_TIMER_20() audioDefevent(AU_TIMER_20)
|
||||
#define AUDIO_TIMER_10() audioDefevent(AU_TIMER_10)
|
||||
|
@ -221,10 +133,7 @@ void audioDefevent(uint8_t e);
|
|||
#define AUDIO_TRIM_MIDDLE() audioDefevent(AU_TRIM_MIDDLE)
|
||||
#define AUDIO_TELEMETRY_ALARM() audioDefevent(AU_WARNING1)
|
||||
|
||||
#if defined(PCBSTD)
|
||||
#define AUDIO_DRIVER() audio.driver()
|
||||
#endif
|
||||
|
||||
#define AUDIO_HEARTBEAT() audio.heartbeat()
|
||||
#define IS_AUDIO_BUSY() audio.busy()
|
||||
|
||||
#endif // audio_h
|
|
@ -99,12 +99,17 @@
|
|||
#else
|
||||
#define TR_SOUND "Beep\0 "
|
||||
#endif
|
||||
#ifdef HAPTIC
|
||||
#define TR_HAPTIC "Haptic\0 "
|
||||
#else
|
||||
#define TR_HAPTIC
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
#define TR_TEST "Test\0 "
|
||||
#else
|
||||
#define TR_TEST
|
||||
#endif
|
||||
#define TR_VFSWFUNC "Security \0 ""Trainer \0 ""Instant Trim " TR_SOUND TR_SOMO "Reset\0 " TR_VVARIO TR_SDCLOGGS TR_TEST
|
||||
#define TR_VFSWFUNC "Security \0 ""Trainer \0 ""Instant Trim " TR_SOUND TR_HAPTIC TR_SOMO "Reset\0 " TR_VVARIO TR_SDCLOGGS TR_TEST
|
||||
|
||||
#define LEN_VFSWRESET "\006"
|
||||
#define TR_VFSWRESET "Timer1""Timer2""All ""Telem."
|
||||
|
|
|
@ -99,12 +99,17 @@
|
|||
#else
|
||||
#define TR_SOUND "Beep\0 "
|
||||
#endif
|
||||
#ifdef HAPTIC
|
||||
#define TR_HAPTIC "Haptic\0 "
|
||||
#else
|
||||
#define TR_HAPTIC
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
#define TR_TEST "Test\0 "
|
||||
#else
|
||||
#define TR_TEST
|
||||
#endif
|
||||
#define TR_VFSWFUNC "Securite \0 ""Ecolage \0 ""Trim instant " TR_SOUND TR_SOMO "Reset\0 " TR_VVARIO TR_SDCLOGGS TR_TEST
|
||||
#define TR_VFSWFUNC "Securite \0 ""Ecolage \0 ""Trim instant " TR_SOUND TR_HAPTIC TR_SOMO "Reset\0 " TR_VVARIO TR_SDCLOGGS TR_TEST
|
||||
|
||||
#define LEN_VFSWRESET "\006"
|
||||
#define TR_VFSWRESET "Timer1""Timer2""All ""Telem."
|
||||
|
|
|
@ -99,12 +99,17 @@
|
|||
#else
|
||||
#define TR_SOUND "Pip \0 "
|
||||
#endif
|
||||
#ifdef HAPTIC
|
||||
#define TR_HAPTIC "Haptic\0 "
|
||||
#else
|
||||
#define TR_HAPTIC
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
#define TR_TEST "Test\0 "
|
||||
#else
|
||||
#define TR_TEST
|
||||
#endif
|
||||
#define TR_VFSWFUNC "S\201kerhet \0 ""Trainer \0 ""Instant Trim " TR_SOUND TR_SOMO "Reset\0 " TR_VVARIO TR_SDCLOGGS TR_TEST
|
||||
#define TR_VFSWFUNC "S\201kerhet \0 ""Trainer \0 ""Instant Trim " TR_SOUND TR_HAPTIC TR_SOMO "Reset\0 " TR_VVARIO TR_SDCLOGGS TR_TEST
|
||||
|
||||
#define LEN_VFSWRESET "\006"
|
||||
#define TR_VFSWRESET "Timer1""Timer2""All ""Telem."
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue