1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-24 08:45:36 +03:00
betaflight/src/main/io/vtx_control.c

260 lines
6.9 KiB
C

/*
* This file is part of Cleanflight.
*
* Cleanflight 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.
*
* Cleanflight 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 Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#if defined(USE_VTX_CONTROL) && defined(USE_VTX_COMMON)
#include "common/maths.h"
#include "config/config_eeprom.h"
#include "pg/pg.h"
#include "pg/pg_ids.h"
#include "drivers/buttons.h"
#include "drivers/light_led.h"
#include "drivers/time.h"
#include "drivers/vtx_common.h"
#include "fc/config.h"
#include "fc/runtime_config.h"
#include "io/beeper.h"
#include "io/osd.h"
#include "io/vtx_control.h"
#include "io/vtx.h"
PG_REGISTER_WITH_RESET_TEMPLATE(vtxConfig_t, vtxConfig, PG_VTX_CONFIG, 1);
PG_RESET_TEMPLATE(vtxConfig_t, vtxConfig,
// .vtxChannelActivationConditions = { 0 },
.halfDuplex = true
);
static uint8_t locked = 0;
void vtxControlInit(void)
{
// NOTHING TO DO
}
static void vtxUpdateBandAndChannel(uint8_t bandStep, uint8_t channelStep)
{
if (ARMING_FLAG(ARMED)) {
locked = 1;
}
if (!locked && vtxCommonDeviceRegistered()) {
vtxSettingsConfigMutable()->band += bandStep;
vtxSettingsConfigMutable()->channel += channelStep;
}
}
void vtxIncrementBand(void)
{
vtxUpdateBandAndChannel(+1, 0);
}
void vtxDecrementBand(void)
{
vtxUpdateBandAndChannel(-1, 0);
}
void vtxIncrementChannel(void)
{
vtxUpdateBandAndChannel(0, +1);
}
void vtxDecrementChannel(void)
{
vtxUpdateBandAndChannel(0, -1);
}
void vtxUpdateActivatedChannel(void)
{
if (ARMING_FLAG(ARMED)) {
locked = 1;
}
if (!locked && vtxCommonDeviceRegistered()) {
static uint8_t lastIndex = -1;
for (uint8_t index = 0; index < MAX_CHANNEL_ACTIVATION_CONDITION_COUNT; index++) {
const vtxChannelActivationCondition_t *vtxChannelActivationCondition = &vtxConfig()->vtxChannelActivationConditions[index];
if (isRangeActive(vtxChannelActivationCondition->auxChannelIndex, &vtxChannelActivationCondition->range)
&& index != lastIndex) {
lastIndex = index;
vtxSettingsConfigMutable()->band = vtxChannelActivationCondition->band;
vtxSettingsConfigMutable()->channel = vtxChannelActivationCondition->channel;
break;
}
}
}
}
void vtxCycleBandOrChannel(const uint8_t bandStep, const uint8_t channelStep)
{
if (vtxCommonDeviceRegistered()) {
uint8_t band = 0, channel = 0;
vtxDeviceCapability_t capability;
bool haveAllNeededInfo = vtxCommonGetBandAndChannel(&band, &channel) && vtxCommonGetDeviceCapability(&capability);
if (!haveAllNeededInfo) {
return;
}
int newChannel = channel + channelStep;
if (newChannel > capability.channelCount) {
newChannel = 1;
} else if (newChannel < 1) {
newChannel = capability.channelCount;
}
int newBand = band + bandStep;
if (newBand > capability.bandCount) {
newBand = 1;
} else if (newBand < 1) {
newBand = capability.bandCount;
}
vtxSettingsConfigMutable()->band = newBand;
vtxSettingsConfigMutable()->channel = newChannel;
}
}
void vtxCyclePower(const uint8_t powerStep)
{
if (vtxCommonDeviceRegistered()) {
uint8_t power = 0;
vtxDeviceCapability_t capability;
bool haveAllNeededInfo = vtxCommonGetPowerIndex(&power) && vtxCommonGetDeviceCapability(&capability);
if (!haveAllNeededInfo) {
return;
}
int newPower = power + powerStep;
if (newPower >= capability.powerCount) {
newPower = 0;
} else if (newPower < 0) {
newPower = capability.powerCount;
}
vtxSettingsConfigMutable()->power = newPower;
}
}
/**
* Allow VTX channel/band/rf power/on-off and save via a single button.
*
* The LED1 flashes a set number of times, followed by a short pause, one per second. The amount of flashes decreases over time while
* the button is held to indicate the action that will be performed upon release.
* The actions are ordered by most-frequently used action. i.e. you change channel more frequently than band.
*
* The vtx settings can be changed while the VTX is OFF.
* If the VTX is OFF when the settings are saved the VTX will be OFF on the next boot, likewise
* If the VTX is ON when the settings are saved the VTX will be ON on the next boot.
*
* 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
* behaviour of the LED1 here.
*
* Future: Blink out the state after changing it.
*/
void handleVTXControlButton(void)
{
#if defined(USE_VTX_RTC6705) && defined(BUTTON_A_PIN)
bool buttonWasPressed = false;
uint32_t start = millis();
uint32_t ledToggleAt = start;
bool ledEnabled = false;
uint8_t flashesDone = 0;
uint8_t actionCounter = 0;
bool buttonHeld;
while ((buttonHeld = buttonAPressed())) {
uint32_t end = millis();
int32_t diff = cmp32(end, start);
if (diff > 25 && diff <= 1000) {
actionCounter = 4;
} else if (diff > 1000 && diff <= 3000) {
actionCounter = 3;
} else if (diff > 3000 && diff <= 5000) {
actionCounter = 2;
} else if (diff > 5000) {
actionCounter = 1;
}
if (actionCounter) {
diff = cmp32(ledToggleAt, end);
if (diff < 0) {
ledEnabled = !ledEnabled;
const uint8_t updateDuration = 60;
ledToggleAt = end + updateDuration;
if (ledEnabled) {
LED1_ON;
} else {
LED1_OFF;
flashesDone++;
}
if (flashesDone == actionCounter) {
ledToggleAt += (1000 - ((flashesDone * updateDuration) * 2));
flashesDone = 0;
}
}
buttonWasPressed = true;
}
}
if (!buttonWasPressed) {
return;
}
LED1_OFF;
switch (actionCounter) {
case 4:
vtxCycleBandOrChannel(0, +1);
break;
case 3:
vtxCycleBandOrChannel(+1, 0);
break;
case 2:
vtxCyclePower(+1);
break;
case 1:
saveConfigAndNotify();
break;
}
#endif
}
#endif