@@ -4,12 +4,14 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- '2.4'
|
||||
- 'main'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '2.4'
|
||||
- 'main'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '.github/ISSUE_TEMPLATE/**'
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
project(OpenTX)
|
||||
|
||||
set(VERSION_MAJOR "2")
|
||||
set(VERSION_MINOR "4")
|
||||
set(VERSION_MINOR "5")
|
||||
set(VERSION_REVISION "0")
|
||||
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
|
||||
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
|
||||
@@ -47,7 +47,7 @@ today(DATE)
|
||||
now(TIME)
|
||||
git_id(GIT_STR)
|
||||
|
||||
message(STATUS "OpenTX ${VERSION} @ ${GIT_STR}")
|
||||
message(STATUS "EdgeTX ${VERSION} @ ${GIT_STR}")
|
||||
|
||||
# options shared by all targets
|
||||
|
||||
|
||||
@@ -672,6 +672,22 @@ PACK(struct ModelData {
|
||||
return thrTrimSw + MIXSRC_FIRST_TRIM;
|
||||
}
|
||||
}
|
||||
|
||||
void setThrottleStickTrimSource(int16_t src)
|
||||
{
|
||||
// The order here is TERA, so that 0 (default) means Throttle
|
||||
switch (src) {
|
||||
case MIXSRC_TrimThr:
|
||||
thrTrimSw = 0;
|
||||
break;
|
||||
case MIXSRC_TrimRud:
|
||||
thrTrimSw = 2;
|
||||
break;
|
||||
default:
|
||||
thrTrimSw = src - MIXSRC_FIRST_TRIM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
@@ -631,12 +631,13 @@ void menuModelSetup(event_t event)
|
||||
case ITEM_MODEL_SETUP_THROTTLE_TRACE:
|
||||
{
|
||||
lcdDrawTextAlignedLeft(y, STR_TTRACE);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.thrTraceSrc, NUM_POTS+NUM_SLIDERS+MAX_OUTPUT_CHANNELS);
|
||||
uint8_t idx = g_model.thrTraceSrc + MIXSRC_Thr;
|
||||
if (idx > MIXSRC_Thr)
|
||||
idx += 1;
|
||||
if (idx >= MIXSRC_FIRST_POT+NUM_POTS+NUM_SLIDERS)
|
||||
idx += MIXSRC_CH1 - MIXSRC_FIRST_POT - NUM_POTS - NUM_SLIDERS;
|
||||
if (attr)
|
||||
CHECK_INCDEC_MODELVAR_ZERO_CHECK(
|
||||
event, g_model.thrTraceSrc,
|
||||
NUM_POTS + NUM_SLIDERS + MAX_OUTPUT_CHANNELS,
|
||||
isThrottleSourceAvailable);
|
||||
|
||||
uint8_t idx = throttleSource2Source(g_model.thrTraceSrc);
|
||||
drawSource(MODEL_SETUP_2ND_COLUMN, y, idx, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -606,12 +606,13 @@ void menuModelSetup(event_t event)
|
||||
case ITEM_MODEL_SETUP_THROTTLE_TRACE:
|
||||
{
|
||||
lcdDrawTextAlignedLeft(y, STR_TTRACE);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, g_model.thrTraceSrc, NUM_POTS+NUM_SLIDERS+MAX_OUTPUT_CHANNELS, isThrottleSourceAvailable);
|
||||
uint8_t idx = g_model.thrTraceSrc + MIXSRC_Thr;
|
||||
if (idx > MIXSRC_Thr)
|
||||
idx += 1;
|
||||
if (idx >= MIXSRC_FIRST_POT+NUM_POTS+NUM_SLIDERS)
|
||||
idx += MIXSRC_CH1 - MIXSRC_FIRST_POT - NUM_POTS - NUM_SLIDERS;
|
||||
if (attr)
|
||||
CHECK_INCDEC_MODELVAR_ZERO_CHECK(
|
||||
event, g_model.thrTraceSrc,
|
||||
NUM_POTS + NUM_SLIDERS + MAX_OUTPUT_CHANNELS,
|
||||
isThrottleSourceAvailable);
|
||||
|
||||
uint8_t idx = throttleSource2Source(g_model.thrTraceSrc);
|
||||
drawSource(MODEL_SETUP_2ND_COLUMN, y, idx, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ endmacro(add_gui_src)
|
||||
|
||||
if(LUA)
|
||||
add_gui_src(standalone_lua.cpp)
|
||||
add_gui_src(model_mixer_scripts.cpp)
|
||||
endif()
|
||||
|
||||
if(HELI)
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
// TODO common code, not in target
|
||||
enum LcdColorIndex
|
||||
{
|
||||
// this one first for when colour is not set
|
||||
DEFAULT_COLOR_INDEX,
|
||||
|
||||
ALARM_COLOR_INDEX,
|
||||
BARGRAPH1_COLOR_INDEX,
|
||||
BARGRAPH2_COLOR_INDEX,
|
||||
@@ -38,7 +41,6 @@ enum LcdColorIndex
|
||||
CURVE_CURSOR_COLOR_INDEX,
|
||||
CUSTOM_COLOR_INDEX,
|
||||
DEFAULT_BGCOLOR_INDEX,
|
||||
DEFAULT_COLOR_INDEX,
|
||||
DISABLE_COLOR_INDEX,
|
||||
EDIT_MARKER_COLOR_INDEX,
|
||||
FIELD_BGCOLOR_INDEX,
|
||||
|
||||
@@ -416,6 +416,12 @@ void drawSensorCustomValue(BitmapBuffer * dc, coord_t x, coord_t y, uint8_t sens
|
||||
}
|
||||
}
|
||||
|
||||
// libopemui defines TIMOUR as zero
|
||||
#if !TIMHOUR
|
||||
#undef TIMEHOUR
|
||||
#define TIMEHOUR 0x2000
|
||||
#endif
|
||||
|
||||
void drawTimer(BitmapBuffer * dc, coord_t x, coord_t y, int32_t tme, LcdFlags flags)
|
||||
{
|
||||
char str[LEN_TIMER_STRING];
|
||||
@@ -437,7 +443,8 @@ void drawSourceCustomValue(BitmapBuffer * dc, coord_t x, coord_t y, source_t sou
|
||||
}
|
||||
else if (source >= MIXSRC_FIRST_TIMER || source == MIXSRC_TX_TIME) {
|
||||
// TODO if (value < 0) flags |= BLINK|INVERS;
|
||||
// TODO drawTimer(dc, x, y, value, flags);
|
||||
if (source == MIXSRC_TX_TIME) flags |= TIMEHOUR;
|
||||
drawTimer(dc, x, y, value, flags);
|
||||
}
|
||||
else if (source == MIXSRC_TX_VOLTAGE) {
|
||||
dc->drawNumber(x, y, value, flags|PREC1);
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#define GET_SET_DEFAULT(value) GET_DEFAULT(value), SET_DEFAULT(value)
|
||||
#define GET_SET_INVERTED(value) GET_INVERTED(value), SET_INVERTED(value)
|
||||
#define GET_SET_VALUE_WITH_OFFSET(value, offset) GET_VALUE_WITH_OFFSET(value, offset), SET_VALUE_WITH_OFFSET(value, offset)
|
||||
#define GET_SET_WITH_OFFSET(value, offset) GET_VALUE_WITH_OFFSET(value, offset), SET_VALUE_WITH_OFFSET(value, offset)
|
||||
#define GET_SET_WITH_OFFSET(value, offset) GET_VALUE_WITH_OFFSET(value, offset), SET_VALUE_WITH_OFFSET(value, offset)
|
||||
#define GET_SET_BF(value, offset, bits) GET_VALUE_WITH_BF(value, offset, bits), SET_VALUE_WITH_BF(value, offset, bits)
|
||||
|
||||
#endif // _GETSET_HELPERS_H_
|
||||
|
||||
@@ -25,7 +25,7 @@ void MainViewTrim::checkEvents()
|
||||
{
|
||||
Window::checkEvents();
|
||||
int8_t stickIndex = CONVERT_MODE(idx);
|
||||
int8_t newValue = getTrimValue(mixerCurrentFlightMode, stickIndex);
|
||||
int newValue = getTrimValue(mixerCurrentFlightMode, stickIndex);
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
invalidate();
|
||||
@@ -43,6 +43,10 @@ void MainViewHorizontalTrim::paint(BitmapBuffer * dc)
|
||||
trimMin = TRIM_MIN;
|
||||
trimMax = TRIM_MAX;
|
||||
}
|
||||
|
||||
int16_t dispVal = value;
|
||||
if (dispVal < trimMin) dispVal = trimMin;
|
||||
if (dispVal > trimMax) dispVal = trimMax;
|
||||
|
||||
// Trim line
|
||||
dc->drawSolidFilledRect(
|
||||
@@ -50,7 +54,7 @@ void MainViewHorizontalTrim::paint(BitmapBuffer * dc)
|
||||
width() - TRIM_SQUARE_SIZE + 1, TRIM_LINE_WIDTH, DEFAULT_COLOR);
|
||||
|
||||
// Trim square
|
||||
coord_t x = divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value - trimMin),
|
||||
coord_t x = divRoundClosest((width() - TRIM_SQUARE_SIZE) * (dispVal - trimMin),
|
||||
trimMax - trimMin);
|
||||
drawTrimSquare(dc, x, 0,
|
||||
(value < TRIM_MIN || value > TRIM_MAX)
|
||||
@@ -85,15 +89,20 @@ void MainViewVerticalTrim::paint(BitmapBuffer * dc)
|
||||
trimMax = TRIM_MAX;
|
||||
}
|
||||
|
||||
int16_t dispVal = value;
|
||||
if (dispVal < trimMin) dispVal = trimMin;
|
||||
if (dispVal > trimMax) dispVal = trimMax;
|
||||
|
||||
// Trim line
|
||||
dc->drawSolidFilledRect((width() - TRIM_LINE_WIDTH) / 2, TRIM_SQUARE_SIZE / 2,
|
||||
TRIM_LINE_WIDTH, height() - TRIM_SQUARE_SIZE + 1,
|
||||
DEFAULT_COLOR);
|
||||
|
||||
// Trim square
|
||||
coord_t y = height() - TRIM_SQUARE_SIZE -
|
||||
divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value - trimMin),
|
||||
trimMax - trimMin);
|
||||
coord_t y =
|
||||
height() - TRIM_SQUARE_SIZE -
|
||||
divRoundClosest((height() - TRIM_SQUARE_SIZE) * (dispVal - trimMin),
|
||||
trimMax - trimMin);
|
||||
drawTrimSquare(dc, 0, y,
|
||||
(value < TRIM_MIN || value > TRIM_MAX)
|
||||
? HIGHLIGHT_COLOR /* TODO add a color */
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "model_gvars.h"
|
||||
#include "model_curves.h"
|
||||
#include "model_logical_switches.h"
|
||||
#include "model_mixer_scripts.h"
|
||||
#include "special_functions.h"
|
||||
#include "model_telemetry.h"
|
||||
|
||||
@@ -47,5 +48,8 @@ ModelMenu::ModelMenu():
|
||||
addTab(new ModelGVarsPage());
|
||||
addTab(new ModelLogicalSwitchesPage());
|
||||
addTab(new SpecialFunctionsPage(g_model.customFn));
|
||||
#if defined(LUA)
|
||||
addTab(new ModelMixerScriptsPage());
|
||||
#endif
|
||||
addTab(new ModelTelemetryPage());
|
||||
}
|
||||
|
||||
@@ -56,20 +56,19 @@ void copyExpo(uint8_t source, uint8_t dest, int8_t input)
|
||||
pauseMixerCalculations();
|
||||
ExpoData sourceExpo;
|
||||
memcpy(&sourceExpo, expoAddress(source), sizeof(ExpoData));
|
||||
ExpoData * expo = expoAddress(dest);
|
||||
|
||||
if(input == PASTE_AFTER) {
|
||||
memmove(expo+2, expo+1, (MAX_EXPOS-(source+1))*sizeof(ExpoData));
|
||||
memcpy(expo+1, &sourceExpo, sizeof(ExpoData));
|
||||
(expo+1)->chn = (expo)->chn;
|
||||
}
|
||||
else if(input == PASTE_BEFORE) {
|
||||
memmove(expo+1, expo, (MAX_EXPOS-(source+1))*sizeof(ExpoData));
|
||||
ExpoData *expo = expoAddress(dest);
|
||||
size_t trailingExpos = MAX_EXPOS - (dest + 1);
|
||||
if (input == PASTE_AFTER) {
|
||||
trailingExpos--;
|
||||
memmove(expo + 2, expo + 1, trailingExpos * sizeof(ExpoData));
|
||||
memcpy(expo + 1, &sourceExpo, sizeof(ExpoData));
|
||||
(expo + 1)->chn = (expo)->chn;
|
||||
} else if (input == PASTE_BEFORE) {
|
||||
memmove(expo + 1, expo, trailingExpos * sizeof(ExpoData));
|
||||
memcpy(expo, &sourceExpo, sizeof(ExpoData));
|
||||
expo->chn = (expo+1)->chn;
|
||||
}
|
||||
else {
|
||||
memmove(expo+1, expo, (MAX_EXPOS-(source+1))*sizeof(ExpoData));
|
||||
expo->chn = (expo + 1)->chn;
|
||||
} else {
|
||||
memmove(expo + 1, expo, trailingExpos * sizeof(ExpoData));
|
||||
memcpy(expo, &sourceExpo, sizeof(ExpoData));
|
||||
expo->chn = input;
|
||||
}
|
||||
|
||||
@@ -144,14 +144,14 @@ class LogicalSwitchEditPage: public Page
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V1);
|
||||
auto timer = new NumberEdit(logicalSwitchOneWindow, grid.getFieldSlot(), -128, 122, GET_SET_DEFAULT(cs->v1));
|
||||
timer->setDisplayHandler([](BitmapBuffer * dc, LcdFlags flags, int32_t value) {
|
||||
dc->drawNumber(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, lswTimerValue(value), flags | PREC1);
|
||||
drawTimer(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, value, flags);
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
new StaticText(logicalSwitchOneWindow, grid.getLabelSlot(), STR_V2);
|
||||
timer = new NumberEdit(logicalSwitchOneWindow, grid.getFieldSlot(), -128, 122, GET_SET_DEFAULT(cs->v2));
|
||||
timer->setDisplayHandler([](BitmapBuffer * dc, LcdFlags flags, int32_t value) {
|
||||
dc->drawNumber(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, lswTimerValue(value), flags | PREC1);
|
||||
drawTimer(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, value, flags);
|
||||
});
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* 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"
|
||||
|
||||
#include "model_mixer_scripts.h"
|
||||
#include "dataconstants.h"
|
||||
#include "lua/lua_api.h"
|
||||
|
||||
#include "translations.h"
|
||||
#include "menus.h"
|
||||
#include "libopenui.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
class ScriptEditWindow : public Page {
|
||||
public:
|
||||
explicit ScriptEditWindow(uint8_t idx) :
|
||||
Page(ICON_MODEL_LUA_SCRIPTS),
|
||||
idx(idx)
|
||||
{
|
||||
buildBody(&body);
|
||||
buildHeader(&header);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t idx;
|
||||
bool update = false;
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
if (update) {
|
||||
TRACE("rebuilding ScriptEditWindow...");
|
||||
rebuildBody(&body);
|
||||
update = false;
|
||||
}
|
||||
// note: 'update' is set from Page::checkEvents()
|
||||
Page::checkEvents();
|
||||
}
|
||||
|
||||
void buildHeader(Window * window)
|
||||
{
|
||||
new StaticText(window,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
|
||||
PAGE_LINE_HEIGHT},
|
||||
STR_MENUCUSTOMSCRIPTS, 0, FOCUS_COLOR);
|
||||
new StaticText(window,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
|
||||
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
|
||||
std::string("LUA") + std::to_string(idx + 1), 0, FOCUS_COLOR);
|
||||
}
|
||||
|
||||
void buildBody(FormWindow * window, bool focusScript = false)
|
||||
{
|
||||
FormGridLayout grid;
|
||||
grid.spacer(PAGE_PADDING);
|
||||
|
||||
ScriptData* sd = &(g_model.scriptsData[idx]);
|
||||
|
||||
// Filename
|
||||
new StaticText(window, grid.getLabelSlot(), STR_SCRIPT);
|
||||
auto fc = new FileChoice(
|
||||
window, grid.getFieldSlot(), SCRIPTS_MIXES_PATH, SCRIPTS_EXT,
|
||||
LEN_SCRIPT_FILENAME,
|
||||
[=]() { return std::string(sd->file, LEN_SCRIPT_FILENAME); },
|
||||
[=](std::string newValue) {
|
||||
strncpy(sd->file, newValue.c_str(), LEN_SCRIPT_FILENAME);
|
||||
if (newValue.empty()) { memset((void*)sd, 0, sizeof(ScriptData)); }
|
||||
storageDirty(EE_MODEL);
|
||||
LUA_LOAD_MODEL_SCRIPT(idx); // async reload...
|
||||
update = true;
|
||||
}, true);
|
||||
grid.nextLine();
|
||||
|
||||
// Custom name
|
||||
new StaticText(window, grid.getLabelSlot(), STR_NAME);
|
||||
new ModelTextEdit(window, grid.getFieldSlot(), sd->name, sizeof(sd->name));
|
||||
grid.nextLine();
|
||||
|
||||
// scriptInputsOutputs
|
||||
ScriptInputsOutputs& sio = scriptInputsOutputs[idx];
|
||||
|
||||
if (sio.inputsCount > 0) {
|
||||
new Subtitle(window, grid.getLineSlot(), STR_INPUTS);
|
||||
grid.nextLine();
|
||||
|
||||
auto gInputs =
|
||||
new FormGroup(window, grid.getFieldSlot(),
|
||||
FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
|
||||
GridLayout inputsGrid(gInputs);
|
||||
|
||||
for (int i = 0; i < sio.inputsCount; i++) {
|
||||
ScriptInput& si = sio.inputs[i];
|
||||
new StaticText(window, grid.getLabelSlot(true), si.name);
|
||||
grid.nextLine();
|
||||
if (si.type == INPUT_TYPE_VALUE) {
|
||||
new NumberEdit(gInputs, inputsGrid.getSlot(), si.min - si.def,
|
||||
si.max - si.def,
|
||||
GET_SET_WITH_OFFSET(sd->inputs[i].value, si.def));
|
||||
} else {
|
||||
new SourceChoice(gInputs, inputsGrid.getSlot(), 0,
|
||||
MIXSRC_LAST_TELEM,
|
||||
GET_SET_DEFAULT(sd->inputs[i].source));
|
||||
}
|
||||
inputsGrid.nextLine();
|
||||
}
|
||||
gInputs->setHeight(inputsGrid.getWindowHeight());
|
||||
}
|
||||
|
||||
if (sio.outputsCount > 0) {
|
||||
new Subtitle(window, grid.getLabelSlot(), STR_OUTPUTS);
|
||||
grid.nextLine();
|
||||
|
||||
auto gOutputs =
|
||||
new FormGroup(window, grid.getLineSlot(),
|
||||
FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
|
||||
FormGridLayout outputsGrid(gOutputs->width());
|
||||
|
||||
for (int i = 0; i < sio.outputsCount; i++) {
|
||||
ScriptOutput* so = &(sio.outputs[i]);
|
||||
new DynamicText(gOutputs, outputsGrid.getLabelSlot(), [=]() {
|
||||
char s[16];
|
||||
getSourceString(s,
|
||||
MIXSRC_FIRST_LUA + (idx * MAX_SCRIPT_OUTPUTS) + i);
|
||||
return std::string(s, sizeof(s) - 1);
|
||||
});
|
||||
new DynamicNumber<int>(gOutputs, outputsGrid.getFieldSlot(),
|
||||
[=]() { return calcRESXto1000(so->value); });
|
||||
|
||||
outputsGrid.nextLine();
|
||||
}
|
||||
gOutputs->setHeight(outputsGrid.getWindowHeight());
|
||||
grid.addWindow(gOutputs);
|
||||
}
|
||||
|
||||
window->setInnerHeight(grid.getWindowHeight());
|
||||
if (focusScript) { fc->setFocus(); }
|
||||
}
|
||||
|
||||
void rebuildBody(FormWindow * window)
|
||||
{
|
||||
coord_t scrollPosition = window->getScrollPositionY();
|
||||
window->clear();
|
||||
buildBody(window);
|
||||
window->setScrollPositionY(scrollPosition);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr char SCRIPT_STATUS_ERROR[] = "(error)";
|
||||
constexpr char SCRIPT_STATUS_KILLED[] = "(killed)";
|
||||
|
||||
class ScriptLineButton : public Button
|
||||
{
|
||||
public:
|
||||
ScriptLineButton(FormGroup* parent, const rect_t& rect,
|
||||
const ScriptData& scriptData,
|
||||
const ScriptInternalData* runtimeData) :
|
||||
Button(parent, rect), scriptData(scriptData), runtimeData(runtimeData)
|
||||
{
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer* dc) override
|
||||
{
|
||||
LcdFlags textColor = DEFAULT_COLOR;
|
||||
LcdFlags bgColor = FIELD_BGCOLOR;
|
||||
|
||||
dc->drawSolidFilledRect(0, 0, width(), height(), bgColor);
|
||||
|
||||
if (runtimeData) {
|
||||
coord_t x = 2*FIELD_PADDING_LEFT;
|
||||
coord_t y = FIELD_PADDING_TOP;
|
||||
|
||||
x = dc->drawSizedText(x, y, scriptData.name, sizeof(scriptData.name), textColor);
|
||||
x += 4*FIELD_PADDING_LEFT;
|
||||
|
||||
dc->drawSizedText(x, y, scriptData.file, sizeof(scriptData.file), textColor);
|
||||
|
||||
x = width() - 2*FIELD_PADDING_LEFT;
|
||||
y = FIELD_PADDING_TOP;
|
||||
textColor |= RIGHT;
|
||||
|
||||
switch (runtimeData->state) {
|
||||
case SCRIPT_SYNTAX_ERROR:
|
||||
dc->drawSizedText(x, y, SCRIPT_STATUS_ERROR,
|
||||
sizeof(SCRIPT_STATUS_ERROR), textColor);
|
||||
break;
|
||||
case SCRIPT_KILLED:
|
||||
dc->drawSizedText(x, y, SCRIPT_STATUS_KILLED,
|
||||
sizeof(SCRIPT_STATUS_KILLED), textColor);
|
||||
break;
|
||||
default:
|
||||
dc->drawNumber(x, y, runtimeData->instructions, textColor, 0, nullptr, "%");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// bounding rect
|
||||
if (hasFocus())
|
||||
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, FOCUS_BGCOLOR);
|
||||
else
|
||||
dc->drawSolidRect(0, 0, rect.w, rect.h, 1, FIELD_FRAME_COLOR);
|
||||
}
|
||||
|
||||
protected:
|
||||
const ScriptData& scriptData;
|
||||
const ScriptInternalData* runtimeData;
|
||||
};
|
||||
|
||||
ModelMixerScriptsPage::ModelMixerScriptsPage() :
|
||||
PageTab(STR_MENUCUSTOMSCRIPTS, ICON_MODEL_LUA_SCRIPTS)
|
||||
{
|
||||
}
|
||||
|
||||
void ModelMixerScriptsPage::rebuild(FormWindow * window, int8_t focusIdx)
|
||||
{
|
||||
coord_t scrollPosition = window->getScrollPositionY();
|
||||
window->clear();
|
||||
build(window, focusIdx);
|
||||
window->setScrollPositionY(scrollPosition);
|
||||
}
|
||||
|
||||
void ModelMixerScriptsPage::build(FormWindow * window, int8_t focusIdx)
|
||||
{
|
||||
FormGridLayout grid;
|
||||
grid.spacer(PAGE_PADDING);
|
||||
grid.setLabelWidth(66);
|
||||
|
||||
int8_t scriptIdx = 0;
|
||||
for (int8_t idx = 0; idx < MAX_SCRIPTS; idx++) {
|
||||
|
||||
ScriptInternalData* runtimeData = nullptr;
|
||||
ScriptData &sd = g_model.scriptsData[idx];
|
||||
|
||||
if (sd.file[0] != '\0') {
|
||||
runtimeData = &(scriptInternalData[scriptIdx++]);
|
||||
}
|
||||
|
||||
// LUAx label
|
||||
auto txt = new StaticText(window, grid.getLabelSlot(),
|
||||
std::string("LUA") + std::to_string(idx + 1),
|
||||
BUTTON_BACKGROUND, CENTERED);
|
||||
|
||||
Button* button = new ScriptLineButton(window, grid.getFieldSlot(), sd, runtimeData);
|
||||
|
||||
button->setPressHandler([=]() -> uint8_t {
|
||||
Menu* menu = new Menu(window);
|
||||
menu->addLine(STR_EDIT, [=]() { editLine(window, idx); });
|
||||
|
||||
if (runtimeData != nullptr) {
|
||||
menu->addLine(STR_RESET, [=]() {
|
||||
memset((void*)&sd, 0, sizeof(sd));
|
||||
// TODO: anything else? reload scripts???
|
||||
storageDirty(EE_MODEL);
|
||||
rebuild(window, idx);
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
button->setFocusHandler([=](bool focus) {
|
||||
if (focus) {
|
||||
txt->setBackgroundColor(FOCUS_BGCOLOR);
|
||||
txt->setTextFlags(FOCUS_COLOR | CENTERED);
|
||||
} else {
|
||||
txt->setBackgroundColor(FIELD_FRAME_COLOR);
|
||||
txt->setTextFlags(CENTERED);
|
||||
}
|
||||
txt->invalidate();
|
||||
});
|
||||
|
||||
if (focusIdx == idx) {
|
||||
button->setFocus(SET_FOCUS_DEFAULT);
|
||||
txt->setBackgroundColor(FOCUS_BGCOLOR);
|
||||
txt->setTextFlags(FOCUS_COLOR | CENTERED);
|
||||
txt->invalidate();
|
||||
}
|
||||
|
||||
txt->setHeight(button->height());
|
||||
grid.spacer(button->height() + 5);
|
||||
}
|
||||
|
||||
grid.nextLine();
|
||||
window->setInnerHeight(grid.getWindowHeight());
|
||||
}
|
||||
|
||||
void ModelMixerScriptsPage::editLine(FormWindow * window, uint8_t idx)
|
||||
{
|
||||
Window::clearFocus();
|
||||
Window * editWindow = new ScriptEditWindow(idx);
|
||||
editWindow->setCloseHandler([=]() {
|
||||
rebuild(window, idx);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tabsgroup.h"
|
||||
|
||||
class ModelMixerScriptsPage: public PageTab {
|
||||
public:
|
||||
ModelMixerScriptsPage();
|
||||
|
||||
virtual void build(FormWindow * window) override
|
||||
{
|
||||
build(window, 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
void build(FormWindow * window, int8_t focusIdx);
|
||||
void rebuild(FormWindow * window, int8_t focusIdx);
|
||||
void editLine(FormWindow * window, uint8_t idx);
|
||||
};
|
||||
@@ -89,7 +89,7 @@ class MixEditWindow : public Page
|
||||
|
||||
// Mix name
|
||||
new StaticText(window, grid.getLabelSlot(), STR_MIXNAME);
|
||||
new RadioTextEdit(window, grid.getFieldSlot(), mix->name,
|
||||
new ModelTextEdit(window, grid.getFieldSlot(), mix->name,
|
||||
sizeof(mix->name));
|
||||
grid.nextLine();
|
||||
|
||||
@@ -531,24 +531,22 @@ void copyMix(uint8_t source, uint8_t dest, int8_t ch)
|
||||
pauseMixerCalculations();
|
||||
MixData sourceMix;
|
||||
memcpy(&sourceMix, mixAddress(source), sizeof(MixData));
|
||||
MixData * mix = mixAddress(dest);
|
||||
if(ch == PASTE_AFTER) {
|
||||
memmove(mix+2, mix+1, (MAX_MIXERS-(source+1))*sizeof(MixData));
|
||||
memcpy(mix+1, &sourceMix, sizeof(MixData));
|
||||
(mix+1)->destCh = (mix)->destCh;
|
||||
}
|
||||
else if(ch == PASTE_BEFORE) {
|
||||
memmove(mix+1, mix, (MAX_MIXERS-(source+1))*sizeof(MixData));
|
||||
MixData *mix = mixAddress(dest);
|
||||
size_t trailingMixes = MAX_MIXERS - (dest + 1);
|
||||
if (ch == PASTE_AFTER) {
|
||||
trailingMixes--;
|
||||
memmove(mix + 2, mix + 1, trailingMixes * sizeof(MixData));
|
||||
memcpy(mix + 1, &sourceMix, sizeof(MixData));
|
||||
(mix + 1)->destCh = (mix)->destCh;
|
||||
} else if (ch == PASTE_BEFORE) {
|
||||
memmove(mix + 1, mix, trailingMixes * sizeof(MixData));
|
||||
memcpy(mix, &sourceMix, sizeof(MixData));
|
||||
mix->destCh = (mix+1)->destCh;
|
||||
}
|
||||
else {
|
||||
memmove(mix+1, mix, (MAX_MIXERS-(source+1))*sizeof(MixData));
|
||||
mix->destCh = (mix + 1)->destCh;
|
||||
} else {
|
||||
memmove(mix + 1, mix, trailingMixes * sizeof(MixData));
|
||||
memcpy(mix, &sourceMix, sizeof(MixData));
|
||||
mix->destCh = ch;
|
||||
mix->destCh = ch;
|
||||
}
|
||||
|
||||
//memmove(mix + 1, mix, (MAX_MIXERS - (dest + 1)) * sizeof(MixData));
|
||||
resumeMixerCalculations();
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class OutputEditWindow : public Page {
|
||||
|
||||
// Name
|
||||
new StaticText(window, grid.getLabelSlot(), STR_NAME);
|
||||
new RadioTextEdit(window, grid.getFieldSlot(), output->name, sizeof(output->name));
|
||||
new ModelTextEdit(window, grid.getFieldSlot(), output->name, sizeof(output->name));
|
||||
grid.nextLine();
|
||||
|
||||
// Offset
|
||||
@@ -130,7 +130,7 @@ class OutputLineButton : public Button {
|
||||
LcdFlags bgColor = FIELD_BGCOLOR;
|
||||
|
||||
dc->drawSolidFilledRect(0, 0, width(), height(), bgColor);
|
||||
|
||||
|
||||
// first line
|
||||
dc->drawNumber(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, output->min - 1000,
|
||||
PREC1 | textColor);
|
||||
|
||||
@@ -245,7 +245,8 @@ class ModelCategoryPageBody : public FormWindow
|
||||
|
||||
modelslist.setCurrentModel(model);
|
||||
modelslist.setCurrentCategory(category);
|
||||
update();
|
||||
this->onEvent(EVT_KEY_FIRST(KEY_EXIT));
|
||||
checkAll();
|
||||
});
|
||||
}
|
||||
menu->addLine(STR_CREATE_MODEL, getCreateModelAction());
|
||||
|
||||
@@ -630,22 +630,42 @@ class ModuleWindow : public FormGroup {
|
||||
|
||||
// Multi type (CUSTOM, brand A, brand B,...)
|
||||
int multiRfProto = g_model.moduleData[moduleIdx].getMultiProtocol();
|
||||
rfChoice = new Choice(this, grid.getFieldSlot(g_model.moduleData[moduleIdx].multi.customProto ? 3 : 2, 0), STR_MULTI_PROTOCOLS, MODULE_SUBTYPE_MULTI_FIRST, MODULE_SUBTYPE_MULTI_LAST,
|
||||
GET_DEFAULT(multiRfProto),
|
||||
[=](int32_t newValue) {
|
||||
g_model.moduleData[moduleIdx].setMultiProtocol(newValue);
|
||||
g_model.moduleData[moduleIdx].subType = 0;
|
||||
if (mmSubProtocol != nullptr) mmSubProtocol->invalidate();
|
||||
resetMultiProtocolsOptions(moduleIdx);
|
||||
SET_DIRTY();
|
||||
update();
|
||||
rfChoice->setFocus(SET_FOCUS_DEFAULT);
|
||||
});
|
||||
rfChoice = new Choice(
|
||||
this,
|
||||
grid.getFieldSlot(
|
||||
g_model.moduleData[moduleIdx].multi.customProto ? 3 : 2, 0),
|
||||
STR_MULTI_PROTOCOLS, MODULE_SUBTYPE_MULTI_FIRST,
|
||||
MODULE_SUBTYPE_MULTI_LAST, GET_DEFAULT(multiRfProto),
|
||||
[=](int32_t newValue) {
|
||||
g_model.moduleData[moduleIdx].setMultiProtocol(newValue);
|
||||
g_model.moduleData[moduleIdx].subType = 0;
|
||||
if (mmSubProtocol != nullptr) mmSubProtocol->invalidate(); // always null ???
|
||||
resetMultiProtocolsOptions(moduleIdx);
|
||||
SET_DIRTY();
|
||||
update();
|
||||
rfChoice->setFocus(SET_FOCUS_DEFAULT);// really valid ???
|
||||
});
|
||||
|
||||
// Subtype (D16, DSMX,...)
|
||||
const mm_protocol_definition * pdef = getMultiProtocolDefinition(g_model.moduleData[moduleIdx].getMultiProtocol());
|
||||
if (pdef->maxSubtype > 0)
|
||||
mmSubProtocol = new Choice(this, grid.getFieldSlot(2, 1), pdef->subTypeString, 0, pdef->maxSubtype,GET_SET_DEFAULT(g_model.moduleData[moduleIdx].subType));
|
||||
if (MULTIMODULE_HAS_SUBTYPE(moduleIdx)) {
|
||||
// Subtype (D16, DSMX,...)
|
||||
const mm_protocol_definition *pdef = getMultiProtocolDefinition(
|
||||
g_model.moduleData[moduleIdx].getMultiProtocol());
|
||||
if (pdef->maxSubtype > 0) {
|
||||
mmSubProtocol = new Choice(
|
||||
this, grid.getFieldSlot(2, 1), pdef->subTypeString, 0,
|
||||
pdef->maxSubtype,
|
||||
[=]() { return g_model.moduleData[moduleIdx].subType; },
|
||||
[=](int16_t newValue) {
|
||||
g_model.moduleData[moduleIdx].subType = newValue;
|
||||
resetMultiProtocolsOptions(moduleIdx);
|
||||
SET_DIRTY();
|
||||
// update(); ??? how to set focus properly ???
|
||||
update();
|
||||
//mmSubProtocol->setFocus(SET_FOCUS_DEFAULT);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
grid.nextLine();
|
||||
|
||||
// Multimodule status
|
||||
@@ -664,46 +684,122 @@ class ModuleWindow : public FormGroup {
|
||||
new StaticText(this, grid.getFieldSlot(), statusText);
|
||||
}*/
|
||||
|
||||
// Multi optional feature row
|
||||
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
|
||||
if (pdef->optionsstr) {
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), pdef->optionsstr);
|
||||
if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
|
||||
auto edit = new NumberEdit(this, grid.getFieldSlot(2,0), 50, 400,
|
||||
GET_DEFAULT(50 + 5 * g_model.moduleData[moduleIdx].multi.optionValue),
|
||||
SET_VALUE(g_model.moduleData[moduleIdx].multi.optionValue, (newValue- 50) / 5));
|
||||
edit->setStep(5);
|
||||
}
|
||||
else if (multi_proto == MODULE_SUBTYPE_MULTI_OLRS) {
|
||||
new NumberEdit(this, grid.getFieldSlot(2,0), -1, 7, GET_SET_DEFAULT(g_model.moduleData[moduleIdx].multi.optionValue));
|
||||
}
|
||||
else {
|
||||
new NumberEdit(this, grid.getFieldSlot(2,0), -128, 127, GET_SET_DEFAULT(g_model.moduleData[moduleIdx].multi.optionValue));
|
||||
if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) {
|
||||
// Multi optional feature row
|
||||
const char *title = getMultiOptionTitleStatic(moduleIdx);
|
||||
if (title != nullptr) {
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), title);
|
||||
|
||||
//Show RSSI next to RF Freq Fine Tune
|
||||
if (getMultiOptionTitle(moduleIdx) == STR_MULTI_RFTUNE)
|
||||
{
|
||||
new DynamicNumber<int>(this, grid.getFieldSlot(2, 1), [] {
|
||||
return (int)TELEMETRY_RSSI();}, 0, "RSSI: ", " db");
|
||||
// int optionValue =
|
||||
// g_model.moduleData[moduleIdx].multi.optionValue;
|
||||
int8_t min, max;
|
||||
getMultiOptionValues(multi_proto, min, max);
|
||||
|
||||
if (title == STR_MULTI_RFPOWER) {
|
||||
new Choice(this, grid.getFieldSlot(2, 0), STR_MULTI_POWER, 0, 15,
|
||||
GET_SET_DEFAULT(
|
||||
g_model.moduleData[moduleIdx].multi.optionValue));
|
||||
} else if (title == STR_MULTI_TELEMETRY) {
|
||||
new Choice(this, grid.getFieldSlot(2, 0),
|
||||
STR_MULTI_TELEMETRY_MODE, min, max,
|
||||
GET_SET_DEFAULT(
|
||||
g_model.moduleData[moduleIdx].multi.optionValue));
|
||||
} else if (title == STR_MULTI_WBUS) {
|
||||
new Choice(this, grid.getFieldSlot(2, 0), STR_MULTI_WBUS_MODE, 0,
|
||||
1,
|
||||
GET_SET_DEFAULT(
|
||||
g_model.moduleData[moduleIdx].multi.optionValue));
|
||||
} else if (multi_proto == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) {
|
||||
auto edit = new NumberEdit(
|
||||
this, grid.getFieldSlot(2, 0), 50, 400,
|
||||
GET_DEFAULT(
|
||||
50 + 5 * g_model.moduleData[moduleIdx].multi.optionValue),
|
||||
SET_VALUE(g_model.moduleData[moduleIdx].multi.optionValue,
|
||||
(newValue - 50) / 5));
|
||||
edit->setStep(5);
|
||||
} else if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
|
||||
new CheckBox(
|
||||
this, grid.getFieldSlot(2, 0),
|
||||
[=]() {
|
||||
return g_model.moduleData[moduleIdx].multi.optionValue &
|
||||
0x01;
|
||||
},
|
||||
[=](int16_t newValue) {
|
||||
g_model.moduleData[moduleIdx].multi.optionValue =
|
||||
(g_model.moduleData[moduleIdx].multi.optionValue &
|
||||
0xFE) +
|
||||
newValue;
|
||||
});
|
||||
} else {
|
||||
if (min == 0 && max == 1) {
|
||||
new CheckBox(
|
||||
this, grid.getFieldSlot(2, 0),
|
||||
GET_SET_DEFAULT(
|
||||
g_model.moduleData[moduleIdx].multi.optionValue));
|
||||
} else {
|
||||
new NumberEdit(
|
||||
this, grid.getFieldSlot(2, 0), -128, 127,
|
||||
GET_SET_DEFAULT(
|
||||
g_model.moduleData[moduleIdx].multi.optionValue));
|
||||
|
||||
// Show RSSI next to RF Freq Fine Tune
|
||||
if (title == STR_MULTI_RFTUNE) {
|
||||
new DynamicNumber<int>(
|
||||
this, grid.getFieldSlot(2, 1),
|
||||
[] { return (int)TELEMETRY_RSSI(); }, 0, "RSSI: ", " db");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bind on power up
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true),g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2 ? STR_MULTI_DSM_AUTODTECT : STR_MULTI_AUTOBIND);
|
||||
new CheckBox(this, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.moduleData[moduleIdx].multi.autoBindMode));
|
||||
|
||||
if (multi_proto == MODULE_SUBTYPE_MULTI_DSM2) {
|
||||
|
||||
const char* servoRates[] = { "22ms", "11ms" };
|
||||
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_MULTI_SERVOFREQ);
|
||||
new Choice(
|
||||
this, grid.getFieldSlot(), servoRates, 0, 1,
|
||||
[=]() {
|
||||
return (g_model.moduleData[moduleIdx].multi.optionValue & 0x02) >> 1;
|
||||
},
|
||||
[=](int16_t newValue) {
|
||||
g_model.moduleData[moduleIdx].multi.optionValue =
|
||||
(g_model.moduleData[moduleIdx].multi.optionValue & 0xFD) +
|
||||
(newValue << 1);
|
||||
});
|
||||
} else {
|
||||
// Bind on power up
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_MULTI_AUTOBIND);
|
||||
new CheckBox(this, grid.getFieldSlot(),
|
||||
GET_SET_DEFAULT(
|
||||
g_model.moduleData[moduleIdx].multi.autoBindMode));
|
||||
}
|
||||
|
||||
// Low power mode
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_MULTI_LOWPOWER);
|
||||
new CheckBox(this, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.moduleData[moduleIdx].multi.lowPowerMode));
|
||||
new CheckBox(
|
||||
this, grid.getFieldSlot(),
|
||||
GET_SET_DEFAULT(g_model.moduleData[moduleIdx].multi.lowPowerMode));
|
||||
|
||||
// Disable telemetry
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_DISABLE_TELEM);
|
||||
new CheckBox(this, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.moduleData[moduleIdx].multi.disableMapping));
|
||||
new CheckBox(this, grid.getFieldSlot(),
|
||||
GET_SET_DEFAULT(
|
||||
g_model.moduleData[moduleIdx].multi.disableTelemetry));
|
||||
|
||||
if (MULTI_DISABLE_CHAN_MAP_ROW_STATIC(moduleIdx) != HIDDEN_ROW) {
|
||||
// Disable channel mapping
|
||||
grid.nextLine();
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_DISABLE_CH_MAP);
|
||||
new CheckBox(this, grid.getFieldSlot(),
|
||||
GET_SET_DEFAULT(g_model.moduleData[moduleIdx].multi.disableMapping));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(AFHDS3)
|
||||
@@ -1021,15 +1117,16 @@ void ModelSetupPage::build(FormWindow * window)
|
||||
|
||||
// Model name
|
||||
new StaticText(window, grid.getLabelSlot(), STR_MODELNAME);
|
||||
auto text = new RadioTextEdit(window, grid.getFieldSlot(), g_model.header.name, sizeof(g_model.header.name),
|
||||
0, MODEL_NAME_EXTRA_CHARS);
|
||||
auto text =
|
||||
new ModelTextEdit(window, grid.getFieldSlot(), g_model.header.name,
|
||||
sizeof(g_model.header.name), 0, MODEL_NAME_EXTRA_CHARS);
|
||||
text->setChangeHandler([=] {
|
||||
modelslist.load();
|
||||
auto model = modelslist.getCurrentModel();
|
||||
if (model) {
|
||||
model->setModelName(g_model.header.name);
|
||||
}
|
||||
SET_DIRTY();
|
||||
modelslist.load();
|
||||
auto model = modelslist.getCurrentModel();
|
||||
if (model) {
|
||||
model->setModelName(g_model.header.name);
|
||||
}
|
||||
SET_DIRTY();
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
@@ -1139,7 +1236,17 @@ void ModelSetupPage::build(FormWindow * window)
|
||||
|
||||
// Throttle source
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_TTRACE);
|
||||
new SourceChoice(window, grid.getFieldSlot(), 0, MIXSRC_LAST_CH, GET_SET_DEFAULT(g_model.thrTraceSrc));
|
||||
auto sc = new SourceChoice(
|
||||
window, grid.getFieldSlot(), 0, MIXSRC_LAST_CH,
|
||||
[=]() { return throttleSource2Source(g_model.thrTraceSrc); },
|
||||
[=](int16_t src) {
|
||||
int16_t val = source2ThrottleSource(src);
|
||||
if (val >= 0) {
|
||||
g_model.thrTraceSrc = val;
|
||||
SET_DIRTY();
|
||||
}
|
||||
});
|
||||
sc->setAvailableHandler(isThrottleSourceAvailable);
|
||||
grid.nextLine();
|
||||
|
||||
// Throttle trim
|
||||
@@ -1149,7 +1256,10 @@ void ModelSetupPage::build(FormWindow * window)
|
||||
|
||||
// Throttle trim source
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_TTRIM_SW);
|
||||
new SourceChoice(window, grid.getFieldSlot(), 0, NUM_TRIMS - 1, GET_SET_DEFAULT( g_model.thrTrimSw));
|
||||
new SourceChoice(
|
||||
window, grid.getFieldSlot(), MIXSRC_FIRST_TRIM, MIXSRC_LAST_TRIM,
|
||||
[=]() { return g_model.getThrottleStickTrimSource(); },
|
||||
[=](int16_t src) { g_model.setThrottleStickTrimSource(src); });
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
|
||||
@@ -32,19 +32,19 @@ class DebugInfoNumber : public Window
|
||||
public:
|
||||
DebugInfoNumber(Window * parent, const rect_t & rect, std::function<T()> numberHandler, LcdFlags textFlags = 0, const char * prefix = nullptr, const char * suffix = nullptr):
|
||||
Window(parent, rect, 0, textFlags),
|
||||
numberHandler(std::move(numberHandler)),
|
||||
prefix(prefix),
|
||||
suffix(suffix)
|
||||
{
|
||||
coord_t prefixSize = getTextWidth(prefix, 0, HEADER_COLOR | FONT(XS));
|
||||
new StaticText(this, {0, 0, prefixSize, rect.h}, prefix, 0, HEADER_COLOR | FONT(XS));
|
||||
new DynamicNumber<uint32_t>(this, {prefixSize, 0, rect.w - prefixSize, rect.h}, [] {
|
||||
return menusStack.available();
|
||||
});
|
||||
coord_t prefixSize = 0;
|
||||
if (prefix != nullptr) {
|
||||
prefixSize = getTextWidth(prefix, 0, HEADER_COLOR | FONT(XS));
|
||||
new StaticText(this, {0, 0, prefixSize, rect.h}, prefix, 0, HEADER_COLOR | FONT(XS));
|
||||
}
|
||||
new DynamicNumber<uint32_t>(this, {prefixSize, 0, rect.w - prefixSize, rect.h},
|
||||
numberHandler);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::function<T()> numberHandler;
|
||||
const char * prefix;
|
||||
const char * suffix;
|
||||
};
|
||||
|
||||
@@ -75,13 +75,13 @@ class ViewTextWindow : public Page
|
||||
}
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer* dc)
|
||||
void paint(BitmapBuffer* dc) override
|
||||
{
|
||||
Page::paint(dc);
|
||||
drawVerticalScrollbar(dc);
|
||||
}
|
||||
#endif
|
||||
virtual void checkEvents();
|
||||
void checkEvents() override;
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override { return "ViewTextWindow"; };
|
||||
@@ -123,4 +123,4 @@ bool isInSetup;
|
||||
};
|
||||
};
|
||||
|
||||
void readModelNotes();
|
||||
void readModelNotes();
|
||||
|
||||
@@ -75,7 +75,7 @@ class OutputsWidget: public Widget
|
||||
dc->drawSizedText(barLft + 23, barTop, g_model.limitData[curChan - 1].name, sizeof(g_model.limitData[curChan - 1].name), FONT(XS) | DEFAULT_COLOR | LEFT);
|
||||
}
|
||||
else {
|
||||
drawSource(dc, barLft + 1, barTop, curChan, FONT(XS) | DEFAULT_COLOR | LEFT);
|
||||
drawSource(dc, barLft + 1, barTop, MIXSRC_FIRST_CH+curChan-1, FONT(XS) | DEFAULT_COLOR | LEFT);
|
||||
}
|
||||
}
|
||||
return lastChan - 1;
|
||||
@@ -111,7 +111,7 @@ class OutputsWidget: public Widget
|
||||
lastRefresh = now;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
#include "opentx.h"
|
||||
#include "widgets_container_impl.h"
|
||||
|
||||
// libopemui defines TIMOUR as zero
|
||||
#ifdef TIMEHOUR
|
||||
#undef TIMEHOUR
|
||||
#define TIMEHOUR 0x2000
|
||||
#endif
|
||||
|
||||
class TimerWidget: public Widget
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -86,30 +86,45 @@ class ValueWidget: public Widget
|
||||
if (timerState.val < 0) {
|
||||
color = ALARM_COLOR;
|
||||
}
|
||||
drawSource(dc, NUMBERS_PADDING, 2, field, color);
|
||||
drawSource(dc, NUMBERS_PADDING + 1, 3, field, COLOR2FLAGS(BLACK));
|
||||
drawTimer(dc, xValue, yValue, abs(timerState.val), attrValue | FONT(XL) | color);
|
||||
}
|
||||
|
||||
if (field == MIXSRC_TX_TIME) {
|
||||
drawTimer(dc, xValue, yValue, getValue(MIXSRC_TX_TIME),
|
||||
attrValue | FONT(XL) | color);
|
||||
}
|
||||
|
||||
if (field >= MIXSRC_FIRST_TELEM) {
|
||||
TelemetryItem & telemetryItem = telemetryItems[(field - MIXSRC_FIRST_TELEM) / 3];
|
||||
if (!telemetryItem.isAvailable() || telemetryItem.isOld()) {
|
||||
color = TEXT_DISABLE_COLOR;
|
||||
if (persistentData->options[2].value.boolValue) {
|
||||
drawSource(dc, xLabel + 1, yLabel + 1, field, attrLabel | COLOR2FLAGS(BLACK));
|
||||
drawTimer(dc, xValue + 1, yValue + 1, abs(timerState.val),
|
||||
attrValue | FONT(STD) | COLOR2FLAGS(BLACK));
|
||||
}
|
||||
}
|
||||
drawSource(dc, xLabel, yLabel, field, attrLabel | color);
|
||||
drawTimer(dc, xValue, yValue, abs(timerState.val),
|
||||
attrValue | FONT(STD) | color);
|
||||
|
||||
if (persistentData->options[2].value.boolValue) {
|
||||
drawSource(dc,xLabel + 1, yLabel + 1, field, attrLabel | COLOR2FLAGS(BLACK));
|
||||
drawSourceValue(dc, xValue + 1, yValue + 1, field, attrValue | COLOR2FLAGS(BLACK));
|
||||
}
|
||||
} else if (field == MIXSRC_TX_TIME) {
|
||||
int32_t tme = getValue(MIXSRC_TX_TIME);
|
||||
if (persistentData->options[2].value.boolValue) {
|
||||
drawSource(dc, xLabel + 1, yLabel + 1, field, COLOR2FLAGS(BLACK));
|
||||
drawTimer(dc, xValue + 1, yValue + 1, tme,
|
||||
attrValue | FONT(STD) | COLOR2FLAGS(BLACK));
|
||||
}
|
||||
drawSource(dc, xLabel, yLabel, field, attrLabel | color);
|
||||
drawTimer(dc, xValue, yValue, tme,
|
||||
attrValue | FONT(STD) | color);
|
||||
} else {
|
||||
|
||||
drawSource(dc, xLabel, yLabel, field, attrLabel | color);
|
||||
drawSourceValue(dc, xValue, yValue, field, attrValue | color);
|
||||
if (field >= MIXSRC_FIRST_TELEM) {
|
||||
TelemetryItem& telemetryItem =
|
||||
telemetryItems[(field - MIXSRC_FIRST_TELEM) / 3];
|
||||
if (!telemetryItem.isAvailable() || telemetryItem.isOld()) {
|
||||
color = TEXT_DISABLE_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (persistentData->options[2].value.boolValue) {
|
||||
drawSource(dc, xLabel + 1, yLabel + 1, field,
|
||||
attrLabel | COLOR2FLAGS(BLACK));
|
||||
drawSourceValue(dc, xValue + 1, yValue + 1, field,
|
||||
attrValue | COLOR2FLAGS(BLACK));
|
||||
}
|
||||
|
||||
drawSource(dc, xLabel, yLabel, field, attrLabel | color);
|
||||
drawSourceValue(dc, xValue, yValue, field, attrValue | color);
|
||||
}
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
|
||||
@@ -442,12 +442,15 @@ bool isSwitch2POSWarningStateAvailable(int state)
|
||||
// return isSwitchAvailable(swtch, TimersContext);
|
||||
//}
|
||||
|
||||
bool isThrottleSourceAvailable(int source)
|
||||
bool isThrottleSourceAvailable(int src)
|
||||
{
|
||||
if (source >= THROTTLE_SOURCE_FIRST_POT && source < THROTTLE_SOURCE_FIRST_POT+NUM_POTS+NUM_SLIDERS && !IS_POT_SLIDER_AVAILABLE(POT1+source-THROTTLE_SOURCE_FIRST_POT))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
#if !defined(LIBOPENUI)
|
||||
src = throttleSource2Source(src);
|
||||
#endif
|
||||
return isSourceAvailable(src) &&
|
||||
((src == MIXSRC_Thr) ||
|
||||
((src >= MIXSRC_FIRST_POT) && (src <= MIXSRC_LAST_POT)) ||
|
||||
((src >= MIXSRC_FIRST_CH) && (src <= MIXSRC_LAST_CH)));
|
||||
}
|
||||
|
||||
bool isLogicalSwitchFunctionAvailable(int function)
|
||||
@@ -1097,6 +1100,13 @@ const mm_protocol_definition *getMultiProtocolDefinition (uint8_t protocol)
|
||||
#endif
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
const char * getMultiOptionTitleStatic(uint8_t moduleIdx)
|
||||
{
|
||||
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
|
||||
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
|
||||
return pdef->optionsstr;
|
||||
}
|
||||
|
||||
const char * getMultiOptionTitle(uint8_t moduleIdx)
|
||||
{
|
||||
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
|
||||
@@ -1107,10 +1117,7 @@ const char * getMultiOptionTitle(uint8_t moduleIdx)
|
||||
}
|
||||
return mm_options_strings::options[status.optionDisp];
|
||||
}
|
||||
else {
|
||||
const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol();
|
||||
const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_proto);
|
||||
return pdef->optionsstr;
|
||||
}
|
||||
|
||||
return getMultiOptionTitleStatic(moduleIdx);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -220,6 +220,21 @@ inline uint8_t IF_ALLOW_RACING_MODE(int)
|
||||
#endif
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW_STATIC(uint8_t moduleIdx)
|
||||
{
|
||||
if (!isModuleMultimodule(moduleIdx))
|
||||
return HIDDEN_ROW;
|
||||
|
||||
uint8_t protocol = g_model.moduleData[moduleIdx].getMultiProtocol();
|
||||
if (protocol < MODULE_SUBTYPE_MULTI_LAST) {
|
||||
const mm_protocol_definition * pdef = getMultiProtocolDefinition(protocol);
|
||||
if (pdef->disable_ch_mapping)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return HIDDEN_ROW;
|
||||
}
|
||||
|
||||
inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW(uint8_t moduleIdx)
|
||||
{
|
||||
if (!isModuleMultimodule(moduleIdx))
|
||||
@@ -230,14 +245,7 @@ inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW(uint8_t moduleIdx)
|
||||
return status.supportsDisableMapping() == true ? 0 : HIDDEN_ROW;
|
||||
}
|
||||
|
||||
uint8_t protocol = g_model.moduleData[moduleIdx].getMultiProtocol();
|
||||
if (protocol < MODULE_SUBTYPE_MULTI_LAST) {
|
||||
const mm_protocol_definition * pdef = getMultiProtocolDefinition(protocol);
|
||||
if (pdef->disable_ch_mapping)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return HIDDEN_ROW;
|
||||
return MULTI_DISABLE_CHAN_MAP_ROW_STATIC(moduleIdx);
|
||||
}
|
||||
|
||||
inline bool isMultiProtocolSelectable(int protocol)
|
||||
@@ -355,6 +363,7 @@ inline uint8_t MODULE_OPTION_ROW(uint8_t moduleIdx) {
|
||||
void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event,
|
||||
LcdFlags flags, uint8_t old_editMode);
|
||||
|
||||
const char * getMultiOptionTitleStatic(uint8_t moduleIdx);
|
||||
const char *getMultiOptionTitle(uint8_t moduleIdx);
|
||||
|
||||
const char * writeScreenshot();
|
||||
|
||||
@@ -374,7 +374,8 @@ bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags)
|
||||
for (int i = 0; i < MAX_TELEMETRY_SENSORS; i++) {
|
||||
if (isTelemetryFieldAvailable(i)) {
|
||||
const char* sensorName = g_model.telemetrySensors[i].label;
|
||||
if ((len <= TELEM_LABEL_LEN) && !strncmp(sensorName, name, len)) {
|
||||
int len = strnlen(sensorName, TELEM_LABEL_LEN);
|
||||
if (!strncmp(sensorName, name, len)) {
|
||||
if (name[len] == '\0') {
|
||||
field.id = MIXSRC_FIRST_TELEM + 3 * i;
|
||||
field.desc[0] = '\0';
|
||||
|
||||
@@ -77,7 +77,7 @@ void setDefaultGVars()
|
||||
#endif
|
||||
}
|
||||
|
||||
void setVendorSpecificModelDefaults()
|
||||
void setVendorSpecificModelDefaults(uint8_t id)
|
||||
{
|
||||
#if defined(FRSKY_RELEASE)
|
||||
g_model.moduleData[INTERNAL_MODULE].type = IS_PXX2_INTERNAL_ENABLED() ? MODULE_TYPE_ISRM_PXX2 : MODULE_TYPE_XJT_PXX1;
|
||||
@@ -132,7 +132,7 @@ void setModelDefaults(uint8_t id)
|
||||
memset(&g_model, 0, sizeof(g_model));
|
||||
applyDefaultTemplate();
|
||||
|
||||
setVendorSpecificModelDefaults();
|
||||
setVendorSpecificModelDefaults(id);
|
||||
|
||||
strAppendUnsigned(strAppend(g_model.header.name, STR_MODEL), id + 1, 2);
|
||||
|
||||
|
||||
@@ -229,32 +229,6 @@ enum SwashType {
|
||||
|
||||
#include "pulses/modules_constants.h"
|
||||
|
||||
enum ThrottleSources {
|
||||
THROTTLE_SOURCE_THR,
|
||||
THROTTLE_SOURCE_FIRST_POT,
|
||||
#if defined(PCBX9E)
|
||||
THROTTLE_SOURCE_F1 = THROTTLE_SOURCE_FIRST_POT,
|
||||
THROTTLE_SOURCE_F2,
|
||||
THROTTLE_SOURCE_F3,
|
||||
THROTTLE_SOURCE_F4,
|
||||
THROTTLE_SOURCE_S1,
|
||||
THROTTLE_SOURCE_S2,
|
||||
THROTTLE_SOURCE_LS,
|
||||
THROTTLE_SOURCE_RS,
|
||||
#elif defined(PCBTARANIS)
|
||||
THROTTLE_SOURCE_S1 = THROTTLE_SOURCE_FIRST_POT,
|
||||
THROTTLE_SOURCE_S2,
|
||||
THROTTLE_SOURCE_S3,
|
||||
THROTTLE_SOURCE_LS,
|
||||
THROTTLE_SOURCE_RS,
|
||||
#else
|
||||
THROTTLE_SOURCE_P1 = THROTTLE_SOURCE_FIRST_POT,
|
||||
THROTTLE_SOURCE_P2,
|
||||
THROTTLE_SOURCE_P3,
|
||||
#endif
|
||||
THROTTLE_SOURCE_CH1,
|
||||
};
|
||||
|
||||
enum DisplayTrims
|
||||
{
|
||||
DISPLAY_TRIMS_NEVER,
|
||||
|
||||
+11
-5
@@ -1007,21 +1007,26 @@ void checkTrims()
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (before>TRIM_MIN && after<=TRIM_MIN) {
|
||||
int16_t tMax = g_model.extendedTrims ? TRIM_EXTENDED_MAX : TRIM_MAX;
|
||||
int16_t tMin = g_model.extendedTrims ? TRIM_EXTENDED_MIN : TRIM_MIN;
|
||||
if (before > tMin && after <= tMin) {
|
||||
beepTrim = true;
|
||||
AUDIO_TRIM_MIN();
|
||||
killEvents(event);
|
||||
}
|
||||
else if (before<TRIM_MAX && after>=TRIM_MAX) {
|
||||
else if (before < tMax && after >= tMax) {
|
||||
beepTrim = true;
|
||||
AUDIO_TRIM_MAX();
|
||||
killEvents(event);
|
||||
}
|
||||
|
||||
if ((before<after && after>TRIM_MAX) || (before>after && after<TRIM_MIN)) {
|
||||
if (!g_model.extendedTrims) after = before;
|
||||
// Allow only move into the right direction if over the limits
|
||||
if ((before < after && after > tMax) || // increasing over tMax
|
||||
(before > after && after < tMin)) { // decreasing under tMin
|
||||
after = before;
|
||||
}
|
||||
|
||||
// Clip at hard limits
|
||||
if (after < TRIM_EXTENDED_MIN) {
|
||||
after = TRIM_EXTENDED_MIN;
|
||||
}
|
||||
@@ -1590,7 +1595,8 @@ void instantTrim()
|
||||
}
|
||||
}
|
||||
if (addTrim && abs(delta) >= INSTANT_TRIM_MARGIN) {
|
||||
int16_t trim = limit<int16_t>(TRIM_EXTENDED_MIN, (delta + trims[stick]) / 2, TRIM_EXTENDED_MAX);
|
||||
int16_t trim = limit<int16_t>(
|
||||
TRIM_EXTENDED_MIN, (delta + trims[stick]) / 2, TRIM_EXTENDED_MAX);
|
||||
setTrimValue(trimFlightMode, stick, trim);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,6 +285,8 @@ void enablePulsesExternalModule(uint8_t protocol)
|
||||
extmoduleSerialStart();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, MULTIMODULE_PERIOD);
|
||||
#endif
|
||||
getMultiModuleStatus(EXTERNAL_MODULE).failsafeChecked = false;
|
||||
getMultiModuleStatus(EXTERNAL_MODULE).flags = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -309,7 +311,7 @@ void enablePulsesExternalModule(uint8_t protocol)
|
||||
#if defined(AFHDS3)
|
||||
case PROTOCOL_CHANNELS_AFHDS3:
|
||||
extmodulePulsesData.afhds3.init(EXTERNAL_MODULE);
|
||||
extmoduleSerialStart(/*AFHDS3_BAUDRATE, AFHDS3_COMMAND_TIMEOUT * 2000, false*/);
|
||||
extmoduleSerialStart();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, AFHDS3_COMMAND_TIMEOUT * 1000 /* us */);
|
||||
break;
|
||||
#endif
|
||||
@@ -491,6 +493,8 @@ static void enablePulsesInternalModule(uint8_t protocol)
|
||||
intmodulePulsesData.multi.initFrame();
|
||||
intmoduleSerialStart(MULTIMODULE_BAUDRATE, true, USART_Parity_Even, USART_StopBits_2, USART_WordLength_9b);
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD);
|
||||
getMultiModuleStatus(INTERNAL_MODULE).failsafeChecked = false;
|
||||
getMultiModuleStatus(INTERNAL_MODULE).flags = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ void preModelLoad()
|
||||
#endif
|
||||
#if defined(HARDWARE_EXTERNAL_MODULE)
|
||||
stopPulsesExternalModule();
|
||||
RTOS_WAIT_MS(200);
|
||||
#endif
|
||||
|
||||
stopTrainer();
|
||||
|
||||
@@ -89,6 +89,16 @@ int zchar2str(char * dest, const char * src, int size)
|
||||
return size+1;
|
||||
}
|
||||
|
||||
int strnlen(const char *src, int max_size)
|
||||
{
|
||||
for (int i=0; i<max_size; i++) {
|
||||
if (src[i] == '\0')
|
||||
return i;
|
||||
}
|
||||
|
||||
return max_size;
|
||||
}
|
||||
|
||||
unsigned int effectiveLen(const char * str, unsigned int size)
|
||||
{
|
||||
while (size > 0) {
|
||||
|
||||
@@ -30,6 +30,7 @@ char char2lower(char c);
|
||||
int8_t char2zchar(char c);
|
||||
void str2zchar(char *dest, const char *src, int size);
|
||||
int zchar2str(char *dest, const char *src, int size);
|
||||
int strnlen(const char *src, int max_size);
|
||||
|
||||
char * strAppend(char * dest, const char * source, int len = 0);
|
||||
char * strAppendUnsigned(char * dest, uint32_t value, uint8_t digits = 0, uint8_t radix = 10);
|
||||
|
||||
@@ -238,7 +238,7 @@ set(TARGET_SRC
|
||||
)
|
||||
|
||||
if(HARDWARE_TOUCH)
|
||||
set(TOUCH_DRIVER tp_gt911.cpp)
|
||||
set(TOUCH_DRIVER tp_gt911.cpp i2c_driver.cpp)
|
||||
add_definitions(-DHARDWARE_TOUCH)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -326,19 +326,21 @@ void extmoduleSendNextFrame()
|
||||
#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)
|
||||
extmoduleSendBuffer(extmodulePulsesData.afhds3.getData(), extmodulePulsesData.afhds3.getSize());
|
||||
#else
|
||||
if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN)
|
||||
return;
|
||||
|
||||
const uint16_t* dataPtr = extmodulePulsesData.afhds3.getData();
|
||||
uint32_t dataSize = extmodulePulsesData.afhds3.getSize();
|
||||
//Peripheral data size
|
||||
//we know that afdhds3 uses 2 byte values!
|
||||
uint32_t dmaSize = (EXTMODULE_TIMER_DMA_SIZE & (DMA_SxCR_PSIZE_0 | DMA_SxCR_PSIZE_1)) | DMA_SxCR_MSIZE_0;
|
||||
|
||||
EXTMODULE_TIMER->CCR2 = dataPtr[dataSize -1] - 4000; // 2mS in advance
|
||||
EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | dmaSize | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
|
||||
EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(dataPtr);
|
||||
EXTMODULE_TIMER_DMA_STREAM->NDTR = (uint32_t)dataSize;
|
||||
EXTMODULE_TIMER_DMA_STREAM->NDTR = dataSize;
|
||||
EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
|
||||
|
||||
// re-init timer
|
||||
EXTMODULE_TIMER->EGR = TIM_PSCReloadMode_Immediate;
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -728,7 +728,7 @@
|
||||
#define I2C_SCL_GPIO_PinSource GPIO_PinSource8
|
||||
#define I2C_SDA_GPIO_PinSource GPIO_PinSource9
|
||||
#endif
|
||||
#define I2C_SPEED 400000
|
||||
#define I2C_CLK_RATE 400000
|
||||
|
||||
// Haptic
|
||||
#define HAPTIC_PWM
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* OpenTX - https://github.com/opentx/opentx
|
||||
* 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.
|
||||
*
|
||||
* The content of this file partially stems from STM32F4 HAL by STMicroelectronics.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define __IO volatile /*!< Defines 'read / write' permissions */
|
||||
|
||||
#define GPIO_NUMBER 16U
|
||||
|
||||
#define GPIO_GET_INDEX(__GPIOx__) (uint8_t)(((__GPIOx__) == (GPIOA))? 0U :\
|
||||
((__GPIOx__) == (GPIOB))? 1U :\
|
||||
((__GPIOx__) == (GPIOC))? 2U :\
|
||||
((__GPIOx__) == (GPIOD))? 3U :\
|
||||
((__GPIOx__) == (GPIOE))? 4U :\
|
||||
((__GPIOx__) == (GPIOF))? 5U :\
|
||||
((__GPIOx__) == (GPIOG))? 6U :\
|
||||
((__GPIOx__) == (GPIOH))? 7U :\
|
||||
((__GPIOx__) == (GPIOI))? 8U :\
|
||||
((__GPIOx__) == (GPIOJ))? 9U : 10U)
|
||||
|
||||
#define HAL_MAX_DELAY 0xFFFFFFFFU
|
||||
|
||||
/* AHB1 Peripheral Clock Enable Disable
|
||||
* @brief Enable or disable the AHB1 peripheral clock.
|
||||
* @note After reset, the peripheral clock (used for registers read/write access)
|
||||
* is disabled and the application software has to enable this clock before
|
||||
* using it.
|
||||
*/
|
||||
#define __HAL_RCC_GPIOA_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\
|
||||
/* Delay after an RCC peripheral clock enabling */ \
|
||||
tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\
|
||||
UNUSED(tmpreg); \
|
||||
} while(0U)
|
||||
#define __HAL_RCC_GPIOB_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN);\
|
||||
/* Delay after an RCC peripheral clock enabling */ \
|
||||
tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN);\
|
||||
UNUSED(tmpreg); \
|
||||
} while(0U)
|
||||
#define __HAL_RCC_GPIOC_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);\
|
||||
/* Delay after an RCC peripheral clock enabling */ \
|
||||
tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);\
|
||||
UNUSED(tmpreg); \
|
||||
} while(0U)
|
||||
#define __HAL_RCC_GPIOH_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\
|
||||
/* Delay after an RCC peripheral clock enabling */ \
|
||||
tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\
|
||||
UNUSED(tmpreg); \
|
||||
} while(0U)
|
||||
|
||||
#define __HAL_RCC_GPIOA_CLK_DISABLE() (RCC->AHB1ENR &= ~(RCC_AHB1ENR_GPIOAEN))
|
||||
#define __HAL_RCC_GPIOB_CLK_DISABLE() (RCC->AHB1ENR &= ~(RCC_AHB1ENR_GPIOBEN))
|
||||
#define __HAL_RCC_GPIOC_CLK_DISABLE() (RCC->AHB1ENR &= ~(RCC_AHB1ENR_GPIOCEN))
|
||||
#define __HAL_RCC_GPIOH_CLK_DISABLE() (RCC->AHB1ENR &= ~(RCC_AHB1ENR_GPIOHEN))
|
||||
|
||||
/* APB1 Peripheral Clock Enable Disable
|
||||
* @brief Enable or disable the Low Speed APB (APB1) peripheral clock.
|
||||
* @note After reset, the peripheral clock (used for registers read/write access)
|
||||
* is disabled and the application software has to enable this clock before
|
||||
* using it.
|
||||
*/
|
||||
#define __HAL_RCC_I2C1_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);\
|
||||
/* Delay after an RCC peripheral clock enabling */ \
|
||||
tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);\
|
||||
UNUSED(tmpreg); \
|
||||
} while(0U)
|
||||
#define __HAL_RCC_I2C2_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C2EN);\
|
||||
/* Delay after an RCC peripheral clock enabling */ \
|
||||
tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C2EN);\
|
||||
UNUSED(tmpreg); \
|
||||
} while(0U)
|
||||
#define __HAL_RCC_I2C3_CLK_ENABLE() do { \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C3EN);\
|
||||
/* Delay after an RCC peripheral clock enabling */ \
|
||||
tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C3EN);\
|
||||
UNUSED(tmpreg); \
|
||||
} while(0U)
|
||||
#define __HAL_RCC_I2C1_CLK_DISABLE() (RCC->APB1ENR &= ~(RCC_APB1ENR_I2C1EN))
|
||||
#define __HAL_RCC_I2C2_CLK_DISABLE() (RCC->APB1ENR &= ~(RCC_APB1ENR_I2C2EN))
|
||||
#define __HAL_RCC_I2C3_CLK_DISABLE() (RCC->APB1ENR &= ~(RCC_APB1ENR_I2C3EN))
|
||||
|
||||
#define __HAL_LOCK(__HANDLE__) \
|
||||
do{ \
|
||||
if((__HANDLE__)->Lock == HAL_LOCKED) \
|
||||
{ \
|
||||
return HAL_BUSY; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(__HANDLE__)->Lock = HAL_LOCKED; \
|
||||
} \
|
||||
}while (0U)
|
||||
|
||||
#define __HAL_UNLOCK(__HANDLE__) \
|
||||
do{ \
|
||||
(__HANDLE__)->Lock = HAL_UNLOCKED; \
|
||||
}while (0U)
|
||||
|
||||
|
||||
/* Enable the specified I2C peripheral.
|
||||
* @param __HANDLE__ specifies the I2C Handle.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE)
|
||||
|
||||
/* Disable the specified I2C peripheral.
|
||||
* @param __HANDLE__ specifies the I2C Handle.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE)
|
||||
|
||||
// I2C Private Constants
|
||||
#define I2C_FLAG_MASK 0x0000FFFFU
|
||||
#define I2C_MIN_PCLK_FREQ_STANDARD 2000000U /*!< 2 MHz */
|
||||
#define I2C_MIN_PCLK_FREQ_FAST 4000000U /*!< 4 MHz */
|
||||
|
||||
#define I2C_TIMEOUT_FLAG 35U /*!< Timeout 35 ms */
|
||||
#define I2C_TIMEOUT_BUSY_FLAG 25U /*!< Timeout 25 ms */
|
||||
#define I2C_TIMEOUT_STOP_FLAG 5U /*!< Timeout 5 ms */
|
||||
#define I2C_NO_OPTION_FRAME 0xFFFF0000U /*!< XferOptions default value */
|
||||
|
||||
// I2C Private Macros
|
||||
#define I2C_MIN_PCLK_FREQ(__PCLK__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__PCLK__) < I2C_MIN_PCLK_FREQ_STANDARD) : ((__PCLK__) < I2C_MIN_PCLK_FREQ_FAST))
|
||||
#define I2C_CCR_CALCULATION(__PCLK__, __SPEED__, __COEFF__) (((((__PCLK__) - 1U)/((__SPEED__) * (__COEFF__))) + 1U) & I2C_CCR_CCR)
|
||||
#define I2C_FREQRANGE(__PCLK__) ((__PCLK__)/1000000U)
|
||||
#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__FREQRANGE__) + 1U) : ((((__FREQRANGE__) * 300U) / 1000U) + 1U))
|
||||
#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__) ((I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U) < 4U)? 4U:I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U))
|
||||
#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__DUTYCYCLE__) == I2C_DUTYCYCLE_2)? I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 3U) : (I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 25U) | I2C_DUTYCYCLE_16_9))
|
||||
#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__SPEED__) <= 100000U)? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) : \
|
||||
((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0U)? 1U : \
|
||||
((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS))
|
||||
#define I2C_7BIT_ADD_WRITE(__ADDRESS__) ((uint8_t)((__ADDRESS__) & (uint8_t)(~I2C_OAR1_ADD0)))
|
||||
#define I2C_7BIT_ADD_READ(__ADDRESS__) ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0))
|
||||
|
||||
#define I2C_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF)))
|
||||
#define I2C_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)0x00F0)))
|
||||
#define I2C_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)(0x00F1))))
|
||||
|
||||
#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0xFF00)) >> 8)))
|
||||
#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF)))
|
||||
|
||||
// I2C duty cycle in fast mode
|
||||
#define I2C_DUTYCYCLE_2 0x00000000U
|
||||
#define I2C_DUTYCYCLE_16_9 I2C_CCR_DUTY
|
||||
|
||||
// I2C addressing mode
|
||||
#define I2C_ADDRESSINGMODE_7BIT 0x00004000U
|
||||
#define I2C_ADDRESSINGMODE_10BIT (I2C_OAR1_ADDMODE | 0x00004000U)
|
||||
|
||||
// I2C dual addressing mode
|
||||
#define I2C_DUALADDRESS_DISABLE 0x00000000U
|
||||
#define I2C_DUALADDRESS_ENABLE I2C_OAR2_ENDUAL
|
||||
|
||||
// I2C general call addressing mode
|
||||
#define I2C_GENERALCALL_DISABLE 0x00000000U
|
||||
#define I2C_GENERALCALL_ENABLE I2C_CR1_ENGC
|
||||
|
||||
// I2C nostretch mode
|
||||
#define I2C_NOSTRETCH_DISABLE 0x00000000U
|
||||
#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH
|
||||
|
||||
// I2C Error Code definition
|
||||
#define HAL_I2C_ERROR_NONE 0x00000000U /*!< No error */
|
||||
#define HAL_I2C_ERROR_BERR 0x00000001U /*!< BERR error */
|
||||
#define HAL_I2C_ERROR_ARLO 0x00000002U /*!< ARLO error */
|
||||
#define HAL_I2C_ERROR_AF 0x00000004U /*!< AF error */
|
||||
#define HAL_I2C_ERROR_OVR 0x00000008U /*!< OVR error */
|
||||
#define HAL_I2C_ERROR_DMA 0x00000010U /*!< DMA transfer error */
|
||||
#define HAL_I2C_ERROR_TIMEOUT 0x00000020U /*!< Timeout Error */
|
||||
#define HAL_I2C_ERROR_SIZE 0x00000040U /*!< Size Management error */
|
||||
#define HAL_I2C_ERROR_DMA_PARAM 0x00000080U /*!< DMA Parameter Error */
|
||||
#define HAL_I2C_WRONG_START 0x00000200U /*!< Wrong start Error */
|
||||
|
||||
// I2C XferOptions definition
|
||||
#define I2C_FIRST_FRAME 0x00000001U
|
||||
#define I2C_FIRST_AND_NEXT_FRAME 0x00000002U
|
||||
#define I2C_NEXT_FRAME 0x00000004U
|
||||
#define I2C_FIRST_AND_LAST_FRAME 0x00000008U
|
||||
#define I2C_LAST_FRAME_NO_STOP 0x00000010U
|
||||
#define I2C_LAST_FRAME 0x00000020U
|
||||
|
||||
// I2C states
|
||||
#define I2C_STATE_MSK ((uint32_t)((uint32_t)((uint32_t)HAL_I2C_STATE_BUSY_TX | (uint32_t)HAL_I2C_STATE_BUSY_RX) & (uint32_t)(~((uint32_t)HAL_I2C_STATE_READY)))) /*!< Mask State define, keep only RX and TX bits */
|
||||
#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE)) /*!< Default Value */
|
||||
#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */
|
||||
#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */
|
||||
#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */
|
||||
#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */
|
||||
|
||||
// I2C Analog Filter
|
||||
#define I2C_ANALOGFILTER_ENABLE 0x00000000U
|
||||
#define I2C_ANALOGFILTER_DISABLE I2C_FLTR_ANOFF
|
||||
|
||||
/* Clears the I2C ADDR pending flag.
|
||||
* @param __HANDLE__ specifies the I2C Handle.
|
||||
* This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \
|
||||
do{ \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
tmpreg = (__HANDLE__)->Instance->SR1; \
|
||||
tmpreg = (__HANDLE__)->Instance->SR2; \
|
||||
UNUSED(tmpreg); \
|
||||
} while(0)
|
||||
|
||||
/* Clears the I2C pending flags which are cleared by writing 0 in a specific bit.
|
||||
* @param __HANDLE__ specifies the I2C Handle.
|
||||
* @param __FLAG__ specifies the flag to clear.
|
||||
* This parameter can be any combination of the following values:
|
||||
* @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode)
|
||||
* @arg I2C_FLAG_AF: Acknowledge failure flag
|
||||
* @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode)
|
||||
* @arg I2C_FLAG_BERR: Bus error flag
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR1 = (uint16_t)(~((__FLAG__) & I2C_FLAG_MASK)))
|
||||
|
||||
// HAL Status structures definition
|
||||
typedef enum
|
||||
{
|
||||
HAL_OK = 0x00U,
|
||||
HAL_ERROR = 0x01U,
|
||||
HAL_BUSY = 0x02U,
|
||||
HAL_TIMEOUT = 0x03U
|
||||
} HAL_StatusTypeDef;
|
||||
|
||||
// HAL lock structures definition
|
||||
typedef enum
|
||||
{
|
||||
HAL_UNLOCKED = 0x00U,
|
||||
HAL_LOCKED = 0x01U
|
||||
} HAL_LockTypeDef;
|
||||
|
||||
/* HAL State structure definition
|
||||
* HAL I2C State value coding follow below described bitmap :
|
||||
* b7-b6 Error information
|
||||
* 00 : No Error
|
||||
* 01 : Abort (Abort user request on going)
|
||||
* 10 : Timeout
|
||||
* 11 : Error
|
||||
* b5 Peripheral initialization status
|
||||
* 0 : Reset (Peripheral not initialized)
|
||||
* 1 : Init done (Peripheral initialized and ready to use. HAL I2C Init function called)
|
||||
* b4 (not used)
|
||||
* x : Should be set to 0
|
||||
* b3
|
||||
* 0 : Ready or Busy (No Listen mode ongoing)
|
||||
* 1 : Listen (Peripheral in Address Listen Mode)
|
||||
* b2 Intrinsic process state
|
||||
* 0 : Ready
|
||||
* 1 : Busy (Peripheral busy with some configuration or internal operations)
|
||||
* b1 Rx state
|
||||
* 0 : Ready (no Rx operation ongoing)
|
||||
* 1 : Busy (Rx operation ongoing)
|
||||
* b0 Tx state
|
||||
* 0 : Ready (no Tx operation ongoing)
|
||||
* 1 : Busy (Tx operation ongoing)
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */
|
||||
HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */
|
||||
HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */
|
||||
HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */
|
||||
HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */
|
||||
HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */
|
||||
HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission
|
||||
process is ongoing */
|
||||
HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception
|
||||
process is ongoing */
|
||||
HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */
|
||||
HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */
|
||||
HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */
|
||||
} HAL_I2C_StateTypeDef;
|
||||
|
||||
/* HAL Mode structure definition
|
||||
* HAL I2C Mode value coding follow below described bitmap :
|
||||
* b7 (not used)
|
||||
* x : Should be set to 0
|
||||
* b6
|
||||
* 0 : None
|
||||
* 1 : Memory (HAL I2C communication is in Memory Mode)
|
||||
* b5
|
||||
* 0 : None
|
||||
* 1 : Slave (HAL I2C communication is in Slave Mode)
|
||||
* b4
|
||||
* 0 : None
|
||||
* 1 : Master (HAL I2C communication is in Master Mode)
|
||||
* b3-b2-b1-b0 (not used)
|
||||
* xxxx : Should be set to 0000
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */
|
||||
HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */
|
||||
HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */
|
||||
HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */
|
||||
} HAL_I2C_ModeTypeDef;
|
||||
|
||||
// I2C configuration structure definition
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ClockSpeed; /*!< Specifies the clock frequency.
|
||||
This parameter must be set to a value lower than 400kHz */
|
||||
uint32_t DutyCycle; /*!< Specifies the I2C fast mode duty cycle.
|
||||
This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */
|
||||
uint32_t OwnAddress1; /*!< Specifies the first device own address.
|
||||
This parameter can be a 7-bit or 10-bit address. */
|
||||
uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected.
|
||||
This parameter can be a value of @ref I2C_addressing_mode */
|
||||
uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected.
|
||||
This parameter can be a value of @ref I2C_dual_addressing_mode */
|
||||
uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected
|
||||
This parameter can be a 7-bit address. */
|
||||
uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected.
|
||||
This parameter can be a value of @ref I2C_general_call_addressing_mode */
|
||||
uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected.
|
||||
This parameter can be a value of @ref I2C_nostretch_mode */
|
||||
} HAL_I2C_InitTypeDef; // WARNING: renamed from I2C_InitTypeDef due to conflict
|
||||
|
||||
// I2C handle structure definition
|
||||
typedef struct
|
||||
{
|
||||
I2C_TypeDef *Instance; /*!< I2C registers base address */
|
||||
HAL_I2C_InitTypeDef Init; /*!< I2C communication parameters (MOD!) */
|
||||
uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */
|
||||
uint16_t XferSize; /*!< I2C transfer size */
|
||||
__IO uint16_t XferCount; /*!< I2C transfer counter */
|
||||
__IO uint32_t XferOptions; /*!< I2C transfer options */
|
||||
__IO uint32_t PreviousState; /*!< I2C communication Previous state and mode
|
||||
context for internal usage */
|
||||
//DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */
|
||||
//DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */
|
||||
HAL_LockTypeDef Lock; /*!< I2C locking object */
|
||||
__IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */
|
||||
__IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */
|
||||
__IO uint32_t ErrorCode; /*!< I2C Error code */
|
||||
__IO uint32_t Devaddress; /*!< I2C Target device address */
|
||||
__IO uint32_t Memaddress; /*!< I2C Target memory address */
|
||||
__IO uint32_t MemaddSize; /*!< I2C Target memory address size */
|
||||
__IO uint32_t EventCount; /*!< I2C Event counter */
|
||||
} I2C_HandleTypeDef;
|
||||
|
||||
HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);
|
||||
HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c);
|
||||
HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter);
|
||||
HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter);
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "i2c_driver.h"
|
||||
#include "tp_gt911.h"
|
||||
#include "touch.h"
|
||||
|
||||
@@ -409,6 +410,8 @@ struct TouchData touchData;
|
||||
uint16_t touchGT911fwver = 0;
|
||||
uint32_t touchGT911hiccups = 0;
|
||||
|
||||
I2C_HandleTypeDef hi2c1;
|
||||
|
||||
static void TOUCH_AF_ExtiStop(void)
|
||||
{
|
||||
SYSCFG_EXTILineConfig(TOUCH_INT_EXTI_PortSource, TOUCH_INT_EXTI_PinSource1);
|
||||
@@ -484,267 +487,75 @@ void TOUCH_AF_INT_Change(void)
|
||||
GPIO_Init(TOUCH_INT_GPIO, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
void I2C_Init()
|
||||
void I2C_Init_Radio(void)
|
||||
{
|
||||
TRACE("I2C Init");
|
||||
|
||||
I2C_DeInit(I2C);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
I2C_InitTypeDef I2C_InitStructure;
|
||||
I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
|
||||
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
|
||||
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
|
||||
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
|
||||
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
|
||||
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
|
||||
I2C_Init(I2C, &I2C_InitStructure);
|
||||
I2C_Cmd(I2C, ENABLE);
|
||||
|
||||
GPIO_PinAFConfig(I2C_GPIO, I2C_SCL_GPIO_PinSource, I2C_GPIO_AF);
|
||||
GPIO_PinAFConfig(I2C_GPIO, I2C_SDA_GPIO_PinSource, I2C_GPIO_AF);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN | I2C_SDA_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(I2C_GPIO, &GPIO_InitStructure);
|
||||
hi2c1.Instance = I2C;
|
||||
hi2c1.Init.ClockSpeed = I2C_CLK_RATE;
|
||||
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
|
||||
hi2c1.Init.OwnAddress1 = 0;
|
||||
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
|
||||
hi2c1.Init.OwnAddress2 = 0;
|
||||
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
||||
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
|
||||
{
|
||||
TRACE("I2C ERROR: HAL_I2C_Init() failed");
|
||||
}
|
||||
// Configure Analogue filter
|
||||
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
|
||||
{
|
||||
TRACE("I2C ERROR: HAL_I2CEx_ConfigAnalogFilter() failed");
|
||||
}
|
||||
// Configure Digital filter
|
||||
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
|
||||
{
|
||||
TRACE("I2C ERROR: HAL_I2CEx_ConfigDigitalFilter() failed");
|
||||
}
|
||||
}
|
||||
|
||||
bool I2C_WaitFlag(uint32_t flag)
|
||||
bool I2C_GT911_WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len)
|
||||
{
|
||||
uint32_t timeout = I2C_TIMEOUT_MAX;
|
||||
while (!I2C_GetFlagStatus(I2C, flag)) {
|
||||
if ((timeout--) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
uint8_t uAddrAndBuf[258];
|
||||
uAddrAndBuf[0] = (uint8_t)((reg & 0xFF00) >> 8);
|
||||
uAddrAndBuf[1] = (uint8_t)(reg & 0x00FF);
|
||||
|
||||
bool I2C_WaitEvent(uint32_t event)
|
||||
{
|
||||
uint32_t timeout = I2C_TIMEOUT_MAX;
|
||||
while (!I2C_CheckEvent(I2C, event)) {
|
||||
if ((timeout--) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2C_WaitEventCleared(uint32_t event)
|
||||
{
|
||||
uint32_t timeout = I2C_TIMEOUT_MAX;
|
||||
while (I2C_CheckEvent(I2C, event)) {
|
||||
if ((timeout--) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t I2C_GT911_WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len)
|
||||
{
|
||||
if (!I2C_WaitEventCleared(I2C_FLAG_BUSY))
|
||||
{
|
||||
TRACE("I2C WRITE ERROR: busy timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_GenerateSTART(I2C, ENABLE);
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
|
||||
{
|
||||
TRACE("I2C WRITE ERROR: could not issue start");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_Send7bitAddress(I2C, GT_CMD_WR, I2C_Direction_Transmitter);
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
|
||||
{
|
||||
TRACE("I2C WRITE ERROR: could not send device address");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_SendData(I2C, (uint8_t)((reg & 0xFF00) >> 8));
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING))
|
||||
{
|
||||
TRACE("I2C WRITE ERROR: could not send register high address");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_SendData(I2C, (uint8_t)(reg & 0x00FF));
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING))
|
||||
{
|
||||
TRACE("I2C WRITE ERROR: could not send register low address");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* While there is data to be written */
|
||||
while (len--) {
|
||||
I2C_SendData(I2C, *buf);
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING))
|
||||
if (len > 0)
|
||||
{
|
||||
TRACE("I2C WRITE ERROR: could not send data with %u bytes remaining", len+1 );
|
||||
return false;
|
||||
for (int i = 0;i < len;i++)
|
||||
{
|
||||
uAddrAndBuf[i + 2] = buf[i];
|
||||
}
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED))
|
||||
{
|
||||
TRACE("I2C WRITE ERROR: waiting for BTF failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_GenerateSTOP(I2C, ENABLE);
|
||||
return true;
|
||||
if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uAddrAndBuf, len + 2, 100) != HAL_OK)
|
||||
{
|
||||
TRACE("I2C ERROR: WriteRegister failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2C_GT911_ReadRegister(u16 reg, uint8_t * buf, uint8_t len)
|
||||
bool I2C_GT911_ReadRegister(uint16_t reg, uint8_t * buf, uint8_t len)
|
||||
{
|
||||
if (!I2C_WaitEventCleared(I2C_FLAG_BUSY))
|
||||
{
|
||||
TRACE("I2C READ ERROR: busy timeout");
|
||||
return false;
|
||||
}
|
||||
uint8_t uRegAddr[2];
|
||||
uRegAddr[0] = (uint8_t)((reg & 0xFF00) >> 8);
|
||||
uRegAddr[1] = (uint8_t)(reg & 0x00FF);
|
||||
|
||||
I2C_GenerateSTART(I2C, ENABLE);
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
|
||||
{
|
||||
TRACE("I2C READ ERROR: could not issue first step start");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_Send7bitAddress(I2C, GT_CMD_WR, I2C_Direction_Transmitter);
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
|
||||
{
|
||||
TRACE("I2C READ ERROR: could not send first step device address");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_SendData(I2C, (uint8_t)((reg & 0xFF00) >> 8));
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING))
|
||||
{
|
||||
TRACE("I2C READ ERROR: could not send register high address");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_SendData(I2C, (uint8_t)(reg & 0x00FF));
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED))
|
||||
{
|
||||
TRACE("I2C READ ERROR: could not send register low address");
|
||||
return false;
|
||||
}
|
||||
|
||||
// According to GP911 data sheet, repeated start is not listed, so we do full stop.
|
||||
// See chapter 6.1.c, page 12, diagram for reading data
|
||||
I2C_GenerateSTOP(I2C, ENABLE);
|
||||
if (!I2C_WaitEventCleared(I2C_FLAG_BUSY))
|
||||
{
|
||||
TRACE("I2C READ ERROR: timeout waiting for first stop");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable Acknowledgement, clear POS flag
|
||||
I2C_AcknowledgeConfig(I2C, ENABLE);
|
||||
I2C_NACKPositionConfig(I2C, I2C_NACKPosition_Current);
|
||||
|
||||
I2C_GenerateSTART(I2C, ENABLE);
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
|
||||
{
|
||||
TRACE("I2C READ ERROR: could not issue second step start");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_Send7bitAddress(I2C, GT_CMD_RD, I2C_Direction_Receiver);
|
||||
if (!I2C_WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
|
||||
{
|
||||
TRACE("I2C READ ERROR: could not send second step device address");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len == 1) {
|
||||
// Clear Ack bit
|
||||
I2C_AcknowledgeConfig(I2C, DISABLE);
|
||||
|
||||
// EV6_1 -- must be atomic -- Clear ADDR, generate STOP
|
||||
__disable_irq();
|
||||
(void) I2C->SR2;
|
||||
I2C_GenerateSTOP(I2C,ENABLE);
|
||||
__enable_irq();
|
||||
|
||||
// Receive data EV7
|
||||
if(!I2C_WaitFlag(I2C_FLAG_RXNE)) {
|
||||
TRACE("I2C READ ERROR: timeout waiting for RxNE");
|
||||
I2C_Init();
|
||||
return false;
|
||||
}
|
||||
|
||||
*buf++ = I2C_ReceiveData(I2C);
|
||||
}
|
||||
else if (len == 2) {
|
||||
|
||||
// Set POS flag
|
||||
I2C_NACKPositionConfig(I2C, I2C_NACKPosition_Next);
|
||||
|
||||
// EV6_1 -- must be atomic and in this order
|
||||
__disable_irq();
|
||||
(void) I2C->SR2; // Clear ADDR flag
|
||||
I2C_AcknowledgeConfig(I2C, DISABLE); // Clear Ack bit
|
||||
__enable_irq();
|
||||
|
||||
// EV7_3 -- Wait for BTF, program stop, read data twice
|
||||
if (!I2C_WaitFlag(I2C_FLAG_BTF)) {
|
||||
TRACE("I2C READ ERROR: timeout waiting for BTF");
|
||||
I2C_Init();
|
||||
return false;
|
||||
}
|
||||
|
||||
__disable_irq();
|
||||
I2C_GenerateSTOP(I2C,ENABLE);
|
||||
*buf++ = I2C->DR;
|
||||
__enable_irq();
|
||||
|
||||
*buf++ = I2C->DR;
|
||||
}
|
||||
else {
|
||||
|
||||
(void) I2C->SR2; // Clear ADDR flag
|
||||
while (len-- != 3) {
|
||||
// EV7 -- cannot guarantee 1 transfer completion time, wait for BTF
|
||||
// instead of RXNE
|
||||
if (!I2C_WaitFlag(I2C_FLAG_BTF)) {
|
||||
TRACE("I2C READ ERROR: timeout waiting for BTF");
|
||||
I2C_Init();
|
||||
if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10) != HAL_OK)
|
||||
{
|
||||
TRACE("I2C ERROR: ReadRegister write reg address failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
*buf++ = I2C_ReceiveData(I2C);
|
||||
}
|
||||
|
||||
// Data N-2 in DR, data N-1 in shift register,
|
||||
// SCL stretched low until data N-2 is read
|
||||
if (!I2C_WaitFlag(I2C_FLAG_BTF)) {
|
||||
TRACE("I2C READ ERROR: timeout waiting for BTF");
|
||||
I2C_Init();
|
||||
return false;
|
||||
if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 100) != HAL_OK)
|
||||
{
|
||||
TRACE("I2C ERROR: ReadRegister read reg address failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
I2C_AcknowledgeConfig(I2C, DISABLE); // clear ack bit
|
||||
*buf++ = I2C_ReceiveData(I2C); // receive byte N-2
|
||||
|
||||
// Wait for BTF, program stop, read data twice
|
||||
if (!I2C_WaitFlag(I2C_FLAG_BTF)) {
|
||||
TRACE("I2C READ ERROR: timeout waiting for BTF");
|
||||
I2C_Init();
|
||||
return false;
|
||||
}
|
||||
|
||||
__disable_irq();
|
||||
I2C_GenerateSTOP(I2C,ENABLE);
|
||||
*buf++ = I2C->DR;
|
||||
__enable_irq();
|
||||
|
||||
*buf++ = I2C->DR;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2C_GT911_SendConfig(void)
|
||||
@@ -791,7 +602,7 @@ bool touchPanelInit(void)
|
||||
TRACE("Touchpanel init start ...");
|
||||
|
||||
TOUCH_AF_GPIOConfig(); //SET RST=OUT INT=OUT INT=LOW
|
||||
I2C_Init();
|
||||
I2C_Init_Radio();
|
||||
|
||||
TPRST_LOW();
|
||||
TPINT_HIGH();
|
||||
@@ -827,7 +638,7 @@ bool touchPanelInit(void)
|
||||
}
|
||||
|
||||
TRACE("Chip config Ver:%x", tmp[0]);
|
||||
if (tmp[0] <= GT911_CFG_NUMER) //Config ver
|
||||
if (tmp[0] < GT911_CFG_NUMER) //Config ver
|
||||
{
|
||||
TRACE("Sending new config %d", GT911_CFG_NUMER);
|
||||
if (!I2C_GT911_SendConfig())
|
||||
@@ -864,6 +675,23 @@ bool touchPanelInit(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool I2C_ReInit(void)
|
||||
{
|
||||
TRACE("I2C ReInit");
|
||||
touchPanelDeInit();
|
||||
if (HAL_I2C_DeInit(&hi2c1) != HAL_OK)
|
||||
TRACE("I2C ReInit - I2C DeInit failed");
|
||||
|
||||
// If DeInit fails, try to re-init anyway
|
||||
if (!touchPanelInit())
|
||||
{
|
||||
TRACE("I2C ReInit - touchPanelInit failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(SIMU) || defined(SEMIHOSTING) || defined(DEBUG)
|
||||
static const char* event2str(uint8_t ev)
|
||||
{
|
||||
@@ -888,10 +716,10 @@ void touchPanelRead()
|
||||
{
|
||||
uint8_t state = 0;
|
||||
|
||||
// if (!touchEventOccured)
|
||||
// return;
|
||||
if (!touchEventOccured)
|
||||
return;
|
||||
|
||||
// touchEventOccured = false;
|
||||
touchEventOccured = false;
|
||||
|
||||
uint32_t startReadStatus = RTOS_GET_MS();
|
||||
do {
|
||||
@@ -899,8 +727,8 @@ void touchPanelRead()
|
||||
//ledRed();
|
||||
touchGT911hiccups++;
|
||||
TRACE("GT911 I2C read XY error");
|
||||
touchPanelDeInit();
|
||||
touchPanelInit();
|
||||
if (!I2C_ReInit())
|
||||
TRACE("I2C ReInit failed");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -921,8 +749,8 @@ void touchPanelRead()
|
||||
//ledRed();
|
||||
touchGT911hiccups++;
|
||||
TRACE("GT911 I2C data read error");
|
||||
touchPanelDeInit();
|
||||
touchPanelInit();
|
||||
if (!I2C_ReInit())
|
||||
TRACE("I2C ReInit failed");
|
||||
return;
|
||||
}
|
||||
if (touchState.event == TE_NONE || touchState.event == TE_UP ||
|
||||
|
||||
@@ -30,28 +30,29 @@ extern bool touchPanelInit();
|
||||
void touchPanelRead();
|
||||
bool touchPanelEventOccured();
|
||||
|
||||
#define GT911_TIMEOUT 3 // 3ms
|
||||
#define GT911_TIMEOUT 3 // 3ms
|
||||
|
||||
#define GT911_MAX_TP 5
|
||||
#define GT911_CFG_NUMER 0x6C
|
||||
#define GT911_CFG_NUMER 0x6D
|
||||
|
||||
//I2C
|
||||
#define GT_CMD_WR 0X28
|
||||
#define GT_CMD_RD 0X29
|
||||
#define I2C_TIMEOUT_MAX 1000
|
||||
#define GT911_I2C_ADDR 0x14
|
||||
//#define GT_CMD_WR 0x28
|
||||
//#define GT_CMD_RD 0x29
|
||||
//#define I2C_TIMEOUT_MAX 1000
|
||||
|
||||
//GT9147
|
||||
#define GT_CTRL_REG 0X8040
|
||||
#define GT_CFGS_REG 0X8047
|
||||
#define GT_CHECK_REG 0X80FF
|
||||
#define GT_PID_REG 0X8140
|
||||
//GT911
|
||||
#define GT_CTRL_REG 0x8040
|
||||
#define GT_CFGS_REG 0x8047
|
||||
#define GT_CHECK_REG 0x80FF
|
||||
#define GT_PID_REG 0x8140
|
||||
|
||||
#define GT_GSTID_REG 0X814E
|
||||
#define GT_TP1_REG 0X8150
|
||||
#define GT_TP2_REG 0X8158
|
||||
#define GT_TP3_REG 0X8160
|
||||
#define GT_TP4_REG 0X8168
|
||||
#define GT_TP5_REG 0X8170
|
||||
#define GT_GSTID_REG 0x814E
|
||||
#define GT_TP1_REG 0x8150
|
||||
#define GT_TP2_REG 0x8158
|
||||
#define GT_TP3_REG 0x8160
|
||||
#define GT_TP4_REG 0x8168
|
||||
#define GT_TP5_REG 0x8170
|
||||
|
||||
#define GT911_READ_XY_REG 0x814E
|
||||
#define GT911_CLEARBUF_REG 0x814E
|
||||
|
||||
@@ -1968,7 +1968,7 @@
|
||||
#define I2C_SDA_GPIO_PinSource GPIO_PinSource7
|
||||
#define I2C_ADDRESS_VOLUME 0x5C
|
||||
#endif
|
||||
#define I2C_SPEED 400000
|
||||
#define I2C_CLK_RATE 400000
|
||||
#define I2C_ADDRESS_EEPROM 0xA2
|
||||
#define I2C_FLASH_PAGESIZE 64
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ void i2cInit()
|
||||
GPIO_ResetBits(I2C_WP_GPIO, I2C_WP_GPIO_PIN);
|
||||
|
||||
I2C_InitTypeDef I2C_InitStructure;
|
||||
I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
|
||||
I2C_InitStructure.I2C_ClockSpeed = I2C_CLK_RATE;
|
||||
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
|
||||
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
|
||||
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
Vendored
+1
-1
Submodule radio/src/thirdparty/libopenui updated: 014e87b9fc...9809596089
@@ -174,3 +174,22 @@ void evalTimers(int16_t throttle, uint8_t tick10ms)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t throttleSource2Source(int16_t thrSrc)
|
||||
{
|
||||
if (thrSrc == 0) return (int16_t)MIXSRC_Thr;
|
||||
if (--thrSrc < NUM_POTS + NUM_SLIDERS)
|
||||
return (int16_t)(thrSrc + MIXSRC_FIRST_POT);
|
||||
return (int16_t)(thrSrc - (NUM_POTS + NUM_SLIDERS) + MIXSRC_FIRST_CH);
|
||||
}
|
||||
|
||||
int16_t source2ThrottleSource(int16_t src)
|
||||
{
|
||||
if (src == MIXSRC_Thr)
|
||||
return 0;
|
||||
else if (src <= MIXSRC_LAST_POT)
|
||||
return src - MIXSRC_FIRST_POT + 1;
|
||||
else if (src <= MIXSRC_LAST_CH)
|
||||
return src - MIXSRC_FIRST_CH + NUM_POTS + NUM_SLIDERS + 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -62,4 +62,7 @@ static inline tmr10ms_t get_tmr10ms()
|
||||
return g_tmr10ms;
|
||||
}
|
||||
|
||||
int16_t throttleSource2Source(int16_t thrSrc);
|
||||
int16_t source2ThrottleSource(int16_t src);
|
||||
|
||||
#endif // _TIMERS_H_
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
#define TR_CSWEQUAL "a=x\0 "
|
||||
|
||||
#define LEN_VCSWFUNC "\005"
|
||||
#define TR_VCSWFUNC "---\0 " TR_CSWEQUAL "a~x\0 ""a>x\0 ""a<x\0 " TR_CSWRANGE "|a|>x""|a|<x""AND\0 ""OR\0 ""XOR\0 " TR_CSWSTAY "a=b\0 ""a>b\0 ""a<b\0 ""Δ}x\0 ""|Δ|}x" TR_CSWTIMER TR_CSWSTICKY
|
||||
#define TR_VCSWFUNC "---\0 " TR_CSWEQUAL "a~x\0 ""a>x\0 ""a<x\0 " TR_CSWRANGE "|a|>x""|a|<x""AND\0 ""OR\0 ""XOR\0 " TR_CSWSTAY "a=b\0 ""a>b\0 ""a<b\0 " STR_CHAR_DELTA "}x\0 " "|" STR_CHAR_DELTA "|}x" TR_CSWTIMER TR_CSWSTICKY
|
||||
|
||||
#define LEN_VFSWFUNC "\012"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user