mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-13 19:40:31 +03:00
CLI parser for vtxtable
This commit is contained in:
parent
fa11287e8d
commit
96fc6dc934
9 changed files with 633 additions and 0 deletions
|
@ -87,6 +87,7 @@ extern uint8_t __config_end;
|
|||
#include "drivers/transponder_ir.h"
|
||||
#include "drivers/usb_msc.h"
|
||||
#include "drivers/vtx_common.h"
|
||||
#include "drivers/vtx_table.h"
|
||||
|
||||
#include "fc/board_info.h"
|
||||
#include "fc/config.h"
|
||||
|
@ -140,6 +141,7 @@ extern uint8_t __config_end;
|
|||
#include "pg/sdio.h"
|
||||
#include "pg/timerio.h"
|
||||
#include "pg/usb.h"
|
||||
#include "pg/vtx_table.h"
|
||||
|
||||
#include "rx/rx.h"
|
||||
#include "rx/spektrum.h"
|
||||
|
@ -2336,6 +2338,348 @@ static void cliVtx(char *cmdline)
|
|||
|
||||
#endif // VTX_CONTROL
|
||||
|
||||
#ifdef USE_VTX_TABLE
|
||||
|
||||
static char *formatVtxTableBandFrequency(const uint16_t *frequency, int channels)
|
||||
{
|
||||
static char freqbuf[5 * VTX_TABLE_MAX_CHANNELS + 1];
|
||||
char freqtmp[5 + 1];
|
||||
freqbuf[0] = 0;
|
||||
for (int channel = 0; channel < channels; channel++) {
|
||||
tfp_sprintf(freqtmp, " %4d", frequency[channel]);
|
||||
strcat(freqbuf, freqtmp);
|
||||
}
|
||||
return freqbuf;
|
||||
}
|
||||
|
||||
static void printVtxTableBand(uint8_t dumpMask, int band, const vtxTableConfig_t *currentConfig, const vtxTableConfig_t *defaultConfig)
|
||||
{
|
||||
char *fmt = "vtxtable band %d %s %c%s";
|
||||
bool equalsDefault = false;
|
||||
|
||||
if (defaultConfig) {
|
||||
equalsDefault = true;
|
||||
if (strcasecmp(currentConfig->bandNames[band], defaultConfig->bandNames[band])) {
|
||||
equalsDefault = false;
|
||||
}
|
||||
if (currentConfig->bandLetters[band] != defaultConfig->bandLetters[band]) {
|
||||
equalsDefault = false;
|
||||
}
|
||||
for (int channel = 0; channel < VTX_TABLE_MAX_CHANNELS; channel++) {
|
||||
if (currentConfig->frequency[band][channel] != defaultConfig->frequency[band][channel]) {
|
||||
equalsDefault = false;
|
||||
}
|
||||
}
|
||||
char *freqbuf = formatVtxTableBandFrequency(defaultConfig->frequency[band], defaultConfig->channels);
|
||||
cliDefaultPrintLinef(dumpMask, equalsDefault, fmt, band + 1, defaultConfig->bandNames[band], defaultConfig->bandLetters[band], freqbuf);
|
||||
}
|
||||
|
||||
char *freqbuf = formatVtxTableBandFrequency(currentConfig->frequency[band], currentConfig->channels);
|
||||
cliDumpPrintLinef(dumpMask, equalsDefault, fmt, band + 1, currentConfig->bandNames[band], currentConfig->bandLetters[band], freqbuf);
|
||||
}
|
||||
|
||||
static char *formatVtxTablePowerValues(const uint16_t *levels, int count)
|
||||
{
|
||||
// (max 4 digit + 1 space) per level
|
||||
static char pwrbuf[5 * VTX_TABLE_MAX_POWER_LEVELS + 1];
|
||||
char pwrtmp[5 + 1];
|
||||
pwrbuf[0] = 0;
|
||||
for (int pwrindex = 0; pwrindex < count; pwrindex++) {
|
||||
tfp_sprintf(pwrtmp, " %d", levels[pwrindex]);
|
||||
strcat(pwrbuf, pwrtmp);
|
||||
}
|
||||
return pwrbuf;
|
||||
}
|
||||
|
||||
static void printVtxTablePowerValues(uint8_t dumpMask, const vtxTableConfig_t *currentConfig, const vtxTableConfig_t *defaultConfig)
|
||||
{
|
||||
char *fmt = "vtxtable powervalues %s";
|
||||
bool equalsDefault = false;
|
||||
if (defaultConfig) {
|
||||
equalsDefault = true;
|
||||
for (int pwrindex = 0; pwrindex < VTX_TABLE_MAX_POWER_LEVELS; pwrindex++) {
|
||||
if (defaultConfig->powerValues[pwrindex] != currentConfig->powerValues[pwrindex]) {
|
||||
equalsDefault = false;
|
||||
}
|
||||
}
|
||||
char *pwrbuf = formatVtxTablePowerValues(defaultConfig->powerValues, VTX_TABLE_MAX_POWER_LEVELS);
|
||||
cliDefaultPrintLinef(dumpMask, equalsDefault, fmt, pwrbuf);
|
||||
}
|
||||
|
||||
char *pwrbuf = formatVtxTablePowerValues(currentConfig->powerValues, currentConfig->powerLevels);
|
||||
cliDumpPrintLinef(dumpMask, equalsDefault, fmt, pwrbuf);
|
||||
}
|
||||
|
||||
static char *formatVtxTablePowerLabels(const char labels[VTX_TABLE_MAX_POWER_LEVELS][VTX_TABLE_POWER_LABEL_LENGTH + 1], int count)
|
||||
{
|
||||
static char pwrbuf[(VTX_TABLE_POWER_LABEL_LENGTH + 1) * VTX_TABLE_MAX_POWER_LEVELS + 1];
|
||||
char pwrtmp[(VTX_TABLE_POWER_LABEL_LENGTH + 1) + 1];
|
||||
pwrbuf[0] = 0;
|
||||
for (int pwrindex = 0; pwrindex < count; pwrindex++) {
|
||||
strcat(pwrbuf, " ");
|
||||
strcpy(pwrtmp, labels[pwrindex]);
|
||||
// trim trailing space
|
||||
char *sp;
|
||||
while ((sp = strchr(pwrtmp, ' '))) {
|
||||
*sp = 0;
|
||||
}
|
||||
strcat(pwrbuf, pwrtmp);
|
||||
}
|
||||
return pwrbuf;
|
||||
}
|
||||
|
||||
static void printVtxTablePowerLabels(uint8_t dumpMask, const vtxTableConfig_t *currentConfig, const vtxTableConfig_t *defaultConfig)
|
||||
{
|
||||
char *fmt = "vtxtable powerlabels%s";
|
||||
bool equalsDefault = false;
|
||||
if (defaultConfig) {
|
||||
equalsDefault = true;
|
||||
for (int pwrindex = 0; pwrindex < VTX_TABLE_MAX_POWER_LEVELS; pwrindex++) {
|
||||
if (strcasecmp(defaultConfig->powerLabels[pwrindex], currentConfig->powerLabels[pwrindex])) {
|
||||
equalsDefault = false;
|
||||
}
|
||||
}
|
||||
char *pwrbuf = formatVtxTablePowerLabels(defaultConfig->powerLabels, VTX_TABLE_MAX_POWER_LEVELS);
|
||||
cliDefaultPrintLinef(dumpMask, equalsDefault, fmt, pwrbuf);
|
||||
}
|
||||
|
||||
char *pwrbuf = formatVtxTablePowerLabels(currentConfig->powerLabels, currentConfig->powerLevels);
|
||||
cliDumpPrintLinef(dumpMask, equalsDefault, fmt, pwrbuf);
|
||||
}
|
||||
|
||||
static void printVtxTable(uint8_t dumpMask, const vtxTableConfig_t *currentConfig, const vtxTableConfig_t *defaultConfig)
|
||||
{
|
||||
bool equalsDefault;
|
||||
char *fmt;
|
||||
|
||||
// bands
|
||||
equalsDefault = false;
|
||||
fmt = "vtxtable bands %d";
|
||||
if (defaultConfig) {
|
||||
equalsDefault = (defaultConfig->bands == currentConfig->bands);
|
||||
cliDefaultPrintLinef(dumpMask, equalsDefault, fmt, defaultConfig->bands);
|
||||
}
|
||||
cliDumpPrintLinef(dumpMask, equalsDefault, fmt, currentConfig->bands);
|
||||
|
||||
// channels
|
||||
equalsDefault = false;
|
||||
fmt = "vtxtable channels %d";
|
||||
if (defaultConfig) {
|
||||
equalsDefault = (defaultConfig->channels == currentConfig->channels);
|
||||
cliDefaultPrintLinef(dumpMask, equalsDefault, fmt, defaultConfig->channels);
|
||||
}
|
||||
cliDumpPrintLinef(dumpMask, equalsDefault, fmt, currentConfig->channels);
|
||||
|
||||
// band
|
||||
|
||||
for (int band = 0; band < currentConfig->bands; band++) {
|
||||
printVtxTableBand(dumpMask, band, currentConfig, defaultConfig);
|
||||
}
|
||||
|
||||
// powerlevels
|
||||
|
||||
equalsDefault = false;
|
||||
fmt = "vtxtable powerlevels %d";
|
||||
if (defaultConfig) {
|
||||
equalsDefault = (defaultConfig->powerLevels == currentConfig->powerLevels);
|
||||
cliDefaultPrintLinef(dumpMask, equalsDefault, fmt, defaultConfig->powerLevels);
|
||||
}
|
||||
cliDumpPrintLinef(dumpMask, equalsDefault, fmt, currentConfig->powerLevels);
|
||||
|
||||
// powervalues
|
||||
|
||||
// powerlabels
|
||||
printVtxTablePowerValues(dumpMask, currentConfig, defaultConfig);
|
||||
printVtxTablePowerLabels(dumpMask, currentConfig, defaultConfig);
|
||||
}
|
||||
|
||||
static void cliVtxTable(char *cmdline)
|
||||
{
|
||||
char *tok;
|
||||
char *saveptr;
|
||||
|
||||
// Band number or nothing
|
||||
tok = strtok_r(cmdline, " ", &saveptr);
|
||||
|
||||
if (!tok) {
|
||||
printVtxTable(DUMP_MASTER | HIDE_UNUSED, vtxTableConfigMutable(), NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(tok, "bands") == 0) {
|
||||
tok = strtok_r(NULL, " ", &saveptr);
|
||||
int bands = atoi(tok);
|
||||
if (bands < 0 || bands > VTX_TABLE_MAX_BANDS) {
|
||||
cliPrintErrorLinef("INVALID BAND COUNT (SHOULD BE BETWEEN 0 AND %d)", VTX_TABLE_MAX_BANDS);
|
||||
return;
|
||||
}
|
||||
if (bands < vtxTableConfigMutable()->bands) {
|
||||
for (int i = bands; i < vtxTableConfigMutable()->bands; i++) {
|
||||
vtxTableConfigClearBand(vtxTableConfigMutable(), i);
|
||||
}
|
||||
}
|
||||
vtxTableConfigMutable()->bands = bands;
|
||||
|
||||
} else if (strcasecmp(tok, "channels") == 0) {
|
||||
tok = strtok_r(NULL, " ", &saveptr);
|
||||
|
||||
int channels = atoi(tok);
|
||||
if (channels < 0 || channels > VTX_TABLE_MAX_BANDS) {
|
||||
cliPrintErrorLinef("INVALID CHANNEL COUNT (SHOULD BE BETWEEN 0 AND %d)", VTX_TABLE_MAX_CHANNELS);
|
||||
return;
|
||||
}
|
||||
if (channels < vtxTableConfigMutable()->channels) {
|
||||
for (int i = 0; i < VTX_TABLE_MAX_BANDS; i++) {
|
||||
vtxTableConfigClearChannels(vtxTableConfigMutable(), i, channels);
|
||||
}
|
||||
}
|
||||
vtxTableConfigMutable()->channels = channels;
|
||||
|
||||
} else if (strcasecmp(tok, "powerlevels") == 0) {
|
||||
// Number of power levels
|
||||
tok = strtok_r(NULL, " ", &saveptr);
|
||||
if (tok) {
|
||||
int levels = atoi(tok);
|
||||
if (levels < 0 || levels > VTX_TABLE_MAX_POWER_LEVELS) {
|
||||
cliPrintErrorLinef("INVALID POWER LEVEL COUNT (SHOULD BE BETWEEN 0 AND %d)", VTX_TABLE_MAX_POWER_LEVELS);
|
||||
} else {
|
||||
if (levels < vtxTableConfigMutable()->powerLevels) {
|
||||
vtxTableConfigClearPowerValues(vtxTableConfigMutable(), levels);
|
||||
vtxTableConfigClearPowerLabels(vtxTableConfigMutable(), levels);
|
||||
}
|
||||
vtxTableConfigMutable()->powerLevels = levels;
|
||||
}
|
||||
} else {
|
||||
// XXX Show current level count?
|
||||
}
|
||||
return;
|
||||
|
||||
} else if (strcasecmp(tok, "powervalues") == 0) {
|
||||
// Power values
|
||||
uint16_t power[VTX_TABLE_MAX_POWER_LEVELS];
|
||||
int count;
|
||||
int levels = vtxTableConfigMutable()->powerLevels;
|
||||
|
||||
memset(power, 0, sizeof(power));
|
||||
|
||||
for (count = 0; count < levels && (tok = strtok_r(NULL, " ", &saveptr)); count++) {
|
||||
int value = atoi(tok);
|
||||
power[count] = value;
|
||||
}
|
||||
|
||||
// Check remaining tokens
|
||||
|
||||
if (count < levels) {
|
||||
cliPrintErrorLinef("NOT ENOUGH VALUES (EXPECTED %d)", levels);
|
||||
return;
|
||||
} else if ((tok = strtok_r(NULL, " ", &saveptr))) {
|
||||
cliPrintErrorLinef("TOO MANY VALUES (EXPECTED %d)", levels);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < VTX_TABLE_MAX_POWER_LEVELS; i++) {
|
||||
vtxTableConfigMutable()->powerValues[i] = power[i];
|
||||
}
|
||||
|
||||
} else if (strcasecmp(tok, "powerlabels") == 0) {
|
||||
// Power labels
|
||||
char label[VTX_TABLE_MAX_POWER_LEVELS][VTX_TABLE_POWER_LABEL_LENGTH + 1];
|
||||
int levels = vtxTableConfigMutable()->powerLevels;
|
||||
int count;
|
||||
for (count = 0; count < levels && (tok = strtok_r(NULL, " ", &saveptr)); count++) {
|
||||
strncpy(label[count], tok, VTX_TABLE_POWER_LABEL_LENGTH);
|
||||
for (unsigned i = 0; i < strlen(label[count]); i++) {
|
||||
label[count][i] = toupper(label[count][i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Check remaining tokens
|
||||
|
||||
if (count < levels) {
|
||||
cliPrintErrorLinef("NOT ENOUGH LABELS (EXPECTED %d)", levels);
|
||||
return;
|
||||
} else if ((tok = strtok_r(NULL, " ", &saveptr))) {
|
||||
cliPrintErrorLinef("TOO MANY LABELS (EXPECTED %d)", levels);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
vtxTableStrncpyWithPad(vtxTableConfigMutable()->powerLabels[i], label[i], VTX_TABLE_POWER_LABEL_LENGTH);
|
||||
}
|
||||
} else if (strcasecmp(tok, "band") == 0) {
|
||||
|
||||
int bands = vtxTableConfigMutable()->bands;
|
||||
|
||||
tok = strtok_r(NULL, " ", &saveptr);
|
||||
if (!tok) {
|
||||
return;
|
||||
}
|
||||
|
||||
int band = atoi(tok);
|
||||
--band;
|
||||
|
||||
if (band < 0 || band >= bands) {
|
||||
cliPrintErrorLinef("INVALID BAND NUMBER %s (EXPECTED 1-%d)", tok, bands);
|
||||
return;
|
||||
}
|
||||
|
||||
// Band name
|
||||
tok = strtok_r(NULL, " ", &saveptr);
|
||||
|
||||
if (!tok) {
|
||||
return;
|
||||
}
|
||||
|
||||
char bandname[VTX_TABLE_BAND_NAME_LENGTH + 1];
|
||||
memset(bandname, 0, VTX_TABLE_BAND_NAME_LENGTH + 1);
|
||||
strncpy(bandname, tok, VTX_TABLE_BAND_NAME_LENGTH);
|
||||
for (unsigned i = 0; i < strlen(bandname); i++) {
|
||||
bandname[i] = toupper(bandname[i]);
|
||||
}
|
||||
|
||||
// Band letter
|
||||
tok = strtok_r(NULL, " ", &saveptr);
|
||||
|
||||
if (!tok) {
|
||||
return;
|
||||
}
|
||||
|
||||
char bandletter = toupper(tok[0]);
|
||||
|
||||
uint16_t bandfreq[VTX_TABLE_MAX_CHANNELS];
|
||||
int channel = 0;
|
||||
int channels = vtxTableConfigMutable()->channels;
|
||||
|
||||
for (channel = 0; channel < channels && (tok = strtok_r(NULL, " ", &saveptr)); channel++) {
|
||||
int freq = atoi(tok);
|
||||
if (freq < 0) {
|
||||
cliPrintErrorLinef("INVALID FREQUENCY %s", tok);
|
||||
return;
|
||||
}
|
||||
bandfreq[channel] = freq;
|
||||
}
|
||||
|
||||
if (channel < channels) {
|
||||
cliPrintErrorLinef("NOT ENOUGH FREQUENCIES (EXPECTED %d)", channels);
|
||||
return;
|
||||
} else if ((tok = strtok_r(NULL, " ", &saveptr))) {
|
||||
cliPrintErrorLinef("TOO MANY FREQUENCIES (EXPECTED %d)", channels);
|
||||
return;
|
||||
}
|
||||
|
||||
vtxTableStrncpyWithPad(vtxTableConfigMutable()->bandNames[band], bandname, VTX_TABLE_BAND_NAME_LENGTH);
|
||||
vtxTableConfigMutable()->bandLetters[band] = bandletter;
|
||||
|
||||
for (int i = 0; i < channel; i++) {
|
||||
vtxTableConfigMutable()->frequency[band][i] = bandfreq[i];
|
||||
}
|
||||
} else {
|
||||
// Bad subcommand
|
||||
cliPrintErrorLinef("INVALID SUBCOMMAND %s", tok);
|
||||
}
|
||||
}
|
||||
#endif // USE_VTX_TABLE
|
||||
|
||||
#ifdef USE_OSD
|
||||
static void printDisplayName(uint8_t dumpMask, const pilotConfig_t *pilotConfig)
|
||||
{
|
||||
|
@ -4762,6 +5106,11 @@ static void printConfig(char *cmdline, bool doDiff)
|
|||
printVtx(dumpMask, &vtxConfig_Copy, vtxConfig());
|
||||
#endif
|
||||
|
||||
#ifdef USE_VTX_TABLE
|
||||
cliPrintHashLine("vtxtable");
|
||||
printVtxTable(dumpMask, &vtxTableConfig_Copy, vtxTableConfig());
|
||||
#endif
|
||||
|
||||
cliPrintHashLine("rxfail");
|
||||
printRxFailsafe(dumpMask, rxFailsafeChannelConfigs_CopyArray, rxFailsafeChannelConfigs(0));
|
||||
|
||||
|
@ -5013,6 +5362,9 @@ const clicmd_t cmdTable[] = {
|
|||
#ifdef USE_VTX_CONTROL
|
||||
CLI_COMMAND_DEF("vtx", "vtx channels on switch", NULL, cliVtx),
|
||||
#endif
|
||||
#ifdef USE_VTX_TABLE
|
||||
CLI_COMMAND_DEF("vtxtable", "vtx frequency able", "<band> <bandname> <bandletter> <freq> ... <freq>\r\n", cliVtxTable),
|
||||
#endif
|
||||
};
|
||||
|
||||
static void cliHelp(char *cmdline)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue