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/>.
23 #include <drivers/vtx_table.h>
27 #if defined(USE_VTX_CONTROL) && defined(USE_VTX_COMMON)
29 #include "common/maths.h"
31 #include "config/config_eeprom.h"
33 #include "drivers/buttons.h"
34 #include "drivers/light_led.h"
35 #include "drivers/time.h"
36 #include "drivers/vtx_common.h"
38 #include "config/config.h"
39 #include "fc/runtime_config.h"
41 #include "io/spektrum_vtx_control.h"
43 #include "io/vtx_control.h"
48 #include "pg/pg_ids.h"
50 PG_REGISTER_WITH_RESET_TEMPLATE(vtxConfig_t
, vtxConfig
, PG_VTX_CONFIG
, 1);
52 PG_RESET_TEMPLATE(vtxConfig_t
, vtxConfig
,
53 // .vtxChannelActivationConditions = { 0 },
57 static uint8_t locked
= 0;
59 void vtxControlInit(void)
64 void vtxControlInputPoll(void)
66 // Check variuos input sources for VTX config updates
67 #if defined(USE_SPEKTRUM_VTX_CONTROL)
73 static void vtxUpdateBandAndChannel(uint8_t bandStep
, uint8_t channelStep
)
75 if (ARMING_FLAG(ARMED
)) {
79 if (!locked
&& vtxCommonDevice()) {
80 vtxSettingsConfigMutable()->band
+= bandStep
;
81 vtxSettingsConfigMutable()->channel
+= channelStep
;
85 void vtxIncrementBand(void)
87 vtxUpdateBandAndChannel(+1, 0);
90 void vtxDecrementBand(void)
92 vtxUpdateBandAndChannel(-1, 0);
95 void vtxIncrementChannel(void)
97 vtxUpdateBandAndChannel(0, +1);
100 void vtxDecrementChannel(void)
102 vtxUpdateBandAndChannel(0, -1);
105 void vtxUpdateActivatedChannel(void)
107 if (ARMING_FLAG(ARMED
)) {
111 if (vtxCommonDevice()) {
112 static uint8_t lastIndex
= -1;
114 for (uint8_t index
= 0; index
< MAX_CHANNEL_ACTIVATION_CONDITION_COUNT
; index
++) {
115 const vtxChannelActivationCondition_t
*vtxChannelActivationCondition
= &vtxConfig()->vtxChannelActivationConditions
[index
];
117 if (isRangeActive(vtxChannelActivationCondition
->auxChannelIndex
, &vtxChannelActivationCondition
->range
)
118 && index
!= lastIndex
) {
122 if (vtxChannelActivationCondition
->band
> 0) {
123 vtxSettingsConfigMutable()->band
= vtxChannelActivationCondition
->band
;
125 if (vtxChannelActivationCondition
->channel
> 0) {
126 vtxSettingsConfigMutable()->channel
= vtxChannelActivationCondition
->channel
;
130 if (vtxChannelActivationCondition
->power
> 0) {
131 vtxSettingsConfigMutable()->power
= vtxChannelActivationCondition
->power
;
139 void vtxCycleBandOrChannel(const uint8_t bandStep
, const uint8_t channelStep
)
141 const vtxDevice_t
*vtxDevice
= vtxCommonDevice();
143 uint8_t band
= 0, channel
= 0;
145 const bool haveAllNeededInfo
= vtxCommonGetBandAndChannel(vtxDevice
, &band
, &channel
);
146 if (!haveAllNeededInfo
) {
150 int newChannel
= channel
+ channelStep
;
151 if (newChannel
> vtxTableChannelCount
) {
153 } else if (newChannel
< 1) {
154 newChannel
= vtxTableChannelCount
;
157 int newBand
= band
+ bandStep
;
158 if (newBand
> vtxTableBandCount
) {
160 } else if (newBand
< 1) {
161 newBand
= vtxTableBandCount
;
164 vtxSettingsConfigMutable()->band
= newBand
;
165 vtxSettingsConfigMutable()->channel
= newChannel
;
169 void vtxCyclePower(const uint8_t powerStep
)
171 const vtxDevice_t
*vtxDevice
= vtxCommonDevice();
174 const bool haveAllNeededInfo
= vtxCommonGetPowerIndex(vtxDevice
, &power
);
175 if (!haveAllNeededInfo
) {
179 int newPower
= power
+ powerStep
;
180 if (newPower
>= vtxTablePowerLevels
) {
182 } else if (newPower
< 0) {
183 newPower
= vtxTablePowerLevels
;
186 vtxSettingsConfigMutable()->power
= newPower
;
191 * Allow VTX channel/band/rf power/on-off and save via a single button.
193 * The LED1 flashes a set number of times, followed by a short pause, one per second. The amount of flashes decreases over time while
194 * the button is held to indicate the action that will be performed upon release.
195 * The actions are ordered by most-frequently used action. i.e. you change channel more frequently than band.
197 * The vtx settings can be changed while the VTX is OFF.
198 * If the VTX is OFF when the settings are saved the VTX will be OFF on the next boot, likewise
199 * If the VTX is ON when the settings are saved the VTX will be ON on the next boot.
201 * Future: It would be nice to re-use the code in statusindicator.c and blink-codes but target a different LED instead of the simple timed
202 * behaviour of the LED1 here.
204 * Future: Blink out the state after changing it.
206 void handleVTXControlButton(void)
208 #if defined(USE_VTX_RTC6705) && defined(BUTTON_A_PIN)
209 bool buttonWasPressed
= false;
210 const timeMs_t start
= millis();
211 timeMs_t ledToggleAt
= start
;
212 bool ledEnabled
= false;
213 uint8_t flashesDone
= 0;
215 uint8_t actionCounter
= 0;
217 while ((buttonHeld
= buttonAPressed())) {
218 const timeMs_t end
= millis();
220 int32_t diff
= cmp32(end
, start
);
221 if (diff
> 25 && diff
<= 1000) {
223 } else if (diff
> 1000 && diff
<= 3000) {
225 } else if (diff
> 3000 && diff
<= 5000) {
227 } else if (diff
> 5000) {
233 diff
= cmp32(ledToggleAt
, end
);
236 ledEnabled
= !ledEnabled
;
238 const uint8_t updateDuration
= 60;
240 ledToggleAt
= end
+ updateDuration
;
249 if (flashesDone
== actionCounter
) {
250 ledToggleAt
+= (1000 - ((flashesDone
* updateDuration
) * 2));
254 buttonWasPressed
= true;
258 if (!buttonWasPressed
) {
264 switch (actionCounter
) {
266 vtxCycleBandOrChannel(0, +1);
269 vtxCycleBandOrChannel(+1, 0);
275 saveConfigAndNotify();