/* * Copyright (C) OpenTX * * Based on code named * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "opentx.h" #define XPOT_DELTA 10 #define XPOT_DELAY 10 /* cycles */ #define POT_BAR_INTERVAL 20 #define POT_BAR_BOTTOM 200 #define STICKS_WIDTH 90 #define STICKS_Y 110 #define STICK_LEFT_X 25 #define STICK_RIGHT_X (LCD_W-STICK_LEFT_X-STICKS_WIDTH) enum CalibrationState { CALIB_START = 0, CALIB_SET_MIDPOINT, CALIB_MOVE_STICKS, CALIB_STORE, CALIB_FINISHED }; void drawSticks() { int16_t calibStickVert = calibratedStick[CONVERT_MODE(1)]; if (g_model.throttleReversed && CONVERT_MODE(1) == THR_STICK) calibStickVert = -calibStickVert; drawStick(STICK_LEFT_X, STICKS_Y, calibratedStick[CONVERT_MODE(0)], calibStickVert); calibStickVert = calibratedStick[CONVERT_MODE(2)]; if (g_model.throttleReversed && CONVERT_MODE(2) == THR_STICK) calibStickVert = -calibStickVert; drawStick(STICK_RIGHT_X, STICKS_Y, calibratedStick[CONVERT_MODE(3)], calibStickVert); } void drawPots() { // The pots which are displayed in the main view extern void drawMainPots(); drawMainPots(); // The 2 main front sliders drawVerticalSlider(125, 120, 120, calibratedStick[7], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON); drawVerticalSlider(LCD_W-125-12, 120, 120, calibratedStick[8], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON); } bool menuCommonCalib(evt_t event) { drawScreenTemplate(NULL, LBM_CALIBRATION_ICON, OPTION_MENU_NO_FOOTER); for (uint8_t i=0; i= POT1 && i <= POT_LAST) { if (IS_POT_WITHOUT_DETENT(i)) { reusableBuffer.calib.midVals[i] = (reusableBuffer.calib.hiVals[i] + reusableBuffer.calib.loVals[i]) / 2; } uint8_t idx = i - POT1; int count = reusableBuffer.calib.xpotsCalib[idx].stepsCount; if (IS_POT_MULTIPOS(i) && count <= XPOTS_MULTIPOS_COUNT) { // use raw analog value for multipos calibraton, anaIn() already has multipos decoded value vt = getAnalogValue(i) >> 1; if (reusableBuffer.calib.xpotsCalib[idx].lastCount == 0 || vt < reusableBuffer.calib.xpotsCalib[idx].lastPosition - XPOT_DELTA || vt > reusableBuffer.calib.xpotsCalib[idx].lastPosition + XPOT_DELTA) { reusableBuffer.calib.xpotsCalib[idx].lastPosition = vt; reusableBuffer.calib.xpotsCalib[idx].lastCount = 1; } else { if (reusableBuffer.calib.xpotsCalib[idx].lastCount < 255) reusableBuffer.calib.xpotsCalib[idx].lastCount++; } if (reusableBuffer.calib.xpotsCalib[idx].lastCount == XPOT_DELAY) { int16_t position = reusableBuffer.calib.xpotsCalib[idx].lastPosition; bool found = false; for (int j=0; j= step-XPOT_DELTA && position <= step+XPOT_DELTA) { found = true; break; } } if (!found) { if (count < XPOTS_MULTIPOS_COUNT) { reusableBuffer.calib.xpotsCalib[idx].steps[count] = position; } reusableBuffer.calib.xpotsCalib[idx].stepsCount += 1; } } } } } switch (event) { case EVT_ENTRY: case EVT_KEY_BREAK(KEY_EXIT): calibrationState = CALIB_START; break; case EVT_KEY_BREAK(KEY_ENTER): calibrationState++; break; } switch (calibrationState) { case CALIB_START: // START CALIBRATION if (!READ_ONLY()) { lcdDrawText(50, 3, STR_MENUCALIBRATION, MENU_TITLE_COLOR); lcdDrawText(50, 3+FH, STR_MENUTOSTART, MENU_TITLE_COLOR); } break; case CALIB_SET_MIDPOINT: // SET MIDPOINT lcdDrawText(50, 3, STR_MENUCALIBRATION, MENU_TITLE_COLOR); lcdDrawText(50, 3+FH, STR_SETMIDPOINT, MENU_TITLE_COLOR); for (int i=0; i 50) { g_eeGeneral.calib[i].mid = reusableBuffer.calib.midVals[i]; int16_t v = reusableBuffer.calib.midVals[i] - reusableBuffer.calib.loVals[i]; g_eeGeneral.calib[i].spanNeg = v - v/STICK_TOLERANCE; v = reusableBuffer.calib.hiVals[i] - reusableBuffer.calib.midVals[i]; g_eeGeneral.calib[i].spanPos = v - v/STICK_TOLERANCE; } } for (int i=POT1; i<=POT_LAST; i++) { int idx = i - POT1; int count = reusableBuffer.calib.xpotsCalib[idx].stepsCount; if (IS_POT_MULTIPOS(i)) { if (count > 1 && count <= XPOTS_MULTIPOS_COUNT) { for (int j=0; jcount = count - 1; for (int j=0; jcount; j++) { calib->steps[j] = (reusableBuffer.calib.xpotsCalib[idx].steps[j+1] + reusableBuffer.calib.xpotsCalib[idx].steps[j]) >> 5; } } else { // g_eeGeneral.potsConfig &= ~(0x03<<(2*idx)); } } } break; case CALIB_STORE: g_eeGeneral.chkSum = evalChkSum(); storageDirty(EE_GENERAL); calibrationState = CALIB_FINISHED; break; default: calibrationState = CALIB_START; break; } static const BitmapBuffer * horus = BitmapBuffer::load(getThemePath("horus.bmp")); if (horus) { lcd->drawBitmap((LCD_W-horus->getWidth())/2, LCD_H-20-horus->getHeight(), horus); } drawSticks(); drawPots(); return true; } bool menuGeneralCalib(evt_t event) { if (event == EVT_ENTRY || event == EVT_ENTRY_UP) TRACE("Menu %s displayed ...", STR_MENUCALIBRATION); if (calibrationState == CALIB_FINISHED) { calibrationState = CALIB_START; popMenu(); return false; } if (!check_submenu_simple(event, 0)) { return false; } menuVerticalPosition = -1; return menuCommonCalib(READ_ONLY() ? 0 : event); } bool menuFirstCalib(evt_t event) { if (event == EVT_KEY_BREAK(KEY_EXIT) || calibrationState == CALIB_FINISHED) { calibrationState = CALIB_START; chainMenu(menuMainView); return false; } else { return menuCommonCalib(event); } }