feat(v12): support for HelloRadioSky V12 (#7114)

Co-authored-by: Peter Feerick <5500713+pfeerick@users.noreply.github.com>
Co-authored-by: radiosky <839034809@qq.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
richardclli
2026-08-05 14:57:46 +10:00
committed by GitHub
co-authored by Peter Feerick radiosky Claude Sonnet 5
parent 256dc98917
commit 866ee0a92e
93 changed files with 4582 additions and 406 deletions
+2
View File
@@ -49,6 +49,7 @@ jobs:
- pa01
- t22
- c14
- v12
container:
image: ghcr.io/edgetx/edgetx-dev:latest
volumes:
@@ -95,6 +96,7 @@ jobs:
- tx16smk3;t14;t15pro
- t22
- c14
- v12
container:
image: ghcr.io/edgetx/edgetx-dev:latest
volumes:
+1
View File
@@ -40,6 +40,7 @@ jobs:
- c14
- tx15
- t15pro
- v12
container:
image: ghcr.io/edgetx/edgetx-dev:latest
volumes:
+3 -1
View File
@@ -92,7 +92,9 @@ void BoardJson::afterLoadFixups(Board::Type board, InputsTable * inputs, Switche
{
// TODO json files do not contain gyro defs
// Radio cmake directive IMU is currently used
if (IS_TARANIS_XLITES(board) || IS_FAMILY_HORUS_OR_T16(board) || IS_RADIOMASTER_TX15(board)) {
if (IS_TARANIS_XLITES(board) || IS_FAMILY_HORUS_OR_T16(board) ||
IS_RADIOMASTER_TX15(board) || IS_RADIOMASTER_TX16SMK3(board) ||
IS_FLYSKY_PA01(board)) {
if (getInputIndex(inputs, "TILT_X", Board::LVT_TAG) < 0) {
InputDefn defn;
defn.type = AIT_FLEX;
+17
View File
@@ -163,6 +163,8 @@ uint32_t Boards::getFourCC(Type board)
return 0x4C78746F;
case BOARD_IFLIGHT_COMMANDO14:
return 0x4F78746F;
case BOARD_HELLORADIOSKY_V12:
return 0x4478746F;
case BOARD_HELLORADIOSKY_V14:
return 0x4D78746F;
case BOARD_HELLORADIOSKY_V14LCD:
@@ -234,6 +236,7 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_FLYSKY_ST16:
case BOARD_IFLIGHT_COMMANDO14:
case BOARD_FATFISH_F16:
case BOARD_HELLORADIOSKY_V12:
case BOARD_HELLORADIOSKY_V16:
return 0;
default:
@@ -300,6 +303,7 @@ int Boards::getFlashSize(Type board)
case BOARD_FLYSKY_ST16: // 8MB SDRAM
case BOARD_IFLIGHT_COMMANDO14: // 8MB SDRAM
case BOARD_FATFISH_F16:
case BOARD_HELLORADIOSKY_V12: // 8MB SDRAM
case BOARD_HELLORADIOSKY_V16:
return FSIZE_2MB;
case BOARD_UNKNOWN:
@@ -342,6 +346,13 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
IS_TARANIS_X9DP_2019(board) || IS_FLYSKY_NV14(board) ||
IS_FLYSKY_EL18(board) || IS_FAMILY_PL18(board));
case HasExternalAntenna:
return IS_FAMILY_HORUS(board) || IS_TARANIS_XLITE(board) ||
getCapability(board, HasHardwareAntennaSwitch);
case HasHardwareAntennaSwitch:
return IS_HELLORADIOSKY_V12(board);
case HasIMU:
return (IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS(board) ||
IS_RADIOMASTER_TX15(board));
@@ -675,6 +686,8 @@ QString Boards::getBoardName(Board::Type board)
return "Fatfish F16";
case BOARD_HELLORADIOSKY_V16:
return "HelloRadioSky V16";
case BOARD_HELLORADIOSKY_V12:
return "HelloRadioSky V12";
case BOARD_HELLORADIOSKY_V14:
return "HelloRadioSky V14";
case BOARD_HELLORADIOSKY_V14LCD:
@@ -784,6 +797,7 @@ int Boards::getDefaultInternalModules(Board::Type board)
case BOARD_BETAFPV_LR3PRO:
case BOARD_FATFISH_F16:
case BOARD_HELLORADIOSKY_V12:
case BOARD_HELLORADIOSKY_V14:
case BOARD_HELLORADIOSKY_V14LCD:
case BOARD_HELLORADIOSKY_V16:
@@ -827,6 +841,7 @@ int Boards::getDefaultInternalModules(Board::Type board)
void Boards::getBattRange(Board::Type board, int& vmin, int& vmax, unsigned int& vwarn)
{
switch (board) {
case BOARD_HELLORADIOSKY_V12:
case BOARD_HELLORADIOSKY_V14:
case BOARD_HELLORADIOSKY_V14LCD:
case BOARD_JUMPER_T12:
@@ -903,6 +918,8 @@ int Boards::getDefaultExternalModuleSize(Board::Type board)
if (getCapability(board, HasColorLcd)) {
if (IS_FLYSKY_EL18(board))
return EXTMODSIZE_BOTH;
else if (IS_HELLORADIOSKY_V12(board))
return EXTMODSIZE_SMALL;
else
return EXTMODSIZE_STD;
}
+9 -4
View File
@@ -100,6 +100,7 @@ namespace Board {
BOARD_HELLORADIOSKY_V14,
BOARD_HELLORADIOSKY_V14LCD,
BOARD_IFLIGHT_COMMANDO14,
BOARD_HELLORADIOSKY_V12,
BOARD_TYPE_COUNT,
BOARD_TYPE_MAX = BOARD_TYPE_COUNT - 1
};
@@ -232,7 +233,9 @@ namespace Board {
HasBlingLEDS,
HasBluetooth,
HasColorLcd,
HasExternalAntenna,
HasExternalModuleSupport,
HasHardwareAntennaSwitch,
HasIMU,
HasInternalGPS,
HasInternalModuleSupport,
@@ -656,6 +659,11 @@ inline bool IS_FATFISH_F16(Board::Type board)
return board == Board::BOARD_FATFISH_F16;
}
inline bool IS_HELLORADIOSKY_V12(Board::Type board)
{
return board == Board::BOARD_HELLORADIOSKY_V12;
}
inline bool IS_HELLORADIOSKY_V14(Board::Type board)
{
return board == Board::BOARD_HELLORADIOSKY_V14;
@@ -674,6 +682,7 @@ inline bool IS_HELLORADIOSKY_V16(Board::Type board)
inline bool IS_FAMILY_T16(Board::Type board)
{
return board == Board::BOARD_FATFISH_F16 ||
board == Board::BOARD_HELLORADIOSKY_V12 ||
board == Board::BOARD_HELLORADIOSKY_V16 ||
board == Board::BOARD_JUMPER_T15 ||
board == Board::BOARD_JUMPER_T15PRO ||
@@ -850,10 +859,6 @@ inline bool HAS_LARGE_LCD(Board::Type board)
return IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board);
}
inline bool HAS_EXTERNAL_ANTENNA(Board::Type board)
{
return (IS_FAMILY_HORUS(board) || IS_FAMILY_T16(board) || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board)));
}
inline bool IS_TARANIS_X9DP_2019(Board::Type board)
{
@@ -138,6 +138,13 @@ static const YamlLookupTable failsafeLut = {
{ FAILSAFE_RECEIVER, "RECEIVER" },
};
static const YamlLookupTable moduleAntennaModeLut = {
{ GeneralSettings::ANTENNA_MODE_INTERNAL, "MODE_INTERNAL" },
{ GeneralSettings::ANTENNA_MODE_ASK, "MODE_ASK" },
{ GeneralSettings::ANTENNA_MODE_PER_MODEL, "MODE_PER_MODEL" },
{ GeneralSettings::ANTENNA_MODE_EXTERNAL, "MODE_EXTERNAL" },
};
static int exportPpmDelay(int delay) { return (delay - 300) / 50; }
static int importPpmDelay(int delay) { return 300 + 50 * delay; }
@@ -197,6 +204,8 @@ Node convert<ModuleData>::encode(const ModuleData& rhs)
node["channelsStart"] = rhs.channelsStart;
node["channelsCount"] = rhs.channelsCount;
node["failsafeMode"] = LookupValue(failsafeLut, rhs.failsafeMode);
if (rhs.antennaMode)
node["antennaMode"] = LookupValue(moduleAntennaModeLut, rhs.antennaMode);
Node mod;
switch (protocol) {
@@ -207,7 +216,6 @@ Node convert<ModuleData>::encode(const ModuleData& rhs)
pxx["power"] = rhs.pxx.power;
// pxx["receiverTelemetryOff"] = rhs.pxx.receiverTelemetryOff;
// pxx["receiverHigherChannels"] = rhs.pxx.receiverHigherChannels;
pxx["antennaMode"] = rhs.pxx.antennaMode;
mod["pxx"] = pxx;
} break;
case PULSES_ACCESS_ISRM:
@@ -362,6 +370,8 @@ bool convert<ModuleData>::decode(const Node& node, ModuleData& rhs)
node["channelsStart"] >> rhs.channelsStart;
node["channelsCount"] >> rhs.channelsCount;
node["failsafeMode"] >> failsafeLut >> rhs.failsafeMode;
if (node["antennaMode"])
node["antennaMode"] >> moduleAntennaModeLut >> rhs.antennaMode;
if (node["mod"]) {
const Node& mod = node["mod"];
@@ -386,7 +396,10 @@ bool convert<ModuleData>::decode(const Node& node, ModuleData& rhs)
pxx["power"] >> rhs.pxx.power;
// pxx["receiverTelemetryOff"] >> rhs.pxx.receiverTelemetryOff;
// pxx["receiverHigherChannels"] >> rhs.pxx.receiverHigherChannels;
pxx["antennaMode"] >> rhs.pxx.antennaMode;
// Migration: legacy raw-int antennaMode, only if not already set
if (!node["antennaMode"] && pxx["antennaMode"]) {
pxx["antennaMode"] >> rhs.antennaMode;
}
} else if (mod["sbus"]) {
mod["sbus"]["refreshRate"] >> rhs.ppm.frameLength;
} else if (mod["pxx2"]) {
+1 -1
View File
@@ -138,6 +138,7 @@ class ModuleData {
unsigned int channelsStart;
int channelsCount;
unsigned int failsafeMode;
int antennaMode; // false = internal antenna, true = external antenna
struct PPM {
int delay;
@@ -191,7 +192,6 @@ class ModuleData {
unsigned int power; // 0 10 mW, 1 100 mW, 2 500 mW, 3 1W
bool receiverTelemetryOff; // false = receiver telem enabled
bool receiverHigherChannels; // false = pwm out 1-8, true 9-16
int antennaMode; // false = internal antenna, true = external antenna
} pxx;
struct GHOST {
@@ -495,6 +495,13 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, EU + FLEX);
/* HelloRadioSky V12 board */
firmware = new OpenTxFirmware(FIRMWAREID("v12"), Firmware::tr("HelloRadioSky V12"), BOARD_HELLORADIOSKY_V12);
addOpenTxCommonOptions(firmware);
addOpenTxFontOptions(firmware);
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
/* HelloRadioSky V14 board */
firmware = new OpenTxFirmware(FIRMWAREID("v14"), Firmware::tr("HelloRadioSky V14"), BOARD_HELLORADIOSKY_V14);
addOpenTxCommonOptions(firmware);
+5 -6
View File
@@ -279,7 +279,7 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
antennaMode->setField(generalSettings.antennaMode, this);
params->append(antennaMode);
if (!(m_internalModule == MODULE_TYPE_XJT_PXX1 && HAS_EXTERNAL_ANTENNA(board))) {
if (!((m_internalModule == MODULE_TYPE_XJT_PXX1 || Boards::getCapability(board, Board::HasHardwareAntennaSwitch)) && Boards::getCapability(board, Board::HasExternalAntenna))) {
antennaLabel->setVisible(false);
antennaMode->setVisible(false);
}
@@ -418,11 +418,10 @@ void HardwarePanel::on_internalModuleChanged()
internalModuleBaudRate->setVisible(false);
}
if (m_internalModule == MODULE_TYPE_XJT_PXX1 && HAS_EXTERNAL_ANTENNA(board)) {
antennaLabel->setVisible(true);
antennaMode->setVisible(true);
}
else {
if ((m_internalModule == MODULE_TYPE_XJT_PXX1 || Boards::getCapability(board, Board::HasHardwareAntennaSwitch)) && Boards::getCapability(board, Board::HasExternalAntenna)) {
antennaLabel->setVisible(true);
antennaMode->setVisible(true);
} else {
antennaLabel->setVisible(false);
antennaMode->setVisible(false);
}
+8 -4
View File
@@ -331,7 +331,7 @@ void ModulePanel::update()
if (isInternalModule(moduleIdx) &&
(protocol==PULSES_PXX_XJT_X16 ||
protocol==PULSES_PXX_XJT_D8 || protocol==PULSES_PXX_XJT_LR12) &&
HAS_EXTERNAL_ANTENNA(board) && generalSettings.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL)
Boards::getCapability(board, Board::HasExternalAntenna) && generalSettings.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL)
mask |= MASK_ANTENNA;
if (protocol == PULSES_ACCESS_ISRM && module.channelsCount == 8)
mask |= MASK_RF_RACING_MODE;
@@ -353,6 +353,10 @@ void ModulePanel::update()
mask |= MASK_CSRF_ARMING_TRIGGER;
ui->crsfArmingTrigger->setCurrentIndex(ui->crsfArmingTrigger->findData(RawSwitch(module.crsf.crsfArmingTrigger).toValue()));
}
if (isInternalModule(moduleIdx) &&
Boards::getCapability(board, Board::HasHardwareAntennaSwitch) &&
generalSettings.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL)
mask |= MASK_ANTENNA;
break;
case PULSES_GHOST:
mask |= MASK_CHANNELS_RANGE | MASK_GHOST | MASK_BAUDRATE;
@@ -467,9 +471,9 @@ void ModulePanel::update()
ui->ppmFrameLength->setValue(22.5 + ((double)module.ppm.frameLength) * 0.5);
if (mask & MASK_ANTENNA) {
if (module.pxx.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL)
module.pxx.antennaMode = GeneralSettings::ANTENNA_MODE_INTERNAL;
ui->antennaMode->setField(module.pxx.antennaMode, this);
if (module.antennaMode == GeneralSettings::ANTENNA_MODE_PER_MODEL)
module.antennaMode = GeneralSettings::ANTENNA_MODE_INTERNAL;
ui->antennaMode->setField(module.antennaMode, this);
ui->antennaLabel->show();
ui->antennaMode->show();
}
+1
View File
@@ -16,6 +16,7 @@
["FrSky X9D Plus 2019", "x9dp2019-"],
["FrSky X9E", "x9e-"],
["FrSky X9E Hall", "x9e-hall-"],
["HelloRadioSky V12", "v12-"],
["HelloRadioSky V14", "v14-"],
["HelloRadioSky V14LCD", "v14lcd-"],
["HelloRadioSky V16", "v16-"],
+3 -1
View File
@@ -1,7 +1,7 @@
include(CMakeForceCompiler)
include(Bitmaps)
set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S PL18 T15PRO ST16 PA01 TX15 TX16SMK3 T22)
set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S PL18 T15PRO ST16 PA01 TX15 TX16SMK3 T22 V12)
set(RADIO_LANGUAGES CN CZ DA DE EN ES FI FR HE HU IT JP KO NL PL PT RU SE SK TW UA)
set(TTS_LANGUAGES CN CZ DA DE EN ES FI FR HE HU IT JP KO NL PL PT RU SE SK TW UA)
@@ -99,6 +99,8 @@ elseif(PCB STREQUAL ST16)
include(targets/c14/CMakeLists.txt)
elseif(PCB STREQUAL PA01)
include(targets/pa01/CMakeLists.txt)
elseif(PCB STREQUAL V12)
include(targets/v12/CMakeLists.txt)
elseif(PCB STREQUAL TX15)
include(targets/tx15/CMakeLists.txt)
elseif(PCB STREQUAL TX16SMK3)
@@ -58,6 +58,16 @@ static const stm32_i2c_hw_def_t _i2c2 = {
};
#endif
#if defined(I2C_B4)
static const stm32_i2c_hw_def_t _i2c4 = {
.I2Cx = I2C_B4,
.SCL_GPIO = (gpio_t)I2C_B4_SCL_GPIO,
.SDA_GPIO = (gpio_t)I2C_B4_SDA_GPIO,
.GPIO_AF = I2C_B4_GPIO_AF,
.set_pwr = nullptr,
};
#endif
int i2c_init(etx_i2c_bus_t bus)
{
#if defined(I2C_B1)
@@ -72,6 +82,12 @@ int i2c_init(etx_i2c_bus_t bus)
}
#endif
#if defined(I2C_B4)
if (bus == I2C_Bus_4) {
return stm32_i2c_init(I2C_Bus_4, I2C_B4_CLK_RATE, &_i2c4);
}
#endif
return -1;
}
@@ -89,6 +105,12 @@ int i2c_deinit(etx_i2c_bus_t bus)
}
#endif
#if defined(I2C_B4)
if (bus == I2C_Bus_4) {
return stm32_i2c_deinit(I2C_Bus_4);
}
#endif
return -1;
}
+4 -1
View File
@@ -48,7 +48,10 @@
static uint8_t _last_adc_state = 0;
static volatile uint8_t _six_pos_state = 0;
void sixPosUpdateFromAdc()
// Called whenever the sticky 6POS position changes. Boards that need to
// map position to a switch-expander state (e.g. FUNCTION_SWITCHES) can
// override this to react to position changes without polling adcValues[].
__attribute__((weak)) void sixPosUpdateFromAdc()
{
uint16_t* values = getAnalogValues();
uint16_t adcValue = values[SIXPOS_SWITCH_INDEX];
@@ -0,0 +1,94 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "hal/gpio.h"
#include "stm32_gpio.h"
#include "stm32_timer.h"
#include "stm32_pulse_driver.h"
#include "edgetx_types.h"
#include "board.h"
#include "globals.h"
static const stm32_pulse_timer_t _bl_timer = {
.GPIO = (gpio_t)BACKLIGHT_GPIO,
.GPIO_Alternate = BACKLIGHT_GPIO_AF,
.TIMx = BACKLIGHT_TIMER,
.TIM_Freq = BACKLIGHT_TIMER_FREQ,
.TIM_Channel = BACKLIGHT_TIMER_CHANNEL,
.TIM_IRQn = (IRQn_Type)-1,
.DMAx = nullptr,
.DMA_Stream = 0,
.DMA_Channel = 0,
.DMA_IRQn = (IRQn_Type)-1,
.DMA_TC_CallbackPtr = nullptr,
};
void backlightLowInit()
{
gpio_init(BACKLIGHT_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_clear(BACKLIGHT_GPIO);
}
void backlightInit()
{
stm32_pulse_init(&_bl_timer, 10000);
stm32_pulse_config_output(&_bl_timer, true, LL_TIM_OCMODE_PWM1, 100);
LL_TIM_SetAutoReload(_bl_timer.TIMx, 100);
LL_TIM_EnableCounter(_bl_timer.TIMx);
}
uint8_t lastDutyCycle = 0;
void backlightEnable(uint8_t dutyCycle)
{
stm32_pulse_set_cmp_val(&_bl_timer, dutyCycle);
// TODO: removed until QSPI & LCD SPI are split
// if(!dutyCycle) {
// //experimental to turn off LCD when no backlight
// // if(lcdOffFunction) lcdOffFunction();
// }
// else if(!lastDutyCycle) {
// // if(lcdOnFunction) lcdOnFunction();
// // else lcdInit();
// }
// lastDutyCycle = dutyCycle;
}
void lcdOff() {
backlightEnable(0);
}
void lcdOn(){
// if(lcdOnFunction) lcdOnFunction();
// else lcdInit();
backlightEnable(BACKLIGHT_LEVEL_MAX);
}
bool boardBacklightOn;
bool isBacklightEnabled()
{
return boardBacklightOn;
}
+419
View File
@@ -0,0 +1,419 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "stm32_adc.h"
#include "stm32_gpio.h"
#include "stm32_i2c_driver.h"
#include "stm32_hal.h"
#include "stm32_spi.h"
#include "flash_driver.h"
#include "extflash_driver.h"
#include "board.h"
#include "boards/generic_stm32/module_ports.h"
#include "boards/generic_stm32/rgb_leds.h"
#include "stm32_switch_driver.h"
#include "hal/adc_driver.h"
#include "hal/flash_driver.h"
#include "hal/trainer_driver.h"
#include "hal/rotary_encoder.h"
#include "hal/switch_driver.h"
#include "hal/abnormal_reboot.h"
#include "hal/watchdog_driver.h"
#include "hal/usb_driver.h"
#include "hal/gpio.h"
#include "globals.h"
#include "sdcard.h"
#include "debug.h"
#include "keys.h"
#include "flysky_gimbal_driver.h"
#include "timers_driver.h"
#include "bitmapbuffer.h"
#include "colors.h"
// #include "touch_driver.h"
#include <string.h>
// common ADC driver
extern const etx_hal_adc_driver_t _adc_driver;
#if defined(SIXPOS_SWITCH_INDEX)
#if defined(FUNCTION_SWITCHES)
extern const stm32_switch_t* boardGetSwitchDef(uint8_t idx);
extern SwitchHwPos stm32_switch_get_position(const stm32_switch_t* sw);
extern uint8_t isSwitch3Pos(uint8_t idx);
struct _adckey_switches_expander {
uint8_t state;
};
// Bitmask of all 6 function switch bits
#define FS_ALL_BITS 0x3F
// For each 6POS position (0=none, 1-6=SW1-SW6): bit of the active switch,
// inverted so active switch pin reads low (DOWN) like real PCA95xx hardware.
// position 0 (none): all bits set = all UP
// position N: all bits set except SW_N's bit = SW_N is DOWN
static uint8_t _pos_to_state(uint8_t pos)
{
if (pos == 0) return FS_ALL_BITS;
uint8_t active_bit = (1 << (pos - 1));
return FS_ALL_BITS & ~active_bit;
}
static _adckey_switches_expander _adckey_switches = { FS_ALL_BITS };
// Called whenever the sticky 6POS position changes. Boards that need to
// map position to a switch-expander state (e.g. FUNCTION_SWITCHES) can
// override this to react to position changes without polling adcValues[].
void sixPosUpdateFromAdc()
{
uint16_t* values = getAnalogValues();
uint16_t adcValue = values[SIXPOS_SWITCH_INDEX];
uint8_t current = 0;
if (adcValue > 3800) current = 1;
else if (adcValue > 3100) current = 2;
else if (adcValue > 2300) current = 3;
else if (adcValue > 1500) current = 4;
else if (adcValue > 1000) current = 5;
else if (adcValue > 400) current = 6;
static uint8_t lastSeen = 0;
static uint8_t debounce = 0;
static uint8_t sixPosState = 0;
if (current != lastSeen) {
lastSeen = current;
debounce = 2; // require this many more stable samples before committing
} else if (debounce > 0) {
if (--debounce == 0) {
// Switch state always reflects the true debounced position
_adckey_switches.state = _pos_to_state(current);
if (current != 0) {
// Indicator value stays sticky on the last active position
sixPosState = current;
}
}
}
values[SIXPOS_SWITCH_INDEX] = sixPosState ? (4096 / 5) * (7 - sixPosState) : 0;
}
static SwitchHwPos _get_switch_pos(uint8_t idx)
{
SwitchHwPos pos = SWITCH_HW_UP;
const stm32_switch_t* def = boardGetSwitchDef(idx);
uint8_t state = _adckey_switches.state;
if (def->isCustomSwitch) {
if ((state & def->Pin_high) == 0) {
return SWITCH_HW_DOWN;
} else {
return SWITCH_HW_UP;
}
}
else if (!def->Pin_low) {
// 2POS switch
if ((state & def->Pin_high) != 0) {
pos = SWITCH_HW_DOWN;
}
} else {
bool hi = state & def->Pin_high;
bool lo = state & def->Pin_low;
if(!isSwitch3Pos(idx))
{
// Switch not declared as 3POS installed in a 3POS HW
if (!(hi && lo)) {
pos = SWITCH_HW_DOWN;
}
} else if (hi && lo) {
pos = SWITCH_HW_MID;
} else if (!hi && lo) {
pos = SWITCH_HW_DOWN;
}
}
return pos;
}
static SwitchHwPos _get_fs_switch_pos(uint8_t idx)
{
const stm32_switch_t* def = boardGetSwitchDef(idx);
uint8_t state = _adckey_switches.state;
if ((state & def->Pin_high) == 0) {
return SWITCH_HW_DOWN;
} else {
return SWITCH_HW_UP;
}
}
bool boardIsCustomSwitch(uint8_t idx);
SwitchHwPos boardSwitchGetPosition(uint8_t idx)
{
if (boardIsCustomSwitch(idx)) {
return _get_fs_switch_pos(idx);
} else if (boardGetSwitchDef(idx)->GPIOx_high != nullptr) {
return stm32_switch_get_position(boardGetSwitchDef(idx));
} else {
return _get_switch_pos(idx);
}
}
#endif
#endif
static void led_strip_off()
{
rgbLedClearAll();
rgbLedColorApply();
}
void INTERNAL_MODULE_ON()
{
gpio_set(INTMODULE_PWR_GPIO);
}
void INTERNAL_MODULE_OFF()
{
gpio_clear(INTMODULE_PWR_GPIO);
}
void EXTERNAL_MODULE_ON()
{
gpio_set(EXTMODULE_PWR_GPIO);
}
void EXTERNAL_MODULE_OFF()
{
gpio_clear(EXTMODULE_PWR_GPIO);
}
void INTMODULE_ANTSEL_EXT()
{
gpio_set(INTMODULE_ANTSEL_GPIO);
}
void INTMODULE_ANTSEL_INT()
{
gpio_clear(INTMODULE_ANTSEL_GPIO);
}
void boardBLEarlyInit()
{
timersInit();
usbChargerInit();
}
void boardBLPreJump()
{
ExtFLASH_Init();
SDRAM_Init();
// Stop 1ms timer
MS_TIMER->CR1 &= ~TIM_CR1_CEN;
}
void boardBLInit()
{
ExtFLASH_Init();
SDRAM_Init();
// register external FLASH for DFU
usbRegisterDFUMedia((void*)extflash_dfu_media);
// register internal & external FLASH for UF2
flashRegisterDriver(FLASH_BANK1_BASE, BOOTLOADER_SIZE, &stm32_flash_driver);
flashRegisterDriver(QSPI_BASE, 8 * 1024 * 1024, &extflash_driver);
}
void USBCharger(uint32_t usbchgstatus)
{
// USB Charger init code can be added here if needed
static uint32_t usbchgmode=0;
if(usbchgstatus>10){
rgbLedClearAll();
rgbLedColorApply();
return;
}
switch (++usbchgmode) {
case 1:
rgbSetLedColor(0, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE);
break;
case 2:
rgbSetLedColor(1, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE);
break;
case 3:
rgbSetLedColor(2, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE);
break;
case 4:
rgbSetLedColor(3, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE);
break;
case 5:
rgbSetLedColor(4, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE);
break;
case 6:
rgbSetLedColor(5, SIXPOS_LED_RED, SIXPOS_LED_GREEN, SIXPOS_LED_BLUE);
break;
case 7:
usbchgmode=0;
rgbLedClearAll();
break;
default:
break;
}
rgbLedColorApply();
}
void boardInit()
{
// enable interrupts
__enable_irq();
ledInit();
boardInitModulePorts();
pwrInit();
delaysInit();
timersInit();
usbChargerInit();
gpio_set(LED_BLUE_GPIO);
ExtFLASH_InitRuntime();
// register internal & external FLASH for UF2
flashRegisterDriver(FLASH_BANK1_BASE, BOOTLOADER_SIZE, &stm32_flash_driver);
flashRegisterDriver(QSPI_BASE, QSPI_FLASH_SIZE, &extflash_driver);
usbInit();
rgbLedInit();
led_strip_off();
#if !defined(DEBUG_SEGGER_RTT)
static uint32_t usbchgstatus=0;
// This is needed to prevent radio from starting when usb is plugged to charge
if (usbPlugged()) {
while (usbPlugged() && !pwrPressed()) {//charging loop
delay_ms(500);
USBCharger(usbchgstatus);
if (IS_UCHARGER_ACTIVE()) {
/* code */
ledRed();
usbchgstatus=0;
}
else{
ledGreen();
usbchgstatus++;
}
}
if (!pwrPressed()) {
pwrOff();
// Wait power to drain
while (true) {
}
}
}
#endif
rgbLedInit();
led_strip_off();
keysInit();
switchInit();
rotaryEncoderInit();
// touchPanelInit();
audioInit();
adcInit(&_adc_driver);
hapticInit();
rtcInit(); // RTC must be initialized before rambackupRestore() is called
}
extern void rtcDisableBackupReg();
void boardOff()
{
lcdOff();
while (pwrPressed()) {
WDG_RESET();
}
SysTick->CTRL = 0; // turn off systick
// Shutdown the Haptic
hapticDone();
rtcDisableBackupReg();
#if !defined(BOOT)
rgbLedClearAll();
while (pwrPressed()) {
WDG_RESET();
}
if (IS_UCHARGER_ACTIVE()||usbPlugged())
{
while (pwrPressed()) {
WDG_RESET();
}
// RTC->BKP0R = SOFTRESET_REQUEST;
NVIC_SystemReset();
}
#endif
// RTC->BKP0R = SHUTDOWN_REQUEST;
pwrOff();
// We reach here only in forced power situations, such as hw-debugging with external power
// Enter STM32 stop mode / deep-sleep
// Code snippet from ST Nucleo PWR_EnterStopMode example
#define PDMode 0x00000000U
#if defined(PWR_CR1_MRUDS) && defined(PWR_CR1_LPUDS) && defined(PWR_CR1_FPDS)
MODIFY_REG(PWR->CR1, (PWR_CR1_PDDS | PWR_CR1_LPDS | PWR_CR1_FPDS | PWR_CR1_LPUDS | PWR_CR1_MRUDS), PDMode);
#elif defined(PWR_CR_MRLVDS) && defined(PWR_CR_LPLVDS) && defined(PWR_CR_FPDS)
MODIFY_REG(PWR->CR1, (PWR_CR1_PDDS | PWR_CR1_LPDS | PWR_CR1_FPDS | PWR_CR1_LPLVDS | PWR_CR1_MRLVDS), PDMode);
#else
// MODIFY_REG(PWR->CR1, (PWR_CR1_P_PDDS| PWR_CR1_LPDS), PDMode);
#endif /* PWR_CR_MRUDS && PWR_CR_LPUDS && PWR_CR_FPDS */
/* Set SLEEPDEEP bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
// To avoid HardFault at return address, end in an endless loop
while (1) {
}
}
+272
View File
@@ -0,0 +1,272 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
#include "definitions.h"
#include "edgetx_constants.h"
#include "board_common.h"
#include "hal.h"
#include "hal/serial_port.h"
#include "hal/watchdog_driver.h"
#define FLASHSIZE 0x800000
#define FLASH_PAGESIZE 256
#define BOOTLOADER_SIZE 0x10000
#define BOOTLOADER_ADDRESS 0x08000000
#define FIRMWARE_ADDRESS 0x90000000
#define FIRMWARE_LEN(fsize) (fsize)
#define FIRMWARE_MAX_LEN FLASHSIZE
#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS)
#define BOOTLOADER_KEYS 0x42
#define MB *1024*1024
#define LUA_MEM_EXTRA_MAX (2 MB) // max allowed memory usage for Lua bitmaps (in bytes)
#define LUA_MEM_MAX (6 MB) // max allowed memory usage for complete Lua (in bytes), 0 means unlimited
extern uint16_t sessionTimer;
#define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
// Board driver
void boardInit();
void boardOff();
// CPU Unique ID
#define LEN_CPU_UID (3*8+2)
void getCPUUniqueID(char * s);
// Flash Write driver
#define FLASH_PAGESIZE 256
void unlockFlash();
void lockFlash();
void flashWrite(uint32_t * address, const uint32_t * buffer);
uint32_t isFirmwareStart(const uint8_t * buffer);
uint32_t isBootloaderStart(const uint8_t * buffer);
// SDRAM driver
extern "C" void SDRAM_Init();
// Pulses driver
#if !defined(SIMU)
void INTMODULE_ANTSEL_EXT();
void INTMODULE_ANTSEL_INT();
void INTERNAL_MODULE_ON();
void INTERNAL_MODULE_OFF();
void EXTERNAL_MODULE_ON();
void EXTERNAL_MODULE_OFF();
#define EXTERNAL_MODULE_PWR_OFF EXTERNAL_MODULE_OFF
#define BLUETOOTH_MODULE_ON() gpio_clear(BLUETOOTH_ON_GPIO)
#define BLUETOOTH_MODULE_OFF() gpio_set(BLUETOOTH_ON_GPIO)
#define IS_INTERNAL_MODULE_ON() (gpio_read(INTMODULE_PWR_GPIO) ? 1 : 0)
#define IS_EXTERNAL_MODULE_ON() (gpio_read(EXTMODULE_PWR_GPIO) ? 1 : 0)
#else
#define INTERNAL_MODULE_OFF()
#define INTERNAL_MODULE_ON()
#define EXTERNAL_MODULE_ON()
#define EXTERNAL_MODULE_OFF()
#define BLUETOOTH_MODULE_ON()
#define BLUETOOTH_MODULE_OFF()
#define IS_INTERNAL_MODULE_ON() (false)
#define IS_EXTERNAL_MODULE_ON() (false)
#endif // defined(SIMU)
#if defined(FUNCTION_SWITCHES)
#define NUM_FUNCTIONS_SWITCHES 6
#define NUM_FUNCTIONS_GROUPS 3
#define DEFAULT_FS_CONFIG \
(SWITCH_2POS << 10) + (SWITCH_2POS << 8) + (SWITCH_2POS << 6) + \
(SWITCH_2POS << 4) + (SWITCH_2POS << 2) + (SWITCH_2POS << 0)
#define DEFAULT_FS_GROUPS \
(1 << 10) + (1 << 8) + (1 << 6) + (1 << 4) + (1 << 2) + \
(1 << 0) // Set all FS to group 1 to act like a 6pos
#define DEFAULT_FS_STARTUP_CONFIG \
((FS_START_PREVIOUS << 10) + (FS_START_PREVIOUS << 8) + \
(FS_START_PREVIOUS << 6) + (FS_START_PREVIOUS << 4) + \
(FS_START_PREVIOUS << 2) + \
(FS_START_PREVIOUS << 0)) // keep last state by default
#else
#define NUM_FUNCTIONS_SWITCHES 0
#endif
#define NUM_TRIMS 8
#define DEFAULT_STICK_DEADZONE 2
#define BATTERY_WARN 74 // 7.4V
#define BATTERY_MIN 70 // 6.8V
#define BATTERY_MAX 86 // 8.6V
// --- MOSFET ---- R1 --- MCU
// |__ R2 --- GND
//
#define VBAT_DIV_R1 100 // kOhms
#define VBAT_DIV_R2 56 // kOhms
#define VBAT_MOSFET_DROP 10 // * 10mV
// #define BATTERY_DIVIDER 1211 // = 2047 * 165k / (165k + 680k) * 10 / 3.3V
#if defined(__cplusplus) && !defined(SIMU)
extern "C" {
#endif
// Power driver
#define SOFT_PWR_CTRL
#define POWER_ON_DELAY 10 // 1s
void pwrInit();
void extModuleInit();
uint32_t pwrCheck();
uint32_t lowPowerCheck();
void pwrOn();
void pwrSoftReboot();
void pwrOff();
void pwrResetHandler();
bool pwrPressed();
bool pwrOffPressed();
#if defined(PWR_EXTRA_SWITCH_GPIO)
bool pwrForcePressed();
#else
#define pwrForcePressed() false
#endif
uint32_t pwrPressedDuration();;
const etx_serial_port_t* auxSerialGetPort(int port_nr);
#define AUX_SERIAL_POWER_ON()
#define AUX_SERIAL_POWER_OFF()
// LED driver
void ledInit();
void ledOff();
void ledRed();
void ledBlue();
void ledGreen();
// LCD driver
void lcdSetInitalFrameBuffer(void* fbAddress);
void lcdInit();
void lcdCopy(void * dest, void * src);
void lcdOff();
void lcdOn();
#define lcdRefreshWait(...)
// Backlight driver
#define BACKLIGHT_LEVEL_MAX 100
#define BACKLIGHT_FORCED_ON BACKLIGHT_LEVEL_MAX + 1
#define BACKLIGHT_LEVEL_MIN 1
extern bool boardBacklightOn;
void backlightLowInit( void );
void backlightInit();
void backlightEnable(uint8_t dutyCycle);
void backlightFullOn();
bool isBacklightEnabled();
#define BACKLIGHT_ENABLE() \
{ \
boardBacklightOn = true; \
backlightEnable(BACKLIGHT_LEVEL_MAX - currentBacklightBright); \
}
#define BACKLIGHT_DISABLE() \
{ \
boardBacklightOn = false; \
backlightEnable(((g_eeGeneral.blOffBright == BACKLIGHT_LEVEL_MIN) && \
(g_eeGeneral.backlightMode != e_backlight_mode_off)) \
? 0 \
: g_eeGeneral.blOffBright); \
}
#if defined(__cplusplus) && !defined(SIMU)
}
#endif
#define IS_UCHARGER_ACTIVE() !gpio_read(UCHARGER_GPIO) ? 1 : 0
#define IS_UCHARGER_CHARGE_END_ACTIVE() gpio_read(UCHARGER_CHARGE_END_GPIO) ? 0 : 1
#define ENABLE_UCHARGER() bsp_output_set(BSP_CHARGE_EN);
#define DISABLE_UCHARGER() bsp_output_clear(BSP_CHARGE_EN)
// Audio driver
class stm32_spi_t;
struct AudioConfig_t
{
stm32_spi_t* spi;
void (*setMuteHigh)();
void (*setMuteLow)();
void (*setResetHigh)();
void (*setResetLow)();
};
void audioInit();
void audioConsumeCurrentBuffer();
#define audioDisableIrq() // interrupts must stay enabled on Horus
#define audioEnableIrq() // interrupts must stay enabled on Horus
#define setSampleRate(freq)
void setScaledVolume(uint8_t volume);
void setVolume(uint8_t volume);
int32_t getVolume();
#define VOLUME_LEVEL_MAX 23
#define VOLUME_LEVEL_DEF 12
// Telemetry driver
#define INTMODULE_FIFO_SIZE 512
#define TELEMETRY_FIFO_SIZE 512
// Haptic driver
void hapticInit();
void hapticDone();
void hapticOff();
void hapticOn(uint32_t pwmPercent);
// Second serial port driver
//#define AUX_SERIAL
#define DEBUG_BAUDRATE 115200
#define LUA_DEFAULT_BAUDRATE 115200
extern uint8_t currentTrainerMode;
void checkTrainerSettings();
// Touch panel driver
bool touchPanelEventOccured();
struct TouchState touchPanelRead();
struct TouchState getInternalTouchState();
// USB Charger
#if defined(USB_CHARGER)
void usbChargerInit();
bool usbChargerLed();
#endif
#endif // _BOARD_H_
@@ -0,0 +1,154 @@
#include "extflash_driver.h"
#include "stm32_hal.h"
#include "stm32_qspi.h"
#include "board.h"
#define QSPI_NOR_PAGE_SIZE 256
int32_t ExtFLASH_Init()
{
if (stm32_qspi_nor_init() != 0) {
return -1;
}
return stm32_qspi_nor_memory_mapped();
}
void ExtFLASH_InitRuntime() { stm32_qspi_no_init_runtime(); }
//
// ETX HAL flash interface
//
static uint32_t extflash_get_size_kb()
{
return QSPI_FLASH_SIZE / 1024;
}
static uint32_t extflash_get_sector(uint32_t address)
{
address -= QSPI_BASE;
return address / (64 * 1024);
}
static uint32_t extflash_get_sector_size(uint32_t sector)
{
(void)sector;
return (64 * 1024);
}
static int extflash_erase_sector(uint32_t address)
{
address -= QSPI_BASE;
return stm32_qspi_nor_erase_sector(address);
}
static int extflash_program(uint32_t address, void* data, uint32_t len)
{
address -= QSPI_BASE;
int ret = 0;
while (len > 0) {
uint32_t size = (len > QSPI_NOR_PAGE_SIZE) ? QSPI_NOR_PAGE_SIZE : len;
ret = stm32_qspi_nor_program(address, data, size);
if (ret != 0) break;
len -= size;
address += size;
data = (uint8_t*)data + size;
}
return ret;
}
static int extflash_read(uint32_t address, void* data, uint32_t len)
{
address -= QSPI_BASE;
return stm32_qspi_nor_read(address, data, len);
}
const etx_flash_driver_t extflash_driver = {
.get_size_kb = extflash_get_size_kb,
.get_sector = extflash_get_sector,
.get_sector_size = extflash_get_sector_size,
.erase_sector = extflash_erase_sector,
.program = extflash_program,
.read = extflash_read,
};
#if defined(BOOT)
//
// USB DFU interface
//
#include "usbd_dfu.h"
#define MEDIA_DESC_STR "@External Flash /0x90000000/128*064Kg"
static uint16_t extflash_dfu_init()
{
return USBD_OK;
}
static uint16_t extflash_dfu_deinit()
{
return USBD_OK;
}
static uint16_t extflash_dfu_erase(uint32_t address)
{
if (extflash_erase_sector(address) < 0) {
return USBD_FAIL;
}
return USBD_OK;
}
static uint16_t extflash_dfu_write(uint8_t* src, uint8_t* dest, uint32_t len)
{
if (extflash_program((intptr_t)dest, (void*)src, len) < 0) {
return USBD_FAIL;
}
return USBD_OK;
}
static uint8_t* extflash_dfu_read(uint8_t* src, uint8_t* dest, uint32_t len)
{
if (extflash_read((intptr_t)src, (void*)dest, len) < 0) {
return nullptr;
}
return dest;
}
static uint16_t extflash_dfu_get_status(uint32_t address, uint8_t cmd, uint8_t *buffer)
{
switch (cmd) {
case DFU_MEDIA_PROGRAM:
buffer[1] = 1;
buffer[2] = 0;
buffer[3] = 0;
break;
case DFU_MEDIA_ERASE:
default:
buffer[1] = 20;
buffer[2] = 0;
buffer[3] = 0;
break;
}
return USBD_OK;
}
const USBD_DFU_MediaTypeDef _extflash_dfu_media = {
.pStrDesc = (uint8_t*)MEDIA_DESC_STR,
.Init = extflash_dfu_init,
.DeInit = extflash_dfu_deinit,
.Erase = extflash_dfu_erase,
.Write = extflash_dfu_write,
.Read = extflash_dfu_read,
.GetStatus = extflash_dfu_get_status,
};
const void* extflash_dfu_media = &_extflash_dfu_media;
#endif // BOOT
@@ -0,0 +1,27 @@
/*
* Copyright (C) EdgeTX
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "hal/flash_driver.h"
extern const etx_flash_driver_t extflash_driver;
extern const void* extflash_dfu_media;
// init external FLASH hardware
int32_t ExtFLASH_Init();
// init only runtime structures
void ExtFLASH_InitRuntime();
@@ -0,0 +1,60 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "hal/gpio.h"
#include "stm32_gpio.h"
#include "stm32_timer.h"
#include "stm32_pulse_driver.h"
#include "board.h"
#define HAPTIC_TIMER_FREQ 200000000
static const stm32_pulse_timer_t _haptic_timer = {
.GPIO = (gpio_t)HAPTIC_GPIO,
.GPIO_Alternate = HAPTIC_GPIO_AF,
.TIMx = HAPTIC_GPIO_TIMER,
.TIM_Freq = HAPTIC_TIMER_FREQ,
.TIM_Channel = LL_TIM_CHANNEL_CH2,
.TIM_IRQn = (IRQn_Type)-1,
.DMAx = nullptr,
.DMA_Stream = 0,
.DMA_Channel = 0,
.DMA_IRQn = (IRQn_Type)-1,
.DMA_TC_CallbackPtr = nullptr,
};
void hapticInit(void)
{
stm32_pulse_init(&_haptic_timer, 10000);
stm32_pulse_config_output(&_haptic_timer, true, LL_TIM_OCMODE_PWM1, 0);
LL_TIM_SetAutoReload(_haptic_timer.TIMx, 100);
LL_TIM_EnableCounter(_haptic_timer.TIMx);
}
void hapticOn(uint32_t pwmPercent)
{
if (pwmPercent > 100) pwmPercent = 100;
stm32_pulse_set_cmp_val(&_haptic_timer, pwmPercent);
}
void hapticOff(void) { hapticOn(0); }
void hapticDone(void) { hapticOff(); }
@@ -0,0 +1,33 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "hal/key_driver.h"
#include "stm32_hal_ll.h"
#include "stm32_gpio_driver.h"
#include "stm32_i2c_driver.h"
#include "hal.h"
#include "delays_driver.h"
#include "keys.h"
#include "stm32_keys.inc"
#include "debug.h"
@@ -0,0 +1,423 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "lcd_driver.h"
#include "stm32_gpio.h"
#include "stm32_spi.h"
#include "delays_driver.h"
#include "hal/gpio.h"
#include "lcd.h"
#include "hal.h"
#include "board.h"
#define LCD_NRST_HIGH() gpio_set(LCD_NRST)
#define LCD_NRST_LOW() gpio_clear(LCD_NRST)
#define LCD_COMMAND_MODE() gpio_clear(LCD_SPI_RS)
#define LCD_DATA_MODE() gpio_set(LCD_SPI_RS)
#define CASET 0x2A
#define RASET 0x2B
#define RAMWR 0x2C
static const stm32_spi_t lcdSpi = {
.SPIx = LCD_SPI,
.SCK = LCD_SPI_CLK,
.MISO = LCD_SPI_MISO,
.MOSI = LCD_SPI_MOSI,
.CS = LCD_SPI_CS,
.DMA = LCD_SPI_DMA,
.txDMA_PeriphRequest = LCD_SPI_TX_DMA,
.rxDMA_PeriphRequest = LCD_SPI_RX_DMA,
.txDMA_Stream = LCD_SPI_TX_DMA_STREAM,
.rxDMA_Stream = LCD_SPI_RX_DMA_STREAM,
};
static void* initialFrameBuffer = nullptr;
static void write_start_end(uint8_t cmd, uint16_t start, uint16_t end)
{
// big endian format
uint8_t buf[4] = {
(uint8_t)(start >> 8),
(uint8_t)(start & 0xFF),
(uint8_t)(end >> 8),
(uint8_t)(end & 0xFF),
};
stm32_spi_select(&lcdSpi);
LCD_COMMAND_MODE();
stm32_spi_transfer_byte(&lcdSpi, cmd);
LCD_DATA_MODE();
stm32_spi_transfer_bytes(&lcdSpi, (uint8_t *)buf, nullptr, sizeof(buf));
stm32_spi_unselect(&lcdSpi);
}
static inline void set_column_addr(uint16_t xs, uint16_t xe)
{
write_start_end(CASET, xs, xe);
}
static inline void set_row_addr(uint16_t ys, uint16_t ye)
{
write_start_end(RASET, ys, ye);
}
static void memory_write(const uint16_t* data, uint32_t length)
{
stm32_spi_select(&lcdSpi);
LCD_COMMAND_MODE();
stm32_spi_transfer_byte(&lcdSpi, RAMWR);
LCD_DATA_MODE();
stm32_spi_set_data_width(&lcdSpi, LL_SPI_DATAWIDTH_16BIT);
SCB_CleanDCache_by_Addr((void *)data, length * sizeof(uint16_t));
stm32_spi_dma_transmit_words(&lcdSpi, data, length);
stm32_spi_unselect(&lcdSpi);
stm32_spi_set_data_width(&lcdSpi, LL_SPI_DATAWIDTH_8BIT);
}
static void startLcdRefresh(lv_disp_drv_t *disp_drv, uint16_t *buffer,
const rect_t &copy_area)
{
(void)disp_drv;
// TODO: replace through some smarter mechanism without busy wait
while (!gpio_read(LCD_FMARK));
coord_t x1 = copy_area.x;
coord_t x2 = x1 + copy_area.w - 1;
set_column_addr(x1, x2);
coord_t y1 = copy_area.y;
coord_t y2 = y1 + copy_area.h - 1;
set_row_addr(y1, y2);
memory_write(buffer, copy_area.w * copy_area.h);
lcdFlushed();
}
lcdSpiInitFucPtr lcdInitFunction;
lcdSpiInitFucPtr lcdOffFunction;
lcdSpiInitFucPtr lcdOnFunction;
uint32_t lcdPixelClock;
static void lcdSpiConfig(void)
{
stm32_spi_init(&lcdSpi, LL_SPI_DATAWIDTH_8BIT);
stm32_spi_set_max_baudrate(&lcdSpi, LCD_SPI_BAUD);
gpio_init(LCD_FMARK, GPIO_IN, GPIO_PIN_SPEED_HIGH);
gpio_init(LCD_NRST, GPIO_OUT, GPIO_PIN_SPEED_HIGH);
gpio_init(LCD_SPI_RS, GPIO_OUT, GPIO_PIN_SPEED_HIGH);
}
void lcdDelay() {
delay_01us(1);
}
static void lcdReset() {
LCD_NRST_HIGH();
delay_ms(1);
LCD_NRST_LOW(); // RESET();
delay_ms(100);
LCD_NRST_HIGH();
delay_ms(120);
}
static void lcdWriteCommand(uint8_t cmd)
{
LCD_COMMAND_MODE();
stm32_spi_select(&lcdSpi);
stm32_spi_transfer_byte(&lcdSpi, cmd);
stm32_spi_unselect(&lcdSpi);
}
// static void lcdWriteReg(uint8_t reg, uint8_t data)
// {
// LCD_COMMAND_MODE();
// stm32_spi_select(&lcdSpi);
// stm32_spi_transfer_byte(&lcdSpi, reg);
// LCD_DATA_MODE();
// stm32_spi_transfer_byte(&lcdSpi, data);
// stm32_spi_unselect(&lcdSpi);
// }
static void lcdWriteData(uint8_t data)
{
LCD_DATA_MODE();
stm32_spi_select(&lcdSpi);
stm32_spi_transfer_byte(&lcdSpi, data);
stm32_spi_unselect(&lcdSpi);
}
// static uint8_t lcdReadReg(uint8_t reg)
// {
// uint8_t data = 0;
// LCD_COMMAND_MODE();
// stm32_spi_select(&lcdSpi);
// stm32_spi_transfer_byte(&lcdSpi, reg);
// LCD_DATA_MODE();
// data = stm32_spi_transfer_byte(&lcdSpi, 0xFF);
// stm32_spi_unselect(&lcdSpi);
// return data;
// }
extern "C" void lcdSetInitalFrameBuffer(void *fbAddress)
{
initialFrameBuffer = fbAddress;
}
static void lcdSetOn(void) { lcdWriteCommand(0x29); }
static void lcdSetOff(void) { lcdWriteCommand(0x28); }
extern "C" void lcdInit()
{
// Configure the LCD SPI + RESET pins
lcdSpiConfig();
stm32_spi_unselect(&lcdSpi);
// hard reset
lcdReset();
// Init command start
lcdWriteCommand( 0xFE );
lcdWriteCommand( 0xEF );
// Display orientation
lcdWriteCommand( 0x36 );
lcdWriteData( 0x60 );
// Color mode
lcdWriteCommand( 0x3A );
lcdWriteData( 0x05 ); // 16-bit color
// Display control
lcdWriteCommand( 0x86 );
lcdWriteData( 0x98 );
lcdWriteCommand( 0x89 );
lcdWriteData( 0x33 );
lcdWriteCommand( 0x8B );
lcdWriteData( 0x80 );
lcdWriteCommand( 0x8D );
lcdWriteData( 0x33 );
lcdWriteCommand( 0x3A );
lcdWriteData( 0x05 );
lcdWriteCommand( 0x8E );
lcdWriteData( 0x0F );
lcdWriteCommand( 0xEC );
lcdWriteData( 0x33 );
lcdWriteData( 0x07 );
lcdWriteData( 0x00 );
lcdWriteCommand( 0xED );
lcdWriteData( 0x18 );
lcdWriteData( 0x08 );
lcdWriteCommand( 0xE8 );
lcdWriteData( 0x12 );
lcdWriteData( 0x00 );
// Init command ends
lcdWriteCommand( 0xFF );
lcdWriteCommand( 0x62 );
// Display control
lcdWriteCommand( 0x99 );
lcdWriteData( 0x3E );
lcdWriteCommand( 0x9D );
lcdWriteData( 0x4B );
lcdWriteCommand( 0x98 );
lcdWriteData( 0x3E );
lcdWriteCommand( 0x9C );
lcdWriteData( 0x4B );
lcdWriteCommand( 0xC3 );
lcdWriteData( 0x39 );
lcdWriteCommand( 0xC4 );
lcdWriteData( 0x29 );
lcdWriteCommand( 0xC9 );
lcdWriteData( 0x09 );
// Gamma Control
lcdWriteCommand( 0xF0 );
lcdWriteData( 0x0B );
lcdWriteData( 0x0C );
lcdWriteData( 0x07 );
lcdWriteData( 0x07 );
lcdWriteData( 0x05 );
lcdWriteData( 0x22 );
lcdWriteCommand( 0xF1);
lcdWriteData( 0x42 );
lcdWriteData( 0x78 );
lcdWriteData( 0x56 );
lcdWriteData( 0x1E );
lcdWriteData( 0x1A );
lcdWriteData( 0x95 );
lcdWriteCommand( 0xF2 );
lcdWriteData( 0x0B );
lcdWriteData( 0x0C );
lcdWriteData( 0x07 );
lcdWriteData( 0x07 );
lcdWriteData( 0x05 );
lcdWriteData( 0x44 );
lcdWriteCommand( 0xF3 );
lcdWriteData( 0x56 );
lcdWriteData( 0x92 );
lcdWriteData( 0x30 );
lcdWriteData( 0x31 );
lcdWriteData( 0x35 );
lcdWriteData( 0x7F );
// Display orientation
lcdWriteCommand( 0x36 );
//lcdWriteData( 0xA0 );
lcdWriteData( 0x60 );
// Display size
lcdWriteCommand( 0x2A );
lcdWriteData( 0x00 );
lcdWriteData( 0x00 );
lcdWriteData( 0x01 );
lcdWriteData( 0x40 );
lcdWriteCommand( 0x2B );
lcdWriteData( 0x00 );
lcdWriteData( 0x00 );
lcdWriteData( 0x00 );
lcdWriteData( 0xF0 );
// Invert color
lcdWriteCommand( 0x21 );
// Tear on
lcdWriteCommand( 0x35 );
// Exit sleep
lcdWriteCommand( 0x11 );
/*
lcdWriteCommand(0x11);
delay_ms(120);
lcdWriteCommand(0xB2);
lcdWriteData(0x0C);
lcdWriteData(0x0C);
lcdWriteData(0x00);
lcdWriteData(0x33);
lcdWriteData(0x33);
lcdWriteCommand(0x35);
lcdWriteData(0x00);
lcdWriteCommand(0x36);
lcdWriteData(0x60);
lcdWriteCommand(0x3A);
lcdWriteData(0x05);
lcdWriteCommand(0xB7);
lcdWriteData(0x35);
lcdWriteCommand(0xBB);
lcdWriteData(0x34);
lcdWriteCommand(0xC0);
lcdWriteData(0x2C);
lcdWriteCommand(0xC2);
lcdWriteData( 0x01);
lcdWriteCommand(0xC3);
lcdWriteData(0x13);//4.5V
lcdWriteCommand(0xC4);
lcdWriteData(0x20);
lcdWriteCommand(0xC6);
lcdWriteData(0x0F);
lcdWriteCommand(0xD0);
lcdWriteData(0xA4);
lcdWriteData(0xA1);
lcdWriteCommand(0xD6);
lcdWriteData(0xA1);
lcdWriteCommand(0xE0);
lcdWriteData(0xD0);
lcdWriteData(0x0A);
lcdWriteData(0x10);
lcdWriteData(0x0C);
lcdWriteData(0x0C);
lcdWriteData(0x18);
lcdWriteData(0x35);
lcdWriteData(0x43);
lcdWriteData(0x4D);
lcdWriteData(0x39);
lcdWriteData(0x13);
lcdWriteData(0x13);
lcdWriteData(0x2D);
lcdWriteData(0x34);
lcdWriteCommand(0xE1);
lcdWriteData(0xD0);
lcdWriteData(0x05);
lcdWriteData(0x0B);
lcdWriteData(0x06);
lcdWriteData(0x05);
lcdWriteData(0x02);
lcdWriteData(0x35);
lcdWriteData(0x43);
lcdWriteData(0x4D);
lcdWriteData(0x16);
lcdWriteData(0x15);
lcdWriteData(0x15);
lcdWriteData(0x2E);
lcdWriteData(0x32);
lcdWriteCommand(0x21);
lcdWriteCommand(0x29);
lcdWriteCommand(0x2C); */
lcdSetOn();
// Init LCD RAM
memory_write((const uint16_t*)initialFrameBuffer, LCD_W * LCD_H);
lcdOnFunction = lcdSetOn;
lcdOffFunction = lcdSetOff;
lcdSetFlushCb(startLcdRefresh);
}
@@ -0,0 +1,77 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __LCD_DRIVER_H__
#define __LCD_DRIVER_H__
#define HBP ( 24 ) // TODO use names from FlySky
#define VBP ( 10 )
#define HSW ( 4 )
#define VSH ( 2 )
#define HFP ( 140 - HBP )
#define VFP ( 22 - VBP )
#define LCD_ST7796S_ID ( 0x7796 )
#define LCD_ILI9481_ID ( 0x9481 )
#define LCD_ILI9486_ID ( 0x9486 )
#define LCD_ILI9488_ID ( 0x9488 )
#define LCD_HX8357D_ID ( 0x99 )
#define LCD_DELAY() LCD_Delay()
typedef void (*lcdSpiInitFucPtr)(void);
typedef unsigned int LcdReadIDFucPtr( void );
extern lcdSpiInitFucPtr lcdInitFunction;
extern lcdSpiInitFucPtr lcdOffFunction;
extern lcdSpiInitFucPtr lcdOnFunction;
#define SET_IO_INPUT( PORT, PIN ) LL_GPIO_SetPinMode( PORT, PIN, LL_GPIO_MODE_INPUT )
#define SET_IO_OUTPUT( PORT, PIN ) LL_GPIO_SetPinMode( PORT, PIN, LL_GPIO_MODE_OUTPUT )
//#define LCD_NRST_HIGH() LL_GPIO_SetOutputPin(LCD_NRST_GPIO, LCD_NRST_GPIO_PIN)
//#define LCD_NRST_LOW() LL_GPIO_ResetOutputPin(LCD_NRST_GPIO, LCD_NRST_GPIO_PIN)
//#define LCD_CS_HIGH() LL_GPIO_SetOutputPin(LCD_SPI_CS_GPIO, LCD_SPI_CS_GPIO_PIN)
//#define LCD_CS_LOW() LL_GPIO_ResetOutputPin(LCD_SPI_CS_GPIO, LCD_SPI_CS_GPIO_PIN)
#define LCD_SCK_HIGH() LL_GPIO_SetOutputPin(LCD_SPI_GPIO, LCD_SPI_SCK_GPIO_PIN)
#define LCD_SCK_LOW() LL_GPIO_ResetOutputPin(LCD_SPI_GPIO, LCD_SPI_SCK_GPIO_PIN)
#define LCD_MOSI_HIGH() LL_GPIO_SetOutputPin(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN)
#define LCD_MOSI_LOW() LL_GPIO_ResetOutputPin(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN)
#define LCD_MOSI_AS_INPUT() SET_IO_INPUT( LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN )
#define LCD_MOSI_AS_OUTPUT() SET_IO_OUTPUT( LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN )
#define LCD_READ_DATA_PIN() LL_GPIO_IsInputPinSet(LCD_SPI_GPIO, LCD_SPI_MOSI_GPIO_PIN)
#define HORIZONTAL_SYNC_WIDTH ( 4 )
#define HORIZONTAL_BACK_PORCH ( 24 )
#define HORIZONTAL_FRONT_PORCH ( 140 - HORIZONTAL_BACK_PORCH )
#define VERTICAL_SYNC_HEIGHT ( 2 )
#define VERTICAL_BACK_PORCH ( 10 )
#define VERTICAL_FRONT_PORCH ( 22 - VERTICAL_BACK_PORCH )
#endif
@@ -0,0 +1,252 @@
/*
* 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 "hal/gpio.h"
#include "stm32_gpio.h"
#include "stm32_hal_ll.h"
#include "board.h"
#define SDRAM_MEMORY_WIDTH FMC_SDRAM_MEM_BUS_WIDTH_16
#define SDRAM_CAS_LATENCY FMC_SDRAM_CAS_LATENCY_3
#define SDCLOCK_PERIOD FMC_SDRAM_CLOCK_PERIOD_2
#define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
#define SDRAM_READBURST FMC_SDRAM_RBURST_DISABLE
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_FULL_PAGE ((uint16_t)0x0007)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_1 ((uint16_t)0x0010)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
#define GPIO_AF_FMC GPIO_AF12
extern "C" void SDRAM_GPIOConfig(void)
{
/*-- GPIOs Configuration -----------------------------------------------------*/
/*
*/
/* GPIOD configuration */
gpio_init_af(GPIO_PIN(GPIOD, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOD, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOD, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOD, 9), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOD, 10), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOD, 14), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOD, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
/* GPIOE configuration */
gpio_init_af(GPIO_PIN(GPIOE, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOE, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//BL1
gpio_init_af(GPIO_PIN(GPIOE, 7), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOE, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOE, 9), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOE, 10), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOE, 11), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOE, 12), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOE, 13), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOE, 14), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOE, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
/* GPIOF configuration */
gpio_init_af(GPIO_PIN(GPIOF, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOF, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOF, 2), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOF, 3), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOF, 4), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOF, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOF, 11), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//RAS
gpio_init_af(GPIO_PIN(GPIOF, 12), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//
gpio_init_af(GPIO_PIN(GPIOF, 13), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOF, 14), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOF, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
/* GPIOG configuration */
gpio_init_af(GPIO_PIN(GPIOG, 0), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOG, 1), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(GPIO_PIN(GPIOG, 4), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//BA0
gpio_init_af(GPIO_PIN(GPIOG, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//BA1
gpio_init_af(GPIO_PIN(GPIOG, 8), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//CLK
gpio_init_af(GPIO_PIN(GPIOG, 15), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//NCAS
gpio_init_af(GPIO_PIN(GPIOH, 2), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//CLKE0 PH2
gpio_init_af(GPIO_PIN(GPIOH, 3), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//NE0 PH3
gpio_init_af(GPIO_PIN(GPIOH, 5), GPIO_AF_FMC, GPIO_PIN_SPEED_VERY_HIGH);//NWE PH5 V14P OK
}
extern "C" void SDRAM_InitSequence(void)
{
FMC_SDRAM_CommandTypeDef FMC_SDRAMCommandStructure;
uint32_t tmpr = 0;
uint32_t timeout = SDRAM_TIMEOUT;
/* Step 3 --------------------------------------------------------------------*/
/* Configure a clock configuration enable command */
FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
FMC_SDRAMCommandStructure.AutoRefreshNumber = 1;
FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
// while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) &&
// (timeout > 0))
// {
// timeout--;
// }
/* Send the command */
FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10);
/* Step 4 --------------------------------------------------------------------*/
/* Insert 1 ms delay */
delay_ms(100);
/* Step 5 --------------------------------------------------------------------*/
/* Configure a PALL (precharge all) command */
FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_PALL;
FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
FMC_SDRAMCommandStructure.AutoRefreshNumber = 1;
FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
// timeout = SDRAM_TIMEOUT;
// while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) && (timeout > 0))
// {
// timeout--;
// }
/* Send the command */
FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10);
// delay_ms(1);
/* Step 6 --------------------------------------------------------------------*/
/* Configure a Auto-Refresh command */
FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
FMC_SDRAMCommandStructure.AutoRefreshNumber = 8;
FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
// timeout = SDRAM_TIMEOUT;
// while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) &&
// (timeout > 0))
// {
// timeout--;
// }
/* Send the command */
FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10);
// delay_ms(1);
/* Step 7 --------------------------------------------------------------------*/
/* Program the external memory mode register */
tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
/* Configure a load Mode register command*/
FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
FMC_SDRAMCommandStructure.AutoRefreshNumber = 1;
FMC_SDRAMCommandStructure.ModeRegisterDefinition = tmpr;
/* Wait until the SDRAM controller is ready */
// timeout = SDRAM_TIMEOUT;
// while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) && (timeout > 0))
// {
// timeout--;
// }
/* Send the command */
FMC_SDRAM_SendCommand(FMC_Bank5_6_R, &FMC_SDRAMCommandStructure, 10);
// delay_ms(1);
/* Step 8 --------------------------------------------------------------------*/
/* Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter */
FMC_SDRAM_SetAutoRefreshNumber(FMC_Bank5_6_R, 15);
FMC_SDRAM_ProgramRefreshRate(FMC_Bank5_6_R, 1855);
/* Wait until the SDRAM controller is ready */
// timeout = SDRAM_TIMEOUT;
// while((__FMC_SDRAM_GET_FLAG(FMC_Bank5_6_R, FMC_SDRAM_FLAG_BUSY) != 0) && (timeout > 0))
// {
// timeout--;
// }
// delay_ms(1);
}
extern "C" void SDRAM_Init(void)
{
//delay funcion needed
delaysInit();
/* GPIO configuration for FMC SDRAM bank */
SDRAM_GPIOConfig();
/* Enable FMC clock */
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_FMC);
/* FMC Configuration ---------------------------------------------------------*/
FMC_SDRAM_InitTypeDef FMC_SDRAMInitStructure;
FMC_SDRAM_TimingTypeDef FMC_SDRAMTimingInitStructure;
/* FMC SDRAM Bank configuration */
/* Timing configuration for 80 Mhz of SD clock */
FMC_SDRAMTimingInitStructure.LoadToActiveDelay = 2;
FMC_SDRAMTimingInitStructure.ExitSelfRefreshDelay = 7;
FMC_SDRAMTimingInitStructure.SelfRefreshTime = 4;
FMC_SDRAMTimingInitStructure.RowCycleDelay = 7;
FMC_SDRAMTimingInitStructure.WriteRecoveryTime = 3;
FMC_SDRAMTimingInitStructure.RPDelay = 2;
FMC_SDRAMTimingInitStructure.RCDDelay = 2;
/* FMC SDRAM control configuration */
FMC_SDRAMInitStructure.SDBank = FMC_SDRAM_BANK1;
FMC_SDRAMInitStructure.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
FMC_SDRAMInitStructure.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
FMC_SDRAMInitStructure.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
FMC_SDRAMInitStructure.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
FMC_SDRAMInitStructure.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
FMC_SDRAMInitStructure.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
FMC_SDRAMInitStructure.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
FMC_SDRAMInitStructure.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
FMC_SDRAMInitStructure.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
/* FMC SDRAM bank initialization */
FMC_SDRAM_Init(FMC_Bank5_6_R, &FMC_SDRAMInitStructure);
FMC_SDRAM_Timing_Init(FMC_Bank5_6_R, &FMC_SDRAMTimingInitStructure, FMC_SDRAM_BANK1);
__FMC_ENABLE();
/* FMC SDRAM device initialization sequence */
SDRAM_InitSequence();
}
@@ -0,0 +1,116 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "stm32h7xx_ll_pwr.h"
#include "stm32h7xx_ll_rcc.h"
#include "stm32h7xx_ll_system.h"
#include "stm32h7xx_ll_bus.h"
#define BOOTSTRAP __attribute__((section(".bootstrap")))
BOOTSTRAP void SystemClock_Config(void)
{
/* Power Configuration */
LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
while (LL_PWR_IsActiveFlag_VOS() == 0){
}
/* Enable HSE oscillator */
LL_RCC_HSE_Enable();
while (LL_RCC_HSE_IsReady() != 1) {
}
/* Set FLASH latency */
LL_FLASH_SetLatency(LL_FLASH_LATENCY_5);
/* Main PLL configuration and activation */
LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE);
LL_RCC_PLL1P_Enable();
LL_RCC_PLL1Q_Enable();
LL_RCC_PLL1R_Enable();
LL_RCC_PLL1FRACN_Disable();
LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4);
LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
LL_RCC_PLL1_SetM(1);
LL_RCC_PLL1_SetN(100);
LL_RCC_PLL1_SetP(2);
LL_RCC_PLL1_SetQ(4);
LL_RCC_PLL1_SetR(2);
LL_RCC_PLL1_Enable();
while (LL_RCC_PLL1_IsReady() != 1) {
}
/* Set Sys & AHB & APB1 & APB2 & APB4 prescaler */
LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
/* Set PLL1 as System Clock Source */
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) {
}
/* Config & activate PLL2 */
LL_RCC_PLL2P_Enable();
LL_RCC_PLL2Q_Enable();
LL_RCC_PLL2R_Enable();
LL_RCC_PLL2FRACN_Disable();
LL_RCC_PLL2_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4);
LL_RCC_PLL2_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
LL_RCC_PLL2_SetM(1);
LL_RCC_PLL2_SetN(120);
LL_RCC_PLL2_SetP(12);
LL_RCC_PLL2_SetQ(2);
LL_RCC_PLL2_SetR(4);
LL_RCC_PLL2_Enable();
while (LL_RCC_PLL2_IsReady() != 1) {
}
/* Config & activate PLL3 */
LL_RCC_PLL3P_Enable();
LL_RCC_PLL3Q_Enable();
LL_RCC_PLL3R_Enable();
LL_RCC_PLL3FRACN_Disable();
LL_RCC_PLL3_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4);
LL_RCC_PLL3_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
LL_RCC_PLL3_SetM(1);
LL_RCC_PLL3_SetN(120);
LL_RCC_PLL3_SetP(5);
LL_RCC_PLL3_SetQ(20);
LL_RCC_PLL3_SetR(80);
LL_RCC_PLL3_Enable();
while (LL_RCC_PLL3_IsReady() != 1) {
}
/* Enable SRAM1, SRAM2 & SRAM3 */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_D2SRAM1 |
LL_AHB2_GRP1_PERIPH_D2SRAM2 |
LL_AHB2_GRP1_PERIPH_D2SRAM3);
/* Set periph clock sources */
LL_RCC_SetFMCClockSource(LL_RCC_FMC_CLKSOURCE_HCLK);
LL_RCC_SetSPIClockSource(LL_RCC_SPI123_CLKSOURCE_PLL3P);
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL3Q);
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_CLKP);
}
@@ -0,0 +1,23 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
void SystemClock_Config();
@@ -0,0 +1,291 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "touch_driver.h"
#include "stm32_hal.h"
#include "stm32_hal_ll.h"
#include "stm32_exti_driver.h"
#include "stm32_gpio.h"
#include "stm32_gpio_driver.h"
#include "stm32_i2c_driver.h"
#include "timers_driver.h"
#include "debug.h"
#include "delays_driver.h"
#include "hal.h"
#include "hal/gpio.h"
#include "hal/i2c_driver.h"
#include "rtos.h"
volatile static bool touchEventOccured;
#define TOUCH_CST836U_I2C_ADDRESS (0x15)
static tc_handle_TypeDef tc_handle = {0, 0};
tmr10ms_t downTime = 0;
tmr10ms_t tapTime = 0;
short tapCount = 0;
#define TAP_TIME 250 // ms
static TouchState internalTouchState = {};
static void _cst836u_exti_isr(void) {
touchEventOccured = true;
}
static void TouchAFExtiConfig(void)
{
TRACE("TOUCH_AF_EXTI_CONFIG");
gpio_init_int(TOUCH_INT_GPIO, GPIO_IN_PU, GPIO_FALLING, _cst836u_exti_isr);
}
void initTouchI2C(void)
{
TRACE("CST836U I2C Init");
if (i2c_init(TOUCH_I2C_BUS) < 0) {
TRACE("CST836U ERROR: i2c_init failed");
return;
}
}
#define I2C_TIMEOUT_MAX 5 // 5 ms
bool touch_i2c_read(uint8_t addr, uint8_t reg, uint8_t* data, uint8_t len)
{
if (stm32_i2c_master_tx(TOUCH_I2C_BUS, addr, &reg, 1, 3) < 0) return false;
delay_us(5);
if (stm32_i2c_master_rx(TOUCH_I2C_BUS, addr, data, len, I2C_TIMEOUT_MAX) < 0)
return false;
return true;
}
static uint8_t TS_IO_Read(uint8_t addr, uint8_t reg)
{
uint8_t result;
uint8_t tryCount = 3;
while (!touch_i2c_read(addr, reg, &result, 1)) {
if (--tryCount == 0) break;
initTouchI2C();
}
return result;
}
static uint16_t TS_IO_ReadMultiple(uint8_t addr, uint8_t reg, uint8_t* buffer,
uint16_t length)
{
uint8_t tryCount = 3;
while (!touch_i2c_read(addr, reg, buffer, length)) {
if (--tryCount == 0) break;
initTouchI2C();
}
return 1;
}
static void touch_cst836u_debug_info(void)
{
#if defined(DEBUG)
TRACE("cst836u: fw ver 0x%02X %02X",
TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_FW_VERSION_H_REG),
TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_FW_VERSION_L_REG));
TRACE("cst836u: module version 0x%02X",
TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_MODULE_VERSION_REG));
TRACE("cst836u: project name 0x%02X",
TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_PROJECT_NAME_REG));
TRACE("cst836u: chip type 0x%02X 0x%02X",
TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_CHIP_TYPE_H_REG),
TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_CHIP_TYPE_L_REG));
#endif
}
/**
* @brief Get the touch screen X and Y positions values
* Manage multi touch thanks to touch Index global
* variable 'tc_handle.currActiveTouchIdx'.
* @param DeviceAddr: Device address on communication Bus.
* @param X: Pointer to X position value
* @param Y: Pointer to Y position value
* @retval None.
*/
static void cst836u_TS_GetXY(uint16_t* X, uint16_t* Y, uint32_t* event)
{
uint8_t regAddress = 0;
uint8_t dataxy[4];
if (tc_handle.currActiveTouchIdx < tc_handle.currActiveTouchNb) {
switch (tc_handle.currActiveTouchIdx) {
case 0:
regAddress = CST836U_TOUCH1_XH_REG;
break;
case 1:
regAddress = CST836U_TOUCH2_XH_REG;
break;
default:
break;
}
/* Read X and Y positions */
TS_IO_ReadMultiple(TOUCH_CST836U_I2C_ADDRESS, regAddress, dataxy,
sizeof(dataxy));
/* Send back ready X position to caller */
*X = ((dataxy[0] & CST836U_MSB_MASK) << 8) | dataxy[1];
/* Send back ready Y position to caller */
*Y = ((dataxy[2] & CST836U_MSB_MASK) << 8) | dataxy[3];
*event = (dataxy[0] & CST836U_TOUCH_EVT_FLAG_MASK) >>
CST836U_TOUCH_EVT_FLAG_SHIFT;
/*
uint32_t weight;
uint32_t area;
*/
tc_handle.currActiveTouchIdx++;
}
}
/**
* @brief Return if there is touches detected or not.
* Try to detect new touches and forget the old ones (reset internal
* global variables).
* @param DeviceAddr: Device address on communication Bus.
* @retval : Number of active touches detected (can be 0, 1 or 2).
*/
static uint8_t cst836u_TS_DetectTouch()
{
volatile uint8_t nbTouch = 0;
/* Read register CST836U_TOUCH_NUM_REG to check number of touches detection */
nbTouch = TS_IO_Read(TOUCH_CST836U_I2C_ADDRESS, CST836U_TOUCH_NUM_REG);
if (nbTouch > CST836U_MAX_DETECTABLE_TOUCH) {
/* If invalid number of touch detected, set it to zero */
nbTouch = 0;
}
tc_handle.currActiveTouchNb = nbTouch;
tc_handle.currActiveTouchIdx = 0;
return (nbTouch);
}
void TouchReset()
{
gpio_clear(TOUCH_RST_GPIO);
delay_ms(10);
gpio_set(TOUCH_RST_GPIO);
delay_ms(300);
}
void touchPanelInit(void)
{
gpio_init(TOUCH_RST_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
initTouchI2C();
TouchReset();
TouchAFExtiConfig();
touch_cst836u_debug_info();
}
void handleTouch()
{
unsigned short touchX;
unsigned short touchY;
uint32_t tEvent = 0;
cst836u_TS_GetXY(&touchX, &touchY, &tEvent);
if (tEvent == CST836U_TOUCH_EVT_FLAG_CONTACT) {
int dx = touchX - internalTouchState.x;
int dy = touchY - internalTouchState.y;
internalTouchState.x = touchX;
internalTouchState.y = touchY;
if (internalTouchState.event == TE_NONE ||
internalTouchState.event == TE_UP ||
internalTouchState.event == TE_SLIDE_END) {
internalTouchState.startX = internalTouchState.x;
internalTouchState.startY = internalTouchState.y;
internalTouchState.event = TE_DOWN;
} else if (internalTouchState.event == TE_DOWN) {
if (dx >= SLIDE_RANGE || dx <= -SLIDE_RANGE || dy >= SLIDE_RANGE ||
dy <= -SLIDE_RANGE) {
internalTouchState.event = TE_SLIDE;
internalTouchState.deltaX = (short)dx;
internalTouchState.deltaY = (short)dy;
} else {
internalTouchState.event = TE_DOWN;
internalTouchState.deltaX = 0;
internalTouchState.deltaY = 0;
}
} else if (internalTouchState.event == TE_SLIDE) {
internalTouchState.event = TE_SLIDE; // no change
internalTouchState.deltaX = (short)dx;
internalTouchState.deltaY = (short)dy;
}
}
}
bool touchPanelEventOccured() { return touchEventOccured; }
TouchState touchPanelRead()
{
if (!touchEventOccured) return internalTouchState;
touchEventOccured = false;
tmr10ms_t now = timersGetMsTick();
internalTouchState.tapCount = 0;
if (cst836u_TS_DetectTouch()) {
handleTouch();
if (internalTouchState.event == TE_DOWN && downTime == 0) {
downTime = now;
}
} else {
if (internalTouchState.event == TE_DOWN) {
internalTouchState.event = TE_UP;
if (now - downTime <= TAP_TIME) {
if (now - tapTime > TAP_TIME) {
tapCount = 1;
} else {
tapCount++;
}
internalTouchState.tapCount = tapCount;
tapTime = now;
} else {
internalTouchState.tapCount = 0; // not a tap
}
downTime = 0;
} else {
tapCount = 0;
internalTouchState.tapCount = 0;
internalTouchState.event = TE_SLIDE_END;
}
}
TouchState ret = internalTouchState;
internalTouchState.deltaX = 0;
internalTouchState.deltaY = 0;
if (internalTouchState.event == TE_UP ||
internalTouchState.event == TE_SLIDE_END)
internalTouchState.event = TE_NONE;
return ret;
}
TouchState getInternalTouchState() { return internalTouchState; }
@@ -0,0 +1,110 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*
Copyright 2016 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <touch.h>
/* Set Multi-touch as non supported */
#ifndef TS_MULTI_TOUCH_SUPPORTED
#define TS_MULTI_TOUCH_SUPPORTED 0
#endif
/* Set Auto-calibration as non supported */
#ifndef TS_AUTO_CALIBRATION_SUPPORTED
#define TS_AUTO_CALIBRATION_SUPPORTED 0
#endif
/* Macros --------------------------------------------------------------------*/
/** @typedef ft6x06_handle_TypeDef
* ft6x06 Handle definition.
*/
typedef struct {
/* field holding the current number of simultaneous active touches */
uint8_t currActiveTouchNb;
/* field holding the touch index currently managed */
uint8_t currActiveTouchIdx;
} tc_handle_TypeDef;
/* clang-format off */
#define CST836U_WORK_MODE_REG 0x00
#define CST836U_PROXIMITY_ID_REG 0x01
#define CST836U_TOUCH_NUM_REG 0x02
#define CST836U_TOUCH1_XH_REG 0x03
#define CST836U_TOUCH1_XL_REG 0x04
#define CST836U_TOUCH1_YH_REG 0x05
#define CST836U_TOUCH1_YL_REG 0x06
#define CST836U_TOUCH2_XH_REG 0x09
#define CST836U_TOUCH2_XL_REG 0x0A
#define CST836U_TOUCH2_YH_REG 0x0B
#define CST836U_TOUCH2_YL_REG 0x0C
#define CST836U_FW_VERSION_L_REG 0xA6
#define CST836U_FW_VERSION_H_REG 0xA7
#define CST836U_MODULE_VERSION_REG 0xA8
#define CST836U_PROJECT_NAME_REG 0xA9
#define CST836U_CHIP_TYPE_L_REG 0xAA
#define CST836U_CHIP_TYPE_H_REG 0xAB
#define CST836U_CHECKSUM_L_REG 0xAC
#define CST836U_CHECKSUM_H_REG 0xAD
#define CST836U_PROX_STATE_REG 0xB0
#define CST836U_GES_STATE_REG 0xD0
#define CST836U_GES_ID_REG_REG 0xD3
#define CST836U_MAX_DETECTABLE_TOUCH 2
#define CST836U_MSB_MASK 0x0F
#define CST836U_TOUCH_EVT_FLAG_SHIFT 6
#define CST836U_TOUCH_EVT_FLAG_MASK (3 << CST836U_TOUCH_EVT_FLAG_SHIFT)
#define CST836U_TOUCH_EVT_FLAG_CONTACT 0x02
/* clang-format on */
extern void touchPanelInit(void);
extern void TouchDriver(void);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,52 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "hal/gpio.h"
#include "stm32_gpio.h"
#include "board.h"
#include "hal/usb_driver.h"
void usbChargerInit()
{
gpio_init(UCHARGER_GPIO, GPIO_IN_PU, GPIO_PIN_SPEED_LOW);
#if defined(UCHARGER_PW)
gpio_init(UCHARGER_PW, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_set(UCHARGER_PW);
//gpio_clear(UCHARGER_PW); 0=DISABLE 1=ENABLE
#endif
#if defined(UCHARGER_EN)
gpio_init(UCHARGER_EN, GPIO_OUT, GPIO_PIN_SPEED_LOW);
//gpio_set(UCHARGER_EN);
gpio_clear(UCHARGER_EN); //cherge EN 0=ENANLE 1=DISABLE
#endif
#if defined(USB_GPIO_SEL)
gpio_init(USB_GPIO_SEL, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_set(USB_GPIO_SEL);
//gpio_clear(USB_GPIO_SEL); // USB HUB SELECT 0->H7 MCU 1->CHARGE MCU
#endif
}
bool usbChargerLed()
{
return (!gpio_read(UCHARGER_GPIO) && usbPlugged());
}
+203 -168
View File
@@ -5,21 +5,21 @@
"name": "MAIN",
"adc": "ADC1",
"dma": "DMA2",
"dma_channel": "LL_DMA_CHANNEL_0",
"dma_channel": "LL_DMAMUX1_REQ_ADC1",
"dma_stream": "LL_DMA_STREAM_4",
"dma_stream_irq": "DMA2_Stream4_IRQn",
"dma_stream_irq_handler": "DMA2_Stream4_IRQHandler",
"sample_time": "LL_ADC_SAMPLINGTIME_28CYCLES"
"sample_time": "LL_ADC_SAMPLINGTIME_8CYCLES_5"
},
{
"name": "EXT",
"adc": "ADC3",
"dma": "DMA2",
"dma_channel": "LL_DMA_CHANNEL_2",
"dma_channel": "LL_DMAMUX1_REQ_ADC3",
"dma_stream": "LL_DMA_STREAM_0",
"dma_stream_irq": "DMA2_Stream0_IRQn",
"dma_stream_irq_handler": "DMA2_Stream0_IRQHandler",
"sample_time": "LL_ADC_SAMPLINGTIME_56CYCLES"
"sample_time": "LL_ADC_SAMPLINGTIME_8CYCLES_5"
}
],
"inputs": [
@@ -29,7 +29,7 @@
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_2",
"channel": "LL_ADC_CHANNEL_2"
"channel": "LL_ADC_CHANNEL_14"
},
{
"name": "LV",
@@ -37,8 +37,7 @@
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_3",
"channel": "LL_ADC_CHANNEL_3",
"inverted": true
"channel": "LL_ADC_CHANNEL_15"
},
{
"name": "RV",
@@ -46,7 +45,8 @@
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_0",
"channel": "LL_ADC_CHANNEL_0"
"channel": "LL_ADC_CHANNEL_17",
"inverted": true
},
{
"name": "RH",
@@ -54,17 +54,16 @@
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_1",
"channel": "LL_ADC_CHANNEL_1",
"channel": "LL_ADC_CHANNEL_16",
"inverted": true
},
{
"name": "P1",
"type": "FLEX",
"adc": "MAIN",
"gpio": "GPIOB",
"pin": "LL_GPIO_PIN_0",
"channel": "LL_ADC_CHANNEL_8",
"inverted": true,
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_1",
"channel": "LL_ADC_CHANNEL_11",
"label": "S1",
"short_label": "1",
"default": "POT_CENTER"
@@ -73,64 +72,36 @@
"name": "P2",
"type": "FLEX",
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_6",
"channel": "LL_ADC_CHANNEL_6",
"inverted": true,
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_0",
"channel": "LL_ADC_CHANNEL_10",
"label": "S2",
"short_label": "2",
"default": "POT_CENTER"
},
{
"name": "P3",
"type": "FLEX",
"adc": "EXT",
"name": "RAW1",
"type": "RAW",
"adc": "MAIN",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_2",
"channel": "LL_ADC_CHANNEL_12",
"label": "S3",
"short_label": "3",
"default": "MULTIPOS"
"pin": "LL_GPIO_PIN_5",
"channel": "LL_ADC_CHANNEL_8"
},
{
"name": "VBAT",
"type": "VBAT",
"adc": "MAIN",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_3",
"channel": "LL_ADC_CHANNEL_13"
},
{
"name": "RTC_BAT",
"type": "RTC_BAT",
"adc": "MAIN",
"adc": "EXT",
"gpio": null,
"pin": null,
"channel": "LL_ADC_CHANNEL_VBAT"
},
{
"name": "SWB",
"type": "SWITCH",
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_5",
"channel": "LL_ADC_CHANNEL_5"
},
{
"name": "SWC",
"type": "SWITCH",
"adc": "MAIN",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_0",
"channel": "LL_ADC_CHANNEL_10"
},
{
"name": "SWE",
"type": "SWITCH",
"adc": "MAIN",
"gpio": "GPIOA",
"pin": "LL_GPIO_PIN_7",
"channel": "LL_ADC_CHANNEL_7"
},
{
"name": "SWF",
"type": "SWITCH",
"adc": "MAIN",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_5",
"channel": "LL_ADC_CHANNEL_15"
}
]
},
@@ -140,39 +111,33 @@
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "3POS",
"display": [
0,
0
],
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_13",
"default": "2POS",
"gpio": "GPIOH",
"pin": "LL_GPIO_PIN_8",
"is_cfs": false
},
{
"name": "SB",
"type": "ADC",
"type": "3POS",
"flags": 0,
"inverted": false,
"inverted": true,
"default": "3POS",
"display": [
0,
1
],
"adc_input": "SWB",
"gpio_high": "GPIOD",
"pin_high": "LL_GPIO_PIN_11",
"gpio_low": "GPIOH",
"pin_low": "LL_GPIO_PIN_7",
"is_cfs": false
},
{
"name": "SC",
"type": "ADC",
"type": "3POS",
"flags": 0,
"inverted": false,
"inverted": true,
"default": "3POS",
"display": [
1,
0
],
"adc_input": "SWC",
"gpio_high": "GPIOG",
"pin_high": "LL_GPIO_PIN_3",
"gpio_low": "GPIOD",
"pin_low": "LL_GPIO_PIN_4",
"is_cfs": false
},
{
@@ -180,70 +145,98 @@
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "3POS",
"display": [
1,
1
],
"gpio": "GPIOE",
"pin": "LL_GPIO_PIN_8",
"default": "TOGGLE",
"gpio": "GPIOI",
"pin": "LL_GPIO_PIN_3",
"is_cfs": false
},
{
"name": "SE",
"type": "ADC",
"name": "SW1",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "2POS",
"display": [
0,
2
],
"adc_input": "SWE",
"is_cfs": false
"gpio": null,
"pin": "PCA95XX_P0",
"is_cfs": true,
"cfs_idx": 0
},
{
"name": "SF",
"type": "ADC",
"name": "SW2",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "TOGGLE",
"display": [
1,
2
],
"adc_input": "SWF",
"is_cfs": false
"default": "2POS",
"gpio": null,
"pin": "PCA95XX_P1",
"is_cfs": true,
"cfs_idx": 1
},
{
"name": "SW3",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "2POS",
"gpio": null,
"pin": "PCA95XX_P2",
"is_cfs": true,
"cfs_idx": 2
},
{
"name": "SW4",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "2POS",
"gpio": null,
"pin": "PCA95XX_P3",
"is_cfs": true,
"cfs_idx": 3
},
{
"name": "SW5",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "2POS",
"gpio": null,
"pin": "PCA95XX_P4",
"is_cfs": true,
"cfs_idx": 4
},
{
"name": "SW6",
"type": "2POS",
"flags": 0,
"inverted": false,
"default": "2POS",
"gpio": null,
"pin": "PCA95XX_P5",
"is_cfs": true,
"cfs_idx": 5
}
],
"keys": [
{
"gpio": "GPIOE",
"pin": "LL_GPIO_PIN_1",
"active_low": true,
"key": "KEY_EXIT",
"name": "EXIT",
"label": "EXIT"
},
{
"gpio": "GPIOD",
"pin": "LL_GPIO_PIN_11",
"gpio": "GPIOI",
"pin": "LL_GPIO_PIN_8",
"active_low": true,
"key": "KEY_ENTER",
"name": "ENTER",
"label": "Enter"
},
{
"gpio": "GPIOD",
"pin": "LL_GPIO_PIN_3",
"gpio": "GPIOI",
"pin": "LL_GPIO_PIN_10",
"active_low": true,
"key": "KEY_PAGEUP",
"name": "PAGEUP",
"label": "PAGE<"
},
{
"gpio": "GPIOD",
"pin": "LL_GPIO_PIN_7",
"gpio": "GPIOI",
"pin": "LL_GPIO_PIN_11",
"active_low": true,
"key": "KEY_PAGEDN",
"name": "PAGEDN",
@@ -251,40 +244,48 @@
},
{
"gpio": "GPIOE",
"pin": "LL_GPIO_PIN_11",
"pin": "LL_GPIO_PIN_5",
"active_low": true,
"key": "KEY_MODEL",
"name": "MDL",
"label": "MDL"
},
{
"gpio": "GPIOD",
"pin": "LL_GPIO_PIN_2",
"gpio": "GPIOK",
"pin": "LL_GPIO_PIN_5",
"active_low": true,
"key": "KEY_TELE",
"name": "TELE",
"label": "TELE"
"key": "KEY_EXIT",
"name": "EXIT",
"label": "EXIT"
},
{
"gpio": "GPIOB",
"pin": "LL_GPIO_PIN_4",
"gpio": "GPIOJ",
"pin": "LL_GPIO_PIN_3",
"active_low": true,
"key": "KEY_SYS",
"name": "SYS",
"label": "SYS"
},
{
"gpio": "GPIOK",
"pin": "LL_GPIO_PIN_4",
"active_low": true,
"key": "KEY_TELE",
"name": "TELE",
"label": "TELE"
}
],
"trims": [
{
"name": "T1",
"dec": {
"gpio": "GPIOD",
"pin": "LL_GPIO_PIN_15",
"gpio": "GPIOB",
"pin": "LL_GPIO_PIN_2",
"active_low": true
},
"inc": {
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_1",
"gpio": "GPIOJ",
"pin": "LL_GPIO_PIN_4",
"active_low": true
},
"active_low": true
@@ -292,13 +293,13 @@
{
"name": "T2",
"dec": {
"gpio": "GPIOE",
"pin": "LL_GPIO_PIN_6",
"gpio": "GPIOJ",
"pin": "LL_GPIO_PIN_2",
"active_low": true
},
"inc": {
"gpio": "GPIOE",
"pin": "LL_GPIO_PIN_5",
"gpio": "GPIOI",
"pin": "LL_GPIO_PIN_15",
"active_low": true
},
"active_low": true
@@ -307,12 +308,12 @@
"name": "T3",
"dec": {
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_3",
"pin": "LL_GPIO_PIN_13",
"active_low": true
},
"inc": {
"gpio": "GPIOD",
"pin": "LL_GPIO_PIN_0",
"gpio": "GPIOC",
"pin": "LL_GPIO_PIN_2",
"active_low": true
},
"active_low": true
@@ -320,12 +321,12 @@
{
"name": "T4",
"dec": {
"gpio": "GPIOE",
"pin": "LL_GPIO_PIN_3",
"gpio": "GPIOB",
"pin": "LL_GPIO_PIN_6",
"active_low": true
},
"inc": {
"gpio": "GPIOE",
"gpio": "GPIOB",
"pin": "LL_GPIO_PIN_4",
"active_low": true
},
@@ -333,45 +334,53 @@
}
],
"display": {
"lcd_w": 128,
"lcd_h": 64,
"lcd_phys_w": 128,
"lcd_phys_h": 64,
"lcd_depth": 1,
"lcd_vertical_invert": true
"lcd_w": 320,
"lcd_h": 240,
"lcd_phys_w": 320,
"lcd_phys_h": 240,
"lcd_depth": 16
},
"backlight": {
"backlight_bdtr": "TIM_BDTR_MOE"
"backlight_gpio": "GPIO_PIN(GPIOI, 2)",
"backlight_timer": "TIM8",
"backlight_timer_channel": "LL_TIM_CHANNEL_CH4",
"backlight_gpio_af": "GPIO_AF3",
"backlight_timer_freq": "(PERI1_FREQUENCY * TIMER_MULT_APB1)"
},
"leds": {
"led_strip_length": 6,
"led_strip_length": 7,
"bling_led_strip_start": 6,
"bling_led_strip_length": 1,
"cfs_led_strip_start": 0,
"cfs_led_strip_length": 6,
"cfs_leds_per_switch": 1,
"led_strip_gpio": "GPIO_PIN(GPIOA, 10)",
"led_strip_gpio_af": "LL_GPIO_AF_1",
"led_strip_timer": "TIM1",
"led_strip_timer_freq": "(PERI2_FREQUENCY * TIMER_MULT_APB2)",
"led_strip_timer_freq": "(PERI1_FREQUENCY * TIMER_MULT_APB1)",
"led_strip_timer_channel": "LL_TIM_CHANNEL_CH3",
"led_strip_timer_dma": "DMA2",
"led_strip_timer_dma_channel": "LL_DMA_CHANNEL_6",
"led_strip_timer_dma_stream": "LL_DMA_STREAM_5",
"led_strip_timer_dma_irqn": "DMA2_Stream5_IRQn",
"led_strip_timer_dma_irqhandler": "DMA2_Stream5_IRQHandler",
"led_strip_timer_dma": "DMA1",
"led_strip_timer_dma_channel": "LL_DMAMUX1_REQ_TIM1_UP",
"led_strip_timer_dma_stream": "LL_DMA_STREAM_0",
"led_strip_timer_dma_irqn": "DMA1_Stream0_IRQn",
"led_strip_timer_dma_irqhandler": "DMA1_Stream0_IRQHandler",
"led_strip_refresh_period": 50,
"status_leds": true,
"led_red_gpio": "GPIO_PIN(GPIOE, 13)",
"led_green_gpio": "GPIO_PIN(GPIOE, 14)",
"led_blue_gpio": "GPIO_PIN(GPIOE, 2)"
"led_red_gpio": "GPIO_PIN(GPIOI, 12)",
"led_green_gpio": "GPIO_PIN(GPIOI, 13)",
"led_blue_gpio": "GPIO_PIN(GPIOI, 14)"
},
"hardware": {
"has_ext_module_support": true,
"has_int_module_support": true,
"sport_max_baudrate": 400000,
"cpu": "STM32F407xG",
"cpu_type": "STM32F4"
"cpu": "STM32H750xB",
"cpu_type": "STM32H7"
},
"timers": {
"cpu_freq": 168000000,
"peri1_frequency": 42000000,
"peri2_frequency": 84000000,
"cpu_freq": 400000000,
"peri1_frequency": 100000000,
"peri2_frequency": 100000000,
"timer_mult_apb1": 2,
"timer_mult_apb2": 2,
"ms_timer": "TIM14",
@@ -382,14 +391,40 @@
"mixer_scheduler_timer_irqn": "TIM8_BRK_TIM12_IRQn",
"mixer_scheduler_timer_irqhandler": "TIM8_BRK_TIM12_IRQHandler"
},
"rotenc": {
"rotary_encoder_gpio_a": "GPIOE",
"rotary_encoder_gpio_pin_a": "LL_GPIO_PIN_3",
"rotary_encoder_gpio_b": "GPIOE",
"rotary_encoder_gpio_pin_b": "LL_GPIO_PIN_4",
"rotary_encoder_inverted": true,
"rotary_encoder_position": "(((ROTARY_ENCODER_GPIO_A->IDR >> 3) & 0x01)|((ROTARY_ENCODER_GPIO_B->IDR >> 3) & 0x02))",
"rotary_encoder_exti_line1": "LL_EXTI_LINE_3",
"rotary_encoder_exti_line2": "LL_EXTI_LINE_4",
"exti": [
{
"irq": "EXTI3_IRQ",
"priority": 5
},
{
"irq": "EXTI4_IRQ",
"priority": 5
}
],
"rotary_encoder_exti_port_a": "LL_SYSCFG_EXTI_PORTE",
"rotary_encoder_exti_port_b": "LL_SYSCFG_EXTI_PORTE",
"rotary_encoder_exti_sys_line1": "LL_SYSCFG_EXTI_LINE3",
"rotary_encoder_exti_sys_line2": "LL_SYSCFG_EXTI_LINE4",
"rotary_encoder_timer": "TIM17",
"rotary_encoder_timer_irqn": "TIM17_IRQn",
"rotary_encoder_timer_irqhandler": "TIM17_IRQHandler"
},
"haptic": {
"haptic_pwm": true,
"haptic_gpio": "GPIO_PIN(GPIOB, 3)",
"haptic_gpio_af": "GPIO_AF1",
"haptic_timer": "TIM2",
"haptic_timer_freq": "(PERI1_FREQUENCY * TIMER_MULT_APB1)",
"haptic_counter_register": "HAPTIC_TIMER->CCR2",
"haptic_ccmr1": "TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2",
"haptic_ccer": "TIM_CCER_CC2E"
"haptic_gpio": "GPIO_PIN(GPIOE, 6)",
"haptic_gpio_timer": "TIM15",
"haptic_gpio_af": "GPIO_AF4",
"haptic_timer_output_enable": "TIM_CCER_CC2E | TIM_CCER_CC2NE",
"haptic_timer_mode": "TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE",
"haptic_timer_compare_value": "HAPTIC_GPIO_TIMER->CCR2"
}
}
+4
View File
@@ -80,6 +80,8 @@ static inline void check_struct()
CHKSIZE(RadioData, 951);
#elif defined(RADIO_ST16) || defined(PCBPA01) || defined(RADIO_TX15) || defined(RADIO_T15PRO) || defined(RADIO_TX16SMK3) || defined(RADIO_T22)
CHKSIZE(RadioData, 1183);
#elif defined(RADIO_V12)
CHKSIZE(RadioData, 1180);
#elif defined(COLORLCD)
#if defined(IMU)
CHKSIZE(RadioData, 1063);
@@ -112,6 +114,8 @@ static inline void check_struct()
#endif
#elif defined(PCBST16) || defined(RADIO_T15PRO) || defined(RADIO_TX15)
CHKSIZE(ModelData, 7641);
#elif defined(RADIO_V12)
CHKSIZE(ModelData, 7640);
#elif defined(PCBC14)
CHKSIZE(ModelData, 7573);
#elif defined(PCBPA01)
+7 -2
View File
@@ -504,7 +504,12 @@ PACK(struct ModuleData {
uint8_t channelsStart;
int8_t channelsCount CUST(r_channelsCount,w_channelsCount); // 0=8 channels
uint8_t failsafeMode:4 ENUM(FailsafeModes); // only 3 bits used
#if defined(EXTERNAL_ANTENNA)
uint8_t subType:2 SKIP;
int8_t antennaMode:2 ENUM(AntennaModes);
#else
uint8_t subType:4 SKIP;
#endif
union {
uint8_t raw[PXX2_MAX_RECEIVERS_PER_MODULE * PXX2_LEN_RX_NAME + 1];
@@ -525,8 +530,8 @@ PACK(struct ModuleData {
uint8_t spare1:2 SKIP;
uint8_t receiverTelemetryOff:1; // false = receiver telem enabled
uint8_t receiverHigherChannels:1; // false = pwm out 1-8, true 9-16
int8_t antennaMode:2;
uint8_t spare2 SKIP;
uint8_t spare2:2 SKIP;
uint8_t spare3 SKIP;
} pxx);
NOBACKUP(struct {
uint8_t spare1:6 SKIP;
+28 -7
View File
@@ -614,7 +614,7 @@ void calcBacklightValue(int16_t source)
{
getvalue_t raw = getValue(source);
#if defined(COLORLCD)
requiredBacklightBright = BACKLIGHT_LEVEL_MAX - (g_eeGeneral.blOffBright +
requiredBacklightBright = BACKLIGHT_LEVEL_MAX - (g_eeGeneral.blOffBright +
((1024 + raw) * ((BACKLIGHT_LEVEL_MAX - g_eeGeneral.backlightBright) - g_eeGeneral.blOffBright) / 2048));
#elif OLED_SCREEN
requiredBacklightBright = (raw + 1024) * 254 / 2048;
@@ -736,7 +736,7 @@ static void checkFailsafe()
void checkAll(bool isBootCheck)
{
checkSDfreeStorage();
// we don't check the throttle stick if the radio is not calibrated
if (g_eeGeneral.chkSum == evalChkSum()) {
checkThrottleStick();
@@ -803,7 +803,7 @@ void checkAll(bool isBootCheck)
}
#endif
#if defined(EXTERNAL_ANTENNA) && defined(INTERNAL_MODULE_PXX1)
#if defined(EXTERNAL_ANTENNA)
checkExternalAntenna();
#endif
@@ -1353,6 +1353,18 @@ uint32_t pwrDelayTime(int delay)
static uint8_t vals[] = { 0, 5, 10, 20, 30 };
return vals[pwrDelayFromYaml(delay)] * 10;
}
// On radios requiring a two-button chord as accidental-activation
// protection, only the chord itself should start/continue the on/off delay
// countdown; a single button held alone must not.
inline bool pwrDelayHoldActive()
{
#if defined(PWR_BUTTON_DUAL)
return pwrForcePressed();
#else
return pwrPressed();
#endif
}
#endif
#if defined(STARTUP_ANIMATION)
@@ -1370,7 +1382,7 @@ void runStartupAnimation()
tmr10ms_t duration = 0;
bool isPowerOn = false;
while (pwrPressed()) {
while (pwrDelayHoldActive()) {
duration = get_tmr10ms() - start;
if (duration < PWR_PRESS_DURATION_MIN()) {
drawStartupAnimation(duration, PWR_PRESS_DURATION_MIN());
@@ -1737,8 +1749,10 @@ inline uint32_t PWR_PRESS_SHUTDOWN_DELAY()
#if defined(PWR_BUTTON_MANAGED)
return 0;
#else
#if !defined(PWR_BUTTON_DUAL)
if (pwrForcePressed())
return 0;
#endif
return pwrDelayTime(g_eeGeneral.pwrOffSpeed);
#endif
}
@@ -1789,7 +1803,7 @@ uint32_t pwrCheck()
static uint8_t pwr_check_state = PWR_CHECK_ON;
bool inactivityShutdown = pwrOffDueToInactivity();
if (pwr_check_state == PWR_CHECK_OFF) {
return e_power_off;
}
@@ -1812,10 +1826,17 @@ uint32_t pwrCheck()
}
#endif
if (pwrPressed() || inactivityShutdown) {
if (pwrDelayHoldActive() || inactivityShutdown) {
if (!inactivityShutdown)
inactivityTimerReset(ActivitySource::Keys);
#if defined(PWR_BUTTON_DUAL_KEY1)
if (!inactivityShutdown) {
killEvents(PWR_BUTTON_DUAL_KEY1);
#if defined(PWR_BUTTON_DUAL_KEY2)
killEvents(PWR_BUTTON_DUAL_KEY2);
#endif
}
#endif
if (TELEMETRY_STREAMING()) {
message = STR_MODEL_STILL_POWERED;
}
+18 -11
View File
@@ -161,7 +161,7 @@ enum MenuModelSetupItems {
#endif
ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_MAPPING,
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA,
#endif
ITEM_MODEL_SETUP_INTERNAL_MODULE_POWER,
@@ -407,18 +407,25 @@ inline uint8_t TIMER_ROW(uint8_t timer, uint8_t value)
#define TRAINER_BLUETOOTH_S_ROW (bluetooth.distantAddr[0] == '\0' ? HIDDEN_ROW : LABEL())
#define IF_BT_TRAINER_ON(x) (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER ? (uint8_t)(x) : HIDDEN_ROW)
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#define EXTERNAL_ANTENNA_ROW ((isModuleXJT(INTERNAL_MODULE) && g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) ? (uint8_t)0 : HIDDEN_ROW),
#if defined(EXTERNAL_ANTENNA)
#if defined(INTMODULE_ANTSEL_GPIO)
#define EXTERNAL_ANTENNA_ROW ((g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) ? (uint8_t)0 : HIDDEN_ROW),
#else
#define EXTERNAL_ANTENNA_ROW ((isModuleXJT(INTERNAL_MODULE) && g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) ? (uint8_t)0 : HIDDEN_ROW),
#endif
void onModelAntennaSwitchConfirm(const char * result)
{
if (result == STR_OK) {
// Switch to external antenna confirmation
g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode = ANTENNA_MODE_EXTERNAL;
globalData.externalAntennaEnabled = true;
g_model.moduleData[INTERNAL_MODULE].antennaMode = ANTENNA_MODE_EXTERNAL;
storageDirty(EE_MODEL);
// Consent already obtained above; mark enabled so checkExternalAntenna()
// applies the GPIO instead of asking again.
globalData.externalAntennaEnabled = true;
checkExternalAntenna();
}
else {
reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode;
reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].antennaMode;
}
}
#else
@@ -885,8 +892,8 @@ void menuModelSetup(event_t event)
reusableBuffer.moduleSetup.newType = g_model.moduleData[EXTERNAL_MODULE].type;
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode;
#if defined(EXTERNAL_ANTENNA)
reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].antennaMode;
#endif
}
@@ -2187,19 +2194,19 @@ void menuModelSetup(event_t event)
}
break;
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
case ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA:
reusableBuffer.moduleSetup.antennaMode = editChoice(MODEL_SETUP_2ND_COLUMN, y, STR_ANTENNA, STR_ANTENNA_MODES,
reusableBuffer.moduleSetup.antennaMode == ANTENNA_MODE_PER_MODEL ? ANTENNA_MODE_INTERNAL : reusableBuffer.moduleSetup.antennaMode,
ANTENNA_MODE_INTERNAL, ANTENNA_MODE_EXTERNAL, attr, event, INDENT_WIDTH,
[](int value) { return value != ANTENNA_MODE_PER_MODEL; });
if (event && !s_editMode && reusableBuffer.moduleSetup.antennaMode != g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode) {
if (event && !s_editMode && reusableBuffer.moduleSetup.antennaMode != g_model.moduleData[INTERNAL_MODULE].antennaMode) {
if (reusableBuffer.moduleSetup.antennaMode == ANTENNA_MODE_EXTERNAL && !isExternalAntennaEnabled()) {
POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onModelAntennaSwitchConfirm);
SET_WARNING_INFO(STR_ANTENNACONFIRM2, strlen(STR_ANTENNACONFIRM2), 0);
}
else {
g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode = reusableBuffer.moduleSetup.antennaMode;
g_model.moduleData[INTERNAL_MODULE].antennaMode = reusableBuffer.moduleSetup.antennaMode;
checkExternalAntenna();
}
}
+2 -2
View File
@@ -76,8 +76,8 @@ static bool isAsteriskDisplayed() {
void drawExternalAntennaAndRSSI()
{
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
if (isModuleXJT(INTERNAL_MODULE) && isExternalAntennaEnabled()) {
#if defined(EXTERNAL_ANTENNA)
if (isExternalAntennaEnabled()) {
lcdDrawText(VBATT_X - 1, VBATT_Y + 8, "E", TINSIZE);
}
#endif
+2 -2
View File
@@ -162,8 +162,8 @@ if(MULTIMODULE)
add_gui_src(module/multi_rfprotos.cpp)
endif()
if(INTERNAL_MODULE_PXX1)
add_gui_src(module/pxx1_settings.cpp)
if(INTERNAL_MODULE_PXX1 OR EXTERNAL_ANTENNA)
add_gui_src(module/ext_antenna_settings.cpp)
endif()
if(PXX2)
+2 -2
View File
@@ -324,7 +324,7 @@ static const uint8_t mask_btn_list_two[] __FLASH = {
// gfx for widgets
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
static const uint8_t mask_topmenu_antenna[] __FLASH = {
#include "mask_widget_antenna.lbm"
};
@@ -473,7 +473,7 @@ static const _BuiltinIcon _builtinIcons[EDGETX_ICONS_COUNT] = {
#if defined(USB_CHARGER)
BI(ICON_TOPMENU_TXBATT_CHARGE, mask_widget_txbatt_charging),
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
BI(ICON_TOPMENU_ANTENNA, mask_topmenu_antenna),
#endif
#if defined(INTERNAL_GPS)
+1 -1
View File
@@ -100,7 +100,7 @@ enum EdgeTxIcon {
#if defined(USB_CHARGER)
ICON_TOPMENU_TXBATT_CHARGE,
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
ICON_TOPMENU_ANTENNA,
#endif
#if defined(INTERNAL_GPS)
@@ -67,8 +67,6 @@ CrossfireSettings::CrossfireSettings(Window* parent, const FlexGridLayout& g,
return std::string(msg);
});
moduleIdx = moduleIdx;
auto armingLine = newLine(grid);
lblArmMode = new StaticText(armingLine, rect_t{}, STR_CRSF_ARMING_MODE);
auto box = new Window(armingLine, rect_t{});
@@ -19,18 +19,16 @@
* GNU General Public License for more details.
*/
#include "pxx1_settings.h"
#include "ext_antenna_settings.h"
#include "choice.h"
#include "edgetx.h"
#include "getset_helpers.h"
#define SET_DIRTY() storageDirty(EE_MODEL)
#if defined(EXTERNAL_ANTENNA)
PXX1AntennaSettings::PXX1AntennaSettings(Window* parent,
const FlexGridLayout& g,
uint8_t moduleIdx) :
ExtAntennaSettings::ExtAntennaSettings(Window* parent,
const FlexGridLayout& g,
uint8_t moduleIdx) :
Window(parent, rect_t{}), md(&g_model.moduleData[moduleIdx])
{
FlexGridLayout grid(g);
@@ -39,25 +37,17 @@ PXX1AntennaSettings::PXX1AntennaSettings(Window* parent,
auto line = newLine(grid);
new StaticText(line, rect_t{}, STR_ANTENNA);
if (md->pxx.antennaMode == ANTENNA_MODE_PER_MODEL) {
md->pxx.antennaMode = ANTENNA_MODE_INTERNAL;
SET_DIRTY();
if (md->antennaMode == ANTENNA_MODE_PER_MODEL) {
md->antennaMode = ANTENNA_MODE_INTERNAL;
storageDirty(EE_MODEL);
}
auto antennaChoice = new Choice(
line, rect_t{}, STR_ANTENNA_MODES, ANTENNA_MODE_INTERNAL,
ANTENNA_MODE_EXTERNAL, GET_DEFAULT(md->pxx.antennaMode),
ANTENNA_MODE_EXTERNAL, GET_DEFAULT(md->antennaMode),
[=](int32_t antenna) -> void {
if (!isExternalAntennaEnabled() && (antenna == ANTENNA_MODE_EXTERNAL)) {
if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) {
md->pxx.antennaMode = antenna;
SET_DIRTY();
}
} else {
md->pxx.antennaMode = antenna;
SET_DIRTY();
checkExternalAntenna();
}
setAntennaModeWithConfirm(antenna, EE_MODEL,
[=](int8_t mode) { md->antennaMode = mode; });
});
antennaChoice->setAvailableHandler(
@@ -26,12 +26,12 @@
struct ModuleData;
class PXX1AntennaSettings : public Window, public ModuleOptions
class ExtAntennaSettings : public Window, public ModuleOptions
{
ModuleData* md;
void update() override {}
public:
PXX1AntennaSettings(Window* parent, const FlexGridLayout& g, uint8_t moduleIdx);
ExtAntennaSettings(Window* parent, const FlexGridLayout& g, uint8_t moduleIdx);
};
+15 -8
View File
@@ -37,8 +37,8 @@
#include "storage/modelslist.h"
#include "toggleswitch.h"
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#include "pxx1_settings.h"
#if defined(EXTERNAL_ANTENNA)
#include "ext_antenna_settings.h"
#endif
#if defined(PXX2)
@@ -165,18 +165,25 @@ class ModuleWindow : public Window
modOpts = new MultimoduleSettings(this, grid, moduleIdx);
}
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
else if (moduleIdx == INTERNAL_MODULE && isModuleXJT(moduleIdx) &&
g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) {
modOpts = new PXX1AntennaSettings(this, grid, moduleIdx);
}
#endif
#if defined(DSMP)
else if (isModuleDSMP(moduleIdx)) {
modOpts = new DSMPSettings(this, grid, moduleIdx);
}
#endif
#if defined(EXTERNAL_ANTENNA)
if (moduleIdx == INTERNAL_MODULE &&
g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL) {
bool antennaModuleOk = isModuleXJT(moduleIdx);
#if defined(INTMODULE_ANTSEL_GPIO)
antennaModuleOk = true;
#endif
if (antennaModuleOk) {
new ExtAntennaSettings(this, grid, moduleIdx);
}
}
#endif
// Channel Range
auto line = newLine(grid);
new StaticText(line, rect_t{}, STR_CHANNELRANGE);
+9 -17
View File
@@ -45,7 +45,7 @@ InternalModuleWindow::InternalModuleWindow(Window *parent, FlexGridLayout& grid)
internalModule->setAvailableHandler(
[](int module) { return isInternalModuleSupported(module); });
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
ant_box = parent->newLine(grid);
ant_box->padLeft(PAD_SMALL);
new StaticText(ant_box, rect_t{}, STR_ANTENNA);
@@ -53,20 +53,8 @@ InternalModuleWindow::InternalModuleWindow(Window *parent, FlexGridLayout& grid)
ant_box, rect_t{}, STR_ANTENNA_MODES, ANTENNA_MODE_INTERNAL,
ANTENNA_MODE_EXTERNAL, GET_DEFAULT(g_eeGeneral.antennaMode),
[](int antenna) {
if (!isExternalAntennaEnabled() &&
(antenna == ANTENNA_MODE_EXTERNAL ||
(antenna == ANTENNA_MODE_PER_MODEL &&
g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode ==
ANTENNA_MODE_EXTERNAL))) {
if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) {
g_eeGeneral.antennaMode = antenna;
SET_DIRTY();
}
} else {
g_eeGeneral.antennaMode = antenna;
checkExternalAntenna();
SET_DIRTY();
}
setAntennaModeWithConfirm(antenna, EE_GENERAL,
[](int8_t mode) { g_eeGeneral.antennaMode = mode; });
});
updateAntennaLine();
@@ -112,7 +100,11 @@ void InternalModuleWindow::updateBaudrateLine()
void InternalModuleWindow::updateAntennaLine()
{
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
ant_box->show(isInternalModuleAvailable(MODULE_TYPE_XJT_PXX1));
#if defined(EXTERNAL_ANTENNA)
#if defined(INTMODULE_ANTSEL_GPIO)
ant_box->show(g_eeGeneral.internalModule != MODULE_TYPE_NONE);
#else
ant_box->show(isModuleXJT(INTERNAL_MODULE));
#endif
#endif
}
@@ -68,7 +68,7 @@ class RadioInfoWidget : public Widget
batteryChargeIcon->hide();
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
extAntenna = new StaticIcon(this, W_RSSI_X - PAD_SMALL, 1,
ICON_TOPMENU_ANTENNA,
COLOR_THEME_PRIMARY2_INDEX);
@@ -149,9 +149,8 @@ class RadioInfoWidget : public Widget
batteryChargeIcon->show(usbChargerLed());
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
extAntenna->show(isModuleXJT(INTERNAL_MODULE) &&
isExternalAntennaEnabled());
#if defined(EXTERNAL_ANTENNA)
extAntenna->show(isExternalAntennaEnabled());
#endif
// Battery level
@@ -219,7 +218,7 @@ class RadioInfoWidget : public Widget
#if defined(USB_CHARGER)
StaticIcon* batteryChargeIcon;
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
StaticIcon* extAntenna;
#endif
};
+15 -7
View File
@@ -86,7 +86,7 @@ enum {
ITEM_RADIO_HARDWARE_BLUETOOTH_DISTANT_ADDR,
ITEM_RADIO_HARDWARE_BLUETOOTH_NAME,
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA,
#endif
ITEM_RADIO_HARDWARE_SERIAL_PORT_LABEL,
@@ -106,19 +106,23 @@ enum {
ITEM_RADIO_HARDWARE_MAX
};
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
static void onHardwareAntennaSwitchConfirm(const char * result)
{
if (result == STR_OK) {
// Switch to external antenna confirmation
g_eeGeneral.antennaMode = reusableBuffer.radioHardware.antennaMode;
storageDirty(EE_GENERAL);
// Consent already obtained above; mark enabled so checkExternalAntenna()
// applies the GPIO instead of asking again.
globalData.externalAntennaEnabled = true;
checkExternalAntenna();
}
else {
reusableBuffer.radioHardware.antennaMode = g_eeGeneral.antennaMode;
}
}
#endif
#endif // defined(EXTERNAL_ANTENNA)
#if defined(FUNCTION_SWITCHES)
#define RADIO_SETUP_2ND_COLUMN (LCD_W-11*FW)
@@ -344,9 +348,13 @@ static void _init_menu_tab_array(uint8_t* tab, size_t len)
tab[ITEM_RADIO_HARDWARE_BLUETOOTH_NAME] = bt_off ? HIDDEN_ROW : 0;
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
tab[ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA] =
#if defined(INTMODULE_ANTSEL_GPIO)
0;
#else
g_eeGeneral.internalModule == MODULE_TYPE_XJT_PXX1 ? 0 : HIDDEN_ROW;
#endif
#endif
bool has_serial = false;
@@ -409,7 +417,7 @@ void menuRadioHardware(event_t event)
}
else if (event == EVT_ENTRY) {
enableVBatBridge();
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
reusableBuffer.radioHardware.antennaMode = g_eeGeneral.antennaMode;
#endif
}
@@ -560,11 +568,11 @@ void menuRadioHardware(event_t event)
break;
#endif
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
#if defined(EXTERNAL_ANTENNA)
case ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA:
reusableBuffer.radioHardware.antennaMode = editChoice(HW_SETTINGS_COLUMN2, y, STR_ANTENNA, STR_ANTENNA_MODES, reusableBuffer.radioHardware.antennaMode, ANTENNA_MODE_INTERNAL, ANTENNA_MODE_EXTERNAL, attr, event);
if (!s_editMode && reusableBuffer.radioHardware.antennaMode != g_eeGeneral.antennaMode) {
if (!isExternalAntennaEnabled() && (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_EXTERNAL || (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_PER_MODEL && g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode == ANTENNA_MODE_EXTERNAL))) {
if (!isExternalAntennaEnabled() && (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_EXTERNAL || (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_PER_MODEL && g_model.moduleData[INTERNAL_MODULE].antennaMode == ANTENNA_MODE_EXTERNAL))) {
POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onHardwareAntennaSwitchConfirm);
SET_WARNING_INFO(STR_ANTENNACONFIRM2, strlen(STR_ANTENNACONFIRM2), 0);
}
+83 -34
View File
@@ -717,7 +717,7 @@ bool isSourceAvailableInResetSpecialFunction(int index)
}
}
#if defined(EXTERNAL_ANTENNA) && defined(INTERNAL_MODULE_PXX1)
#if defined(EXTERNAL_ANTENNA)
#if defined(COLORLCD)
@@ -749,7 +749,9 @@ static void runAntennaSelectionMenu()
return menu->deleted();
});
}
#else
#else // !COLORLCD
#if defined(EXTERNAL_ANTENNA)
void onAntennaSelection(const char* result)
{
if (result == STR_USE_INTERNAL_ANTENNA) {
@@ -768,49 +770,96 @@ void onAntennaSwitchConfirm(const char * result)
globalData.externalAntennaEnabled = true;
}
}
#endif
#endif // defined(EXTERNAL_ANTENNA)
#endif // defined(COLORLCD)
void checkExternalAntenna()
{
if (isModuleXJT(INTERNAL_MODULE)) {
if (g_eeGeneral.antennaMode == ANTENNA_MODE_EXTERNAL) {
// TRACE("checkExternalAntenna(): External");
globalData.externalAntennaEnabled = true;
} else if (g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL &&
g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode ==
ANTENNA_MODE_EXTERNAL) {
// TRACE("checkExternalAntenna(): Per Model, External");
if (!globalData.externalAntennaEnabled) {
#if defined(COLORLCD)
if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) {
globalData.externalAntennaEnabled = true;
}
#else
POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onAntennaSwitchConfirm);
SET_WARNING_INFO(STR_ANTENNACONFIRM2, strlen(STR_ANTENNACONFIRM2), 0);
// Get the per-model antenna mode from the appropriate field
int8_t modelAntennaMode = g_model.moduleData[INTERNAL_MODULE].antennaMode;
#if !defined(INTMODULE_ANTSEL_GPIO)
if (!isModuleXJT(INTERNAL_MODULE)) {
globalData.externalAntennaEnabled = false;
return;
}
#endif
if (g_eeGeneral.antennaMode == ANTENNA_MODE_EXTERNAL) {
globalData.externalAntennaEnabled = true;
#if defined(INTMODULE_ANTSEL_GPIO) && !defined(SIMU)
INTMODULE_ANTSEL_EXT();
LED_ERROR_BEGIN();
RAISE_ALERT(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2, STR_PRESS_ANY_KEY_TO_SKIP, AU_WARNING1);
#endif
} else if (g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL &&
modelAntennaMode == ANTENNA_MODE_EXTERNAL) {
if (!globalData.externalAntennaEnabled) {
#if defined(COLORLCD)
if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) {
globalData.externalAntennaEnabled = true;
}
} else if (g_eeGeneral.antennaMode == ANTENNA_MODE_ASK ||
(g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL &&
g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode ==
ANTENNA_MODE_ASK)) {
// TRACE("checkExternalAntenna(): Ask");
globalData.externalAntennaEnabled = false;
#if defined(COLORLCD)
runAntennaSelectionMenu();
#else
POPUP_MENU_START(onAntennaSelection, 2, STR_USE_INTERNAL_ANTENNA, STR_USE_EXTERNAL_ANTENNA);
#elif defined(EXTERNAL_ANTENNA)
POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onAntennaSwitchConfirm);
SET_WARNING_INFO(STR_ANTENNACONFIRM2, strlen(STR_ANTENNACONFIRM2), 0);
#endif
} else {
globalData.externalAntennaEnabled = false;
}
} else if (g_eeGeneral.antennaMode == ANTENNA_MODE_ASK ||
(g_eeGeneral.antennaMode == ANTENNA_MODE_PER_MODEL &&
modelAntennaMode == ANTENNA_MODE_ASK)) {
globalData.externalAntennaEnabled = false;
#if defined(COLORLCD)
runAntennaSelectionMenu();
#elif defined(EXTERNAL_ANTENNA)
POPUP_MENU_START(onAntennaSelection, 2, STR_USE_INTERNAL_ANTENNA, STR_USE_EXTERNAL_ANTENNA);
#endif
} else {
globalData.externalAntennaEnabled = false;
}
}
#if defined(INTMODULE_ANTSEL_GPIO) && !defined(SIMU)
// Apply hardware GPIO switch based on result
if (g_eeGeneral.antennaMode != ANTENNA_MODE_EXTERNAL) {
if (globalData.externalAntennaEnabled) {
INTMODULE_ANTSEL_EXT();
} else {
INTMODULE_ANTSEL_INT();
}
}
#endif
}
#if defined(COLORLCD)
// Shared by every antenna-mode Choice widget (radio-level and per-model,
// GPIO and non-GPIO boards) so the "apply to hardware" step can't be
// forgotten in just one of the call sites.
void setAntennaModeWithConfirm(int8_t newMode, uint8_t storageId,
std::function<void(int8_t)> setter)
{
int8_t modelAntennaMode = g_model.moduleData[INTERNAL_MODULE].antennaMode;
bool willEnableExternal =
newMode == ANTENNA_MODE_EXTERNAL ||
(newMode == ANTENNA_MODE_PER_MODEL && modelAntennaMode == ANTENNA_MODE_EXTERNAL);
if (!isExternalAntennaEnabled() && willEnableExternal) {
if (confirmationDialog(STR_ANTENNACONFIRM1, STR_ANTENNACONFIRM2)) {
setter(newMode);
storageDirty(storageId);
// Consent already obtained above; mark enabled so checkExternalAntenna()
// applies the GPIO instead of asking again.
globalData.externalAntennaEnabled = true;
checkExternalAntenna();
}
} else {
setter(newMode);
storageDirty(storageId);
checkExternalAntenna();
}
}
#endif // defined(COLORLCD)
#endif // defined(EXTERNAL_ANTENNA)
#if defined(PXX2)
bool isPxx2IsrmChannelsCountAllowed(int channels)
+8 -2
View File
@@ -140,11 +140,17 @@ void drawSourceValue(coord_t x, coord_t y, source_t channel, LcdFlags flags=0);
extern uint8_t MODULE_BIND_ROWS(int moduleIdx);
extern uint8_t MODULE_CHANNELS_ROWS(int moduleIdx);
#if defined(EXTERNAL_ANTENNA) && defined(INTERNAL_MODULE_PXX1)
void onAntennaSwitchConfirm(const char * result);
#if defined(EXTERNAL_ANTENNA)
void checkExternalAntenna();
#if defined(COLORLCD)
void setAntennaModeWithConfirm(int8_t newMode, uint8_t storageId,
std::function<void(int8_t)> setter);
#endif
#if defined(INTERNAL_MODULE_PXX1) && !defined(COLORLCD)
void onAntennaSwitchConfirm(const char* result);
void onAntennaSelection(const char* result);
#endif
#endif
#if defined(PXX2)
inline bool isRacingModeAllowed()
+1 -1
View File
@@ -27,7 +27,7 @@
#define ROTENC_MIDSPEED 5
#define ROTENC_HIGHSPEED 50
#if defined(RADIO_FAMILY_T20) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_T15) || defined(RADIO_T15PRO) || defined(RADIO_T22) || defined(RADIO_BUMBLEBEE)
#if defined(RADIO_FAMILY_T20) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_T15) || defined(RADIO_T15PRO) || defined(RADIO_T22) || defined(RADIO_BUMBLEBEE) || defined(RADIO_V12)
#define ROTARY_ENCODER_GRANULARITY 4
#else
#define ROTARY_ENCODER_GRANULARITY 2
+1 -1
View File
@@ -30,7 +30,7 @@ bool isExternalAntennaEnabled()
case ANTENNA_MODE_EXTERNAL:
return true;
case ANTENNA_MODE_PER_MODEL:
switch (g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode) {
switch (g_model.moduleData[INTERNAL_MODULE].antennaMode) {
case ANTENNA_MODE_EXTERNAL:
case ANTENNA_MODE_ASK:
return globalData.externalAntennaEnabled;
+2
View File
@@ -34,6 +34,8 @@ elseif(PCB STREQUAL PL18)
endif()
elseif(PCB STREQUAL T15PRO)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_t15pro.cpp)
elseif(PCB STREQUAL V12)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_v12.cpp)
elseif(PCB STREQUAL T22)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_t22.cpp)
elseif(PCB STREQUAL ST16)
@@ -42,6 +42,8 @@
#include "yaml_datastructs_t15pro.cpp"
#elif defined(PCBTX16SMK3)
#include "yaml_datastructs_tx16smk3.cpp"
#elif defined(PCBV12)
#include "yaml_datastructs_v12.cpp"
#elif defined(RADIO_T22)
#include "yaml_datastructs_t22.cpp"
#elif defined(PCBPL18)
@@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -657,7 +657,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -658,7 +658,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -605,7 +605,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -648,7 +648,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -655,7 +655,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -655,7 +655,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -648,7 +648,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -666,7 +666,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -590,7 +590,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -590,7 +590,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -681,7 +681,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -682,7 +682,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
File diff suppressed because it is too large Load Diff
@@ -657,7 +657,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -735,7 +735,8 @@ static const struct YamlNode struct_ModuleData[] = {
YAML_UNSIGNED( "channelsStart", 8 ),
YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ),
YAML_ENUM("failsafeMode", 4, enum_FailsafeModes, NULL),
YAML_PADDING( 4 ),
YAML_PADDING( 2 ),
YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL),
YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type),
YAML_END
};
@@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -581,7 +581,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -659,7 +659,8 @@ static const struct YamlNode struct_ModuleData[] = {
YAML_UNSIGNED( "channelsStart", 8 ),
YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ),
YAML_ENUM("failsafeMode", 4, enum_FailsafeModes, NULL),
YAML_PADDING( 4 ),
YAML_PADDING( 2 ),
YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL),
YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type),
YAML_END
};
@@ -586,7 +586,7 @@ static const struct YamlNode struct_anonymous_6[] = {
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 2 ),
YAML_PADDING( 8 ),
YAML_END
};
@@ -664,7 +664,8 @@ static const struct YamlNode struct_ModuleData[] = {
YAML_UNSIGNED( "channelsStart", 8 ),
YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ),
YAML_ENUM("failsafeMode", 4, enum_FailsafeModes, NULL),
YAML_PADDING( 4 ),
YAML_PADDING( 2 ),
YAML_ENUM("antennaMode", 2, enum_AntennaModes, NULL),
YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type),
YAML_END
};
@@ -47,6 +47,12 @@ void pwrInit()
INTERNAL_MODULE_OFF();
#endif
// Internal module select
#if defined(HARDWARE_INTERNAL_MODULE) && defined(INTMODULE_ANTSEL_GPIO)
gpio_init(INTMODULE_ANTSEL_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_clear(INTMODULE_ANTSEL_GPIO);
#endif
// External module power
#if defined(HARDWARE_EXTERNAL_MODULE) && defined(EXTMODULE_PWR_GPIO)
gpio_init(EXTMODULE_PWR_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
@@ -125,7 +131,13 @@ bool pwrPressed()
}
#endif
#if defined(PWR_EXTRA_SWITCH_GPIO)
return !gpio_read(PWR_SWITCH_GPIO) || !gpio_read(PWR_EXTRA_SWITCH_GPIO);
#if defined(PWR_BUTTON_DUAL)
return pwrForcePressed();
#else
return !gpio_read(PWR_SWITCH_GPIO) || !gpio_read(PWR_EXTRA_SWITCH_GPIO);
#endif
#elif defined(PWR_SWITCH_GPIO)
return !gpio_read(PWR_SWITCH_GPIO);
#else
@@ -153,6 +165,6 @@ void pwrResetHandler()
#if defined(BOOT)
void* _pwr_init_hook[] __INIT_HOOK = {
(void*)pwrResetHandler,
(void*)pwrResetHandler,
};
#endif
@@ -32,7 +32,7 @@
#endif
#include "debug.h"
#define MAX_I2C_DEVICES 2
#define MAX_I2C_DEVICES 4
struct stm32_i2c_device {
I2C_HandleTypeDef handle;
@@ -27,8 +27,8 @@
#include <stdint.h>
// Maxmimum 2 I2C bus instances
enum { I2C_Bus_1 = 0, I2C_Bus_2 };
// I2C bus instances
enum { I2C_Bus_1 = 0, I2C_Bus_2, I2C_Bus_3, I2C_Bus_4 };
typedef struct {
I2C_TypeDef* I2Cx;
@@ -128,13 +128,18 @@ void usbInit()
#endif
gpio_init_af(USB_GPIO_DM, USB_GPIO_AF, GPIO_PIN_SPEED_VERY_HIGH);
gpio_init_af(USB_GPIO_DP, USB_GPIO_AF, GPIO_PIN_SPEED_VERY_HIGH);
#if defined(USB_GPIO_VBUS)
#if defined(USB_GPIO_VBUS_OPEN_DRAIN)
gpio_init(USB_GPIO_VBUS, GPIO_IN_PU, GPIO_PIN_SPEED_LOW);
#else
gpio_init(USB_GPIO_VBUS, GPIO_IN, GPIO_PIN_SPEED_LOW);
#endif
#if defined(USB_GPIO_SEL)
gpio_init(USB_GPIO_SEL, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_set(USB_GPIO_SEL);
#endif
// prime debounce state...
usbPlugged();
#endif
+8
View File
@@ -54,6 +54,7 @@ if (PCB STREQUAL X10)
set(DEFAULT_INTERNAL_MODULE ISRM_PXX2 CACHE STRING "Default internal module")
set(BLUETOOTH ON)
set(AUX_SERIAL OFF)
set(EXTERNAL_ANTENNA ON)
add_definitions(-DHARDWARE_POWER_MANAGEMENT_UNIT)
add_definitions(-DMANUFACTURER_FRSKY)
elseif (PCBREV STREQUAL T15)
@@ -135,12 +136,14 @@ if (PCB STREQUAL X10)
set(FLAVOUR x10)
set(DEFAULT_INTERNAL_MODULE XJT_PXX1 CACHE STRING "Default internal module")
set(BLUETOOTH ON)
set(EXTERNAL_ANTENNA ON)
add_definitions(-DMANUFACTURER_FRSKY)
endif()
elseif (PCB STREQUAL X12S)
set(DEFAULT_INTERNAL_MODULE XJT_PXX1 CACHE STRING "Default internal module")
set(FLAVOUR x12s)
set(BLUETOOTH ON)
set(EXTERNAL_ANTENNA ON)
set(PCBREV "13" CACHE STRING "PCB Revision")
set(AUX2_SERIAL ON) # wire to GPS
set(USE_VS1053B ON)
@@ -149,6 +152,11 @@ elseif (PCB STREQUAL X12S)
add_definitions(-DMANUFACTURER_FRSKY)
endif()
# Handset supports external antenna
if(EXTERNAL_ANTENNA)
add_definitions(-DEXTERNAL_ANTENNA)
endif()
# enable GPS support if there is AUX port available unless otherwise disabled
if(AUX_SERIAL)
option(INTERNAL_GPS "Support for internal GPS" ON)
+1 -4
View File
@@ -485,10 +485,7 @@
#define FLYSKY_HALL_DMA_Stream_TX LL_DMA_STREAM_4
#endif
// Internal PXX1 Module:
// -> let's assume all internal XJT modules used are either X10 or X12S type
#define EXTERNAL_ANTENNA
// Internal Module
#define INTMODULE_PWR_GPIO GPIO_PIN(GPIOA, 8) // PA.08
#define INTMODULE_TX_GPIO GPIO_PIN(GPIOB, 6) // PB.06
#define INTMODULE_RX_GPIO GPIO_PIN(GPIOB, 7) // PB.07
-15
View File
@@ -360,21 +360,6 @@ elseif(PCB STREQUAL X7)
set(BLUETOOTH YES)
set(ROTARY_ENCODER YES)
add_definitions(-DMANUFACTURER_FRSKY)
elseif(PCBREV STREQUAL V12)
set(DEFAULT_INTERNAL_MODULE CROSSFIRE CACHE STRING "Default internal module")
set(INTERNAL_MODULE_SERIAL YES)
set(MODULE_SIZE_STD YES)
set(FLAVOUR v12)
set(CPU_TYPE_FULL STM32F407xG)
set(ROTARY_ENCODER YES)
set(USB_CHARGER YES)
add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS)
set(PXX2 ON)
set(ENABLE_SERIAL_PASSTHROUGH ON CACHE BOOL "Enable serial passthrough")
set(CSD203_SENSOR ON)
if (NOT BLUETOOTH)
set(AUX_SERIAL ON)
endif()
elseif(PCBREV STREQUAL V14 OR PCBREV STREQUAL V14LCD)
set(DEFAULT_INTERNAL_MODULE CROSSFIRE CACHE STRING "Default internal module")
set(INTERNAL_MODULE_SERIAL YES)
+13 -13
View File
@@ -104,7 +104,7 @@
#define USE_EXTI15_10_IRQ
#define EXTI15_10_IRQ_Priority 5
#endif
#elif defined(RADIO_TX12) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_ZORRO) || defined(RADIO_MT12) || defined(RADIO_POCKET) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) || defined(RADIO_GX12)
#elif defined(RADIO_TX12) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_ZORRO) || defined(RADIO_MT12) || defined(RADIO_POCKET) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_GX12)
#define ROTARY_ENCODER_NAVIGATION
#define ROTARY_ENCODER_GPIO GPIOE
#define ROTARY_ENCODER_GPIO_PIN_A LL_GPIO_PIN_9 // PE.9
@@ -125,7 +125,7 @@
#define USE_EXTI15_10_IRQ
#define EXTI15_10_IRQ_Priority 5
#endif
#if defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_ZORRO) || defined(RADIO_MT12) || defined(RADIO_POCKET) || defined(RADIO_T14) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12)
#if defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_ZORRO) || defined(RADIO_MT12) || defined(RADIO_POCKET) || defined(RADIO_T14) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD)
#define ROTARY_ENCODER_INVERTED
#endif
#endif
@@ -137,7 +137,7 @@
#endif
// 6POS SW
#if defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12)
#if defined(RADIO_V14) || defined(RADIO_V14LCD)
#define SIXPOS_SWITCH_INDEX 6
#define SIXPOS_LED_RED 200
#define SIXPOS_LED_GREEN 0
@@ -192,7 +192,7 @@
#define ADC_VREF_PREC2 330
#elif defined(RADIO_GX12)
#define ADC_VREF_PREC2 330
#elif defined(RADIO_V12) || defined(RADIO_V14) || defined(RADIO_V14LCD)
#elif defined(RADIO_V14) || defined(RADIO_V14LCD)
#define ADC_VREF_PREC2 330
#elif defined(PCBX7)
#define ADC_VREF_PREC2 330
@@ -220,7 +220,7 @@
#elif defined(RADIO_FAMILY_T20) || defined(RADIO_BUMBLEBEE)
#define PWR_SWITCH_GPIO GPIO_PIN(GPIOG, 5) // PG.05
#define PWR_ON_GPIO GPIO_PIN(GPIOG, 6) // PG.06
#elif defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12)
#elif defined(RADIO_V14) || defined(RADIO_V14LCD)
#define PWR_SWITCH_GPIO GPIO_PIN(GPIOD, 1) // PD.01
#define PWR_ON_GPIO GPIO_PIN(GPIOB, 2) // PB.02
#else
@@ -316,7 +316,7 @@
#define INTMODULE_DMA_STREAM_IRQ DMA2_Stream7_IRQn
#define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream7_IRQHandler
#define INTMODULE_DMA_CHANNEL LL_DMA_CHANNEL_4
#elif defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) || defined(RADIO_T20V2) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) || defined(RADIO_GX12) || defined(RADIO_BUMBLEBEE)
#elif defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) || defined(RADIO_T20V2) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_GX12) || defined(RADIO_BUMBLEBEE)
#if defined(RADIO_T20V2) || defined(RADIO_BUMBLEBEE)
#define INTMODULE_BOOTCMD_GPIO GPIO_PIN(GPIOE, 4) // PE.04
#define INTMODULE_PWR_GPIO GPIO_PIN(GPIOC, 6) // PC.06
@@ -328,7 +328,7 @@
#endif
#define INTMODULE_PWR_GPIO GPIO_PIN(GPIOC, 4) // PC.04
#endif
#if defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12)
#if defined(RADIO_V14) || defined(RADIO_V14LCD)
#define INTMODULE_BOOTCMD_DEFAULT 1 // RESET
#else
#define INTMODULE_BOOTCMD_DEFAULT 0 // RESET
@@ -413,8 +413,8 @@
#endif
// External Module
#if defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019) || defined(PCBX7ACCESS) || defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) || defined(RADIO_T12MAX) || defined(RADIO_GX12)
#if defined(RADIO_X9DP2019) || defined(RADIO_X7ACCESS) || defined(RADIO_ZORRO)|| defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12)|| defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12)
#if defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019) || defined(PCBX7ACCESS) || defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) || defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_T12MAX) || defined(RADIO_GX12)
#if defined(RADIO_X9DP2019) || defined(RADIO_X7ACCESS) || defined(RADIO_ZORRO)|| defined(RADIO_POCKET) || defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12)|| defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_TPROS) || defined(RADIO_V14) || defined(RADIO_V14LCD)
#define EXTMODULE_PWR_GPIO GPIO_PIN(GPIOD, 8) // PD.08
#elif defined(PCBX9LITE)
#define EXTMODULE_PWR_GPIO GPIO_PIN(GPIOA, 8) // PA.08
@@ -447,7 +447,7 @@
#define EXTMODULE_USART_TX_DMA_STREAM LL_DMA_STREAM_6
#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMA_CHANNEL_5
#define EXTMODULE_USART_RX_DMA_STREAM LL_DMA_STREAM_1
#if defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12)
#if defined(RADIO_V14) || defined(RADIO_V14LCD)
#define EXTMODULE_TX_INVERT_GPIO GPIO_PIN(GPIOE, 7) // PE.07
#define EXTMODULE_RX_INVERT_GPIO GPIO_PIN(GPIOE, 15) // PE.15
#endif
@@ -563,7 +563,7 @@
#else
#define TELEMETRY_SET_INPUT 0
#endif
#if defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12)
#if defined(RADIO_V14) || defined(RADIO_V14LCD)
#define TELEMETRY_RX_REV_GPIO GPIO_PIN(GPIOE, 0) // PE.00
#define TELEMETRY_TX_REV_GPIO GPIO_PIN(GPIOE, 0) // PE.00
#endif
@@ -688,7 +688,7 @@
#if defined(PCBX9LITE) || defined(PCBXLITE) || defined(RADIO_X9DP2019) || \
defined(PCBX7ACCESS) || defined(RADIO_ZORRO) || defined(RADIO_POCKET) || \
defined(RADIO_TX12MK2) || defined(RADIO_BOXER) || defined(RADIO_MT12) ||\
defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_V14) || defined(RADIO_V14LCD) || defined(RADIO_V12) \
defined(RADIO_T14) || defined(RADIO_T12MAX) || defined(RADIO_V14) || defined(RADIO_V14LCD) \
|| defined(RADIO_GX12)
#define TRAINER_MODULE_CPPM_TIMER TIM3
#define TRAINER_MODULE_CPPM_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
@@ -852,7 +852,7 @@
#if defined(PCBXLITE) || defined(PCBX9LITE) || defined(PCBX7ACCESS) || \
defined(RADIO_ZORRO) || defined(RADIO_POCKET) || defined(RADIO_X9DP2019) || \
defined(RADIO_GX12) || defined(RADIO_V12) || defined(RADIO_V14) || defined(RADIO_V14LCD)
defined(RADIO_GX12) || defined(RADIO_V14) || defined(RADIO_V14LCD)
#define I2C_B1_SCL_GPIO GPIO_PIN(GPIOB, 8) // PB.08
#define I2C_B1_SDA_GPIO GPIO_PIN(GPIOB, 9) // PB.09
#else
+3 -17
View File
@@ -37,7 +37,7 @@
#if OLED_SCREEN
#define LCD_CONTRAST_OFFSET 0
#elif defined(RADIO_FAMILY_JUMPER_T12) || defined(MANUFACTURER_RADIOMASTER) || defined(RADIO_COMMANDO8) || defined(RADIO_TPRO) || defined(RADIO_T12MAX) || defined(RADIO_V12) || defined(RADIO_V14) || defined(RADIO_V14LCD)
#elif defined(RADIO_FAMILY_JUMPER_T12) || defined(MANUFACTURER_RADIOMASTER) || defined(RADIO_COMMANDO8) || defined(RADIO_TPRO) || defined(RADIO_T12MAX) || defined(RADIO_V14) || defined(RADIO_V14LCD)
#define LCD_CONTRAST_OFFSET -10
#else
#define LCD_CONTRAST_OFFSET 160
@@ -160,23 +160,10 @@ void lcdStart()
#else
#if LCD_VERTICAL_INVERT
// T12 and TX12 have the screen inverted.
#if defined(RADIO_V12)
lcdWriteCommand(0xe2); // (14) Soft reset
lcdWriteCommand(0xa0); // Set seg
lcdWriteCommand(0xc8); // Set com
lcdWriteCommand(0xf8); // Set booster
lcdWriteCommand(0x00); // 5x
lcdWriteCommand(0xa2); // Set bias=1/6
lcdWriteCommand(0x26); // Set internal rb/ra=5.0
lcdWriteCommand(0x2f); // All built-in power circuits on
lcdWriteCommand(0x81); // Set contrast
lcdWriteCommand(0x1F); // Set Vop
lcdWriteCommand(0xa6); // Set display mode
#else
lcdWriteCommand(0xe2); // (14) Soft reset
#if LCD_HORIZONTAL_INVERT
lcdWriteCommand(0xa1); // Set seg
#else
#else
lcdWriteCommand(0xa0); // Set seg
#endif
lcdWriteCommand(0xc8); // Set com
@@ -189,7 +176,6 @@ void lcdStart()
lcdWriteCommand(0x81); // Set contrast
lcdWriteCommand(0x0A); // Set Vop
lcdWriteCommand(0xa6); // Set display mode
#endif
#else
#if defined(RADIO_V14) || defined(RADIO_V14LCD)
lcdWriteCommand(0xe2); // (14) Soft reset
@@ -453,7 +439,7 @@ void lcdSetRefVolt(uint8_t val)
WAIT_FOR_DMA_END();
#endif
#if defined(RADIO_V12) || defined(RADIO_V14) || defined(RADIO_V14LCD)
#if defined(RADIO_V14) || defined(RADIO_V14LCD)
lcdWriteCommand(0x81); // Set Vop
lcdWriteCommand(val+LCD_CONTRAST_OFFSET+20);// 0-255
#else
@@ -93,10 +93,6 @@
#define USB_NAME "iFlight Commando 8"
#define USB_MANUFACTURER 'i', 'F', 'l', 'i', 'g', 'h', 't', '-' /* 8 bytes */
#define USB_PRODUCT 'C', 'o', 'm', 'm', 'a', 'n', 'd', 'o' /* 8 Bytes */
#elif defined(RADIO_V12)
#define USB_NAME "HelloRadioSky V12"
#define USB_MANUFACTURER 'H', 'R', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */
#define USB_PRODUCT 'V', '1', '2', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */
#elif defined(RADIO_V14)
#define USB_NAME "HelloRadioSky V14"
#define USB_MANUFACTURER 'H', 'R', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */
+195
View File
@@ -0,0 +1,195 @@
option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON)
option(PXX1 "PXX1 protocol support" ON)
option(PXX2 "PXX2 protocol support" OFF)
option(AFHDS3 "AFHDS3 TX Module" ON)
option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON)
option(GHOST "Ghost TX Module" ON)
option(MODULE_SIZE_STD "Standard size TX Module" ON)
option(LUA_MIXER "Enable LUA mixer/model scripts support" ON)
option(DISK_CACHE "Enable SD card disk cache" ON)
set(FIRMWARE_QSPI YES)
set(FIRMWARE_FORMAT_UF2 YES)
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
set(CPU_TYPE STM32H7)
set(HSE_VALUE 8000000)
set(SDCARD YES)
set(STORAGE_MODELSLIST YES)
set(HAPTIC YES)
set(GUI_DIR colorlcd)
set(BITMAPS_DIR 320x240)
set(TARGET_DIR v12)
set(RTC_BACKUP_RAM YES)
set(PPM_LIMITS_SYMETRICAL YES)
set(USB_SERIAL ON CACHE BOOL "Enable USB serial (CDC)")
set(HARDWARE_EXTERNAL_MODULE YES)
set(INTERNAL_MODULE_AFHDS3 NO)
set(INTERNAL_EXTERNAL_ANT YES)
set(ROTARY_ENCODER YES)
set(FUNCTION_SWITCHES_WITH_RGB YES)
#option(STICKS_DEAD_ZONE "Enable sticks dead zone" YES)
# IMU is not populated on production V12/V12p units.
set(IMU OFF)
# for size report script
set(CPU_TYPE_FULL STM32H750xB)
set(TARGET_LINKER_DIR stm32h750_sdram)
set(TARGET_EXTRAM_START 0xC0000000)
set(SIZE_TARGET_MEM_DEFINE "MEM_SIZE_SDRAM1=8192")
set(FIRMWARE_STRIP_BOOTLOADER YES)
add_definitions(-DPCBV12 -DPCBHORUS)
add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS)
add_definitions(-DFIRMWARE_QSPI)
add_definitions(-DFIRMWARE_FORMAT_UF2)
add_definitions(-DUSE_CUSTOM_EXTI_IRQ)
add_definitions(-DUSB_CHARGER)
set(FLAVOUR v12)
add_definitions(-DRADIO_V12)
add_definitions(-DMANUFACTURER_HELLORADIOSKY)
# defines existing internal modules
set(INTERNAL_MODULES CRSF CACHE STRING "Internal modules")
set(DEFAULT_INTERNAL_MODULE CROSSFIRE CACHE STRING "Default internal module")
set(BITMAPS_TARGET bm320_bitmaps)
set(FONTS_TARGET x12_fonts)
set(LCD_DRIVER lcd_driver.cpp)
set(HARDWARE_TOUCH NO)
set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} ${BITMAPS_TARGET})
set(FIRMWARE_DEPENDENCIES datacopy)
set(SOFTWARE_KEYBOARD ON)
set(FLYSKY_GIMBAL OFF)
add_definitions(
-DSTM32H750XBTx -DSTM32H750xx
-DSDRAM -DCCMRAM
-DCOLORLCD -DLIBOPENUI
-DHARDWARE_KEYS -DSOFTWARE_KEYBOARD
-DINTERNAL_EXTERNAL_ANT
)
set(SDRAM ON)
set(AUX_SERIAL OFF CACHE BOOL "AUX serial port" FORCE)
# Handset supports external antenna selection via hardware GPIO switch
set(EXTERNAL_ANTENNA ON)
add_definitions(-DEXTERNAL_ANTENNA)
add_definitions(-DAUDIO -DVOICE)
add_definitions(-DSOFTWARE_VOLUME)
add_definitions(-DRTCLOCK)
add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE})
add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
add_definitions(-DPWR_BUTTON_DUAL)
add_definitions(-DI2C_HAS_BUS_4)
if(STICKS_DEAD_ZONE)
add_definitions(-DSTICK_DEAD_ZONE)
endif()
if(NOT UNEXPECTED_SHUTDOWN)
add_definitions(-DNO_UNEXPECTED_SHUTDOWN)
endif()
if(DISK_CACHE)
set(SRC ${SRC} disk_cache.cpp)
add_definitions(-DDISK_CACHE)
endif()
if(FUNCTION_SWITCHES_WITH_RGB)
set(FUNCTION_SWITCHES YES)
add_definitions(-DFUNCTION_SWITCHES)
add_definitions(-DFUNCTION_SWITCHES_RGB_LEDS)
endif()
set(AFHDS3 ON)
# VCP CLI
set(ENABLE_SERIAL_PASSTHROUGH ON CACHE BOOL "Enable serial passthrough")
set(CLI ON CACHE BOOL "Enable CLI")
set(BOARD helloradio-h750)
set(BOARD_SRC_DIR boards/${BOARD})
include_directories(boards/${BOARD})
set(TARGET_SRC_DIR targets/${TARGET_DIR})
set(BOARD_COMMON_SRC
${BOARD_SRC_DIR}/board.cpp
${BOARD_SRC_DIR}/key_driver.cpp
${BOARD_SRC_DIR}/lcd_driver.cpp
${BOARD_SRC_DIR}/backlight_driver.cpp
${BOARD_SRC_DIR}/haptic_driver.cpp
${BOARD_SRC_DIR}/extflash_driver.cpp
${BOARD_SRC_DIR}/usb_charger_driver.cpp
targets/common/arm/stm32/abnormal_reboot.cpp
targets/common/arm/stm32/delays_driver.cpp
targets/common/arm/stm32/dma2d.cpp
targets/common/arm/stm32/flash_driver.cpp
targets/common/arm/stm32/pwr_driver.cpp
targets/common/arm/stm32/rotary_encoder_driver.cpp
targets/common/arm/stm32/rtc_driver.cpp
targets/common/arm/stm32/watchdog_driver.cpp
drivers/pca95xx.cpp
)
# Bootloader board library
add_library(board_bl OBJECT EXCLUDE_FROM_ALL
${BOARD_COMMON_SRC}
${BOARD_SRC_DIR}/sdram_driver.cpp
${RADIO_SRC_DIR}/gui/colorlcd/boot_menu.cpp
targets/common/arm/stm32/stm32_qspi.cpp
targets/common/arm/stm32/stm32_pulse_driver.cpp
targets/common/arm/stm32/stm32_rgbleds.cpp
)
add_dependencies(board_bl minimal_board_lib)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:board_bl>)
set(CMSIS_SRC ${BOARD_SRC_DIR}/system_clock.c)
# Firmware board library
add_library(board OBJECT EXCLUDE_FROM_ALL
${BOARD_COMMON_SRC}
targets/common/arm/stm32/audio_dac_driver.cpp
targets/common/arm/stm32/heartbeat_driver.cpp
targets/common/arm/stm32/mixer_scheduler_driver.cpp
targets/common/arm/stm32/module_timer_driver.cpp
targets/common/arm/stm32/stm32_pulse_driver.cpp
targets/common/arm/stm32/stm32_softserial_driver.cpp
targets/common/arm/stm32/stm32_qspi.cpp
targets/common/arm/stm32/stm32_switch_driver.cpp
targets/common/arm/stm32/stm32_rgbleds.cpp
targets/common/arm/stm32/trainer_driver.cpp
)
add_dependencies(board board_lib)
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:board>)
include_directories(${RADIO_SRC_DIR}/fonts/colorlcd gui/${GUI_DIR} gui/${GUI_DIR}/layouts)
if(BOOTLOADER)
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
../../bootloader/loadboot.cpp
)
endif()
set(SRC
${SRC}
io/frsky_firmware_update.cpp
io/multi_firmware_update.cpp
)
if (MULTIMODULE)
add_definitions(-DMULTI_PROTOLIST)
set(SRC ${SRC}
io/multi_protolist.cpp
)
endif()
# Make malloc() thread-safe
add_definitions(-DTHREADSAFE_MALLOC)
+272
View File
@@ -0,0 +1,272 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*
STM32H750
DMA1
Stream0: LED_STRIP_TIMER_DMA_STREAM
Stream1: INTMODULE_DMA_STREAM
Stream2: (free)
Stream3: TELEMETRY_DMA_Stream_RX
Stream4: LCD_SPI_TX_DMA_STREAM
Stream5: INTMODULE_RX_DMA_STREAM / LCD_SPI_RX_DMA_STREAM
Stream6:
Stream7: TELEMETRY_DMA_Stream_TX
DMA2
Stream0: ADC_EXT_DMA_STREAM (ADC3, see boards/hw_defs/v12.json)
Stream1: AUDIO_DMA_Stream
Stream2:
Stream3: EXTMODULE_TIMER_DMA_STREAM
Stream4: ADC_DMA_STREAM (ADC1, see boards/hw_defs/v12.json)
Stream5: EXTMODULE_USART_RX_DMA_STREAM
Stream6: EXTMODULE_USART_TX_DMA_STREAM
TIM1: LED_STRIP_TIMER
TIM2: (free)
TIM3: EXTMODULE_TIMER
TIM4: TRAINER_TIMER
TIM5: (free)
TIM6: AUDIO_TIMER
TIM7: (free)
TIM8: BACKLIGHT_TIMER
TIM12: MIXER_SCHEDULER_TIMER
TIM13:
TIM14: MS_TIMER
TIM15: HAPTIC_GPIO_TIMER
TIM16:
TIM17: ROTARY_ENCODER_TIMER
USARTS
USART1: TELEMETRY_USART
USART2: INTMODULE_USART
USART6: EXTMODULE_USART
*/
#ifndef _HAL_H_
#define _HAL_H_
#include "hal_settings.h"
#define ADC_VREF_PREC2 330
// 6POS SW
#define SIXPOS_SWITCH_INDEX 6
// 6POS SW indicator color (used while charging / before Lua takes over)
#define SIXPOS_LED_RED 200
#define SIXPOS_LED_GREEN 0
#define SIXPOS_LED_BLUE 0
// Power
// SYS+MDL form the dual-button power-on/off chord on this radio.
#define PWR_SWITCH_GPIO GPIO_PIN(GPIOJ, 3) // SYS
#define PWR_EXTRA_SWITCH_GPIO GPIO_PIN(GPIOE, 5) // MDL
#define PWR_ON_GPIO GPIO_PIN(GPIOE, 2)
#define PWR_BUTTON_DUAL_KEY1 KEY_SYS
#define PWR_BUTTON_DUAL_KEY2 KEY_MODEL
// S.Port update connector
#define HAS_SPORT_UPDATE_CONNECTOR() (false)
// Telemetry SPORT
#define TELEMETRY_SET_INPUT 0
#define TELEMETRY_TX_GPIO GPIO_PIN(GPIOA, 9)
#define TELEMETRY_RX_GPIO GPIO_UNDEF
#define TELEMETRY_USART USART1
#define TELEMETRY_USART_IRQn USART1_IRQn
#define TELEMETRY_DMA DMA1
#define TELEMETRY_DMA_Stream_TX LL_DMA_STREAM_7
#define TELEMETRY_DMA_Channel_TX LL_DMAMUX1_REQ_USART1_TX
#define TELEMETRY_DMA_TX_Stream_IRQ DMA1_Stream7_IRQn
#define TELEMETRY_DMA_TX_IRQHandler DMA1_Stream7_IRQHandler
#define TELEMETRY_DMA_Stream_RX LL_DMA_STREAM_3
#define TELEMETRY_DMA_Channel_RX LL_DMAMUX1_REQ_USART1_RX
#define TELEMETRY_USART_IRQHandler USART1_IRQHandler
// Software IRQ (Prio 5 -> FreeRTOS compatible)
#define TELEMETRY_USE_CUSTOM_EXTI
#define CUSTOM_EXTI_IRQ_NAME ETH_WKUP_IRQ
#define ETH_WKUP_IRQ_Priority 5
#define CUSTOM_EXTI_IRQ_LINE 86
#define TELEMETRY_RX_FRAME_EXTI_LINE CUSTOM_EXTI_IRQ_LINE
// USB
#define USB_GPIO GPIOA
#define USB_GPIO_VBUS GPIO_PIN(GPIOB, 12)
#define USB_GPIO_DM GPIO_PIN(GPIOA, 11)
#define USB_GPIO_DP GPIO_PIN(GPIOA, 12)
#define USB_GPIO_AF GPIO_AF10
// Chargers (USB and wireless)
#define UCHARGER_PW GPIO_PIN(GPIOJ, 5) // charge power sw 0=DISABLE 1=ENABLE
#define UCHARGER_EN GPIO_PIN(GPIOK, 6) // charge EN 0=ENABLE 1=DISABLE
#define USB_GPIO_SEL GPIO_PIN(GPIOH, 6) // USB HUB SELECT 0->H7 MCU 1->CHARGE MCU
#define UCHARGER_GPIO GPIO_PIN(GPIOJ, 15) // charge status
// LCD (hardware SPI + DMA)
#define LCD_SPI SPI1
#define LCD_SPI_DMA DMA1
#define LCD_SPI_TX_DMA LL_DMAMUX1_REQ_SPI1_TX
#define LCD_SPI_RX_DMA LL_DMAMUX1_REQ_SPI1_RX
#define LCD_SPI_TX_DMA_STREAM LL_DMA_STREAM_4
#define LCD_SPI_RX_DMA_STREAM LL_DMA_STREAM_5
#define LCD_FMARK GPIO_PIN(GPIOH, 15)
#define LCD_NRST GPIO_PIN(GPIOI, 0)
#define LCD_SPI_RS GPIO_PIN(GPIOI, 1)
#define LCD_SPI_CS GPIO_PIN(GPIOG, 10)
#define LCD_SPI_CLK GPIO_PIN(GPIOG, 11)
#define LCD_SPI_MOSI GPIO_PIN(GPIOB, 5)
#define LCD_SPI_MISO GPIO_PIN(GPIOK, 0)
#define LCD_SPI_BAUD 100000000
// QSPI Flash
#define QSPI_CLK_GPIO GPIO_PIN(GPIOF, 10)
#define QSPI_CLK_GPIO_AF GPIO_AF9
#define QSPI_CS_GPIO GPIO_PIN(GPIOB, 10)
#define QSPI_CS_GPIO_AF GPIO_AF9
#define QSPI_MISO_GPIO GPIO_PIN(GPIOF, 9) // IO1
#define QSPI_MISO_GPIO_AF GPIO_AF10
#define QSPI_MOSI_GPIO GPIO_PIN(GPIOF, 8) // IO0
#define QSPI_MOSI_GPIO_AF GPIO_AF10
#define QSPI_WP_GPIO GPIO_PIN(GPIOF, 7) // IO2
#define QSPI_WP_GPIO_AF GPIO_AF9
#define QSPI_HOLD_GPIO GPIO_PIN(GPIOF, 6) // IO3
#define QSPI_HOLD_GPIO_AF GPIO_AF9
#define QSPI_FLASH_SIZE 0x800000
#define SD_SDIO SDMMC1
#define SD_SDIO_CLK_DIV(fq) (HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC) / (2 * fq))
#define SD_SDIO_TRANSFER_CLK_DIV SD_SDIO_CLK_DIV(24000000)
#define STORAGE_USE_SDIO
// Audio
#define INVERTED_MUTE_PIN
#define AUDIO_MUTE_GPIO GPIO_PIN(GPIOB, 1)
#define AUDIO_OUTPUT_GPIO GPIO_PIN(GPIOA, 4)
#define AUDIO_DAC DAC1
#define AUDIO_DMA_Stream LL_DMA_STREAM_1
#define AUDIO_DMA_Channel LL_DMAMUX1_REQ_DAC1_CH1
#define AUDIO_TIM_IRQn TIM6_DAC_IRQn
#define AUDIO_TIM_IRQHandler TIM6_DAC_IRQHandler
#define AUDIO_DMA_Stream_IRQn DMA2_Stream1_IRQn
#define AUDIO_DMA_Stream_IRQHandler DMA2_Stream1_IRQHandler
#define AUDIO_TIMER TIM6
#define AUDIO_DMA DMA2
// I2C Bus (shared by touch and IMU)
#define I2C_B4 I2C4
#define I2C_B4_SDA_GPIO GPIO_PIN(GPIOH, 12)
#define I2C_B4_SCL_GPIO GPIO_PIN(GPIOH, 11)
#define I2C_B4_GPIO_AF LL_GPIO_AF_4
#define I2C_B4_CLK_RATE 400000
// Touch - not present
// #define TOUCH_I2C_BUS I2C_Bus_4
// #define TOUCH_RST_GPIO GPIO_PIN(GPIOJ, 14)
// #define TOUCH_INT_GPIO GPIO_PIN(GPIOD, 11)
// #define TOUCH_INT_EXTI_Line LL_EXTI_LINE_11
// #define TOUCH_INT_EXTI_Port LL_SYSCFG_EXTI_PORTD
// #define TOUCH_INT_EXTI_SysCfgLine LL_SYSCFG_EXTI_LINE11
// TOUCH_INT_EXTI IRQ
// #if !defined(USE_EXTI15_10_IRQ)
// #define USE_EXTI15_10_IRQ
// #define EXTI15_10_IRQ_Priority 9
// #endif
// IMU (not populated on production units; kept disabled -- see CMakeLists IMU option)
#if defined(IMU)
#define IMU_I2C_BUS I2C_Bus_4
#define IMU_I2C_ADDRESS 0x69
#endif
// Internal Module
// (EXTERNAL_ANTENNA is defined via CMakeLists.txt add_definitions)
#define INTMODULE_PWR_GPIO GPIO_PIN(GPIOG, 13)
#define INTMODULE_ANTSEL_GPIO GPIO_PIN(GPIOA, 8) // antenna select 0=Int 1=Ext
#define INTMODULE_BOOTCMD_GPIO GPIO_PIN(GPIOG, 9)
#define INTMODULE_BOOTCMD_DEFAULT 0
#define INTMODULE_TX_GPIO GPIO_PIN(GPIOD, 5)
#define INTMODULE_RX_GPIO GPIO_PIN(GPIOD, 6)
#define INTMODULE_USART USART2
#define INTMODULE_GPIO_AF LL_GPIO_AF_7
#define INTMODULE_USART_IRQn USART2_IRQn
#define INTMODULE_USART_IRQHandler USART2_IRQHandler
#define INTMODULE_DMA DMA1
#define INTMODULE_DMA_STREAM LL_DMA_STREAM_1
#define INTMODULE_DMA_STREAM_IRQ DMA1_Stream1_IRQn
#define INTMODULE_DMA_FLAG_TC DMA_FLAG_TCIF1
#define INTMODULE_DMA_CHANNEL LL_DMAMUX1_REQ_USART2_TX
#define INTMODULE_RX_DMA DMA1
#define INTMODULE_RX_DMA_STREAM LL_DMA_STREAM_5
#define INTMODULE_RX_DMA_CHANNEL LL_DMAMUX1_REQ_USART2_RX
#define INTMODULE_RX_DMA_Stream_IRQn DMA1_Stream5_IRQn
#define INTMODULE_RX_DMA_Stream_IRQHandler DMA1_Stream5_IRQHandler
// External Module
#define EXTMODULE
#define EXTMODULE_PULSES
#define EXTMODULE_PWR_GPIO GPIO_PIN(GPIOI, 4)
#define EXTMODULE_TX_GPIO GPIO_PIN(GPIOC, 6) // TIM3_CH1
#define EXTMODULE_RX_GPIO GPIO_PIN(GPIOC, 7)
#define EXTMODULE_TIMER TIM3
#define EXTMODULE_TIMER_Channel LL_TIM_CHANNEL_CH1
#define EXTMODULE_TIMER_IRQn TIM3_IRQn
#define EXTMODULE_TIMER_IRQHandler TIM3_IRQHandler
#define EXTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#define EXTMODULE_TIMER_TX_GPIO_AF LL_GPIO_AF_2
// EXTMODULE USART
#define EXTMODULE_USART USART6
#define EXTMODULE_USART_TX_DMA DMA2
#define EXTMODULE_USART_TX_DMA_CHANNEL LL_DMAMUX1_REQ_USART6_TX
#define EXTMODULE_USART_TX_DMA_STREAM LL_DMA_STREAM_6
#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMAMUX1_REQ_USART6_RX
#define EXTMODULE_USART_RX_DMA_STREAM LL_DMA_STREAM_5
#define EXTMODULE_USART_IRQHandler USART6_IRQHandler
#define EXTMODULE_USART_IRQn USART6_IRQn
// EXTMODULE TIMER DMA
#define EXTMODULE_TIMER_DMA_CHANNEL LL_DMAMUX1_REQ_TIM3_UP
#define EXTMODULE_TIMER_DMA DMA2
#define EXTMODULE_TIMER_DMA_STREAM LL_DMA_STREAM_3
#define EXTMODULE_TIMER_DMA_STREAM_IRQn DMA2_Stream3_IRQn
#define EXTMODULE_TIMER_DMA_IRQHandler DMA2_Stream3_IRQHandler
// Trainer Port
#define TRAINER_IN_GPIO GPIO_PIN(GPIOD, 13) // TIM4_CH2
#define TRAINER_IN_TIMER_Channel LL_TIM_CHANNEL_CH2
#define TRAINER_OUT_GPIO GPIO_PIN(GPIOD, 12) // TIM4_CH1
#define TRAINER_OUT_TIMER_Channel LL_TIM_CHANNEL_CH1
#define TRAINER_TIMER TIM4
#define TRAINER_TIMER_IRQn TIM4_IRQn
#define TRAINER_TIMER_IRQHandler TIM4_IRQHandler
#define TRAINER_GPIO_AF LL_GPIO_AF_2
#define TRAINER_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
#define LSE_DRIVE_STRENGTH RCC_LSEDRIVE_HIGH
#endif // _HAL_H_
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#define USB_NAME "HelloRadioSky V12"
#define USB_MANUFACTURER 'H', 'E', 'L', 'L', 'O', ' ', ' ', ' ' /* 8 bytes */
#define USB_PRODUCT 'V', '1', '2', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */
+1 -2
View File
@@ -200,8 +200,7 @@ def main():
firmware_options = options_fatfish_f16
maxsize = 2 * 1024 * 1024
elif board_name == "v12":
cmake_options["PCB"] = "X7"
cmake_options["PCBREV"] = "V12"
cmake_options["PCB"] = "V12"
firmware_options = options_helloradiosky_v12
maxsize = 65536 * 8 * 2
elif board_name == "v14":
+40 -1
View File
@@ -776,7 +776,46 @@ LEGACY_NAMES = [
}
},
{
"targets": {"v12", "v14", "v14lcd"},
"targets": {"v12"},
"inputs": {
"LH": {
"yaml": "Rud",
"lua": "rud",
"description": "Rudder"
},
"LV": {
"yaml": "Ele",
"lua": "ele",
"description": "Elevator"
},
"RV": {
"yaml": "Thr",
"lua": "thr",
"description": "Throttle"
},
"RH": {
"yaml": "Ail",
"lua": "ail",
"description": "Aileron"
},
"P1": {
"yaml": "POT1",
"lua": "s1",
"label": "P1",
"short_label": "1",
"description": "Potentiometer 1"
},
"P2": {
"yaml": "POT2",
"lua": "s2",
"label": "P2",
"short_label": "2",
"description": "Potentiometer 2"
}
}
},
{
"targets": {"v14", "v14lcd"},
"inputs": {
"LH": {
"yaml": "Rud",
+1 -2
View File
@@ -69,8 +69,7 @@ boards = {
"INTERNAL_MODULE_MULTI": "YES"
},
"V12": {
"PCB": "X7",
"PCBREV": "V12",
"PCB": "V12",
},
"V14": {
"PCB": "X7",
+1 -1
View File
@@ -132,7 +132,7 @@ get_target_build_options() {
BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=F16"
;;
v12)
BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=V12"
BUILD_OPTIONS+="-DPCB=V12"
;;
v14)
BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=V14"
+1 -1
View File
@@ -11,7 +11,7 @@ if [[ -n ${GCC_ARM} ]] ; then
export PATH=${GCC_ARM}:$PATH
fi
: ${FLAVOR:="x10;t15;tx16s;pl18;nv14;pl18u;nb4p;x9d;x9dp2019;x9e;xlite;xlites;x7;tpro;t20;f16;gx12;st16;c14;pa01;tx15;t15pro;tx16smk3;t22"}
: ${FLAVOR:="x10;t15;tx16s;pl18;nv14;pl18u;nb4p;x9d;x9dp2019;x9e;xlite;xlites;x7;tpro;t20;f16;gx12;st16;c14;pa01;tx15;t15pro;tx16smk3;t22;v12"}
: ${SRCDIR:=$(dirname "$(pwd)/$0")/..}
: ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -Wno-dev -DDISABLE_COMPANION=YES -DCMAKE_MESSAGE_LOG_LEVEL=WARNING"}