1
0
Fork 0
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:
Alberto García Hierro 2017-10-07 13:02:44 +01:00 committed by GitHub
parent 206940461a
commit f1fb918803
9 changed files with 278 additions and 232 deletions

View file

@ -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;

View file

@ -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 },
{ "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

View file

@ -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,
};

View file

@ -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

View file

@ -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
};

View file

@ -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,
};

View file

@ -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;

View file

@ -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)];
}

View file

@ -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