mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-26 01:35:35 +03:00
Add support for modifying settings directly in CMS (#2262)
* Add macros for injecting CMS key presses Useful for testing and debugging * Add support for CMS elements represented by just a bool function Function is called for both getting and setting the value. Will allow simplying the code for several CMS items. * Use OME_BoolFunc on cms_menu_ledstrip.c Allows removing a couple of static variables and replacing two functions with just one. * Add support for manipulating settings directly in CMS Allows changing settings without intermediary values/functions, reducing memory usage. Due to the required code to support this feature we're using ~250 bytes of flash, but we're saving around ~300 bytes of RAM. However, eventually we should be able to migrate all CMS code to use the settings API and end up saving flash space. Also, the memory overhead per memory setting is now way smaller. * Don't use SETTING_VBAT_* when the target doesn't use the ADC Fixes build on COLIBRI * Add support for CMS setting data types This allows us to format angular rates without introducing a function pointer for formatting on every CMS setting. * Remove CMS_INJECTED_KEYS used for debugging * Fix off-by-one error in setting_get_max() for MODE_LOOKUP values Maximum value is one less than the number of entries in the table
This commit is contained in:
parent
206940461a
commit
f1fb918803
9 changed files with 278 additions and 232 deletions
|
@ -42,7 +42,9 @@
|
|||
#include "cms/cms_types.h"
|
||||
|
||||
#include "common/maths.h"
|
||||
#include "common/printf.h"
|
||||
#include "common/typeconversion.h"
|
||||
#include "common/utils.h"
|
||||
|
||||
#include "drivers/system.h"
|
||||
#include "drivers/time.h"
|
||||
|
@ -56,6 +58,7 @@
|
|||
#include "fc/config.h"
|
||||
#include "fc/rc_controls.h"
|
||||
#include "fc/runtime_config.h"
|
||||
#include "fc/settings.h"
|
||||
|
||||
#include "flight/mixer.h"
|
||||
|
||||
|
@ -305,6 +308,14 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, OSD_Entry *p, uint8_t row)
|
|||
}
|
||||
break;
|
||||
|
||||
case OME_BoolFunc:
|
||||
if (IS_PRINTVALUE(p) && p->data) {
|
||||
bool (*func)(bool *arg) = p->data;
|
||||
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, func(NULL) ? "YES" : "NO ");
|
||||
CLR_PRINTVALUE(p);
|
||||
}
|
||||
break;
|
||||
|
||||
case OME_TAB:
|
||||
if (IS_PRINTVALUE(p)) {
|
||||
OSD_TAB_t *ptr = p->data;
|
||||
|
@ -381,6 +392,76 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, OSD_Entry *p, uint8_t row)
|
|||
}
|
||||
break;
|
||||
|
||||
case OME_Setting:
|
||||
if (IS_PRINTVALUE(p) && p->data) {
|
||||
buff[0] = '\0';
|
||||
OSD_SETTING_t *ptr = p->data;
|
||||
const setting_t *var = &settingsTable[ptr->val];
|
||||
int32_t value;
|
||||
const void *valuePointer = setting_get_value_pointer(var);
|
||||
switch (SETTING_TYPE(var)) {
|
||||
case VAR_UINT8:
|
||||
value = *(uint8_t *)valuePointer;
|
||||
break;
|
||||
case VAR_INT8:
|
||||
value = *(int8_t *)valuePointer;
|
||||
break;
|
||||
case VAR_UINT16:
|
||||
value = *(uint16_t *)valuePointer;
|
||||
break;
|
||||
case VAR_INT16:
|
||||
value = *(int16_t *)valuePointer;
|
||||
break;
|
||||
case VAR_UINT32:
|
||||
value = *(uint32_t *)valuePointer;
|
||||
break;
|
||||
case VAR_FLOAT:
|
||||
// XXX: This bypasses the data types. However, we
|
||||
// don't have any VAR_FLOAT settings which require
|
||||
// a data type yet.
|
||||
ftoa(*(float *)valuePointer, buff);
|
||||
break;
|
||||
}
|
||||
if (buff[0] == '\0') {
|
||||
const char *suffix = NULL;
|
||||
switch (CMS_DATA_TYPE(p)) {
|
||||
case CMS_DATA_TYPE_ANGULAR_RATE:
|
||||
// Setting is in degrees/10 per second
|
||||
value *= 10;
|
||||
suffix = " DPS";
|
||||
break;
|
||||
}
|
||||
switch (SETTING_MODE(var)) {
|
||||
case MODE_DIRECT:
|
||||
if (SETTING_TYPE(var) == VAR_UINT32) {
|
||||
tfp_sprintf(buff, "%u", value);
|
||||
} else {
|
||||
tfp_sprintf(buff, "%d", value);
|
||||
}
|
||||
break;
|
||||
case MODE_LOOKUP:
|
||||
{
|
||||
const char *str = NULL;
|
||||
if (var->config.lookup.tableIndex < LOOKUP_TABLE_COUNT) {
|
||||
const lookupTableEntry_t *tableEntry = &settingLookupTables[var->config.lookup.tableIndex];
|
||||
if (value < tableEntry->valueCount) {
|
||||
str = tableEntry->values[value];
|
||||
}
|
||||
}
|
||||
strncpy(buff, str ? str : "INVALID", sizeof(buff) - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (suffix) {
|
||||
strcat(buff, suffix);
|
||||
}
|
||||
}
|
||||
cmsPadToSize(buff, 8);
|
||||
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, buff);
|
||||
CLR_PRINTVALUE(p);
|
||||
}
|
||||
break;
|
||||
|
||||
case OME_Label:
|
||||
if (IS_PRINTVALUE(p) && p->data) {
|
||||
// A label with optional string, immediately following text
|
||||
|
@ -754,6 +835,15 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, uint8_t key)
|
|||
}
|
||||
break;
|
||||
|
||||
case OME_BoolFunc:
|
||||
if (p->data) {
|
||||
bool (*func)(bool *arg) = p->data;
|
||||
bool val = key == KEY_RIGHT;
|
||||
func(&val);
|
||||
SET_PRINTVALUE(p);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef OSD
|
||||
case OME_VISIBLE:
|
||||
if (p->data) {
|
||||
|
@ -859,6 +949,69 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, uint8_t key)
|
|||
}
|
||||
break;
|
||||
|
||||
case OME_Setting:
|
||||
if (p->data) {
|
||||
OSD_SETTING_t *ptr = p->data;
|
||||
const setting_t *var = &settingsTable[ptr->val];
|
||||
setting_min_t min = setting_get_min(var);
|
||||
setting_max_t max = setting_get_max(var);
|
||||
float step = ptr->step ?: 1;
|
||||
if (key != KEY_RIGHT) {
|
||||
step = -step;
|
||||
}
|
||||
const void *valuePointer = setting_get_value_pointer(var);
|
||||
switch (SETTING_TYPE(var)) {
|
||||
case VAR_UINT8:
|
||||
{
|
||||
uint8_t val = *(uint8_t *)valuePointer;
|
||||
val = MIN(MAX(val + step, (uint8_t)min), (uint8_t)max);
|
||||
*(uint8_t *)valuePointer = val;
|
||||
break;
|
||||
}
|
||||
case VAR_INT8:
|
||||
{
|
||||
int8_t val = *(int8_t *)valuePointer;
|
||||
val = MIN(MAX(val + step, (int8_t)min), (int8_t)max);
|
||||
*(int8_t *)valuePointer = val;
|
||||
break;
|
||||
}
|
||||
case VAR_UINT16:
|
||||
{
|
||||
uint16_t val = *(uint16_t *)valuePointer;
|
||||
val = MIN(MAX(val + step, (uint16_t)min), (uint16_t)max);
|
||||
*(uint16_t *)valuePointer = val;
|
||||
break;
|
||||
}
|
||||
case VAR_INT16:
|
||||
{
|
||||
int16_t val = *(int16_t *)valuePointer;
|
||||
val = MIN(MAX(val + step, (int16_t)min), (int16_t)max);
|
||||
*(int16_t *)valuePointer = val;
|
||||
break;
|
||||
}
|
||||
case VAR_UINT32:
|
||||
{
|
||||
uint32_t val = *(uint32_t *)valuePointer;
|
||||
val = MIN(MAX(val + step, (uint32_t)min), (uint32_t)max);
|
||||
*(uint32_t *)valuePointer = val;
|
||||
break;
|
||||
}
|
||||
case VAR_FLOAT:
|
||||
{
|
||||
float val = *(float *)valuePointer;
|
||||
val = MIN(MAX(val + step, (float)min), (float)max);
|
||||
*(float *)valuePointer = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
SET_PRINTVALUE(p);
|
||||
if (p->func) {
|
||||
p->func(pDisplay, p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OME_String:
|
||||
break;
|
||||
|
||||
|
@ -890,6 +1043,13 @@ void cmsUpdate(uint32_t currentTimeUs)
|
|||
static int holdCount = 1;
|
||||
static int repeatCount = 1;
|
||||
static int repeatBase = 0;
|
||||
// e.g #define CMS_INJECTED_KEYS KEY_DOWN,KEY_RIGHT,KEY_DOWN,KEY_RIGHT,KEY_DOWN
|
||||
#define CMS_INJECTED_KEYS_INTERVAL 800
|
||||
#if defined CMS_INJECTED_KEYS
|
||||
int cmsInjectedKeys[] = {KEY_NONE, CMS_INJECTED_KEYS};
|
||||
static timeMs_t lastInjectedKeyMs = 0;
|
||||
static unsigned lastInjectedKeyIndex = 0;
|
||||
#endif
|
||||
|
||||
static uint32_t lastCalledMs = 0;
|
||||
static uint32_t lastCmsHeartBeatMs = 0;
|
||||
|
@ -898,10 +1058,15 @@ void cmsUpdate(uint32_t currentTimeUs)
|
|||
|
||||
if (!cmsInMenu) {
|
||||
// Detect menu invocation
|
||||
#if defined(CMS_INJECTED_KEYS)
|
||||
cmsMenuOpen();
|
||||
rcDelayMs = 0;
|
||||
#else
|
||||
if (IS_MID(THROTTLE) && IS_LO(YAW) && IS_HI(PITCH) && !ARMING_FLAG(ARMED)) {
|
||||
cmsMenuOpen();
|
||||
rcDelayMs = BUTTON_PAUSE; // Tends to overshoot if BUTTON_TIME
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
//
|
||||
// Scan 'key' first
|
||||
|
@ -929,6 +1094,14 @@ void cmsUpdate(uint32_t currentTimeUs)
|
|||
key = KEY_ESC;
|
||||
}
|
||||
|
||||
#if defined(CMS_INJECTED_KEYS)
|
||||
if (lastInjectedKeyMs < currentTimeMs - CMS_INJECTED_KEYS_INTERVAL) {
|
||||
if (lastInjectedKeyIndex < ARRAYLEN(cmsInjectedKeys)) {
|
||||
key = cmsInjectedKeys[lastInjectedKeyIndex++];
|
||||
lastInjectedKeyMs = currentTimeMs;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (key == KEY_NONE) {
|
||||
// No 'key' pressed, reset repeat control
|
||||
holdCount = 1;
|
||||
|
|
|
@ -63,43 +63,25 @@ static long cmsx_EraseFlash(displayPort_t *pDisplay, const void *ptr)
|
|||
}
|
||||
#endif // USE_FLASHFS
|
||||
|
||||
static bool featureRead = false;
|
||||
static uint8_t cmsx_FeatureBlackbox;
|
||||
static uint8_t blackboxConfig_rate_denom;
|
||||
|
||||
static long cmsx_menuBlackboxOnEnter(void)
|
||||
static bool cmsx_Blackbox_Enabled(bool *enabled)
|
||||
{
|
||||
if (!featureRead) {
|
||||
cmsx_FeatureBlackbox = feature(FEATURE_BLACKBOX) ? 1 : 0;
|
||||
blackboxConfig_rate_denom = blackboxConfig()->rate_denom;
|
||||
featureRead = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_Blackbox_FeatureWriteback(void)
|
||||
{
|
||||
// If we did read the data into CMS cache - write it back
|
||||
if (featureRead) {
|
||||
if (cmsx_FeatureBlackbox)
|
||||
if (enabled) {
|
||||
if (*enabled) {
|
||||
featureSet(FEATURE_BLACKBOX);
|
||||
else
|
||||
} else {
|
||||
featureClear(FEATURE_BLACKBOX);
|
||||
|
||||
blackboxConfigMutable()->rate_denom = blackboxConfig_rate_denom;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return featureConfigured(FEATURE_BLACKBOX);
|
||||
}
|
||||
|
||||
static OSD_Entry cmsx_menuBlackboxEntries[] =
|
||||
{
|
||||
{ "-- BLACKBOX --", OME_Label, NULL, NULL, 0},
|
||||
{ "ENABLED", OME_Bool, NULL, &cmsx_FeatureBlackbox, 0 },
|
||||
{ "RATE DENOM", OME_UINT8, NULL, &(OSD_UINT8_t){ &blackboxConfig_rate_denom,1,32,1 }, 0 },
|
||||
|
||||
{ "-- BLACKBOX --", OME_Label, NULL, NULL, 0},
|
||||
{ "ENABLED", OME_BoolFunc, NULL, cmsx_Blackbox_Enabled, 0 },
|
||||
OSD_SETTING_ENTRY("RATE DENOM", SETTING_BLACKBOX_RATE_DENOM),
|
||||
#ifdef USE_FLASHFS
|
||||
{ "ERASE FLASH", OME_Funcall, cmsx_EraseFlash, NULL, 0 },
|
||||
{ "ERASE FLASH",OME_Funcall, cmsx_EraseFlash, NULL, 0 },
|
||||
#endif // USE_FLASHFS
|
||||
|
||||
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||
|
@ -109,9 +91,9 @@ static OSD_Entry cmsx_menuBlackboxEntries[] =
|
|||
CMS_Menu cmsx_menuBlackbox = {
|
||||
.GUARD_text = "MENUBB",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = cmsx_menuBlackboxOnEnter,
|
||||
.onEnter = NULL,
|
||||
.onExit = NULL,
|
||||
.onGlobalExit = cmsx_Blackbox_FeatureWriteback,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = cmsx_menuBlackboxEntries
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -256,42 +256,6 @@ static CMS_Menu cmsx_menuPidGpsnav = {
|
|||
//
|
||||
// Rate & Expo
|
||||
//
|
||||
static controlRateConfig_t rateProfile;
|
||||
static uint16_t cmsx_rateRoll;
|
||||
static uint16_t cmsx_ratePitch;
|
||||
static uint16_t cmsx_rateYaw;
|
||||
|
||||
static long cmsx_RateProfileRead(void)
|
||||
{
|
||||
memcpy(&rateProfile, controlRateProfiles(profileIndex), sizeof(controlRateConfig_t));
|
||||
|
||||
cmsx_rateRoll = DEKADEGREES_TO_DEGREES(rateProfile.rates[FD_ROLL]);
|
||||
cmsx_ratePitch = DEKADEGREES_TO_DEGREES(rateProfile.rates[FD_PITCH]);
|
||||
cmsx_rateYaw = DEKADEGREES_TO_DEGREES(rateProfile.rates[FD_YAW]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_RateProfileWriteback(const OSD_Entry *self)
|
||||
{
|
||||
UNUSED(self);
|
||||
|
||||
rateProfile.rates[FD_ROLL] = DEGREES_TO_DEKADEGREES(cmsx_rateRoll);
|
||||
rateProfile.rates[FD_PITCH] = DEGREES_TO_DEKADEGREES(cmsx_ratePitch);
|
||||
rateProfile.rates[FD_YAW] = DEGREES_TO_DEKADEGREES(cmsx_rateYaw);
|
||||
|
||||
memcpy((controlRateConfig_t *)controlRateProfiles(profileIndex), &rateProfile, sizeof(controlRateConfig_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_RateProfileOnEnter(void)
|
||||
{
|
||||
cmsx_RateProfileRead();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static OSD_Entry cmsx_menuRateProfileEntries[] =
|
||||
{
|
||||
{ "-- RATE --", OME_Label, NULL, profileIndexString, 0 },
|
||||
|
@ -301,18 +265,18 @@ static OSD_Entry cmsx_menuRateProfileEntries[] =
|
|||
{ "RC YAW RATE", OME_FLOAT, NULL, &(OSD_FLOAT_t){ &rateProfile.rcYawRate8, 0, 255, 1, 10 }, 0 },
|
||||
#endif
|
||||
|
||||
{ "ROLL RATE", OME_UINT16, NULL, &(OSD_UINT16_t){ &cmsx_rateRoll, (CONTROL_RATE_CONFIG_ROLL_PITCH_RATE_MIN * DEGREES_PER_DEKADEGREE), (CONTROL_RATE_CONFIG_ROLL_PITCH_RATE_MAX * DEGREES_PER_DEKADEGREE), DEGREES_PER_DEKADEGREE }, 0 },
|
||||
{ "PITCH RATE", OME_UINT16, NULL, &(OSD_UINT16_t){ &cmsx_ratePitch, (CONTROL_RATE_CONFIG_ROLL_PITCH_RATE_MIN * DEGREES_PER_DEKADEGREE), (CONTROL_RATE_CONFIG_ROLL_PITCH_RATE_MAX * DEGREES_PER_DEKADEGREE), DEGREES_PER_DEKADEGREE }, 0 },
|
||||
{ "YAW RATE", OME_UINT16, NULL, &(OSD_UINT16_t){ &cmsx_rateYaw, (CONTROL_RATE_CONFIG_YAW_RATE_MIN * DEGREES_PER_DEKADEGREE), (CONTROL_RATE_CONFIG_YAW_RATE_MAX * DEGREES_PER_DEKADEGREE), DEGREES_PER_DEKADEGREE }, 0 },
|
||||
OSD_SETTING_ENTRY_TYPE("ROLL RATE", SETTING_ROLL_RATE, CMS_DATA_TYPE_ANGULAR_RATE),
|
||||
OSD_SETTING_ENTRY_TYPE("PITCH RATE", SETTING_PITCH_RATE, CMS_DATA_TYPE_ANGULAR_RATE),
|
||||
OSD_SETTING_ENTRY_TYPE("YAW RATE", SETTING_YAW_RATE, CMS_DATA_TYPE_ANGULAR_RATE),
|
||||
|
||||
{ "RC EXPO", OME_UINT8, NULL, &(OSD_UINT8_t){ &rateProfile.rcExpo8, 0, 100, 1 }, 0 },
|
||||
{ "RC YAW EXP", OME_UINT8, NULL, &(OSD_UINT8_t){ &rateProfile.rcYawExpo8, 0, 100, 1 }, 0 },
|
||||
OSD_SETTING_ENTRY("RC EXPO", SETTING_RC_EXPO),
|
||||
OSD_SETTING_ENTRY("RC YAW EXP", SETTING_RC_YAW_EXPO),
|
||||
|
||||
{ "THR MID", OME_UINT8, NULL, &(OSD_UINT8_t){ &rateProfile.thrMid8, 0, 100, 1 }, 0 },
|
||||
{ "THR EXPO", OME_UINT8, NULL, &(OSD_UINT8_t){ &rateProfile.thrExpo8, 0, 100, 1 }, 0 },
|
||||
OSD_SETTING_ENTRY("THR MID", SETTING_THR_MID),
|
||||
OSD_SETTING_ENTRY("THR EXPO", SETTING_THR_EXPO),
|
||||
|
||||
{ "THRPID ATT", OME_UINT8, NULL, &(OSD_UINT8_t){ &rateProfile.dynThrPID, 0, 100, 1 }, 0 },
|
||||
{ "TPA BRKPT", OME_UINT16, NULL, &(OSD_UINT16_t){ &rateProfile.tpa_breakpoint, 1000, 2000, 10}, 0 },
|
||||
OSD_SETTING_ENTRY("THRPID ATT", SETTING_TPA_RATE),
|
||||
OSD_SETTING_ENTRY_STEP("TPA BRKPT", SETTING_TPA_BREAKPOINT, 10),
|
||||
|
||||
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||
{ NULL, OME_END, NULL, NULL, 0 }
|
||||
|
@ -321,8 +285,8 @@ static OSD_Entry cmsx_menuRateProfileEntries[] =
|
|||
static CMS_Menu cmsx_menuRateProfile = {
|
||||
.GUARD_text = "MENURATE",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = cmsx_RateProfileOnEnter,
|
||||
.onExit = cmsx_RateProfileWriteback,
|
||||
.onEnter = NULL,
|
||||
.onExit = NULL,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = cmsx_menuRateProfileEntries
|
||||
};
|
||||
|
@ -388,41 +352,14 @@ static CMS_Menu cmsx_menuProfileOther = {
|
|||
//
|
||||
// Per profile filters
|
||||
//
|
||||
static uint8_t cmsx_dterm_lpf_hz;
|
||||
static uint8_t cmsx_gyroSoftLpf;
|
||||
static uint16_t cmsx_yaw_p_limit;
|
||||
static uint8_t cmsx_yaw_lpf_hz;
|
||||
|
||||
static long cmsx_FilterPerProfileRead(void)
|
||||
{
|
||||
cmsx_dterm_lpf_hz = pidProfile()->dterm_lpf_hz;
|
||||
cmsx_gyroSoftLpf = gyroConfig()->gyro_soft_lpf_hz;
|
||||
cmsx_yaw_p_limit = pidProfile()->yaw_p_limit;
|
||||
cmsx_yaw_lpf_hz = pidProfile()->yaw_lpf_hz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_FilterPerProfileWriteback(const OSD_Entry *self)
|
||||
{
|
||||
UNUSED(self);
|
||||
|
||||
pidProfileMutable()->dterm_lpf_hz = cmsx_dterm_lpf_hz;
|
||||
gyroConfigMutable()->gyro_soft_lpf_hz = cmsx_gyroSoftLpf;
|
||||
pidProfileMutable()->yaw_p_limit = cmsx_yaw_p_limit;
|
||||
pidProfileMutable()->yaw_lpf_hz = cmsx_yaw_lpf_hz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static OSD_Entry cmsx_menuFilterPerProfileEntries[] =
|
||||
{
|
||||
{ "-- FILTER PP --", OME_Label, NULL, profileIndexString, 0 },
|
||||
|
||||
{ "DTERM LPF", OME_UINT8, NULL, &(OSD_UINT8_t){ &cmsx_dterm_lpf_hz, 0, 200, 1 }, 0 },
|
||||
{ "GYRO SLPF", OME_UINT8, NULL, &(OSD_UINT8_t){ &cmsx_gyroSoftLpf, 0, 200, 1 }, 0 },
|
||||
{ "YAW P LIM", OME_UINT16, NULL, &(OSD_UINT16_t){ &cmsx_yaw_p_limit, 100, 500, 1 }, 0 },
|
||||
{ "YAW LPF", OME_UINT8, NULL, &(OSD_UINT8_t){ &cmsx_yaw_lpf_hz, 0, 200, 1 }, 0 },
|
||||
OSD_SETTING_ENTRY("DTERM LPF", SETTING_DTERM_LPF_HZ),
|
||||
OSD_SETTING_ENTRY("GYRO SLPF", SETTING_GYRO_LPF_HZ),
|
||||
OSD_SETTING_ENTRY("YAW P LIM", SETTING_YAW_P_LIMIT),
|
||||
OSD_SETTING_ENTRY("YAW LPF", SETTING_YAW_LPF_HZ),
|
||||
|
||||
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||
{ NULL, OME_END, NULL, NULL, 0 }
|
||||
|
@ -431,51 +368,19 @@ static OSD_Entry cmsx_menuFilterPerProfileEntries[] =
|
|||
static CMS_Menu cmsx_menuFilterPerProfile = {
|
||||
.GUARD_text = "XFLTPP",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = cmsx_FilterPerProfileRead,
|
||||
.onExit = cmsx_FilterPerProfileWriteback,
|
||||
.onEnter = NULL,
|
||||
.onExit = NULL,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = cmsx_menuFilterPerProfileEntries,
|
||||
};
|
||||
|
||||
static uint8_t cmsx_gyroSync; // Global
|
||||
static uint8_t cmsx_gyroSyncDenom; // Global
|
||||
static uint8_t cmsx_gyroLpf; // Global
|
||||
|
||||
static long cmsx_menuGyro_onEnter(void)
|
||||
{
|
||||
cmsx_gyroSync = gyroConfig()->gyroSync;
|
||||
cmsx_gyroSyncDenom = gyroConfig()->gyroSyncDenominator;
|
||||
cmsx_gyroLpf = gyroConfig()->gyro_lpf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_menuGyro_onExit(const OSD_Entry *self)
|
||||
{
|
||||
UNUSED(self);
|
||||
|
||||
gyroConfigMutable()->gyroSync = cmsx_gyroSync;
|
||||
gyroConfigMutable()->gyroSyncDenominator = cmsx_gyroSyncDenom;
|
||||
gyroConfigMutable()->gyro_lpf = cmsx_gyroLpf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *cmsx_gyroSyncNames[] = {
|
||||
"OFF", "ON "
|
||||
};
|
||||
|
||||
static const char *cmsx_gyroLpfNames[] = {
|
||||
"10 ", "20 ", "42 ", "98 ", "188", "256"
|
||||
};
|
||||
|
||||
static OSD_Entry cmsx_menuGyroEntries[] =
|
||||
{
|
||||
{ "-- GYRO GLB --", OME_Label, NULL, profileIndexString, 0},
|
||||
|
||||
{ "GYRO SYNC", OME_TAB, NULL, &(OSD_TAB_t){ &cmsx_gyroSync, 1, cmsx_gyroSyncNames}, 0 },
|
||||
{ "GYRO DENOM", OME_UINT8, NULL, &(OSD_UINT8_t){ &cmsx_gyroSyncDenom, 1, 32, 1 }, 0 },
|
||||
{ "GYRO LPF", OME_TAB, NULL, &(OSD_TAB_t){ &cmsx_gyroLpf, 5, cmsx_gyroLpfNames}, 0 },
|
||||
OSD_SETTING_ENTRY("GYRO SYNC", SETTING_GYRO_SYNC),
|
||||
OSD_SETTING_ENTRY("GYRO DENOM", SETTING_GYRO_SYNC_DENOM),
|
||||
OSD_SETTING_ENTRY("GYRO LPF", SETTING_GYRO_HARDWARE_LPF),
|
||||
|
||||
{"BACK", OME_Back, NULL, NULL, 0},
|
||||
{NULL, OME_END, NULL, NULL, 0}
|
||||
|
@ -484,8 +389,8 @@ static OSD_Entry cmsx_menuGyroEntries[] =
|
|||
static CMS_Menu cmsx_menuGyro = {
|
||||
.GUARD_text = "XGYROGLB",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = cmsx_menuGyro_onEnter,
|
||||
.onExit = cmsx_menuGyro_onExit,
|
||||
.onEnter = NULL,
|
||||
.onExit = NULL,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = cmsx_menuGyroEntries,
|
||||
};
|
||||
|
|
|
@ -44,35 +44,22 @@
|
|||
|
||||
#ifdef LED_STRIP
|
||||
|
||||
static bool featureRead = false;
|
||||
static uint8_t cmsx_FeatureLedstrip;
|
||||
|
||||
static long cmsx_Ledstrip_FeatureRead(void)
|
||||
static bool cmsx_FeatureLedStrip_Enabled(bool *enabled)
|
||||
{
|
||||
if (!featureRead) {
|
||||
cmsx_FeatureLedstrip = feature(FEATURE_LED_STRIP) ? 1 : 0;
|
||||
featureRead = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_Ledstrip_FeatureWriteback(void)
|
||||
{
|
||||
if (featureRead) {
|
||||
if (cmsx_FeatureLedstrip)
|
||||
if (enabled) {
|
||||
if (*enabled) {
|
||||
featureSet(FEATURE_LED_STRIP);
|
||||
else
|
||||
} else {
|
||||
featureClear(FEATURE_LED_STRIP);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return featureConfigured(FEATURE_LED_STRIP);
|
||||
}
|
||||
|
||||
static OSD_Entry cmsx_menuLedstripEntries[] =
|
||||
{
|
||||
{ "-- LED STRIP --", OME_Label, NULL, NULL, 0 },
|
||||
{ "ENABLED", OME_Bool, NULL, &cmsx_FeatureLedstrip, 0 },
|
||||
{ "ENABLED", OME_BoolFunc, NULL, cmsx_FeatureLedStrip_Enabled, 0 },
|
||||
|
||||
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||
{ NULL, OME_END, NULL, NULL, 0 }
|
||||
|
@ -81,9 +68,9 @@ static OSD_Entry cmsx_menuLedstripEntries[] =
|
|||
CMS_Menu cmsx_menuLedstrip = {
|
||||
.GUARD_text = "MENULED",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = cmsx_Ledstrip_FeatureRead,
|
||||
.onEnter = NULL,
|
||||
.onExit = NULL,
|
||||
.onGlobalExit = cmsx_Ledstrip_FeatureWriteback,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = cmsx_menuLedstripEntries
|
||||
};
|
||||
#endif // LED_STRIP
|
||||
|
|
|
@ -79,35 +79,16 @@ CMS_Menu cmsx_menuRcPreview = {
|
|||
.entries = cmsx_menuRcEntries
|
||||
};
|
||||
|
||||
static uint16_t motorConfig_minthrottle;
|
||||
static uint8_t batteryConfig_vbatscale;
|
||||
static uint8_t batteryConfig_vbatmaxcellvoltage;
|
||||
|
||||
static long cmsx_menuMiscOnEnter(void)
|
||||
{
|
||||
motorConfig_minthrottle = motorConfig()->minthrottle;
|
||||
batteryConfig_vbatscale = batteryConfig()->vbatscale;
|
||||
batteryConfig_vbatmaxcellvoltage = batteryConfig()->vbatmaxcellvoltage;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_menuMiscOnExit(const OSD_Entry *self)
|
||||
{
|
||||
UNUSED(self);
|
||||
|
||||
motorConfigMutable()->minthrottle = motorConfig_minthrottle;
|
||||
batteryConfigMutable()->vbatscale = batteryConfig_vbatscale;
|
||||
batteryConfigMutable()->vbatmaxcellvoltage = batteryConfig_vbatmaxcellvoltage;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static OSD_Entry menuMiscEntries[]=
|
||||
{
|
||||
{ "-- MISC --", OME_Label, NULL, NULL, 0 },
|
||||
|
||||
{ "MIN THR", OME_UINT16, NULL, &(OSD_UINT16_t){ &motorConfig_minthrottle, 1000, 2000, 1 }, 0 },
|
||||
{ "VBAT SCALE", OME_UINT8, NULL, &(OSD_UINT8_t) { &batteryConfig_vbatscale, 1, 250, 1 }, 0 },
|
||||
{ "VBAT CLMAX", OME_UINT8, NULL, &(OSD_UINT8_t) { &batteryConfig_vbatmaxcellvoltage, 10, 50, 1 }, 0 },
|
||||
OSD_SETTING_ENTRY("MIN THR", SETTING_MIN_THROTTLE),
|
||||
#ifdef USE_ADC
|
||||
OSD_SETTING_ENTRY("VBAT SCALE", SETTING_VBAT_SCALE),
|
||||
OSD_SETTING_ENTRY("VBAT CLMAX", SETTING_VBAT_MAX_CELL_VOLTAGE),
|
||||
#endif
|
||||
|
||||
{ "RC PREV", OME_Submenu, cmsMenuChange, &cmsx_menuRcPreview, 0},
|
||||
|
||||
{ "BACK", OME_Back, NULL, NULL, 0},
|
||||
|
@ -117,8 +98,8 @@ static OSD_Entry menuMiscEntries[]=
|
|||
CMS_Menu cmsx_menuMisc = {
|
||||
.GUARD_text = "XMISC",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = cmsx_menuMiscOnEnter,
|
||||
.onExit = cmsx_menuMiscOnExit,
|
||||
.onEnter = NULL,
|
||||
.onExit = NULL,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = menuMiscEntries
|
||||
};
|
||||
|
|
|
@ -29,41 +29,19 @@
|
|||
#include "cms/cms_types.h"
|
||||
#include "cms/cms_menu_osd.h"
|
||||
|
||||
#include "fc/settings.h"
|
||||
|
||||
#include "io/osd.h"
|
||||
|
||||
|
||||
static uint8_t osdConfig_rssi_alarm;
|
||||
static uint16_t osdConfig_cap_alarm;
|
||||
static uint16_t osdConfig_time_alarm;
|
||||
static uint16_t osdConfig_alt_alarm;
|
||||
|
||||
static long cmsx_menuAlarmsOnEnter(void)
|
||||
{
|
||||
osdConfig_rssi_alarm = osdConfig()->rssi_alarm;
|
||||
osdConfig_cap_alarm = osdConfig()->cap_alarm;
|
||||
osdConfig_time_alarm = osdConfig()->time_alarm;
|
||||
osdConfig_alt_alarm = osdConfig()->alt_alarm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_menuAlarmsOnExit(const OSD_Entry *self)
|
||||
{
|
||||
UNUSED(self);
|
||||
|
||||
osdConfigMutable()->rssi_alarm = osdConfig_rssi_alarm;
|
||||
osdConfigMutable()->cap_alarm = osdConfig_cap_alarm;
|
||||
osdConfigMutable()->time_alarm = osdConfig_time_alarm;
|
||||
osdConfigMutable()->alt_alarm = osdConfig_alt_alarm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
OSD_Entry cmsx_menuAlarmsEntries[] =
|
||||
{
|
||||
{"--- ALARMS ---", OME_Label, NULL, NULL, 0},
|
||||
{"RSSI", OME_UINT8, NULL, &(OSD_UINT8_t){&osdConfig_rssi_alarm, 5, 90, 5}, 0},
|
||||
{"MAIN BAT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_cap_alarm, 50, 30000, 50}, 0},
|
||||
{"FLY TIME", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_time_alarm, 1, 200, 1}, 0},
|
||||
{"MAX ALT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_alt_alarm, 1, 200, 1}, 0},
|
||||
|
||||
OSD_SETTING_ENTRY_STEP("RSSI", SETTING_OSD_RSSI_ALARM, 5),
|
||||
OSD_SETTING_ENTRY_STEP("MAIN BAT", SETTING_OSD_CAP_ALARM, 50),
|
||||
OSD_SETTING_ENTRY("FLY TIME", SETTING_OSD_TIME_ALARM),
|
||||
OSD_SETTING_ENTRY("MAX ALT", SETTING_OSD_ALT_ALARM),
|
||||
|
||||
{"BACK", OME_Back, NULL, NULL, 0},
|
||||
{NULL, OME_END, NULL, NULL, 0}
|
||||
};
|
||||
|
@ -71,8 +49,8 @@ OSD_Entry cmsx_menuAlarmsEntries[] =
|
|||
CMS_Menu cmsx_menuAlarms = {
|
||||
.GUARD_text = "MENUALARMS",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = cmsx_menuAlarmsOnEnter,
|
||||
.onExit = cmsx_menuAlarmsOnExit,
|
||||
.onEnter = NULL,
|
||||
.onExit = NULL,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = cmsx_menuAlarmsEntries,
|
||||
};
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "fc/settings.h"
|
||||
|
||||
//type of elements
|
||||
|
||||
typedef enum
|
||||
|
@ -32,12 +36,14 @@ typedef enum
|
|||
OME_Submenu,
|
||||
OME_Funcall,
|
||||
OME_Bool,
|
||||
OME_BoolFunc, // bool func(bool*):
|
||||
OME_INT8,
|
||||
OME_UINT8,
|
||||
OME_UINT16,
|
||||
OME_INT16,
|
||||
OME_String,
|
||||
OME_FLOAT, //only up to 255 value and cant be 2.55 or 25.5, just for PID's
|
||||
OME_Setting,
|
||||
//wlasciwosci elementow
|
||||
#ifdef OSD
|
||||
OME_VISIBLE,
|
||||
|
@ -63,10 +69,20 @@ typedef struct
|
|||
} OSD_Entry;
|
||||
|
||||
// Bits in flags
|
||||
#define PRINT_VALUE 0x01 // Value has been changed, need to redraw
|
||||
#define PRINT_LABEL 0x02 // Text label should be printed
|
||||
#define DYNAMIC 0x04 // Value should be updated dynamically
|
||||
#define OPTSTRING 0x08 // (Temporary) Flag for OME_Submenu, indicating func should be called to get a string to display.
|
||||
#define PRINT_VALUE (1 << 0) // Value has been changed, need to redraw
|
||||
#define PRINT_LABEL (1 << 1) // Text label should be printed
|
||||
#define DYNAMIC (1 << 2) // Value should be updated dynamically
|
||||
#define OPTSTRING (1 << 3) // (Temporary) Flag for OME_Submenu, indicating func should be called to get a string to display.
|
||||
|
||||
// Data type for OME_Setting. Uses upper 4 bits
|
||||
// of flags, leaving 16 data types.
|
||||
#define CMS_DATA_TYPE_OFFSET (4)
|
||||
typedef enum {
|
||||
CMS_DATA_TYPE_ANGULAR_RATE = (1 << CMS_DATA_TYPE_OFFSET),
|
||||
} CMSDataType_e;
|
||||
|
||||
// Use a function and data type to make sure switches are exhaustive
|
||||
inline CMSDataType_e CMS_DATA_TYPE(const OSD_Entry *entry) { return entry->flags & 0xF0; }
|
||||
|
||||
#define IS_PRINTVALUE(p) ((p)->flags & PRINT_VALUE)
|
||||
#define SET_PRINTVALUE(p) { (p)->flags |= PRINT_VALUE; }
|
||||
|
@ -145,6 +161,16 @@ typedef struct
|
|||
uint16_t multipler;
|
||||
} OSD_FLOAT_t;
|
||||
|
||||
typedef struct OSD_SETTING_s {
|
||||
const uint16_t val; // setting number, from the constants in settings_generated.h
|
||||
const uint8_t step;
|
||||
} __attribute__((packed)) OSD_SETTING_t;
|
||||
|
||||
#define OSD_SETTING_ENTRY_STEP_TYPE(name, setting, step, type) { name, OME_Setting, NULL, &(OSD_SETTING_t){ setting, step }, type }
|
||||
#define OSD_SETTING_ENTRY_TYPE(name, setting, type) OSD_SETTING_ENTRY_STEP_TYPE(name, setting, 0, type)
|
||||
#define OSD_SETTING_ENTRY_STEP(name, setting, step) OSD_SETTING_ENTRY_STEP_TYPE(name, setting, step, 0)
|
||||
#define OSD_SETTING_ENTRY(name, setting) OSD_SETTING_ENTRY_STEP(name, setting, 0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *val;
|
||||
|
|
|
@ -102,10 +102,16 @@ const void * setting_get_copy_value_pointer(const setting_t *val)
|
|||
|
||||
setting_min_t setting_get_min(const setting_t *val)
|
||||
{
|
||||
if (SETTING_MODE(val) == MODE_LOOKUP) {
|
||||
return 0;
|
||||
}
|
||||
return settingMinMaxTable[SETTING_INDEXES_GET_MIN(val)];
|
||||
}
|
||||
|
||||
setting_max_t setting_get_max(const setting_t *val)
|
||||
{
|
||||
if (SETTING_MODE(val) == MODE_LOOKUP) {
|
||||
return settingLookupTables[val->config.lookup.tableIndex].valueCount - 1;
|
||||
}
|
||||
return settingMinMaxTable[SETTING_INDEXES_GET_MAX(val)];
|
||||
}
|
||||
|
|
|
@ -367,6 +367,14 @@ class Generator
|
|||
buf << "extern const char * const #{table_variable_name(name)}[];\n"
|
||||
end
|
||||
|
||||
# Write #define'd constants for referencing each setting
|
||||
ii = 0
|
||||
foreach_enabled_member do |group, member|
|
||||
name = member["name"]
|
||||
buf << "#define SETTING_#{name.upcase} #{ii}\n"
|
||||
ii += 1
|
||||
end
|
||||
|
||||
File.open(file, 'w') {|file| file.write(buf.string)}
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue