2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
26 #if defined(USE_VTX_COMMON)
30 #include "common/maths.h"
31 #include "common/time.h"
33 #include "drivers/vtx_common.h"
34 #if defined(USE_VTX_RTC6705)
35 #include "drivers/vtx_rtc6705.h"
37 #include "drivers/vtx_table.h"
39 #include "config/config.h"
40 #include "fc/rc_modes.h"
41 #include "fc/runtime_config.h"
43 #include "flight/failsafe.h"
45 #include "io/vtx_control.h"
48 #include "pg/pg_ids.h"
53 PG_REGISTER_WITH_RESET_FN(vtxSettingsConfig_t
, vtxSettingsConfig
, PG_VTX_SETTINGS_CONFIG
, 0);
55 void pgResetFn_vtxSettingsConfig(vtxSettingsConfig_t
*vtxSettingsConfig
)
58 vtxSettingsConfig
->band
= 0;
59 vtxSettingsConfig
->channel
= 0;
60 vtxSettingsConfig
->power
= 0;
61 vtxSettingsConfig
->freq
= 0;
63 vtxSettingsConfig
->freq
= VTX_TABLE_DEFAULT_FREQ
;
64 vtxSettingsConfig
->band
= VTX_TABLE_DEFAULT_BAND
;
65 vtxSettingsConfig
->channel
= VTX_TABLE_DEFAULT_CHANNEL
;
66 vtxSettingsConfig
->power
= VTX_TABLE_DEFAULT_POWER
;
68 vtxSettingsConfig
->pitModeFreq
= VTX_TABLE_DEFAULT_PITMODE_FREQ
;
69 vtxSettingsConfig
->lowPowerDisarm
= VTX_LOW_POWER_DISARM_OFF
;
78 } vtxScheduleParams_e
;
82 bool settingsUpdated
= false;
84 vtxDevice_t
*vtxDevice
= vtxCommonDevice();
87 // If a device is not registered, we don't have any table to refer.
88 // Don't manipulate settings and just return in this case.
92 // sync frequency in parameter group when band/channel are specified
93 const uint16_t freq
= vtxCommonLookupFrequency(vtxDevice
, vtxSettingsConfig()->band
, vtxSettingsConfig()->channel
);
94 if (vtxSettingsConfig()->band
&& freq
!= vtxSettingsConfig()->freq
) {
95 vtxSettingsConfigMutable()->freq
= freq
;
96 settingsUpdated
= true;
99 #if defined(VTX_SETTINGS_FREQCMD)
100 // constrain pit mode frequency
101 if (vtxSettingsConfig()->pitModeFreq
) {
102 const uint16_t constrainedPitModeFreq
= MAX(vtxSettingsConfig()->pitModeFreq
, VTX_TABLE_MIN_USER_FREQ
);
103 if (constrainedPitModeFreq
!= vtxSettingsConfig()->pitModeFreq
) {
104 vtxSettingsConfigMutable()->pitModeFreq
= constrainedPitModeFreq
;
105 settingsUpdated
= true;
110 if (settingsUpdated
) {
111 saveConfigAndNotify();
115 // Once refactoring for RTC6705 to handle pit mode properly and remove the requirement
116 // for having a 0 value in the vtxtable power levels is completed then this function will
117 // no longer be required and the VTX_TABLE_LOW_POWER_INDEX value can always be used.
118 static uint8_t vtxGetMinimumPowerIndex(void)
120 const vtxDevice_t
*vtxDevice
= vtxCommonDevice();
121 vtxDevType_e vtxType
= VTXDEV_UNKNOWN
;
123 vtxType
= vtxCommonGetDeviceType(vtxDevice
);
126 #if defined(USE_VTX_RTC6705)
128 // special handling for rtc6705 which has the low power setting in index 2
129 return VTX_RTC6705_DEFAULT_POWER_INDEX
;
132 return VTX_TABLE_LOW_POWER_INDEX
;
136 STATIC_UNIT_TESTED vtxSettingsConfig_t
vtxGetSettings(void)
138 vtxSettingsConfig_t settings
= {
139 .band
= vtxSettingsConfig()->band
,
140 .channel
= vtxSettingsConfig()->channel
,
141 .power
= vtxSettingsConfig()->power
,
142 .freq
= vtxSettingsConfig()->freq
,
143 .pitModeFreq
= vtxSettingsConfig()->pitModeFreq
,
144 .lowPowerDisarm
= vtxSettingsConfig()->lowPowerDisarm
,
147 #if defined(VTX_SETTINGS_FREQCMD)
148 if (IS_RC_MODE_ACTIVE(BOXVTXPITMODE
) && settings
.pitModeFreq
) {
150 settings
.freq
= settings
.pitModeFreq
;
151 settings
.power
= vtxGetMinimumPowerIndex();
155 if (!ARMING_FLAG(ARMED
) && !failsafeIsActive() &&
156 (settings
.lowPowerDisarm
== VTX_LOW_POWER_DISARM_ALWAYS
||
157 (settings
.lowPowerDisarm
== VTX_LOW_POWER_DISARM_UNTIL_FIRST_ARM
&& !ARMING_FLAG(WAS_EVER_ARMED
)))) {
158 settings
.power
= vtxGetMinimumPowerIndex();
164 static bool vtxProcessBandAndChannel(vtxDevice_t
*vtxDevice
)
166 if (!ARMING_FLAG(ARMED
)) {
169 if (vtxCommonGetBandAndChannel(vtxDevice
, &vtxBand
, &vtxChan
)) {
170 const vtxSettingsConfig_t settings
= vtxGetSettings();
171 if (vtxBand
!= settings
.band
|| vtxChan
!= settings
.channel
) {
172 vtxCommonSetBandAndChannel(vtxDevice
, settings
.band
, settings
.channel
);
180 #if defined(VTX_SETTINGS_FREQCMD)
181 static bool vtxProcessFrequency(vtxDevice_t
*vtxDevice
)
183 if (!ARMING_FLAG(ARMED
)) {
185 if (vtxCommonGetFrequency(vtxDevice
, &vtxFreq
)) {
186 const vtxSettingsConfig_t settings
= vtxGetSettings();
187 if (vtxFreq
!= settings
.freq
) {
188 vtxCommonSetFrequency(vtxDevice
, settings
.freq
);
197 static bool vtxProcessPower(vtxDevice_t
*vtxDevice
)
200 if (vtxCommonGetPowerIndex(vtxDevice
, &vtxPower
)) {
201 const vtxSettingsConfig_t settings
= vtxGetSettings();
202 if (vtxPower
!= settings
.power
) {
203 vtxCommonSetPowerByIndex(vtxDevice
, settings
.power
);
210 static bool vtxProcessPitMode(vtxDevice_t
*vtxDevice
)
212 static bool prevPmSwitchState
= false;
215 if (!ARMING_FLAG(ARMED
) && vtxCommonGetStatus(vtxDevice
, &vtxStatus
)) {
216 bool currPmSwitchState
= IS_RC_MODE_ACTIVE(BOXVTXPITMODE
);
218 if (currPmSwitchState
!= prevPmSwitchState
) {
219 prevPmSwitchState
= currPmSwitchState
;
221 if (currPmSwitchState
) {
222 #if defined(VTX_SETTINGS_FREQCMD)
223 if (vtxSettingsConfig()->pitModeFreq
) {
227 if (!(vtxStatus
& VTX_STATUS_PIT_MODE
)) {
228 vtxCommonSetPitMode(vtxDevice
, true);
233 if (vtxStatus
& VTX_STATUS_PIT_MODE
) {
234 vtxCommonSetPitMode(vtxDevice
, false);
245 static bool vtxProcessStateUpdate(vtxDevice_t
*vtxDevice
)
247 const vtxSettingsConfig_t vtxSettingsState
= vtxGetSettings();
248 vtxSettingsConfig_t vtxState
= vtxSettingsState
;
250 if (vtxSettingsState
.band
) {
251 vtxCommonGetBandAndChannel(vtxDevice
, &vtxState
.band
, &vtxState
.channel
);
252 #if defined(VTX_SETTINGS_FREQCMD)
254 vtxCommonGetFrequency(vtxDevice
, &vtxState
.freq
);
258 vtxCommonGetPowerIndex(vtxDevice
, &vtxState
.power
);
260 return (bool)memcmp(&vtxSettingsState
, &vtxState
, sizeof(vtxSettingsConfig_t
));
263 void vtxUpdate(timeUs_t currentTimeUs
)
265 static uint8_t currentSchedule
= 0;
271 vtxDevice_t
*vtxDevice
= vtxCommonDevice();
273 // Check input sources for config updates
274 vtxControlInputPoll();
276 const uint8_t startingSchedule
= currentSchedule
;
277 bool vtxUpdatePending
= false;
279 switch (currentSchedule
) {
280 case VTX_PARAM_POWER
:
281 vtxUpdatePending
= vtxProcessPower(vtxDevice
);
283 case VTX_PARAM_BANDCHAN
:
284 if (vtxGetSettings().band
) {
285 vtxUpdatePending
= vtxProcessBandAndChannel(vtxDevice
);
286 #if defined(VTX_SETTINGS_FREQCMD)
288 vtxUpdatePending
= vtxProcessFrequency(vtxDevice
);
292 case VTX_PARAM_PITMODE
:
293 vtxUpdatePending
= vtxProcessPitMode(vtxDevice
);
295 case VTX_PARAM_CONFIRM
:
296 vtxUpdatePending
= vtxProcessStateUpdate(vtxDevice
);
301 currentSchedule
= (currentSchedule
+ 1) % VTX_PARAM_COUNT
;
302 } while (!vtxUpdatePending
&& currentSchedule
!= startingSchedule
);
304 if (!ARMING_FLAG(ARMED
) || vtxUpdatePending
) {
305 vtxCommonProcess(vtxDevice
, currentTimeUs
);