From a6674ae236539de3f78505502f69d99ea030f2bd Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 12 Jul 2021 20:06:30 +0200 Subject: [PATCH 01/46] [color] mixer scripts screen Todo: - display only one of .lua/.luac in filechoice - display proper script status on list page --- radio/src/gui/colorlcd/CMakeLists.txt | 1 + radio/src/gui/colorlcd/getset_helpers.h | 2 +- radio/src/gui/colorlcd/menu_model.cpp | 4 + .../src/gui/colorlcd/model_mixer_scripts.cpp | 289 ++++++++++++++++++ radio/src/gui/colorlcd/model_mixer_scripts.h | 39 +++ radio/src/gui/colorlcd/model_setup.cpp | 17 +- 6 files changed, 343 insertions(+), 9 deletions(-) create mode 100644 radio/src/gui/colorlcd/model_mixer_scripts.cpp create mode 100644 radio/src/gui/colorlcd/model_mixer_scripts.h diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index de3a1d804..138aef38d 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -76,6 +76,7 @@ endmacro(add_gui_src) if(LUA) add_gui_src(standalone_lua.cpp) + add_gui_src(model_mixer_scripts.cpp) endif() if(HELI) diff --git a/radio/src/gui/colorlcd/getset_helpers.h b/radio/src/gui/colorlcd/getset_helpers.h index a13695433..7d7c930dc 100644 --- a/radio/src/gui/colorlcd/getset_helpers.h +++ b/radio/src/gui/colorlcd/getset_helpers.h @@ -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_ diff --git a/radio/src/gui/colorlcd/menu_model.cpp b/radio/src/gui/colorlcd/menu_model.cpp index 3d19a8a41..1b9f028d2 100644 --- a/radio/src/gui/colorlcd/menu_model.cpp +++ b/radio/src/gui/colorlcd/menu_model.cpp @@ -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()); } diff --git a/radio/src/gui/colorlcd/model_mixer_scripts.cpp b/radio/src/gui/colorlcd/model_mixer_scripts.cpp new file mode 100644 index 000000000..dd57d5658 --- /dev/null +++ b/radio/src/gui/colorlcd/model_mixer_scripts.cpp @@ -0,0 +1,289 @@ +/* + * 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 + +#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, SCRIPT_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(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); + } +}; + +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) { + dc->drawSizedText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, + scriptData.file, LEN_SCRIPT_FILENAME, + textColor); + } + + // 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); + }); +} diff --git a/radio/src/gui/colorlcd/model_mixer_scripts.h b/radio/src/gui/colorlcd/model_mixer_scripts.h new file mode 100644 index 000000000..8486a193c --- /dev/null +++ b/radio/src/gui/colorlcd/model_mixer_scripts.h @@ -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); +}; diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index a69df8222..640f547ce 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -1035,15 +1035,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(); From 34fa23d423afb257b1652a7518f0648013e4cf1d Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 13 Jul 2021 08:44:30 +0200 Subject: [PATCH 02/46] Display only unique names (regardless of extension .lua or .luac) --- radio/src/gui/colorlcd/model_mixer_scripts.cpp | 2 +- radio/src/thirdparty/libopenui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/model_mixer_scripts.cpp b/radio/src/gui/colorlcd/model_mixer_scripts.cpp index dd57d5658..a7cb72bfe 100644 --- a/radio/src/gui/colorlcd/model_mixer_scripts.cpp +++ b/radio/src/gui/colorlcd/model_mixer_scripts.cpp @@ -80,7 +80,7 @@ class ScriptEditWindow : public Page { // Filename new StaticText(window, grid.getLabelSlot(), STR_SCRIPT); auto fc = new FileChoice( - window, grid.getFieldSlot(), SCRIPTS_MIXES_PATH, SCRIPT_EXT, + window, grid.getFieldSlot(), SCRIPTS_MIXES_PATH, SCRIPTS_EXT, LEN_SCRIPT_FILENAME, [=]() { return std::string(sd->file, LEN_SCRIPT_FILENAME); }, [=](std::string newValue) { diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 014e87b9f..8e58aa3e1 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 014e87b9fc5dd345a3619f375b84c5e9747a398f +Subproject commit 8e58aa3e16dfdc45b5c7b226e005f237346f6809 From a93c543576ef68cb1650753c6cdbee006582a7b5 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 13 Jul 2021 09:11:06 +0200 Subject: [PATCH 03/46] Display proper script status and custom name --- .../src/gui/colorlcd/model_mixer_scripts.cpp | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/radio/src/gui/colorlcd/model_mixer_scripts.cpp b/radio/src/gui/colorlcd/model_mixer_scripts.cpp index a7cb72bfe..0e0fd012a 100644 --- a/radio/src/gui/colorlcd/model_mixer_scripts.cpp +++ b/radio/src/gui/colorlcd/model_mixer_scripts.cpp @@ -166,6 +166,9 @@ class ScriptEditWindow : public Page { } }; +constexpr char SCRIPT_STATUS_ERROR[] = "(error)"; +constexpr char SCRIPT_STATUS_KILLED[] = "(killed)"; + class ScriptLineButton : public Button { public: @@ -184,9 +187,31 @@ class ScriptLineButton : public Button dc->drawSolidFilledRect(0, 0, width(), height(), bgColor); if (runtimeData) { - dc->drawSizedText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, - scriptData.file, LEN_SCRIPT_FILENAME, - textColor); + 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 From ea6b9a38dd27d1ce8be58c2d1c3f3b4e121814e5 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 13 Jul 2021 09:13:19 +0200 Subject: [PATCH 04/46] Updated libopenui with include fix --- radio/src/thirdparty/libopenui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 8e58aa3e1..980959608 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 8e58aa3e16dfdc45b5c7b226e005f237346f6809 +Subproject commit 980959608920417990b7f9aeb1ffa7d4d78096b7 From 6b7a573ec7db97f7e39e3f9ce630e323578c3a5a Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 14 Jul 2021 07:47:43 +0200 Subject: [PATCH 05/46] Compilation fix for FRSKY_RELEASE --- radio/src/model_init.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/model_init.cpp b/radio/src/model_init.cpp index 1a4b8ce2e..202784a9f 100644 --- a/radio/src/model_init.cpp +++ b/radio/src/model_init.cpp @@ -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); From f02667006590914fa16a7edbd93954056c88124b Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 14 Jul 2021 07:59:52 +0200 Subject: [PATCH 06/46] [ViewText] fix compiler warnings --- radio/src/gui/colorlcd/view_text.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/gui/colorlcd/view_text.h b/radio/src/gui/colorlcd/view_text.h index e73938ef1..aa7b598f7 100644 --- a/radio/src/gui/colorlcd/view_text.h +++ b/radio/src/gui/colorlcd/view_text.h @@ -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(); \ No newline at end of file +void readModelNotes(); From 6d11fa803349c8262902ce7b50f51ac995360735 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 14 Jul 2021 08:45:00 +0200 Subject: [PATCH 07/46] [lua] Fix sensor max and min matching Resolves #442 --- radio/src/lua/api_general.cpp | 3 ++- radio/src/strhelpers.cpp | 10 ++++++++++ radio/src/strhelpers.h | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index bed2e48df..9cd4db639 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -372,7 +372,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'; diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index 48bb7a8af..f5d1d5917 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -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 0) { diff --git a/radio/src/strhelpers.h b/radio/src/strhelpers.h index de39c8867..1b25ab682 100644 --- a/radio/src/strhelpers.h +++ b/radio/src/strhelpers.h @@ -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); From 2cbc7a6209e825f9cb8657b5161fa81969152215 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 14 Jul 2021 12:17:16 +0200 Subject: [PATCH 08/46] [color] fix throttle source --- radio/src/gui/colorlcd/model_setup.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 75033cc05..6e6f97265 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -1139,7 +1139,29 @@ 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, + [=]() { + int16_t src = g_model.thrTraceSrc; + if (src == 0) return (int16_t)MIXSRC_Thr; + if (--src < NUM_POTS + NUM_SLIDERS) return (int16_t)(src + MIXSRC_FIRST_POT); + return (int16_t)(src - (NUM_POTS + NUM_SLIDERS) + MIXSRC_FIRST_CH); + }, + [=](int16_t src) { + if (src == MIXSRC_Thr) + g_model.thrTraceSrc = 0; + else if (src <= MIXSRC_LAST_POT) + g_model.thrTraceSrc = src - MIXSRC_FIRST_POT + 1; + else if (src <= MIXSRC_LAST_CH) + g_model.thrTraceSrc = src - MIXSRC_FIRST_CH + NUM_POTS + NUM_SLIDERS + 1; + SET_DIRTY(); + }); + sc->setAvailableHandler([=](int16_t src) { + return isSourceAvailable(src) && + ((src == MIXSRC_Thr) || + ((src >= MIXSRC_FIRST_POT) && (src <= MIXSRC_LAST_POT)) || + ((src >= MIXSRC_FIRST_CH) && (src <= MIXSRC_LAST_CH))); + }); grid.nextLine(); // Throttle trim From 90bd1b6329571818eb0766ed458690db8996b2a7 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 14 Jul 2021 12:30:19 +0200 Subject: [PATCH 09/46] Unify throttle source check/conversion code --- radio/src/gui/128x64/model_setup.cpp | 13 +++++++------ radio/src/gui/212x64/model_setup.cpp | 13 +++++++------ radio/src/gui/colorlcd/model_setup.cpp | 26 +++++++------------------- radio/src/gui/gui_common.cpp | 13 ++++++++----- radio/src/myeeprom.h | 26 -------------------------- radio/src/timers.cpp | 19 +++++++++++++++++++ radio/src/timers.h | 3 +++ 7 files changed, 51 insertions(+), 62 deletions(-) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 9a5f4bd69..8ac5fc51f 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -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; } diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 5b187a545..2bc541987 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -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; } diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 6e6f97265..85e8a8e20 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -1141,27 +1141,15 @@ void ModelSetupPage::build(FormWindow * window) new StaticText(window, grid.getLabelSlot(true), STR_TTRACE); auto sc = new SourceChoice( window, grid.getFieldSlot(), 0, MIXSRC_LAST_CH, - [=]() { - int16_t src = g_model.thrTraceSrc; - if (src == 0) return (int16_t)MIXSRC_Thr; - if (--src < NUM_POTS + NUM_SLIDERS) return (int16_t)(src + MIXSRC_FIRST_POT); - return (int16_t)(src - (NUM_POTS + NUM_SLIDERS) + MIXSRC_FIRST_CH); - }, + [=]() { return throttleSource2Source(g_model.thrTraceSrc); }, [=](int16_t src) { - if (src == MIXSRC_Thr) - g_model.thrTraceSrc = 0; - else if (src <= MIXSRC_LAST_POT) - g_model.thrTraceSrc = src - MIXSRC_FIRST_POT + 1; - else if (src <= MIXSRC_LAST_CH) - g_model.thrTraceSrc = src - MIXSRC_FIRST_CH + NUM_POTS + NUM_SLIDERS + 1; - SET_DIRTY(); + int16_t val = source2ThrottleSource(src); + if (val >= 0) { + g_model.thrTraceSrc = val; + SET_DIRTY(); + } }); - sc->setAvailableHandler([=](int16_t src) { - return isSourceAvailable(src) && - ((src == MIXSRC_Thr) || - ((src >= MIXSRC_FIRST_POT) && (src <= MIXSRC_LAST_POT)) || - ((src >= MIXSRC_FIRST_CH) && (src <= MIXSRC_LAST_CH))); - }); + sc->setAvailableHandler(isThrottleSourceAvailable); grid.nextLine(); // Throttle trim diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index d243d154f..f703aa5e3 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -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) diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 438989eb0..ac9f9d460 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -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, diff --git a/radio/src/timers.cpp b/radio/src/timers.cpp index 0ee289e78..c3d336b1f 100644 --- a/radio/src/timers.cpp +++ b/radio/src/timers.cpp @@ -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; +} diff --git a/radio/src/timers.h b/radio/src/timers.h index fb5f7a4be..5226414a0 100644 --- a/radio/src/timers.h +++ b/radio/src/timers.h @@ -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_ From ed59ce281934b076e6a2c4d12a53b44bc2d7940e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 14 Jul 2021 14:25:12 +0200 Subject: [PATCH 10/46] [color] fixed displayed trim range --- radio/src/gui/colorlcd/layouts/trims.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/layouts/trims.cpp b/radio/src/gui/colorlcd/layouts/trims.cpp index 312d7adbf..f164b6968 100644 --- a/radio/src/gui/colorlcd/layouts/trims.cpp +++ b/radio/src/gui/colorlcd/layouts/trims.cpp @@ -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(); From a268a9a1d763d09945303ee4eef63c4728b0ead3 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 14 Jul 2021 19:22:56 +0200 Subject: [PATCH 11/46] [color] Fixed throttle trim switch setting --- radio/src/datastructs.h | 16 ++++++++++++++++ radio/src/gui/colorlcd/model_setup.cpp | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index a41f03b68..ad59b8b4a 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -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; + } + } }); /* diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 989890f46..75149e8b2 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -1160,7 +1160,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(); } From c04cd509a86a5ea24d47accfc6eaeba684944eaa Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Sat, 10 Jul 2021 18:28:16 +1000 Subject: [PATCH 12/46] Run safety checks on model select and exit menu --- radio/src/gui/colorlcd/model_select.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/gui/colorlcd/model_select.cpp b/radio/src/gui/colorlcd/model_select.cpp index 8ecb3ffa7..fd0354c5a 100644 --- a/radio/src/gui/colorlcd/model_select.cpp +++ b/radio/src/gui/colorlcd/model_select.cpp @@ -246,6 +246,8 @@ class ModelCategoryPageBody : public FormWindow modelslist.setCurrentModel(model); modelslist.setCurrentCategory(category); update(); + checkAll(); + this->onEvent(EVT_KEY_FIRST(KEY_EXIT)); }); } menu->addLine(STR_CREATE_MODEL, getCreateModelAction()); From b98f03184f3a981af01e2f8e8a7441ec85242f29 Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Sat, 10 Jul 2021 19:02:56 +1000 Subject: [PATCH 13/46] No need to re-run update as not updating menu Also removes slight UI flicker/lag --- radio/src/gui/colorlcd/model_select.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/gui/colorlcd/model_select.cpp b/radio/src/gui/colorlcd/model_select.cpp index fd0354c5a..5097f9e9f 100644 --- a/radio/src/gui/colorlcd/model_select.cpp +++ b/radio/src/gui/colorlcd/model_select.cpp @@ -245,7 +245,6 @@ class ModelCategoryPageBody : public FormWindow modelslist.setCurrentModel(model); modelslist.setCurrentCategory(category); - update(); checkAll(); this->onEvent(EVT_KEY_FIRST(KEY_EXIT)); }); From e745ea254aa02cc4e7614626a987c2287e8712c6 Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Wed, 14 Jul 2021 15:46:59 +1000 Subject: [PATCH 14/46] Clear module flags and failsafeChecked on enable Clearing the MPM capability flags and failsafeChecked resolves the issue with false failsafe not set warnings. Needs further testing to see if it causes any other issues. --- radio/src/pulses/pulses.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 779771c04..1d0b75045 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -285,6 +285,12 @@ void enablePulsesExternalModule(uint8_t protocol) extmoduleSerialStart(); mixerSchedulerSetPeriod(EXTERNAL_MODULE, MULTIMODULE_PERIOD); #endif + for (int i = 0; i < NUM_MODULES; i++) { + if (isModuleMultimodule(i)) { + getMultiModuleStatus(i).failsafeChecked = false; + getMultiModuleStatus(i).flags = 0; + } + } break; #endif @@ -491,6 +497,12 @@ 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); + for (int i = 0; i < NUM_MODULES; i++) { + if (isModuleMultimodule(i)) { + getMultiModuleStatus(i).failsafeChecked = false; + getMultiModuleStatus(i).flags = 0; + } + } break; #endif From 46b3f07f70f765e7750910cb1c87ffc00b91512a Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Wed, 14 Jul 2021 15:59:00 +1000 Subject: [PATCH 15/46] Only reset flags on module being enabled --- radio/src/pulses/pulses.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 1d0b75045..9169a9b6e 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -285,12 +285,8 @@ void enablePulsesExternalModule(uint8_t protocol) extmoduleSerialStart(); mixerSchedulerSetPeriod(EXTERNAL_MODULE, MULTIMODULE_PERIOD); #endif - for (int i = 0; i < NUM_MODULES; i++) { - if (isModuleMultimodule(i)) { - getMultiModuleStatus(i).failsafeChecked = false; - getMultiModuleStatus(i).flags = 0; - } - } + getMultiModuleStatus(EXTERNAL_MODULE).failsafeChecked = false; + getMultiModuleStatus(EXTERNAL_MODULE).flags = 0; break; #endif @@ -497,12 +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); - for (int i = 0; i < NUM_MODULES; i++) { - if (isModuleMultimodule(i)) { - getMultiModuleStatus(i).failsafeChecked = false; - getMultiModuleStatus(i).flags = 0; - } - } + getMultiModuleStatus(INTERNAL_MODULE).failsafeChecked = false; + getMultiModuleStatus(INTERNAL_MODULE).flags = 0; break; #endif From 232dabdb0bbbf2030e84ccae7b44a34e4af08b4c Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Thu, 15 Jul 2021 13:30:55 +1000 Subject: [PATCH 16/46] Prevent pre-flight checklist focus blocked --- radio/src/gui/colorlcd/model_select.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/model_select.cpp b/radio/src/gui/colorlcd/model_select.cpp index 5097f9e9f..f73600b10 100644 --- a/radio/src/gui/colorlcd/model_select.cpp +++ b/radio/src/gui/colorlcd/model_select.cpp @@ -245,8 +245,8 @@ class ModelCategoryPageBody : public FormWindow modelslist.setCurrentModel(model); modelslist.setCurrentCategory(category); - checkAll(); this->onEvent(EVT_KEY_FIRST(KEY_EXIT)); + checkAll(); }); } menu->addLine(STR_CREATE_MODEL, getCreateModelAction()); From c1486c878061b27a072631df2bfc851f52b036d2 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 15 Jul 2021 10:45:57 +0200 Subject: [PATCH 17/46] Adjust audio announcements on trim limits --- radio/src/opentx.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index dab39d0fc..4d014785b 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1003,21 +1003,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) { + else if (before < tMax && after >= tMax) { beepTrim = true; AUDIO_TRIM_MAX(); killEvents(event); } - if ((beforeTRIM_MAX) || (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; } @@ -1586,7 +1591,8 @@ void instantTrim() } } if (addTrim && abs(delta) >= INSTANT_TRIM_MARGIN) { - int16_t trim = limit(TRIM_EXTENDED_MIN, (delta + trims[stick]) / 2, TRIM_EXTENDED_MAX); + int16_t trim = limit( + TRIM_EXTENDED_MIN, (delta + trims[stick]) / 2, TRIM_EXTENDED_MAX); setTrimValue(trimFlightMode, stick, trim); } } From cdbc62c5590663641522e741fd3b2dd381012e82 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 15 Jul 2021 10:46:44 +0200 Subject: [PATCH 18/46] [color] clip trim value displayed based on range set. Resolves #443 --- radio/src/gui/colorlcd/layouts/trims.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/layouts/trims.cpp b/radio/src/gui/colorlcd/layouts/trims.cpp index f164b6968..07cbebc07 100644 --- a/radio/src/gui/colorlcd/layouts/trims.cpp +++ b/radio/src/gui/colorlcd/layouts/trims.cpp @@ -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) From 000836a01868a821a2519a997ad439f82ccc3286 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 15 Jul 2021 11:32:07 +0200 Subject: [PATCH 19/46] [color] Fix vertical trims as well --- radio/src/gui/colorlcd/layouts/trims.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/radio/src/gui/colorlcd/layouts/trims.cpp b/radio/src/gui/colorlcd/layouts/trims.cpp index 07cbebc07..1336522a1 100644 --- a/radio/src/gui/colorlcd/layouts/trims.cpp +++ b/radio/src/gui/colorlcd/layouts/trims.cpp @@ -89,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 */ From 237672122e102b375842a0e3026836b5fca4778c Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Thu, 15 Jul 2021 19:34:22 +1000 Subject: [PATCH 20/46] Make outputs widget use outputs names --- radio/src/gui/colorlcd/widgets/outputs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/widgets/outputs.cpp b/radio/src/gui/colorlcd/widgets/outputs.cpp index 71c634562..3a79eef6f 100644 --- a/radio/src/gui/colorlcd/widgets/outputs.cpp +++ b/radio/src/gui/colorlcd/widgets/outputs.cpp @@ -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(); } From 8bfbb723f37c4416e15a935815fe367b09c7204b Mon Sep 17 00:00:00 2001 From: rotorman Date: Thu, 15 Jul 2021 19:25:31 +0200 Subject: [PATCH 21/46] Integrated STM32F4 I2C HAL functions. Changed old "I2C_SPEED" to "I2C_CLK_RATE" in order not to conflict with HAL. Use TOUCH_INT again to gate touch sampling. --- radio/src/targets/horus/CMakeLists.txt | 2 +- radio/src/targets/horus/hal.h | 2 +- radio/src/targets/horus/i2c_driver.cpp | 1020 ++++++++++++++++++++++ radio/src/targets/horus/i2c_driver.h | 397 +++++++++ radio/src/targets/horus/tp_gt911.cpp | 308 ++----- radio/src/targets/horus/tp_gt911.h | 31 +- radio/src/targets/taranis/hal.h | 2 +- radio/src/targets/taranis/i2c_driver.cpp | 2 +- 8 files changed, 1498 insertions(+), 266 deletions(-) create mode 100644 radio/src/targets/horus/i2c_driver.cpp create mode 100644 radio/src/targets/horus/i2c_driver.h diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index c01057e9c..be80a40ce 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -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() diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 8d7be0da5..fd1605892 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -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 diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp new file mode 100644 index 000000000..d47af3221 --- /dev/null +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -0,0 +1,1020 @@ +/* + * 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. + */ + +#include "opentx.h" +#include "i2c_driver.h" + +uint32_t GetTickCountMS(void) +{ + static uint32_t tickcount = 0; + tickcount++; + return (tickcount >> 10); + //return (ticksNow()/CYCLES_IN_MS); +} + +/* I2C MSP Initialization + * This function configures the hardware resources used in this example + * @param hi2c: I2C handle pointer + * @retval None + */ +void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (I2C_GPIO == GPIOA) + __HAL_RCC_GPIOA_CLK_ENABLE(); + else + if (I2C_GPIO == GPIOB) + __HAL_RCC_GPIOB_CLK_ENABLE(); + else + if (I2C_GPIO == GPIOC) + __HAL_RCC_GPIOC_CLK_ENABLE(); + else + if (I2C_GPIO == GPIOH) + __HAL_RCC_GPIOH_CLK_ENABLE(); + else + TRACE("I2C ERROR: HAL_I2C_MspInit() I2C_GPIO misconfiguration"); + + GPIO_PinAFConfig(I2C_GPIO, I2C_SCL_GPIO_PinSource, I2C_GPIO_AF); + GPIO_PinAFConfig(I2C_GPIO, I2C_SDA_GPIO_PinSource, I2C_GPIO_AF); + + GPIO_InitStruct.GPIO_Pin = I2C_SCL_GPIO_PIN | I2C_SDA_GPIO_PIN; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(I2C_GPIO, &GPIO_InitStruct); + + /* Peripheral clock enable */ + if (I2C == I2C1) + __HAL_RCC_I2C1_CLK_ENABLE(); + else + if (I2C == I2C2) + __HAL_RCC_I2C2_CLK_ENABLE(); + else + if (I2C == I2C3) + __HAL_RCC_I2C3_CLK_ENABLE(); + else + TRACE("I2C ERROR: HAL_I2C_MspInit() I2C misconfiguration"); +} + +/* Initializes the I2C according to the specified parameters + * in the HAL_I2C_InitTypeDef and initialize the associated handle. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) +{ + uint32_t freqrange; + uint32_t pclk1; + + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_CLOCK_SPEED(hi2c->Init.ClockSpeed)); + assert_param(IS_I2C_DUTY_CYCLE(hi2c->Init.DutyCycle)); + assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1)); + assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode)); + assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode)); + assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2)); + assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode)); + assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode)); + + if (hi2c->State == HAL_I2C_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hi2c->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + HAL_I2C_MspInit(hi2c); + } + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /*Reset I2C*/ + hi2c->Instance->CR1 |= I2C_CR1_SWRST; + hi2c->Instance->CR1 &= ~I2C_CR1_SWRST; + + /* Get PCLK1 frequency */ + RCC_ClocksTypeDef rccClocks; + RCC_GetClocksFreq(&rccClocks); + pclk1 = rccClocks.PCLK1_Frequency; + + /* Check the minimum allowed PCLK1 frequency */ + if (I2C_MIN_PCLK_FREQ(pclk1, hi2c->Init.ClockSpeed) == 1U) + { + return HAL_ERROR; + } + + /* Calculate frequency range */ + freqrange = I2C_FREQRANGE(pclk1); + + /*---------------------------- I2Cx CR2 Configuration ----------------------*/ + /* Configure I2Cx: Frequency range */ + MODIFY_REG(hi2c->Instance->CR2, I2C_CR2_FREQ, freqrange); + + /*---------------------------- I2Cx TRISE Configuration --------------------*/ + /* Configure I2Cx: Rise Time */ + MODIFY_REG(hi2c->Instance->TRISE, I2C_TRISE_TRISE, I2C_RISE_TIME(freqrange, hi2c->Init.ClockSpeed)); + + /*---------------------------- I2Cx CCR Configuration ----------------------*/ + /* Configure I2Cx: Speed */ + MODIFY_REG(hi2c->Instance->CCR, (I2C_CCR_FS | I2C_CCR_DUTY | I2C_CCR_CCR), I2C_SPEED(pclk1, hi2c->Init.ClockSpeed, hi2c->Init.DutyCycle)); + + /*---------------------------- I2Cx CR1 Configuration ----------------------*/ + /* Configure I2Cx: Generalcall and NoStretch mode */ + MODIFY_REG(hi2c->Instance->CR1, (I2C_CR1_ENGC | I2C_CR1_NOSTRETCH), (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode)); + + /*---------------------------- I2Cx OAR1 Configuration ---------------------*/ + /* Configure I2Cx: Own Address1 and addressing mode */ + MODIFY_REG(hi2c->Instance->OAR1, (I2C_OAR1_ADDMODE | I2C_OAR1_ADD8_9 | I2C_OAR1_ADD1_7 | I2C_OAR1_ADD0), (hi2c->Init.AddressingMode | hi2c->Init.OwnAddress1)); + + /*---------------------------- I2Cx OAR2 Configuration ---------------------*/ + /* Configure I2Cx: Dual mode and Own Address2 */ + MODIFY_REG(hi2c->Instance->OAR2, (I2C_OAR2_ENDUAL | I2C_OAR2_ADD2), (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2)); + + /* Enable the selected I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + return HAL_OK; +} + +/* Configures I2C Analog noise filter. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param AnalogFilter new state of the Analog filter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Reset I2Cx ANOFF bit */ + hi2c->Instance->FLTR &= ~(I2C_FLTR_ANOFF); + + /* Disable the analog filter */ + hi2c->Instance->FLTR |= AnalogFilter; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/* Configures I2C Digital noise filter. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param DigitalFilter Coefficient of digital noise filter between 0x00 and 0x0F. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter) +{ + uint16_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Get the old register value */ + tmpreg = hi2c->Instance->FLTR; + + /* Reset I2Cx DNF bit [3:0] */ + tmpreg &= ~(I2C_FLTR_DNF); + + /* Set I2Cx DNF coefficient */ + tmpreg |= DigitalFilter; + + /* Store the new register value */ + hi2c->Instance->FLTR = tmpreg; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +FlagStatus __HAL_I2C_GET_FLAG(I2C_HandleTypeDef *hi2c, uint32_t Flag) +{ + return I2C_GetFlagStatus(hi2c->Instance, Flag); +} + +/* This function handles I2C Communication Timeout. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param Flag specifies the I2C flag to check. + * @param Status The new Flag status (SET or RESET). + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart) +{ + /* Wait until flag is set */ + while (I2C_GetFlagStatus(hi2c->Instance, Flag) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/* This function handles I2C Communication Timeout for Master addressing phase. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param Flag specifies the I2C flag to check. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Clear AF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/* hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + /* Generate Start condition if first transfer */ + if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) + { + /* Generate ReStart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else + { + /* Do nothing */ + } + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + } + else + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); + + /* Wait until ADD10 flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); + } + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/* This function handles Acknowledge failed detection during an I2C Communication. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) +{ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Clear NACKF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + return HAL_OK; +} + +/* This function handles I2C Communication Timeout for specific usage of TXE flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original: HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/* This function handles I2C Communication Timeout for specific usage of BTF flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/* Transmits in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = GetTickCountMS(); // Original: HAL_GetTick(); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Send Slave Address */ + if (I2C_MasterRequestWrite(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + while (hi2c->XferSize > 0U) + { + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + hi2c->XferSize--; + + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + hi2c->XferSize--; + } + + /* Wait until BTF flag is set */ + if (I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/* Master sends target device address for read request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start condition if first transfer */ + if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) + { + /* Generate ReStart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else + { + /* Do nothing */ + } + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); + } + else + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); + + /* Wait until ADD10 flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Restart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_READ(DevAddress); + } + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/* This function handles I2C Communication Timeout for specific usage of RXNE flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) + { + /* Check if a STOPF is detected */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) + { + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + return HAL_OK; +} + +/* Receives in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = GetTickCountMS(); // Original HAL_GetTick(); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Send Slave Address */ + if (I2C_MasterRequestRead(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + if (hi2c->XferSize == 0U) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else if (hi2c->XferSize == 1U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else if (hi2c->XferSize == 2U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Enable Pos */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + while (hi2c->XferSize > 0U) + { + if (hi2c->XferSize <= 3U) + { + /* One byte */ + if (hi2c->XferSize == 1U) + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + /* Two bytes */ + else if (hi2c->XferSize == 2U) + { + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + /* 3 Last bytes */ + else + { + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + else + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + } + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} diff --git a/radio/src/targets/horus/i2c_driver.h b/radio/src/targets/horus/i2c_driver.h new file mode 100644 index 000000000..c31b44f0c --- /dev/null +++ b/radio/src/targets/horus/i2c_driver.h @@ -0,0 +1,397 @@ +/* + * 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 + +#define __IO volatile /*!< Defines 'read / write' permissions */ + +#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) + +/* Checks whether the specified I2C flag is set or not. + * @param __HANDLE__ specifies the I2C Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2C_FLAG_OVR: Overrun/Underrun flag + * @arg I2C_FLAG_AF: Acknowledge failure flag + * @arg I2C_FLAG_ARLO: Arbitration lost flag + * @arg I2C_FLAG_BERR: Bus error flag + * @arg I2C_FLAG_TXE: Data register empty flag + * @arg I2C_FLAG_RXNE: Data register not empty flag + * @arg I2C_FLAG_STOPF: Stop detection flag + * @arg I2C_FLAG_ADD10: 10-bit header sent flag + * @arg I2C_FLAG_BTF: Byte transfer finished flag + * @arg I2C_FLAG_ADDR: Address sent flag + * Address matched flag + * @arg I2C_FLAG_SB: Start bit flag + * @arg I2C_FLAG_DUALF: Dual flag + * @arg I2C_FLAG_GENCALL: General call header flag + * @arg I2C_FLAG_TRA: Transmitter/Receiver flag + * @arg I2C_FLAG_BUSY: Bus busy flag + * @arg I2C_FLAG_MSL: Master/Slave flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ + +/* 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_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); diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index 8dd01b49b..82200288b 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -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,78 @@ void TOUCH_AF_INT_Change(void) GPIO_Init(TOUCH_INT_GPIO, &GPIO_InitStructure); } -void I2C_Init() +void I2C_Init_Radio() { 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, 10000) != HAL_OK) + { + TRACE("I2C ERROR: WriteRegister failed"); + asm("bkpt 255"); + 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, 10000) != HAL_OK) + { + TRACE("I2C ERROR: ReadRedister write reg address failed"); + asm("bkpt 255"); 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, 10000) != HAL_OK) + { + TRACE("I2C ERROR: ReadRedister read reg address failed"); + asm("bkpt 255"); + 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 +605,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(); @@ -888,10 +702,10 @@ void touchPanelRead() { uint8_t state = 0; - // if (!touchEventOccured) - // return; + if (!touchEventOccured) + return; - // touchEventOccured = false; + touchEventOccured = false; uint32_t startReadStatus = RTOS_GET_MS(); do { diff --git a/radio/src/targets/horus/tp_gt911.h b/radio/src/targets/horus/tp_gt911.h index 0651dc1b6..5f3f44f8f 100644 --- a/radio/src/targets/horus/tp_gt911.h +++ b/radio/src/targets/horus/tp_gt911.h @@ -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 //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 diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 27d68d9c0..e25ed35c5 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -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 diff --git a/radio/src/targets/taranis/i2c_driver.cpp b/radio/src/targets/taranis/i2c_driver.cpp index 2620312ba..24d15a2c0 100644 --- a/radio/src/targets/taranis/i2c_driver.cpp +++ b/radio/src/targets/taranis/i2c_driver.cpp @@ -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; From 2ca5cc771cb21ead71c713328dcd868f06ed0aae Mon Sep 17 00:00:00 2001 From: rotorman Date: Thu, 15 Jul 2021 21:34:20 +0200 Subject: [PATCH 22/46] Added De-Init and Re-Init (in case this is ever required). --- radio/src/targets/horus/i2c_driver.cpp | 158 ++++++++++++++++++++++--- radio/src/targets/horus/i2c_driver.h | 38 +++--- radio/src/targets/horus/tp_gt911.cpp | 30 +++-- 3 files changed, 175 insertions(+), 51 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp index d47af3221..0a1a99bf9 100644 --- a/radio/src/targets/horus/i2c_driver.cpp +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -77,12 +77,102 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) TRACE("I2C ERROR: HAL_I2C_MspInit() I2C misconfiguration"); } +/* De-initializes the GPIOx peripheral registers to their default reset values. + * @param GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or + * x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices. + * @param GPIO_Pin specifies the port bit to be written. + * This parameter can be one of GPIO_PIN_x where x can be (0..15). + * @retval None + */ +void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin) +{ + uint32_t position; + uint32_t ioposition = 0x00U; + uint32_t iocurrent = 0x00U; + uint32_t tmp = 0x00U; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); + + /* Configure the port pins */ + for(position = 0U; position < GPIO_NUMBER; position++) + { + /* Get the IO position */ + ioposition = 0x01U << position; + /* Get the current IO position */ + iocurrent = (GPIO_Pin) & ioposition; + + if(iocurrent == ioposition) + { + /*------------------------- EXTI Mode Configuration --------------------*/ + tmp = SYSCFG->EXTICR[position >> 2U]; + tmp &= (0x0FU << (4U * (position & 0x03U))); + if(tmp == ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4U * (position & 0x03U)))) + { + /* Clear EXTI line configuration */ + EXTI->IMR &= ~((uint32_t)iocurrent); + EXTI->EMR &= ~((uint32_t)iocurrent); + + /* Clear Rising Falling edge configuration */ + EXTI->RTSR &= ~((uint32_t)iocurrent); + EXTI->FTSR &= ~((uint32_t)iocurrent); + + /* Configure the External Interrupt or event for the current IO */ + tmp = 0x0FU << (4U * (position & 0x03U)); + SYSCFG->EXTICR[position >> 2U] &= ~tmp; + } + + /*------------------------- GPIO Mode Configuration --------------------*/ + /* Configure IO Direction in Input Floating Mode */ + GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (position * 2U)); + + /* Configure the default Alternate Function in current IO */ + GPIOx->AFR[position >> 3U] &= ~(0xFU << ((uint32_t)(position & 0x07U) * 4U)) ; + + /* Deactivate the Pull-up and Pull-down resistor for the current IO */ + GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (position * 2U)); + + /* Configure the default value IO Output Type */ + GPIOx->OTYPER &= ~(GPIO_OTYPER_OT_0 << position) ; + + /* Configure the default value for IO Speed */ + GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2U)); + } + } +} + +/* I2C MSP De-Initialization + * This function freeze the hardware resources used in this example + * @param hi2c: I2C handle pointer + * @retval None + */ +void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) +{ + if(hi2c->Instance==I2C1) + { + __HAL_RCC_I2C1_CLK_DISABLE(); + } else + { + if(hi2c->Instance==I2C2) + { + __HAL_RCC_I2C2_CLK_DISABLE(); + if(hi2c->Instance==I2C3) + { + __HAL_RCC_I2C3_CLK_DISABLE(); + } else + TRACE("I2C ERROR: HAL_I2C_MspDeInit() I2C misconfiguration"); + } + } + HAL_GPIO_DeInit(I2C_GPIO, I2C_SCL_GPIO_PinSource); + HAL_GPIO_DeInit(I2C_GPIO, I2C_SDA_GPIO_PinSource); +} + /* Initializes the I2C according to the specified parameters - * in the HAL_I2C_InitTypeDef and initialize the associated handle. - * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains - * the configuration information for the specified I2C. - * @retval HAL status - */ + * in the HAL_I2C_InitTypeDef and initialize the associated handle. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) { uint32_t freqrange; @@ -172,6 +262,41 @@ HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) return HAL_OK; } +/* DeInitialize the I2C peripheral. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c) +{ + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the I2C Peripheral Clock */ + __HAL_I2C_DISABLE(hi2c); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_I2C_MspDeInit(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_RESET; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + /* Configures I2C Analog noise filter. * @param hi2c pointer to a I2C_HandleTypeDef structure that contains * the configuration information for the specified I2Cx peripheral. @@ -254,11 +379,6 @@ HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_ } } -FlagStatus __HAL_I2C_GET_FLAG(I2C_HandleTypeDef *hi2c, uint32_t Flag) -{ - return I2C_GetFlagStatus(hi2c->Instance, Flag); -} - /* This function handles I2C Communication Timeout. * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains * the configuration information for I2C module @@ -303,9 +423,9 @@ static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uin */ static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) + while (I2C_GetFlagStatus(hi2c->Instance, Flag) == RESET) { - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + if (I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_AF) == SET) { /* Generate Stop */ SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); @@ -419,7 +539,7 @@ static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_ */ static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) { - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + if ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_AF) == SET) { /* Clear NACKF Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); @@ -446,7 +566,7 @@ static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) */ static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) + while ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_TXE) == RESET) { /* Check if a NACK is detected */ if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) @@ -483,7 +603,7 @@ static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, */ static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) + while ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_BTF) == RESET) { /* Check if a NACK is detected */ if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) @@ -589,7 +709,7 @@ HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevA hi2c->XferCount--; hi2c->XferSize--; - if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + if (( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) { /* Write data to DR */ hi2c->Instance->DR = *hi2c->pBuffPtr; @@ -738,10 +858,10 @@ static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) { - while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) + while ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_RXNE) == RESET) { /* Check if a STOPF is detected */ - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) + if ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_STOPF) == SET) { /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); @@ -990,7 +1110,7 @@ HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAd hi2c->XferSize--; hi2c->XferCount--; - if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + if ( I2C_GetFlagStatus(hi2c->Instance, I2C_FLAG_BTF) == SET) { /* Read data from DR */ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; diff --git a/radio/src/targets/horus/i2c_driver.h b/radio/src/targets/horus/i2c_driver.h index c31b44f0c..f2008084d 100644 --- a/radio/src/targets/horus/i2c_driver.h +++ b/radio/src/targets/horus/i2c_driver.h @@ -28,6 +28,19 @@ #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 @@ -226,30 +239,6 @@ UNUSED(tmpreg); \ } while(0) -/* Checks whether the specified I2C flag is set or not. - * @param __HANDLE__ specifies the I2C Handle. - * @param __FLAG__ specifies the flag to check. - * This parameter can be one of the following values: - * @arg I2C_FLAG_OVR: Overrun/Underrun flag - * @arg I2C_FLAG_AF: Acknowledge failure flag - * @arg I2C_FLAG_ARLO: Arbitration lost flag - * @arg I2C_FLAG_BERR: Bus error flag - * @arg I2C_FLAG_TXE: Data register empty flag - * @arg I2C_FLAG_RXNE: Data register not empty flag - * @arg I2C_FLAG_STOPF: Stop detection flag - * @arg I2C_FLAG_ADD10: 10-bit header sent flag - * @arg I2C_FLAG_BTF: Byte transfer finished flag - * @arg I2C_FLAG_ADDR: Address sent flag - * Address matched flag - * @arg I2C_FLAG_SB: Start bit flag - * @arg I2C_FLAG_DUALF: Dual flag - * @arg I2C_FLAG_GENCALL: General call header flag - * @arg I2C_FLAG_TRA: Transmitter/Receiver flag - * @arg I2C_FLAG_BUSY: Bus busy flag - * @arg I2C_FLAG_MSL: Master/Slave flag - * @retval The new state of __FLAG__ (TRUE or FALSE). - */ - /* 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. @@ -391,6 +380,7 @@ typedef struct } 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); diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index 82200288b..6b0471629 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -487,7 +487,7 @@ void TOUCH_AF_INT_Change(void) GPIO_Init(TOUCH_INT_GPIO, &GPIO_InitStructure); } -void I2C_Init_Radio() +void I2C_Init_Radio(void) { TRACE("I2C Init"); @@ -533,7 +533,6 @@ bool I2C_GT911_WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len) if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uAddrAndBuf, len + 2, 10000) != HAL_OK) { TRACE("I2C ERROR: WriteRegister failed"); - asm("bkpt 255"); return false; } return true; @@ -548,14 +547,12 @@ bool I2C_GT911_ReadRegister(uint16_t reg, uint8_t * buf, uint8_t len) if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10000) != HAL_OK) { TRACE("I2C ERROR: ReadRedister write reg address failed"); - asm("bkpt 255"); return false; } if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 10000) != HAL_OK) { TRACE("I2C ERROR: ReadRedister read reg address failed"); - asm("bkpt 255"); return false; } return true; @@ -678,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) { @@ -713,8 +727,8 @@ void touchPanelRead() //ledRed(); touchGT911hiccups++; TRACE("GT911 I2C read XY error"); - touchPanelDeInit(); - touchPanelInit(); + if (!I2C_ReInit()) + TRACE("I2C ReInit failed"); return; } @@ -735,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 || From b86745d8f43492f9cbcc325a3f8852ac76290fb9 Mon Sep 17 00:00:00 2001 From: rotorman Date: Thu, 15 Jul 2021 22:41:12 +0200 Subject: [PATCH 23/46] Clear ADDR bit in atomic way. Not in original STM32F4 HAL. Lower timeouts to more reasonable values. --- radio/src/targets/horus/i2c_driver.cpp | 17 ++++++++--------- radio/src/targets/horus/i2c_driver.h | 4 ++-- radio/src/targets/horus/tp_gt911.cpp | 6 +++--- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp index 0a1a99bf9..9998be448 100644 --- a/radio/src/targets/horus/i2c_driver.cpp +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -28,8 +28,7 @@ uint32_t GetTickCountMS(void) { static uint32_t tickcount = 0; tickcount++; - return (tickcount >> 10); - //return (ticksNow()/CYCLES_IN_MS); + return (tickcount >> 11); // division with 2048, roughly to get milliseconds } /* I2C MSP Initialization @@ -396,7 +395,7 @@ static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uin /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -447,7 +446,7 @@ static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeD /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -577,7 +576,7 @@ static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original: HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -614,7 +613,7 @@ static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, /* Check for the Timeout */ if (Timeout != HAL_MAX_DELAY) { - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -644,7 +643,7 @@ static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) { /* Init tickstart for timeout management*/ - uint32_t tickstart = GetTickCountMS(); // Original: HAL_GetTick(); + uint32_t tickstart = GetTickCountMS(); if (hi2c->State == HAL_I2C_STATE_READY) { @@ -878,7 +877,7 @@ static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, } /* Check for the Timeout */ - if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) // Original HAL_GetTick() + if (((GetTickCountMS() - Tickstart) > Timeout) || (Timeout == 0U)) { hi2c->PreviousState = I2C_STATE_NONE; hi2c->State = HAL_I2C_STATE_READY; @@ -907,7 +906,7 @@ static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) { /* Init tickstart for timeout management*/ - uint32_t tickstart = GetTickCountMS(); // Original HAL_GetTick(); + uint32_t tickstart = GetTickCountMS(); if (hi2c->State == HAL_I2C_STATE_READY) { diff --git a/radio/src/targets/horus/i2c_driver.h b/radio/src/targets/horus/i2c_driver.h index f2008084d..f1c6069bf 100644 --- a/radio/src/targets/horus/i2c_driver.h +++ b/radio/src/targets/horus/i2c_driver.h @@ -234,8 +234,10 @@ #define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ do{ \ __IO uint32_t tmpreg = 0x00U; \ + __disable_irq(); \ tmpreg = (__HANDLE__)->Instance->SR1; \ tmpreg = (__HANDLE__)->Instance->SR2; \ + __enable_irq(); \ UNUSED(tmpreg); \ } while(0) @@ -307,7 +309,6 @@ typedef enum 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 @@ -332,7 +333,6 @@ typedef enum 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 diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index 6b0471629..b49d34a7a 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -530,7 +530,7 @@ bool I2C_GT911_WriteRegister(uint16_t reg, uint8_t * buf, uint8_t len) } } - if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uAddrAndBuf, len + 2, 10000) != HAL_OK) + if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uAddrAndBuf, len + 2, 100) != HAL_OK) { TRACE("I2C ERROR: WriteRegister failed"); return false; @@ -544,13 +544,13 @@ bool I2C_GT911_ReadRegister(uint16_t reg, uint8_t * buf, uint8_t len) uRegAddr[0] = (uint8_t)((reg & 0xFF00) >> 8); uRegAddr[1] = (uint8_t)(reg & 0x00FF); - if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10000) != HAL_OK) + if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10) != HAL_OK) { TRACE("I2C ERROR: ReadRedister write reg address failed"); return false; } - if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 10000) != HAL_OK) + if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 100) != HAL_OK) { TRACE("I2C ERROR: ReadRedister read reg address failed"); return false; From a886c72a556f86d586c83c41dbb474e58657717d Mon Sep 17 00:00:00 2001 From: rotorman Date: Thu, 15 Jul 2021 23:09:33 +0200 Subject: [PATCH 24/46] Cosmetics --- radio/src/targets/horus/i2c_driver.cpp | 29 +++++++++++--------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp index 9998be448..251b40f68 100644 --- a/radio/src/targets/horus/i2c_driver.cpp +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -41,17 +41,14 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) GPIO_InitTypeDef GPIO_InitStruct = {0}; if (I2C_GPIO == GPIOA) __HAL_RCC_GPIOA_CLK_ENABLE(); + else if (I2C_GPIO == GPIOB) + __HAL_RCC_GPIOB_CLK_ENABLE(); + else if (I2C_GPIO == GPIOC) + __HAL_RCC_GPIOC_CLK_ENABLE(); + else if (I2C_GPIO == GPIOH) + __HAL_RCC_GPIOH_CLK_ENABLE(); else - if (I2C_GPIO == GPIOB) - __HAL_RCC_GPIOB_CLK_ENABLE(); - else - if (I2C_GPIO == GPIOC) - __HAL_RCC_GPIOC_CLK_ENABLE(); - else - if (I2C_GPIO == GPIOH) - __HAL_RCC_GPIOH_CLK_ENABLE(); - else - TRACE("I2C ERROR: HAL_I2C_MspInit() I2C_GPIO misconfiguration"); + TRACE("I2C ERROR: HAL_I2C_MspInit() I2C_GPIO misconfiguration"); GPIO_PinAFConfig(I2C_GPIO, I2C_SCL_GPIO_PinSource, I2C_GPIO_AF); GPIO_PinAFConfig(I2C_GPIO, I2C_SDA_GPIO_PinSource, I2C_GPIO_AF); @@ -66,14 +63,12 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) /* Peripheral clock enable */ if (I2C == I2C1) __HAL_RCC_I2C1_CLK_ENABLE(); + else if (I2C == I2C2) + __HAL_RCC_I2C2_CLK_ENABLE(); + else if (I2C == I2C3) + __HAL_RCC_I2C3_CLK_ENABLE(); else - if (I2C == I2C2) - __HAL_RCC_I2C2_CLK_ENABLE(); - else - if (I2C == I2C3) - __HAL_RCC_I2C3_CLK_ENABLE(); - else - TRACE("I2C ERROR: HAL_I2C_MspInit() I2C misconfiguration"); + TRACE("I2C ERROR: HAL_I2C_MspInit() I2C misconfiguration"); } /* De-initializes the GPIOx peripheral registers to their default reset values. From 00f3ec6eec0c3aee07db5355b803d36e444bce49 Mon Sep 17 00:00:00 2001 From: eshifri Date: Thu, 15 Jul 2021 22:43:53 -0700 Subject: [PATCH 25/46] Fix timer edit and time display in logical switch edit --- radio/src/gui/colorlcd/draw_functions.cpp | 10 +++++++++- radio/src/gui/colorlcd/model_logical_switches.cpp | 6 ++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/radio/src/gui/colorlcd/draw_functions.cpp b/radio/src/gui/colorlcd/draw_functions.cpp index a0530c2b0..f9e2a3ab9 100644 --- a/radio/src/gui/colorlcd/draw_functions.cpp +++ b/radio/src/gui/colorlcd/draw_functions.cpp @@ -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,9 @@ 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); + //dc->drawNumber(x, y, lswTimerValue(value), flags | PREC1); } else if (source == MIXSRC_TX_VOLTAGE) { dc->drawNumber(x, y, value, flags|PREC1); diff --git a/radio/src/gui/colorlcd/model_logical_switches.cpp b/radio/src/gui/colorlcd/model_logical_switches.cpp index cbe2d968d..3ac73a1cd 100644 --- a/radio/src/gui/colorlcd/model_logical_switches.cpp +++ b/radio/src/gui/colorlcd/model_logical_switches.cpp @@ -144,14 +144,16 @@ 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); + //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); + //dc->drawNumber(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, lswTimerValue(value), flags | PREC1); + drawTimer(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, value, flags); }); grid.nextLine(); } From acd84f917a52520b576e461555c3c5d9ad96166a Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Fri, 16 Jul 2021 21:11:23 +1000 Subject: [PATCH 26/46] TextEdit should trigger Model save, not Radio save --- radio/src/gui/colorlcd/model_mixes.cpp | 2 +- radio/src/gui/colorlcd/model_outputs.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/gui/colorlcd/model_mixes.cpp b/radio/src/gui/colorlcd/model_mixes.cpp index a6fae37a9..36bdd1000 100644 --- a/radio/src/gui/colorlcd/model_mixes.cpp +++ b/radio/src/gui/colorlcd/model_mixes.cpp @@ -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(); diff --git a/radio/src/gui/colorlcd/model_outputs.cpp b/radio/src/gui/colorlcd/model_outputs.cpp index bbc42f58c..020a46546 100644 --- a/radio/src/gui/colorlcd/model_outputs.cpp +++ b/radio/src/gui/colorlcd/model_outputs.cpp @@ -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); From 5f0bac3dc94a9ee3f4307c4a1dea6dacbd5787b0 Mon Sep 17 00:00:00 2001 From: rotorman Date: Fri, 16 Jul 2021 18:40:52 +0200 Subject: [PATCH 27/46] Rewrore STM32F4 HAL_I2C_MspDeInit to not call HAL_GPIO_DeInit(), but only disable I2C GPIO with GPIO_Init(). --- radio/src/targets/horus/i2c_driver.cpp | 29 ++++++++++++++++++-------- radio/src/targets/horus/tp_gt911.cpp | 4 ++-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.cpp b/radio/src/targets/horus/i2c_driver.cpp index 251b40f68..1bd9b403d 100644 --- a/radio/src/targets/horus/i2c_driver.cpp +++ b/radio/src/targets/horus/i2c_driver.cpp @@ -145,20 +145,31 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) if(hi2c->Instance==I2C1) { __HAL_RCC_I2C1_CLK_DISABLE(); - } else + } + else { if(hi2c->Instance==I2C2) { - __HAL_RCC_I2C2_CLK_DISABLE(); - if(hi2c->Instance==I2C3) - { - __HAL_RCC_I2C3_CLK_DISABLE(); - } else - TRACE("I2C ERROR: HAL_I2C_MspDeInit() I2C misconfiguration"); + __HAL_RCC_I2C2_CLK_DISABLE(); + if(hi2c->Instance==I2C3) + __HAL_RCC_I2C3_CLK_DISABLE(); + else + TRACE("I2C ERROR: HAL_I2C_MspDeInit() I2C misconfiguration"); } } - HAL_GPIO_DeInit(I2C_GPIO, I2C_SCL_GPIO_PinSource); - HAL_GPIO_DeInit(I2C_GPIO, I2C_SDA_GPIO_PinSource); + + GPIO_InitTypeDef GPIO_InitStructure; + + /* Configure the default Alternate Function in current IO */ + GPIO_PinAFConfig(I2C_GPIO, I2C_SCL_GPIO_PinSource, 0); + GPIO_PinAFConfig(I2C_GPIO, I2C_SDA_GPIO_PinSource, 0); + + GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN | I2C_SDA_GPIO_PIN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; /* Configure a low value for IO Speed */ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; /* Configure IO Direction in Input Floating Mode */ + GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; /* Leave the configuration to Open Drain */ + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; /* Deactivate the Pull-up and Pull-down resistor for the current IO */ + GPIO_Init(I2C_GPIO, &GPIO_InitStructure); } /* Initializes the I2C according to the specified parameters diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index b49d34a7a..b9065ad54 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -546,13 +546,13 @@ bool I2C_GT911_ReadRegister(uint16_t reg, uint8_t * buf, uint8_t len) if (HAL_I2C_Master_Transmit(&hi2c1, GT911_I2C_ADDR << 1, uRegAddr, 2, 10) != HAL_OK) { - TRACE("I2C ERROR: ReadRedister write reg address failed"); + TRACE("I2C ERROR: ReadRegister write reg address failed"); return false; } if (HAL_I2C_Master_Receive(&hi2c1, GT911_I2C_ADDR << 1, buf, len, 100) != HAL_OK) { - TRACE("I2C ERROR: ReadRedister read reg address failed"); + TRACE("I2C ERROR: ReadRegister read reg address failed"); return false; } return true; From 64b658371e2b01737a2c22778ae339007c3bc17d Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Sat, 17 Jul 2021 18:24:05 +1000 Subject: [PATCH 28/46] Make default colour first entry For functions/cases where the default colour is not specified --- radio/src/gui/colorlcd/colors.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/colors.h b/radio/src/gui/colorlcd/colors.h index 93c83152c..a670fde42 100644 --- a/radio/src/gui/colorlcd/colors.h +++ b/radio/src/gui/colorlcd/colors.h @@ -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, From 0423b8d28686bc5442e24b73dbc505665fc28556 Mon Sep 17 00:00:00 2001 From: Risto Date: Sat, 17 Jul 2021 14:40:28 +0200 Subject: [PATCH 29/46] Stop disabling interrupts while clearing ADDR bit --- radio/src/targets/horus/i2c_driver.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/radio/src/targets/horus/i2c_driver.h b/radio/src/targets/horus/i2c_driver.h index f1c6069bf..30bb9ffda 100644 --- a/radio/src/targets/horus/i2c_driver.h +++ b/radio/src/targets/horus/i2c_driver.h @@ -234,10 +234,8 @@ #define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ do{ \ __IO uint32_t tmpreg = 0x00U; \ - __disable_irq(); \ tmpreg = (__HANDLE__)->Instance->SR1; \ tmpreg = (__HANDLE__)->Instance->SR2; \ - __enable_irq(); \ UNUSED(tmpreg); \ } while(0) From 82461505fdacb26feaea83b1f5d4323bdc1a0a37 Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Sun, 18 Jul 2021 13:11:37 +1000 Subject: [PATCH 30/46] Replace image to resolve test error --- radio/src/tests/transparency_EN_480x272.png | Bin 8989 -> 9025 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/radio/src/tests/transparency_EN_480x272.png b/radio/src/tests/transparency_EN_480x272.png index a1cc5987bb553b3e4b43a3a3ca9b8fd0e5fe2023..301584068b0c709c06228a5dc6c14ba7d5fd8ddf 100644 GIT binary patch delta 1100 zcmbR1cF=8tGLtgLM%8PghJF^C6HHQtB$-&%I2R|HN--@~WZ+?x61(t&d(FiQ^1O`~ z1tdVk0ePmy$rl!Drc6E{Vm7&3ihuGn1;NQvh2<3@+>#4Fv>)hHS9c3B@m+9W`{LaK z?!{jUxEe1SzPR|sX7WU!25D*j$##m4n(tI(o_T&gCfTU?{IGm^-GsN#i)9Z9A|4s7vfiMw85B9R;n)2~s?hXNUx80CoB5TR1;BD%{7&Iafaa#P)B;XN!yM zs4NkGlu;%TqiA4t#Bi39`{Z~fv&kpqlqYkE^Gr5YP}k@7bvoee+LTjl8FAwNL5%~> z`^s4&PVDFYcxP&xc;V#W*z#v?i;T#U3_i9` z^W$#i@VT7I*GsWqGI30DTYvg=>jd%(A>bq*sE-P;u}BvPiYBBiwcbk zK8^SIm7d)Ht1%(aVAe18N{AH~fmWCUgN=W3tCFp`hjYWCxh;ZxT#E&*rI-$@v9P?G zP;aiFx?4aJ=-$>J&F&3vKKwsm(3rCq7^p8Nzj2Sgu$cADWO)hm$rTC#`VCv=wit8C zxHXrXu(&xhcysKjaID*~A)rX|5&NdMe+!#x)cfB#E%DcrkbNYfn>#s9$s8$olyq3i zgziNM7)s4stY{#`w1u}(|H*r{lpl@<^<3K6Q+{Wch%40^9ep8iJmaA;l6RH#brv6V zoiCta;HhwX5vPd7$K!M5Q(pi3*jCeRsj)LX-z2cF?LY=cgL6VjN3w}x&*X!0TF^LA zhDNHgcDWE=;}@rsdPn5T{U*FUET11YVQqLr`=5rV624OxFTH`O-;x<<+~fc$8SQ4E zf4}GOeqI7hIF60{C-1jv9B}#<+abdv^5Ut4Znm3q!jF~%8QfJSrjrlIX#?%HnS4`0 zMWe}>MdM~`#p83lo1DKLp3R@~`soA3dTqtyFZ7OFykl^}3G86cKB$AGCv!{N8aV

wzF+BZ|Hab+?wb|A2}tBR_AdjaK2Xx| zR|jc|YYXMzND-Ovc0NCk@QG``AG4?){E=WH+SkT#O#l>~z7mrUh`CKZFX<}U)5c)J z()JAKg%{H2AbDXQC@;89j**g|d|z5ga&F6F&temn6#`7mTY-uAQ(HMl&$b2b!9RdW zsnx3C1*u~j!a&Js+V3WSgi)O3p(7+v6CB;Ynil`PdTk|o4I)`4%4L@sOnX7o`;oDc4#omXn<5#xq+IozF|sSQp)K3_1wZ#39NLntPv6lF7@I%6NGBjkXO zqhOj8f^iZBj3QMNEx%iH%^G02Qm{zQj!uj3zH9jyJ;Gy>vg_03w}R^+KR^Ywxbaj&jF>Tt-J1GpdtMrFp{|m zQFIDyDe?ToGd$l~7G4&l4j{-{;G;t-^&~2-ntt59LD@T28)9LdyY4%B676Y8RGc;U zr_Ju_Jw*z>L0g}7wrvkrG)aF?8h!erv9nFn54T;Cwx07k$2t_d(?sBj80GoKL-t>w zx!`3|^16=aW(Yr1TO{Mqgigkx3`q8GrC21Sla0WSHp?=9bCNA>uNdZEim(@JjL`Ge z)8V)Xb|JVVbppGJ)Tz#DB0f$Ja~Y4L3=7=JdD#oy8g!_z{Bo0w+JF z2^t=EVs;ngTiOZGz{@H-(o8Jf`hcoawzpchsxRP0EA{FX>`}Mzn8WX384=s@Svt7} zgvC`r0O=1AYVGBrbfH8z`e7^Oj#YaF;?=BL$92bkLVa=HEvj*BK`LY)>k32Ct_j&5 z=}O(zF8WXIXVO;#m3?4V?gSc) zBw?hPbqhez>1@@5hay4h^!)Qb5cSdp)AvtAaDGe=DCreRi0>wD^Bd#gEFU!Ue9*vG zz675WIUuYOf_F0rcrPjOhN_*0`8O?&P&3g~F$@CEbvWXLH*+WL;NG6JE5MXEQy$N1 z9!;=>Y-m`MZwa1_--U8$D^CCT-X3>y#1czraPX7?w_7{@`WMp|HlV@|f=^|+36L7t w&QKQk4sXS Date: Sun, 18 Jul 2021 13:42:47 +1000 Subject: [PATCH 31/46] Replace image to resolve test error (CN) --- radio/src/tests/transparency_CN_480x272.png | Bin 9206 -> 9228 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/radio/src/tests/transparency_CN_480x272.png b/radio/src/tests/transparency_CN_480x272.png index 92083a206f956f9e805ec8a2c652f29351f35f5a..a6ee82449dfaf6e0943823681abd701adf67dcd9 100644 GIT binary patch delta 1042 zcmez7-s3Srh4J!6)#YM_a|_ZAW}H$nV&U=;ayy)5!s6!4Ai-p!v*4q6#NvhaQcQ~# z4M0SLJ&W7%1@6HoCMzgJPCh5jJNc)CfRcxEL#jy{TRq2|ilQVJ*UKziHP*Yh3r*bl zmkUVbI`%JnKG|PE3#wdyvZkz(<_o_=iSy#}<_Jm@+5IVe&VDoRUt#;7*y*BzVvCm^ z&*0!$B_JXDNWyo*R_<3tA7n5ICOE zB{SJjPHS?XsO4lXDRuo;HN^)Dl^nP2l+k(eK0)Mx;(co-ohSEOD;}TY-K2Xh;G%?Y zE6_8hEN<-NLE2BR=beg-uYR*0i-^mK`<^Ep9lM?-DAcPzY&Vxb!FODm zXYpFv0UTi@c0DZroV?B|FOBT@yT(S1TXmB%<;3_ zo-0M9XW2hTIi|(BFD|NBP5!88HrYWsT5|&@W25zx`@9|}^<3D*K9wu}dmyM_{m0(G zMjegSjvR%MF<#5%>(P*!rQ3-Q5O6eDg7zwl&C+t0W&~m>mH|xwFh-&E&}+<;^DV77tLr z>uE8|q&<{_BSmDw+xh%F!Y8i%e$1kJ@JE7)XkQz{HE@1W>w)GMnaPyhmA0 Ymmj)#YM_ZzBqmOj3m;nM4J}7AKlYF)dbP;9-;!yYPd1&BY7yyp0zH zBtXOgd8Wn57Zz)#OiolZn_ME|ptwZwfRU7Ovpox6Ooid0MV)_Qr!U?u;9mTtfUEJM z*q4l|$pzBtlcy^NOs){&(dM}%AaU2z;>_e_jb|==Uchjgf0JzO<8!>5zGkh+=n)H9 ztZ1;pDPaq%?JR}KYn4(aXGkecJ}1wiC}hJdY$3z*gN zR~DGCY-l_1Lg0ADA&JQkgv}<)$pz^wewliqwc&v5r}u12QpA;*xqt2!sQ@2gG^~>bHVr7#z$O);Js6Wi8l8jUQ@QC&2zr=-4jE?Z9-2VNT z<)@$A-Byb|#veeIFxpN&FP%KOLRwGm181ZDllN>XKO7J0xwNsTv_E{IcjVz*M)&9o zi&@`HUMtzEKVjSC0=LG)86W!E4rFj7v>j*>7kT6K=R@-!g{2Pq#~EI(U9m#K*U1Iq zfuPCvh0THP=bzlJC?9YjgS*Ovw+EyVNEmQ5UR3P6m|_EpO#>;WW)l{UH!6EJDkPb_ za&t~FVabqUQnw2z5?2Cx)v_*NL-RzTy&^5oJZ`sI+-j23t#O;YPRVTY4&gv8oy7-T z=L@Xp*s$QhBH@(Rq6rHVmP<0TR$00QUjy02uvF2&>WJa2Hkg(m9c#{ZhpL4s;*WZ* z%};!L*lzyh{?y|Ko&SY7^<9kZSiJN`21kQ)LPjlf9QCS@>rhmySh3%^5& z^WscGOn|z0**=vk8U<{aJfX3*X>H4t7fT=T9lMy64s^R96DTfTW&smow{~G0gX(Sp z`wou@vYYHHSWfhd@_l+A2n^x9{N z=EE$TzW%dt>@1g?u>L1At2JkR&pRiXvu!sZj!XqPvO}s|sBhVHM{y?SBJoE+hhCiH z(hNy}VXy=!4>Fc#wSdHm*bW(yH!4pg_5wx3A3-8xiQ!~^kq%j47MK<1=FA|)H06yG zM1|}{1s1n<3%AKvfytm-Y_Xz4tH26iRP!FcD6pW4qld4sM{U()J|(xw#}pNTc}Z^a bC1o{{He2uAa~I4JW&i?DS3j3^P6 Date: Sun, 18 Jul 2021 09:52:48 +0200 Subject: [PATCH 32/46] [color] fixed MPM options (esp. DSM related) --- radio/src/gui/colorlcd/model_setup.cpp | 165 +++++++++++++++++++------ 1 file changed, 125 insertions(+), 40 deletions(-) diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 75149e8b2..3eb1b2286 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -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,111 @@ 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) { + if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) { + // Multi optional feature row + const char *title = getMultiOptionTitle(moduleIdx); 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)); + new StaticText(this, grid.getLabelSlot(true), title); - //Show RSSI next to RF Freq Fine Tune - if (getMultiOptionTitle(moduleIdx) == STR_MULTI_RFTUNE) - { - new DynamicNumber(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 (getMultiOptionTitle(moduleIdx) == STR_MULTI_RFTUNE) { + new DynamicNumber( + 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(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) From ef08fc019f1130b17546016a9436c1090ae4a426 Mon Sep 17 00:00:00 2001 From: rotorman Date: Sun, 18 Jul 2021 11:32:14 +0200 Subject: [PATCH 33/46] Incremented GT911 configuration with +1 and stopped writing it to GT911 on init/start if the same version has already been flashed to GT911 (as previously). --- radio/src/targets/horus/tp_gt911.cpp | 2 +- radio/src/targets/horus/tp_gt911.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/targets/horus/tp_gt911.cpp b/radio/src/targets/horus/tp_gt911.cpp index b9065ad54..667df4b50 100644 --- a/radio/src/targets/horus/tp_gt911.cpp +++ b/radio/src/targets/horus/tp_gt911.cpp @@ -638,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()) diff --git a/radio/src/targets/horus/tp_gt911.h b/radio/src/targets/horus/tp_gt911.h index 5f3f44f8f..d0fe6e903 100644 --- a/radio/src/targets/horus/tp_gt911.h +++ b/radio/src/targets/horus/tp_gt911.h @@ -33,7 +33,7 @@ bool touchPanelEventOccured(); #define GT911_TIMEOUT 3 // 3ms #define GT911_MAX_TP 5 -#define GT911_CFG_NUMER 0x6C +#define GT911_CFG_NUMER 0x6D //I2C #define GT911_I2C_ADDR 0x14 From 311c0931334f24f3e41490016636a491e7e834b0 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Jul 2021 12:44:12 +0200 Subject: [PATCH 34/46] PR 461 cleanup --- radio/src/gui/colorlcd/model_logical_switches.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/radio/src/gui/colorlcd/model_logical_switches.cpp b/radio/src/gui/colorlcd/model_logical_switches.cpp index 3ac73a1cd..ea91b8550 100644 --- a/radio/src/gui/colorlcd/model_logical_switches.cpp +++ b/radio/src/gui/colorlcd/model_logical_switches.cpp @@ -144,7 +144,6 @@ 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(); @@ -152,7 +151,6 @@ class LogicalSwitchEditPage: public Page 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(); From c981f4f1dbc7e07fa9fe496e3890293e6eadf270 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Jul 2021 12:45:14 +0200 Subject: [PATCH 35/46] Another PR 461 cleanup --- radio/src/gui/colorlcd/draw_functions.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/gui/colorlcd/draw_functions.cpp b/radio/src/gui/colorlcd/draw_functions.cpp index f9e2a3ab9..e08966048 100644 --- a/radio/src/gui/colorlcd/draw_functions.cpp +++ b/radio/src/gui/colorlcd/draw_functions.cpp @@ -445,7 +445,6 @@ void drawSourceCustomValue(BitmapBuffer * dc, coord_t x, coord_t y, source_t sou // TODO if (value < 0) flags |= BLINK|INVERS; if (source == MIXSRC_TX_TIME) flags |= TIMEHOUR; drawTimer(dc, x, y, value, flags); - //dc->drawNumber(x, y, lswTimerValue(value), flags | PREC1); } else if (source == MIXSRC_TX_VOLTAGE) { dc->drawNumber(x, y, value, flags|PREC1); From b553713527e22a9473c8b5662eb77353fc3fb194 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Jul 2021 19:49:12 +0200 Subject: [PATCH 36/46] Fixed german translation file (logic switches) --- radio/src/translations/de.h.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index de1c9e9cb..7b99fb514 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -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 ""ax""|a|b\0 ""ax\0 ""ax""|a|b\0 ""a Date: Mon, 19 Jul 2021 09:29:27 +0200 Subject: [PATCH 37/46] [color] Fix MPM option title==nullptr --- radio/src/gui/colorlcd/model_setup.cpp | 105 ++++++++++++++----------- 1 file changed, 58 insertions(+), 47 deletions(-) diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 3eb1b2286..c46aae3e3 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -688,57 +688,68 @@ class ModuleWindow : public FormGroup { if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) { // Multi optional feature row const char *title = getMultiOptionTitle(moduleIdx); - grid.nextLine(); - new StaticText(this, grid.getLabelSlot(true), title); + if (title != nullptr) { + grid.nextLine(); + new StaticText(this, grid.getLabelSlot(true), title); - //int optionValue = g_model.moduleData[moduleIdx].multi.optionValue; - int8_t min, max; - getMultiOptionValues(multi_proto, min, max); + // 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)); + 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 { - new NumberEdit( - this, grid.getFieldSlot(2, 0), -128, 127, - GET_SET_DEFAULT( - g_model.moduleData[moduleIdx].multi.optionValue)); + 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 (getMultiOptionTitle(moduleIdx) == STR_MULTI_RFTUNE) { - new DynamicNumber( - this, grid.getFieldSlot(2, 1), - [] { return (int)TELEMETRY_RSSI(); }, 0, "RSSI: ", " db"); + // Show RSSI next to RF Freq Fine Tune + if (title == STR_MULTI_RFTUNE) { + new DynamicNumber( + this, grid.getFieldSlot(2, 1), + [] { return (int)TELEMETRY_RSSI(); }, 0, "RSSI: ", " db"); + } } } } From 69283a7d5c2e861bf4f4c78f6e9a528891bba961 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 19 Jul 2021 12:36:11 +0200 Subject: [PATCH 38/46] [color] fix mix/input copy/paste --- radio/src/gui/colorlcd/model_inputs.cpp | 25 +++++++++++----------- radio/src/gui/colorlcd/model_mixes.cpp | 28 ++++++++++++------------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/radio/src/gui/colorlcd/model_inputs.cpp b/radio/src/gui/colorlcd/model_inputs.cpp index a28b1e0dd..2157ac2b3 100644 --- a/radio/src/gui/colorlcd/model_inputs.cpp +++ b/radio/src/gui/colorlcd/model_inputs.cpp @@ -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; } diff --git a/radio/src/gui/colorlcd/model_mixes.cpp b/radio/src/gui/colorlcd/model_mixes.cpp index 36bdd1000..1e67b5656 100644 --- a/radio/src/gui/colorlcd/model_mixes.cpp +++ b/radio/src/gui/colorlcd/model_mixes.cpp @@ -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); } From 36bddfb8d2604fd773abad7bebf681c19dbc61c7 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 19 Jul 2021 13:10:53 +0200 Subject: [PATCH 39/46] [color] MPM options: use static options rather than the dynamic ones This is necessary until a broader solution is found to display real-time info coming from the MPM. --- radio/src/gui/colorlcd/model_setup.cpp | 2 +- radio/src/gui/gui_common.cpp | 14 +++++++++----- radio/src/gui/gui_common.h | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index c46aae3e3..783fc656e 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -687,7 +687,7 @@ class ModuleWindow : public FormGroup { const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol(); if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) { // Multi optional feature row - const char *title = getMultiOptionTitle(moduleIdx); + const char *title = getMultiOptionTitleStatic(moduleIdx); if (title != nullptr) { grid.nextLine(); new StaticText(this, grid.getLabelSlot(true), title); diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index f703aa5e3..058c20765 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -1100,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); @@ -1110,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 diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 46efa21d0..dff36d222 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -355,6 +355,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(); From 8266948e098c4bb1f006f319554f634beb92cc52 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 19 Jul 2021 13:15:25 +0200 Subject: [PATCH 40/46] Use static table to determine the existence of channel mapping option --- radio/src/gui/colorlcd/model_setup.cpp | 2 +- radio/src/gui/gui_common.h | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 783fc656e..f045fabfc 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -793,7 +793,7 @@ class ModuleWindow : public FormGroup { GET_SET_DEFAULT( g_model.moduleData[moduleIdx].multi.disableTelemetry)); - if (MULTI_DISABLE_CHAN_MAP_ROW(moduleIdx) != HIDDEN_ROW) { + 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); diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index dff36d222..e59b5df57 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -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) From 3eeca550dad17b174848f9bea59a0e5b8d45b9d5 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 20 Jul 2021 10:46:54 +0200 Subject: [PATCH 41/46] Wait 200ms after switching external module OFF on model change --- radio/src/storage/storage_common.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/storage/storage_common.cpp b/radio/src/storage/storage_common.cpp index 439032e74..0a7c81564 100644 --- a/radio/src/storage/storage_common.cpp +++ b/radio/src/storage/storage_common.cpp @@ -58,6 +58,7 @@ void preModelLoad() #endif #if defined(HARDWARE_EXTERNAL_MODULE) stopPulsesExternalModule(); + RTOS_WAIT_MS(200); #endif stopTrainer(); From 648514dc5032a5c6b80a15b06b7428f84a6a275d Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 20 Jul 2021 13:42:54 +0200 Subject: [PATCH 42/46] Updated version for next release --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80c365e64..8b14b9256 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 From d3c16a89c4b5866788faaddfec3f7e11df19366d Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 20 Jul 2021 13:45:59 +0200 Subject: [PATCH 43/46] Added "main" to the branches built automatically --- .github/workflows/actions.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 69076f2b6..a951d29b3 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -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/**' From c832a74114782c04f69c2b0ce695a9a17887ea5c Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 22 Jul 2021 09:00:26 +0200 Subject: [PATCH 44/46] [color] fix statistics view (now displays proper numbers) --- radio/src/gui/colorlcd/view_statistics.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/radio/src/gui/colorlcd/view_statistics.h b/radio/src/gui/colorlcd/view_statistics.h index f9632e628..5305dbca5 100644 --- a/radio/src/gui/colorlcd/view_statistics.h +++ b/radio/src/gui/colorlcd/view_statistics.h @@ -32,19 +32,19 @@ class DebugInfoNumber : public Window public: DebugInfoNumber(Window * parent, const rect_t & rect, std::function 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(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(this, {prefixSize, 0, rect.w - prefixSize, rect.h}, + numberHandler); } protected: - std::function numberHandler; const char * prefix; const char * suffix; }; From 44d4d25f4f2fb35febd26c87c4001952c51e5687 Mon Sep 17 00:00:00 2001 From: eshifri Date: Tue, 20 Jul 2021 19:55:23 -0700 Subject: [PATCH 45/46] [color] Fix timer display problem --- radio/src/gui/colorlcd/widgets/timer.cpp | 6 +++ radio/src/gui/colorlcd/widgets/value.cpp | 57 +++++++++++++++--------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/radio/src/gui/colorlcd/widgets/timer.cpp b/radio/src/gui/colorlcd/widgets/timer.cpp index 389303acb..eb2c0db2a 100644 --- a/radio/src/gui/colorlcd/widgets/timer.cpp +++ b/radio/src/gui/colorlcd/widgets/timer.cpp @@ -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: diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp index 6c8821a2a..e2ed19f9a 100644 --- a/radio/src/gui/colorlcd/widgets/value.cpp +++ b/radio/src/gui/colorlcd/widgets/value.cpp @@ -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 From fd94ffeb86178f1695ff263edaf2f18cf4c31043 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 21 Jul 2021 08:55:46 +0200 Subject: [PATCH 46/46] Fix colorlcd FRM302 (#8624) --- radio/src/pulses/pulses.cpp | 2 +- radio/src/targets/horus/extmodule_driver.cpp | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 9169a9b6e..d1f067d53 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -311,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 diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index 878e3ffea..80737d3b5 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -325,19 +325,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;