void osdEraseFlash(void *ptr) { UNUSED(ptr); max7456ClearScreen(); max7456Write(5, 3, "ERASING FLASH..."); max7456RefreshAll(); flashfsEraseCompletely(); while (!flashfsIsReady()) { delay(100); } max7456ClearScreen(); max7456RefreshAll(); }
void osdMenuBack(void) { 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++) { curr_profile.pidProfile.P8[i] = tempPid[i][0]; curr_profile.pidProfile.I8[i] = tempPid[i][1]; curr_profile.pidProfile.D8[i] = tempPid[i][2]; } curr_profile.pidProfile.P8[PIDLEVEL] = tempPid[3][0]; curr_profile.pidProfile.I8[PIDLEVEL] = tempPid[3][1]; curr_profile.pidProfile.D8[PIDLEVEL] = tempPid[3][2]; } // 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)); if (menuStackIdx) { max7456ClearScreen(); menuStackIdx--; nextPage = NULL; currentMenu = menuStack[menuStackIdx]; currentMenuPos = menuStackHistory[menuStackIdx]; osdUpdateMaxRows(); } else osdOpenMenu(); }
void osdInit(void) { char x, string_buffer[30]; armState = ARMING_FLAG(ARMED); max7456Init(masterConfig.osdProfile.video_system); max7456ClearScreen(); // display logo and help x = 160; for (int i = 1; i < 5; i++) { for (int j = 3; j < 27; j++) { if (x != 255) max7456WriteChar(j, i, x++); } } sprintf(string_buffer, "BF VERSION: %s", FC_VERSION_STRING); max7456Write(5, 6, string_buffer); max7456Write(7, 7, "MENU: THRT MID"); max7456Write(13, 8, "YAW RIGHT"); max7456Write(13, 9, "PITCH UP"); max7456RefreshAll(); refreshTimeout = 4 * REFRESH_1S; }
void osdDrawElements(void) { max7456ClearScreen(); if (currentElement) osdDrawElementPositioningHelp(); else if (sensors(SENSOR_ACC) || inMenu) { osdDrawSingleElement(OSD_ARTIFICIAL_HORIZON); osdDrawSingleElement(OSD_CROSSHAIRS); } osdDrawSingleElement(OSD_MAIN_BATT_VOLTAGE); osdDrawSingleElement(OSD_RSSI_VALUE); osdDrawSingleElement(OSD_FLYTIME); osdDrawSingleElement(OSD_ONTIME); osdDrawSingleElement(OSD_FLYMODE); osdDrawSingleElement(OSD_THROTTLE_POS); osdDrawSingleElement(OSD_VTX_CHANNEL); osdDrawSingleElement(OSD_CURRENT_DRAW); osdDrawSingleElement(OSD_MAH_DRAWN); osdDrawSingleElement(OSD_CRAFT_NAME); osdDrawSingleElement(OSD_ALTITUDE); #ifdef GPS if (sensors(SENSOR_GPS) || inMenu) { osdDrawSingleElement(OSD_GPS_SATS); osdDrawSingleElement(OSD_GPS_SPEED); } #endif // GPS }
void osdChangeScreen(void *ptr) { uint8_t i; if (ptr) { max7456ClearScreen(); // hack - save profile to temp if (ptr == &menuPid[0]) { for (i = 0; i < 3; i++) { tempPid[i][0] = curr_profile.pidProfile.P8[i]; tempPid[i][1] = curr_profile.pidProfile.I8[i]; tempPid[i][2] = curr_profile.pidProfile.D8[i]; } tempPid[3][0] = curr_profile.pidProfile.P8[PIDLEVEL]; tempPid[3][1] = curr_profile.pidProfile.I8[PIDLEVEL]; tempPid[3][2] = curr_profile.pidProfile.D8[PIDLEVEL]; } if (ptr == &menuRateExpo[0]) memcpy(&rateProfile, &masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile], sizeof(controlRateConfig_t)); menuStack[menuStackIdx] = currentMenu; menuStackHistory[menuStackIdx] = currentMenuPos; menuStackIdx++; currentMenu = (OSD_Entry *)ptr; currentMenuPos = 0; osdUpdateMaxRows(); } }
// called when motors armed void osdArmMotors(void) { max7456ClearScreen(); max7456Write(12, 7, "ARMED"); refreshTimeout = REFRESH_1S / 2; osdResetStats(); }
static int clearScreen(displayPort_t *displayPort) { UNUSED(displayPort); max7456Invert(displayPortProfileMax7456()->invert); max7456Brightness(displayPortProfileMax7456()->blackBrightness, displayPortProfileMax7456()->whiteBrightness); max7456ClearScreen(); return 0; }
void osdEditElement(void *ptr) { uint32_t address = (uint32_t)ptr; // zsave position on menu stack menuStack[menuStackIdx] = currentMenu; menuStackHistory[menuStackIdx] = currentMenuPos; menuStackIdx++; currentElement = (uint16_t *)address; *currentElement |= BLINK_FLAG; max7456ClearScreen(); }
void osdShowStats(void) { uint8_t top = 2; char buff[10]; max7456ClearScreen(); max7456Write(2, top++, " --- STATS ---"); if (STATE(GPS_FIX)) { max7456Write(2, top, "MAX SPEED :"); itoa(stats.max_speed, buff, 10); max7456Write(22, top++, buff); } max7456Write(2, top, "MIN BATTERY :"); sprintf(buff, "%d.%1dV", stats.min_voltage / 10, stats.min_voltage % 10); max7456Write(22, top++, buff); max7456Write(2, top, "MIN RSSI :"); itoa(stats.min_rssi, buff, 10); strcat(buff, "%"); max7456Write(22, top++, buff); if (feature(FEATURE_CURRENT_METER)) { max7456Write(2, top, "MAX CURRENT :"); itoa(stats.max_current, buff, 10); strcat(buff, "A"); max7456Write(22, top++, buff); max7456Write(2, top, "USED MAH :"); itoa(mAhDrawn, buff, 10); strcat(buff, "\x07"); max7456Write(22, top++, buff); } max7456Write(2, top, "MAX ALTITUDE :"); int32_t alt = osdGetAltitude(stats.max_altitude); sprintf(buff, "%c%d.%01d%c", alt < 0 ? '-' : ' ', abs(alt / 100), abs((alt % 100) / 10), osdGetAltitudeSymbol()); max7456Write(22, top++, buff); refreshTimeout = 60 * REFRESH_1S; }
void osdExitMenu(void *ptr) { max7456ClearScreen(); max7456Write(5, 3, "RESTARTING IMU..."); max7456RefreshAll(); stopMotors(); stopPwmAllMotors(); delay(200); if (ptr) { // save local variables to configuration if (featureBlackbox) featureSet(FEATURE_BLACKBOX); else featureClear(FEATURE_BLACKBOX); if (featureLedstrip) featureSet(FEATURE_LED_STRIP); else featureClear(FEATURE_LED_STRIP); #if defined(VTX) || defined(USE_RTC6705) if (featureVtx) featureSet(FEATURE_VTX); else featureClear(FEATURE_VTX); #endif // VTX || USE_RTC6705 #ifdef VTX masterConfig.vtxBand = vtxBand; masterConfig.vtx_channel = vtxChannel - 1; #endif // VTX #ifdef USE_RTC6705 masterConfig.vtx_channel = vtxBand * 8 + vtxChannel - 1; #endif // USE_RTC6705 saveConfigAndNotify(); } systemReset(); }
void osdOpenMenu(void) { if (inMenu) return; if (feature(FEATURE_LED_STRIP)) featureLedstrip = 1; if (feature(FEATURE_BLACKBOX)) featureBlackbox = 1; #if defined(VTX) || defined(USE_RTC6705) if (feature(FEATURE_VTX)) featureVtx = 1; #endif // VTX || USE_RTC6705 #ifdef VTX vtxBand = masterConfig.vtxBand; vtxChannel = masterConfig.vtx_channel + 1; #endif // VTX #ifdef USE_RTC6705 vtxBand = masterConfig.vtx_channel / 8; vtxChannel = masterConfig.vtx_channel % 8 + 1; #endif // USE_RTC6705 osdRows = max7456GetRowsCount(); inMenu = true; refreshTimeout = 0; max7456ClearScreen(); currentMenu = &menuMain[0]; osdResetAlarms(); osdChangeScreen(currentMenu); #ifdef LED_STRIP getLedColor(); #endif // LED_STRIP }
uint8_t osdHandleKey(uint8_t key) { uint8_t res = BUTTON_TIME; OSD_Entry *p; if (!currentMenu) return res; if (key == KEY_ESC) { osdMenuBack(); return BUTTON_PAUSE; } if (key == KEY_DOWN) { if (currentMenuPos < currentMenuIdx) currentMenuPos++; else { if (nextPage) // we have more pages { max7456ClearScreen(); p = nextPage; nextPage = currentMenu; currentMenu = (OSD_Entry *)p; currentMenuPos = 0; osdUpdateMaxRows(); } currentMenuPos = 0; } } if (key == KEY_UP) { currentMenuPos--; if ((currentMenu + currentMenuPos)->type == OME_Label && currentMenuPos > 0) currentMenuPos--; if (currentMenuPos == -1 || (currentMenu + currentMenuPos)->type == OME_Label) { if (nextPage) { max7456ClearScreen(); p = nextPage; nextPage = currentMenu; currentMenu = (OSD_Entry *)p; currentMenuPos = 0; osdUpdateMaxRows(); } currentMenuPos = currentMenuIdx; } } if (key == KEY_DOWN || key == KEY_UP) return res; p = currentMenu + currentMenuPos; switch (p->type) { case OME_POS: if (key == KEY_RIGHT) { uint32_t address = (uint32_t)p->data; uint16_t *val; val = (uint16_t *)address; if (!(*val & VISIBLE_FLAG)) // no submenu for hidden elements break; } case OME_Submenu: case OME_OSD_Exit: if (p->func && key == KEY_RIGHT) { p->func(p->data); res = BUTTON_PAUSE; } break; case OME_Back: osdMenuBack(); res = BUTTON_PAUSE; break; case OME_Bool: if (p->data) { uint8_t *val = p->data; if (key == KEY_RIGHT) *val = 1; else *val = 0; } break; case OME_VISIBLE: if (p->data) { uint32_t address = (uint32_t)p->data; uint16_t *val; val = (uint16_t *)address; if (key == KEY_RIGHT) *val |= VISIBLE_FLAG; else *val %= ~VISIBLE_FLAG; } break; case OME_UINT8: case OME_FLOAT: if (p->data) { OSD_UINT8_t *ptr = p->data; if (key == KEY_RIGHT) { if (*ptr->val < ptr->max) *ptr->val += ptr->step; } else { if (*ptr->val > ptr->min) *ptr->val -= ptr->step; } } break; case OME_TAB: if (p->type == OME_TAB) { OSD_TAB_t *ptr = p->data; if (key == KEY_RIGHT) { if (*ptr->val < ptr->max) *ptr->val += 1; } else { if (*ptr->val > 0) *ptr->val -= 1; } if (p->func) p->func(p->data); } break; case OME_INT8: if (p->data) { OSD_INT8_t *ptr = p->data; if (key == KEY_RIGHT) { if (*ptr->val < ptr->max) *ptr->val += ptr->step; } else { if (*ptr->val > ptr->min) *ptr->val -= ptr->step; } } break; case OME_UINT16: if (p->data) { OSD_UINT16_t *ptr = p->data; if (key == KEY_RIGHT) { if (*ptr->val < ptr->max) *ptr->val += ptr->step; } else { if (*ptr->val > ptr->min) *ptr->val -= ptr->step; } } break; case OME_INT16: if (p->data) { OSD_INT16_t *ptr = p->data; if (key == KEY_RIGHT) { if (*ptr->val < ptr->max) *ptr->val += ptr->step; } else { if (*ptr->val > ptr->min) *ptr->val -= ptr->step; } } break; case OME_Label: case OME_END: break; } return res; }
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(); } }