Line data Source code
1 : /* 2 : This program is free software: you can redistribute it and/or modify 3 : it under the terms of the GNU General Public License as published by 4 : the Free Software Foundation, either version 3 of the License, or 5 : (at your option) any later version. 6 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : #pragma once 16 : 17 : #include "AP_VideoTX_config.h" 18 : 19 : #if AP_VIDEOTX_ENABLED 20 : 21 : #include <AP_Param/AP_Param.h> 22 : 23 : #define VTX_MAX_CHANNELS 8 24 : #define VTX_MAX_POWER_LEVELS 10 25 : 26 : class AP_VideoTX { 27 : public: 28 : AP_VideoTX(); 29 : ~AP_VideoTX(); 30 : 31 : /* Do not allow copies */ 32 : CLASS_NO_COPY(AP_VideoTX); 33 : 34 : // init - perform required initialisation 35 : bool init(); 36 : 37 : // run any required updates 38 : void update(); 39 : 40 6872 : static AP_VideoTX *get_singleton(void) { 41 6872 : return singleton; 42 : } 43 : static const struct AP_Param::GroupInfo var_info[]; 44 : 45 : enum class VideoOptions { 46 : VTX_PITMODE = (1 << 0), 47 : VTX_PITMODE_UNTIL_ARM = (1 << 1), 48 : VTX_PITMODE_ON_DISARM = (1 << 2), 49 : VTX_UNLOCKED = (1 << 3), 50 : VTX_PULLDOWN = (1 << 4), 51 : VTX_SA_ONE_STOP_BIT = (1 << 5), 52 : VTX_SA_IGNORE_CRC = (1 << 6), 53 : VTX_CRSF_IGNORE_STAT = (1 << 7), 54 : }; 55 : 56 : static const char *band_names[]; 57 : 58 : enum VideoBand { 59 : BAND_A, 60 : BAND_B, 61 : BAND_E, 62 : FATSHARK, 63 : RACEBAND, 64 : LOW_RACEBAND, 65 : BAND_1G3_A, 66 : BAND_1G3_B, 67 : BAND_X, 68 : BAND_3G3_A, 69 : BAND_3G3_B, 70 : MAX_BANDS 71 : }; 72 : 73 : enum class PowerActive { 74 : Unknown, 75 : Active, 76 : Inactive 77 : }; 78 : 79 : enum VTXType { 80 : CRSF = 1U<<0, 81 : SmartAudio = 1U<<1, 82 : Tramp = 1U<<2, 83 : MSP = 1U<<3 84 : }; 85 : 86 : struct PowerLevel { 87 : uint8_t level; 88 : uint16_t mw; 89 : uint8_t dbm; 90 : uint8_t dac; // SmartAudio v1 dac value 91 : PowerActive active; 92 : }; 93 : 94 : static PowerLevel _power_levels[VTX_MAX_POWER_LEVELS]; 95 : 96 : static const uint16_t VIDEO_CHANNELS[MAX_BANDS][VTX_MAX_CHANNELS]; 97 : 98 141 : static uint16_t get_frequency_mhz(uint8_t band, uint8_t channel) { return VIDEO_CHANNELS[band][channel]; } 99 : static bool get_band_and_channel(uint16_t freq, VideoBand& band, uint8_t& channel); 100 : 101 0 : void set_frequency_mhz(uint16_t freq) { _current_frequency = freq; } 102 12 : void set_configured_frequency_mhz(uint16_t freq) { _frequency_mhz.set_and_save_ifchanged(freq); } 103 0 : uint16_t get_frequency_mhz() const { return _current_frequency; } 104 16 : uint16_t get_configured_frequency_mhz() const { return _frequency_mhz; } 105 0 : bool update_frequency() const { return _defaults_set && _frequency_mhz != _current_frequency; } 106 : void update_configured_frequency(); 107 : // get / set power level 108 : void set_power_mw(uint16_t power); 109 : void set_power_level(uint8_t level, PowerActive active=PowerActive::Active); 110 : void set_power_dbm(uint8_t power, PowerActive active=PowerActive::Active); 111 : void set_power_dac(uint16_t power, PowerActive active=PowerActive::Active); 112 : // add a new dbm setting to those supported 113 : uint8_t update_power_dbm(uint8_t power, PowerActive active=PowerActive::Active); 114 : void update_all_power_dbm(uint8_t nlevels, const uint8_t levels[]); 115 : void set_configured_power_mw(uint16_t power); 116 141 : uint16_t get_configured_power_mw() const { return _power_mw; } 117 196 : uint16_t get_power_mw() const { return _power_levels[_current_power].mw; } 118 : // VTX-reported actual power; -1 if the provider doesn't report it, 0 is pit mode 119 0 : void set_actual_power_mw(uint16_t power) { _actual_power_mw = int32_t(power); } 120 0 : int32_t get_actual_power_mw() const { return _actual_power_mw; } 121 0 : uint16_t get_max_power_mw() const { return _max_power_mw; } 122 : 123 : // get the power in dbm, rounding appropriately 124 0 : uint8_t get_configured_power_dbm() const { 125 0 : return _power_levels[find_current_power()].dbm; 126 : } 127 : // get the power "level" 128 0 : uint8_t get_configured_power_level() const { 129 0 : return _power_levels[find_current_power()].level & 0xF; 130 : } 131 : // get the power "dac" 132 0 : uint8_t get_configured_power_dac() const { 133 0 : return _power_levels[find_current_power()].dac; 134 : } 135 : 136 : // mark the power level matching the given mW as supported, learning it 137 : // into the custom slot if it is not a standard value 138 : void update_power_mw(uint16_t power_mw, PowerActive active = PowerActive::Active); 139 : // a provider's power index is one based and refers to the supported (active) 140 : // levels in ascending order, so index 1 is the lowest supported level 141 : uint8_t get_num_power_levels() const; 142 : // mW for a one based power index, 0 if not known 143 : uint16_t get_power_mw_for_index(uint8_t index) const; 144 : // one based power index for a mW value, 0 if not matched 145 : uint8_t get_power_index_for_mw(uint16_t power_mw) const; 146 : 147 : bool update_power() const; 148 : // change the video power based on switch input 149 : void change_power(int8_t position); 150 : // get / set the frequency band 151 0 : void set_band(uint8_t band) { _current_band = band; } 152 12 : void set_configured_band(uint8_t band) { _band.set_and_save_ifchanged(band); } 153 266 : uint8_t get_configured_band() const { return _band; } 154 0 : uint8_t get_band() const { return _current_band; } 155 0 : bool update_band() const { return _defaults_set && _band != _current_band; } 156 : // get / set the frequency channel 157 0 : void set_channel(uint8_t channel) { _current_channel = channel; } 158 12 : void set_configured_channel(uint8_t channel) { _channel.set_and_save_ifchanged(channel); } 159 266 : uint8_t get_configured_channel() const { return _channel; } 160 0 : uint8_t get_channel() const { return _current_channel; } 161 0 : bool update_channel() const { return _defaults_set && _channel != _current_channel; } 162 : void update_configured_channel_and_band(); 163 : // get / set vtx option 164 0 : void set_options(uint16_t options) { _current_options = options; } 165 10 : void set_configured_options(uint16_t options) { _options.set_and_save_ifchanged(options); } 166 10 : uint16_t get_configured_options() const { return _options; } 167 0 : uint16_t get_options() const { return _current_options; } 168 402 : bool has_option(VideoOptions option) const { return _options.get() & uint16_t(option); } 169 : // set or clear a single configured option bit, leaving the others untouched 170 10 : void set_option_enabled(VideoOptions option, bool enabled) { 171 18 : set_configured_options(enabled ? (get_configured_options() | uint16_t(option)) 172 8 : : (get_configured_options() & ~uint16_t(option))); 173 10 : } 174 141 : bool get_configured_pitmode() const { return _options.get() & uint8_t(AP_VideoTX::VideoOptions::VTX_PITMODE); } 175 0 : bool get_pitmode() const { return _current_options & uint8_t(AP_VideoTX::VideoOptions::VTX_PITMODE); } 176 : bool update_options() const; 177 : // get / set whether the vtx is enabled 178 : void set_enabled(bool enabled); 179 4967 : bool get_enabled() const { return _enabled; } 180 : bool update_enabled() const { return _defaults_set && _enabled != _current_enabled; } 181 : 182 : // have the parameters been updated 183 : bool have_params_changed() const; 184 : // set configured defaults from current settings, return true if defaults were set 185 : bool set_defaults(); 186 : // display the current VTX settings in the GCS 187 : void announce_vtx_settings() const; 188 : // force the current values to reflect the configured values 189 : void set_power_is_current(); 190 : void set_freq_is_current(); 191 : void set_options_are_current() { _current_options = _options; } 192 : 193 0 : void set_configuration_finished(bool configuration_finished) { _configuration_finished = configuration_finished; } 194 0 : bool is_configuration_finished() { return _configuration_finished; } 195 : 196 : // manage VTX backends 197 0 : bool is_provider_enabled(VTXType type) const { return (_types & type) != 0; } 198 : // a provider may only register if the user allows its type (VTX_TYPES) 199 10 : void set_provider_enabled(VTXType type) { if (is_type_enabled(type)) { _types |= type; } } 200 : // is this control transport allowed to manage the VTX 201 10 : bool is_type_enabled(VTXType type) const { return (uint8_t(_types_allowed) & uint8_t(type)) != 0; } 202 : 203 : static AP_VideoTX *singleton; 204 : 205 : private: 206 : uint8_t find_current_power() const; 207 : // channel frequency 208 : AP_Int16 _frequency_mhz; 209 : uint16_t _current_frequency; 210 : 211 : // power output in mw 212 : AP_Int16 _power_mw; 213 : uint16_t _current_power; 214 : int32_t _actual_power_mw {-1}; 215 : AP_Int16 _max_power_mw; 216 : 217 : // frequency band 218 : AP_Int8 _band; 219 : uint16_t _current_band; 220 : 221 : // frequency channel 222 : AP_Int8 _channel; 223 : uint8_t _current_channel; 224 : 225 : // vtx options 226 : AP_Int16 _options; 227 : uint16_t _current_options; 228 : 229 : AP_Int8 _enabled; 230 : bool _current_enabled; 231 : 232 : // bitmask of VTXType control transports the user permits (VTX_TYPES) 233 : AP_Int8 _types_allowed; 234 : 235 : bool _initialized; 236 : // when defaults have been configured 237 : bool _defaults_set; 238 : // true when configuration have been applied successfully to the VTX 239 : bool _configuration_finished; 240 : 241 : // types of VTX providers 242 : uint8_t _types; 243 : }; 244 : 245 : namespace AP { 246 : AP_VideoTX& vtx(); 247 : }; 248 : 249 : #endif // AP_VIDEOTX_ENABLED