mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-26 01:35:41 +03:00
More displayPort_t, CANVAS as new feature, multi-display cycling
- Further touch-ups with displayPort_t handling. - CANVAS is a FEATURE now. - Device specific xxxCmsInit() are registered by device’s init, and called by CMS upon entry to menu. - Multiple display devices can be cycled by entering menu invocation command while in menu. - The menu invocation command is (was) changed to THR-Mid + YAW-Left + Pitch-Full to avoid collision with MWOSD menu invocation command. - More separation attempt.
This commit is contained in:
parent
7960b1665d
commit
720a841008
17 changed files with 267 additions and 182 deletions
|
@ -37,7 +37,9 @@
|
|||
|
||||
#include "io/cms.h"
|
||||
#include "io/cms_types.h"
|
||||
#ifdef CANVAS
|
||||
#include "io/canvas.h"
|
||||
#endif
|
||||
|
||||
#include "io/flashfs.h"
|
||||
#include "io/osd.h"
|
||||
|
@ -57,9 +59,50 @@
|
|||
|
||||
#include "build/debug.h"
|
||||
|
||||
// Device management
|
||||
|
||||
#define CMS_MAX_DEVICE 4
|
||||
|
||||
cmsDeviceInitFuncPtr cmsDeviceInitFunc[CMS_MAX_DEVICE];
|
||||
int cmsDeviceCount;
|
||||
int cmsCurrentDevice = -1;
|
||||
int cmsLastDevice = -1;
|
||||
|
||||
bool cmsDeviceRegister(cmsDeviceInitFuncPtr func)
|
||||
{
|
||||
if (cmsDeviceCount == CMS_MAX_DEVICE)
|
||||
return false;
|
||||
|
||||
cmsDeviceInitFunc[cmsDeviceCount++] = func;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
cmsDeviceInitFuncPtr cmsDeviceSelectCurrent(void)
|
||||
{
|
||||
if (cmsDeviceCount == 0)
|
||||
return NULL;
|
||||
|
||||
if (cmsCurrentDevice < 0)
|
||||
cmsCurrentDevice = 0;
|
||||
|
||||
return cmsDeviceInitFunc[cmsCurrentDevice];
|
||||
}
|
||||
|
||||
cmsDeviceInitFuncPtr cmsDeviceSelectNext(void)
|
||||
{
|
||||
if (cmsDeviceCount == 0)
|
||||
return NULL;
|
||||
|
||||
cmsCurrentDevice = (cmsCurrentDevice + 1) % cmsDeviceCount; // -1 Okay
|
||||
|
||||
return cmsDeviceInitFunc[cmsCurrentDevice];
|
||||
}
|
||||
|
||||
#define CMS_UPDATE_INTERVAL 50 // msec
|
||||
|
||||
// XXX Why is this here? Something is wrong?
|
||||
// XXX Why is this here? Something wrong?
|
||||
// XXX We need something like Drawing Context that holds all state variables?
|
||||
int8_t lastCursorPos;
|
||||
|
||||
void cmsScreenClear(displayPort_t *instance)
|
||||
|
@ -97,21 +140,9 @@ void cmsScreenResync(displayPort_t *instance)
|
|||
instance->VTable->resync();
|
||||
}
|
||||
|
||||
displayPort_t *cmsScreenInit(void)
|
||||
void cmsScreenInit(displayPort_t *pDisp, cmsDeviceInitFuncPtr cmsDeviceInitFunc)
|
||||
{
|
||||
#ifdef OSD
|
||||
return osdCmsInit();
|
||||
#endif
|
||||
|
||||
#ifdef CANVAS
|
||||
return canvasCmsInit();
|
||||
#endif
|
||||
|
||||
#ifdef OLEDCMS
|
||||
return displayCmsInit();
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
cmsDeviceInitFunc(pDisp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -407,38 +438,31 @@ void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTime)
|
|||
|
||||
// XXX Needs separation
|
||||
OSD_Entry menuPid[];
|
||||
void cmsx_PidRead(void);
|
||||
void cmsx_PidWriteback(void);
|
||||
OSD_Entry menuRateExpo[];
|
||||
uint8_t tempPid[4][3];
|
||||
controlRateConfig_t rateProfile;
|
||||
void cmsx_RateExpoRead(void);
|
||||
void cmsx_RateExpoWriteback(void);
|
||||
|
||||
void cmsMenuChange(displayPort_t *pDisplay, void *ptr)
|
||||
{
|
||||
uint8_t i;
|
||||
if (ptr) {
|
||||
// hack - save profile to temp
|
||||
// XXX (jflyper) This hack could be avoided by adding pre- and post-
|
||||
// (onEntry and onExit?) functions to OSD_Entry, that are called
|
||||
// before and after the menu item is displayed.
|
||||
if (ptr == &menuPid[0]) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
tempPid[i][0] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.P8[i];
|
||||
tempPid[i][1] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.I8[i];
|
||||
tempPid[i][2] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.D8[i];
|
||||
}
|
||||
tempPid[3][0] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.P8[PIDLEVEL];
|
||||
tempPid[3][1] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.I8[PIDLEVEL];
|
||||
tempPid[3][2] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.D8[PIDLEVEL];
|
||||
}
|
||||
|
||||
// XXX (jflyper): This can be avoided by adding pre- and post-
|
||||
// XXX (or onEnter and onExit) functions?
|
||||
if (ptr == &menuPid[0])
|
||||
cmsx_PidRead();
|
||||
if (ptr == &menuRateExpo[0])
|
||||
memcpy(&rateProfile, &masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile], sizeof(controlRateConfig_t));
|
||||
cmsx_RateExpoRead();
|
||||
|
||||
menuStack[menuStackIdx] = currentMenu;
|
||||
menuStackHistory[menuStackIdx] = currentCursorPos;
|
||||
menuStackIdx++;
|
||||
|
||||
currentMenu = (OSD_Entry *)ptr;
|
||||
currentCursorPos = 0;
|
||||
if ((OSD_Entry *)ptr != currentMenu) {
|
||||
// Stack it and move to a new menu.
|
||||
// (ptr == curretMenu case occurs when reopening for display sw)
|
||||
menuStack[menuStackIdx] = currentMenu;
|
||||
menuStackHistory[menuStackIdx] = currentCursorPos;
|
||||
menuStackIdx++;
|
||||
currentMenu = (OSD_Entry *)ptr;
|
||||
currentCursorPos = 0;
|
||||
}
|
||||
cmsScreenClear(pDisplay);
|
||||
cmsUpdateMaxRows(pDisplay);
|
||||
}
|
||||
|
@ -446,25 +470,14 @@ void cmsMenuChange(displayPort_t *pDisplay, void *ptr)
|
|||
|
||||
void cmsMenuBack(displayPort_t *pDisplay)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
// becasue pids and rates meybe stored in profiles we need some thicks to manipulate it
|
||||
// hack to save pid profile
|
||||
if (currentMenu == &menuPid[0]) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.P8[i] = tempPid[i][0];
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.I8[i] = tempPid[i][1];
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.D8[i] = tempPid[i][2];
|
||||
}
|
||||
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.P8[PIDLEVEL] = tempPid[3][0];
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.I8[PIDLEVEL] = tempPid[3][1];
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.D8[PIDLEVEL] = tempPid[3][2];
|
||||
}
|
||||
if (currentMenu == &menuPid[0])
|
||||
cmsx_PidWriteback();
|
||||
|
||||
// hack - save rate config for current profile
|
||||
if (currentMenu == &menuRateExpo[0])
|
||||
memcpy(&masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile], &rateProfile, sizeof(controlRateConfig_t));
|
||||
cmsx_RateExpoWriteback();
|
||||
|
||||
if (menuStackIdx) {
|
||||
cmsScreenClear(pDisplay);
|
||||
|
@ -477,29 +490,43 @@ void cmsMenuBack(displayPort_t *pDisplay)
|
|||
}
|
||||
}
|
||||
|
||||
// XXX This should go to device
|
||||
void cmsComputeBatchsize(displayPort_t *pDisplay)
|
||||
{
|
||||
pDisplay->batchsize = (pDisplay->buftime < CMS_UPDATE_INTERVAL) ? pDisplay->bufsize : (pDisplay->bufsize * CMS_UPDATE_INTERVAL) / pDisplay->buftime;
|
||||
}
|
||||
|
||||
// XXX Separation
|
||||
void cmsx_FeatureRead(void);
|
||||
void cmsx_FeatureWriteback(void);
|
||||
void cmsx_InfoInit(void);
|
||||
|
||||
void cmsMenuOpen(displayPort_t *pDisplay)
|
||||
displayPort_t currentDisplay;
|
||||
|
||||
void cmsMenuOpen(void)
|
||||
{
|
||||
if (cmsInMenu)
|
||||
cmsDeviceInitFuncPtr initfunc;
|
||||
|
||||
if (!cmsInMenu) {
|
||||
// New open
|
||||
cmsInMenu = true;
|
||||
DISABLE_ARMING_FLAG(OK_TO_ARM);
|
||||
initfunc = cmsDeviceSelectCurrent();
|
||||
cmsx_FeatureRead();
|
||||
currentMenu = &menuMain[0];
|
||||
} else {
|
||||
// Switch display
|
||||
cmsScreenEnd(¤tDisplay);
|
||||
initfunc = cmsDeviceSelectNext();
|
||||
}
|
||||
|
||||
if (!initfunc)
|
||||
return;
|
||||
|
||||
cmsx_FeatureRead();
|
||||
|
||||
if (!pDisplay)
|
||||
return;
|
||||
|
||||
pDisplay->batchsize = (pDisplay->buftime < CMS_UPDATE_INTERVAL) ? pDisplay->bufsize : (pDisplay->bufsize * CMS_UPDATE_INTERVAL) / pDisplay->buftime;
|
||||
|
||||
cmsInMenu = true;
|
||||
DISABLE_ARMING_FLAG(OK_TO_ARM);
|
||||
|
||||
cmsScreenBegin(pDisplay);
|
||||
currentMenu = &menuMain[0];
|
||||
cmsMenuChange(pDisplay, currentMenu);
|
||||
cmsScreenInit(¤tDisplay, initfunc);
|
||||
cmsComputeBatchsize(¤tDisplay);
|
||||
cmsScreenBegin(¤tDisplay);
|
||||
cmsMenuChange(¤tDisplay, currentMenu);
|
||||
}
|
||||
|
||||
void cmsMenuExit(displayPort_t *pDisplay, void *ptr)
|
||||
|
@ -715,19 +742,20 @@ void cmsUpdate(displayPort_t *pDisplay, uint32_t currentTime)
|
|||
|
||||
uint8_t key = 0;
|
||||
|
||||
// Detect menu invocation
|
||||
if (IS_MID(THROTTLE) && IS_LO(YAW) && IS_HI(PITCH) && !ARMING_FLAG(ARMED)) {
|
||||
// XXX Double enter!?
|
||||
cmsMenuOpen(pDisplay);
|
||||
rcDelay = BUTTON_PAUSE; // Tends to overshoot if BUTTON_TIME
|
||||
lastCalled = currentTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmsInMenu) {
|
||||
if (!cmsInMenu) {
|
||||
// Detect menu invocation
|
||||
if (IS_MID(THROTTLE) && IS_LO(YAW) && IS_HI(PITCH) && !ARMING_FLAG(ARMED)) {
|
||||
cmsMenuOpen();
|
||||
rcDelay = BUTTON_PAUSE; // Tends to overshoot if BUTTON_TIME
|
||||
}
|
||||
} else {
|
||||
if (rcDelay > 0) {
|
||||
rcDelay -= currentTime - lastCalled;
|
||||
debug[0] = rcDelay;
|
||||
rcDelay -= (currentTime - lastCalled);
|
||||
}
|
||||
else if (IS_MID(THROTTLE) && IS_LO(YAW) && IS_HI(PITCH) && !ARMING_FLAG(ARMED)) {
|
||||
// Double enter = display switching
|
||||
cmsMenuOpen();
|
||||
rcDelay = BUTTON_PAUSE;
|
||||
}
|
||||
else if (IS_HI(PITCH)) {
|
||||
key = KEY_UP;
|
||||
|
@ -751,10 +779,10 @@ void cmsUpdate(displayPort_t *pDisplay, uint32_t currentTime)
|
|||
rcDelay = BUTTON_TIME;
|
||||
}
|
||||
|
||||
lastCalled = currentTime;
|
||||
//lastCalled = currentTime;
|
||||
|
||||
if (key && !currentElement) {
|
||||
rcDelay = cmsHandleKey(pDisplay, key);
|
||||
rcDelay = cmsHandleKey(¤tDisplay, key);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -763,33 +791,31 @@ void cmsUpdate(displayPort_t *pDisplay, uint32_t currentTime)
|
|||
if (currentTime > lastCmsHeartBeat + 500) {
|
||||
// Heart beat for external CMS display device @ 500msec
|
||||
// (Timeout @ 1000msec)
|
||||
cmsScreenHeartBeat(pDisplay);
|
||||
cmsScreenHeartBeat(¤tDisplay);
|
||||
lastCmsHeartBeat = currentTime;
|
||||
}
|
||||
}
|
||||
lastCalled = currentTime;
|
||||
}
|
||||
|
||||
displayPort_t *currentDisplay = NULL;
|
||||
|
||||
void cmsHandler(uint32_t unusedTime)
|
||||
{
|
||||
UNUSED(unusedTime);
|
||||
|
||||
if (!currentDisplay)
|
||||
if (cmsDeviceCount < 0)
|
||||
return;
|
||||
|
||||
static uint32_t lastCalled = 0;
|
||||
uint32_t now = millis();
|
||||
|
||||
if (now - lastCalled >= CMS_UPDATE_INTERVAL) {
|
||||
cmsUpdate(currentDisplay, now);
|
||||
cmsUpdate(¤tDisplay, now);
|
||||
lastCalled = now;
|
||||
}
|
||||
}
|
||||
|
||||
void cmsInit(void)
|
||||
{
|
||||
currentDisplay = cmsScreenInit();
|
||||
cmsx_InfoInit();
|
||||
}
|
||||
|
||||
|
@ -803,6 +829,8 @@ void cmsInit(void)
|
|||
|
||||
OSD_UINT8_t entryPidProfile = {&masterConfig.current_profile_index, 0, MAX_PROFILE_COUNT, 1};
|
||||
|
||||
uint8_t tempPid[4][3];
|
||||
|
||||
static OSD_UINT8_t entryRollP = {&tempPid[PIDROLL][0], 10, 150, 1};
|
||||
static OSD_UINT8_t entryRollI = {&tempPid[PIDROLL][1], 1, 150, 1};
|
||||
static OSD_UINT8_t entryRollD = {&tempPid[PIDROLL][2], 0, 150, 1};
|
||||
|
@ -815,6 +843,35 @@ static OSD_UINT8_t entryYawP = {&tempPid[PIDYAW][0], 10, 150, 1};
|
|||
static OSD_UINT8_t entryYawI = {&tempPid[PIDYAW][1], 1, 150, 1};
|
||||
static OSD_UINT8_t entryYawD = {&tempPid[PIDYAW][2], 0, 150, 1};
|
||||
|
||||
void cmsx_PidRead(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
tempPid[i][0] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.P8[i];
|
||||
tempPid[i][1] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.I8[i];
|
||||
tempPid[i][2] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.D8[i];
|
||||
}
|
||||
tempPid[3][0] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.P8[PIDLEVEL];
|
||||
tempPid[3][1] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.I8[PIDLEVEL];
|
||||
tempPid[3][2] = masterConfig.profile[masterConfig.current_profile_index].pidProfile.D8[PIDLEVEL];
|
||||
}
|
||||
|
||||
void cmsx_PidWriteback(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.P8[i] = tempPid[i][0];
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.I8[i] = tempPid[i][1];
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.D8[i] = tempPid[i][2];
|
||||
}
|
||||
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.P8[PIDLEVEL] = tempPid[3][0];
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.I8[PIDLEVEL] = tempPid[3][1];
|
||||
masterConfig.profile[masterConfig.current_profile_index].pidProfile.D8[PIDLEVEL] = tempPid[3][2];
|
||||
}
|
||||
|
||||
OSD_Entry menuPid[] =
|
||||
{
|
||||
{"--- PID ---", OME_Label, NULL, NULL, 0},
|
||||
|
@ -834,6 +891,11 @@ OSD_Entry menuPid[] =
|
|||
{NULL, OME_END, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
//
|
||||
// Rate & Expo
|
||||
//
|
||||
controlRateConfig_t rateProfile;
|
||||
|
||||
static OSD_FLOAT_t entryRollRate = {&rateProfile.rates[0], 0, 250, 1, 10};
|
||||
static OSD_FLOAT_t entryPitchRate = {&rateProfile.rates[1], 0, 250, 1, 10};
|
||||
static OSD_FLOAT_t entryYawRate = {&rateProfile.rates[2], 0, 250, 1, 10};
|
||||
|
@ -846,6 +908,16 @@ static OSD_UINT16_t entryTpaBreak = {&rateProfile.tpa_breakpoint, 1100, 1800, 10
|
|||
static OSD_FLOAT_t entryPSetpoint = {&masterConfig.profile[0].pidProfile.setpointRelaxRatio, 0, 100, 1, 10};
|
||||
static OSD_FLOAT_t entryDSetpoint = {&masterConfig.profile[0].pidProfile.dtermSetpointWeight, 0, 255, 1, 10};
|
||||
|
||||
void cmsx_RateExpoRead()
|
||||
{
|
||||
memcpy(&rateProfile, &masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile], sizeof(controlRateConfig_t));
|
||||
}
|
||||
|
||||
void cmsx_RateExpoWriteback()
|
||||
{
|
||||
memcpy(&masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile], &rateProfile, sizeof(controlRateConfig_t));
|
||||
}
|
||||
|
||||
OSD_Entry menuRateExpo[] =
|
||||
{
|
||||
{"--- RATE&EXPO ---", OME_Label, NULL, NULL, 0},
|
||||
|
@ -931,6 +1003,29 @@ OSD_Entry menuImu[] =
|
|||
//
|
||||
// Black box
|
||||
//
|
||||
|
||||
//
|
||||
// Should goto flashfs eventually.
|
||||
//
|
||||
#ifdef USE_FLASHFS
|
||||
void cmsx_EraseFlash(displayPort_t *pDisplay, void *ptr)
|
||||
{
|
||||
UNUSED(ptr);
|
||||
|
||||
cmsScreenClear(pDisplay);
|
||||
cmsScreenWrite(pDisplay, 5, 3, "ERASING FLASH...");
|
||||
cmsScreenResync(pDisplay); // Was max7456RefreshAll(); Why at this timing?
|
||||
|
||||
flashfsEraseCompletely();
|
||||
while (!flashfsIsReady()) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
cmsScreenClear(pDisplay);
|
||||
cmsScreenResync(pDisplay); // Was max7456RefreshAll(); wedges during heavy SPI?
|
||||
}
|
||||
#endif // USE_FLASHFS
|
||||
|
||||
uint8_t featureBlackbox = 0;
|
||||
|
||||
OSD_UINT8_t entryBlackboxRateDenom = {&masterConfig.blackbox_rate_denom,1,32,1};
|
||||
|
@ -1056,28 +1151,6 @@ OSD_Entry menuLedstrip[] =
|
|||
};
|
||||
#endif // LED_STRIP
|
||||
|
||||
//
|
||||
// Should goto flashfs eventually.
|
||||
//
|
||||
#ifdef USE_FLASHFS
|
||||
void cmsx_EraseFlash(void *ptr)
|
||||
{
|
||||
UNUSED(ptr);
|
||||
|
||||
cmsScreenClear(currentDisplay);
|
||||
cmsScreenWrite(currentDisplay5, 3, "ERASING FLASH...");
|
||||
cmsScreenResync(currentDisplay); // Was max7456RefreshAll(); Why at this timing?
|
||||
|
||||
flashfsEraseCompletely();
|
||||
while (!flashfsIsReady()) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
cmsScreenClear(currentDisplay);
|
||||
cmsScreenResync(currentDisplay); // Was max7456RefreshAll(); wedges during heavy SPI?
|
||||
}
|
||||
#endif // USE_FLASHFS
|
||||
|
||||
#ifdef OSD
|
||||
//
|
||||
// OSD specific menu pages and items
|
||||
|
@ -1221,10 +1294,13 @@ void cmsx_FeatureWriteback(void)
|
|||
else
|
||||
featureClear(FEATURE_BLACKBOX);
|
||||
|
||||
#ifdef LED_STRIP
|
||||
if (featureLedstrip)
|
||||
featureSet(FEATURE_LED_STRIP);
|
||||
else
|
||||
featureClear(FEATURE_LED_STRIP);
|
||||
#endif
|
||||
|
||||
#if defined(VTX) || defined(USE_RTC6705)
|
||||
if (featureVtx)
|
||||
featureSet(FEATURE_VTX);
|
||||
|
@ -1244,4 +1320,5 @@ void cmsx_FeatureWriteback(void)
|
|||
saveConfigAndNotify();
|
||||
}
|
||||
|
||||
|
||||
#endif // CMS
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue