diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 0c419213a..d7a9efc27 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -19,7 +19,7 @@ option(AUTOSOURCE "Automatic source detection in menus" ON) option(AUTOSWITCH "Automatic switch detection in menus" ON) option(JITTER_MEASURE "Enable ADC jitter measurement" OFF) option(JITTER_FILTER "Enable ADC jitter filtering" ON) -option(WATCHDOG_DISABLED "Disable hardware Watchdog on Horus" ON) # TODO remove it when it's OK +option(WATCHDOG_DISABLED "Disable hardware Watchdog on Horus" OFF) # TODO remove it when it's OK enable_language(ASM) set(OPT s) @@ -441,6 +441,7 @@ if(CPU_FAMILY STREQUAL STM32) foreach(FILE ${STM32USB_SRC}) set(FIRMWARE_SRC ${FIRMWARE_SRC} ${STM32USB_DIR}/${FILE}) endforeach() + set(SRC ${SRC} sbus.cpp) endif() if(ARCH STREQUAL ARM) @@ -510,7 +511,6 @@ if(ARCH STREQUAL ARM) main_arm.cpp tasks_arm.cpp audio_arm.cpp - sbus.cpp telemetry/telemetry.cpp telemetry/frsky.cpp telemetry/frsky_d_arm.cpp diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index 0e1d41370..669ac9634 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -498,11 +498,13 @@ int cliDebugVars(const char ** argv) #if defined(PCBHORUS) extern uint32_t ioMutexReq, ioMutexRel; extern uint32_t sdReadRetries; - serialPrint("ioMutexReq=%d", ioMutexReq); serialPrint("ioMutexRel=%d", ioMutexRel); serialPrint("sdReadRetries=%d", sdReadRetries); +#elif defined(PCBTARANIS) + serialPrint("telemetryErrors=%d", telemetryErrors); #endif + return 0; } diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 35b93eee2..09bee8e97 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -150,49 +150,53 @@ enum CurveType { #define MAX_POINTS 17 #if defined(PCBHORUS) - #define LEN_MODEL_NAME 15 - #define LEN_TIMER_NAME 8 - #define LEN_FLIGHT_MODE_NAME 10 - #define LEN_BITMAP_NAME 10 - #define LEN_EXPOMIX_NAME 6 - #define LEN_CHANNEL_NAME 6 - #define LEN_INPUT_NAME 4 - #define LEN_CURVE_NAME 3 - #define MAX_CURVES 32 - #define NUM_POINTS 512 + #define LEN_MODEL_NAME 15 + #define LEN_TIMER_NAME 8 + #define LEN_FLIGHT_MODE_NAME 10 + #define LEN_BITMAP_NAME 10 + #define LEN_EXPOMIX_NAME 6 + #define LEN_CHANNEL_NAME 6 + #define LEN_INPUT_NAME 4 + #define LEN_CURVE_NAME 3 + #define LEN_CFN_NAME 10 + #define MAX_CURVES 32 + #define NUM_POINTS 512 #elif defined(PCBFLAMENCO) - #define LEN_MODEL_NAME 12 - #define LEN_TIMER_NAME 8 - #define LEN_FLIGHT_MODE_NAME 10 - #define LEN_EXPOMIX_NAME 6 - #define LEN_CHANNEL_NAME 6 - #define LEN_INPUT_NAME 4 - #define LEN_CURVE_NAME 3 - #define MAX_CURVES 32 - #define NUM_POINTS 512 + #define LEN_MODEL_NAME 12 + #define LEN_TIMER_NAME 8 + #define LEN_FLIGHT_MODE_NAME 10 + #define LEN_EXPOMIX_NAME 6 + #define LEN_CHANNEL_NAME 6 + #define LEN_INPUT_NAME 4 + #define LEN_CURVE_NAME 3 + #define LEN_CFN_NAME 8 + #define MAX_CURVES 32 + #define NUM_POINTS 512 #elif defined(PCBTARANIS) - #define LEN_MODEL_NAME 12 - #define LEN_TIMER_NAME 8 - #define LEN_FLIGHT_MODE_NAME 10 - #define LEN_BITMAP_NAME 10 - #define LEN_EXPOMIX_NAME 8 - #define LEN_CHANNEL_NAME 6 - #define LEN_INPUT_NAME 4 - #define LEN_CURVE_NAME 3 - #define MAX_CURVES 32 - #define NUM_POINTS 512 + #define LEN_MODEL_NAME 12 + #define LEN_TIMER_NAME 8 + #define LEN_FLIGHT_MODE_NAME 10 + #define LEN_BITMAP_NAME 10 + #define LEN_EXPOMIX_NAME 8 + #define LEN_CHANNEL_NAME 6 + #define LEN_INPUT_NAME 4 + #define LEN_CURVE_NAME 3 + #define LEN_CFN_NAME 8 + #define MAX_CURVES 32 + #define NUM_POINTS 512 #elif defined(CPUARM) - #define LEN_MODEL_NAME 10 - #define LEN_TIMER_NAME 3 - #define LEN_FLIGHT_MODE_NAME 6 - #define LEN_EXPOMIX_NAME 6 - #define MAX_CURVES 16 - #define NUM_POINTS 512 + #define LEN_MODEL_NAME 10 + #define LEN_TIMER_NAME 3 + #define LEN_FLIGHT_MODE_NAME 6 + #define LEN_EXPOMIX_NAME 6 + #define LEN_CFN_NAME 6 + #define MAX_CURVES 16 + #define NUM_POINTS 512 #else - #define LEN_MODEL_NAME 10 - #define LEN_FLIGHT_MODE_NAME 6 - #define MAX_CURVES 8 - #define NUM_POINTS (112-MAX_CURVES) + #define LEN_MODEL_NAME 10 + #define LEN_FLIGHT_MODE_NAME 6 + #define MAX_CURVES 8 + #define NUM_POINTS (112-MAX_CURVES) #endif #if defined(PCBTARANIS) || defined(PCBSKY9X) || defined(PCBHORUS) @@ -265,6 +269,36 @@ enum BeeperMode { e_mode_all }; +#if defined(PCBFLAMENCO) + enum ModuleIndex { + EXTERNAL_MODULE, + TRAINER_MODULE, + }; + enum TrainerMode { + TRAINER_MODE_MASTER, + TRAINER_MODE_SLAVE + }; +#elif defined(PCBTARANIS) || defined(PCBHORUS) + enum ModuleIndex { + INTERNAL_MODULE, + EXTERNAL_MODULE, + TRAINER_MODULE + }; + enum TrainerMode { + TRAINER_MODE_MASTER_TRAINER_JACK, + TRAINER_MODE_SLAVE, + TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE, + TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, + TRAINER_MODE_MASTER_BATTERY_COMPARTMENT, + }; +#elif defined(PCBSKY9X) + enum ModuleIndex { + EXTERNAL_MODULE, + EXTRA_MODULE, + TRAINER_MODULE + }; +#endif + enum UartModes { #if defined(CLI) || defined(DEBUG) UART_MODE_DEBUG, @@ -498,7 +532,7 @@ enum PotsWarnMode { #define GVAR_MIN -GVAR_MAX #endif -#define RESERVE_RANGE_FOR_GVARS 10 +#define RESERVE_RANGE_FOR_GVARS 10 // even we do not spend space in EEPROM for 10 GVARS, we reserve the space inside the range of values, like offset, weight, etc. #if defined(PCBSTD) && defined(GVARS) @@ -513,12 +547,6 @@ enum PotsWarnMode { #endif #endif -#if defined(PCBTARANIS) - #define LEN_CFN_NAME 8 -#elif defined(CPUARM) - #define LEN_CFN_NAME 6 -#endif - enum SwitchSources { SWSRC_NONE = 0, diff --git a/radio/src/definitions.h b/radio/src/definitions.h new file mode 100644 index 000000000..9f95c2ded --- /dev/null +++ b/radio/src/definitions.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DEFINITIONS_H_ +#define _DEFINITIONS_H_ + +#if defined(SIMU) + #define __ALIGNED +#else + #define __ALIGNED __attribute__((aligned(32))) +#endif + +#if defined(SIMU) + #define __DMA +#elif defined(STM32F4) && !defined(BOOT) + #define __DMA __attribute__((section(".ram"), aligned(32))) +#else + #define __DMA __ALIGNED +#endif + +#if defined(PCBHORUS) && !defined(SIMU) + #define __SDRAM __attribute__((section(".sdram"), aligned(32))) +#else + #define __SDRAM __DMA +#endif + +#if defined(SIMU) || defined(CPUARM) || GCC_VERSION < 472 + typedef int32_t int24_t; +#else + typedef __int24 int24_t; +#endif + +#endif // _DEFINITIONS_H_ diff --git a/radio/src/dmafifo.h b/radio/src/dmafifo.h new file mode 100644 index 000000000..d4aaef4d3 --- /dev/null +++ b/radio/src/dmafifo.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DMA_FIFO_H_ +#define _DMA_FIFO_H_ + +#include "definitions.h" + +template +class DMAFifo +{ + public: + DMAFifo(DMA_Stream_TypeDef * stream): + stream(stream), + ridx(0) + { + } + + void clear() + { + ridx = 0; + } + + uint32_t size() + { + return N; + } + + bool isEmpty() + { +#if defined(SIMU) + return true; +#endif + return (ridx == N - stream->NDTR); + } + + bool pop(uint8_t & element) + { + if (isEmpty()) { + return false; + } + else { + element = fifo[ridx]; + ridx = (ridx+1) & (N-1); + return true; + } + } + + uint8_t * buffer() + { + return fifo; + } + + protected: + uint8_t fifo[N]; + DMA_Stream_TypeDef * stream; + volatile uint32_t ridx; +}; + +#endif // _DMA_FIFO_H_ diff --git a/radio/src/fifo.h b/radio/src/fifo.h index 933a332e6..e8dc3e624 100644 --- a/radio/src/fifo.h +++ b/radio/src/fifo.h @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -36,7 +36,8 @@ class Fifo widx = ridx = 0; } - void push(T element) { + void push(T element) + { uint32_t next = (widx+1) & (N-1); if (next != ridx) { fifo[widx] = element; @@ -44,7 +45,8 @@ class Fifo } } - bool pop(T & element) { + bool pop(T & element) + { if (isEmpty()) { return false; } @@ -55,16 +57,19 @@ class Fifo } } - bool isEmpty() { + bool isEmpty() + { return (ridx == widx); } - bool isFull() { + bool isFull() + { uint32_t next = (widx+1) & (N-1); return (next == ridx); } - void flush() { + void flush() + { while (!isEmpty()) {}; } diff --git a/radio/src/gui/gui_helpers.cpp b/radio/src/gui/gui_helpers.cpp index 45461f8b4..cc267cbca 100644 --- a/radio/src/gui/gui_helpers.cpp +++ b/radio/src/gui/gui_helpers.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -157,7 +157,7 @@ bool isSourceAvailable(int source) if (source>=MIXSRC_FIRST_SWITCH && source<=MIXSRC_LAST_SWITCH) { return SWITCH_EXISTS(source-MIXSRC_FIRST_SWITCH); } - + #if !defined(HELI) if (source>=MIXSRC_CYC1 && source<=MIXSRC_CYC3) return false; @@ -227,7 +227,7 @@ bool isInputSourceAvailable(int source) if (source>=MIXSRC_FIRST_SWITCH && source<=MIXSRC_LAST_SWITCH) return SWITCH_EXISTS(source-MIXSRC_FIRST_SWITCH); - + if (source>=MIXSRC_FIRST_CH && source<=MIXSRC_LAST_CH) return true; @@ -470,6 +470,16 @@ bool isRfProtocolAvailable(int protocol) return true; } +#if defined(PCBHORUS) || defined(PCBTARANIS) +bool isTrainerModeAvailable(int mode) +{ + if (IS_EXTERNAL_MODULE_PRESENT() && (mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || mode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)) + return false; + else + return true; +} +#endif + bool modelHasNotes() { char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/"; diff --git a/radio/src/gui/gui_helpers.h b/radio/src/gui/gui_helpers.h index 9c1238055..e63b8d997 100644 --- a/radio/src/gui/gui_helpers.h +++ b/radio/src/gui/gui_helpers.h @@ -46,6 +46,7 @@ bool isSwitchAvailableInMixes(int swtch); bool isSwitchAvailableInTimers(int swtch); bool isModuleAvailable(int module); bool isRfProtocolAvailable(int protocol); +bool isTrainerModeAvailable(int mode); bool isSensorUnit(int sensor, uint8_t unit); bool isCellsSensor(int sensor); diff --git a/radio/src/gui/horus/bitmapbuffer.cpp b/radio/src/gui/horus/bitmapbuffer.cpp index 3fc9f44fb..309c35c35 100644 --- a/radio/src/gui/horus/bitmapbuffer.cpp +++ b/radio/src/gui/horus/bitmapbuffer.cpp @@ -274,9 +274,9 @@ void BitmapBuffer::drawSizedText(coord_t x, coord_t y, const pm_char * s, uint8_ if (FONTSIZE(flags) == TINSIZE) drawSolidFilledRect(x-INVERT_HORZ_MARGIN+2, y-INVERT_VERT_MARGIN+2, width+2*INVERT_HORZ_MARGIN-5, INVERT_LINE_HEIGHT-7, TEXT_INVERTED_BGCOLOR); else if (FONTSIZE(flags) == SMLSIZE) - drawSolidFilledRect(x-INVERT_HORZ_MARGIN+1, y-INVERT_VERT_MARGIN, width+2*INVERT_HORZ_MARGIN-2, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR); + drawSolidFilledRect(x-INVERT_HORZ_MARGIN, y+1, width+2*INVERT_HORZ_MARGIN-2, INVERT_LINE_HEIGHT-5, TEXT_INVERTED_BGCOLOR); else - drawSolidFilledRect(x-INVERT_HORZ_MARGIN, y/*-INVERT_VERT_MARGIN*/, width+2*INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR); + drawSolidFilledRect(x-INVERT_HORZ_MARGIN, y, width+2*INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR); } char str[256]; diff --git a/radio/src/gui/horus/bitmaps.cpp b/radio/src/gui/horus/bitmaps.cpp index 177bcbba8..309b396ac 100644 --- a/radio/src/gui/horus/bitmaps.cpp +++ b/radio/src/gui/horus/bitmaps.cpp @@ -96,10 +96,15 @@ const uint8_t LBM_STATS_DEBUG_ICON[] = { #include "mask_stats_debug.lbm" }; +const uint8_t LBM_STATS_ANALOGS_ICON[] = { +#include "mask_analogs.lbm" +}; + const uint8_t * const LBM_STATS_ICONS[] = { LBM_STATS_ICON, LBM_STATS_GRAPH_ICON, LBM_STATS_TIME_ICON, + LBM_STATS_ANALOGS_ICON, #if defined(DEBUG_TRACE_BUFFER) LBM_STATS_DEBUG_ICON #endif diff --git a/radio/src/gui/horus/bitmaps.h b/radio/src/gui/horus/bitmaps.h index a520571a3..a624f7ed4 100644 --- a/radio/src/gui/horus/bitmaps.h +++ b/radio/src/gui/horus/bitmaps.h @@ -51,6 +51,7 @@ extern const uint8_t LBM_MIXER_ICON[]; extern const uint8_t LBM_CURVES_ICON[]; extern const uint8_t LBM_LUA_SCRIPTS_ICON[]; extern const uint8_t LBM_TELEMETRY_ICON[]; +extern const uint8_t LBM_STATS_ANALOGS_ICON[]; // UI (theme / layout / widgets bitmaps extern const uint8_t LBM_MAINVIEWS_ICON[]; diff --git a/radio/src/gui/horus/lcd.cpp b/radio/src/gui/horus/lcd.cpp index 7c2024e92..c84670cce 100644 --- a/radio/src/gui/horus/lcd.cpp +++ b/radio/src/gui/horus/lcd.cpp @@ -20,7 +20,7 @@ #include #include -#include "../../opentx.h" +#include "opentx.h" #if defined(SIMU) display_t displayBuf[DISPLAY_BUFFER_SIZE]; diff --git a/radio/src/gui/horus/menu_general_hardware.cpp b/radio/src/gui/horus/menu_general_hardware.cpp index e9775468f..291da19f1 100644 --- a/radio/src/gui/horus/menu_general_hardware.cpp +++ b/radio/src/gui/horus/menu_general_hardware.cpp @@ -46,6 +46,7 @@ enum menuGeneralHwItems { ITEM_SETUP_HW_SH, ITEM_SETUP_HW_BLUETOOTH, // ITEM_SETUP_HW_UART3_MODE, + ITEM_SETUP_HW_BAT_CAL, ITEM_SETUP_HW_MAX }; @@ -175,6 +176,12 @@ bool menuGeneralHardware(evt_t event) } break; #endif + + case ITEM_SETUP_HW_BAT_CAL: + lcdDrawText(MENUS_MARGIN_LEFT, y, "Battery cal."); + lcdDrawNumber(HW_SETTINGS_COLUMN, y, getBatteryVoltage(), attr|LEFT|PREC2, 0, NULL, "V"); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.txVoltageCalibration, -127, 127); + break; } } diff --git a/radio/src/gui/horus/menu_general_setup.cpp b/radio/src/gui/horus/menu_general_setup.cpp index 542c8526b..b13f9b21c 100644 --- a/radio/src/gui/horus/menu_general_setup.cpp +++ b/radio/src/gui/horus/menu_general_setup.cpp @@ -329,7 +329,7 @@ bool menuGeneralSetup(evt_t event) case ITEM_SETUP_BATTERY_WARNING: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_BATTERYWARNING); putsValueWithUnit(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.vBatWarn, UNIT_VOLTS, attr|PREC1|LEFT); - if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatWarn, 27, 42); // 2.7-4.2V + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatWarn, 40, 120); //4-12V break; #if 0 diff --git a/radio/src/gui/horus/menu_model_curves.cpp b/radio/src/gui/horus/menu_model_curves.cpp index 326915f2a..938edebcc 100644 --- a/radio/src/gui/horus/menu_model_curves.cpp +++ b/radio/src/gui/horus/menu_model_curves.cpp @@ -19,7 +19,7 @@ */ #include -#include "../../opentx.h" +#include "opentx.h" uint8_t s_curveChan; diff --git a/radio/src/gui/horus/menu_model_custom_functions.cpp b/radio/src/gui/horus/menu_model_custom_functions.cpp index 2f7d90173..551f2956d 100644 --- a/radio/src/gui/horus/menu_model_custom_functions.cpp +++ b/radio/src/gui/horus/menu_model_custom_functions.cpp @@ -18,12 +18,12 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" -#define MODEL_CUSTOM_FUNC_1ST_COLUMN 50 -#define MODEL_CUSTOM_FUNC_2ND_COLUMN 100 -#define MODEL_CUSTOM_FUNC_2ND_COLUMN_EXT 180 -#define MODEL_CUSTOM_FUNC_3RD_COLUMN 300 +#define MODEL_CUSTOM_FUNC_1ST_COLUMN 60 +#define MODEL_CUSTOM_FUNC_2ND_COLUMN 120 +#define MODEL_CUSTOM_FUNC_2ND_COLUMN_EXT (lcdNextPos + 5) +#define MODEL_CUSTOM_FUNC_3RD_COLUMN 295 #define MODEL_CUSTOM_FUNC_4TH_COLUMN 440 #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF 450 diff --git a/radio/src/gui/horus/menu_model_logical_switches.cpp b/radio/src/gui/horus/menu_model_logical_switches.cpp index b514e2d2c..7c98e1854 100644 --- a/radio/src/gui/horus/menu_model_logical_switches.cpp +++ b/radio/src/gui/horus/menu_model_logical_switches.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -19,7 +19,7 @@ */ #include -#include "../../opentx.h" +#include "opentx.h" enum LogicalSwitchFields { LS_FIELD_FUNCTION, @@ -33,28 +33,25 @@ enum LogicalSwitchFields { LS_FIELD_LAST = LS_FIELD_COUNT-1 }; -#define CSW_1ST_COLUMN 42 -#define CSW_2ND_COLUMN 90 -#define CSW_3RD_COLUMN 140 -#define CSW_4TH_COLUMN 200 -#define CSW_5TH_COLUMN 245 -#define CSW_6TH_COLUMN 300 +#define CSW_1ST_COLUMN 50 +#define CSW_2ND_COLUMN 120 +#define CSW_3RD_COLUMN 200 +#define CSW_4TH_COLUMN 280 +#define CSW_5TH_COLUMN 340 +#define CSW_6TH_COLUMN 390 void putsEdgeDelayParam(coord_t x, coord_t y, LogicalSwitchData *cs, uint8_t lattr, uint8_t rattr) { - char s[32]; - div_t left = div(lswTimerValue(cs->v2), 10); - char sleft[10]; - sprintf(sleft, "%d.%d", left.quot, left.rem); - div_t right = div(lswTimerValue(cs->v2+cs->v3), 10); - char sright[10]; - sprintf(sright, "%d.%d", right.quot, right.rem); - sprintf(s, "[%s:%s]", sleft, sright); - lcdDrawText(x-4, y, s); - /* if (cs->v3 < 0) - lcdDrawText(lcdLastPos+3, y, "<<", rattr); + lcdDrawChar(x, y, '['); + lcdDrawNumber(lcdNextPos+3, y, lswTimerValue(cs->v2), LEFT|PREC1|lattr); + lcdDrawChar(lcdNextPos+3, y, ':'); + if (cs->v3 < 0) + lcdDrawText(lcdNextPos+3, y, "<<", rattr); else if (cs->v3 == 0) - lcdDrawText(lcdLastPos+3, y, "--", rattr); */ + lcdDrawText(lcdNextPos+3, y, "--", rattr); + else + lcdDrawNumber(lcdNextPos+3, y, lswTimerValue(cs->v2+cs->v3), LEFT|PREC1|rattr); + lcdDrawChar(lcdNextPos+3, y, ']'); } void onLogicalSwitchesMenu(const char *result) @@ -173,7 +170,7 @@ bool menuModelLogicalSwitches(evt_t event) INCDEC_ENABLE_CHECK(NULL); } v2_max = getMaximumValue(v1_val); - v2_min = - v2_min; + v2_min = - v2_max; putsChannelValue(CSW_3RD_COLUMN, y, v1_val, v1_val <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2, LEFT|attr2); } diff --git a/radio/src/gui/horus/menu_model_setup.cpp b/radio/src/gui/horus/menu_model_setup.cpp index 46f89a3ef..ad58a0d36 100644 --- a/radio/src/gui/horus/menu_model_setup.cpp +++ b/radio/src/gui/horus/menu_model_setup.cpp @@ -730,88 +730,114 @@ bool menuModelSetup(evt_t event) bool menuModelFailsafe(evt_t event) { - static bool longNames = false; - bool newLongNames = false; uint8_t ch = 0; + uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart; - if (event == EVT_KEY_LONG(KEY_ENTER) && s_editMode) { - START_NO_HIGHLIGHT(); - g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition]; - storageDirty(EE_MODEL); - AUDIO_WARNING1(); - SEND_FAILSAFE_NOW(g_moduleIdx); + if (event == EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + event = 0; + if (s_editMode) { + g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart]; + storageDirty(EE_MODEL); + AUDIO_WARNING1(); + s_editMode = 0; + SEND_FAILSAFE_NOW(g_moduleIdx); + } + else { + int16_t & failsafe = g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition]; + if (failsafe < FAILSAFE_CHANNEL_HOLD) + failsafe = FAILSAFE_CHANNEL_HOLD; + else if (failsafe == FAILSAFE_CHANNEL_HOLD) + failsafe = FAILSAFE_CHANNEL_NOPULSE; + else + failsafe = 0; + storageDirty(EE_MODEL); + AUDIO_WARNING1(); + SEND_FAILSAFE_NOW(g_moduleIdx); + } } - SIMPLE_SUBMENU_NOTITLE(NUM_CHNOUT); + SIMPLE_SUBMENU_WITH_OPTIONS("FAILSAFE", LBM_STATS_ANALOGS_ICON, NUM_CHANNELS(g_moduleIdx), OPTION_MENU_NO_SCROLLBAR); + drawStringWithIndex(50, 3+FH, "Module", g_moduleIdx+1, MENU_TITLE_COLOR); #define COL_W (LCD_W/2) - const uint8_t SLIDER_W = 64; - // Column separator - // TODO lcdDrawSolidVerticalLine(LCD_W/2, FH, LCD_H-FH); + const uint8_t SLIDER_W = 128; - if (menuVerticalPosition >= 16) { - ch = 16; - } + unsigned int lim = g_model.extendedLimits ? 640*2 : 512*2; - // TODO lcd_putsCenter(0, FAILSAFESET); - // TODO lcdInvertLine(0); + for (uint8_t col=0; col<2; col++) { + for (uint8_t line=0; line<8; line++) { + coord_t x = col*(LCD_W/2); + coord_t y = MENU_CONTENT_TOP - FH + line*(FH+4); + int32_t channelValue = channelOutputs[ch+channelStart]; + int32_t failsafeValue = 0; + bool failsafeEditable = false; - for (int col=0; col<2; col++) { - coord_t x = col*COL_W+1; - - // Channels - for (int line=0; line<8; line++) { - coord_t y = 9+line*7; - int32_t val; - int ofs = (col ? 0 : 1); - - if (ch < g_model.moduleData[g_moduleIdx].channelsStart || ch >= NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart) - val = 0; - else if (s_editMode && menuVerticalPosition == ch) - val = channelOutputs[ch]; - else - val = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line]; - - // Channel name if present, number if not - uint8_t lenLabel = ZLEN(g_model.limitData[ch].name); - if (lenLabel > 4) { - newLongNames = longNames = true; + if (ch < NUM_CHANNELS(g_moduleIdx)) { + failsafeValue = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line]; + failsafeEditable = true; } - if (lenLabel > 0) - lcdDrawSizedText(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE); - else - putsChn(x+1-ofs, y, ch+1, SMLSIZE); + if (failsafeEditable) { + // Channel name if present, number if not + uint8_t lenLabel = ZLEN(g_model.limitData[ch+channelStart].name); + if (lenLabel > 0) { + putsChn(x+MENUS_MARGIN_LEFT, y-3, ch+1, TINSIZE); + lcdDrawSizedText(x+MENUS_MARGIN_LEFT, y+5, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR|SMLSIZE); + } + else { + putsChn(x+MENUS_MARGIN_LEFT, y, ch+1, 0); + } - // Value - LcdFlags flags = TINSIZE; - if (menuVerticalPosition == ch && !NO_HIGHLIGHT()) { - flags |= INVERS; - if (s_editMode) - flags |= BLINK; - } + // Value + LcdFlags flags = RIGHT; + if (menuVerticalPosition == ch) { + flags |= INVERS; + if (s_editMode) { + if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { + s_editMode = 0; + } + else { + flags |= BLINK; + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line], -lim, +lim); + } + } + } + + x += COL_W-4-MENUS_MARGIN_LEFT-SLIDER_W; + + if (failsafeValue == FAILSAFE_CHANNEL_HOLD) { + lcdDrawText(x, y+2, "HOLD", flags|SMLSIZE); + failsafeValue = 0; + } + else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { + lcdDrawText(x, y+2, "NONE", flags|SMLSIZE); + failsafeValue = 0; + } + else { #if defined(PPM_UNIT_US) - uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W); - lcdDrawNumber(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags|RIGHT); + lcdDrawNumber(x, y, PPM_CH_CENTER(ch)+failsafeValue/2, flags); #elif defined(PPM_UNIT_PERCENT_PREC1) - uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6); - lcdDrawNumber(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags|RIGHT); + lcdDrawNumber(x, y, calcRESXto1000(failsafeValue), PREC1|flags); #else - uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W); - lcdDrawNumber(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val)/10, flags|RIGHT); + lcdDrawNumber(x, y, calcRESXto1000(failsafeValue)/10, flags); #endif + } - // Gauge - lcdDrawRect(x+COL_W-3-wbar-ofs, y, wbar+1, 6); - uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2; - uint8_t len = limit((uint8_t)1, uint8_t((abs(val) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); - coord_t x0 = (val>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-len; - lcdDrawSolidFilledRect(x0, y+1, len, 4, LINE_COLOR); + // Gauge + x += 4; + lcdDrawRect(x, y+3, SLIDER_W+1, 12); + unsigned int lenChannel = limit((uint8_t)1, uint8_t((abs(channelValue) * SLIDER_W/2 + lim/2) / lim), uint8_t(SLIDER_W/2)); + unsigned int lenFailsafe = limit((uint8_t)1, uint8_t((abs(failsafeValue) * SLIDER_W/2 + lim/2) / lim), uint8_t(SLIDER_W/2)); + x += SLIDER_W/2; + coord_t xChannel = (channelValue>0) ? x : x+1-lenChannel; + coord_t xFailsafe = (failsafeValue>0) ? x : x+1-lenFailsafe; + lcdDrawSolidFilledRect(xChannel, y+4, lenChannel, 5, TEXT_COLOR); + lcdDrawSolidFilledRect(xFailsafe, y+9, lenFailsafe, 5, ALARM_COLOR); + } ch++; } } - longNames = newLongNames; - return true; } diff --git a/radio/src/gui/horus/menu_model_telemetry.cpp b/radio/src/gui/horus/menu_model_telemetry.cpp index 75ee6a73e..90355d580 100644 --- a/radio/src/gui/horus/menu_model_telemetry.cpp +++ b/radio/src/gui/horus/menu_model_telemetry.cpp @@ -18,7 +18,7 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" enum menuModelTelemetryItems { ITEM_TELEMETRY_PROTOCOL_TYPE, diff --git a/radio/src/gui/horus/menus.cpp b/radio/src/gui/horus/menus.cpp index b79ec0924..b7a623024 100644 --- a/radio/src/gui/horus/menus.cpp +++ b/radio/src/gui/horus/menus.cpp @@ -18,7 +18,7 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" MenuHandlerFunc menuHandlers[5]; evt_t menuEvent = 0; diff --git a/radio/src/gui/horus/menus.h b/radio/src/gui/horus/menus.h index c4914b120..92de43b30 100644 --- a/radio/src/gui/horus/menus.h +++ b/radio/src/gui/horus/menus.h @@ -148,6 +148,7 @@ enum EnumTabDiag { e_StatsGraph, e_StatsDebug, + e_StatsAnalogs, #if defined(DEBUG_TRACE_BUFFER) e_StatsTraces, #endif @@ -155,11 +156,13 @@ enum EnumTabDiag bool menuStatsGraph(evt_t event); bool menuStatsDebug(evt_t event); +bool menuStatsAnalogs(evt_t event); bool menuStatsTraces(evt_t event); static const MenuHandlerFunc menuTabStats[] PROGMEM = { menuStatsGraph, menuStatsDebug, + menuStatsAnalogs, #if defined(DEBUG_TRACE_BUFFER) menuStatsTraces, #endif @@ -316,13 +319,14 @@ bool check_submenu_simple(check_event_t event, uint8_t maxrow); if (!check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, lines_count)) return false; \ drawScreenTemplate(title, icon, options); -#define SIMPLE_SUBMENU_NOTITLE(lines_count) \ - if (!check_submenu_simple(event, lines_count)) return false - #define SIMPLE_SUBMENU(title, icon, lines_count) \ - SIMPLE_SUBMENU_NOTITLE(lines_count); \ + if (!check_submenu_simple(event, lines_count)) return false; \ drawScreenTemplate(title, icon) +#define SIMPLE_SUBMENU_WITH_OPTIONS(title, icon, lines_count, options) \ + if (!check_submenu_simple(event, lines_count)) return false; \ + drawScreenTemplate(title, icon, options) + typedef int select_menu_value_t; select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char * values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, evt_t event); diff --git a/radio/src/gui/horus/view_statistics.cpp b/radio/src/gui/horus/view_statistics.cpp index 202aa1f04..73db48324 100644 --- a/radio/src/gui/horus/view_statistics.cpp +++ b/radio/src/gui/horus/view_statistics.cpp @@ -47,18 +47,18 @@ bool menuStatsGraph(evt_t event) putsTimer(MENU_STATS_COLUMN3, MENU_CONTENT_TOP, g_eeGeneral.globalTimer+sessionTimer, TIMEHOUR); lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+FH, "Throttle"); - putsTimer(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+FH, s_timeCumThr); - lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP+FH, "Throttle %"); - putsTimer(MENU_STATS_COLUMN3, MENU_CONTENT_TOP+FH, s_timeCum16ThrP/16); + putsTimer(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+FH, s_timeCumThr, TIMEHOUR); + lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP+FH, "Throttle %", TIMEHOUR); + putsTimer(MENU_STATS_COLUMN3, MENU_CONTENT_TOP+FH, s_timeCum16ThrP/16, TIMEHOUR); lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+2*FH, "Timers"); lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+2*FH, "[1]", HEADER_COLOR); - putsTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[0].val); + putsTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[0].val, TIMEHOUR); lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP+2*FH, "[2]", HEADER_COLOR); - putsTimer(lcdNextPos+10, MENU_CONTENT_TOP+2*FH, timersStates[1].val); + putsTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[1].val, TIMEHOUR); #if TIMERS > 2 lcdDrawText(MENU_STATS_COLUMN3, MENU_CONTENT_TOP+2*FH, "[3]", HEADER_COLOR); - putsTimer(lcdNextPos+10, MENU_CONTENT_TOP+2*FH, timersStates[2].val); + putsTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[2].val, TIMEHOUR); #endif const coord_t x = 10; @@ -129,10 +129,10 @@ bool menuStatsDebug(evt_t event) #if defined(LUA) lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+3*FH, "Lua duration"); - lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+4*FH, 10*maxLuaDuration, LEFT, 0, NULL, "ms"); + lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+3*FH, 10*maxLuaDuration, LEFT, 0, NULL, "ms"); lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+4*FH, "Lua interval"); - lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+5*FH, 10*maxLuaInterval, LEFT, 0, NULL, "ms"); + lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+4*FH, 10*maxLuaInterval, LEFT, 0, NULL, "ms"); #endif lcdDrawText(LCD_W/2, MENU_FOOTER_TOP+2, STR_MENUTORESET, CENTERED); @@ -140,6 +140,28 @@ bool menuStatsDebug(evt_t event) return true; } +bool menuStatsAnalogs(evt_t event) +{ + MENU("Analogs", LBM_STATS_ICONS, menuTabStats, e_StatsAnalogs, 0, { 0 }); + + for (int i=0; i= 3600) { + putsTimer(zone.x + 70, zone.y + 31, abs(timerState.val), TEXT_COLOR | MIDSIZE | LEFT | TIMEHOUR); + } + else { + putsTimer(zone.x + 76, zone.y + 31, abs(timerState.val), TEXT_COLOR | DBLSIZE | LEFT); + } if (ZLEN(timerData.name) > 0) { lcdDrawSizedText(zone.x + 78, zone.y + 20, timerData.name, LEN_TIMER_NAME, ZCHAR | SMLSIZE | TEXT_COLOR); } @@ -64,10 +69,20 @@ void TimerWidget::refresh() else { drawStringWithIndex(zone.x, zone.y, "TMR", index + 1, SMLSIZE | TEXT_INVERTED_COLOR); if (zone.w > 100 && zone.h > 40) { - putsTimer(zone.x, zone.y + 16, abs(timerState.val), TEXT_INVERTED_COLOR | LEFT | MIDSIZE); + if (abs(timerState.val) >= 3600) { + putsTimer(zone.x, zone.y + 16, abs(timerState.val), TEXT_INVERTED_COLOR | LEFT | TIMEHOUR); + } + else { + putsTimer(zone.x, zone.y + 16, abs(timerState.val), TEXT_INVERTED_COLOR | LEFT | MIDSIZE); + } } else { - putsTimer(zone.x, zone.y + 14, abs(timerState.val), TEXT_INVERTED_COLOR | LEFT); + if (abs(timerState.val) >= 3600) { + putsTimer(zone.x, zone.y + 14, abs(timerState.val), TEXT_INVERTED_COLOR | LEFT | SMLSIZE | TIMEHOUR); + } + else { + putsTimer(zone.x, zone.y + 14, abs(timerState.val), TEXT_INVERTED_COLOR | LEFT); + } } } } diff --git a/radio/src/gui/taranis/lcd.cpp b/radio/src/gui/taranis/lcd.cpp index bbea48118..fd433ea73 100644 --- a/radio/src/gui/taranis/lcd.cpp +++ b/radio/src/gui/taranis/lcd.cpp @@ -295,11 +295,6 @@ void lcdDrawHexNumber(coord_t x, coord_t y, uint32_t val, LcdFlags flags) } } -void lcdDraw8bitsNumber(coord_t x, coord_t y, int8_t val) -{ - lcdDrawNumber(x, y, val); -} - void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags) { lcdDrawNumber(x, y, val, flags, 0); diff --git a/radio/src/gui/taranis/lcd.h b/radio/src/gui/taranis/lcd.h index a751dc026..2f32b7b0b 100644 --- a/radio/src/gui/taranis/lcd.h +++ b/radio/src/gui/taranis/lcd.h @@ -140,7 +140,6 @@ void lcdDrawHexNumber(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0); void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags mode, uint8_t len); void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags mode=0); -void lcdDraw8bitsNumber(coord_t x, coord_t y, int8_t val); void drawStringWithIndex(coord_t x, coord_t y, const pm_char *str, uint8_t idx, LcdFlags att=0); void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att); diff --git a/radio/src/gui/taranis/menu_general_diaganas.cpp b/radio/src/gui/taranis/menu_general_diaganas.cpp index 5fbb274eb..d55dea47d 100644 --- a/radio/src/gui/taranis/menu_general_diaganas.cpp +++ b/radio/src/gui/taranis/menu_general_diaganas.cpp @@ -35,18 +35,13 @@ void menuGeneralDiagAna(uint8_t event) #if defined(JITTER_MEASURE) lcdDrawNumber(x+10*FW-1, y, rawJitter[i].get()); lcdDrawNumber(x+13*FW-1, y, avgJitter[i].get()); - lcdDraw8bitsNumber(x+17*FW-1, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256); + lcdDrawNumber(x+17*FW-1, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256); #else - lcdDraw8bitsNumber(x+10*FW-1, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256); + lcdDrawNumber(x+10*FW-1, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256); #endif } lcd_putsLeft(MENU_HEADER_HEIGHT+1+6*FH, STR_BATT_CALIB); - static int32_t adcBatt; - adcBatt = ((adcBatt * 7) + anaIn(TX_VOLTAGE)) / 8; - uint32_t batCalV = (adcBatt + (adcBatt*g_eeGeneral.txVoltageCalibration)/128) * BATT_SCALE; - batCalV >>= 11; - batCalV += 2; // because of the diode - putsVolts(LEN_CALIB_FIELDS*FW+4*FW, MENU_HEADER_HEIGHT+1+6*FH, batCalV, s_editMode > 0 ? BLINK|INVERS : INVERS); + putsVolts(LEN_CALIB_FIELDS*FW+4*FW, MENU_HEADER_HEIGHT+1+6*FH, getBatteryVoltage(), (s_editMode > 0 ? BLINK : 0) | INVERS | PREC2); if (s_editMode > 0) CHECK_INCDEC_GENVAR(event, g_eeGeneral.txVoltageCalibration, -127, 127); } diff --git a/radio/src/gui/taranis/menu_general_version.cpp b/radio/src/gui/taranis/menu_general_version.cpp index 283e787d3..eabf57ac5 100644 --- a/radio/src/gui/taranis/menu_general_version.cpp +++ b/radio/src/gui/taranis/menu_general_version.cpp @@ -77,10 +77,16 @@ void menuGeneralVersion(uint8_t event) exit(0); #endif } + + if (event == EVT_ENTRY) { + getCPUUniqueID(reusableBuffer.version.id); + } SIMPLE_MENU(STR_MENUVERSION, menuTabGeneral, e_Vers, 1); lcd_putsLeft(MENU_HEADER_HEIGHT+1, vers_stamp); + lcd_putsLeft(MENU_HEADER_HEIGHT+4*FH+1, "UID\037\033:"); + lcdDrawText(5*FW+3, MENU_HEADER_HEIGHT+4*FH+1, reusableBuffer.version.id); lcd_putsLeft(MENU_HEADER_HEIGHT+5*FH+1, STR_EEBACKUP); lcd_putsLeft(MENU_HEADER_HEIGHT+6*FH+1, STR_FACTORYRESET); diff --git a/radio/src/gui/taranis/menu_model_logical_switches.cpp b/radio/src/gui/taranis/menu_model_logical_switches.cpp index 0e8311924..43f8bb017 100644 --- a/radio/src/gui/taranis/menu_model_logical_switches.cpp +++ b/radio/src/gui/taranis/menu_model_logical_switches.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -18,7 +18,7 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" enum LogicalSwitchFields { LS_FIELD_FUNCTION, diff --git a/radio/src/gui/taranis/menu_model_setup.cpp b/radio/src/gui/taranis/menu_model_setup.cpp index a0a455cad..b62e980f3 100644 --- a/radio/src/gui/taranis/menu_model_setup.cpp +++ b/radio/src/gui/taranis/menu_model_setup.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -18,7 +18,7 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" uint8_t g_moduleIdx; void menuModelFailsafe(uint8_t event); @@ -219,16 +219,16 @@ void menuModelSetup(uint8_t event) MENU_TAB({ 0, 0, TIMERS_ROWS, TOPLCD_ROWS 0, 1, 0, 0, LABEL(Throttle), 0, 0, 0, LABEL(PreflightCheck), 0, 0, SW_WARN_ITEMS(), POT_WARN_ITEMS(), NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), 0, - LABEL(InternalModule), - INTERNAL_MODULE_MODE_ROWS, + LABEL(InternalModule), + INTERNAL_MODULE_MODE_ROWS, INTERNAL_MODULE_CHANNELS_ROWS, IF_INTERNAL_MODULE_ON(IS_MODULE_XJT(INTERNAL_MODULE) ? (HAS_RF_PROTOCOL_MODELINDEX(g_model.moduleData[INTERNAL_MODULE].rfProtocol) ? (uint8_t)2 : (uint8_t)1) : (IS_MODULE_PPM(INTERNAL_MODULE) ? (uint8_t)1 : HIDDEN_ROW)), - IF_INTERNAL_MODULE_ON((IS_MODULE_XJT(INTERNAL_MODULE)) ? FAILSAFE_ROWS(INTERNAL_MODULE) : HIDDEN_ROW), - LABEL(ExternalModule), - (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, + IF_INTERNAL_MODULE_ON((IS_MODULE_XJT(INTERNAL_MODULE)) ? FAILSAFE_ROWS(INTERNAL_MODULE) : HIDDEN_ROW), + LABEL(ExternalModule), + (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, EXTERNAL_MODULE_CHANNELS_ROWS, (IS_MODULE_XJT(EXTERNAL_MODULE) && !HAS_RF_PROTOCOL_MODELINDEX(g_model.moduleData[EXTERNAL_MODULE].rfProtocol)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW, - IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), + IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)}); #else MENU_TAB({ 0, 0, TIMERS_ROWS, TOPLCD_ROWS 0, 1, 0, 0, LABEL(Throttle), 0, 0, 0, LABEL(PreflightCheck), 0, 0, SW_WARN_ITEMS(), POT_WARN_ITEMS(), @@ -613,7 +613,7 @@ void menuModelSetup(uint8_t event) case ITEM_MODEL_INTERNAL_MODULE_MODE: lcd_putsLeft(y, STR_MODE); lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_TARANIS_PROTOCOLS, g_model.moduleData[INTERNAL_MODULE].type, menuHorizontalPosition==0 ? attr : 0); - if (IS_MODULE_XJT(INTERNAL_MODULE)) + if (IS_MODULE_XJT(INTERNAL_MODULE)) lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[INTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0); if (attr && s_editMode>0) { switch (menuHorizontalPosition) { @@ -625,7 +625,7 @@ void menuModelSetup(uint8_t event) g_model.moduleData[INTERNAL_MODULE].channelsCount = 0; } break; - case 1: + case 1: g_model.moduleData[INTERNAL_MODULE].rfProtocol = checkIncDec(event, g_model.moduleData[INTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST, EE_MODEL, isRfProtocolAvailable); if (checkIncDec_Ret) { g_model.moduleData[INTERNAL_MODULE].channelsStart = 0; @@ -649,7 +649,9 @@ void menuModelSetup(uint8_t event) break; #endif case ITEM_MODEL_TRAINER_MODE: - g_model.trainerMode = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_MODE, STR_VTRAINERMODES, g_model.trainerMode, 0, HAS_WIRELESS_TRAINER_HARDWARE() ? TRAINER_MODE_MASTER_BATTERY_COMPARTMENT : TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, attr, event); + lcd_putsLeft(y, STR_MODE); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerMode, attr); + if (attr) g_model.trainerMode = checkIncDec(event, g_model.trainerMode, 0, HAS_WIRELESS_TRAINER_HARDWARE() ? TRAINER_MODE_MASTER_BATTERY_COMPARTMENT : TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, EE_MODEL, isTrainerModeAvailable); break; case ITEM_MODEL_EXTERNAL_MODULE_LABEL: @@ -666,7 +668,7 @@ void menuModelSetup(uint8_t event) if (attr && s_editMode>0) { switch (menuHorizontalPosition) { case 0: - g_model.moduleData[EXTERNAL_MODULE].type = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, MODULE_TYPE_COUNT-1, EE_MODEL, isModuleAvailable); + g_model.moduleData[EXTERNAL_MODULE].type = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, IS_TRAINER_EXTERNAL_MODULE() ? 0 : MODULE_TYPE_COUNT-1, EE_MODEL, isModuleAvailable); if (checkIncDec_Ret) { g_model.moduleData[EXTERNAL_MODULE].rfProtocol = 0; g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0; @@ -709,7 +711,7 @@ void menuModelSetup(uint8_t event) break; case 1: CHECK_INCDEC_MODELVAR(event, moduleData.channelsCount, -4, min(MAX_CHANNELS(moduleIdx), 32-8-moduleData.channelsStart)); - + #if defined(TARANIS_INTERNAL_PPM) if ((k == ITEM_MODEL_EXTERNAL_MODULE_CHANNELS && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) || (k == ITEM_MODEL_INTERNAL_MODULE_CHANNELS && g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_PPM) || (k == ITEM_MODEL_TRAINER_CHANNELS)) { SET_DEFAULT_PPM_FRAME_LENGTH(moduleIdx); @@ -875,8 +877,11 @@ void menuModelFailsafe(uint8_t event) #define COL_W (LCD_W/2) const uint8_t SLIDER_W = 64; - // Column separator - lcdDrawSolidVerticalLine(LCD_W/2, FH, LCD_H-FH); + + if (NUM_CHANNELS(g_moduleIdx) > 8) { + // Column separator + lcdDrawSolidVerticalLine(LCD_W/2, FH, LCD_H-FH); + } lcd_putsCenter(0*FH, FAILSAFESET); lcdInvertLine(0); @@ -949,7 +954,7 @@ void menuModelFailsafe(uint8_t event) lcdDrawNumber(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue)/10, flags); #endif } - + // Gauge lcdDrawRect(x+COL_W-3-wbar-ofs, y, wbar+1, 6); unsigned int lenChannel = limit((uint8_t)1, uint8_t((abs(channelValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); @@ -960,7 +965,7 @@ void menuModelFailsafe(uint8_t event) lcdDrawHorizontalLine(xChannel, y+2, lenChannel, DOTTED, 0); lcdDrawSolidHorizontalLine(xFailsafe, y+3, lenFailsafe); lcdDrawSolidHorizontalLine(xFailsafe, y+4, lenFailsafe); - } + } ch++; } } diff --git a/radio/src/gui/taranis/menus.h b/radio/src/gui/taranis/menus.h index 89279b047..893cdb49c 100644 --- a/radio/src/gui/taranis/menus.h +++ b/radio/src/gui/taranis/menus.h @@ -333,7 +333,7 @@ swsrc_t switchMenuItem(coord_t x, coord_t y, swsrc_t value, LcdFlags attr, uint8 #else #define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) editGVarFieldValue(x, y, v, min, max, lcdattr, event) int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); - #define displayGVar(x, y, v, min, max) lcdDraw8bitsNumber(x, y, v) + #define displayGVar(x, y, v, min, max) lcdDrawNumber(x, y, v) #endif extern uint8_t s_curveChan; diff --git a/radio/src/main_arm.cpp b/radio/src/main_arm.cpp index 9b64283a4..6b5103aee 100644 --- a/radio/src/main_arm.cpp +++ b/radio/src/main_arm.cpp @@ -98,6 +98,71 @@ void checkEeprom() } #endif +#define BAT_AVG_SAMPLES 8 + +void checkBatteryAlarms() +{ + // TRACE("checkBatteryAlarms()"); + if (IS_TXBATT_WARNING() && g_vbat100mV>50) { + AUDIO_TX_BATTERY_LOW(); + // TRACE("checkBatteryAlarms(): battery low"); + } +#if defined(PCBSKY9X) + else if (g_eeGeneral.temperatureWarn && getTemperature() >= g_eeGeneral.temperatureWarn) { + AUDIO_TX_TEMP_HIGH(); + } + else if (g_eeGeneral.mAhWarn && (g_eeGeneral.mAhUsed + Current_used * (488 + g_eeGeneral.txCurrentCalibration)/8192/36) / 500 >= g_eeGeneral.mAhWarn) { // TODO move calculation into board file + AUDIO_TX_MAH_HIGH(); + } +#endif +} + +void checkBattery() +{ + static uint32_t batSum; + static uint8_t sampleCount; + // filter battery voltage by averaging it + if (g_vbat100mV == 0) { + g_vbat100mV = (getBatteryVoltage() + 5) / 10; + batSum = 0; + sampleCount = 0; + } + else { + batSum += getBatteryVoltage(); + // TRACE("checkBattery(): sampled = %d", getBatteryVoltage()); + if (++sampleCount >= BAT_AVG_SAMPLES) { + g_vbat100mV = (batSum + BAT_AVG_SAMPLES * 5 ) / (BAT_AVG_SAMPLES * 10); + batSum = 0; + sampleCount = 0; + // TRACE("checkBattery(): g_vbat100mV = %d", g_vbat100mV); + } + } +} + +void periodicTick_1s() +{ + checkBattery(); +} + +void periodicTick_10s() +{ + checkBatteryAlarms(); +} + +void periodicTick() +{ + static uint8_t count10s; + static uint32_t lastTime; + if ( (get_tmr10ms() - lastTime) >= 100 ) { + lastTime += 100; + periodicTick_1s(); + if (++count10s >= 10) { + count10s = 0; + periodicTick_10s(); + } + } +} + #if defined(GUI) && defined(COLORLCD) void guiMain(evt_t evt) { @@ -328,7 +393,7 @@ void perMain() writeLogs(); handleUsbConnection(); checkTrainerSettings(); - checkBattery(); + periodicTick(); evt_t evt = getEvent(false); if (evt && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) backlightOn(); // on keypress turn the light on diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 65becded8..cae80e7e6 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -55,39 +55,11 @@ #define SET_DEFAULT_PPM_FRAME_LENGTH(idx) g_model.moduleData[idx].ppmFrameLength = 4 * max((int8_t)0, g_model.moduleData[idx].channelsCount) -#if defined(PCBFLAMENCO) - enum ModuleIndex { - EXTERNAL_MODULE, - TRAINER_MODULE, - }; - enum TrainerMode { - TRAINER_MODE_MASTER, - TRAINER_MODE_SLAVE - }; -#elif defined(PCBTARANIS) || defined(PCBHORUS) - enum ModuleIndex { - INTERNAL_MODULE, - EXTERNAL_MODULE, - TRAINER_MODULE - }; - enum TrainerMode { - TRAINER_MODE_MASTER_TRAINER_JACK, - TRAINER_MODE_SLAVE, - TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE, - TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, - TRAINER_MODE_MASTER_BATTERY_COMPARTMENT, - }; +#if defined(PCBTARANIS) || defined(PCBHORUS) #define IS_TRAINER_EXTERNAL_MODULE() (g_model.trainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || g_model.trainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE) #define HAS_WIRELESS_TRAINER_HARDWARE() (g_eeGeneral.serial2Mode==UART_MODE_SBUS_TRAINER/* || g_eeGeneral.serial2Mode==UART_MODE_CPPM_TRAINER*/) -#elif defined(PCBSKY9X) - enum ModuleIndex { - EXTERNAL_MODULE, - EXTRA_MODULE, - TRAINER_MODULE - }; #endif - #if defined(VOICE) #define IS_PLAY_FUNC(func) ((func) >= FUNC_PLAY_SOUND && func <= FUNC_PLAY_VALUE) #else @@ -539,7 +511,7 @@ enum AntennaTypes { XJT_EXTERNAL_ANTENNA }; -#define IS_PULSES_EXTERNAL_MODULE() (g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) +#define IS_EXTERNAL_MODULE_PRESENT() (g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) enum FailsafeModes { FAILSAFE_NOT_SET, diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 39d88a62f..dac1c4f38 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1509,10 +1509,14 @@ uint16_t BandGap ; JitterMeter rawJitter[NUMBER_ANALOG]; JitterMeter avgJitter[NUMBER_ANALOG]; tmr10ms_t jitterResetTime = 0; - #if defined(PCBTARANIS) + #if defined(PCBHORUS) + #define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuStatsAnalogs) + #elif defined(PCBTARANIS) #define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuGeneralDiagAna) #elif defined(CLI) #define JITTER_MEASURE_ACTIVE() (1) + #else + #define JITTER_MEASURE_ACTIVE() (0) #endif #endif @@ -1765,10 +1769,7 @@ void doMixerCalculations() // handle tick10ms overrun // correct overflow handling costs a lot of code; happens only each 11 min; // therefore forget the exact calculation and use only 1 instead; good compromise - -#if !defined(CPUARM) lastTMR = tmr10ms; -#endif getADC(); @@ -1778,10 +1779,6 @@ void doMixerCalculations() getSwitchesPosition(!s_mixer_first_run_done); -#if defined(CPUARM) - lastTMR = tmr10ms; -#endif - #if defined(PCBSKY9X) && !defined(REVA) && !defined(SIMU) Current_analogue = (Current_analogue*31 + s_anaFilt[8] ) >> 5 ; if (Current_analogue > Current_max) @@ -2160,6 +2157,7 @@ uint8_t getSticksNavigationEvent() } #endif +#if !defined(CPUARM) void checkBattery() { static uint8_t counter = 0; @@ -2173,14 +2171,7 @@ void checkBattery() if (counter-- == 0) { counter = 10; int32_t instant_vbat = anaIn(TX_VOLTAGE); -#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS) - instant_vbat = (instant_vbat + instant_vbat*(g_eeGeneral.txVoltageCalibration)/128) * BATT_SCALE; - instant_vbat >>= 11; - instant_vbat += 2; // because of the diode -#elif defined(PCBSKY9X) - instant_vbat = (instant_vbat + instant_vbat*(g_eeGeneral.txVoltageCalibration)/128) * 4191; - instant_vbat /= 55296; -#elif defined(CPUM2560) +#if defined(CPUM2560) instant_vbat = (instant_vbat*1112 + instant_vbat*g_eeGeneral.txVoltageCalibration + (BandGap<<2)) / (BandGap<<3); #else instant_vbat = (instant_vbat*16 + instant_vbat*g_eeGeneral.txVoltageCalibration/8) / BandGap; @@ -2218,17 +2209,11 @@ void checkBattery() if (IS_TXBATT_WARNING() && g_vbat100mV>50) { AUDIO_TX_BATTERY_LOW(); } -#if defined(PCBSKY9X) - else if (g_eeGeneral.temperatureWarn && getTemperature() >= g_eeGeneral.temperatureWarn) { - AUDIO_TX_TEMP_HIGH(); - } - else if (g_eeGeneral.mAhWarn && (g_eeGeneral.mAhUsed + Current_used * (488 + g_eeGeneral.txCurrentCalibration)/8192/36) / 500 >= g_eeGeneral.mAhWarn) { - AUDIO_TX_MAH_HIGH(); - } -#endif } } } +#endif // #if !defined(CPUARM) + #if !defined(SIMU) && !defined(CPUARM) @@ -2678,9 +2663,13 @@ int main() #if defined(CPUM2560) || defined(CPUM2561) uint8_t mcusr = MCUSR; // save the WDT (etc) flags MCUSR = 0; // must be zeroed before disabling the WDT + MCUCR = 0x80 ; // Disable JTAG port that can interfere with POT3 + MCUCR = 0x80 ; // Must be done twice #elif defined(PCBSTD) uint8_t mcusr = MCUCSR; MCUCSR = 0; + MCUCSR = 0x80 ; // Disable JTAG port that can interfere with POT3 + MCUCSR = 0x80 ; // Must be done twice #endif #if defined(PCBTARANIS) g_eeGeneral.contrast = 30; @@ -2753,6 +2742,11 @@ int main() if ((shutdown_state=pwrCheck()) > e_power_trainer) break; #endif +#if defined(SIMU) + sleep(5/*ms*/); + if (main_thread_running == 0) + return 0; +#endif perMain(); diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 6bb84001c..b9da6c379 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -25,6 +25,7 @@ #include #include #include +#include "definitions.h" #if defined(SIMU) #define SWITCH_SIMU(a, b) (a) @@ -203,32 +204,6 @@ #define ROTARY_ENCODER_NAVIGATION #endif -#if defined(SIMU) - #define __ALIGNED -#else - #define __ALIGNED __attribute__((aligned(32))) -#endif - -#if defined(SIMU) - #define __DMA -#elif defined(STM32F4) && !defined(BOOT) - #define __DMA __attribute__((section(".ram"), aligned(32))) -#else - #define __DMA __ALIGNED -#endif - -#if defined(PCBHORUS) && !defined(SIMU) - #define __SDRAM __attribute__((section(".sdram"), aligned(32))) -#else - #define __SDRAM __DMA -#endif - -#if defined(SIMU) || defined(CPUARM) || GCC_VERSION < 472 - typedef int32_t int24_t; -#else - typedef __int24 int24_t; -#endif - #if defined(FAI) #define IS_FAI_ENABLED() true #define IF_FAI_CHOICE(x) @@ -1559,6 +1534,13 @@ union ReusableBuffer char originalName[SD_SCREEN_FILE_LENGTH+1]; } sdmanager; #endif + +#if defined(PCBTARANIS) + struct + { + char id[27]; + } version; +#endif }; extern union ReusableBuffer reusableBuffer; diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index 9a8fb4091..7dc7277b7 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -68,7 +68,7 @@ PACK(struct Dsm2PulsesData { }); #endif -#define CROSSFIRE_BAUDRATE 400000 +#define CROSSFIRE_BAUDRATE 921600 #define CROSSFIRE_FRAME_LEN 25 #define CROSSFIRE_CHANNELS_COUNT 16 PACK(struct CrossfirePulsesData { diff --git a/radio/src/sbus.cpp b/radio/src/sbus.cpp index 57b7d22e5..f2cddc188 100644 --- a/radio/src/sbus.cpp +++ b/radio/src/sbus.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -33,7 +33,6 @@ #define SBUS_CH_CENTER 0x3E0 -Fifo sbusFifo; uint8_t SbusFrame[SBUS_MAX_FRAME_SIZE]; uint16_t SbusTimer ; uint8_t SbusIndex = 0 ; @@ -74,9 +73,10 @@ void processSbusFrame(uint8_t * sbus, int16_t * pulses, uint32_t size) void processSbusInput() { +#if !defined(SIMU) uint8_t rxchar; uint32_t active = 0; - while (sbusFifo.pop(rxchar)) { + while (sbusGetByte(&rxchar)) { active = 1; SbusFrame[SbusIndex++] = rxchar; if (SbusIndex > SBUS_MAX_FRAME_SIZE-1) { @@ -95,4 +95,5 @@ void processSbusInput() } } } +#endif } diff --git a/radio/src/sbus.h b/radio/src/sbus.h index 4ab46a084..5ef7359a5 100644 --- a/radio/src/sbus.h +++ b/radio/src/sbus.h @@ -26,6 +26,5 @@ #define SBUS_MAX_FRAME_SIZE 28 void processSbusInput(); -void processSbusFrame(uint8_t * sbus, int16_t * pulses, uint32_t size); #endif // _SBUS_H_ diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index 911eb7f52..57f7c4201 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -544,9 +544,15 @@ uint16_t anaIn(uint8_t chan) return th9xSim->sliders[chan]->getValue(); else if (chanknobs[chan-NUM_STICKS]->getValue(); -#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS) +#if defined(PCBHORUS) else if (chan == TX_VOLTAGE) - return 1000; + return 1737; //~10.6V +#elif (defined(PCBTARANIS) && defined(REV9E)) + else if (chan == TX_VOLTAGE) + return 1420; //~10.6V +#elif defined(PCBTARANIS) || defined(PCBFLAMENCO) + else if (chan == TX_VOLTAGE) + return 1000; //~7.4V #elif defined(PCBSKY9X) else if (chan == TX_VOLTAGE) return 5.1*1500/11.3; diff --git a/radio/src/stamp.cpp b/radio/src/stamp.cpp index b7a8d1aca..ca65e5c26 100644 --- a/radio/src/stamp.cpp +++ b/radio/src/stamp.cpp @@ -41,6 +41,8 @@ const pm_char date_stamp[] PROGMEM = "DATE" TAB ": " DATE; const pm_char time_stamp[] PROGMEM = "TIME" TAB ": " TIME; const pm_char eeprom_stamp[] PROGMEM = "EEPR" TAB ": " EEPROM_STR; +#elif defined(PCBTARANIS) + const pm_char vers_stamp[] PROGMEM = "FW\037\033: " "opentx-" FLAVOUR "\036VERS\037\033: " VERSION "\036DATE\037\033: " DATE " " TIME "\036EEPR\037\033: " EEPROM_STR; #else const pm_char vers_stamp[] PROGMEM = "FW\037\033: " "opentx-" FLAVOUR "\036VERS\037\033: " VERSION "\036DATE\037\033: " DATE "\036TIME\037\033: " TIME "\036EEPR\037\033: " EEPROM_STR; #endif diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index 8e6a901bf..9a62948e1 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -157,9 +157,9 @@ char * strAppendUnsigned(char * dest, uint32_t value, uint8_t digits, uint8_t ra } uint8_t idx = digits; while(idx > 0) { - div_t qr = div(value, radix); - dest[--idx] = (qr.rem >= 10 ? 'A'-10 : '0') + qr.rem; - value = qr.quot; + uint32_t rem = value % radix; + dest[--idx] = (rem >= 10 ? 'A'-10 : '0') + rem; + value /= radix; } dest[digits] = '\0'; return &dest[digits]; diff --git a/radio/src/targets/horus/audio_driver.cpp b/radio/src/targets/horus/audio_driver.cpp index 07223b6e0..28147dd9a 100644 --- a/radio/src/targets/horus/audio_driver.cpp +++ b/radio/src/targets/horus/audio_driver.cpp @@ -20,12 +20,6 @@ #include "../../opentx.h" -const uint8_t volumeScale[VOLUME_LEVEL_MAX+1] = { - 254, 127, 110, 100, 90, 80, 70, 60, 50, 40, - 30, 20, 19, 18, 17, 16, 15, 14, 13, 12, - 11, 10, 5, 0 -}; - #if !defined(SIMU) #define VS_WRITE_COMMAND 0x02 @@ -414,13 +408,24 @@ bool audioPushBuffer(AudioBuffer * buffer) } } +// adjust this value for a volume level just above the silence +// values is attenuation in dB, higher value - less volume +// max value is 126 +#define VOLUME_MIN_DB 40 + void setScaledVolume(uint8_t volume) { if (volume > VOLUME_LEVEL_MAX) { volume = VOLUME_LEVEL_MAX; } - - setVolume(volumeScale[volume]); + // maximum volume is 0x00 and total silence is 0xFE + if (volume == 0) { + setVolume(0xFE); // silence + } + else { + uint32_t vol = (VOLUME_MIN_DB * 2) - ((uint32_t)volume * (VOLUME_MIN_DB * 2)) / VOLUME_LEVEL_MAX; + setVolume(vol); + } } void setVolume(uint8_t volume) diff --git a/radio/src/targets/horus/board_horus.cpp b/radio/src/targets/horus/board_horus.cpp index 9898f2a47..f930c45bf 100644 --- a/radio/src/targets/horus/board_horus.cpp +++ b/radio/src/targets/horus/board_horus.cpp @@ -266,3 +266,9 @@ void checkTrainerSettings() } } } + +uint16_t getBatteryVoltage() +{ + int32_t instant_vbat = anaIn(TX_VOLTAGE); // using filtered ADC value on purpose + return (uint16_t)((instant_vbat * (1000 + g_eeGeneral.txVoltageCalibration) ) / 1637); +} diff --git a/radio/src/targets/horus/board_horus.h b/radio/src/targets/horus/board_horus.h index a72a31807..7ee5498cb 100644 --- a/radio/src/targets/horus/board_horus.h +++ b/radio/src/targets/horus/board_horus.h @@ -242,12 +242,7 @@ extern uint16_t adcValues[NUMBER_ANALOG]; void adcInit(void); void adcRead(void); uint16_t getAnalogValue(uint8_t index); - -#if defined(REV3) - #define BATT_SCALE 120 -#else - #define BATT_SCALE 150 -#endif +uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps #if defined(__cplusplus) && !defined(SIMU) extern "C" { @@ -308,6 +303,7 @@ int32_t getVolume(void); void telemetryPortInit(uint32_t baudrate); void telemetryPortSetDirectionOutput(void); void sportSendBuffer(uint8_t * buffer, uint32_t count); +int telemetryGetByte(uint8_t * byte); // Haptic driver void hapticInit(void); @@ -318,12 +314,14 @@ void hapticOn(uint32_t pwmPercent); // Second serial port driver #define DEBUG_BAUDRATE 115200 +extern uint8_t serial2Mode; void serial2Init(unsigned int mode, unsigned int protocol); void serial2Putc(char c); #define serial2TelemetryInit(protocol) serial2Init(UART_MODE_TELEMETRY, protocol) void serial2SbusInit(void); void serial2Stop(void); #define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) +int sbusGetByte(uint8_t * byte); #if defined(USB_JOYSTICK) && !defined(SIMU) void usbJoystickUpdate(void); @@ -332,4 +330,12 @@ void usbJoystickUpdate(void); extern uint8_t currentTrainerMode; void checkTrainerSettings(void); +#if defined(__cplusplus) +#include "fifo.h" +#include "dmafifo.h" +extern DMAFifo<512> telemetryFifo; +extern DMAFifo<32> serial2RxFifo; +extern Fifo sbusFifo; +#endif + #endif // _BOARD_HORUS_H_ diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index c1d67965e..3b1886bfc 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -151,9 +151,11 @@ #define SERIAL_USART USART3 #define SERIAL_USART_IRQHandler USART3_IRQHandler #define SERIAL_USART_IRQn USART3_IRQn +#define SERIAL_DMA_Stream_RX DMA1_Stream1 +#define SERIAL_DMA_Channel_RX DMA_Channel_4 // Telemetry -#define TELEMETRY_RCC_AHB1Periph RCC_AHB1Periph_GPIOD +#define TELEMETRY_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1) #define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2 #define TELEMETRY_GPIO_DIR GPIOD #define TELEMETRY_DIR_GPIO_PIN GPIO_Pin_4 // PD.04 @@ -164,8 +166,13 @@ #define TELEMETRY_GPIO_PinSource_RX GPIO_PinSource6 #define TELEMETRY_GPIO_AF GPIO_AF_USART2 #define TELEMETRY_USART USART2 -#define TELEMETRY_USART_IRQHandler USART2_IRQHandler -#define TELEMETRY_USART_IRQn USART2_IRQn +#define TELEMETRY_DMA_Stream_RX DMA1_Stream5 +#define TELEMETRY_DMA_Channel_RX DMA_Channel_4 +#define TELEMETRY_DMA_Stream_TX DMA1_Stream6 +#define TELEMETRY_DMA_Channel_TX DMA_Channel_4 +#define TELEMETRY_DMA_TX_Stream_IRQ DMA1_Stream6_IRQn +#define TELEMETRY_DMA_TX_IRQHandler DMA1_Stream6_IRQHandler +#define TELEMETRY_DMA_TX_FLAG_TC DMA_IT_TCIF6 // Heartbeat #define HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD diff --git a/radio/src/targets/horus/pulses_driver.cpp b/radio/src/targets/horus/pulses_driver.cpp index 85bcd30ab..f65565bc5 100644 --- a/radio/src/targets/horus/pulses_driver.cpp +++ b/radio/src/targets/horus/pulses_driver.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -18,7 +18,7 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" void setupPulses(unsigned int port); void setupPulsesPPM(unsigned int port); @@ -188,7 +188,7 @@ extern "C" void TIM1_CC_IRQHandler() DMA_InitStructure.DMA_BufferSize = (uint8_t *)modulePulsesData[INTERNAL_MODULE].pxx.ptr - (uint8_t *)modulePulsesData[INTERNAL_MODULE].pxx.pulses; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; - DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; @@ -309,35 +309,6 @@ void intmodulePxxStart() NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); -#if 0 - NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIM_RF_PRIO; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init( &NVIC_InitStructure ); - - // open heartbit --------------------- - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); - - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(GPIOD, &GPIO_InitStructure); - - /* Connect EXTI Line12 to PD12 pin */ - EXTI_InitTypeDef EXTI_InitStructure; - SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource12); - EXTI_InitStructure.EXTI_Line = EXTI_Line12; - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;/////// - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; - EXTI_InitStructure.EXTI_LineCmd = ENABLE; - EXTI_Init(&EXTI_InitStructure); - - EXTI15_10_Interrupt_Handler = EXTI15_10_IRQHandler_pxx; -#endif - // TX Pin GPIO_PinAFConfig(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PinSource, INTMODULE_GPIO_AF); GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN; @@ -529,7 +500,7 @@ static void extmodulePpmStart() // Hardware timer in PWM mode is used for PPM generation // Output is OFF if CNTARR = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++ ; if (*modulePulsesData[EXTERNAL_MODULE].ppm.ptr == 0) { // we reached the end of PPM pulses - // enable CC2 interrupt (which comes before Update in any case) + // enable CC2 interrupt (which comes before Update in any case) // to start new PPM cycle and setup pulses EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear CC1 flag EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; // Enable CC1 interrupt diff --git a/radio/src/targets/horus/pwr_driver.cpp b/radio/src/targets/horus/pwr_driver.cpp index ab9583845..8cf940775 100644 --- a/radio/src/targets/horus/pwr_driver.cpp +++ b/radio/src/targets/horus/pwr_driver.cpp @@ -39,11 +39,6 @@ void pwrInit() GPIO_Init(AUDIO_SHUTDOWN_GPIO, &GPIO_InitStructure); // Init Module PWR - GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN); - GPIO_InitStructure.GPIO_Pin = EXTMODULE_PWR_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; - GPIO_Init(EXTMODULE_PWR_GPIO, &GPIO_InitStructure); - // TODO not here GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN); GPIO_InitStructure.GPIO_Pin = INTMODULE_PWR_GPIO_PIN; @@ -112,4 +107,4 @@ void pwrResetHandler() pwrOn(); } -} \ No newline at end of file +} diff --git a/radio/src/targets/horus/serial2_driver.cpp b/radio/src/targets/horus/serial2_driver.cpp index c1a17db15..7cb617592 100644 --- a/radio/src/targets/horus/serial2_driver.cpp +++ b/radio/src/targets/horus/serial2_driver.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -22,10 +22,9 @@ uint8_t serial2Mode = 0; Fifo serial2TxFifo; -extern Fifo telemetryFifo; -extern Fifo sbusFifo; +DMAFifo<32> serial2RxFifo __DMA (SERIAL_DMA_Stream_RX); -void uart3Setup(unsigned int baudrate) +void uart3Setup(unsigned int baudrate, bool dma) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; @@ -39,42 +38,69 @@ void uart3Setup(unsigned int baudrate) GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SERIAL_GPIO, &GPIO_InitStructure); - + USART_InitStructure.USART_BaudRate = baudrate; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; - USART_Init(SERIAL_USART, &USART_InitStructure); - USART_Cmd(SERIAL_USART, ENABLE); - USART_ITConfig(SERIAL_USART, USART_IT_RXNE, ENABLE); - USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE); - - NVIC_SetPriority(SERIAL_USART_IRQn, 7); - NVIC_EnableIRQ(SERIAL_USART_IRQn); + if (dma) { + DMA_InitTypeDef DMA_InitStructure; + serial2RxFifo.clear(); + USART_ITConfig(SERIAL_USART, USART_IT_RXNE, DISABLE); + USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE); + DMA_InitStructure.DMA_Channel = SERIAL_DMA_Channel_RX; + DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&SERIAL_USART->DR); + DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(serial2RxFifo.buffer()); + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; + DMA_InitStructure.DMA_BufferSize = serial2RxFifo.size(); + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; + DMA_InitStructure.DMA_Priority = DMA_Priority_Low; + DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; + DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; + DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; + DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + DMA_Init(SERIAL_DMA_Stream_RX, &DMA_InitStructure); + USART_DMACmd(SERIAL_USART, USART_DMAReq_Rx, ENABLE); + USART_Cmd(SERIAL_USART, ENABLE); + DMA_Cmd(SERIAL_DMA_Stream_RX, ENABLE); + } + else { +#if !defined(USB_SERIAL) && defined(CLI) + USART_Cmd(SERIAL_USART, ENABLE); + USART_ITConfig(SERIAL_USART, USART_IT_RXNE, ENABLE); + USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE); + NVIC_SetPriority(SERIAL_USART_IRQn, 7); + NVIC_EnableIRQ(SERIAL_USART_IRQn); +#endif + } } void serial2Init(unsigned int mode, unsigned int protocol) { - USART_DeInit(SERIAL_USART); + serial2Stop(); serial2Mode = mode; switch (mode) { case UART_MODE_TELEMETRY_MIRROR: - uart3Setup(FRSKY_SPORT_BAUDRATE); + uart3Setup(FRSKY_SPORT_BAUDRATE, false); break; #if !defined(USB_SERIAL) && (defined(DEBUG) || defined(CLI)) case UART_MODE_DEBUG: - uart3Setup(DEBUG_BAUDRATE); + uart3Setup(DEBUG_BAUDRATE, false); break; #endif case UART_MODE_TELEMETRY: if (protocol == PROTOCOL_FRSKY_D_SECONDARY) { - uart3Setup(FRSKY_D_BAUDRATE); + uart3Setup(FRSKY_D_BAUDRATE, true); } break; } @@ -89,18 +115,20 @@ void serial2Putc(char c) void serial2SbusInit() { - uart3Setup(100000); + // TODO is it possible on Horus? + uart3Setup(SBUS_BAUDRATE, true); SERIAL_USART->CR1 |= USART_CR1_M | USART_CR1_PCE ; } void serial2Stop() { + DMA_DeInit(SERIAL_DMA_Stream_RX); USART_DeInit(SERIAL_USART); } uint8_t serial2TracesEnabled() { - return 1; // (serial2Mode == 0); + return 1; // TODO (serial2Mode == 0); } #if !defined(SIMU) @@ -118,29 +146,21 @@ extern "C" void SERIAL_USART_IRQHandler(void) } } +#if !defined(USB_SERIAL) && defined(CLI) // Receive uint32_t status = SERIAL_USART->SR; while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) { uint8_t data = SERIAL_USART->DR; - if (!(status & USART_FLAG_ERRORS)) { switch (serial2Mode) { - case UART_MODE_TELEMETRY: - telemetryFifo.push(data); - break; - case UART_MODE_SBUS_TRAINER: - sbusFifo.push(data); - break; -#if defined(CLI) case UART_MODE_DEBUG: cliRxFifo.push(data); break; -#endif } } - status = SERIAL_USART->SR; } -} #endif +} +#endif diff --git a/radio/src/targets/horus/telemetry_driver.cpp b/radio/src/targets/horus/telemetry_driver.cpp index be550df04..5edd40fca 100644 --- a/radio/src/targets/horus/telemetry_driver.cpp +++ b/radio/src/targets/horus/telemetry_driver.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -18,9 +18,9 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" -extern Fifo telemetryFifo; +DMAFifo<512> telemetryFifo __DMA (TELEMETRY_DMA_Stream_RX); void telemetryPortInit(uint32_t baudrate) { @@ -29,6 +29,13 @@ void telemetryPortInit(uint32_t baudrate) return; } + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = TELEMETRY_DMA_TX_Stream_IRQ; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; @@ -47,32 +54,45 @@ void telemetryPortInit(uint32_t baudrate) GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(TELEMETRY_GPIO_DIR, &GPIO_InitStructure); GPIO_ResetBits(TELEMETRY_GPIO_DIR, TELEMETRY_DIR_GPIO_PIN); - + USART_InitStructure.USART_BaudRate = baudrate; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; - + USART_Init(TELEMETRY_USART, &USART_InitStructure); + + DMA_InitTypeDef DMA_InitStructure; + telemetryFifo.clear(); + USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, DISABLE); + USART_ITConfig(TELEMETRY_USART, USART_IT_TXE, DISABLE); + DMA_InitStructure.DMA_Channel = TELEMETRY_DMA_Channel_RX; + DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&TELEMETRY_USART->DR); + DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(telemetryFifo.buffer()); + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; + DMA_InitStructure.DMA_BufferSize = telemetryFifo.size(); + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; + DMA_InitStructure.DMA_Priority = DMA_Priority_Low; + DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; + DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; + DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; + DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + DMA_Init(TELEMETRY_DMA_Stream_RX, &DMA_InitStructure); + USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Rx, ENABLE); USART_Cmd(TELEMETRY_USART, ENABLE); - USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, ENABLE); - - NVIC_SetPriority(TELEMETRY_USART_IRQn, 6); - NVIC_EnableIRQ(TELEMETRY_USART_IRQn); + DMA_Cmd(TELEMETRY_DMA_Stream_RX, ENABLE); } -struct SportTxBuffer -{ - uint8_t *ptr; - uint32_t count; -} sportTxBuffer; - void telemetryPortSetDirectionOutput() { TELEMETRY_GPIO_DIR->BSRRL = TELEMETRY_DIR_GPIO_PIN; // output enable - TELEMETRY_USART->CR1 &= ~USART_CR1_RE; // turn off receiver + TELEMETRY_USART->CR1 &= ~USART_CR1_RE; // turn off receiver } void telemetryPortSetDirectionInput() @@ -81,49 +101,64 @@ void telemetryPortSetDirectionInput() TELEMETRY_USART->CR1 |= USART_CR1_RE; // turn on receiver } -void sportSendBuffer(uint8_t *buffer, uint32_t count) +void sportSendBuffer(uint8_t * buffer, uint32_t count) { - sportTxBuffer.ptr = buffer ; - sportTxBuffer.count = count ; + #if 0 telemetryPortSetDirectionOutput(); - TELEMETRY_USART->CR1 |= USART_CR1_TXEIE ; + + DMA_InitTypeDef DMA_InitStructure; + DMA_DeInit(TELEMETRY_DMA_Stream_TX); + DMA_InitStructure.DMA_Channel = TELEMETRY_DMA_Channel_TX; + DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&TELEMETRY_USART->DR); + DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; + DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(buffer); + DMA_InitStructure.DMA_BufferSize = count; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; + DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; + DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; + DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; + DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + DMA_Init(TELEMETRY_DMA_Stream_TX, &DMA_InitStructure); + DMA_Cmd(TELEMETRY_DMA_Stream_TX, ENABLE); + USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Tx, ENABLE); + DMA_ITConfig(TELEMETRY_DMA_Stream_TX, DMA_IT_TC, ENABLE); + + // enable interrupt and set it's priority + NVIC_EnableIRQ(TELEMETRY_DMA_TX_Stream_IRQ) ; + NVIC_SetPriority(TELEMETRY_DMA_TX_Stream_IRQ, 7); + #endif } -#if !defined(SIMU) -#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) - -extern "C" void TELEMETRY_USART_IRQHandler() +extern "C" void TELEMETRY_DMA_TX_IRQHandler(void) { - uint32_t status; - uint8_t data; - - status = TELEMETRY_USART->SR; - - if (status & USART_SR_TXE) { - if (sportTxBuffer.count) { - TELEMETRY_USART->DR = *sportTxBuffer.ptr++; - if (--sportTxBuffer.count == 0) { - TELEMETRY_USART->CR1 &= ~USART_CR1_TXEIE; // stop Tx interrupt - TELEMETRY_USART->CR1 |= USART_CR1_TCIE; // enable complete interrupt - } - } - } - - if ((status & USART_SR_TC) && (TELEMETRY_USART->CR1 & USART_CR1_TCIE)) { - TELEMETRY_USART->CR1 &= ~USART_CR1_TCIE ; // stop Complete interrupt + if (DMA_GetITStatus(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC)) { + DMA_ClearITPendingBit(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC); telemetryPortSetDirectionInput(); - while (status & (USART_FLAG_RXNE)) { - status = TELEMETRY_USART->DR; - status = TELEMETRY_USART->SR ; - } - } - - while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) { - data = TELEMETRY_USART->DR; - if (!(status & USART_FLAG_ERRORS)) { - telemetryFifo.push(data); - } - status = TELEMETRY_USART->SR; } } + +// TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp +int telemetryGetByte(uint8_t * byte) +{ + // TODO I am not sure it's possible to have this cable on Horus ... +#if 0 + if (telemetryProtocol == PROTOCOL_FRSKY_D_SECONDARY) { + if (serial2Mode == UART_MODE_TELEMETRY) + return serial2RxFifo.pop(*byte); + else + return 0; + } + else { + return telemetryFifo.pop(*byte); + } +#else + return telemetryFifo.pop(*byte); #endif + + +} diff --git a/radio/src/targets/horus/trainer_driver.cpp b/radio/src/targets/horus/trainer_driver.cpp index c29d28029..0df472d99 100644 --- a/radio/src/targets/horus/trainer_driver.cpp +++ b/radio/src/targets/horus/trainer_driver.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -177,7 +177,7 @@ void stop_cppm_on_heartbeat_capture(void) TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt - if (!IS_PULSES_EXTERNAL_MODULE()) { + if (!IS_EXTERNAL_MODULE_PRESENT()) { EXTERNAL_MODULE_OFF(); } } @@ -221,7 +221,7 @@ void stop_sbus_on_heartbeat_capture(void) configure_pins(HEARTBEAT_GPIO_PIN, PIN_INPUT | PIN_PORTC); NVIC_DisableIRQ(HEARTBEAT_USART_IRQn); #endif - if (!IS_PULSES_EXTERNAL_MODULE()) { + if (!IS_EXTERNAL_MODULE_PRESENT()) { EXTERNAL_MODULE_OFF(); } } @@ -246,3 +246,8 @@ extern "C" void HEARTBEAT_USART_IRQHandler() } } #endif + +int sbusGetByte(uint8_t * byte) +{ + return false; +} diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index 4bb3c425a..d79130eae 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -57,7 +57,7 @@ uint32_t Peri1_frequency, Peri2_frequency; GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog, gpioh, gpioi, gpioj; TIM_TypeDef tim1, tim2, tim3, tim4, tim5, tim6, tim7, tim8, tim9, tim10; RCC_TypeDef rcc; -DMA_Stream_TypeDef dma2_stream2, dma2_stream6; +DMA_Stream_TypeDef dma2_stream2, dma2_stream6, dma1_stream5; DMA_TypeDef dma2; USART_TypeDef Usart0, Usart1, Usart2, Usart3, Usart4; #elif defined(CPUARM) @@ -1297,6 +1297,7 @@ FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG) { ret void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF) { } void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct) { } void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState) { } +void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState) { } void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState) { } void RCC_PLLI2SConfig(uint32_t PLLI2SN, uint32_t PLLI2SR) { } void RCC_PLLI2SCmd(FunctionalState NewState) { } diff --git a/radio/src/targets/simu/simpgmspace.h b/radio/src/targets/simu/simpgmspace.h index f691feffc..647c73115 100644 --- a/radio/src/targets/simu/simpgmspace.h +++ b/radio/src/targets/simu/simpgmspace.h @@ -93,7 +93,7 @@ extern GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog, gpioh, gpio extern TIM_TypeDef tim1, tim2, tim3, tim4, tim5, tim6, tim7, tim8, tim9, tim10; extern USART_TypeDef Usart0, Usart1, Usart2, Usart3, Usart4; extern RCC_TypeDef rcc; -extern DMA_Stream_TypeDef dma2_stream2, dma2_stream6; +extern DMA_Stream_TypeDef dma2_stream2, dma2_stream6, dma1_stream5; extern DMA_TypeDef dma2; #undef GPIOA #undef GPIOB @@ -145,8 +145,10 @@ extern DMA_TypeDef dma2; #define USART3 (&Usart3) #undef RCC #define RCC (&rcc) +#undef DMA1_Stream5 #undef DMA2_Stream2 #undef DMA2_Stream6 +#define DMA1_Stream5 (&dma1_stream5) #define DMA2_Stream2 (&dma2_stream2) #define DMA2_Stream6 (&dma2_stream6) #undef DMA2 @@ -427,7 +429,9 @@ OS_TID CoCreateTask(FUNCPtr task, void *argv, uint32_t parameter, void * stk, ui #if defined(CPUSTM32) inline void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) { } #define TIM_DeInit(...) -#define TIM_TimeBaseInit(...) +#if defined(PCBHORUS) +inline void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) { } +#endif #define TIM_SetCompare2(...) #define TIM_ClearFlag(...) #define TIM_Cmd(...) @@ -449,6 +453,8 @@ inline void DMA_ITConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT, Func inline void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct) { } inline void DMA_Cmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState) { } inline FlagStatus DMA_GetFlagStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG) { return RESET; } +inline ITStatus DMA_GetITStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT) { return RESET; } +inline void DMA_ClearITPendingBit(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT) { } inline void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState) { } inline void UART3_Configure(uint32_t baudrate, uint32_t masterClock) { } inline void NVIC_Init(NVIC_InitTypeDef *) { } diff --git a/radio/src/targets/sky9x/board_sky9x.cpp b/radio/src/targets/sky9x/board_sky9x.cpp index 4f8249077..1398a4888 100644 --- a/radio/src/targets/sky9x/board_sky9x.cpp +++ b/radio/src/targets/sky9x/board_sky9x.cpp @@ -590,3 +590,10 @@ void checkTrainerSettings() } } +uint16_t getBatteryVoltage() +{ + int32_t instant_vbat = anaIn(TX_VOLTAGE); // using filtered ADC value on purpose + instant_vbat = (instant_vbat + instant_vbat*(g_eeGeneral.txVoltageCalibration)/128) * 4191; + instant_vbat /= 5530; + return (uint16_t)instant_vbat; +} diff --git a/radio/src/targets/sky9x/board_sky9x.h b/radio/src/targets/sky9x/board_sky9x.h index 72a7033aa..258cde686 100644 --- a/radio/src/targets/sky9x/board_sky9x.h +++ b/radio/src/targets/sky9x/board_sky9x.h @@ -228,6 +228,7 @@ enum Analogs { void adcInit(); void adcRead(void); uint16_t getAnalogValue(uint8_t index); +uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps void setSticksGain(uint8_t gains); // Buzzer driver diff --git a/radio/src/targets/taranis/audio_driver.cpp b/radio/src/targets/taranis/audio_driver.cpp index f2123b510..834450941 100644 --- a/radio/src/targets/taranis/audio_driver.cpp +++ b/radio/src/targets/taranis/audio_driver.cpp @@ -27,23 +27,20 @@ void setSampleRate(uint32_t frequency) { register uint32_t timer = (PERI1_FREQUENCY * TIMER_MULT_APB1) / frequency - 1 ; // MCK/8 and 100 000 Hz - TIM6->CR1 &= ~TIM_CR1_CEN ; - TIM6->CNT = 0 ; - TIM6->ARR = limit(2, timer, 65535) ; - TIM6->CR1 |= TIM_CR1_CEN ; + AUDIO_TIMER->CR1 &= ~TIM_CR1_CEN ; + AUDIO_TIMER->CNT = 0 ; + AUDIO_TIMER->ARR = limit(2, timer, 65535) ; + AUDIO_TIMER->CR1 |= TIM_CR1_CEN ; } // Start TIMER6 at 100000Hz, used for DAC trigger void dacTimerInit() { - // Now for timer 6 - RCC->APB1ENR |= RCC_APB1ENR_TIM6EN ; // Enable clock - - TIM6->PSC = 0 ; // Max speed - TIM6->ARR = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 100000 - 1 ; // 10 uS, 100 kHz - TIM6->CR2 = 0 ; - TIM6->CR2 = 0x20 ; - TIM6->CR1 = TIM_CR1_CEN ; + AUDIO_TIMER->PSC = 0 ; // Max speed + AUDIO_TIMER->ARR = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 100000 - 1 ; // 10 uS, 100 kHz + AUDIO_TIMER->CR2 = 0 ; + AUDIO_TIMER->CR2 = 0x20 ; + AUDIO_TIMER->CR1 = TIM_CR1_CEN ; } // Configure DAC0 (or DAC1 for REVA) @@ -53,39 +50,36 @@ void dacInit() { dacTimerInit(); - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN ; // Enable portA clock configure_pins( GPIO_Pin_4, PIN_ANALOG | PIN_PORTA ) ; - RCC->APB1ENR |= RCC_APB1ENR_DACEN ; // Enable clock - RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN ; // Enable DMA1 clock // Chan 7, 16-bit wide, Medium priority, memory increments - DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA - DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits - DMA1_Stream5->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 | + AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA + AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits + AUDIO_DMA_Stream->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_CIRC ; - DMA1_Stream5->PAR = CONVERT_PTR_UINT(&DAC->DHR12R1); - // DMA1_Stream5->M0AR = CONVERT_PTR_UINT(Sine_values); - DMA1_Stream5->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ; - // DMA1_Stream5->NDTR = 100 ; + AUDIO_DMA_Stream->PAR = CONVERT_PTR_UINT(&DAC->DHR12R1); + // AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(Sine_values); + AUDIO_DMA_Stream->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ; + // AUDIO_DMA_Stream->NDTR = 100 ; DAC->DHR12R1 = 2010 ; DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag DAC->CR = DAC_CR_TEN1 | DAC_CR_EN1 ; // Enable DAC - NVIC_EnableIRQ(TIM6_DAC_IRQn); // TODO needed? - NVIC_SetPriority(TIM6_DAC_IRQn, 7); - NVIC_EnableIRQ(DMA1_Stream5_IRQn); - NVIC_SetPriority(DMA1_Stream5_IRQn, 7); + NVIC_EnableIRQ(AUDIO_TIM_IRQn); // TODO needed? + NVIC_SetPriority(AUDIO_TIM_IRQn, 7); + NVIC_EnableIRQ(AUDIO_DMA_Stream_IRQn); + NVIC_SetPriority(AUDIO_DMA_Stream_IRQn, 7); } bool audioPushBuffer(AudioBuffer * buffer) { if (dacIdle) { dacIdle = false; - DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA channel - DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits - DMA1_Stream5->M0AR = CONVERT_PTR_UINT(buffer->data); - DMA1_Stream5->NDTR = buffer->size; - DMA1_Stream5->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel and interrupt + AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA channel + AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits + AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(buffer->data); + AUDIO_DMA_Stream->NDTR = buffer->size; + AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel and interrupt DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1 ; // Enable DAC return true; @@ -97,15 +91,15 @@ bool audioPushBuffer(AudioBuffer * buffer) void dacStart() { - DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits - DMA1_Stream5->CR |= DMA_SxCR_CIRC | DMA_SxCR_EN ; // Enable DMA channel + AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits + AUDIO_DMA_Stream->CR |= DMA_SxCR_CIRC | DMA_SxCR_EN ; // Enable DMA channel DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1 ; // Enable DAC } void dacStop() { - DMA1_Stream5->CR &= ~DMA_SxCR_CIRC ; + AUDIO_DMA_Stream->CR &= ~DMA_SxCR_CIRC ; } @@ -118,13 +112,13 @@ void audioInit() void audioEnd() { DAC->CR = 0 ; - TIM6->CR1 = 0 ; + AUDIO_TIMER->CR1 = 0 ; // Also need to turn off any possible interrupts - NVIC_DisableIRQ(TIM6_DAC_IRQn) ; - NVIC_DisableIRQ(DMA1_Stream5_IRQn) ; + NVIC_DisableIRQ(AUDIO_TIM_IRQn) ; + NVIC_DisableIRQ(AUDIO_DMA_Stream_IRQn) ; } -extern "C" void TIM6_DAC_IRQHandler() +extern "C" void AUDIO_TIM_IRQHandler() { DAC->CR &= ~DAC_CR_DMAEN1 ; // Stop DMA requests #if !defined(REV9E) @@ -133,18 +127,18 @@ extern "C" void TIM6_DAC_IRQHandler() DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag } -extern "C" void DMA1_Stream5_IRQHandler() +extern "C" void AUDIO_DMA_Stream_IRQHandler() { - DMA1_Stream5->CR &= ~DMA_SxCR_TCIE ; // Stop interrupt - DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear flags - DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA channel + AUDIO_DMA_Stream->CR &= ~DMA_SxCR_TCIE ; // Stop interrupt + AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear flags + AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA channel AudioBuffer * nextBuffer = audioQueue.getNextFilledBuffer(); if (nextBuffer) { - DMA1_Stream5->M0AR = CONVERT_PTR_UINT(nextBuffer->data); - DMA1_Stream5->NDTR = nextBuffer->size; - DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits - DMA1_Stream5->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel + AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(nextBuffer->data); + AUDIO_DMA_Stream->NDTR = nextBuffer->size; + AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits + AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel DAC->SR = DAC_SR_DMAUDR1; // Write 1 to clear flag } else { diff --git a/radio/src/targets/taranis/board_taranis.cpp b/radio/src/targets/taranis/board_taranis.cpp index 2dd4f43bc..9894d1379 100644 --- a/radio/src/targets/taranis/board_taranis.cpp +++ b/radio/src/targets/taranis/board_taranis.cpp @@ -41,7 +41,11 @@ void watchdogInit(unsigned int duration) void getCPUUniqueID(char * s) { +#if defined(SIMU) + uint32_t cpu_uid[3] = { 0x12345678, 0x55AA55AA, 0x87654321}; +#else uint32_t * cpu_uid = (uint32_t *)0x1FFF7A10; +#endif char * tmp = strAppendUnsigned(s, cpu_uid[0], 8, 16); *tmp = ' '; tmp = strAppendUnsigned(tmp+1, cpu_uid[1], 8, 16); @@ -121,8 +125,8 @@ extern "C" void INTERRUPT_5MS_IRQHandler() void boardInit() { - RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | ADC_RCC_AHB1Periph | I2C_RCC_AHB1Periph | SD_RCC_AHB1Periph | HAPTIC_RCC_AHB1Periph | INTMODULE_RCC_AHB1Periph | EXTMODULE_RCC_AHB1Periph | TELEMETRY_RCC_AHB1Periph | SERIAL_RCC_AHB1Periph | TRAINER_RCC_AHB1Periph | HEARTBEAT_RCC_AHB1Periph, ENABLE); - RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | INTERRUPT_5MS_APB1Periph | TIMER_2MHz_APB1Periph | I2C_RCC_APB1Periph | SD_RCC_APB1Periph | TRAINER_RCC_APB1Periph | TELEMETRY_RCC_APB1Periph | SERIAL_RCC_APB1Periph, ENABLE); + RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | LCD_RCC_AHB1Periph | AUDIO_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | ADC_RCC_AHB1Periph | I2C_RCC_AHB1Periph | SD_RCC_AHB1Periph | HAPTIC_RCC_AHB1Periph | INTMODULE_RCC_AHB1Periph | EXTMODULE_RCC_AHB1Periph | TELEMETRY_RCC_AHB1Periph | SERIAL_RCC_AHB1Periph | TRAINER_RCC_AHB1Periph | HEARTBEAT_RCC_AHB1Periph, ENABLE); + RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | AUDIO_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | INTERRUPT_5MS_APB1Periph | TIMER_2MHz_APB1Periph | I2C_RCC_APB1Periph | SD_RCC_APB1Periph | TRAINER_RCC_APB1Periph | TELEMETRY_RCC_APB1Periph | SERIAL_RCC_APB1Periph, ENABLE); RCC_APB2PeriphClockCmd(BACKLIGHT_RCC_APB2Periph | ADC_RCC_APB2Periph | HAPTIC_RCC_APB2Periph | INTMODULE_RCC_APB2Periph | EXTMODULE_RCC_APB2Periph | HEARTBEAT_RCC_APB2Periph, ENABLE); #if !defined(REV9E) @@ -312,3 +316,11 @@ void checkTrainerSettings() } } } + +uint16_t getBatteryVoltage() +{ + int32_t instant_vbat = anaIn(TX_VOLTAGE); // using filtered ADC value on purpose + instant_vbat = (instant_vbat * BATT_SCALE * (128 + g_eeGeneral.txVoltageCalibration) ) / 26214; + instant_vbat += 20; // add 0.2V because of the diode TODO check if this is needed, but removal will beak existing calibrations!!! + return (uint16_t)instant_vbat; +} diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index 3d9657fc2..00b28505f 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -212,6 +212,7 @@ void stop_cppm_on_heartbeat_capture(void); void init_sbus_on_heartbeat_capture(void); void stop_sbus_on_heartbeat_capture(void); void set_trainer_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive); +int sbusGetByte(uint8_t * byte); // Keys driver void keysInit(void); @@ -267,6 +268,7 @@ void adcInit(void); void adcRead(void); extern uint16_t adcValues[NUMBER_ANALOG]; uint16_t getAnalogValue(uint8_t index); +uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps #define BATT_SCALE 150 @@ -322,7 +324,9 @@ void debugPutc(const char c); // Telemetry driver void telemetryPortInit(uint32_t baudrate); void telemetryPortSetDirectionOutput(void); -void sportSendBuffer(uint8_t *buffer, uint32_t count); +void sportSendBuffer(uint8_t * buffer, uint32_t count); +int telemetryGetByte(uint8_t * byte); +extern uint32_t telemetryErrors; // Audio driver void audioInit(void) ; @@ -348,6 +352,7 @@ void hapticOff(void); // Second serial port driver #define DEBUG_BAUDRATE 115200 +extern uint8_t serial2Mode; void serial2Init(unsigned int mode, unsigned int protocol); void serial2Putc(char c); #define serial2TelemetryInit(protocol) serial2Init(UART_MODE_TELEMETRY, protocol) @@ -391,4 +396,12 @@ void usbJoystickUpdate(void); extern uint8_t currentTrainerMode; void checkTrainerSettings(void); +#if defined(__cplusplus) +#include "fifo.h" +#include "dmafifo.h" +extern Fifo telemetryFifo; +extern DMAFifo<32> serial2RxFifo; +extern Fifo sbusFifo; +#endif + #endif // _BOARD_TARANIS_H_ diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 5533becdd..1a60e7935 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -375,12 +375,14 @@ #define SERIAL_USART USART3 #define SERIAL_USART_IRQHandler USART3_IRQHandler #define SERIAL_USART_IRQn USART3_IRQn +#define SERIAL_DMA_Stream_RX DMA1_Stream1 +#define SERIAL_DMA_Channel_RX DMA_Channel_4 // Telemetry -#define TELEMETRY_RCC_AHB1Periph RCC_AHB1Periph_GPIOD +#define TELEMETRY_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1) +#define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2 #define TELEMETRY_GPIO_DIR GPIOD #define TELEMETRY_DIR_GPIO_PIN GPIO_Pin_4 // PD.04 -#define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2 #define TELEMETRY_GPIO GPIOD #define TELEMETRY_TX_GPIO_PIN GPIO_Pin_5 // PD.05 #define TELEMETRY_RX_GPIO_PIN GPIO_Pin_6 // PD.06 @@ -388,6 +390,11 @@ #define TELEMETRY_GPIO_PinSource_RX GPIO_PinSource6 #define TELEMETRY_GPIO_AF GPIO_AF_USART2 #define TELEMETRY_USART USART2 +#define TELEMETRY_DMA_Stream_TX DMA1_Stream6 +#define TELEMETRY_DMA_Channel_TX DMA_Channel_4 +#define TELEMETRY_DMA_TX_Stream_IRQ DMA1_Stream6_IRQn +#define TELEMETRY_DMA_TX_IRQHandler DMA1_Stream6_IRQHandler +#define TELEMETRY_DMA_TX_FLAG_TC DMA_IT_TCIF6 #define TELEMETRY_USART_IRQHandler USART2_IRQHandler #define TELEMETRY_USART_IRQn USART2_IRQn @@ -400,6 +407,8 @@ #define HEARTBEAT_USART USART6 #define HEARTBEAT_USART_IRQHandler USART6_IRQHandler #define HEARTBEAT_USART_IRQn USART6_IRQn +#define HEARTBEAT_DMA_Stream DMA2_Stream2 +#define HEARTBEAT_DMA_Channel DMA_Channel_5 // USB #define USB_RCC_AHB1Periph_GPIO RCC_AHB1Periph_GPIOA @@ -481,7 +490,7 @@ #define LCD_GPIO_PIN_NCS GPIO_Pin_14 // PD.14 #define LCD_GPIO_PIN_A0 GPIO_Pin_13 // PD.13 #define LCD_GPIO_PIN_RST GPIO_Pin_12 // PD.12 -#endif +#endif // I2C Bus: EEPROM and CAT5137 digital pot for volume control #define I2C_RCC_AHB1Periph RCC_AHB1Periph_GPIOB @@ -530,6 +539,17 @@ #define SD_DMA_Channel_SPI DMA_Channel_0 #endif +// Audio +#define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1) +#define AUDIO_RCC_APB1Periph (RCC_APB1Periph_TIM6 | RCC_APB1Periph_DAC) +#define AUDIO_DMA_Stream DMA1_Stream5 +#define AUDIO_DMA_Stream_IRQn DMA1_Stream5_IRQn +#define AUDIO_TIM_IRQn TIM6_DAC_IRQn +#define AUDIO_TIM_IRQHandler TIM6_DAC_IRQHandler +#define AUDIO_DMA_Stream_IRQHandler DMA1_Stream5_IRQHandler +#define AUDIO_TIMER TIM6 +#define AUDIO_DMA DMA1 + // Haptic #if defined(REVPLUS) #define HAPTIC_RCC_AHB1Periph RCC_AHB1Periph_GPIOB diff --git a/radio/src/targets/taranis/serial2_driver.cpp b/radio/src/targets/taranis/serial2_driver.cpp index 614e9b9d0..ab5018a6c 100644 --- a/radio/src/targets/taranis/serial2_driver.cpp +++ b/radio/src/targets/taranis/serial2_driver.cpp @@ -1,31 +1,30 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "../../opentx.h" +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "opentx.h" uint8_t serial2Mode = 0; Fifo serial2TxFifo; -extern Fifo telemetryFifo; -extern Fifo sbusFifo; +DMAFifo<32> serial2RxFifo __DMA (SERIAL_DMA_Stream_RX); -void uart3Setup(unsigned int baudrate) +void uart3Setup(unsigned int baudrate, bool dma) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; @@ -39,42 +38,70 @@ void uart3Setup(unsigned int baudrate) GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SERIAL_GPIO, &GPIO_InitStructure); - + USART_InitStructure.USART_BaudRate = baudrate; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; - + USART_Init(SERIAL_USART, &USART_InitStructure); - USART_Cmd(SERIAL_USART, ENABLE); - USART_ITConfig(SERIAL_USART, USART_IT_RXNE, ENABLE); - USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE); - - NVIC_SetPriority(SERIAL_USART_IRQn, 7); - NVIC_EnableIRQ(SERIAL_USART_IRQn); + if (dma) { + DMA_InitTypeDef DMA_InitStructure; + serial2RxFifo.clear(); + USART_ITConfig(SERIAL_USART, USART_IT_RXNE, DISABLE); + USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE); + DMA_InitStructure.DMA_Channel = SERIAL_DMA_Channel_RX; + DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&SERIAL_USART->DR); + DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(serial2RxFifo.buffer()); + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; + DMA_InitStructure.DMA_BufferSize = serial2RxFifo.size(); + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; + DMA_InitStructure.DMA_Priority = DMA_Priority_Low; + DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; + DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; + DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; + DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + DMA_Init(SERIAL_DMA_Stream_RX, &DMA_InitStructure); + USART_DMACmd(SERIAL_USART, USART_DMAReq_Rx, ENABLE); + USART_Cmd(SERIAL_USART, ENABLE); + DMA_Cmd(SERIAL_DMA_Stream_RX, ENABLE); + } + else { +#if !defined(USB_SERIAL) && defined(CLI) + USART_Cmd(SERIAL_USART, ENABLE); + USART_ITConfig(SERIAL_USART, USART_IT_RXNE, ENABLE); + USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE); + NVIC_SetPriority(SERIAL_USART_IRQn, 7); + NVIC_EnableIRQ(SERIAL_USART_IRQn); +#endif + } } void serial2Init(unsigned int mode, unsigned int protocol) { - USART_DeInit(SERIAL_USART); + serial2Stop(); serial2Mode = mode; switch (mode) { case UART_MODE_TELEMETRY_MIRROR: - uart3Setup(FRSKY_SPORT_BAUDRATE); + uart3Setup(FRSKY_SPORT_BAUDRATE, false); break; #if !defined(USB_SERIAL) && (defined(DEBUG) || defined(CLI)) case UART_MODE_DEBUG: - uart3Setup(DEBUG_BAUDRATE); + uart3Setup(DEBUG_BAUDRATE, false); break; #endif case UART_MODE_TELEMETRY: if (protocol == PROTOCOL_FRSKY_D_SECONDARY) { - uart3Setup(FRSKY_D_BAUDRATE); + uart3Setup(FRSKY_D_BAUDRATE, true); } break; } @@ -89,12 +116,13 @@ void serial2Putc(char c) void serial2SbusInit() { - uart3Setup(SBUS_BAUDRATE); + uart3Setup(SBUS_BAUDRATE, true); SERIAL_USART->CR1 |= USART_CR1_M | USART_CR1_PCE ; } void serial2Stop() { + DMA_DeInit(SERIAL_DMA_Stream_RX); USART_DeInit(SERIAL_USART); } @@ -122,29 +150,21 @@ extern "C" void SERIAL_USART_IRQHandler(void) } } +#if !defined(USB_SERIAL) && defined(CLI) // Receive uint32_t status = SERIAL_USART->SR; while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) { uint8_t data = SERIAL_USART->DR; - if (!(status & USART_FLAG_ERRORS)) { switch (serial2Mode) { - case UART_MODE_TELEMETRY: - telemetryFifo.push(data); - break; - case UART_MODE_SBUS_TRAINER: - sbusFifo.push(data); - break; -#if !defined(USB_SERIAL) && defined(CLI) case UART_MODE_DEBUG: cliRxFifo.push(data); break; -#endif } } - status = SERIAL_USART->SR; } -} #endif +} +#endif diff --git a/radio/src/targets/taranis/telemetry_driver.cpp b/radio/src/targets/taranis/telemetry_driver.cpp index 3ebfffc64..0718ce059 100644 --- a/radio/src/targets/taranis/telemetry_driver.cpp +++ b/radio/src/targets/taranis/telemetry_driver.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -18,9 +18,10 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" -extern Fifo telemetryFifo; +Fifo telemetryFifo; +uint32_t telemetryErrors = 0; void telemetryPortInit(uint32_t baudrate) { @@ -29,6 +30,13 @@ void telemetryPortInit(uint32_t baudrate) return; } + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = TELEMETRY_DMA_TX_Stream_IRQ; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; @@ -41,7 +49,7 @@ void telemetryPortInit(uint32_t baudrate) GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure); - + GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; @@ -54,21 +62,13 @@ void telemetryPortInit(uint32_t baudrate) USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; - USART_Init(TELEMETRY_USART, &USART_InitStructure); USART_Cmd(TELEMETRY_USART, ENABLE); USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, ENABLE); - NVIC_SetPriority(TELEMETRY_USART_IRQn, 6); NVIC_EnableIRQ(TELEMETRY_USART_IRQn); } -struct SportTxBuffer -{ - uint8_t *ptr; - uint32_t count; -} sportTxBuffer; - void telemetryPortSetDirectionOutput() { TELEMETRY_GPIO_DIR->BSRRL = TELEMETRY_DIR_GPIO_PIN; // output enable @@ -83,47 +83,69 @@ void telemetryPortSetDirectionInput() void sportSendBuffer(uint8_t * buffer, uint32_t count) { - sportTxBuffer.ptr = buffer; - sportTxBuffer.count = count; telemetryPortSetDirectionOutput(); - TELEMETRY_USART->CR1 |= USART_CR1_TXEIE; + + DMA_InitTypeDef DMA_InitStructure; + DMA_DeInit(TELEMETRY_DMA_Stream_TX); + DMA_InitStructure.DMA_Channel = TELEMETRY_DMA_Channel_TX; + DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&TELEMETRY_USART->DR); + DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; + DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(buffer); + DMA_InitStructure.DMA_BufferSize = count; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; + DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; + DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; + DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; + DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + DMA_Init(TELEMETRY_DMA_Stream_TX, &DMA_InitStructure); + DMA_Cmd(TELEMETRY_DMA_Stream_TX, ENABLE); + USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Tx, ENABLE); + DMA_ITConfig(TELEMETRY_DMA_Stream_TX, DMA_IT_TC, ENABLE); + + // enable interrupt and set it's priority + NVIC_EnableIRQ(TELEMETRY_DMA_TX_Stream_IRQ) ; + NVIC_SetPriority(TELEMETRY_DMA_TX_Stream_IRQ, 7); } -#if !defined(SIMU) -#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) - -extern "C" void TELEMETRY_USART_IRQHandler() +extern "C" void TELEMETRY_DMA_TX_IRQHandler(void) { - uint32_t status; - uint8_t data; - - status = TELEMETRY_USART->SR; - - if (status & USART_SR_TXE) { - if (sportTxBuffer.count) { - TELEMETRY_USART->DR = *sportTxBuffer.ptr++; - if (--sportTxBuffer.count == 0) { - TELEMETRY_USART->CR1 &= ~USART_CR1_TXEIE; // stop Tx interrupt - TELEMETRY_USART->CR1 |= USART_CR1_TCIE; // enable complete interrupt - } - } - } - - if ((status & USART_SR_TC) && (TELEMETRY_USART->CR1 & USART_CR1_TCIE)) { - TELEMETRY_USART->CR1 &= ~USART_CR1_TCIE ; // stop Complete interrupt + if (DMA_GetITStatus(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC)) { + DMA_ClearITPendingBit(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC); telemetryPortSetDirectionInput(); - while (status & (USART_FLAG_RXNE)) { - status = TELEMETRY_USART->DR; - status = TELEMETRY_USART->SR; - } } - +} + +#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) +extern "C" void TELEMETRY_USART_IRQHandler(void) +{ + uint32_t status = TELEMETRY_USART->SR; while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) { - data = TELEMETRY_USART->DR; - if (!(status & USART_FLAG_ERRORS)) { + uint8_t data = TELEMETRY_USART->DR; + if (status & USART_FLAG_ERRORS) { + telemetryErrors++; + } + else { telemetryFifo.push(data); } status = TELEMETRY_USART->SR; } } -#endif + +// TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp +int telemetryGetByte(uint8_t * byte) +{ + if (telemetryProtocol == PROTOCOL_FRSKY_D_SECONDARY) { + if (serial2Mode == UART_MODE_TELEMETRY) + return serial2RxFifo.pop(*byte); + else + return 0; + } + else { + return telemetryFifo.pop(*byte); + } +} diff --git a/radio/src/targets/taranis/trainer_driver.cpp b/radio/src/targets/taranis/trainer_driver.cpp index 7da2b6f4d..80fd99615 100644 --- a/radio/src/targets/taranis/trainer_driver.cpp +++ b/radio/src/targets/taranis/trainer_driver.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -18,9 +18,9 @@ * GNU General Public License for more details. */ -#include "../../opentx.h" +#include "opentx.h" -extern Fifo sbusFifo; +DMAFifo<32> heartbeatFifo __DMA (HEARTBEAT_DMA_Stream); #define setupTrainerPulses() setupPulsesPPM(TRAINER_MODULE) @@ -177,7 +177,7 @@ void stop_cppm_on_heartbeat_capture(void) TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt - if (!IS_PULSES_EXTERNAL_MODULE()) { + if (!IS_EXTERNAL_MODULE_PRESENT()) { EXTERNAL_MODULE_OFF(); } } @@ -204,13 +204,31 @@ void init_sbus_on_heartbeat_capture() USART_InitStructure.USART_Parity = USART_Parity_Even; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx; - USART_Init(HEARTBEAT_USART, &USART_InitStructure); - USART_Cmd(HEARTBEAT_USART, ENABLE); - USART_ITConfig(HEARTBEAT_USART, USART_IT_RXNE, ENABLE); - NVIC_SetPriority(HEARTBEAT_USART_IRQn, 6); - NVIC_EnableIRQ(HEARTBEAT_USART_IRQn); + DMA_InitTypeDef DMA_InitStructure; + heartbeatFifo.clear(); + USART_ITConfig(HEARTBEAT_USART, USART_IT_RXNE, DISABLE); + USART_ITConfig(HEARTBEAT_USART, USART_IT_TXE, DISABLE); + DMA_InitStructure.DMA_Channel = HEARTBEAT_DMA_Channel; + DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&HEARTBEAT_USART->DR); + DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(heartbeatFifo.buffer()); + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; + DMA_InitStructure.DMA_BufferSize = heartbeatFifo.size(); + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; + DMA_InitStructure.DMA_Priority = DMA_Priority_Low; + DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; + DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; + DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; + DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + DMA_Init(HEARTBEAT_DMA_Stream, &DMA_InitStructure); + USART_DMACmd(HEARTBEAT_USART, USART_DMAReq_Rx, ENABLE); + USART_Cmd(HEARTBEAT_USART, ENABLE); + DMA_Cmd(HEARTBEAT_DMA_Stream, ENABLE); } void stop_sbus_on_heartbeat_capture(void) @@ -218,28 +236,19 @@ void stop_sbus_on_heartbeat_capture(void) configure_pins(HEARTBEAT_GPIO_PIN, PIN_INPUT | PIN_PORTC); NVIC_DisableIRQ(HEARTBEAT_USART_IRQn); - if (!IS_PULSES_EXTERNAL_MODULE()) { + if (!IS_EXTERNAL_MODULE_PRESENT()) { EXTERNAL_MODULE_OFF(); } } -#if !defined(SIMU) && !defined(REV9E) -extern "C" void HEARTBEAT_USART_IRQHandler() +int sbusGetByte(uint8_t * byte) { - uint32_t status; - uint8_t data; - - status = HEARTBEAT_USART->SR; - - while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) { - data = HEARTBEAT_USART->DR; - - if (!(status & USART_FLAG_ERRORS)) { - if (currentTrainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE) - sbusFifo.push(data); - } - - status = HEARTBEAT_USART->SR; + switch (currentTrainerMode) { + case TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE: + return heartbeatFifo.pop(*byte); + case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: + return serial2RxFifo.pop(*byte); + default: + return false; } } -#endif diff --git a/radio/src/telemetry/frsky.cpp b/radio/src/telemetry/frsky.cpp index 96a1300c1..934dc5437 100644 --- a/radio/src/telemetry/frsky.cpp +++ b/radio/src/telemetry/frsky.cpp @@ -43,10 +43,6 @@ uint8_t frskyTxBufferCount = 0; uint8_t telemetryState = TELEMETRY_INIT; #endif -#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS) -Fifo telemetryFifo; // TODO should be in the driver -#endif - uint8_t frskyRxBufferCount = 0; FrskyData frskyData; diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp index 6347ea181..ba77828bf 100644 --- a/radio/src/telemetry/frsky_sport.cpp +++ b/radio/src/telemetry/frsky_sport.cpp @@ -337,9 +337,9 @@ bool sportWaitState(SportUpdateState state, int timeout) return true; #else for (int i=timeout/2; i>=0; i--) { - uint8_t data ; - while (telemetryFifo.pop(data)) { - processSerialData(data); + uint8_t byte ; + while (telemetryGetByte(&byte)) { + processSerialData(byte); } if (sportUpdateState == state) { return true; @@ -358,7 +358,7 @@ void blankPacket(uint8_t *packet) memset(packet+2, 0, 6); } -uint8_t sportUpdatePacket[16]; +uint8_t sportUpdatePacket[16] __DMA; void writePacket(uint8_t * packet) { diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index 5cb981ccb..36b3f695d 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -21,8 +21,6 @@ #ifndef _TELEMETRY_H_ #define _TELEMETRY_H_ -extern Fifo telemetryFifo; - enum TelemetryProtocol { TELEM_PROTO_FRSKY_D, diff --git a/radio/src/tests/lcd.cpp b/radio/src/tests/lcd.cpp index 926fe07f6..1f27bad18 100644 --- a/radio/src/tests/lcd.cpp +++ b/radio/src/tests/lcd.cpp @@ -194,16 +194,6 @@ TEST(Lcd, vline_x_lt0) #endif #if defined(CPUARM) -TEST(Lcd, SmlsizeDecimalPoint) -{ - lcdClear(); - lcdDrawNumber(0, 1, 105, PREC1|SMLSIZE|LEFT); - lcdDrawNumber(0, LCD_H-7, 105, PREC1|SMLSIZE|LEFT|INVERS); - lcdDrawNumber(LCD_W, 1, 105, PREC2|SMLSIZE); - lcdDrawNumber(LCD_W, LCD_H-7, 105, PREC2|SMLSIZE|INVERS); - EXPECT_TRUE(checkScreenshot("SmlsizeDecimalPoint")); -} - TEST(Lcd, Smlsize) { lcdClear();