static void cmsUpdate(uint32_t currentTimeUs) { static int16_t rcDelayMs = BUTTON_TIME; static int holdCount = 1; static int repeatCount = 1; static int repeatBase = 0; static uint32_t lastCalledMs = 0; static uint32_t lastCmsHeartBeatMs = 0; const uint32_t currentTimeMs = currentTimeUs / 1000; if (!cmsInMenu) { // Detect menu invocation if (IS_MID(THROTTLE) && IS_LO(YAW) && IS_HI(PITCH) && !ARMING_FLAG(ARMED)) { cmsMenuOpen(); rcDelayMs = BUTTON_PAUSE; // Tends to overshoot if BUTTON_TIME } } else { // // Scan 'key' first // uint8_t key = KEY_NONE; if (IS_MID(THROTTLE) && IS_LO(YAW) && IS_HI(PITCH) && !ARMING_FLAG(ARMED)) { key = KEY_MENU; } else if (IS_HI(PITCH)) { key = KEY_UP; } else if (IS_LO(PITCH)) { key = KEY_DOWN; } else if (IS_LO(ROLL)) { key = KEY_LEFT; } else if (IS_HI(ROLL)) { key = KEY_RIGHT; } else if (IS_HI(YAW) || IS_LO(YAW)) { key = KEY_ESC; } if (key == KEY_NONE) { // No 'key' pressed, reset repeat control holdCount = 1; repeatCount = 1; repeatBase = 0; } else { // The 'key' is being pressed; keep counting ++holdCount; } if (rcDelayMs > 0) { rcDelayMs -= (currentTimeMs - lastCalledMs); } else if (key) { rcDelayMs = cmsHandleKeyWithRepeat(pCurrentDisplay, key, repeatCount); // Key repeat effect is implemented in two phases. // First phldase is to decrease rcDelayMs reciprocal to hold time. // When rcDelayMs reached a certain limit (scheduling interval), // repeat rate will not raise anymore, so we call key handler // multiple times (repeatCount). // // XXX Caveat: Most constants are adjusted pragmatically. // XXX Rewrite this someday, so it uses actual hold time instead // of holdCount, which depends on the scheduling interval. if (((key == KEY_LEFT) || (key == KEY_RIGHT)) && (holdCount > 20)) { // Decrease rcDelayMs reciprocally rcDelayMs /= (holdCount - 20); // When we reach the scheduling limit, if (rcDelayMs <= 50) { // start calling handler multiple times. if (repeatBase == 0) repeatBase = holdCount; repeatCount = repeatCount + (holdCount - repeatBase) / 5; if (repeatCount > 5) { repeatCount= 5; } } } } cmsDrawMenu(pCurrentDisplay, currentTimeUs); if (currentTimeMs > lastCmsHeartBeatMs + 500) { // Heart beat for external CMS display device @ 500msec // (Timeout @ 1000msec) displayHeartbeat(pCurrentDisplay); lastCmsHeartBeatMs = currentTimeMs; } } lastCalledMs = currentTimeMs; }
void osdUpdate(uint32_t currentTime) { static uint8_t rcDelay = BUTTON_TIME; static uint8_t lastSec = 0; uint8_t key = 0, sec; // detect enter to menu if (IS_MID(THROTTLE) && IS_HI(YAW) && IS_HI(PITCH) && !ARMING_FLAG(ARMED)) osdOpenMenu(); // detect arm/disarm if (armState != ARMING_FLAG(ARMED)) { if (ARMING_FLAG(ARMED)) osdArmMotors(); // reset statistic etc else osdShowStats(); // show statistic armState = ARMING_FLAG(ARMED); } osdUpdateStats(); sec = currentTime / 1000000; if (ARMING_FLAG(ARMED) && sec != lastSec) { flyTime++; lastSec = sec; } if (refreshTimeout) { if (IS_HI(THROTTLE) || IS_HI(PITCH)) // hide statistics refreshTimeout = 1; refreshTimeout--; if (!refreshTimeout) max7456ClearScreen(); return; } blinkState = (millis() / 200) % 2; if (inMenu) { if (rcDelay) { rcDelay--; } else if (IS_HI(PITCH)) { key = KEY_UP; rcDelay = BUTTON_TIME; } else if (IS_LO(PITCH)) { key = KEY_DOWN; rcDelay = BUTTON_TIME; } else if (IS_LO(ROLL)) { key = KEY_LEFT; rcDelay = BUTTON_TIME; } else if (IS_HI(ROLL)) { key = KEY_RIGHT; rcDelay = BUTTON_TIME; } else if ((IS_HI(YAW) || IS_LO(YAW)) && currentMenu != menuRc) // this menu is used to check transmitter signals so can exit using YAW { key = KEY_ESC; rcDelay = BUTTON_TIME; } if (key && !currentElement) { rcDelay = osdHandleKey(key); return; } if (currentElement) // edit position of element { if (key) { if (key == KEY_ESC) { // exit osdMenuBack(); rcDelay = BUTTON_PAUSE; *currentElement &= ~BLINK_FLAG; currentElement = NULL; return; } else { uint8_t x, y; x = OSD_X(*currentElement); y = OSD_Y(*currentElement); switch (key) { case KEY_UP: y--; break; case KEY_DOWN: y++; break; case KEY_RIGHT: x++; break; case KEY_LEFT: x--; break; } *currentElement &= 0xFC00; *currentElement |= OSD_POS(x, y); max7456ClearScreen(); } } osdDrawElements(); } else osdDrawMenu(); } else { osdUpdateAlarms(); osdDrawElements(); } }
static void rcdevice5KeySimulationProcess(timeUs_t currentTimeUs) { UNUSED(currentTimeUs); #ifdef USE_CMS if (cmsInMenu) { return; } #endif if (ARMING_FLAG(ARMED) || getArmingDisableFlags() & ARMING_DISABLED_RUNAWAY_TAKEOFF) { return; } rcdeviceCamSimulationKeyEvent_e key = RCDEVICE_CAM_KEY_NONE; if (needRelease) { if (IS_MID(YAW) && IS_MID(PITCH) && IS_MID(ROLL)) { if ((camDevice->serialPort != NULL || reInitializeDevice()) && rcdeviceIs5KeyEnabled()) { key = RCDEVICE_CAM_KEY_RELEASE; if (rcdeviceSend5KeyOSDCableSimualtionEvent(key)) { needRelease = false; } else { rcdeviceInMenu = false; } } } return; } else { if (IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_LO(YAW)) { // Disconnect HI YAW if (rcdeviceInMenu) { key = RCDEVICE_CAM_KEY_CONNECTION_CLOSE; } } else { if (rcdeviceInMenu) { if (IS_LO(ROLL)) { // Left LO ROLL key = RCDEVICE_CAM_KEY_LEFT; } else if (IS_HI(PITCH)) { // Up HI PITCH key = RCDEVICE_CAM_KEY_UP; } else if (IS_HI(ROLL)) { // Right HI ROLL key = RCDEVICE_CAM_KEY_RIGHT; } else if (IS_LO(PITCH)) { // Down LO PITCH key = RCDEVICE_CAM_KEY_DOWN; } else if (IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_HI(YAW)) { // Enter HI YAW key = RCDEVICE_CAM_KEY_ENTER; } } else { if (IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_HI(YAW)) { // Enter HI YAW key = RCDEVICE_CAM_KEY_CONNECTION_OPEN; } } } } if (key != RCDEVICE_CAM_KEY_NONE) { if ((camDevice->serialPort != NULL || reInitializeDevice()) && rcdeviceIs5KeyEnabled()) { if (rcdeviceSend5KeyOSDCableSimualtionEvent(key)) { needRelease = true; } else { rcdeviceInMenu = false; } } } }