/* * 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 5 /* cycles */ #define STICKS_WIDTH 90 #define STICKS_Y 60 #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 }; #define STICK_PANEL_WIDTH 68 void drawStick(coord_t x, coord_t y, const BitmapBuffer * background, int16_t xval, int16_t yval) { static const BitmapBuffer * stick = BitmapBuffer::load(getThemePath("stick_pointer.png")); lcd->drawBitmap(x, y, background); lcd->drawBitmap(x + 2 + STICK_PANEL_WIDTH/2 + STICK_PANEL_WIDTH/2 * xval/RESX, y + 2 + STICK_PANEL_WIDTH/2 - STICK_PANEL_WIDTH/2 * yval/RESX, stick); } void drawSticks() { static const BitmapBuffer * background = BitmapBuffer::load(getThemePath("stick_background.png")); int16_t calibStickVert = calibratedStick[CONVERT_MODE(1)]; if (g_model.throttleReversed && CONVERT_MODE(1) == THR_STICK) calibStickVert = -calibStickVert; drawStick(STICK_LEFT_X, STICKS_Y, background, 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, background, 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); } void drawMouse() { static const BitmapBuffer * background = BitmapBuffer::load(getThemePath("trackp_background.png")); drawStick(STICK_LEFT_X, STICKS_Y+100, background, calibratedStick[11], calibratedStick[12]); } bool menuCommonCalib(event_t event) { drawMenuTemplate(NULL, ICON_RADIO_CALIBRATION, NULL, 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_FIRST(KEY_EXIT): menuCalibrationState = CALIB_START; break; case EVT_KEY_FIRST(KEY_ENTER): killEvents(event); menuCalibrationState++; break; } switch (menuCalibrationState) { 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 (uint8_t 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); menuCalibrationState = CALIB_FINISHED; break; default: menuCalibrationState = 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(); drawMouse(); return true; } bool menuRadioCalibration(event_t event) { if (event == EVT_ENTRY || event == EVT_ENTRY_UP) TRACE("Menu %s displayed ...", STR_MENUCALIBRATION); if (menuCalibrationState == CALIB_FINISHED || (menuCalibrationState == CALIB_START && event == EVT_KEY_FIRST(KEY_EXIT))) { menuCalibrationState = CALIB_START; killEvents(event); popMenu(); return false; } if (!check_submenu_simple(event, 0)) { return false; } menuVerticalPosition = -1; return menuCommonCalib(READ_ONLY() ? 0 : event); } bool menuFirstCalib(event_t event) { if (event == EVT_KEY_FIRST(KEY_EXIT) || menuCalibrationState == CALIB_FINISHED) { menuCalibrationState = CALIB_START; chainMenu(menuMainView); return false; } else { return menuCommonCalib(event); } }