|
|
|
@ -8,33 +8,12 @@
@@ -8,33 +8,12 @@
|
|
|
|
|
#include <sys/types.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
|
|
|
|
|
#include <AP_Math/AP_Math.h> |
|
|
|
|
#include <AP_HAL/AP_HAL.h> |
|
|
|
|
|
|
|
|
|
using namespace Linux; |
|
|
|
|
|
|
|
|
|
extern const AP_HAL::HAL& hal; |
|
|
|
|
static uint16_t notes[] = { 0, |
|
|
|
|
NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4, |
|
|
|
|
NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5, |
|
|
|
|
NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6, |
|
|
|
|
NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//List of RTTTL tones
|
|
|
|
|
const char* ToneAlarm::tune[TONE_NUMBER_OF_TUNES] = { |
|
|
|
|
"Startup:d=8,o=6,b=480:a,d7,c7,a,d7,c7,a,d7,16d7,16c7,16d7,16c7,16d7,16c7,16d7,16c7", |
|
|
|
|
"Error:d=4,o=6,b=400:8a,8a,8a,p,a,a,a,p", |
|
|
|
|
"notify_pos:d=4,o=6,b=400:8e,8e,a", |
|
|
|
|
"notify_neut:d=4,o=6,b=400:8e,e", |
|
|
|
|
"notify_neg:d=4,o=6,b=400:8e,8c,8e,8c,8e,8c", |
|
|
|
|
"arming_warn:d=1,o=4,b=75:g", |
|
|
|
|
"batt_war_slow:d=4,o=6,b=200:8a", |
|
|
|
|
"batt_war_fast:d=4,o=6,b=512:8a,8a,8a,8a,8a,8a,8a,8a,8a,8a,8a,8a,8a,8a,8a,8a,8a", |
|
|
|
|
"GPS_war:d=4,o=6,b=512:a,a,a,1f#", |
|
|
|
|
"Arm_fail:d=4,o=4,b=512:b,a,p", |
|
|
|
|
"para_rel:d=16,o=6,b=512:a,g,a,g,a,g,a,g"}; |
|
|
|
|
//Tune Repeat true: play rtttl tune in loop, false: play only once
|
|
|
|
|
bool ToneAlarm::tune_repeat[TONE_NUMBER_OF_TUNES] = {false,true,false,false,false,false,true,true,false,false,false}; |
|
|
|
|
|
|
|
|
|
ToneAlarm::ToneAlarm() |
|
|
|
|
{ |
|
|
|
@ -45,14 +24,10 @@ ToneAlarm::ToneAlarm()
@@ -45,14 +24,10 @@ ToneAlarm::ToneAlarm()
|
|
|
|
|
duty_fd = open("/sys/devices/ocp.3/pwm_test_P8_36.12/duty",O_WRONLY|O_CLOEXEC); |
|
|
|
|
run_fd = open("/sys/devices/ocp.3/pwm_test_P8_36.12/run",O_WRONLY|O_CLOEXEC); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
tune_num = -1; //initialy no tune to play
|
|
|
|
|
tune_pos = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ToneAlarm::init() |
|
|
|
|
{ |
|
|
|
|
tune_num = 0; //play startup tune
|
|
|
|
|
if ((period_fd == -1) || (duty_fd == -1) || (run_fd == -1)) { |
|
|
|
|
#if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BLUE || \ |
|
|
|
|
CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXF || \
|
|
|
|
@ -64,200 +39,14 @@ bool ToneAlarm::init()
@@ -64,200 +39,14 @@ bool ToneAlarm::init()
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ToneAlarm::set_tune(uint8_t tone) |
|
|
|
|
{ |
|
|
|
|
tune_num = tone; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ToneAlarm::is_tune_comp() |
|
|
|
|
{ |
|
|
|
|
return tune_comp; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ToneAlarm::stop() |
|
|
|
|
{ |
|
|
|
|
dprintf(run_fd,"0"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ToneAlarm::play() |
|
|
|
|
void ToneAlarm::set_buzzer_tone(float frequency, float volume) |
|
|
|
|
{ |
|
|
|
|
const uint32_t cur_time = AP_HAL::millis(); |
|
|
|
|
if(tune_num != prev_tune_num){ |
|
|
|
|
tune_changed = true; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
if(cur_note != 0){ |
|
|
|
|
if (is_zero(frequency) || is_zero(volume)) { |
|
|
|
|
dprintf(run_fd,"0"); |
|
|
|
|
} else { |
|
|
|
|
dprintf(run_fd,"0"); |
|
|
|
|
dprintf(period_fd,"%u",1000000000/cur_note); |
|
|
|
|
dprintf(duty_fd,"%u",500000000/cur_note); |
|
|
|
|
dprintf(period_fd,"%u",(unsigned int)roundf(1000000000/frequency)); |
|
|
|
|
dprintf(duty_fd,"%u",(unsigned int)roundf(volume*500000000/frequency)); |
|
|
|
|
dprintf(run_fd,"1"); |
|
|
|
|
cur_note =0; |
|
|
|
|
prev_time = cur_time; |
|
|
|
|
} |
|
|
|
|
if((cur_time - prev_time) > duration){ |
|
|
|
|
stop(); |
|
|
|
|
if(tune[tune_num][tune_pos] == '\0'){ |
|
|
|
|
if(!tune_repeat[tune_num]){ |
|
|
|
|
tune_num = -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tune_pos = 0; |
|
|
|
|
tune_comp = true; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ToneAlarm::set_note(){ |
|
|
|
|
// first, get note duration, if available
|
|
|
|
|
uint16_t scale,note,num =0; |
|
|
|
|
duration = 0; |
|
|
|
|
|
|
|
|
|
while(isdigit(tune[tune_num][tune_pos])){ //this is a safe while loop as it can't go further than
|
|
|
|
|
//the length of the rtttl tone string
|
|
|
|
|
num = (num * 10) + (tune[tune_num][tune_pos++] - '0'); |
|
|
|
|
} |
|
|
|
|
if(num){ |
|
|
|
|
duration = wholenote / num; |
|
|
|
|
} else{ |
|
|
|
|
duration = wholenote / 4; // we will need to check if we are a dotted note after
|
|
|
|
|
} |
|
|
|
|
// now get the note
|
|
|
|
|
note = 0; |
|
|
|
|
|
|
|
|
|
switch(tune[tune_num][tune_pos]){ |
|
|
|
|
case 'c': |
|
|
|
|
note = 1; |
|
|
|
|
break; |
|
|
|
|
case 'd': |
|
|
|
|
note = 3; |
|
|
|
|
break; |
|
|
|
|
case 'e': |
|
|
|
|
note = 5; |
|
|
|
|
break; |
|
|
|
|
case 'f': |
|
|
|
|
note = 6; |
|
|
|
|
break; |
|
|
|
|
case 'g': |
|
|
|
|
note = 8; |
|
|
|
|
break; |
|
|
|
|
case 'a': |
|
|
|
|
note = 10; |
|
|
|
|
break; |
|
|
|
|
case 'b': |
|
|
|
|
note = 12; |
|
|
|
|
break; |
|
|
|
|
case 'p': |
|
|
|
|
default: |
|
|
|
|
note = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tune_pos++; |
|
|
|
|
|
|
|
|
|
// now, get optional '#' sharp
|
|
|
|
|
if(tune[tune_num][tune_pos] == '#'){ |
|
|
|
|
note++; |
|
|
|
|
tune_pos++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// now, get optional '.' dotted note
|
|
|
|
|
|
|
|
|
|
if(tune[tune_num][tune_pos] == '.'){ |
|
|
|
|
duration += duration/2; |
|
|
|
|
tune_pos++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// now, get scale
|
|
|
|
|
|
|
|
|
|
if(isdigit(tune[tune_num][tune_pos])){ |
|
|
|
|
scale = tune[tune_num][tune_pos] - '0'; |
|
|
|
|
tune_pos++; |
|
|
|
|
} else{ |
|
|
|
|
scale = default_oct; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
scale += OCTAVE_OFFSET; |
|
|
|
|
|
|
|
|
|
if(tune[tune_num][tune_pos] == ','){ |
|
|
|
|
tune_pos++; // skip comma for next note (or we may be at the end)
|
|
|
|
|
} |
|
|
|
|
// now play the note
|
|
|
|
|
|
|
|
|
|
if(note){ |
|
|
|
|
if(tune_changed == true){ |
|
|
|
|
tune_pos =0; |
|
|
|
|
tune_changed = false; |
|
|
|
|
} |
|
|
|
|
cur_note = notes[(scale - 4) * 12 + note]; |
|
|
|
|
return true; |
|
|
|
|
} else{ |
|
|
|
|
cur_note = 0; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ToneAlarm::init_tune(){ |
|
|
|
|
|
|
|
|
|
uint16_t num; |
|
|
|
|
default_dur = 4; |
|
|
|
|
default_oct = 6; |
|
|
|
|
bpm = 63; |
|
|
|
|
prev_tune_num = tune_num; |
|
|
|
|
if(tune_num <0 || tune_num > TONE_NUMBER_OF_TUNES){ |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tune_comp = false; |
|
|
|
|
while(tune[tune_num][tune_pos] != ':'){ |
|
|
|
|
if(tune[tune_num][tune_pos] == '\0'){ |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
tune_pos++; |
|
|
|
|
} |
|
|
|
|
tune_pos++; |
|
|
|
|
|
|
|
|
|
if(tune[tune_num][tune_pos] == 'd'){ |
|
|
|
|
tune_pos+=2; |
|
|
|
|
num = 0; |
|
|
|
|
|
|
|
|
|
while(isdigit(tune[tune_num][tune_pos])){ |
|
|
|
|
num = (num * 10) + (tune[tune_num][tune_pos++] - '0'); |
|
|
|
|
} |
|
|
|
|
if(num > 0){ |
|
|
|
|
default_dur = num; |
|
|
|
|
} |
|
|
|
|
tune_pos++; // skip comma
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// get default octave
|
|
|
|
|
|
|
|
|
|
if(tune[tune_num][tune_pos] == 'o') |
|
|
|
|
{ |
|
|
|
|
tune_pos+=2; // skip "o="
|
|
|
|
|
num = tune[tune_num][tune_pos++] - '0'; |
|
|
|
|
if(num >= 3 && num <=7){ |
|
|
|
|
default_oct = num; |
|
|
|
|
} |
|
|
|
|
tune_pos++; // skip comma
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// get BPM
|
|
|
|
|
|
|
|
|
|
if(tune[tune_num][tune_pos] == 'b'){ |
|
|
|
|
tune_pos+=2; // skip "b="
|
|
|
|
|
num = 0; |
|
|
|
|
while(isdigit(tune[tune_num][tune_pos])){ |
|
|
|
|
num = (num * 10) + (tune[tune_num][tune_pos++] - '0'); |
|
|
|
|
} |
|
|
|
|
bpm = num; |
|
|
|
|
tune_pos++; // skip colon
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// BPM usually expresses the number of quarter notes per minute
|
|
|
|
|
wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds)
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|