1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-19 14:25:11 +03:00

Audio port from er9x (thanks Rob!)

This commit is contained in:
bsongis 2012-01-26 20:15:45 +00:00
parent be6385bf2f
commit a8ec3ddaa7
19 changed files with 1076 additions and 264 deletions

View file

@ -226,6 +226,13 @@ ifneq ($(SPLASH), NO)
CPPDEFS += -DSPLASH CPPDEFS += -DSPLASH
endif endif
ifeq ($(BEEPER), SPEAKER)
CPPDEFS += -DBEEPSPKR
CPPSRC += audio.cpp
else
CPPSRC += beeper.cpp
endif
ifeq ($(PCB), STD) ifeq ($(PCB), STD)
# STD PCB, so ... # STD PCB, so ...
@ -259,11 +266,6 @@ ifeq ($(PCB), STD)
endif endif
endif endif
# gruvin: If buzzer speaker replacment supported
ifeq ($(BEEPER), SPEAKER)
CPPDEFS += -DBEEPSPKR
endif
# If buzzer modified (no interference with PPM jack) # If buzzer modified (no interference with PPM jack)
ifeq ($(BEEPER), BUZZER_MOD) ifeq ($(BEEPER), BUZZER_MOD)
CPPDEFS += -DBUZZER_MOD CPPDEFS += -DBUZZER_MOD
@ -293,9 +295,6 @@ else
CPPSRC += frsky.cpp CPPSRC += frsky.cpp
CPPDEFS += -DPCBV3 -DFRSKY -DFRSKY_HUB -DWS_HOW_HIGH CPPDEFS += -DPCBV3 -DFRSKY -DFRSKY_HUB -DWS_HOW_HIGH
ifeq ($(PCB), V3)
CPPDEFS += -DBEEPSPKR
endif
ifeq ($(LOGS), YES) ifeq ($(LOGS), YES)
CPPSRC += logs.cpp CPPSRC += logs.cpp
CPPDEFS += -DLOGS CPPDEFS += -DLOGS
@ -303,13 +302,6 @@ else
endif endif
ifeq ($(PCB), V4) ifeq ($(PCB), V4)
CPPDEFS += -DPCBV4 CPPDEFS += -DPCBV4
# Temporary hack to get stock beeper working for testing, etc ... make BEEPER=BUZZER_MOD
# TODO should not be needed / tested here in V4
ifeq ($(BEEPER), BUZZER_MOD)
CPPDEFS += -DBUZZER_MOD
else
CPPDEFS += -DBEEPSPKR
endif
endif endif
ifeq ($(SOMO), YES) ifeq ($(SOMO), YES)
CPPSRC += somo14d.cpp CPPSRC += somo14d.cpp

601
src/audio.cpp Normal file
View file

@ -0,0 +1,601 @@
/*
* Author - Rob Thomson <rob@marotori.com>
*
* 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()
{
aqinit();
}
void audioQueue::aqinit()
{
//make sure haptic off by default
HAPTIC_OFF;
//initialize all arrays
flushqueue(0);
//set key vars to 0 to ensure no garbage
toneFreq = 0;
toneFreqEnd = 0;
toneRepeat = 0;
toneTimeLeft = 0;
queueState = 0;
toneRepeatCnt = 0;
inToneRepeat = 0;
hapticTick = 0;
#ifdef FRSKY
frskySample = 0;
#endif
heartbeatTimer = 0;
flushTemp();
}
bool audioQueue::busy()
{
if (toneTimeLeft > 0) {
return true;
}
else {
return false;
}
}
bool audioQueue::freeslots(uint8_t slots)
{
//find out if enough queue space exists to add the requested routine!
for (uint8_t i = AUDIO_QUEUE_LENGTH; i--;) {
slots--;
if (slots == 0) {
break;
} //only loop for the number of items indicated in slots
if (queueToneStart[i] != 0) {
return false;
break;
}
}
return true;
}
void audioQueue::commit(uint8_t toneInterupt)
{
if (toneInterupt == 0) {
//queued events
if (freeslots(3)) { //do not insert into the queue if less than 3 spare slots! this stops sound collitions from occuring
for (uint8_t i = 0; i < AUDIO_QUEUE_LENGTH; i++) {
if (queueToneStart[i] == 0) { //add to the first entry that has a start tone of zero (no sound)
queueToneStart[i] = t_queueToneStart;
queueToneEnd[i] = t_queueToneEnd;
queueToneLength[i] = t_queueToneLength;
queueTonePause[i] = t_queueTonePause;
queueToneRepeat[i] = t_queueToneRepeat;
queueToneHaptic[i] = t_queueToneHaptic;
flushTemp();
break;
}
}
}
}
else {
//interrupt events
queueToneStart[0] = t_queueToneStart;
queueToneEnd[0] = t_queueToneEnd;
queueToneLength[0] = t_queueToneLength;
queueTonePause[0] = t_queueTonePause;
queueToneRepeat[0] = t_queueToneRepeat;
queueToneHaptic[0] = t_queueToneHaptic;
flushqueue(1); //purge queue on interrupt events to stop broken audio
flushTemp();
}
}
void audioQueue::flushqueue(uint8_t startpos)
{
for (; startpos < AUDIO_QUEUE_LENGTH; startpos++) {
queueToneStart[startpos] = 0;
queueToneEnd[startpos] = 0;
queueToneLength[startpos] = 0;
queueTonePause[startpos] = 0;
queueToneRepeat[startpos] = 0;
queueToneHaptic[startpos] = 0;
}
}
//set all temporary buffers to default
void audioQueue::flushTemp()
{
t_queueToneStart = 0;
t_queueToneEnd = 0;
t_queueToneLength = 0;
t_queueTonePause = 0;
t_queueToneRepeat = 0;
t_queueToneHaptic = 0;
rateOfChange = 0;
toneHaptic = 0;
}
void audioQueue::restack()
{
for (uint8_t i = 0; i < AUDIO_QUEUE_LENGTH - 1; i++) {
queueToneStart[i] = queueToneStart[i + 1];
queueToneEnd[i] = queueToneEnd[i + 1];
queueToneLength[i] = queueToneLength[i + 1];
queueTonePause[i] = queueTonePause[i + 1];
queueToneRepeat[i] = queueToneRepeat[i + 1];
queueToneHaptic[i] = queueToneHaptic[i + 1];
}
flushqueue(AUDIO_QUEUE_LENGTH - 1); //set the last entry to 0 as nothing in stack to add too!
}
//heartbeat is responsibile for issueing the audio tones and general square waves
// it is essentially the life of the class.
void audioQueue::heartbeat()
{
uint8_t z; //direction calulations
uint8_t hTimer; //heartbeat timer
if (queueState == 1) {
if (g_eeGeneral.beeperVal > 0) {
//never do sounds if we are set to go quiet
#if 0
switch (g_eeGeneral.speakerMode) {
case 0:
//stock beeper. simply turn port on for x time!
if (toneTimeLeft > 0) {
#if defined (PCBV3)
TCCR0A &= ~(0b01<<COM0A0);
#else
PORTE |= (1 << OUT_E_BUZZER); // speaker output 'high'
#endif
}
else {
#if defined (PCVV3)
TCCR0A &= ~(0b01<<COM0A0);
#else
PORTE &= ~(1 << OUT_E_BUZZER); // speaker output 'low'
#endif
}
break;
case 1:
#endif
//square wave generator use for speaker mod
//simply generates a square wave for toneFreq for
//as long as the toneTimeLeft is more than 0
static uint8_t toneCounter;
if (toneTimeLeft > 0) {
toneCounter += toneFreq;
if ((toneCounter & 0x80) == 0x80) {
#if defined (PCBV3)
TCCR0A &= ~(0b01<<COM0A0);
#else
PORTE |= (1 << OUT_E_BUZZER); // speaker output 'high'
#endif
}
else {
#if defined (PCVV3)
TCCR0A &= ~(0b01<<COM0A0);
#else
PORTE &= ~(1 << OUT_E_BUZZER); // speaker output 'low'
#endif
}
}
else {
#if defined (PCVV3)
TCCR0A &= ~(0b01<<COM0A0);
#else
PORTE &= ~(1 << OUT_E_BUZZER); // speaker output 'low'
#endif
}
#if 0
break;
case 2:
//PCMWav
break;
}
#endif
}
uint8_t hapticStrength = g_eeGeneral.hapticStrength;
if (toneHaptic == 1) {
if ((hapticTick <= hapticStrength - 1) && hapticStrength > 0) {
HAPTIC_ON; // haptic output 'high'
hapticTick++;
}
else {
HAPTIC_OFF; //haptic output low
hapticTick = 0;
}
}
else {
HAPTIC_OFF; // haptic output 'low'
}
}
else {
PORTE &= ~(1 << OUT_E_BUZZER); // speaker output 'low'
HAPTIC_OFF;
}
//step through array checking if we have any tones to play
//next heartbeat will play whatever we put in queue
if ((queueToneStart[0] > 0 || queueToneHaptic[0] == 1) && toneTimeLeft <= 0
&& queueState == 0) {
if (queueToneEnd[0] > 0 && queueToneEnd[0] != queueToneStart[0]) {
if (queueToneStart[0] > queueToneEnd[0]) { //tone going down
z = queueToneStart[0] - queueToneEnd[0];
rateOfChange = -2;
}
else { //tone going up
z = queueToneEnd[0] - queueToneStart[0];
rateOfChange = 2;
}
if (queueToneStart[0] > 0) {
toneFreq = queueToneStart[0] + g_eeGeneral.speakerPitch + BEEP_OFFSET; // add pitch compensator
}
else {
toneFreq = queueToneStart[0]; // done so hapticOnly option can work
}
toneFreqEnd = queueToneEnd[0] + g_eeGeneral.speakerPitch + BEEP_OFFSET;
toneTimeLeft = z;
tonePause = queueTonePause[0];
toneRepeat = queueToneRepeat[0];
toneHaptic = queueToneHaptic[0];
}
else {
//simple tone handler
if (queueToneStart[0] > 0) {
toneFreq = (queueToneStart[0] + g_eeGeneral.speakerPitch) + BEEP_OFFSET; // add pitch compensator
}
else {
toneFreq = queueToneStart[0];
}
rateOfChange = 0;
toneFreqEnd = 0;
toneTimeLeft = queueToneLength[0];
tonePause = queueTonePause[0];
toneRepeat = queueToneRepeat[0];
toneHaptic = queueToneHaptic[0];
}
queueState = 1;
if (toneRepeat != 0 && inToneRepeat == 0) {
inToneRepeat = 1;
toneRepeatCnt = toneRepeat;
}
if (inToneRepeat == 1) {
toneRepeatCnt--;
if (toneRepeatCnt <= 0) {
inToneRepeat = 0;
restack();
}
}
else {
restack();
}
}
hTimer = AUDIO_QUEUE_HEARTBEAT_NORM; // default
if (g_eeGeneral.beeperVal == 2) {
//xshort
hTimer = AUDIO_QUEUE_HEARTBEAT_XSHORT;
}
else if (g_eeGeneral.beeperVal == 3) {
//short
hTimer = AUDIO_QUEUE_HEARTBEAT_SHORT;
}
else if (g_eeGeneral.beeperVal == 5) {
//long
hTimer = AUDIO_QUEUE_HEARTBEAT_LONG;
}
else if (g_eeGeneral.beeperVal == 6) {
//xlong
hTimer = AUDIO_QUEUE_HEARTBEAT_XLONG;
}
heartbeatTimer++;
if (heartbeatTimer >= hTimer) {
heartbeatTimer = 0;
if (queueState == 1) {
if (toneTimeLeft > 0) {
toneFreq += rateOfChange; // -2, 0 or 2
toneTimeLeft--; //time gets counted down
}
if (toneTimeLeft <= 0) {
if (tonePause-- <= 0) {
queueState = 0;
}
}
}
}
}
void audioQueue::playNow(uint8_t tStart, uint8_t tLen, uint8_t tPause,
uint8_t tRepeat, uint8_t tHaptic, uint8_t tEnd)
{
t_queueToneStart = tStart;
t_queueToneLength = tLen;
t_queueTonePause = tPause;
t_queueToneHaptic = tHaptic;
t_queueToneRepeat = tRepeat;
t_queueToneEnd = tEnd;
commit(1);
}
void audioQueue::playASAP(uint8_t tStart, uint8_t tLen, uint8_t tPause,
uint8_t tRepeat, uint8_t tHaptic, uint8_t tEnd)
{
t_queueToneStart = tStart;
t_queueToneLength = tLen;
t_queueTonePause = tPause;
t_queueToneHaptic = tHaptic;
t_queueToneRepeat = tRepeat;
t_queueToneEnd = tEnd;
commit(0);
}
#ifdef FRSKY
//this is done so the menu selections only plays tone once!
void audioQueue::frskyeventSample(uint8_t e) {
if(frskySample != e) {
aqinit(); //flush the queue
frskyevent(e);
frskySample = e;
}
}
void audioQueue::frskyevent(uint8_t e) {
// example playASAP(tStart,tLen,tPause,tRepeat,tHaptic,tEnd);
switch(e) {
case AU_FRSKY_WARN1:
playASAP(BEEP_DEFAULT_FREQ+20,25,5,2,1);
break;
case AU_FRSKY_WARN2:
playASAP(BEEP_DEFAULT_FREQ+30,25,5,2,1);
break;
case AU_FRSKY_CHEEP:
playASAP(BEEP_DEFAULT_FREQ+30,20,2,2,1,BEEP_DEFAULT_FREQ+25);
break;
case AU_FRSKY_RING:
playASAP(BEEP_DEFAULT_FREQ+25,2,2,10,1);
playASAP(BEEP_DEFAULT_FREQ+25,2,10,1,1);
playASAP(BEEP_DEFAULT_FREQ+25,2,2,10,1);
break;
case AU_FRSKY_SCIFI:
playASAP(80,4,3,2,0,70);
playASAP(60,4,3,2,0,70);
playASAP(70,2,1,0,2);
break;
case AU_FRSKY_ROBOT:
playASAP(70,2,1,1,1);
playASAP(50,6,2,1,1);
playASAP(80,6,2,1,1);
break;
case AU_FRSKY_CHIRP:
playASAP(BEEP_DEFAULT_FREQ+40,2,1,2,1);
playASAP(BEEP_DEFAULT_FREQ+54,2,1,3,1);
break;
case AU_FRSKY_TADA:
playASAP(50,10,5);
playASAP(90,10,5);
playASAP(110,6,4,2);
break;
case AU_FRSKY_CRICKET:
playASAP(80,1,10,3,1);
playASAP(80,1,20,1,1);
playASAP(80,1,10,3,1);
break;
case AU_FRSKY_SIREN:
playASAP(10,5,5,2,1,40);
break;
case AU_FRSKY_ALARMC:
playASAP(50,5,10,2,1);
playASAP(70,5,20,1,1);
playASAP(50,5,10,2,1);
playASAP(70,5,20,1,1);
break;
case AU_FRSKY_RATATA:
playASAP(BEEP_DEFAULT_FREQ+50,2,10,10,1);
break;
case AU_FRSKY_TICK:
playASAP(BEEP_DEFAULT_FREQ+50,2,50,2,1);
break;
case AU_FRSKY_HAPTIC1:
playASAP(0,2,10,1,1);
break;
case AU_FRSKY_HAPTIC2:
playASAP(0,2,10,2,1);
break;
case AU_FRSKY_HAPTIC3:
playASAP(0,2,10,3,1);
break;
default:
break;
}
}
#endif
void audioQueue::event(uint8_t e, uint8_t f) {
uint8_t beepVal = g_eeGeneral.beeperVal;
switch (e) {
//startup tune
// case 0:
case AU_TADA:
playASAP(50, 10, 5);
playASAP(90, 10, 5);
playASAP(110, 6, 4, 2);
break;
//warning one
// case 1:
case AU_WARNING1:
playNow(BEEP_DEFAULT_FREQ, 25, 1, 0, 1);
break;
//warning two
//case 2:
case AU_WARNING2:
playNow(BEEP_DEFAULT_FREQ, 34, 1, 0, 1);
break;
//warning three
//case 3:
case AU_WARNING3:
playNow(BEEP_DEFAULT_FREQ, 15, 1, 0, 1);
break;
//error
//case 4:
case AU_ERROR:
playNow(BEEP_DEFAULT_FREQ, 30, 1, 0, 1);
break;
//keypad up (seems to be used when going left/right through system menu options. 0-100 scales etc)
//case 5:
case AU_KEYPAD_UP:
if (beepVal != BEEP_NOKEYS) {
playNow(BEEP_KEY_UP_FREQ, 2, 1);
}
break;
//keypad down (seems to be used when going left/right through system menu options. 0-100 scales etc)
//case 6:
case AU_KEYPAD_DOWN:
if (beepVal != BEEP_NOKEYS) {
playNow(BEEP_KEY_DOWN_FREQ, 2, 1);
}
break;
//trim sticks move
//case 7:
case AU_TRIM_MOVE:
//if(beepVal != BEEP_NOKEYS){
playNow(f, 2, 1);
//}
break;
//trim sticks center
//case 8:
case AU_TRIM_MIDDLE:
//if(beepVal != BEEP_NOKEYS){
playNow(BEEP_DEFAULT_FREQ, 10, 2, 0, 1);
//}
break;
//menu display (also used by a few generic beeps)
//case 9:
case AU_MENUS:
if (beepVal != BEEP_NOKEYS) {
playNow(BEEP_DEFAULT_FREQ, 2, 2, 0, 1);
}
break;
//pot/stick center
//case 10:
case AU_POT_STICK_MIDDLE:
playNow(BEEP_DEFAULT_FREQ + 50, 3, 1, 0, 1);
break;
//mix warning 1
//case 11:
case AU_MIX_WARNING_1:
playNow(BEEP_DEFAULT_FREQ + 50, 2, 1, 1, 1);
break;
//mix warning 2
//case 12:
case AU_MIX_WARNING_2:
playNow(BEEP_DEFAULT_FREQ + 52, 2, 1, 2, 1);
break;
//mix warning 3
//case 13:
case AU_MIX_WARNING_3:
playNow(BEEP_DEFAULT_FREQ + 54, 2, 1, 3, 1);
break;
//time 30 seconds left
//case 14:
case AU_TIMER_30:
playNow(BEEP_DEFAULT_FREQ + 50, 5, 3, 3, 1);
break;
//time 20 seconds left
//case 15:
case AU_TIMER_20:
playNow(BEEP_DEFAULT_FREQ + 50, 5, 3, 2, 1);
break;
//time 10 seconds left
//case 16:
case AU_TIMER_10:
playNow(BEEP_DEFAULT_FREQ + 50, 5, 3, 1, 1);
break;
//time <3 seconds left
//case 17:
case AU_TIMER_LT3:
playNow(BEEP_DEFAULT_FREQ, 20, 5, 1, 1);
break;
//inactivity timer alert
//case 18:
case AU_INACTIVITY:
playASAP(70, 3, 2);
playASAP(50, 3, 5);
break;
//low battery in tx
//case 19:
case AU_TX_BATTERY_LOW:
playASAP(60, 4, 3, 2, 1, 70);
playASAP(80, 4, 3, 2, 1, 70);
break;
default:
break;
}
}
void audioDefevent(uint8_t e) {
audio.event(e, BEEP_DEFAULT_FREQ);
}

193
src/audio.h Normal file
View file

@ -0,0 +1,193 @@
/*
* Author - Rob Thomson <rob@marotori.com>
*
* 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
//audio
#define AUDIO_QUEUE_LENGTH (8) //8 seems to suit most alerts
#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)
#define AUDIO_QUEUE_HEARTBEAT_XSHORT (30) //speaker timing [Norm]
#define AUDIO_QUEUE_HEARTBEAT_SHORT (50) //speaker timing [Norm]
#define AUDIO_QUEUE_HEARTBEAT_NORM (77) //speaker timing [Norm]
#define AUDIO_QUEUE_HEARTBEAT_LONG (130) //speaker timing [Long]
#define AUDIO_QUEUE_HEARTBEAT_XLONG (200) //speaker timing [xLong]
#define HAPTIC_ON PORTG |= (1<<2)
#define HAPTIC_OFF PORTG &= ~(1<<2)
/* make sure the defines below always go in numeric order */
#define AU_TADA (0)
#define AU_WARNING1 (1)
#define AU_WARNING2 (2)
#define AU_WARNING3 (3)
#define AU_ERROR (4)
#define AU_KEYPAD_UP (5)
#define AU_KEYPAD_DOWN (6)
#define AU_TRIM_MOVE (7)
#define AU_TRIM_MIDDLE (8)
#define AU_MENUS (9)
#define AU_POT_STICK_MIDDLE (10)
#define AU_MIX_WARNING_1 (11)
#define AU_MIX_WARNING_2 (12)
#define AU_MIX_WARNING_3 (13)
#define AU_TIMER_30 (14)
#define AU_TIMER_20 (15)
#define AU_TIMER_10 (16)
#define AU_TIMER_LT3 (17)
#define AU_INACTIVITY (18)
#define AU_TX_BATTERY_LOW (19)
#ifdef FRSKY
#define AU_FRSKY_WARN1 (0)
#define AU_FRSKY_WARN2 (1)
#define AU_FRSKY_CHEEP (2)
#define AU_FRSKY_RING (3)
#define AU_FRSKY_SCIFI (4)
#define AU_FRSKY_ROBOT (5)
#define AU_FRSKY_CHIRP (6)
#define AU_FRSKY_TADA (7)
#define AU_FRSKY_CRICKET (8)
#define AU_FRSKY_SIREN (9)
#define AU_FRSKY_ALARMC (10)
#define AU_FRSKY_RATATA (11)
#define AU_FRSKY_TICK (12)
#define AU_FRSKY_HAPTIC1 (13)
#define AU_FRSKY_HAPTIC2 (14)
#define AU_FRSKY_HAPTIC3 (15)
#endif
#define BEEP_QUIET (0)
#define BEEP_NOKEYS (1)
#define BEEP_XSHORT (2)
#define BEEP_SHORT (3)
#define BEEP_NORMAL (4)
#define BEEP_LONG (5)
#define BEEP_XLONG (6)
struct audioQueue{
//queue temporaries
uint8_t t_queueToneStart;
uint8_t t_queueToneEnd;
uint8_t t_queueToneLength;
uint8_t t_queueTonePause;
uint8_t t_queueToneRepeat;
uint8_t t_queueToneHaptic;
//queue general vars
uint8_t toneFreq;
uint8_t toneFreqEnd;
uint8_t toneTimeLeft;
int8_t rateOfChange;
uint8_t tonePause;
uint8_t queueState;
uint8_t toneRepeat;
uint8_t toneRepeatCnt;
uint8_t inToneRepeat;
uint8_t toneHaptic;
uint8_t hapticTick;
uint8_t heartbeatTimer;
#ifdef FRSKY
uint8_t frskySample;
#endif
//queue arrays
uint8_t queueToneStart[AUDIO_QUEUE_LENGTH];
uint8_t queueToneEnd[AUDIO_QUEUE_LENGTH];
uint8_t queueToneLength[AUDIO_QUEUE_LENGTH];
uint8_t queueTonePause[AUDIO_QUEUE_LENGTH];
uint8_t queueToneRepeat[AUDIO_QUEUE_LENGTH];
uint8_t queueToneHaptic[AUDIO_QUEUE_LENGTH];
//beep length table
// uint8_t beepLenTable[10];
public:
//constructor
audioQueue();
void aqinit() ; // To stop constructor being compiled twice
//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 tStart,uint8_t tLen,uint8_t tPause,uint8_t tRepeat=0,uint8_t tHaptic=0,uint8_t tEnd=0);
void playASAP(uint8_t tStart,uint8_t tLen,uint8_t tPause,uint8_t tRepeat=0,uint8_t tHaptic=0,uint8_t tEnd=0);
bool busy();
void event(uint8_t e,uint8_t f=BEEP_DEFAULT_FREQ);
#ifdef FRSKY
void frskyevent(uint8_t e);
void frskyeventSample(uint8_t e);
#endif
void commit( uint8_t toneInterupt );
//set all temporary buffers to default
void flushTemp();
void flushqueue( uint8_t startpos ) ;
void restack();
//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);
};
//wrapper function - dirty but results in a space saving!!!
extern audioQueue audio;
//void audioevent(uint8_t e,uint8_t f=BEEP_DEFAULT_FREQ);
void audioDefevent(uint8_t e);
void audioError();
#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_3() audioDefevent(AU_MIX_WARNING_3)
#define AUDIO_HEARTBEAT() audio.heartbeat()
#endif // audio_h

45
src/beeper.cpp Normal file
View file

@ -0,0 +1,45 @@
/*
* Authors (alphabetical order)
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
*
* gruvin9x is based on code named er9x by
* Author - Erez Raviv <erezraviv@gmail.com>, which is in turn
* was based on 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"
uint8_t g_beepCnt;
uint8_t beepAgain = 0;
uint8_t beepAgainOrig = 0;
uint8_t beepOn = false;
// The various "beep" tone lengths
static prog_uint8_t APM beepTab[]= {
// 0 1 2 3 4
0, 1, 8, 30, 100, //silent
1, 1, 8, 30, 100, //xShort
1, 1, 8, 30, 100, //short
1, 1, 8, 30, 100, //normal
1, 1, 15, 50, 150, //long
10, 10, 30, 50, 150, //xLong
};
void beep(uint8_t val)
{
if (g_eeGeneral.beeperVal>0) {
_beep(pgm_read_byte(beepTab+5*g_eeGeneral.beeperVal-5+val));
}
}

94
src/beeper.h Normal file
View file

@ -0,0 +1,94 @@
/*
* Authors (alphabetical order)
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
*
* gruvin9x is based on code named er9x by
* Author - Erez Raviv <erezraviv@gmail.com>, which is in turn
* was based on 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 BEEPER_H
#define BEEPER_H
extern uint8_t g_beepCnt;
extern uint8_t g_beepVal[5];
extern uint8_t beepAgain;
extern uint8_t beepAgainOrig;
extern uint8_t beepOn;
extern void beep(uint8_t val);
#define AUDIO_KEYPAD_UP() beep(0)
#define AUDIO_KEYPAD_DOWN() beep(0)
#define AUDIO_MENUS() beep(0)
#define AUDIO_TRIM() beep(1)
#define AUDIO_WARNING2() beep(2)
#define AUDIO_WARNING1() beep(3)
#define AUDIO_ERROR() beep(4)
#define IS_AUDIO_BUSY() (g_beepCnt || beepAgain || beepOn)
#define AUDIO_TIMER_30() { beepAgain=2; beep(2); }
#define AUDIO_TIMER_20() { beepAgain=1; beep(2); }
#define AUDIO_TIMER_10() beep(2)
#define AUDIO_TIMER_LT3() beep(2)
#define AUDIO_MINUTE_BEEP() beep(2)
#define AUDIO_INACTIVITY() beep(3)
#define AUDIO_MIX_WARNING_1() beep(1)
#define AUDIO_MIX_WARNING_3() beep(1)
inline void AUDIO_HEARTBEAT()
{
//cnt >/=0
//beepon/off
//beepagain y/n
if(g_beepCnt) {
if(!beepAgainOrig) {
beepAgainOrig = g_beepCnt;
beepOn = true;
}
g_beepCnt--;
}
else
{
if(beepAgain && beepAgainOrig) {
beepOn = !beepOn;
g_beepCnt = beepOn ? beepAgainOrig : 8;
if(beepOn) beepAgain--;
}
else {
beepAgainOrig = 0;
beepOn = false;
warble = false;
}
}
// G: use original external buzzer for beeps
if (beepOn) {
static bool warbleC;
warbleC = warble && !warbleC;
if (warbleC)
PORTE &= ~(1<<OUT_E_BUZZER);//buzzer off
else
PORTE |= (1<<OUT_E_BUZZER);//buzzer on
}
else {
PORTE &= ~(1<<OUT_E_BUZZER);
}
}
#endif

View file

@ -444,12 +444,13 @@ void per10ms()
} }
else if (g_eeGeneral.enableTelemetryAlarm && (g_model.frsky.channels[0].ratio || g_model.frsky.channels[1].ratio)) { else if (g_eeGeneral.enableTelemetryAlarm && (g_model.frsky.channels[0].ratio || g_model.frsky.channels[1].ratio)) {
#if defined (BEEPSPKR) #if defined (BEEPSPKR)
if (!(g_tmr10ms % 30)) beepWarn2Spkr((g_tmr10ms % 60) ? 25 : 20); if (!(g_tmr10ms % 30)) {
audioDefevent(AU_WARNING1);
}
#else #else
if (!(g_tmr10ms % 30)) if (!(g_tmr10ms % 30)) {
{
warble = !(g_tmr10ms % 60); warble = !(g_tmr10ms % 60);
beepWarn2(); AUDIO_WARNING2();
} }
#endif #endif
} }
@ -457,15 +458,7 @@ void per10ms()
#endif #endif
// These moved here from perOut() [gruvin9x.cpp] to improve beep trigger reliability. // These moved here from perOut() [gruvin9x.cpp] to improve beep trigger reliability.
#if defined (BEEPSPKR) if(mixWarning & 1) if(((g_tmr10ms&0xFF)== 0)) AUDIO_MIX_WARNING_1();
if(mixWarning & 1) if(((g_tmr10ms&0xFF)== 0)) beepWarn1Spkr(BEEP_DEFAULT_FREQ+7); if(mixWarning & 2) if(((g_tmr10ms&0xFF)== 64) || ((g_tmr10ms&0xFF)== 72)) AUDIO_MIX_WARNING_1();
if(mixWarning & 2) if(((g_tmr10ms&0xFF)== 64) if(mixWarning & 4) if(((g_tmr10ms&0xFF)==128) || ((g_tmr10ms&0xFF)==136) || ((g_tmr10ms&0xFF)==144)) AUDIO_MIX_WARNING_3();
|| ((g_tmr10ms&0xFF)== 72)) beepWarn1Spkr(BEEP_DEFAULT_FREQ+9);
if(mixWarning & 4) if(((g_tmr10ms&0xFF)==128) || ((g_tmr10ms&0xFF)==136)
|| ((g_tmr10ms&0xFF)==144)) beepWarn1Spkr(BEEP_DEFAULT_FREQ+11);
#else
if(mixWarning & 1) if(((g_tmr10ms&0xFF)== 0)) beepWarn1();
if(mixWarning & 2) if(((g_tmr10ms&0xFF)== 64) || ((g_tmr10ms&0xFF)== 72)) beepWarn1();
if(mixWarning & 4) if(((g_tmr10ms&0xFF)==128) || ((g_tmr10ms&0xFF)==136) || ((g_tmr10ms&0xFF)==144)) beepWarn1();
#endif
} }

View file

@ -1,4 +1,3 @@
#ifndef file_h
/* /*
* Authors (alphabetical order) * Authors (alphabetical order)
* - Bertrand Songis <bsongis@gmail.com> * - Bertrand Songis <bsongis@gmail.com>
@ -20,6 +19,7 @@
* *
*/ */
#ifndef file_h
#define file_h #define file_h
#include <inttypes.h> #include <inttypes.h>

View file

@ -56,34 +56,65 @@ MenuFuncP_PROGMEM APM menuTabDiag[] = {
menuProcDiagCalib menuProcDiagCalib
}; };
enum menuProcSetupItems {
ITEM_SETUP_BASE=17,
#ifdef SPLASH
ITEM_SETUP_SPLASH,
#endif
#ifdef BEEPSPKR
ITEM_SETUP_SPEAKER,
#endif
#ifdef HAPTIC
ITEM_SETUP_HAPTIC,
#endif
ITEM_SETUP_MAX
};
void menuProcSetup(uint8_t event) void menuProcSetup(uint8_t event)
{ {
#ifdef SPLASH
#define COUNT_ITEMS 19
#else
#define COUNT_ITEMS 18
#endif
#undef PARAM_OFS #undef PARAM_OFS
#define PARAM_OFS 17*FW #define PARAM_OFS 17*FW
SIMPLE_MENU(STR_MENURADIOSETUP, menuTabDiag, e_Setup, COUNT_ITEMS+1); SIMPLE_MENU(STR_MENURADIOSETUP, menuTabDiag, e_Setup, ITEM_SETUP_MAX+1);
int8_t sub = m_posVert; int8_t sub = m_posVert;
// last 2 lines (radio mode) are non break-able // last 2 lines (radio mode) are non break-able
if(s_pgOfs==COUNT_ITEMS-7) s_pgOfs= sub<(COUNT_ITEMS-4) ? COUNT_ITEMS-8 : COUNT_ITEMS-6; // TODO line to be checked
if(s_pgOfs==ITEM_SETUP_MAX-7) s_pgOfs= sub<(ITEM_SETUP_MAX-4) ? ITEM_SETUP_MAX-8 : ITEM_SETUP_MAX-6;
uint8_t y = 1*FH; uint8_t y = 1*FH;
uint8_t subN = 1; uint8_t subN = 1;
if(s_pgOfs<subN) { if(s_pgOfs<subN) {
lcd_puts_P(0, y, STR_BEEPER); lcd_puts_P(0, y, STR_BEEPER);
lcd_putsnAtt(PARAM_OFS - FW, y, STR_VBEEPER+LEN_VBEEPER*g_eeGeneral.beeperVal, LEN_VBEEPER, (sub==subN ? INVERS:0)); lcd_putsnAtt(PARAM_OFS - 2*FW, y, STR_VBEEPER+LEN_VBEEPER*g_eeGeneral.beeperVal, LEN_VBEEPER, (sub==subN ? INVERS:0));
if(sub==subN) CHECK_INCDEC_GENVAR(event, g_eeGeneral.beeperVal, 0, 4); if(sub==subN) CHECK_INCDEC_GENVAR(event, g_eeGeneral.beeperVal, 0, 6);
if((y+=FH)>7*FH) return; if((y+=FH)>7*FH) return;
}subN++; }subN++;
#ifdef BEEPSPKR
if(s_pgOfs<subN) {
lcd_puts_P(0, y, PSTR("Speaker Pitch"));
lcd_outdezAtt(PARAM_OFS,y,g_eeGeneral.speakerPitch,(sub==subN ? INVERS : 0)|LEFT);
if(sub==subN) {
CHECK_INCDEC_GENVAR(event, g_eeGeneral.speakerPitch, 1, 100);
}
if((y+=FH)>7*FH) return;
}subN++;
#endif
#ifdef HAPTIC
if(s_pgOfs<subN) {
lcd_puts_P(0, y, PSTR("Haptic Strength"));
lcd_outdezAtt(PARAM_OFS,y,g_eeGeneral.hapticStrength,(sub==subN ? INVERS : 0)|LEFT);
if(sub==subN) {
CHECK_INCDEC_GENVAR(event, g_eeGeneral.speakerPitch, 0, 5);
}
if((y+=FH)>7*FH) return;
}subN++;
#endif
if(s_pgOfs<subN) { if(s_pgOfs<subN) {
lcd_puts_P(0, y, STR_CONTRAST); lcd_puts_P(0, y, STR_CONTRAST);
lcd_outdezAtt(PARAM_OFS,y,g_eeGeneral.contrast,(sub==subN ? INVERS : 0)|LEFT); lcd_outdezAtt(PARAM_OFS,y,g_eeGeneral.contrast,(sub==subN ? INVERS : 0)|LEFT);
@ -420,7 +451,7 @@ void menuProcTrainer(uint8_t event)
if (event==EVT_KEY_FIRST(KEY_MENU)){ if (event==EVT_KEY_FIRST(KEY_MENU)){
memcpy(g_eeGeneral.trainer.calib, g_ppmIns, sizeof(g_eeGeneral.trainer.calib)); memcpy(g_eeGeneral.trainer.calib, g_ppmIns, sizeof(g_eeGeneral.trainer.calib));
eeDirty(EE_GENERAL); eeDirty(EE_GENERAL);
beepKey(); AUDIO_KEYPAD_UP();
} }
} }
} }

View file

@ -119,8 +119,8 @@ void doLogs()
if (result != FR_OK) if (result != FR_OK)
{ {
g_logState = -result; g_logState = -result;
beepAgain = result - 1; // TODO beepAgain = result - 1;
beepKey(); AUDIO_KEYPAD_UP();
} }
else else
{ {
@ -129,14 +129,14 @@ void doLogs()
if (result != FR_OK) if (result != FR_OK)
{ {
g_logState = -result; g_logState = -result;
beepAgain = result - 1; // TODO beepAgain = result - 1;
beepKey(); AUDIO_KEYPAD_UP();
} }
else else
{ {
f_lseek(&g_oLogFile, g_oLogFile.fsize); // append f_lseek(&g_oLogFile, g_oLogFile.fsize); // append
g_logState = 1; g_logState = 1;
beepWarn2(); AUDIO_WARNING2();
} }
} }
} }
@ -149,7 +149,7 @@ void doLogs()
else if (g_logState > 0) else if (g_logState > 0)
{ {
f_close(&g_oLogFile); f_close(&g_oLogFile);
beepWarn2(); AUDIO_WARNING2();
g_logState = 0; g_logState = 0;
} }
} }

View file

@ -101,12 +101,14 @@ void menuMainView(uint8_t event)
switch(event) switch(event)
{ {
/* TODO if timer2 is OFF, it's possible to use this timer2 as in er9x...
case EVT_KEY_BREAK(KEY_MENU): case EVT_KEY_BREAK(KEY_MENU):
if (view_base == e_timer2) { if (view_base == e_timer2) {
// TODO Timer2_running = !Timer2_running; Timer2_running = !Timer2_running;
beepKey(); AUDIO_KEYPAD_UP();
} }
break; break;
*/
case EVT_KEY_LONG(KEY_MENU):// go to last menu case EVT_KEY_LONG(KEY_MENU):// go to last menu
pushMenu(lastPopMenu()); pushMenu(lastPopMenu());
killEvents(event); killEvents(event);
@ -124,7 +126,7 @@ void menuMainView(uint8_t event)
#endif #endif
g_eeGeneral.view = (view + (event == EVT_KEY_BREAK(KEY_RIGHT) ? ALTERNATE_VIEW : tabViews[view_base]*ALTERNATE_VIEW-ALTERNATE_VIEW)) % (tabViews[view_base]*ALTERNATE_VIEW); g_eeGeneral.view = (view + (event == EVT_KEY_BREAK(KEY_RIGHT) ? ALTERNATE_VIEW : tabViews[view_base]*ALTERNATE_VIEW-ALTERNATE_VIEW)) % (tabViews[view_base]*ALTERNATE_VIEW);
eeDirty(EE_GENERAL); eeDirty(EE_GENERAL);
beepKey(); AUDIO_KEYPAD_UP();
break; break;
case EVT_KEY_LONG(KEY_RIGHT): case EVT_KEY_LONG(KEY_RIGHT):
pushMenu(menuProcModelSelect); pushMenu(menuProcModelSelect);
@ -138,7 +140,7 @@ void menuMainView(uint8_t event)
g_eeGeneral.view = view+1; g_eeGeneral.view = view+1;
if(g_eeGeneral.view>=MAX_VIEWS) g_eeGeneral.view=0; if(g_eeGeneral.view>=MAX_VIEWS) g_eeGeneral.view=0;
eeDirty(EE_GENERAL); eeDirty(EE_GENERAL);
beepKey(); AUDIO_KEYPAD_UP();
break; break;
case EVT_KEY_BREAK(KEY_DOWN): case EVT_KEY_BREAK(KEY_DOWN):
if(view>0) if(view>0)
@ -146,7 +148,7 @@ void menuMainView(uint8_t event)
else else
g_eeGeneral.view = MAX_VIEWS-1; g_eeGeneral.view = MAX_VIEWS-1;
eeDirty(EE_GENERAL); eeDirty(EE_GENERAL);
beepKey(); AUDIO_KEYPAD_UP();
break; break;
case EVT_KEY_LONG(KEY_UP): case EVT_KEY_LONG(KEY_UP):
chainMenu(menuProcStatistic); chainMenu(menuProcStatistic);
@ -176,7 +178,7 @@ void menuMainView(uint8_t event)
else { else {
resetTimer(0); resetTimer(0);
} }
beepKey(); AUDIO_KEYPAD_UP();
break; break;
case EVT_KEY_LONG(KEY_EXIT): case EVT_KEY_LONG(KEY_EXIT):
resetTimer(0); resetTimer(0);
@ -184,7 +186,7 @@ void menuMainView(uint8_t event)
#ifdef FRSKY #ifdef FRSKY
resetTelemetry(); resetTelemetry();
#endif #endif
beepKey(); AUDIO_KEYPAD_UP();
break; break;
case EVT_ENTRY: case EVT_ENTRY:
killEvents(KEY_EXIT); killEvents(KEY_EXIT);

View file

@ -63,19 +63,12 @@ int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, ui
} }
if(event==EVT_KEY_FIRST(kpl) || event== EVT_KEY_REPT(kpl) || (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_UP) || event== EVT_KEY_REPT(KEY_UP))) ) { if(event==EVT_KEY_FIRST(kpl) || event== EVT_KEY_REPT(kpl) || (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_UP) || event== EVT_KEY_REPT(KEY_UP))) ) {
newval++; newval++;
#if defined (BEEPSPKR) AUDIO_KEYPAD_UP();
beepKeySpkr(BEEP_KEY_UP_FREQ);
#else
beepKey();
#endif
kother=kmi; kother=kmi;
}else if(event==EVT_KEY_FIRST(kmi) || event== EVT_KEY_REPT(kmi) || (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_DOWN) || event== EVT_KEY_REPT(KEY_DOWN))) ) { }
else if(event==EVT_KEY_FIRST(kmi) || event== EVT_KEY_REPT(kmi) || (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_DOWN) || event== EVT_KEY_REPT(KEY_DOWN))) ) {
newval--; newval--;
#if defined (BEEPSPKR) AUDIO_KEYPAD_DOWN();
beepKeySpkr(BEEP_KEY_DOWN_FREQ);
#else
beepKey();
#endif
kother=kpl; kother=kpl;
} }
if((kother != (uint8_t)-1) && keyState((EnumKeys)kother)){ if((kother != (uint8_t)-1) && keyState((EnumKeys)kother)){
@ -98,33 +91,21 @@ int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, ui
{ {
newval = i_max; newval = i_max;
killEvents(event); killEvents(event);
#if defined (BEEPSPKR) AUDIO_WARNING2();
beepWarn2Spkr(BEEP_KEY_UP_FREQ);
#else
beepWarn2();
#endif
} }
if(newval < i_min) if(newval < i_min)
{ {
newval = i_min; newval = i_min;
killEvents(event); killEvents(event);
#if defined (BEEPSPKR) AUDIO_WARNING2();
beepWarn2Spkr(BEEP_KEY_DOWN_FREQ);
#else
beepWarn2();
#endif
} }
if(newval != val){ if(newval != val){
if(newval==0) { if(newval==0) {
pauseEvents(event); // delay before auto-repeat continues pauseEvents(event); // delay before auto-repeat continues
#if defined (BEEPSPKR) if (newval>val) // TODO check if without BEEPSPKR it's optimized!
if (newval>val) AUDIO_KEYPAD_UP();
beepWarn2Spkr(BEEP_KEY_UP_FREQ);
else else
beepWarn2Spkr(BEEP_KEY_DOWN_FREQ); AUDIO_KEYPAD_DOWN();
#else
beepKey();
#endif
} }
eeDirty(i_flags & (EE_GENERAL|EE_MODEL)); eeDirty(i_flags & (EE_GENERAL|EE_MODEL));
checkIncDec_Ret = (newval > val ? 1 : -1); checkIncDec_Ret = (newval > val ? 1 : -1);
@ -318,8 +299,9 @@ bool check(uint8_t event, uint8_t curr, MenuFuncP *menuTab, uint8_t menuTabSize,
popMenu(); //beeps itself popMenu(); //beeps itself
} }
else { else {
beepKey(); AUDIO_MENUS();
minit();BLINK_SYNC; minit();
BLINK_SYNC;
} }
break; break;
@ -380,7 +362,7 @@ void popMenu()
{ {
if (g_menuStackPtr>0) { if (g_menuStackPtr>0) {
g_menuStackPtr = g_menuStackPtr-1; g_menuStackPtr = g_menuStackPtr-1;
beepKey(); AUDIO_KEYPAD_UP();
m_posHorz = 0; m_posHorz = 0;
m_posVert = g_menuPos[g_menuStackPtr]; m_posVert = g_menuPos[g_menuStackPtr];
(*g_menuStack[g_menuStackPtr])(EVT_ENTRY_UP); (*g_menuStack[g_menuStackPtr])(EVT_ENTRY_UP);
@ -394,7 +376,7 @@ void chainMenu(MenuFuncP newMenu)
{ {
g_menuStack[g_menuStackPtr] = newMenu; g_menuStack[g_menuStackPtr] = newMenu;
(*newMenu)(EVT_ENTRY); (*newMenu)(EVT_ENTRY);
beepKey(); AUDIO_MENUS();
} }
void pushMenu(MenuFuncP newMenu) void pushMenu(MenuFuncP newMenu)
@ -408,7 +390,7 @@ void pushMenu(MenuFuncP newMenu)
alert(STR_MENUSERROR); alert(STR_MENUSERROR);
return; return;
} }
beepKey(); AUDIO_MENUS();
g_menuStack[g_menuStackPtr] = newMenu; g_menuStack[g_menuStackPtr] = newMenu;
(*newMenu)(EVT_ENTRY); (*newMenu)(EVT_ENTRY);
} }

View file

@ -264,7 +264,7 @@ void menuProcModelSelect(uint8_t event)
chainMenu(_event == EVT_KEY_FIRST(KEY_RIGHT) ? menuProcModel : menuTabModel[DIM(menuTabModel)-1]); chainMenu(_event == EVT_KEY_FIRST(KEY_RIGHT) ? menuProcModel : menuTabModel[DIM(menuTabModel)-1]);
return; return;
} }
beepWarn(); AUDIO_WARNING1(); // TODO it was beepWarn();
break; break;
case EVT_KEY_FIRST(KEY_UP): case EVT_KEY_FIRST(KEY_UP):
case EVT_KEY_FIRST(KEY_DOWN): case EVT_KEY_FIRST(KEY_DOWN):
@ -279,7 +279,7 @@ void menuProcModelSelect(uint8_t event)
m_posVert = eeFindEmptyModel(s_copySrcRow, _event==EVT_KEY_FIRST(KEY_DOWN)); m_posVert = eeFindEmptyModel(s_copySrcRow, _event==EVT_KEY_FIRST(KEY_DOWN));
if (m_posVert == (uint8_t)-1) { if (m_posVert == (uint8_t)-1) {
// no free room for duplicating the model // no free room for duplicating the model
beepWarn(); AUDIO_WARNING1();
m_posVert = oldSub; m_posVert = oldSub;
s_copyMode = 0; // TODO only this one? s_copyMode = 0; // TODO only this one?
s_copyTgtOfs = 0; s_copyTgtOfs = 0;
@ -1926,7 +1926,7 @@ void menuProcTemplates(uint8_t event)
applyTemplate(sub); applyTemplate(sub);
if (sub==NUM_TEMPLATES) if (sub==NUM_TEMPLATES)
clearMixes(); clearMixes();
beepWarn1(); AUDIO_WARNING1();
break; break;
} }

View file

@ -95,6 +95,8 @@ PACK(typedef struct t_EEGeneral {
uint8_t templateSetup; //RETA order according to chout_ar array uint8_t templateSetup; //RETA order according to chout_ar array
int8_t PPM_Multiplier; int8_t PPM_Multiplier;
FrSkyRSSIAlarm frskyRssiAlarms[2]; FrSkyRSSIAlarm frskyRssiAlarms[2];
uint8_t speakerPitch;
uint8_t hapticStrength;
}) EEGeneral; }) EEGeneral;
// eeprom modelspec // eeprom modelspec

View file

@ -56,7 +56,12 @@ uint8_t toneFreq = BEEP_DEFAULT_FREQ;
uint8_t toneOn = false; uint8_t toneOn = false;
#endif #endif
bool warble = false; bool warble = false; // TODO is it needed with BEEPSPKR?
#ifdef BEEPSPKR
//new audio object
audioQueue audio;
#endif
uint8_t heartbeat; uint8_t heartbeat;
@ -651,9 +656,6 @@ void checkSwitches()
} }
} }
uint8_t g_beepCnt;
uint8_t g_beepVal[5];
void message(const prog_char * s) void message(const prog_char * s)
{ {
lcd_clear(); lcd_clear();
@ -671,7 +673,7 @@ void alert(const prog_char * s, bool defaults)
lcd_puts_P(64-LEN_PRESSANYKEY*FW/2, 7*FH, STR_PRESSANYKEY); lcd_puts_P(64-LEN_PRESSANYKEY*FW/2, 7*FH, STR_PRESSANYKEY);
refreshDisplay(); refreshDisplay();
lcdSetRefVolt(defaults ? 25 : g_eeGeneral.contrast); lcdSetRefVolt(defaults ? 25 : g_eeGeneral.contrast);
beepErr(); AUDIO_ERROR();
clearKeyEvents(); clearKeyEvents();
while(1) while(1)
{ {
@ -742,17 +744,17 @@ uint8_t checkTrim(uint8_t event)
killEvents(event); killEvents(event);
warble = false; warble = false;
#if defined (BEEPSPKR) #if defined (BEEPSPKR)
beepWarn2Spkr(after); audio.event(AU_TRIM_MOVE, after);
#else #else
beepWarn2(); AUDIO_WARNING2();
#endif #endif
} }
else { else {
if (event & _MSK_KEY_REPT) warble = true; if (event & _MSK_KEY_REPT) warble = true;
#if defined (BEEPSPKR) #if defined (BEEPSPKR)
beepTrimSpkr(after); audio.event(AU_TRIM_MOVE, after);
#else #else
beepWarn1(); AUDIO_TRIM();
#endif #endif
} }
return 0; return 0;
@ -886,10 +888,6 @@ uint16_t g_vbat100mV = 0;
volatile uint8_t tick10ms = 0; volatile uint8_t tick10ms = 0;
uint16_t g_LightOffCounter; uint16_t g_LightOffCounter;
uint8_t beepAgain = 0;
uint8_t beepAgainOrig = 0;
uint8_t beepOn = false;
FORCEINLINE bool checkSlaveMode() FORCEINLINE bool checkSlaveMode()
{ {
// no power -> only phone jack = slave mode // no power -> only phone jack = slave mode
@ -899,7 +897,7 @@ FORCEINLINE bool checkSlaveMode()
#else #else
static bool lastSlaveMode = false; static bool lastSlaveMode = false;
static uint8_t checkDelay = 0; static uint8_t checkDelay = 0;
if (g_beepCnt || beepAgain || beepOn) { if (IS_AUDIO_BUSY()) {
checkDelay = 20; checkDelay = 20;
} }
else if (checkDelay) { else if (checkDelay) {
@ -1085,7 +1083,7 @@ void perOut(int16_t *chanOut, uint8_t phase)
//===========BEEP CENTER================ //===========BEEP CENTER================
anaCenter &= g_model.beepANACenter; anaCenter &= g_model.beepANACenter;
if(((bpanaCenter ^ anaCenter) & anaCenter)) beepWarn1(); if(((bpanaCenter ^ anaCenter) & anaCenter)) AUDIO_WARNING1();
bpanaCenter = anaCenter; bpanaCenter = anaCenter;
anas[MIX_MAX-1] = RESX; // MAX anas[MIX_MAX-1] = RESX; // MAX
@ -1571,22 +1569,22 @@ void perMain()
if (last_tmr != s_timerVal[0]) { // beep only if seconds advance if (last_tmr != s_timerVal[0]) { // beep only if seconds advance
if (s_timerState[0] == TMR_RUNNING) { if (s_timerState[0] == TMR_RUNNING) {
if (g_eeGeneral.preBeep && g_model.timer1.val) { // beep when 30, 15, 10, 5,4,3,2,1 seconds remaining if (g_eeGeneral.preBeep && g_model.timer1.val) { // beep when 30, 15, 10, 5,4,3,2,1 seconds remaining
if(s_timerVal[0]==30) {beepAgain=2; beepWarn2();} //beep three times if(s_timerVal[0]==30) AUDIO_TIMER_30(); //beep three times
if(s_timerVal[0]==20) {beepAgain=1; beepWarn2();} //beep two times if(s_timerVal[0]==20) AUDIO_TIMER_20(); //beep two times
if(s_timerVal[0]==10) beepWarn2(); if(s_timerVal[0]==10) AUDIO_TIMER_10();
if(s_timerVal[0]<= 3) beepWarn2(); if(s_timerVal[0]<= 3) AUDIO_TIMER_LT3();
if(g_eeGeneral.flashBeep && (s_timerVal[0]==30 || s_timerVal[0]==20 || s_timerVal[0]==10 || s_timerVal[0]<=3)) if(g_eeGeneral.flashBeep && (s_timerVal[0]==30 || s_timerVal[0]==20 || s_timerVal[0]==10 || s_timerVal[0]<=3))
g_LightOffCounter = FLASH_DURATION; g_LightOffCounter = FLASH_DURATION;
} }
if (g_eeGeneral.minuteBeep && (((g_model.timer1.val ? g_model.timer1.val-s_timerVal[0] : s_timerVal[0])%60)==0)) { // short beep every minute if (g_eeGeneral.minuteBeep && (((g_model.timer1.val ? g_model.timer1.val-s_timerVal[0] : s_timerVal[0])%60)==0)) { // short beep every minute
beepWarn2(); AUDIO_MINUTE_BEEP();
if(g_eeGeneral.flashBeep) g_LightOffCounter = FLASH_DURATION; if(g_eeGeneral.flashBeep) g_LightOffCounter = FLASH_DURATION;
} }
} }
else if(s_timerState[0] == TMR_BEEPING) { else if(s_timerState[0] == TMR_BEEPING) {
beepWarn(); AUDIO_WARNING1();
if(g_eeGeneral.flashBeep) g_LightOffCounter = FLASH_DURATION; if(g_eeGeneral.flashBeep) g_LightOffCounter = FLASH_DURATION;
} }
last_tmr = s_timerVal[0]; last_tmr = s_timerVal[0];
@ -1628,7 +1626,7 @@ void perMain()
inacCounter=0; inacCounter=0;
} }
if(inacCounter>((uint32_t)g_eeGeneral.inactivityTimer*100*60)) if(inacCounter>((uint32_t)g_eeGeneral.inactivityTimer*100*60))
if((inacCounter&0x3F)==10) beepWarn(); if((inacCounter&0x3F)==10) AUDIO_INACTIVITY();
} }
if (trimsCheckTimer > 0) if (trimsCheckTimer > 0)
@ -1741,31 +1739,13 @@ Gruvin:
static uint8_t s_batCheck; static uint8_t s_batCheck;
s_batCheck+=32; s_batCheck+=32;
if(s_batCheck==0 && g_vbat100mV<g_eeGeneral.vBatWarn && g_vbat100mV>50) { if(s_batCheck==0 && g_vbat100mV<g_eeGeneral.vBatWarn && g_vbat100mV>50) {
beepErr(); AUDIO_ERROR();
if (g_eeGeneral.flashBeep) g_LightOffCounter = FLASH_DURATION; if (g_eeGeneral.flashBeep) g_LightOffCounter = FLASH_DURATION;
} }
} }
break; break;
case 3:
{
// The various "beep" tone lengths
static prog_uint8_t APM beepTab[]= {
// 0 1 2 3 4
0, 0, 0, 0, 0, //quiet
0, 1, 8, 30, 100, //silent
1, 1, 8, 30, 100, //normal
1, 1, 15, 50, 150, //for motor
10, 10, 30, 50, 150, //for motor
};
memcpy_P(g_beepVal,beepTab+5*g_eeGeneral.beeperVal,5);
//g_beepVal = BEEP_VAL;
}
break;
} }
} }
int16_t g_ppmIns[8]; int16_t g_ppmIns[8];
uint8_t ppmInState = 0; //0=unsync 1..8= wait for value i-1 uint8_t ppmInState = 0; //0=unsync 1..8= wait for value i-1
@ -1809,6 +1789,7 @@ ISR(TIMER0_COMP_vect, ISR_NOBLOCK) //10ms timer
#endif #endif
{ {
cli(); cli();
#if defined (PCBV3) #if defined (PCBV3)
static uint8_t accuracyWarble = 4; // becasue 16M / 1024 / 100 = 156.25. So bump every 4. static uint8_t accuracyWarble = 4; // becasue 16M / 1024 / 100 = 156.25. So bump every 4.
uint8_t bump = (!(accuracyWarble++ & 0x03)) ? 157 : 156; uint8_t bump = (!(accuracyWarble++ & 0x03)) ? 157 : 156;
@ -1824,30 +1805,17 @@ ISR(TIMER0_COMP_vect, ISR_NOBLOCK) //10ms timer
OCR0 += bump; OCR0 += bump;
#endif #endif
#endif #endif
sei(); sei();
AUDIO_HEARTBEAT();
#if defined (PCBSTD) && defined (BEEPSPKR) #if defined (PCBSTD) && defined (BEEPSPKR)
// gruvin: Begin Tone Generator
static uint8_t toneCounter;
if (toneOn)
{
toneCounter += toneFreq;
if ((toneCounter & 0x80) == 0x80)
PORTE |= (1<<OUT_E_BUZZER); // speaker output 'high'
else
PORTE &= ~(1<<OUT_E_BUZZER); // speaker output 'low'
}
else
PORTE &= ~(1<<OUT_E_BUZZER); // speaker output 'low'
// gruvin: END Tone Generator
static uint8_t cnt10ms = 77; // execute 10ms code once every 78 ISRs static uint8_t cnt10ms = 77; // execute 10ms code once every 78 ISRs
if (cnt10ms-- == 0) // BEGIN { ... every 10ms ... } if (cnt10ms-- == 0) // BEGIN { ... every 10ms ... }
{ {
// Begin 10ms event // Begin 10ms event
cnt10ms = 77; cnt10ms = 77;
#endif #endif
#ifdef DEBUG #ifdef DEBUG
@ -1857,73 +1825,6 @@ ISR(TIMER0_COMP_vect, ISR_NOBLOCK) //10ms timer
sei(); sei();
#endif #endif
//cnt >/=0
//beepon/off
//beepagain y/n
if(g_beepCnt) {
if(!beepAgainOrig) {
beepAgainOrig = g_beepCnt;
beepOn = true;
}
g_beepCnt--;
}
else
{
if(beepAgain && beepAgainOrig) {
beepOn = !beepOn;
g_beepCnt = beepOn ? beepAgainOrig : 8;
if(beepOn) beepAgain--;
}
else {
beepAgainOrig = 0;
beepOn = false;
warble = false;
}
}
#if defined (PCBV3) && defined (BEEPSPKR)
// G: use timer0 WGM mode tone generator for beeps
if(beepOn)
{
static bool warbleC;
warbleC = warble && !warbleC;
if(warbleC)
TCCR0A &= ~(0b01<<COM0A0); // tone off
else
TCCR0A |= (0b01<<COM0A0); // tone on
}else{
TCCR0A &= ~(0b01<<COM0A0); // tone off
}
#else
#if defined (BEEPSPKR)
// G: use speaker tone generator for beeps
if(beepOn)
{
static bool warbleC;
warbleC = warble && !warbleC;
if(warbleC)
toneOn = false;
else
toneOn = true;
}else{
toneOn = false;
}
#else
// G: use original external buzzer for beeps
if(beepOn){
static bool warbleC;
warbleC = warble && !warbleC;
if(warbleC)
PORTE &= ~(1<<OUT_E_BUZZER);//buzzer off
else
PORTE |= (1<<OUT_E_BUZZER);//buzzer on
}else{
PORTE &= ~(1<<OUT_E_BUZZER);
}
#endif // BEEPSPKR
#endif // PCBV3 && BEEPSPKR
per10ms(); per10ms();
#if defined (PCBV3) #if defined (PCBV3)
@ -1953,8 +1854,6 @@ ISR(TIMER0_COMP_vect, ISR_NOBLOCK) //10ms timer
sei(); sei();
} }
// Timer3 used for PPM_IN pulse width capture. Counter running at 16MHz / 8 = 2MHz // Timer3 used for PPM_IN pulse width capture. Counter running at 16MHz / 8 = 2MHz
// equating to one count every half millisecond. (2 counts = 1ms). Control channel // equating to one count every half millisecond. (2 counts = 1ms). Control channel
// count delta values thus can range from about 1600 to 4400 counts (800us to 2200us), // count delta values thus can range from about 1600 to 4400 counts (800us to 2200us),
@ -2137,7 +2036,7 @@ void instantTrim()
} }
STORE_MODELVARS; STORE_MODELVARS;
beepWarn1(); AUDIO_WARNING1();
} }
void moveTrimsToOffsets() // copy state of 3 primary to subtrim void moveTrimsToOffsets() // copy state of 3 primary to subtrim
@ -2163,7 +2062,7 @@ void moveTrimsToOffsets() // copy state of 3 primary to subtrim
} }
STORE_MODELVARS; STORE_MODELVARS;
beepWarn1(); AUDIO_WARNING1();
} }
#if defined (PCBV4) #if defined (PCBV4)
@ -2239,7 +2138,7 @@ int main(void)
# endif # endif
DDRE = (1<<OUT_E_BUZZER); PORTE = 0xff-(1<<OUT_E_BUZZER); //pullups + buzzer 0 DDRE = (1<<OUT_E_BUZZER); PORTE = 0xff-(1<<OUT_E_BUZZER); //pullups + buzzer 0
DDRF = 0x00; PORTF = 0x00; //anain DDRF = 0x00; PORTF = 0x00; //anain
DDRG = 0x10; PORTG = 0xff; //pullups + SIM_CTL=1 = phonejack = ppm_in DDRG = 0x10; PORTG = 0xfB; //pullups + SIM_CTL=1 = phonejack = ppm_in
#endif #endif
lcd_init(); lcd_init();

View file

@ -123,7 +123,7 @@ extern RlcFile theFile; //used for any file operation
// rud thro elev aile // rud thro elev aile
//PORTG 7 6 5 4 3 2 1 0 //PORTG 7 6 5 4 3 2 1 0
// - - - O i i i // - - - O i i i
// SIM_CTL ID1 NC RF_POW RuddDR // SIM_CTL ID1 Haptic RF_POW RuddDR
#define PORTA_LCD_DAT PORTA #define PORTA_LCD_DAT PORTA
#define PORTC_LCD_CTRL PORTC #define PORTC_LCD_CTRL PORTC
@ -263,13 +263,6 @@ extern uint16_t DEBUG2;
#endif // defined (PCBV4) #endif // defined (PCBV4)
#if defined (BEEPSPKR)
#define BEEP_KEY_TIME 5
#define BEEP_DEFAULT_FREQ 50
#define BEEP_KEY_UP_FREQ 55
#define BEEP_KEY_DOWN_FREQ 45
#endif
#define SLAVE_MODE (PING & (1<<INP_G_RF_POW)) #define SLAVE_MODE (PING & (1<<INP_G_RF_POW))
extern const prog_uint8_t APM chout_ar[24*4]; extern const prog_uint8_t APM chout_ar[24*4];
@ -691,29 +684,6 @@ inline void _beepSpkr(uint8_t d, uint8_t f)
} }
#endif #endif
#if defined (BEEPSPKR)
#define beepKeySpkr(freq) _beepSpkr(g_beepVal[0],freq)
#define beepTrimSpkr(freq) _beepSpkr(g_beepVal[0],freq)
#define beepWarn1Spkr(freq) _beepSpkr(g_beepVal[1],freq)
#define beepWarn2Spkr(freq) _beepSpkr(g_beepVal[2],freq)
#define beepKey() _beepSpkr(g_beepVal[0],BEEP_DEFAULT_FREQ)
#define beepWarn() _beepSpkr(g_beepVal[3],BEEP_DEFAULT_FREQ)
#define beepWarn1() _beepSpkr(g_beepVal[1],BEEP_DEFAULT_FREQ)
#define beepWarn2() _beepSpkr(g_beepVal[2],BEEP_DEFAULT_FREQ)
#define beepErr() _beepSpkr(g_beepVal[4],BEEP_DEFAULT_FREQ)
#else
/// Erzeugt einen kurzen beep
#define beepKey() _beep(g_beepVal[0])
#define beepWarn() _beep(g_beepVal[3])
#define beepWarn1() _beep(g_beepVal[1])
#define beepWarn2() _beep(g_beepVal[2])
#define beepErr() _beep(g_beepVal[4])
#endif
// MM/SD card Disk IO Support // MM/SD card Disk IO Support
#if defined (PCBV3) #if defined (PCBV3)
#include "rtc.h" #include "rtc.h"
@ -753,5 +723,13 @@ extern FIL g_oLogFile; // pers.cpp::resetTelemetry()
extern volatile uint8_t g_rotenc[2]; extern volatile uint8_t g_rotenc[2];
#endif #endif
#ifdef BEEPSPKR
//audio settungs are external to keep out clutter!
// TODO what does mean "keep out clutter"?
#include "audio.h"
#else
#include "beeper.h"
#endif
#endif // gruvin9x_h #endif // gruvin9x_h
/*eof*/ /*eof*/

View file

@ -77,7 +77,7 @@ void menuProcDebug(uint8_t event)
g_tmr1Latency_min = 0xff; g_tmr1Latency_min = 0xff;
g_tmr1Latency_max = 0; g_tmr1Latency_max = 0;
g_timeMain = 0; g_timeMain = 0;
beepKey(); AUDIO_KEYPAD_UP();
break; break;
case EVT_KEY_FIRST(KEY_DOWN): case EVT_KEY_FIRST(KEY_DOWN):
chainMenu(menuProcStatistic); chainMenu(menuProcStatistic);

View file

@ -8,8 +8,8 @@
#define LEN_NCHANNELS 4 #define LEN_NCHANNELS 4
#define TR_NCHANNELS "4CH 6CH 8CH 10CH12CH14CH16CH" #define TR_NCHANNELS "4CH 6CH 8CH 10CH12CH14CH16CH"
#define LEN_VBEEPER 5 #define LEN_VBEEPER 6
#define TR_VBEEPER "Quiet""NoKey""Norm ""Long ""xLong" #define TR_VBEEPER "Quiet ""NoKey ""xShort""Short ""Norm ""Long ""xLong "
#define LEN_ADCFILTER 4 #define LEN_ADCFILTER 4
#define TR_ADCFILTER "SING""OSMP""FILT" #define TR_ADCFILTER "SING""OSMP""FILT"

View file

@ -8,8 +8,8 @@
#define LEN_NCHANNELS 4 #define LEN_NCHANNELS 4
#define TR_NCHANNELS "4CH 6CH 8CH 10CH12CH14CH16CH" #define TR_NCHANNELS "4CH 6CH 8CH 10CH12CH14CH16CH"
#define LEN_VBEEPER 5 #define LEN_VBEEPER 6
#define TR_VBEEPER "Quiet""NoKey""Norm ""Long ""xLong" #define TR_VBEEPER "Quiet ""NoKey ""xShort""Short ""Norm ""Long ""xLong "
#define LEN_ADCFILTER 4 #define LEN_ADCFILTER 4
#define TR_ADCFILTER "SING""OSMP""FILT" #define TR_ADCFILTER "SING""OSMP""FILT"

View file

@ -21,8 +21,8 @@ def generate(hex, arg, options):
states = [False] * len(options) states = [False] * len(options)
index = 0 index = 0
while index >= 0: while 1:
print states # print index, states
for language in languages: for language in languages:
hex_file = hex hex_file = hex
@ -36,15 +36,15 @@ def generate(hex, arg, options):
print hex_file print hex_file
call(["make", "clean"]) call(["make", "clean"])
call(make_args) call(make_args)
shutil.copyfile("open9x.hex", "../" + hex_file + ".hex") shutil.copyfile("open9x.hex", "../binaries/" + hex_file + ".hex")
for i in range(index):
states[i] = False
states[index] = True
try: try:
index = states.index(False) index = states.index(False)
except: except:
index = -1 break
for i in range(index):
states[i] = False
states[index] = True
# stock board # stock board
generate("open9x-stock", "PCB=STD", options_stock) generate("open9x-stock", "PCB=STD", options_stock)