diff --git a/src/main/drivers/vtx_common.h b/src/main/drivers/vtx_common.h index 83e608dc49b..c6068b818ca 100644 --- a/src/main/drivers/vtx_common.h +++ b/src/main/drivers/vtx_common.h @@ -67,6 +67,7 @@ typedef enum { FREQUENCYGROUP_5G8 = 0, FREQUENCYGROUP_2G4 = 1, FREQUENCYGROUP_1G3 = 2, + FREQUENCYGROUP_3G3 = 3, } vtxFrequencyGroups_e; struct vtxVTable_s; diff --git a/src/main/fc/fc_msp.c b/src/main/fc/fc_msp.c index cf5308067e9..4a8345f41be 100644 --- a/src/main/fc/fc_msp.c +++ b/src/main/fc/fc_msp.c @@ -1806,6 +1806,27 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF } break; +#ifdef USE_VTX_CONTROL + case MSP2_INAV_VTX_TABLE_CUSTOM: + { + // Send 3.3GHz SX33 frequency table to configurator + sbufWriteU8(dst, 5); // band count + sbufWriteU8(dst, 8); // channel count + sbufWriteU8(dst, 3); // power level count + for (uint8_t band = 0; band < 5; band++) { + sbufWriteU8(dst, vtx3G3BandLetter[band + 1]); + for (uint8_t ch = 0; ch < 8; ch++) { + sbufWriteU16(dst, vtx3G3frequencyTable[band][ch]); + } + } + // Power levels: 25, 2000, 5000 mW + sbufWriteU16(dst, 25); + sbufWriteU16(dst, 2000); + sbufWriteU16(dst, 5000); + } + break; +#endif + default: return false; } @@ -2920,6 +2941,28 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src) return MSP_RESULT_ERROR; } break; + + case MSP2_INAV_SET_VTX_TABLE_CUSTOM: + { + // Receive custom VTX table from configurator + // Format: band(u8), channel(u8), power(u8) + if (dataSize >= 2) { + uint8_t newBand = sbufReadU8(src); + uint8_t newChannel = sbufReadU8(src); + if (newBand > 0 && newBand <= 5 && newChannel > 0 && newChannel <= 8) { + vtxSettingsConfigMutable()->band = newBand; + vtxSettingsConfigMutable()->channel = newChannel; + vtxSettingsConfigMutable()->frequencyGroup = FREQUENCYGROUP_3G3; + if (sbufBytesRemaining(src) >= 1) { + uint8_t newPower = sbufReadU8(src); + vtxSettingsConfigMutable()->power = newPower; + } + } + } else { + return MSP_RESULT_ERROR; + } + } + break; #endif #ifdef USE_FLASHFS diff --git a/src/main/io/vtx_string.c b/src/main/io/vtx_string.c index 97857429775..62a9713c28c 100644 --- a/src/main/io/vtx_string.c +++ b/src/main/io/vtx_string.c @@ -33,6 +33,10 @@ #define VTX_STRING_1G3_CHAN_COUNT 8 #define VTX_STRING_1G3_POWER_COUNT 3 +#define VTX_STRING_3G3_BAND_COUNT 5 +#define VTX_STRING_3G3_CHAN_COUNT 8 +#define VTX_STRING_3G3_POWER_COUNT 3 + const uint16_t vtx58frequencyTable[VTX_STRING_5G8_BAND_COUNT][VTX_STRING_5G8_CHAN_COUNT] = { { 5865, 5845, 5825, 5805, 5785, 5765, 5745, 5725 }, // A @@ -131,3 +135,41 @@ uint16_t vtx1G3_Bandchan2Freq(uint8_t band, uint8_t channel) } return 0; } + +// 3.3 GHz SX33 IRC Tramp frequency table +const uint16_t vtx3G3frequencyTable[VTX_STRING_3G3_BAND_COUNT][VTX_STRING_3G3_CHAN_COUNT] = +{ + { 3200, 3220, 3240, 3260, 3280, 3300, 3320, 3340 }, // A + { 3360, 3380, 3400, 3420, 3440, 3460, 3480, 3500 }, // B + { 3520, 3540, 3560, 3580, 3600, 3620, 3640, 3680 }, // C + { 3210, 3250, 3290, 3330, 3370, 3410, 3450, 3490 }, // D + { 3230, 3290, 3350, 3410, 3470, 3530, 3590, 3700 }, // E +}; + +const char * const vtx3G3BandNames[VTX_STRING_3G3_BAND_COUNT + 1] = { + "-", + "A", + "B", + "C", + "D", + "E", +}; + +const char vtx3G3BandLetter[VTX_STRING_3G3_BAND_COUNT + 1] = {'-', 'A', 'B', 'C', 'D', 'E'}; + +const char * const vtx3G3ChannelNames[VTX_STRING_3G3_CHAN_COUNT + 1] = { + "-", "1", "2", "3", "4", "5", "6", "7", "8", +}; + +const char * const vtx3G3DefaultPowerNames[VTX_STRING_3G3_POWER_COUNT + 1] = { + "---", "25 ", "2W ", "5W " +}; + +uint16_t vtx3G3_Bandchan2Freq(uint8_t band, uint8_t channel) +{ + if (band > 0 && band <= VTX_STRING_3G3_BAND_COUNT && + channel > 0 && channel <= VTX_STRING_3G3_CHAN_COUNT) { + return vtx3G3frequencyTable[band - 1][channel - 1]; + } + return 0; +} diff --git a/src/main/io/vtx_string.h b/src/main/io/vtx_string.h index e23990ec77c..f47d755e74d 100644 --- a/src/main/io/vtx_string.h +++ b/src/main/io/vtx_string.h @@ -14,6 +14,13 @@ extern const char * const vtx1G3ChannelNames[]; extern const char * const vtx1G3DefaultPowerNames[]; extern const char vtx51G3BandLetter[]; +extern const uint16_t vtx3G3frequencyTable[5][8]; +extern const char * const vtx3G3BandNames[]; +extern const char * const vtx3G3ChannelNames[]; +extern const char * const vtx3G3DefaultPowerNames[]; +extern const char vtx3G3BandLetter[]; + bool vtx58_Freq2Bandchan(uint16_t freq, uint8_t *pBand, uint8_t *pChannel); uint16_t vtx58_Bandchan2Freq(uint8_t band, uint8_t channel); uint16_t vtx1G3_Bandchan2Freq(uint8_t band, uint8_t channel); +uint16_t vtx3G3_Bandchan2Freq(uint8_t band, uint8_t channel); diff --git a/src/main/io/vtx_tramp.c b/src/main/io/vtx_tramp.c index 540c9c9f222..24e40a681cc 100644 --- a/src/main/io/vtx_tramp.c +++ b/src/main/io/vtx_tramp.c @@ -412,6 +412,8 @@ static void impl_SetBandAndChannel(vtxDevice_t * vtxDevice, uint8_t band, uint8_ if (vtxSettingsConfig()->frequencyGroup == FREQUENCYGROUP_1G3) { newFreqMhz = vtx1G3_Bandchan2Freq(band, channel); + } else if (vtxSettingsConfig()->frequencyGroup == FREQUENCYGROUP_3G3) { + newFreqMhz = vtx3G3_Bandchan2Freq(band, channel); } if (newFreqMhz < vtxState.capabilities.freqMin || newFreqMhz > vtxState.capabilities.freqMax) { @@ -523,7 +525,12 @@ static bool impl_GetOsdInfo(const vtxDevice_t *vtxDevice, vtxDeviceOsdInfo_t * pOsdInfo->bandName = vtx1G3BandNames[vtxState.request.band]; pOsdInfo->channelName = vtx1G3ChannelNames[vtxState.request.channel]; break; - default: // Currently all except 1.3GHz + case FREQUENCYGROUP_3G3: + pOsdInfo->bandLetter = vtx3G3BandNames[vtxState.request.band][0]; + pOsdInfo->bandName = vtx3G3BandNames[vtxState.request.band]; + pOsdInfo->channelName = vtx3G3ChannelNames[vtxState.request.channel]; + break; + default: pOsdInfo->bandLetter = vtx58BandNames[vtxState.request.band][0]; pOsdInfo->bandName = vtx58BandNames[vtxState.request.band]; pOsdInfo->channelName = vtx58ChannelNames[vtxState.request.channel]; @@ -578,9 +585,23 @@ const char * const trampPowerNames_1G3_800[VTX_TRAMP_1G3_MAX_POWER_COUNT + 1] = const uint16_t trampPowerTable_1G3_2000[VTX_TRAMP_1G3_MAX_POWER_COUNT] = { 25, 200, 2000 }; const char * const trampPowerNames_1G3_2000[VTX_TRAMP_1G3_MAX_POWER_COUNT + 1] = { "---", "25 ", "200", "2000" }; +const uint16_t trampPowerTable_3G3[VTX_TRAMP_3G3_MAX_POWER_COUNT] = { 25, 2000, 5000 }; +const char * const trampPowerNames_3G3[VTX_TRAMP_3G3_MAX_POWER_COUNT + 1] = { "---", "25 ", "2W ", "5W " }; + static void vtxProtoUpdatePowerMetadata(uint16_t maxPower) { switch (vtxSettingsConfig()->frequencyGroup) { + case FREQUENCYGROUP_3G3: + vtxState.metadata.powerTablePtr = trampPowerTable_3G3; + vtxState.metadata.powerTableCount = VTX_TRAMP_3G3_MAX_POWER_COUNT; + + impl_vtxDevice.capability.powerNames = (char **)trampPowerNames_3G3; + impl_vtxDevice.capability.powerCount = VTX_TRAMP_3G3_MAX_POWER_COUNT; + impl_vtxDevice.capability.bandCount = VTX_TRAMP_3G3_BAND_COUNT; + impl_vtxDevice.capability.channelCount = VTX_TRAMP_3G3_CHANNEL_COUNT; + impl_vtxDevice.capability.bandNames = (char **)vtx3G3BandNames; + impl_vtxDevice.capability.channelNames = (char **)vtx3G3ChannelNames; + break; case FREQUENCYGROUP_1G3: if (maxPower >= 2000) { vtxState.metadata.powerTablePtr = trampPowerTable_1G3_2000; diff --git a/src/main/io/vtx_tramp.h b/src/main/io/vtx_tramp.h index 1f44201853c..8a7ab9873c8 100644 --- a/src/main/io/vtx_tramp.h +++ b/src/main/io/vtx_tramp.h @@ -39,4 +39,14 @@ #define VTX_TRAMP_1G3_MIN_FREQUENCY_MHZ 1000 #define VTX_TRAMP_1G3_MAX_FREQUENCY_MHZ 1399 +// 3.3 GHz (SX33) +#define VTX_TRAMP_3G3_BAND_COUNT 5 +#define VTX_TRAMP_3G3_CHANNEL_COUNT 8 + +#define VTX_TRAMP_3G3_MAX_POWER_COUNT 3 +#define VTX_TRAMP_3G3_DEFAULT_POWER 1 + +#define VTX_TRAMP_3G3_MIN_FREQUENCY_MHZ 3200 +#define VTX_TRAMP_3G3_MAX_FREQUENCY_MHZ 3700 + bool vtxTrampInit(void); diff --git a/src/main/msp/msp_protocol_v2_inav.h b/src/main/msp/msp_protocol_v2_inav.h index 0b893916895..9bc3e81db1d 100755 --- a/src/main/msp/msp_protocol_v2_inav.h +++ b/src/main/msp/msp_protocol_v2_inav.h @@ -125,4 +125,7 @@ #define MSP2_INAV_SET_GEOZONE_VERTEX 0x2213 #define MSP2_INAV_SET_GVAR 0x2214 +#define MSP2_INAV_VTX_TABLE_CUSTOM 0x2F00 +#define MSP2_INAV_SET_VTX_TABLE_CUSTOM 0x2F01 + #define MSP2_INAV_FULL_LOCAL_POSE 0x2220 diff --git a/src/main/programming/logic_condition.c b/src/main/programming/logic_condition.c index edba68b8e94..242009ba012 100644 --- a/src/main/programming/logic_condition.c +++ b/src/main/programming/logic_condition.c @@ -343,6 +343,30 @@ static int logicConditionCompute( return false; break; } + case LOGIC_CONDITION_SET_VTX_CUSTOM_SLOT: + { + // operandA encodes band*8+channel (1-based), operandB is power index + uint8_t slot = constrain(operandA, 1, 40); + uint8_t newBand = ((slot - 1) / 8) + 1; + uint8_t newChannel = ((slot - 1) % 8) + 1; + + vtxSettingsConfigMutable()->frequencyGroup = FREQUENCYGROUP_3G3; + + if (newBand != vtxSettingsConfig()->band || newChannel != vtxSettingsConfig()->channel) { + vtxSettingsConfigMutable()->band = newBand; + vtxSettingsConfigMutable()->channel = newChannel; + if (vtxCommonDevice()) { + vtxCommonSetBandAndChannel(vtxCommonDevice(), newBand, newChannel); + } + } + + if (operandB > 0 && operandB <= 3) { + vtxSettingsConfigMutable()->power = operandB; + } + + return slot; + break; + } #endif case LOGIC_CONDITION_SET_GIMBAL_SENSITIVITY: diff --git a/src/main/programming/logic_condition.h b/src/main/programming/logic_condition.h index 74ea96c98ee..356bd66abbd 100644 --- a/src/main/programming/logic_condition.h +++ b/src/main/programming/logic_condition.h @@ -86,6 +86,7 @@ typedef enum { LOGIC_CONDITION_RESET_MAG_CALIBRATION = 54, LOGIC_CONDITION_SET_GIMBAL_SENSITIVITY = 55, LOGIC_CONDITION_OVERRIDE_MIN_GROUND_SPEED = 56, + LOGIC_CONDITION_SET_VTX_CUSTOM_SLOT = 57, LOGIC_CONDITION_LAST } logicOperation_e;