Skip to content

Commit

Permalink
smartaudio: autmatically convert dbm values to labels
Browse files Browse the repository at this point in the history
  • Loading branch information
bkleiner committed Aug 10, 2024
1 parent 727f630 commit cdd9181
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 22 deletions.
19 changes: 10 additions & 9 deletions src/driver/vtx/sa.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,11 @@ extern uint32_t vtx_last_request;
extern uint8_t vtx_payload[32];
extern uint8_t vtx_payload_offset;

const uint8_t default_dac_power_levels[VTX_POWER_LEVEL_MAX] = {
const uint8_t default_dac_power_levels[4] = {
7,
16,
25,
40,
40,
40,
40,
40,
};

static void serial_smart_audio_reconfigure() {
Expand Down Expand Up @@ -125,13 +121,18 @@ static uint8_t serial_smart_audio_parse_packet(uint8_t cmd, uint8_t *payload, ui
if (cmd == SA_CMD_GET_SETTINGS_V21) {
smart_audio_settings.power = payload[5];

const uint8_t count = max(payload[6], VTX_POWER_LEVEL_MAX);
smart_audio_settings.level_count = min(payload[6], VTX_POWER_LEVEL_MAX);

for (uint8_t i = 0; i < count; i++) {
smart_audio_settings.dac_power_levels[i] = payload[7 + i];
// SmartAudio seems to report buf[8] + 1 power levels, but one of them is zero.
// zero is indeed a valid power level to set the vtx to, but it activates pit mode.
// crucially, after sending 0 dbm, the vtx does NOT report its power level to be 0 dbm.
// instead, it reports whatever value was set previously and it reports to be in pit mode.
for (uint8_t i = 0; i < smart_audio_settings.level_count; i++) {
smart_audio_settings.dac_power_levels[i] = payload[7 + i + 1]; //+ 1 to skip the first power level, as mentioned above
}
} else {
for (uint8_t i = 0; i < VTX_POWER_LEVEL_MAX; i++) {
smart_audio_settings.level_count = 4;
for (uint8_t i = 0; i < smart_audio_settings.level_count; i++) {
smart_audio_settings.dac_power_levels[i] = default_dac_power_levels[i];
}
}
Expand Down
1 change: 1 addition & 0 deletions src/driver/vtx/sa.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ typedef struct {
uint8_t power;
uint8_t mode;
uint16_t frequency;
uint8_t level_count;
uint16_t dac_power_levels[8];
} smart_audio_settings_t;

Expand Down
2 changes: 1 addition & 1 deletion src/io/msp.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ static void msp_process_serial_cmd(msp_t *msp, msp_magic_t magic, uint16_t cmd,

case MSP_VTXTABLE_POWERLEVEL: {
const uint8_t level = payload[0];
if (level <= 0 || level > VTX_POWER_LEVEL_MAX) {
if (level <= 0 || level > vtx_actual.power_table.levels) {
msp_send_error(msp, magic, cmd);
break;
}
Expand Down
2 changes: 1 addition & 1 deletion src/io/vtx.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ void vtx_set(vtx_settings_t *vtx) {
if (vtx_settings.pit_mode != VTX_PIT_MODE_NO_SUPPORT)
vtx_settings.pit_mode = vtx->pit_mode;

vtx_settings.power_level = vtx->power_level < VTX_POWER_LEVEL_MAX ? vtx->power_level : (VTX_POWER_LEVEL_MAX - 1);
vtx_settings.power_level = vtx->power_level < vtx_settings.power_table.levels ? vtx->power_level : (vtx_settings.power_table.levels - 1);

vtx_settings.band = vtx->band < VTX_BAND_MAX ? vtx->band : 0;
vtx_settings.channel = vtx->channel < VTX_CHANNEL_MAX ? vtx->channel : 0;
Expand Down
44 changes: 35 additions & 9 deletions src/io/vtx_smartaudio.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "vtx.h"

#include <math.h>
#include <string.h>

#include "driver/serial.h"
Expand All @@ -17,17 +18,36 @@ extern smart_audio_settings_t smart_audio_settings;

static bool smart_audio_needs_update = false;

static const char smart_audio_power_level_labels[VTX_POWER_LEVEL_MAX][VTX_POWER_LABEL_LEN] = {
static const char smart_audio_power_level_labels[4][VTX_POWER_LABEL_LEN] = {
"25 ",
"100 ",
"200 ",
"300 ",
"400 ",
" ",
" ",
" ",
"500 ",
"800 ",
};

static uint32_t smart_audio_dbi_to_mw(uint16_t dbi) {
uint16_t mw = (uint16_t)powf(10.0f, dbi / 10.0f);
if (dbi > 14) {
// For powers greater than 25mW round up to a multiple of 50 to match expectations
mw = 50 * ((mw + 25) / 50);
}
return mw;
}

static char *i2a(char *ptr, uint32_t val) {
const uint32_t div = val / 10;
if (div > 0)
ptr = i2a(ptr, div);
*ptr = '0' + (val % 10);
return ptr + 1;
}

static void smart_audio_write_mw(char *buf, uint32_t val) {
char *ptr = i2a(buf, val);
while (ptr != (buf + VTX_POWER_LABEL_LEN))
*ptr++ = ' ';
}

vtx_detect_status_t vtx_smart_audio_update(vtx_settings_t *actual) {
if (smart_audio_settings.version == 0 && vtx_connect_tries > SMART_AUDIO_DETECT_TRIES) {
return VTX_DETECT_ERROR;
Expand Down Expand Up @@ -55,9 +75,15 @@ vtx_detect_status_t vtx_smart_audio_update(vtx_settings_t *actual) {
actual->channel = channel_index % VTX_CHANNEL_MAX;
}

actual->power_table.levels = VTX_POWER_LEVEL_MAX;
actual->power_table.levels = smart_audio_settings.level_count;
memcpy(actual->power_table.values, smart_audio_settings.dac_power_levels, sizeof(smart_audio_settings.dac_power_levels));
memcpy(actual->power_table.labels, smart_audio_power_level_labels, sizeof(smart_audio_power_level_labels));
if (smart_audio_settings.version == 3) {
for (uint32_t i = 0; i < smart_audio_settings.level_count; i++) {
smart_audio_write_mw(actual->power_table.labels[i], smart_audio_dbi_to_mw(smart_audio_settings.dac_power_levels[i]));
}
} else {
memcpy(actual->power_table.labels, smart_audio_power_level_labels, sizeof(smart_audio_power_level_labels));
}

if (smart_audio_settings.version == 2) {
actual->power_level = min(smart_audio_settings.power, VTX_POWER_LEVEL_MAX - 1);
Expand Down
3 changes: 3 additions & 0 deletions src/io/vtx_tramp.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ static const uint16_t tramp_power_level_values[VTX_POWER_LEVEL_MAX] = {
200,
300,
400,
0,
0,
0,
};

static const char tramp_power_level_labels[VTX_POWER_LEVEL_MAX][VTX_POWER_LABEL_LEN] = {
Expand Down
4 changes: 2 additions & 2 deletions src/osd/render.c
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ void osd_display() {
static char power_level_labels_terminated[VTX_POWER_LEVEL_MAX][VTX_POWER_LABEL_LEN + 1];
if (!vtx_buffer_populated) {
vtx_settings_copy = vtx_settings;
for (uint8_t i = 0; i < VTX_POWER_LEVEL_MAX; i++) {
for (uint8_t i = 0; i < vtx_settings.power_table.levels; i++) {
memcpy(power_level_labels_terminated[i], vtx_settings.power_table.labels[i], VTX_POWER_LABEL_LEN);
power_level_labels_terminated[i][VTX_POWER_LABEL_LEN] = 0;
power_level_labels[i] = power_level_labels_terminated[i];
Expand All @@ -947,7 +947,7 @@ void osd_display() {

const char *channel_labels[] = {"1", "2", "3", "4", "5", "6", "7", "8"};
osd_menu_select_enum_adjust(4, 5, "CHANNEL", 20, &vtx_settings_copy.channel, channel_labels, VTX_CHANNEL_1, VTX_CHANNEL_8);
osd_menu_select_enum_adjust(4, 6, "POWER LEVEL", 20, &vtx_settings_copy.power_level, power_level_labels, VTX_POWER_LEVEL_1, VTX_POWER_LEVEL_MAX - 1);
osd_menu_select_enum_adjust(4, 6, "POWER LEVEL", 20, &vtx_settings_copy.power_level, power_level_labels, VTX_POWER_LEVEL_1, vtx_settings.power_table.levels - 1);

const char *pit_mode_labels[] = {"OFF", "ON ", "N/A"};
osd_menu_select(4, 7, "PITMODE");
Expand Down

0 comments on commit cdd9181

Please sign in to comment.