2021-02-17 15:15:27 -04:00
|
|
|
/*
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
|
2023-01-19 09:00:17 -04:00
|
|
|
#include "AP_VideoTX_config.h"
|
|
|
|
|
|
|
|
#if AP_VIDEOTX_ENABLED
|
|
|
|
|
2021-02-17 15:15:27 -04:00
|
|
|
#include <AP_Param/AP_Param.h>
|
|
|
|
|
|
|
|
#define VTX_MAX_CHANNELS 8
|
2024-04-29 15:09:09 -03:00
|
|
|
#define VTX_MAX_POWER_LEVELS 10
|
2021-02-17 15:15:27 -04:00
|
|
|
|
|
|
|
class AP_VideoTX {
|
|
|
|
public:
|
|
|
|
AP_VideoTX();
|
|
|
|
~AP_VideoTX();
|
|
|
|
|
|
|
|
/* Do not allow copies */
|
2022-09-30 06:50:43 -03:00
|
|
|
CLASS_NO_COPY(AP_VideoTX);
|
2021-02-17 15:15:27 -04:00
|
|
|
|
|
|
|
// init - perform required initialisation
|
|
|
|
bool init();
|
|
|
|
|
|
|
|
// run any required updates
|
|
|
|
void update();
|
|
|
|
|
|
|
|
static AP_VideoTX *get_singleton(void) {
|
|
|
|
return singleton;
|
|
|
|
}
|
|
|
|
static const struct AP_Param::GroupInfo var_info[];
|
|
|
|
|
|
|
|
enum class VideoOptions {
|
|
|
|
VTX_PITMODE = (1 << 0),
|
|
|
|
VTX_PITMODE_UNTIL_ARM = (1 << 1),
|
|
|
|
VTX_PITMODE_ON_DISARM = (1 << 2),
|
|
|
|
VTX_UNLOCKED = (1 << 3),
|
2021-06-02 04:44:17 -03:00
|
|
|
VTX_PULLDOWN = (1 << 4),
|
2021-12-12 12:35:10 -04:00
|
|
|
VTX_SA_ONE_STOP_BIT = (1 << 5),
|
|
|
|
VTX_SA_IGNORE_CRC = (1 << 6),
|
|
|
|
VTX_CRSF_IGNORE_STAT = (1 << 7),
|
2021-02-17 15:15:27 -04:00
|
|
|
};
|
|
|
|
|
2021-05-31 10:15:18 -03:00
|
|
|
static const char *band_names[];
|
|
|
|
|
2021-02-17 15:15:27 -04:00
|
|
|
enum VideoBand {
|
|
|
|
BAND_A,
|
|
|
|
BAND_B,
|
|
|
|
BAND_E,
|
|
|
|
FATSHARK,
|
|
|
|
RACEBAND,
|
|
|
|
LOW_RACEBAND,
|
2023-09-12 07:02:03 -03:00
|
|
|
BAND_1G3_A,
|
|
|
|
BAND_1G3_B,
|
2024-03-15 10:11:18 -03:00
|
|
|
BAND_X,
|
2024-08-07 05:54:18 -03:00
|
|
|
BAND_3G3_A,
|
|
|
|
BAND_3G3_B,
|
2021-02-17 15:15:27 -04:00
|
|
|
MAX_BANDS
|
|
|
|
};
|
|
|
|
|
2021-12-12 12:35:10 -04:00
|
|
|
enum class PowerActive {
|
|
|
|
Unknown,
|
|
|
|
Active,
|
|
|
|
Inactive
|
|
|
|
};
|
|
|
|
|
2024-04-29 15:09:09 -03:00
|
|
|
enum VTXType {
|
|
|
|
CRSF = 1U<<0,
|
|
|
|
SmartAudio = 1U<<1,
|
|
|
|
Tramp = 1U<<2
|
|
|
|
};
|
|
|
|
|
2021-12-12 12:35:10 -04:00
|
|
|
struct PowerLevel {
|
|
|
|
uint8_t level;
|
|
|
|
uint16_t mw;
|
|
|
|
uint8_t dbm;
|
|
|
|
uint8_t dac; // SmartAudio v1 dac value
|
|
|
|
PowerActive active;
|
|
|
|
};
|
|
|
|
|
|
|
|
static PowerLevel _power_levels[VTX_MAX_POWER_LEVELS];
|
|
|
|
|
2021-02-17 15:15:27 -04:00
|
|
|
static const uint16_t VIDEO_CHANNELS[MAX_BANDS][VTX_MAX_CHANNELS];
|
|
|
|
|
|
|
|
static uint16_t get_frequency_mhz(uint8_t band, uint8_t channel) { return VIDEO_CHANNELS[band][channel]; }
|
|
|
|
static bool get_band_and_channel(uint16_t freq, VideoBand& band, uint8_t& channel);
|
|
|
|
|
|
|
|
void set_frequency_mhz(uint16_t freq) { _current_frequency = freq; }
|
|
|
|
void set_configured_frequency_mhz(uint16_t freq) { _frequency_mhz.set_and_save_ifchanged(freq); }
|
|
|
|
uint16_t get_frequency_mhz() const { return _current_frequency; }
|
|
|
|
uint16_t get_configured_frequency_mhz() const { return _frequency_mhz; }
|
|
|
|
bool update_frequency() const { return _defaults_set && _frequency_mhz != _current_frequency; }
|
|
|
|
void update_configured_frequency();
|
|
|
|
// get / set power level
|
2021-12-12 12:35:10 -04:00
|
|
|
void set_power_mw(uint16_t power);
|
|
|
|
void set_power_level(uint8_t level, PowerActive active=PowerActive::Active);
|
|
|
|
void set_power_dbm(uint8_t power, PowerActive active=PowerActive::Active);
|
|
|
|
void set_power_dac(uint16_t power, PowerActive active=PowerActive::Active);
|
|
|
|
// add a new dbm setting to those supported
|
|
|
|
uint8_t update_power_dbm(uint8_t power, PowerActive active=PowerActive::Active);
|
|
|
|
void update_all_power_dbm(uint8_t nlevels, const uint8_t levels[]);
|
2021-02-17 15:15:27 -04:00
|
|
|
void set_configured_power_mw(uint16_t power);
|
|
|
|
uint16_t get_configured_power_mw() const { return _power_mw; }
|
2021-12-12 12:35:10 -04:00
|
|
|
uint16_t get_power_mw() const { return _power_levels[_current_power].mw; }
|
|
|
|
|
|
|
|
// get the power in dbm, rounding appropriately
|
|
|
|
uint8_t get_configured_power_dbm() const {
|
|
|
|
return _power_levels[find_current_power()].dbm;
|
|
|
|
}
|
|
|
|
// get the power "level"
|
|
|
|
uint8_t get_configured_power_level() const {
|
|
|
|
return _power_levels[find_current_power()].level & 0xF;
|
|
|
|
}
|
|
|
|
// get the power "dac"
|
|
|
|
uint8_t get_configured_power_dac() const {
|
|
|
|
return _power_levels[find_current_power()].dac;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool update_power() const;
|
2021-02-17 15:15:27 -04:00
|
|
|
// change the video power based on switch input
|
|
|
|
void change_power(int8_t position);
|
|
|
|
// get / set the frequency band
|
|
|
|
void set_band(uint8_t band) { _current_band = band; }
|
|
|
|
void set_configured_band(uint8_t band) { _band.set_and_save_ifchanged(band); }
|
|
|
|
uint8_t get_configured_band() const { return _band; }
|
|
|
|
uint8_t get_band() const { return _current_band; }
|
|
|
|
bool update_band() const { return _defaults_set && _band != _current_band; }
|
|
|
|
// get / set the frequency channel
|
|
|
|
void set_channel(uint8_t channel) { _current_channel = channel; }
|
|
|
|
void set_configured_channel(uint8_t channel) { _channel.set_and_save_ifchanged(channel); }
|
|
|
|
uint8_t get_configured_channel() const { return _channel; }
|
|
|
|
uint8_t get_channel() const { return _current_channel; }
|
|
|
|
bool update_channel() const { return _defaults_set && _channel != _current_channel; }
|
|
|
|
void update_configured_channel_and_band();
|
|
|
|
// get / set vtx option
|
2021-12-12 12:35:10 -04:00
|
|
|
void set_options(uint16_t options) { _current_options = options; }
|
|
|
|
void set_configured_options(uint16_t options) { _options.set_and_save_ifchanged(options); }
|
|
|
|
uint16_t get_configured_options() const { return _options; }
|
|
|
|
uint16_t get_options() const { return _current_options; }
|
|
|
|
bool has_option(VideoOptions option) const { return _options.get() & uint16_t(option); }
|
|
|
|
bool get_configured_pitmode() const { return _options.get() & uint8_t(AP_VideoTX::VideoOptions::VTX_PITMODE); }
|
|
|
|
bool get_pitmode() const { return _current_options & uint8_t(AP_VideoTX::VideoOptions::VTX_PITMODE); }
|
2021-05-06 17:26:10 -03:00
|
|
|
bool update_options() const;
|
2021-02-17 15:15:27 -04:00
|
|
|
// get / set whether the vtx is enabled
|
|
|
|
void set_enabled(bool enabled);
|
|
|
|
bool get_enabled() const { return _enabled; }
|
|
|
|
bool update_enabled() const { return _defaults_set && _enabled != _current_enabled; }
|
|
|
|
|
|
|
|
// have the parameters been updated
|
|
|
|
bool have_params_changed() const;
|
|
|
|
// set configured defaults from current settings, return true if defaults were set
|
|
|
|
bool set_defaults();
|
|
|
|
// display the current VTX settings in the GCS
|
|
|
|
void announce_vtx_settings() const;
|
2021-12-12 12:35:10 -04:00
|
|
|
// force the current values to reflect the configured values
|
|
|
|
void set_power_is_current();
|
|
|
|
void set_freq_is_current();
|
|
|
|
void set_options_are_current() { _current_options = _options; }
|
2021-02-17 15:15:27 -04:00
|
|
|
|
2021-05-27 12:48:04 -03:00
|
|
|
void set_configuration_finished(bool configuration_finished) { _configuration_finished = configuration_finished; }
|
|
|
|
bool is_configuration_finished() { return _configuration_finished; }
|
|
|
|
|
2024-04-29 15:09:09 -03:00
|
|
|
// manage VTX backends
|
|
|
|
bool is_provider_enabled(VTXType type) const { return (_types & type) != 0; }
|
|
|
|
void set_provider_enabled(VTXType type) { _types |= type; }
|
|
|
|
|
2021-02-17 15:15:27 -04:00
|
|
|
static AP_VideoTX *singleton;
|
|
|
|
|
|
|
|
private:
|
2021-12-12 12:35:10 -04:00
|
|
|
uint8_t find_current_power() const;
|
2021-02-17 15:15:27 -04:00
|
|
|
// channel frequency
|
|
|
|
AP_Int16 _frequency_mhz;
|
|
|
|
uint16_t _current_frequency;
|
|
|
|
|
|
|
|
// power output in mw
|
|
|
|
AP_Int16 _power_mw;
|
|
|
|
uint16_t _current_power;
|
|
|
|
AP_Int16 _max_power_mw;
|
|
|
|
|
|
|
|
// frequency band
|
|
|
|
AP_Int8 _band;
|
|
|
|
uint16_t _current_band;
|
|
|
|
|
|
|
|
// frequency channel
|
|
|
|
AP_Int8 _channel;
|
|
|
|
uint8_t _current_channel;
|
|
|
|
|
|
|
|
// vtx options
|
2021-12-12 12:35:10 -04:00
|
|
|
AP_Int16 _options;
|
|
|
|
uint16_t _current_options;
|
2021-02-17 15:15:27 -04:00
|
|
|
|
|
|
|
AP_Int8 _enabled;
|
|
|
|
bool _current_enabled;
|
|
|
|
|
|
|
|
bool _initialized;
|
|
|
|
// when defaults have been configured
|
|
|
|
bool _defaults_set;
|
2021-12-12 12:35:10 -04:00
|
|
|
// true when configuration have been applied successfully to the VTX
|
2021-05-27 12:48:04 -03:00
|
|
|
bool _configuration_finished;
|
2024-04-29 15:09:09 -03:00
|
|
|
|
|
|
|
// types of VTX providers
|
|
|
|
uint8_t _types;
|
2021-02-17 15:15:27 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
namespace AP {
|
|
|
|
AP_VideoTX& vtx();
|
2021-05-27 12:48:04 -03:00
|
|
|
};
|
2023-01-19 09:00:17 -04:00
|
|
|
|
|
|
|
#endif // AP_VIDEOTX_ENABLED
|