mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-07-08 17:50:34 +08:00
drivers/tone_alarm and tune_control small improvements/cleanup
- drivers/tone_alarm: move to ModuleBase and purge CDev (/dev/tone_alarm0) - drivers/tone_alarm: only run on tune_control publication (or scheduled note) rather than continuously - drivers/tone_alarm: use HRT to schedule tone stop (prevents potential disruption) - msg/tune_control: add tune_id numbering - systemcmds/tune_control: add "error" special case tune_id - move all tune_control publication to new uORB::PublicationQueued<> - start tone_alarm immediately after board defaults are loaded to fix potential startup issues - for SITL (or other boards with no TONE output) print common messages (startup, error, etc)
This commit is contained in:
@@ -34,64 +34,16 @@
|
||||
/**
|
||||
* @file drv_tone_alarm.h
|
||||
*
|
||||
* Driver for the PX4 audio alarm port, /dev/tone_alarm.
|
||||
* Driver for the PX4 audio alarm port.
|
||||
*
|
||||
* The tone_alarm driver supports a set of predefined "alarm"
|
||||
* patterns and one user-supplied pattern. Patterns are ordered by
|
||||
* priority, with a higher-priority pattern interrupting any
|
||||
* lower-priority pattern that might be playing.
|
||||
*
|
||||
* The TONE_SET_ALARM ioctl can be used to select a predefined
|
||||
* alarm pattern, from 1 - <TBD>. Selecting pattern zero silences
|
||||
* the alarm.
|
||||
*
|
||||
* To supply a custom pattern, write an array of 1 - <TBD> tone_note
|
||||
* structures to /dev/tone_alarm. The custom pattern has a priority
|
||||
* of zero.
|
||||
*
|
||||
* Patterns will normally play once and then silence (if a pattern
|
||||
* was overridden it will not resume). A pattern may be made to
|
||||
* repeat by inserting a note with the duration set to
|
||||
* DURATION_REPEAT. This pattern will loop until either a
|
||||
* higher-priority pattern is started or pattern zero is requested
|
||||
* via the ioctl.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "drv_hrt.h"
|
||||
#include <lib/tunes/tune_definition.h>
|
||||
#include <uORB/topics/tune_control.h>
|
||||
|
||||
#define CBRK_BUZZER_KEY 782097
|
||||
#define CBRK_OFF 0
|
||||
#define CBRK_ON 1
|
||||
#define CBRK_UNINIT 2
|
||||
|
||||
#define _TONE_ALARM_BASE 0x7400
|
||||
#define TONE_SET_ALARM _PX4_IOC(_TONE_ALARM_BASE, 1)
|
||||
#define TONE_ALARM0_DEVICE_PATH "/dev/tone_alarm0"
|
||||
|
||||
// TODO: remove this once the tone_alarm driver is changed to the new tunelib
|
||||
enum {
|
||||
TONE_STOP_TUNE = 0,
|
||||
TONE_STARTUP_TUNE,
|
||||
TONE_ERROR_TUNE,
|
||||
TONE_NOTIFY_POSITIVE_TUNE,
|
||||
TONE_NOTIFY_NEUTRAL_TUNE,
|
||||
TONE_NOTIFY_NEGATIVE_TUNE,
|
||||
TONE_ARMING_WARNING_TUNE,
|
||||
TONE_BATTERY_WARNING_SLOW_TUNE,
|
||||
TONE_BATTERY_WARNING_FAST_TUNE,
|
||||
TONE_GPS_WARNING_TUNE,
|
||||
TONE_ARMING_FAILURE_TUNE,
|
||||
TONE_PARACHUTE_RELEASE_TUNE,
|
||||
TONE_EKF_WARNING_TUNE,
|
||||
TONE_BARO_WARNING_TUNE,
|
||||
TONE_SINGLE_BEEP_TUNE,
|
||||
TONE_HOME_SET,
|
||||
TONE_NUMBER_OF_TUNES
|
||||
};
|
||||
|
||||
namespace ToneAlarmInterface
|
||||
{
|
||||
|
||||
@@ -102,8 +54,9 @@ void init();
|
||||
|
||||
/**
|
||||
* @brief Starts playing the note.
|
||||
* @return the time the note started played.
|
||||
*/
|
||||
void start_note(unsigned frequency);
|
||||
hrt_abstime start_note(unsigned frequency);
|
||||
|
||||
/**
|
||||
* @brief Stops playing the current note and makes the player 'safe'.
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include <systemlib/err.h>
|
||||
#include <lib/mixer/MixerGroup.hpp>
|
||||
|
||||
#include <uORB/Publication.hpp>
|
||||
#include <uORB/topics/actuator_controls.h>
|
||||
#include <uORB/topics/actuator_outputs.h>
|
||||
#include <uORB/topics/actuator_armed.h>
|
||||
@@ -161,7 +162,7 @@ private:
|
||||
char _device[20];
|
||||
orb_advert_t _t_outputs;
|
||||
orb_advert_t _t_esc_status;
|
||||
orb_advert_t _tune_control_sub;
|
||||
uORB::PublicationQueued<tune_control_s> _tune_control_pub{ORB_ID(tune_control)};
|
||||
unsigned int _num_outputs;
|
||||
bool _primary_pwm_device;
|
||||
bool _motortest;
|
||||
@@ -448,14 +449,14 @@ MK::scaling(float val, float inMin, float inMax, float outMin, float outMax)
|
||||
void
|
||||
MK::play_beep(int count)
|
||||
{
|
||||
tune_control_s tune = {};
|
||||
tune_control_s tune{};
|
||||
tune.tune_id = static_cast<int>(TuneID::SINGLE_BEEP);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
orb_publish(ORB_ID(tune_control), _tune_control_sub, &tune);
|
||||
tune.timestamp = hrt_absolute_time();
|
||||
_tune_control_pub.publish(tune);
|
||||
usleep(300000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
@@ -490,12 +491,6 @@ MK::task_main()
|
||||
memset(&esc, 0, sizeof(esc));
|
||||
_t_esc_status = orb_advertise(ORB_ID(esc_status), &esc);
|
||||
|
||||
/*
|
||||
* advertise the tune_control.
|
||||
*/
|
||||
tune_control_s tune = {};
|
||||
_tune_control_sub = orb_advertise_queue(ORB_ID(tune_control), &tune, tune_control_s::ORB_QUEUE_LENGTH);
|
||||
|
||||
pollfd fds[2];
|
||||
fds[0].fd = _t_actuators;
|
||||
fds[0].events = POLLIN;
|
||||
|
||||
@@ -129,14 +129,11 @@ SafetyButton::CheckPairingRequest(bool button_pressed)
|
||||
++_pairing_button_counter;
|
||||
}
|
||||
|
||||
|
||||
if (_pairing_button_counter == 3) {
|
||||
|
||||
|
||||
vehicle_command_s vcmd{};
|
||||
vcmd.command = vehicle_command_s::VEHICLE_CMD_START_RX_PAIR;
|
||||
vcmd.timestamp = now;
|
||||
vcmd.param1 = 10.f; // GCS pairing request handled by a companion.
|
||||
vcmd.timestamp = hrt_absolute_time();
|
||||
_to_command.publish(vcmd);
|
||||
PX4_DEBUG("Sending GCS pairing request");
|
||||
|
||||
@@ -150,9 +147,8 @@ SafetyButton::CheckPairingRequest(bool button_pressed)
|
||||
_to_led_control.publish(led_control);
|
||||
|
||||
tune_control_s tune_control{};
|
||||
tune_control.tune_id = TONE_NOTIFY_POSITIVE_TUNE;
|
||||
tune_control.tune_id = tune_control_s::TUNE_ID_NOTIFY_POSITIVE;
|
||||
tune_control.volume = tune_control_s::VOLUME_LEVEL_DEFAULT;
|
||||
tune_control.tune_override = 0;
|
||||
tune_control.timestamp = hrt_absolute_time();
|
||||
_to_tune_control.publish(tune_control);
|
||||
|
||||
|
||||
@@ -77,7 +77,6 @@ private:
|
||||
void FlashButton();
|
||||
void CheckPairingRequest(bool button_pressed);
|
||||
|
||||
|
||||
uORB::Subscription _armed_sub{ORB_ID(actuator_armed)};
|
||||
uORB::Publication<safety_s> _to_safety{ORB_ID(safety)};
|
||||
uORB::PublicationQueued<vehicle_command_s> _to_command{ORB_ID(vehicle_command)};
|
||||
|
||||
@@ -7,7 +7,7 @@ serial_config:
|
||||
then
|
||||
mavlink start -d /dev/iridium -m iridium -b 115200
|
||||
else
|
||||
tune_control play -t 20
|
||||
tune_control play error
|
||||
fi
|
||||
port_config_param:
|
||||
name: ISBD_CONFIG
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (C) 2015-2019 PX4 Development Team. All rights reserved.
|
||||
# Copyright (C) 2015-2020 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
@@ -34,8 +34,11 @@
|
||||
px4_add_module(
|
||||
MODULE drivers__tone_alarm
|
||||
MAIN tone_alarm
|
||||
COMPILE_FLAGS
|
||||
#-DDEBUG_BUILD
|
||||
SRCS
|
||||
ToneAlarm.cpp
|
||||
ToneAlarm.h
|
||||
DEPENDS
|
||||
circuit_breaker
|
||||
arch_tone_alarm
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013-2019 PX4 Development Team. All rights reserved.
|
||||
* Copyright (C) 2013-2020 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -38,195 +38,228 @@
|
||||
#include "ToneAlarm.h"
|
||||
|
||||
#include <px4_platform_common/time.h>
|
||||
#include <uORB/Publication.hpp>
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
ToneAlarm::ToneAlarm() :
|
||||
CDev(TONE_ALARM0_DEVICE_PATH),
|
||||
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::hp_default)
|
||||
{
|
||||
// ensure ORB_ID(tune_control) is advertised with correct queue depth
|
||||
orb_advertise_queue(ORB_ID(tune_control), nullptr, tune_control_s::ORB_QUEUE_LENGTH);
|
||||
}
|
||||
|
||||
ToneAlarm::~ToneAlarm()
|
||||
{
|
||||
_should_run = false;
|
||||
int counter = 0;
|
||||
|
||||
while (_running && counter < 10) {
|
||||
px4_usleep(100000);
|
||||
counter++;
|
||||
}
|
||||
ToneAlarmInterface::stop_note();
|
||||
}
|
||||
|
||||
int ToneAlarm::init()
|
||||
bool ToneAlarm::Init()
|
||||
{
|
||||
if (CDev::init() != OK) {
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
// NOTE: Implement hardware specific detail in the ToneAlarmInterface class implementation.
|
||||
ToneAlarmInterface::init();
|
||||
|
||||
_running = true;
|
||||
_tune_control_sub.set_interval_us(10_ms);
|
||||
|
||||
if (!_tune_control_sub.registerCallback()) {
|
||||
PX4_ERR("tune_control callback registration failed!");
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
ScheduleNow();
|
||||
|
||||
return OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ToneAlarm::next_note()
|
||||
void ToneAlarm::InterruptStopNote(void *arg)
|
||||
{
|
||||
if (!_should_run) {
|
||||
_running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for updates
|
||||
orb_update();
|
||||
|
||||
unsigned int frequency = 0;
|
||||
unsigned int duration = 0;
|
||||
|
||||
// Does an inter-note silence occur?
|
||||
if (_silence_length > 0) {
|
||||
stop_note();
|
||||
duration = _silence_length;
|
||||
_silence_length = 0;
|
||||
|
||||
} else if (_play_tone) {
|
||||
int parse_ret_val = _tunes.get_next_note(frequency, duration, _silence_length);
|
||||
|
||||
if (parse_ret_val > 0) {
|
||||
// Continue playing.
|
||||
_play_tone = true;
|
||||
|
||||
// A frequency of 0 corresponds to stop_note();
|
||||
if (frequency > 0) {
|
||||
// Start playing the note.
|
||||
start_note(frequency);
|
||||
}
|
||||
|
||||
} else {
|
||||
_play_tone = false;
|
||||
stop_note();
|
||||
}
|
||||
|
||||
} else {
|
||||
// Schedule a callback with the tunes max interval.
|
||||
duration = _tunes.get_maximum_update_interval();
|
||||
stop_note();
|
||||
}
|
||||
|
||||
// Schedule a callback when the note should stop.
|
||||
ScheduleDelayed(duration);
|
||||
ToneAlarmInterface::stop_note();
|
||||
}
|
||||
|
||||
void ToneAlarm::Run()
|
||||
{
|
||||
next_note();
|
||||
}
|
||||
|
||||
void ToneAlarm::orb_update()
|
||||
{
|
||||
// Check for updates
|
||||
if (_tune_control_sub.updated()) {
|
||||
_tune_control_sub.copy(&_tune);
|
||||
|
||||
if (_tune.timestamp > 0) {
|
||||
_play_tone = _tunes.set_control(_tune) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ToneAlarm::status()
|
||||
{
|
||||
if (_running) {
|
||||
PX4_INFO("running");
|
||||
|
||||
} else {
|
||||
PX4_INFO("stopped");
|
||||
}
|
||||
}
|
||||
|
||||
void ToneAlarm::start_note(unsigned frequency)
|
||||
{
|
||||
// Check if circuit breaker is enabled.
|
||||
if (_cbrk == CBRK_UNINIT) {
|
||||
_cbrk = circuit_breaker_enabled("CBRK_BUZZER", CBRK_BUZZER_KEY);
|
||||
if (!_circuit_break_initialized) {
|
||||
if (circuit_breaker_enabled("CBRK_BUZZER", CBRK_BUZZER_KEY)) {
|
||||
request_stop();
|
||||
}
|
||||
|
||||
_circuit_break_initialized = true;
|
||||
}
|
||||
|
||||
if (_cbrk != CBRK_OFF) {
|
||||
if (should_exit()) {
|
||||
_tune_control_sub.unregisterCallback();
|
||||
exit_and_cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: Implement hardware specific detail in the ToneAlarmInterface class implementation.
|
||||
ToneAlarmInterface::start_note(frequency);
|
||||
}
|
||||
// Check for next tune_control when not currently playing
|
||||
if (_tune_control_sub.updated()) {
|
||||
tune_control_s tune_control;
|
||||
|
||||
void ToneAlarm::stop_note()
|
||||
{
|
||||
// NOTE: Implement hardware specific detail in the ToneAlarmInterface class implementation.
|
||||
ToneAlarmInterface::stop_note();
|
||||
}
|
||||
if (_tune_control_sub.copy(&tune_control)) {
|
||||
if (tune_control.timestamp > 0) {
|
||||
if (!_play_tone || (_play_tone && tune_control.tune_override)) {
|
||||
PX4_DEBUG("new tune %d", tune_control.tune_id);
|
||||
|
||||
/**
|
||||
* Local functions in support of the shell command.
|
||||
*/
|
||||
namespace
|
||||
{
|
||||
if (_tunes.set_control(tune_control) == PX4_OK) {
|
||||
if (tune_control.tune_override) {
|
||||
// clear existing
|
||||
ToneAlarmInterface::stop_note();
|
||||
_next_note_time = 0;
|
||||
hrt_cancel(&_hrt_call);
|
||||
}
|
||||
|
||||
ToneAlarm *g_dev;
|
||||
_play_tone = true;
|
||||
|
||||
} // namespace
|
||||
#if (!defined(TONE_ALARM_TIMER) && !defined(GPIO_TONE_ALARM_GPIO)) || defined(DEBUG_BUILD)
|
||||
|
||||
/**
|
||||
* Tone alarm Driver 'main' command.
|
||||
* Entry point for the tone_alarm driver module.
|
||||
*/
|
||||
extern "C" __EXPORT int tone_alarm_main(int argc, char *argv[])
|
||||
{
|
||||
if (argc > 1) {
|
||||
const char *argv1 = argv[1];
|
||||
switch (tune_control.tune_id) {
|
||||
case tune_control_s::TUNE_ID_STARTUP:
|
||||
PX4_INFO("startup tune");
|
||||
break;
|
||||
|
||||
if (!strcmp(argv1, "start")) {
|
||||
if (g_dev == nullptr) {
|
||||
g_dev = new ToneAlarm();
|
||||
case tune_control_s::TUNE_ID_ERROR:
|
||||
PX4_ERR("error tune");
|
||||
break;
|
||||
|
||||
if (g_dev == nullptr) {
|
||||
PX4_ERR("could not allocate the driver.");
|
||||
case tune_control_s::TUNE_ID_NOTIFY_POSITIVE:
|
||||
PX4_INFO("notify positive");
|
||||
break;
|
||||
|
||||
case tune_control_s::TUNE_ID_NOTIFY_NEUTRAL:
|
||||
PX4_INFO("notify neutral");
|
||||
break;
|
||||
|
||||
case tune_control_s::TUNE_ID_NOTIFY_NEGATIVE:
|
||||
PX4_ERR("notify negative");
|
||||
break;
|
||||
|
||||
case tune_control_s::TUNE_ID_ARMING_WARNING:
|
||||
PX4_WARN("arming warning");
|
||||
break;
|
||||
|
||||
case tune_control_s::TUNE_ID_BATTERY_WARNING_SLOW:
|
||||
PX4_WARN("battery warning (slow)");
|
||||
break;
|
||||
|
||||
case tune_control_s::TUNE_ID_BATTERY_WARNING_FAST:
|
||||
PX4_WARN("battery warning (fast)");
|
||||
break;
|
||||
|
||||
case tune_control_s::TUNE_ID_ARMING_FAILURE:
|
||||
PX4_ERR("arming failure");
|
||||
break;
|
||||
|
||||
case tune_control_s::TUNE_ID_SINGLE_BEEP:
|
||||
PX4_WARN("beep");
|
||||
break;
|
||||
|
||||
case tune_control_s::TUNE_ID_HOME_SET:
|
||||
PX4_INFO("home set");
|
||||
break;
|
||||
}
|
||||
|
||||
#endif // (!TONE_ALARM_TIMER && !GPIO_TONE_ALARM_GPIO) || DEBUG_BUILD
|
||||
}
|
||||
|
||||
} else if (_play_tone && !tune_control.tune_override) {
|
||||
// otherwise re-publish tune to process next
|
||||
PX4_DEBUG("tune already playing, requeing tune: %d", tune_control.tune_id);
|
||||
uORB::PublicationQueued<tune_control_s> tune_control_pub{ORB_ID(tune_control)};
|
||||
tune_control.timestamp = hrt_absolute_time();
|
||||
tune_control_pub.publish(tune_control);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_dev->init() != OK) {
|
||||
delete g_dev;
|
||||
g_dev = nullptr;
|
||||
PX4_ERR("driver init failed.");
|
||||
}
|
||||
unsigned int frequency = 0;
|
||||
unsigned int duration = 0;
|
||||
unsigned int silence_length = 0;
|
||||
|
||||
} else {
|
||||
PX4_INFO("already started");
|
||||
// Does an inter-note silence occur?
|
||||
if ((_next_note_time != 0) && (hrt_absolute_time() < _next_note_time)) {
|
||||
PX4_DEBUG("inter-note silence");
|
||||
ScheduleAt(_next_note_time);
|
||||
|
||||
} else if (_play_tone && (_tunes.get_next_note(frequency, duration, silence_length) == Tunes::Status::Continue)) {
|
||||
PX4_DEBUG("Play frequency: %d, duration: %d us, silence: %d us", frequency, duration, silence_length);
|
||||
|
||||
if (frequency > 0) {
|
||||
// Start playing the note.
|
||||
const hrt_abstime time_started = ToneAlarmInterface::start_note(frequency);
|
||||
|
||||
if (time_started > 0) {
|
||||
// schedule stop with HRT
|
||||
hrt_call_at(&_hrt_call, time_started + duration, (hrt_callout)&InterruptStopNote, this);
|
||||
_next_note_time = time_started + duration + silence_length;
|
||||
|
||||
// schedule next note
|
||||
ScheduleAt(_next_note_time);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv1, "stop")) {
|
||||
delete g_dev;
|
||||
g_dev = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv1, "status")) {
|
||||
if (g_dev != nullptr) {
|
||||
g_dev->status();
|
||||
|
||||
} else {
|
||||
PX4_INFO("driver stopped");
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
// A frequency of 0 corresponds to ToneAlarmInterface::stop_note()
|
||||
_next_note_time = hrt_absolute_time() + duration + silence_length;
|
||||
ToneAlarmInterface::stop_note();
|
||||
ScheduleAt(_next_note_time);
|
||||
}
|
||||
|
||||
} else {
|
||||
PX4_INFO("missing command, try 'start', status, 'stop'");
|
||||
PX4_DEBUG("stopping");
|
||||
ToneAlarmInterface::stop_note();
|
||||
_play_tone = false;
|
||||
_next_note_time = 0;
|
||||
}
|
||||
|
||||
// if done playing and a new tune_control is still available re-schedule
|
||||
if (!Scheduled() && _tune_control_sub.updated()) {
|
||||
ScheduleDelayed(_tunes.get_maximum_update_interval());
|
||||
}
|
||||
}
|
||||
|
||||
int ToneAlarm::task_spawn(int argc, char *argv[])
|
||||
{
|
||||
ToneAlarm *instance = new ToneAlarm();
|
||||
|
||||
if (!instance) {
|
||||
PX4_ERR("alloc failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!instance->Init()) {
|
||||
delete instance;
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
_object.store(instance);
|
||||
_task_id = task_id_is_work_queue;
|
||||
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
int ToneAlarm::print_usage(const char *reason)
|
||||
{
|
||||
if (reason) {
|
||||
PX4_WARN("%s\n", reason);
|
||||
}
|
||||
|
||||
PRINT_MODULE_DESCRIPTION(
|
||||
R"DESCR_STR(
|
||||
### Description
|
||||
This module is responsible for the tone alarm.
|
||||
|
||||
)DESCR_STR");
|
||||
|
||||
PRINT_MODULE_USAGE_NAME("tone_alarm", "driver");
|
||||
PRINT_MODULE_USAGE_COMMAND("start");
|
||||
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
extern "C" __EXPORT int tone_alarm_main(int argc, char *argv[])
|
||||
{
|
||||
return ToneAlarm::main(argc, argv);
|
||||
}
|
||||
|
||||
@@ -40,79 +40,50 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <circuit_breaker/circuit_breaker.h>
|
||||
#include <drivers/device/device.h>
|
||||
#include <drivers/drv_tone_alarm.h>
|
||||
#include <lib/tunes/tunes.h>
|
||||
#include <px4_platform_common/defines.h>
|
||||
#include <px4_platform_common/px4_config.h>
|
||||
#include <px4_platform_common/getopt.h>
|
||||
#include <px4_platform_common/log.h>
|
||||
#include <px4_platform_common/module.h>
|
||||
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
|
||||
#include <lib/circuit_breaker/circuit_breaker.h>
|
||||
#include <lib/tunes/tunes.h>
|
||||
#include <uORB/Subscription.hpp>
|
||||
#include <uORB/SubscriptionCallback.hpp>
|
||||
#include <uORB/topics/tune_control.h>
|
||||
|
||||
#include <drivers/drv_tone_alarm.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(UNUSED)
|
||||
# define UNUSED(a) ((void)(a))
|
||||
#endif
|
||||
|
||||
class ToneAlarm : public cdev::CDev, public px4::ScheduledWorkItem
|
||||
class ToneAlarm : public ModuleBase<ToneAlarm>, public px4::ScheduledWorkItem
|
||||
{
|
||||
public:
|
||||
ToneAlarm();
|
||||
~ToneAlarm();
|
||||
~ToneAlarm() override;
|
||||
|
||||
/**
|
||||
* @brief Initializes the character device and hardware registers.
|
||||
*/
|
||||
int init() override;
|
||||
/** @see ModuleBase */
|
||||
static int task_spawn(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* @brief Prints the driver status to the console.
|
||||
*/
|
||||
void status();
|
||||
/** @see ModuleBase */
|
||||
static int custom_command(int argc, char *argv[]) { return 0; };
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Parses the next note out of the string and plays it.
|
||||
*/
|
||||
void next_note();
|
||||
|
||||
/**
|
||||
* @brief Trampoline for the work queue.
|
||||
*/
|
||||
void Run() override;
|
||||
|
||||
/**
|
||||
* @brief Updates the uORB topics for local subscribers.
|
||||
*/
|
||||
void orb_update();
|
||||
|
||||
/**
|
||||
* @brief Starts playing the note.
|
||||
*/
|
||||
void start_note(unsigned frequency);
|
||||
|
||||
/**
|
||||
* @brief Stops playing the current note and makes the player 'safe'.
|
||||
*/
|
||||
void stop_note();
|
||||
|
||||
volatile bool _running{false}; ///< Flag to indicate the current driver status.
|
||||
|
||||
int _cbrk{CBRK_UNINIT}; ///< If true, no audio output.
|
||||
/** @see ModuleBase */
|
||||
static int print_usage(const char *reason = nullptr);
|
||||
|
||||
private:
|
||||
static void InterruptStopNote(void *arg);
|
||||
|
||||
volatile bool _should_run{true};
|
||||
bool Init();
|
||||
void Run() override;
|
||||
|
||||
hrt_call _hrt_call{};
|
||||
|
||||
Tunes _tunes;
|
||||
|
||||
hrt_abstime _next_note_time{0};
|
||||
|
||||
uORB::SubscriptionCallbackWorkItem _tune_control_sub{this, ORB_ID(tune_control)};
|
||||
|
||||
bool _circuit_break_initialized{false};
|
||||
bool _play_tone{false};
|
||||
|
||||
unsigned int _silence_length{0}; ///< If nonzero, silence before next note.
|
||||
|
||||
uORB::Subscription _tune_control_sub{ORB_ID(tune_control)};
|
||||
|
||||
tune_control_s _tune{};
|
||||
|
||||
Tunes _tunes = Tunes();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user