1
0
Fork 0
mirror of https://github.com/EdgeTX/edgetx.git synced 2025-07-15 20:35:14 +03:00

feat: Flysky PL18 Support (#4105)

Co-authored-by: raphaelcoeffic <raphael.coeffic@frafos.com>
Co-authored-by: rotorman <risto.koiva@web.de>
Co-authored-by: Xy201207 <yaoxu@flysky.com>
Co-authored-by: Peter Feerick <peter.feerick@gmail.com>
This commit is contained in:
richardclli 2023-12-06 07:00:44 +08:00 committed by GitHub
parent 5153aaeea0
commit cc17046e7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
128 changed files with 9178 additions and 171 deletions

View file

@ -46,6 +46,8 @@ jobs:
- tx16s - tx16s
- nv14 - nv14
- el18 - el18
- pl18
- pl18ev
- t12 - t12
- t16 - t16
- t18 - t18
@ -90,9 +92,9 @@ jobs:
matrix: matrix:
target: target:
- nv14;el18 - nv14;el18
- pl18;pl18ev
- t12 - t12
- t16 - t16;t18
- t18
- t8;zorro;pocket;mt12;commando8 - t8;zorro;pocket;mt12;commando8
- tlite;tpro;tprov2;lr3pro - tlite;tpro;tprov2;lr3pro
- t20 - t20

View file

@ -16,6 +16,7 @@ jobs:
matrix: matrix:
target: target:
- nv14;el18 - nv14;el18
- pl18;pl18ev
- t12 - t12
- t16 - t16
- t18 - t18

View file

@ -318,6 +318,8 @@ elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T18)
set(FLAVOUR t18) set(FLAVOUR t18)
elseif(PCB STREQUAL NV14 AND PCBREV STREQUAL EL18) elseif(PCB STREQUAL NV14 AND PCBREV STREQUAL EL18)
set(FLAVOUR el18) set(FLAVOUR el18)
elseif(PCB STREQUAL PL18)
set(FLAVOUR pl18)
else() else()
string(TOLOWER ${PCB} FLAVOUR) string(TOLOWER ${PCB} FLAVOUR)
endif() endif()

View file

@ -293,6 +293,10 @@
<file>images/simulator/NV14/right.png</file> <file>images/simulator/NV14/right.png</file>
<file>images/simulator/NV14/top.png</file> <file>images/simulator/NV14/top.png</file>
<file>images/simulator/NV14/bottom.png</file> <file>images/simulator/NV14/bottom.png</file>
<file>images/simulator/PL18/left.png</file>
<file>images/simulator/PL18/right.png</file>
<file>images/simulator/PL18/top.png</file>
<file>images/simulator/PL18/bottom.png</file>
<file>images/wizard/ailerons.png</file> <file>images/wizard/ailerons.png</file>
<file>images/wizard/airbrakes.png</file> <file>images/wizard/airbrakes.png</file>
<file>images/wizard/elevons.png</file> <file>images/wizard/elevons.png</file>

View file

@ -110,7 +110,9 @@ uint32_t Boards::getFourCC(Type board)
case BOARD_FLYSKY_NV14: case BOARD_FLYSKY_NV14:
return 0x3A78746F; return 0x3A78746F;
case BOARD_FLYSKY_EL18: case BOARD_FLYSKY_EL18:
return 0x3A78746F; // TODO: check this return 0x3A78746F;
case BOARD_FLYSKY_PL18:
return 0x4878746F;
default: default:
return 0; return 0;
} }
@ -159,6 +161,7 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_RADIOMASTER_TX16S: case BOARD_RADIOMASTER_TX16S:
case BOARD_FLYSKY_NV14: case BOARD_FLYSKY_NV14:
case BOARD_FLYSKY_EL18: case BOARD_FLYSKY_EL18:
case BOARD_FLYSKY_PL18:
return 0; return 0;
default: default:
return 0; return 0;
@ -206,6 +209,7 @@ int Boards::getFlashSize(Type board)
case BOARD_RADIOMASTER_TX16S: case BOARD_RADIOMASTER_TX16S:
case BOARD_FLYSKY_NV14: case BOARD_FLYSKY_NV14:
case BOARD_FLYSKY_EL18: case BOARD_FLYSKY_EL18:
case BOARD_FLYSKY_PL18:
return FSIZE_HORUS; return FSIZE_HORUS;
case BOARD_UNKNOWN: case BOARD_UNKNOWN:
return FSIZE_MAX; return FSIZE_MAX;
@ -419,6 +423,20 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches)) if (index < DIM(switches))
return switches[index]; return switches[index];
} }
else if (IS_FLYSKY_PL18(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_2POS, "SA"},
{SWITCH_3POS, "SB"},
{SWITCH_2POS, "SC"},
{SWITCH_3POS, "SD"},
{SWITCH_3POS, "SE"},
{SWITCH_2POS, "SF"},
{SWITCH_3POS, "SG"},
{SWITCH_3POS, "SH"}
};
if (index < DIM(switches))
return switches[index];
}
else if (IS_FAMILY_HORUS_OR_T16(board)) { else if (IS_FAMILY_HORUS_OR_T16(board)) {
const Board::SwitchInfo switches[] = { const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"}, {SWITCH_3POS, "SA"},
@ -497,6 +515,8 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 7; return 7;
else if (IS_HORUS_X12S(board)) else if (IS_HORUS_X12S(board))
return 3; return 3;
else if (IS_FLYSKY_PL18(board))
return 3;
else else
return 3; return 3;
@ -509,7 +529,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case Sliders: case Sliders:
if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board) || IS_JUMPER_T20(board)) if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board) || IS_JUMPER_T20(board))
return 4; return 4;
else if (IS_TARANIS_X9D(board) || IS_HORUS_X10(board) || IS_FAMILY_T16(board)) else if (IS_TARANIS_X9D(board) || IS_HORUS_X10(board) || IS_FAMILY_T16(board) || IS_FLYSKY_PL18(board))
return 2; return 2;
else else
return 0; return 0;
@ -531,7 +551,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
getCapability(board, Board::MouseAnalogs) + getCapability(board, Board::GyroAnalogs); getCapability(board, Board::MouseAnalogs) + getCapability(board, Board::GyroAnalogs);
case MultiposPots: case MultiposPots:
if (IS_HORUS_OR_TARANIS(board) && !(IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board))) if (IS_HORUS_OR_TARANIS(board) && !(IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board)))
return getCapability(board, Board::Pots); return getCapability(board, Board::Pots);
else else
return 0; return 0;
@ -558,6 +578,8 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 6; return 6;
else if (board == BOARD_FLYSKY_NV14 || board == BOARD_FLYSKY_EL18) else if (board == BOARD_FLYSKY_NV14 || board == BOARD_FLYSKY_EL18)
return 8; return 8;
else if (board == BOARD_FLYSKY_PL18)
return 8;
else if (board == BOARD_RADIOMASTER_TX12_MK2 || board == BOARD_RADIOMASTER_BOXER || board == BOARD_JUMPER_TPRO) else if (board == BOARD_RADIOMASTER_TX12_MK2 || board == BOARD_RADIOMASTER_BOXER || board == BOARD_JUMPER_TPRO)
return 6; return 6;
else if (board == BOARD_RADIOMASTER_POCKET) else if (board == BOARD_RADIOMASTER_POCKET)
@ -600,7 +622,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return getCapability(board, Board::Switches); return getCapability(board, Board::Switches);
case SwitchPositions: case SwitchPositions:
if (IS_HORUS_OR_TARANIS(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board)) if (IS_HORUS_OR_TARANIS(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board))
return getCapability(board, Board::Switches) * 3; return getCapability(board, Board::Switches) * 3;
else else
return 9; return 9;
@ -610,7 +632,9 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case NumTrims: case NumTrims:
if (IS_FAMILY_HORUS_OR_T16(board) && !(IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board))) if (IS_FLYSKY_PL18(board))
return 8;
else if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board))
return 6; return 6;
else if (IS_IFLIGHT_COMMANDO8(board)) else if (IS_IFLIGHT_COMMANDO8(board))
return 0; return 0;
@ -626,7 +650,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return IS_STM32(board) ? true : false; return IS_STM32(board) ? true : false;
case HasColorLcd: case HasColorLcd:
return IS_FAMILY_HORUS_OR_T16(board); return IS_FAMILY_HORUS_OR_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board);
case HasSDCard: case HasSDCard:
return IS_STM32(board); return IS_STM32(board);
@ -647,7 +671,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return false; return false;
case SportMaxBaudRate: case SportMaxBaudRate:
if (IS_FAMILY_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_TARANIS_X7_ACCESS(board) || if (IS_FAMILY_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board) ||IS_TARANIS_X7_ACCESS(board) ||
(IS_TARANIS(board) && !IS_TARANIS_XLITE(board) && !IS_TARANIS_X7(board) && !IS_TARANIS_X9LITE(board))) (IS_TARANIS(board) && !IS_TARANIS_XLITE(board) && !IS_TARANIS_X7(board) && !IS_TARANIS_X9LITE(board)))
return 400000; // 400K and higher return 400000; // 400K and higher
else else
@ -833,6 +857,14 @@ StringTagMappingTable Boards::getAnalogNamesLookupTable(Board::Type board, const
{tr("TltY").toStdString(), "TILT_Y", 14}, {tr("TltY").toStdString(), "TILT_Y", 14},
}); });
} }
} else if (IS_FLYSKY_PL18(board)) {
tbl.insert(tbl.end(), {
{tr("VRA").toStdString(), "POT1"},
{tr("VRB").toStdString(), "POT2"},
{tr("VRC").toStdString(), "POT3"},
{tr("LS").toStdString(), "LS"},
{tr("RS").toStdString(), "RS"},
});
} else if (IS_HORUS_X10(board) || IS_FAMILY_T16(board)) { } else if (IS_HORUS_X10(board) || IS_FAMILY_T16(board)) {
if (version < adcVersion) { if (version < adcVersion) {
tbl.insert(tbl.end(), { tbl.insert(tbl.end(), {
@ -964,6 +996,8 @@ QString Boards::getBoardName(Board::Type board)
return "FlySky NV14"; return "FlySky NV14";
case BOARD_FLYSKY_EL18: case BOARD_FLYSKY_EL18:
return "FlySky EL18"; return "FlySky EL18";
case BOARD_FLYSKY_PL18:
return "FlySky PL18";
case BOARD_BETAFPV_LR3PRO: case BOARD_BETAFPV_LR3PRO:
return "BETAFPV LR3PRO"; return "BETAFPV LR3PRO";
case BOARD_IFLIGHT_COMMANDO8: case BOARD_IFLIGHT_COMMANDO8:
@ -1198,6 +1232,7 @@ int Boards::getDefaultInternalModules(Board::Type board)
case BOARD_JUMPER_TLITE_F4: case BOARD_JUMPER_TLITE_F4:
case BOARD_JUMPER_TPRO: case BOARD_JUMPER_TPRO:
case BOARD_JUMPER_TPROV2: case BOARD_JUMPER_TPROV2:
case BOARD_FLYSKY_PL18:
return (int)MODULE_TYPE_MULTIMODULE; return (int)MODULE_TYPE_MULTIMODULE;
case BOARD_BETAFPV_LR3PRO: case BOARD_BETAFPV_LR3PRO:

View file

@ -69,6 +69,7 @@ namespace Board {
BOARD_JUMPER_TLITE, BOARD_JUMPER_TLITE,
BOARD_JUMPER_TLITE_F4, BOARD_JUMPER_TLITE_F4,
BOARD_FLYSKY_NV14, BOARD_FLYSKY_NV14,
BOARD_FLYSKY_PL18,
BOARD_RADIOMASTER_ZORRO, BOARD_RADIOMASTER_ZORRO,
BOARD_JUMPER_TPRO, BOARD_JUMPER_TPRO,
BOARD_BETAFPV_LR3PRO, BOARD_BETAFPV_LR3PRO,
@ -398,6 +399,11 @@ inline bool IS_FLYSKY_EL18(Board::Type board)
return (board == Board::BOARD_FLYSKY_EL18); return (board == Board::BOARD_FLYSKY_EL18);
} }
inline bool IS_FLYSKY_PL18(Board::Type board)
{
return (board == Board::BOARD_FLYSKY_PL18);
}
inline bool IS_TARANIS_XLITE(Board::Type board) inline bool IS_TARANIS_XLITE(Board::Type board)
{ {
return board == Board::BOARD_TARANIS_XLITE || board == Board::BOARD_TARANIS_XLITES; return board == Board::BOARD_TARANIS_XLITE || board == Board::BOARD_TARANIS_XLITES;
@ -475,7 +481,9 @@ inline bool IS_FAMILY_HORUS(Board::Type board)
inline bool IS_FAMILY_HORUS_OR_T16(Board::Type board) inline bool IS_FAMILY_HORUS_OR_T16(Board::Type board)
{ {
return IS_FAMILY_HORUS(board) || IS_FAMILY_T16(board) || IS_FLYSKY_NV14(board)/*generally*/ || IS_FLYSKY_EL18(board)/*generally*/; return IS_FAMILY_HORUS(board) || IS_FAMILY_T16(board) ||
IS_FLYSKY_NV14(board)/*generally*/ || IS_FLYSKY_EL18(board)/*generally*/
|| IS_FLYSKY_PL18(board);
} }
inline bool IS_HORUS_OR_TARANIS(Board::Type board) inline bool IS_HORUS_OR_TARANIS(Board::Type board)
@ -485,7 +493,8 @@ inline bool IS_HORUS_OR_TARANIS(Board::Type board)
inline bool IS_STM32(Board::Type board) inline bool IS_STM32(Board::Type board)
{ {
return IS_TARANIS(board) || IS_FAMILY_HORUS_OR_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board); return IS_TARANIS(board) || IS_FAMILY_HORUS_OR_T16(board) ||
IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board);
} }
inline bool IS_ARM(Board::Type board) inline bool IS_ARM(Board::Type board)

View file

@ -154,6 +154,8 @@ void GeneralSettings::init()
strcpy(bluetoothName, "t16"); strcpy(bluetoothName, "t16");
else if (IS_FLYSKY_NV14(board)) else if (IS_FLYSKY_NV14(board))
strcpy(bluetoothName, "nv14"); strcpy(bluetoothName, "nv14");
else if (IS_FLYSKY_PL18(board))
strcpy(bluetoothName, "pl18");
else if (IS_FAMILY_HORUS_OR_T16(board)) else if (IS_FAMILY_HORUS_OR_T16(board))
strcpy(bluetoothName, "horus"); strcpy(bluetoothName, "horus");
else if (IS_TARANIS_X9E(board) || IS_TARANIS_SMALL(board)) else if (IS_TARANIS_X9E(board) || IS_TARANIS_SMALL(board))
@ -269,7 +271,7 @@ void GeneralSettings::init()
internalModule = g.profile[g.sessionId()].defaultInternalModule(); internalModule = g.profile[g.sessionId()].defaultInternalModule();
if (IS_FLYSKY_NV14(board)) if (IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board))
stickDeadZone = 2; stickDeadZone = 2;
} }
@ -285,7 +287,7 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board)
return; return;
// TODO: move to Boards, like with switches // TODO: move to Boards, like with switches
if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) { if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)) {
potConfig[0] = Board::POT_WITH_DETENT; potConfig[0] = Board::POT_WITH_DETENT;
potConfig[1] = Board::POT_MULTIPOS_SWITCH; potConfig[1] = Board::POT_MULTIPOS_SWITCH;
potConfig[2] = Board::POT_WITH_DETENT; potConfig[2] = Board::POT_WITH_DETENT;
@ -294,6 +296,11 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board)
potConfig[0] = Board::POT_WITHOUT_DETENT; potConfig[0] = Board::POT_WITHOUT_DETENT;
potConfig[1] = Board::POT_WITHOUT_DETENT; potConfig[1] = Board::POT_WITHOUT_DETENT;
} }
else if (IS_FLYSKY_PL18(board)) {
potConfig[0] = Board::POT_WITHOUT_DETENT;
potConfig[1] = Board::POT_WITHOUT_DETENT;
potConfig[2] = Board::POT_WITHOUT_DETENT;
}
else if (IS_TARANIS_XLITE(board)) { else if (IS_TARANIS_XLITE(board)) {
potConfig[0] = Board::POT_WITHOUT_DETENT; potConfig[0] = Board::POT_WITHOUT_DETENT;
potConfig[1] = Board::POT_WITHOUT_DETENT; potConfig[1] = Board::POT_WITHOUT_DETENT;

View file

@ -116,7 +116,7 @@ inline int MAX_POTS_STORAGE(Board::Type board, int version)
{ {
if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board)) if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
return 3; return 3;
if (version <= 220 && IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) if (version <= 220 && IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board))
return 5; return 5;
if (IS_FAMILY_T12(board)) if (IS_FAMILY_T12(board))
return 2; return 2;
@ -147,7 +147,7 @@ inline int MAX_XPOTS(Board::Type board, int version)
inline int MAX_SLIDERS_STORAGE(Board::Type board, int version) inline int MAX_SLIDERS_STORAGE(Board::Type board, int version)
{ {
if (version >= 219 && (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board))) if (version >= 219 && (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)))
return 4; return 4;
return Boards::getCapability(board, Board::Sliders); return Boards::getCapability(board, Board::Sliders);
} }
@ -183,7 +183,7 @@ inline int SWITCHES_CONFIG_SIZE(Board::Type board, int version)
inline int MAX_MOUSE_ANALOG_SOURCES(Board::Type board, int version) inline int MAX_MOUSE_ANALOG_SOURCES(Board::Type board, int version)
{ {
if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) if (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board))
return 2; return 2;
else else
return 0; return 0;
@ -211,10 +211,10 @@ inline int MAX_GYRO_ANALOGS(Board::Type board, int version)
#define MAX_CURVES(board, version) ((version >= 219 || HAS_LARGE_LCD(board)) ? 32 : 16) #define MAX_CURVES(board, version) ((version >= 219 || HAS_LARGE_LCD(board)) ? 32 : 16)
#define MAX_GVARS(board, version) 9 #define MAX_GVARS(board, version) 9
#define MAX_SCRIPTS(board) (IS_FAMILY_HORUS_OR_T16(board) ? 9 : 7) #define MAX_SCRIPTS(board) (IS_FAMILY_HORUS_OR_T16(board) ? 9 : 7)
#define MAX_TELEMETRY_SENSORS(board, version) (version <= 218 ? 32 : ((IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board) || IS_FLYSKY_NV14(board)) ? 60 : 40)) #define MAX_TELEMETRY_SENSORS(board, version) (version <= 218 ? 32 : ((IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X9(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) ? 60 : 40))
#define NUM_PPM_INPUTS(board, version) 16 #define NUM_PPM_INPUTS(board, version) 16
#define ROTENC_COUNT(board, version) ((IS_STM32(board) && version >= 218) ? 0 : 1) #define ROTENC_COUNT(board, version) ((IS_STM32(board) && version >= 218) ? 0 : 1)
#define MAX_AUX_TRIMS(board) ((IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) ? 2 : 0) #define MAX_AUX_TRIMS(board) ((IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board)) ? 2 : 0)
#define MAX_SOURCE_TYPE_SPECIAL(board, version) SOURCE_TYPE_SPECIAL_COUNT #define MAX_SOURCE_TYPE_SPECIAL(board, version) SOURCE_TYPE_SPECIAL_COUNT
inline int switchIndex(int i, Board::Type board, unsigned int version) inline int switchIndex(int i, Board::Type board, unsigned int version)
@ -2910,7 +2910,7 @@ void OpenTxModelData::beforeExport()
// TODO remove when enum not radio specific requires eeprom change and conversion // TODO remove when enum not radio specific requires eeprom change and conversion
// Note: this must mirror reverse afterImport // Note: this must mirror reverse afterImport
if (!IS_FLYSKY_NV14(board)) if (!IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board))
modelData.trainerMode -= 1; modelData.trainerMode -= 1;
if (modelData.trainerMode > TRAINER_MODE_SLAVE_JACK) { if (modelData.trainerMode > TRAINER_MODE_SLAVE_JACK) {
@ -2957,7 +2957,7 @@ void OpenTxModelData::afterImport()
// TODO remove when enum not radio specific requires eeprom change and conversion // TODO remove when enum not radio specific requires eeprom change and conversion
// Note: this must mirror reverse beforeExport // Note: this must mirror reverse beforeExport
if (!IS_FLYSKY_NV14(board)) if (!IS_FLYSKY_NV14(board) && !IS_FLYSKY_PL18(board))
modelData.trainerMode += 1; modelData.trainerMode += 1;
if (modelData.trainerMode > TRAINER_MODE_SLAVE_JACK) { if (modelData.trainerMode > TRAINER_MODE_SLAVE_JACK) {
@ -3003,7 +3003,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
internalField.Append(new UnsignedField<16>(this, chkSum)); internalField.Append(new UnsignedField<16>(this, chkSum));
if (!IS_FAMILY_HORUS_OR_T16(board) || (IS_FLYSKY_NV14(board))) { if (!IS_FAMILY_HORUS_OR_T16(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) {
internalField.Append(new UnsignedField<8>(this, generalData.currModelIndex)); internalField.Append(new UnsignedField<8>(this, generalData.currModelIndex));
internalField.Append(new UnsignedField<8>(this, generalData.contrast)); internalField.Append(new UnsignedField<8>(this, generalData.contrast));
} }
@ -3067,11 +3067,11 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
internalField.Append(new SignedField<8>(this, generalData.PPM_Multiplier)); internalField.Append(new SignedField<8>(this, generalData.PPM_Multiplier));
internalField.Append(new SignedField<8>(this, generalData.hapticLength)); internalField.Append(new SignedField<8>(this, generalData.hapticLength));
if (version < 218 || (!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board)) || IS_FLYSKY_NV14(board)) { if (version < 218 || (!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board)) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) {
internalField.Append(new UnsignedField<8>(this, generalData.reNavigation)); internalField.Append(new UnsignedField<8>(this, generalData.reNavigation));
} }
if ((!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board)) || IS_FLYSKY_NV14(board)) { if ((!IS_TARANIS(board) && !IS_FAMILY_HORUS_OR_T16(board)) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) {
internalField.Append(new UnsignedField<8>(this, generalData.stickReverse)); internalField.Append(new UnsignedField<8>(this, generalData.stickReverse));
} }

View file

@ -124,6 +124,8 @@ const char * OpenTxEepromInterface::getName()
return "EdgeTX for FlySky NV14"; return "EdgeTX for FlySky NV14";
case BOARD_FLYSKY_EL18: case BOARD_FLYSKY_EL18:
return "EdgeTX for FlySky EL18"; return "EdgeTX for FlySky EL18";
case BOARD_FLYSKY_PL18:
return "EdgeTX for FlySky PL18";
case BOARD_BETAFPV_LR3PRO: case BOARD_BETAFPV_LR3PRO:
return "EdgeTx for BETAFPV LR3PRO"; return "EdgeTx for BETAFPV LR3PRO";
case BOARD_IFLIGHT_COMMANDO8: case BOARD_IFLIGHT_COMMANDO8:
@ -664,6 +666,8 @@ int OpenTxFirmware::getCapability(::Capability capability)
case LcdWidth: case LcdWidth:
if (IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board)) if (IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board))
return 320; return 320;
else if (IS_FLYSKY_PL18(board))
return 480;
else if (IS_FAMILY_HORUS_OR_T16(board)) else if (IS_FAMILY_HORUS_OR_T16(board))
return 480; return 480;
else if (IS_TARANIS_SMALL(board)) else if (IS_TARANIS_SMALL(board))
@ -675,6 +679,8 @@ int OpenTxFirmware::getCapability(::Capability capability)
case LcdHeight: case LcdHeight:
if (IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board)) if (IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board))
return 480; return 480;
else if (IS_FLYSKY_PL18(board))
return 320;
else if (IS_FAMILY_HORUS_OR_T16(board)) else if (IS_FAMILY_HORUS_OR_T16(board))
return 272; return 272;
else else
@ -777,7 +783,7 @@ int OpenTxFirmware::getCapability(::Capability capability)
IS_JUMPER_TPRO(board) || IS_RADIOMASTER_TX12_MK2(board) || IS_RADIOMASTER_BOXER(board) || IS_RADIOMASTER_POCKET(board); IS_JUMPER_TPRO(board) || IS_RADIOMASTER_TX12_MK2(board) || IS_RADIOMASTER_BOXER(board) || IS_RADIOMASTER_POCKET(board);
case HasBluetooth: case HasBluetooth:
return (IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board)|| IS_TARANIS_X9E(board) || return (IS_FAMILY_HORUS_OR_T16(board) || IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board)|| IS_TARANIS_X9E(board) ||
IS_TARANIS_X9DP_2019(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board)) ? true : false; IS_TARANIS_X9DP_2019(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_EL18(board) || IS_FLYSKY_PL18(board)) ? true : false;
case HasADCJitterFilter: case HasADCJitterFilter:
return IS_HORUS_OR_TARANIS(board); return IS_HORUS_OR_TARANIS(board);
case HasTelemetryBaudrate: case HasTelemetryBaudrate:
@ -1244,6 +1250,13 @@ void registerOpenTxFirmwares()
addOpenTxRfOptions(firmware, FLEX + AFHDS2A + AFHDS3); addOpenTxRfOptions(firmware, FLEX + AFHDS2A + AFHDS3);
registerOpenTxFirmware(firmware); registerOpenTxFirmware(firmware);
/* FlySky PL18 board */
firmware = new OpenTxFirmware(FIRMWAREID("pl18"), Firmware::tr("FlySky PL18"), BOARD_FLYSKY_PL18);
addOpenTxFrskyOptions(firmware);
firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module"));
addOpenTxRfOptions(firmware, FLEX + AFHDS3);
registerOpenTxFirmware(firmware);
/* FrSky Horus X10 board */ /* FrSky Horus X10 board */
firmware = new OpenTxFirmware(FIRMWAREID("x10"), Firmware::tr("FrSky Horus X10 / X10S"), BOARD_X10); firmware = new OpenTxFirmware(FIRMWAREID("x10"), Firmware::tr("FrSky Horus X10 / X10S"), BOARD_X10);
addOpenTxFrskyOptions(firmware); addOpenTxFrskyOptions(firmware);

View file

@ -175,7 +175,7 @@ ui(new Ui::GeneralSetup)
ui->usbModeCB->hide(); ui->usbModeCB->hide();
} }
if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board)) { if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) {
ui->hatsModeCB->setModel(new FilteredItemModel(GeneralSettings::hatsModeItemModel())); ui->hatsModeCB->setModel(new FilteredItemModel(GeneralSettings::hatsModeItemModel()));
ui->hatsModeCB->setField(generalSettings.hatsMode, this); ui->hatsModeCB->setField(generalSettings.hatsMode, this);
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

View file

@ -1696,7 +1696,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
ui->trimsDisplay->setField(model.trimsDisplay, this); ui->trimsDisplay->setField(model.trimsDisplay, this);
if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board)) { if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) {
ui->cboHatsMode->setModel(panelFilteredModels->getItemModel(FIM_HATSMODE)); ui->cboHatsMode->setModel(panelFilteredModels->getItemModel(FIM_HATSMODE));
ui->cboHatsMode->setField(model.hatsMode, this); ui->cboHatsMode->setField(model.hatsMode, this);
} }

View file

@ -841,7 +841,7 @@ QString ModelPrinter::printSettingsTrim()
str << printLabelValue(tr("Display"), printTrimsDisplayMode()); str << printLabelValue(tr("Display"), printTrimsDisplayMode());
str << printLabelValue(tr("Extended"), printBoolean(model.extendedTrims, BOOLEAN_YESNO)); str << printLabelValue(tr("Extended"), printBoolean(model.extendedTrims, BOOLEAN_YESNO));
Board::Type board = firmware->getBoard(); Board::Type board = firmware->getBoard();
if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board)) { if (IS_FLYSKY_EL18(board) || IS_FLYSKY_NV14(board) || IS_FLYSKY_PL18(board)) {
str << printLabelValue(tr("Hats Mode"), printHatsMode()); str << printLabelValue(tr("Hats Mode"), printHatsMode());
} }
return str.join(" "); return str.join(" ");

View file

@ -40,6 +40,7 @@ set(${PROJECT_NAME}_SRCS
simulateduiwidgetJumperTPRO.cpp simulateduiwidgetJumperTPRO.cpp
simulateduiwidgetLR3PRO.cpp simulateduiwidgetLR3PRO.cpp
simulateduiwidgetNV14.cpp simulateduiwidgetNV14.cpp
simulateduiwidgetPL18.cpp
simulateduiwidgetT8.cpp simulateduiwidgetT8.cpp
simulateduiwidgetTX12.cpp simulateduiwidgetTX12.cpp
simulateduiwidgetTX16S.cpp simulateduiwidgetTX16S.cpp

View file

@ -125,6 +125,7 @@ namespace Ui {
class SimulatedUIWidgetT8; class SimulatedUIWidgetT8;
class SimulatedUIWidgetNV14; class SimulatedUIWidgetNV14;
class SimulatedUIWidgetEL18; class SimulatedUIWidgetEL18;
class SimulatedUIWidgetPL18;
} }
class SimulatedUIWidget9X: public SimulatedUIWidget class SimulatedUIWidget9X: public SimulatedUIWidget
@ -407,4 +408,16 @@ class SimulatedUIWidgetEL18: public SimulatedUIWidget
Ui::SimulatedUIWidgetEL18 * ui; Ui::SimulatedUIWidgetEL18 * ui;
}; };
class SimulatedUIWidgetPL18: public SimulatedUIWidget
{
Q_OBJECT
public:
explicit SimulatedUIWidgetPL18(SimulatorInterface * simulator, QWidget * parent = nullptr);
virtual ~SimulatedUIWidgetPL18();
private:
Ui::SimulatedUIWidgetPL18 * ui;
};
#endif // SIMULATEDUIWIDGET_H #endif // SIMULATEDUIWIDGET_H

View file

@ -0,0 +1,76 @@
/*
* 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.
*/
// NOTE: RadioUiAction(NUMBER,...): NUMBER relates to enum EnumKeys in the specific board.h
#include "simulateduiwidget.h"
#include "ui_simulateduiwidgetPL18.h"
SimulatedUIWidgetPL18::SimulatedUIWidgetPL18(SimulatorInterface *simulator, QWidget * parent):
SimulatedUIWidget(simulator, parent),
ui(new Ui::SimulatedUIWidgetPL18)
{
RadioUiAction * act;
ui->setupUi(this);
// add actions in order of appearance on the help menu
// Note: the PL18 has no physical buttons though at some point the trim joystick is repurposed
// allow for colorlcd key events and see what works
// the mouse click areas do not map to visual buttons on the background images
act = new RadioUiAction(3, QList<int>() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL);
addRadioWidget(ui->rightbuttons->addArea(QRect(10, 1, 80, 35), "PL18/left.png", act));
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
addRadioWidget(ui->rightbuttons->addArea(QRect(10, 40, 80, 35), "PL18/left.png", m_mouseMidClickAction));
act = new RadioUiAction(6, QList<int>() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS);
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 80, 80, 35), "PL18/left.png", act));
act = new RadioUiAction(5, QList<int>() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE);
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 120, 80, 35), "PL18/left.png", act));
act = new RadioUiAction(1, QList<int>() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN);
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 160, 80, 35), "PL18/left.png", act));
act = new RadioUiAction(0, QList<int>() << Qt::Key_PageUp, SIMU_STR_HLP_KEY_PGUP, SIMU_STR_HLP_ACT_PGUP);
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 200, 80, 35), "PL18/left.png", act));
act = new RadioUiAction(4, QList<int>() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace,
SIMU_STR_HLP_KEY_DN % "<br>" % SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_RTN);
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 240, 80, 35), "PL18/left.png", act));
m_scrollUpAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Minus, SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_ROT_LFT);
m_scrollDnAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT);
connectScrollActions();
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 280, 30, 30), "PL18/left.png", m_screenshotAction));
m_backlightColors << QColor(47, 123, 227);
setLcd(ui->lcd);
}
SimulatedUIWidgetPL18::~SimulatedUIWidgetPL18()
{
delete ui;
}

View file

@ -0,0 +1,206 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SimulatedUIWidgetPL18</class>
<widget class="QWidget" name="SimulatedUIWidgetPL18">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>520</width>
<height>500</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>520</width>
<height>500</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>520</width>
<height>500</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="2" rowspan="3">
<widget class="ButtonsWidget" name="rightbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>500</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>500</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/PL18/right.png)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LcdWidget" name="lcd" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>320</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>320</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
</font>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<widget class="ButtonsWidget" name="leftbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>500</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>500</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/PL18/left.png);</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QWidget" name="top" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<height>10</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/PL18/top.png)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QWidget" name="bottom" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<height>10</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
<kerning>false</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/PL18/bottom.png)</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LcdWidget</class>
<extends>QWidget</extends>
<header>lcdwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ButtonsWidget</class>
<extends>QWidget</extends>
<header>buttonswidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -133,6 +133,9 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato
case Board::BOARD_FLYSKY_EL18: case Board::BOARD_FLYSKY_EL18:
radioUiWidget = new SimulatedUIWidgetEL18(simulator, this); radioUiWidget = new SimulatedUIWidgetEL18(simulator, this);
break; break;
case Board::BOARD_FLYSKY_PL18:
radioUiWidget = new SimulatedUIWidgetPL18(simulator, this);
break;
default: default:
radioUiWidget = new SimulatedUIWidget9X(simulator, this); radioUiWidget = new SimulatedUIWidget9X(simulator, this);
break; break;

View file

@ -3,6 +3,8 @@
["BETAFPV LiteRadio 3 Pro", "lr3pro-"], ["BETAFPV LiteRadio 3 Pro", "lr3pro-"],
["Flysky EL18", "el18-"], ["Flysky EL18", "el18-"],
["Flysky NV14", "nv14-"], ["Flysky NV14", "nv14-"],
["Flysky PL18", "pl18-"],
["Flysky PL18EV", "pl18ev-"],
["FrSky Horus X10", "x10-"], ["FrSky Horus X10", "x10-"],
["FrSky Horus X10 Access", "x10-access-"], ["FrSky Horus X10 Access", "x10-access-"],
["FrSky Horus X12s", "x12s-"], ["FrSky Horus X12s", "x12s-"],

View file

@ -1,7 +1,7 @@
include(CMakeForceCompiler) include(CMakeForceCompiler)
include(Bitmaps) include(Bitmaps)
set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S NV14) set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S NV14 PL18)
set(RADIO_LANGUAGES CN CZ DA DE EN ES FI FR HE IT JP PT RU SK SE PL HU NL TW) set(RADIO_LANGUAGES CN CZ DA DE EN ES FI FR HE IT JP PT RU SK SE PL HU NL TW)
set(TTS_LANGUAGES CN CZ DA DE EN ES FR HE IT JP PT RU SK SE PL HU NL) set(TTS_LANGUAGES CN CZ DA DE EN ES FR HE IT JP PT RU SK SE PL HU NL)
@ -85,6 +85,8 @@ if(PCB STREQUAL X12S OR PCB STREQUAL X10)
include(targets/horus/CMakeLists.txt) include(targets/horus/CMakeLists.txt)
elseif(PCB STREQUAL NV14) elseif(PCB STREQUAL NV14)
include(targets/nv14/CMakeLists.txt) include(targets/nv14/CMakeLists.txt)
elseif(PCB STREQUAL PL18)
include(targets/pl18/CMakeLists.txt)
elseif(PCB STREQUAL X9E OR PCB STREQUAL X9D+ OR PCB STREQUAL X9D OR PCB STREQUAL X7 OR PCB STREQUAL X9LITE OR PCB STREQUAL X9LITES OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES) elseif(PCB STREQUAL X9E OR PCB STREQUAL X9D+ OR PCB STREQUAL X9D OR PCB STREQUAL X7 OR PCB STREQUAL X9LITE OR PCB STREQUAL X9LITES OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES)
include(targets/taranis/CMakeLists.txt) include(targets/taranis/CMakeLists.txt)
else() else()

View file

@ -4,6 +4,8 @@ set(MASK_ARGS ${BITMAP_SIZE_ARGS})
if(PCB STREQUAL NV14) if(PCB STREQUAL NV14)
set(BITMAP_TARGET_PREFIX nv14) set(BITMAP_TARGET_PREFIX nv14)
elseif(PCB STREQUAL PL18)
set(BITMAP_TARGET_PREFIX pl18)
elseif(PCB STREQUAL X12S) elseif(PCB STREQUAL X12S)
set(BITMAP_TARGET_PREFIX x12s) set(BITMAP_TARGET_PREFIX x12s)
else() else()

View file

@ -47,6 +47,9 @@ constexpr uint8_t n_ADC_spi = DIM(_ADC_spi);
constexpr uint8_t n_GPIO = DIM(_ADC_GPIOs); constexpr uint8_t n_GPIO = DIM(_ADC_GPIOs);
constexpr uint8_t n_inputs = DIM(_ADC_inputs); constexpr uint8_t n_inputs = DIM(_ADC_inputs);
static_assert(n_inputs <= MAX_ADC_INPUTS, "Too many ADC inputs");
static_assert(n_inputs <= MAX_ANALOG_INPUTS, "Too many analog inputs");
static bool adc_init() static bool adc_init()
{ {
bool success = stm32_hal_adc_init(_ADC_adc, n_ADC, _ADC_inputs, _ADC_GPIOs, n_GPIO); bool success = stm32_hal_adc_init(_ADC_adc, n_ADC, _ADC_inputs, _ADC_GPIOs, n_GPIO);

View file

@ -26,23 +26,27 @@
#include "stm32_keys.inc" #include "stm32_keys.inc"
void keysInit() #define __weak __attribute__((weak))
__weak void keysInit()
{ {
_init_keys(); _init_keys();
_init_trims(); _init_trims();
} }
uint32_t readKeys() __weak uint32_t readKeys()
{ {
return _read_keys(); return _read_keys();
} }
uint32_t readTrims() __weak uint32_t readTrims()
{ {
uint32_t trims = _read_trims(); uint32_t trims = _read_trims();
#if defined(PCBXLITE) #if defined(PCBXLITE)
if (_read_keys() & (1 << KEY_SHIFT)) if (_read_keys() & (1 << KEY_SHIFT))
return ((trims & 0x03) << 6) | ((trims & 0x0c) << 2); return ((trims & 0x03) << 6) | ((trims & 0x0c) << 2);
#endif #endif
return trims; return trims;
} }

View file

@ -28,6 +28,7 @@
#include "board.h" #include "board.h"
#include "dataconstants.h" #include "dataconstants.h"
#if defined (HARDWARE_INTERNAL_MODULE)
#if defined(INTMODULE_USART) #if defined(INTMODULE_USART)
#define INTMODULE_USART_IRQ_PRIORITY 5 #define INTMODULE_USART_IRQ_PRIORITY 5
@ -110,7 +111,8 @@ extern "C" void INTMODULE_TIMER_IRQHandler()
DEFINE_STM32_SOFTSERIAL_PORT(InternalModule, intmoduleTimer); DEFINE_STM32_SOFTSERIAL_PORT(InternalModule, intmoduleTimer);
#endif #endif // INTMODULE_USART
#endif // HARDWARE_INTERNAL_MODULE
#include "module_timer_driver.h" #include "module_timer_driver.h"

View file

@ -1040,6 +1040,7 @@ int cliSet(const char **argv)
} }
#if defined(ENABLE_SERIAL_PASSTHROUGH) #if defined(ENABLE_SERIAL_PASSTHROUGH)
#if defined(HARDWARE_INTERNAL_MODULE)
static etx_module_state_t *spInternalModuleState = nullptr; static etx_module_state_t *spInternalModuleState = nullptr;
static void spInternalModuleTx(uint8_t* buf, uint32_t len) static void spInternalModuleTx(uint8_t* buf, uint32_t len)
@ -1060,6 +1061,7 @@ static const etx_serial_init spIntmoduleSerialInitParams = {
.polarity = ETX_Pol_Normal, .polarity = ETX_Pol_Normal,
}; };
#endif // HARDWARE_INTERNAL_MODULE
// TODO: use proper method instead // TODO: use proper method instead
extern bool cdcConnected; extern bool cdcConnected;
extern uint32_t usbSerialBaudRate(void*); extern uint32_t usbSerialBaudRate(void*);
@ -1576,7 +1578,7 @@ int cliCrypt(const char ** argv)
} }
#endif #endif
#if defined(HARDWARE_TOUCH) && !defined(PCBNV14) #if defined(HARDWARE_TOUCH) && !defined(PCBNV14) && !defined(PCBPL18)
// from tp_gt911.cpp // from tp_gt911.cpp
extern uint8_t tp_gt911_cfgVer; extern uint8_t tp_gt911_cfgVer;
@ -1648,7 +1650,7 @@ const CliCommand cliCommands[] = {
#if defined(ACCESS_DENIED) && defined(DEBUG_CRYPT) #if defined(ACCESS_DENIED) && defined(DEBUG_CRYPT)
{ "crypt", cliCrypt, "<string to be encrypted>" }, { "crypt", cliCrypt, "<string to be encrypted>" },
#endif #endif
#if defined(HARDWARE_TOUCH) && !defined(PCBNV14) #if defined(HARDWARE_TOUCH) && !defined(PCBNV14) && !defined(PCBPL18)
{ "reset_gt911", cliResetGT911, ""}, { "reset_gt911", cliResetGT911, ""},
#endif #endif
{ nullptr, nullptr, nullptr } /* sentinel */ { nullptr, nullptr, nullptr } /* sentinel */

View file

@ -39,7 +39,7 @@
#define LABELS_LENGTH 100 // Maximum length of the label string #define LABELS_LENGTH 100 // Maximum length of the label string
#define LABEL_LENGTH 16 #define LABEL_LENGTH 16
#if defined(PCBHORUS) || defined(PCBNV14) #if defined(PCBHORUS) || defined(PCBNV14) || defined(PCBPL18)
#define MAX_MODELS 60 #define MAX_MODELS 60
#define MAX_OUTPUT_CHANNELS 32 // number of real output channels CH1-CH32 #define MAX_OUTPUT_CHANNELS 32 // number of real output channels CH1-CH32
#define MAX_FLIGHT_MODES 9 #define MAX_FLIGHT_MODES 9
@ -98,7 +98,7 @@ enum CurveType {
#define MIN_POINTS_PER_CURVE 3 #define MIN_POINTS_PER_CURVE 3
#define MAX_POINTS_PER_CURVE 17 #define MAX_POINTS_PER_CURVE 17
#if defined(PCBHORUS) || defined(PCBNV14) #if defined(PCBHORUS) || defined(PCBNV14) || defined(PCBPL18)
#define LEN_MODEL_NAME 15 #define LEN_MODEL_NAME 15
#define LEN_TIMER_NAME 8 #define LEN_TIMER_NAME 8
#define LEN_FLIGHT_MODE_NAME 10 #define LEN_FLIGHT_MODE_NAME 10
@ -408,7 +408,7 @@ enum PotsWarnMode {
#define MAX_FLEX_SWITCHES 0 #define MAX_FLEX_SWITCHES 0
#endif #endif
#if defined(RADIO_T20) #if NUM_TRIMS > 6
#define MAX_TRIMS 8 #define MAX_TRIMS 8
#else #else
#define MAX_TRIMS 6 #define MAX_TRIMS 6
@ -428,6 +428,13 @@ enum SwitchSources {
SWSRC_FIRST_TRIM SKIP, SWSRC_FIRST_TRIM SKIP,
SWSRC_LAST_TRIM SKIP = SWSRC_FIRST_TRIM + 2 * MAX_TRIMS - 1, SWSRC_LAST_TRIM SKIP = SWSRC_FIRST_TRIM + 2 * MAX_TRIMS - 1,
#if NUM_TRIMS > 6
SWSRC_TrimT7Down,
SWSRC_TrimT7Up,
SWSRC_TrimT8Down,
SWSRC_TrimT8Up,
#endif
SWSRC_FIRST_LOGICAL_SWITCH SKIP, SWSRC_FIRST_LOGICAL_SWITCH SKIP,
SWSRC_LAST_LOGICAL_SWITCH SKIP = SWSRC_FIRST_LOGICAL_SWITCH + MAX_LOGICAL_SWITCHES - 1, SWSRC_LAST_LOGICAL_SWITCH SKIP = SWSRC_FIRST_LOGICAL_SWITCH + MAX_LOGICAL_SWITCHES - 1,
@ -605,7 +612,7 @@ enum Functions {
#if defined(DEBUG) #if defined(DEBUG)
FUNC_MAX SKIP FUNC_MAX SKIP
#else #else
FUNC_MAX SKIP = FUNC_TEST - 1 FUNC_MAX SKIP = FUNC_TEST
#endif #endif
}; };

View file

@ -87,7 +87,7 @@ static inline void check_struct()
CHKSIZE(CurveHeader, 4); CHKSIZE(CurveHeader, 4);
CHKSIZE(CustomScreenData, 852); CHKSIZE(CustomScreenData, 852);
CHKTYPE(TopBarPersistentData, 444); CHKTYPE(TopBarPersistentData, 444);
#elif defined(PCBNV14) #elif defined(PCBNV14) || defined(PCBPL18)
// TODO // TODO
#else #else
// Common for all variants // Common for all variants

View file

@ -602,7 +602,7 @@ PACK(struct CustomScreenData {
#define TOPBAR_DATA #define TOPBAR_DATA
#endif #endif
#if defined(PCBHORUS) || defined(PCBTARANIS) || defined(PCBNV14) #if defined(PCBHORUS) || defined(PCBTARANIS) || defined(PCBNV14) || defined(PCBPL18)
#define SCRIPT_DATA \ #define SCRIPT_DATA \
NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]); NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]);
#else #else

View file

@ -46,8 +46,8 @@ EXTERN_C(extern volatile uint32_t g_tmr10ms);
#define debugPrintf(...) #define debugPrintf(...)
#endif #endif
#define TRACE_TIME_FORMAT "%0.2fs: " #define TRACE_TIME_FORMAT "%dms: "
#define TRACE_TIME_VALUE ((float)g_tmr10ms / 100.0) #define TRACE_TIME_VALUE (g_tmr10ms * 10)
#define TRACE_NOCRLF(...) debugPrintf(__VA_ARGS__) #define TRACE_NOCRLF(...) debugPrintf(__VA_ARGS__)
#define TRACE(f_, ...) debugPrintf((TRACE_TIME_FORMAT f_ CRLF), TRACE_TIME_VALUE, ##__VA_ARGS__) #define TRACE(f_, ...) debugPrintf((TRACE_TIME_FORMAT f_ CRLF), TRACE_TIME_VALUE, ##__VA_ARGS__)

View file

@ -93,7 +93,7 @@ void RadioCalibrationPage::buildBody(FormWindow * window)
deco->setSlidersVisible(true); deco->setSlidersVisible(true);
deco->setFlightModeVisible(false); deco->setFlightModeVisible(false);
#if defined(PCBNV14) #if defined(PCBNV14) || defined(PCBPL18)
new TextButton(window, {LCD_W - 120, LCD_H - 140, 90, 40}, "Next", new TextButton(window, {LCD_W - 120, LCD_H - 140, 90, 40}, "Next",
[=]() -> uint8_t { [=]() -> uint8_t {
nextStep(); nextStep();

View file

@ -177,7 +177,7 @@ class AnaCalibratedViewWindow: public AnaViewWindow {
}, COLOR_THEME_PRIMARY1); }, COLOR_THEME_PRIMARY1);
lv_obj_set_grid_cell(lbl->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, 5, LV_GRID_ALIGN_CENTER, 0, 1); lv_obj_set_grid_cell(lbl->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, 5, LV_GRID_ALIGN_CENTER, 0, 1);
#if !defined(SIMU) && !defined(PCBNV14) #if !defined(SIMU) && !defined(PCBNV14) && !defined(PCBPL18)
line = newLine(grid); line = newLine(grid);
auto lbl2 = new StaticText(line, rect_t{}, std::string("Touch GT911 FW ver: ") + std::to_string(touchGT911fwver), COLOR_THEME_PRIMARY1); auto lbl2 = new StaticText(line, rect_t{}, std::string("Touch GT911 FW ver: ") + std::to_string(touchGT911fwver), COLOR_THEME_PRIMARY1);
lv_obj_set_grid_cell(lbl2->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, 5, LV_GRID_ALIGN_CENTER, 0, 1); lv_obj_set_grid_cell(lbl2->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, 5, LV_GRID_ALIGN_CENTER, 0, 1);

View file

@ -25,7 +25,11 @@
#include "hal/rotary_encoder.h" #include "hal/rotary_encoder.h"
#if defined(PCBPL18)
static const uint8_t _trimMap[MAX_TRIMS * 2] = {8, 9, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 0, 1, 6, 7};
#else
static const uint8_t _trimMap[MAX_TRIMS * 2] = {6, 7, 4, 5, 2, 3, 0, 1, 8, 9, 10, 11}; static const uint8_t _trimMap[MAX_TRIMS * 2] = {6, 7, 4, 5, 2, 3, 0, 1, 8, 9, 10, 11};
#endif
static EnumKeys get_ith_key(uint8_t i) static EnumKeys get_ith_key(uint8_t i)
{ {
@ -122,8 +126,13 @@ class RadioKeyDiagsWindow : public Window
for (uint8_t i = 0; i < keysGetMaxTrims() * 2; i++) { for (uint8_t i = 0; i < keysGetMaxTrims() * 2; i++) {
coord_t y = 1 + FH + FH * (i / 2); coord_t y = 1 + FH + FH * (i / 2);
if (i & 1) { if (i & 1) {
#if defined(PCBPL18)
dc->drawText(TRIM_COLUMN, y, "TR", COLOR_THEME_PRIMARY1);
dc->drawNumber(TRIM_COLUMN + 20, y, i / 2 + 1, COLOR_THEME_PRIMARY1);
#else
dc->drawText(TRIM_COLUMN, y, "T", COLOR_THEME_PRIMARY1); dc->drawText(TRIM_COLUMN, y, "T", COLOR_THEME_PRIMARY1);
dc->drawNumber(TRIM_COLUMN + 10, y, i / 2 + 1, COLOR_THEME_PRIMARY1); dc->drawNumber(TRIM_COLUMN + 10, y, i / 2 + 1, COLOR_THEME_PRIMARY1);
#endif
} }
displayTrimState(dc, i & 1 ? TRIM_PLUS_COLUMN : TRIM_MINUS_COLUMN, y, _trimMap[i]); displayTrimState(dc, i & 1 ? TRIM_PLUS_COLUMN : TRIM_MINUS_COLUMN, y, _trimMap[i]);
} }

View file

@ -110,12 +110,14 @@ static void ghostmoduleconfig_cb(lv_event_t* e)
} }
} }
#if defined(HARDWARE_KEYS) && !defined(PCBPL18)
void RadioGhostModuleConfig::onCancel() void RadioGhostModuleConfig::onCancel()
{ {
reusableBuffer.ghostMenu.buttonAction = GHST_BTN_JOYLEFT; reusableBuffer.ghostMenu.buttonAction = GHST_BTN_JOYLEFT;
reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_NONE; reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_NONE;
moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL; moduleState[EXTERNAL_MODULE].counter = GHST_MENU_CONTROL;
} }
#endif
RadioGhostModuleConfig::RadioGhostModuleConfig(uint8_t moduleIdx) : RadioGhostModuleConfig::RadioGhostModuleConfig(uint8_t moduleIdx) :
Page(ICON_RADIO_TOOLS), Page(ICON_RADIO_TOOLS),
@ -144,7 +146,7 @@ void RadioGhostModuleConfig::buildBody(FormWindow * window)
new GhostModuleConfigWindow(window, {0, 0, LCD_W, LCD_H - MENU_HEADER_HEIGHT - 5}); new GhostModuleConfigWindow(window, {0, 0, LCD_W, LCD_H - MENU_HEADER_HEIGHT - 5});
} }
#if defined(HARDWARE_KEYS) #if defined(HARDWARE_KEYS) && !defined(PCBPL18)
void RadioGhostModuleConfig::onEvent(event_t event) void RadioGhostModuleConfig::onEvent(event_t event)
{ {
switch (event) { switch (event) {

View file

@ -28,7 +28,7 @@ class RadioGhostModuleConfig: public Page
public: public:
explicit RadioGhostModuleConfig(uint8_t moduleIdx); explicit RadioGhostModuleConfig(uint8_t moduleIdx);
#if defined(HARDWARE_KEYS) #if defined(HARDWARE_KEYS) && !defined(PCBPL18)
void onEvent(event_t event) override; void onEvent(event_t event) override;
void checkEvents() override; void checkEvents() override;
void onCancel() override; void onCancel() override;

View file

@ -77,13 +77,14 @@ class VersionDialog : public Dialog
memclear(&reusableBuffer.hardwareAndSettings.modules, memclear(&reusableBuffer.hardwareAndSettings.modules,
sizeof(reusableBuffer.hardwareAndSettings.modules)); sizeof(reusableBuffer.hardwareAndSettings.modules));
reusableBuffer.hardwareAndSettings.updateTime = get_tmr10ms(); reusableBuffer.hardwareAndSettings.updateTime = get_tmr10ms();
#if defined(HARDWARE_INTERNAL_MODULE)
// Query modules // Query modules
if (isModulePXX2(INTERNAL_MODULE) && modulePortPowered(INTERNAL_MODULE)) { if (isModulePXX2(INTERNAL_MODULE) && modulePortPowered(INTERNAL_MODULE)) {
moduleState[INTERNAL_MODULE].readModuleInformation( moduleState[INTERNAL_MODULE].readModuleInformation(
&reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE], &reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE],
PXX2_HW_INFO_TX_ID, PXX2_MAX_RECEIVERS_PER_MODULE - 1); PXX2_HW_INFO_TX_ID, PXX2_MAX_RECEIVERS_PER_MODULE - 1);
} }
#endif
if (isModulePXX2(EXTERNAL_MODULE) && modulePortPowered(EXTERNAL_MODULE)) { if (isModulePXX2(EXTERNAL_MODULE) && modulePortPowered(EXTERNAL_MODULE)) {
moduleState[EXTERNAL_MODULE].readModuleInformation( moduleState[EXTERNAL_MODULE].readModuleInformation(
@ -165,11 +166,13 @@ class VersionDialog : public Dialog
void update() void update()
{ {
#if defined(HARDWARE_INTERNAL_MODULE)
updateModule(INTERNAL_MODULE, updateModule(INTERNAL_MODULE,
int_name, int_name,
int_module_status_w, int_status, int_module_status_w, int_status,
int_rx_name_w, int_rx_name, int_rx_name_w, int_rx_name,
int_rx_status_w, int_rx_status); int_rx_status_w, int_rx_status);
#endif
updateModule(EXTERNAL_MODULE, updateModule(EXTERNAL_MODULE,
ext_name, ext_name,
ext_module_status_w, ext_status, ext_module_status_w, ext_status,
@ -309,11 +312,13 @@ class VersionDialog : public Dialog
{ {
if (get_tmr10ms() >= reusableBuffer.hardwareAndSettings.updateTime) { if (get_tmr10ms() >= reusableBuffer.hardwareAndSettings.updateTime) {
// Query modules // Query modules
#if defined(HARDWARE_INTERNAL_MODULE)
if (isModulePXX2(INTERNAL_MODULE) && modulePortPowered(INTERNAL_MODULE)) { if (isModulePXX2(INTERNAL_MODULE) && modulePortPowered(INTERNAL_MODULE)) {
moduleState[INTERNAL_MODULE].readModuleInformation( moduleState[INTERNAL_MODULE].readModuleInformation(
&reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE], &reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE],
PXX2_HW_INFO_TX_ID, PXX2_MAX_RECEIVERS_PER_MODULE - 1); PXX2_HW_INFO_TX_ID, PXX2_MAX_RECEIVERS_PER_MODULE - 1);
} }
#endif
if (isModulePXX2(EXTERNAL_MODULE) && modulePortPowered(EXTERNAL_MODULE)) { if (isModulePXX2(EXTERNAL_MODULE) && modulePortPowered(EXTERNAL_MODULE)) {
moduleState[EXTERNAL_MODULE].readModuleInformation( moduleState[EXTERNAL_MODULE].readModuleInformation(
&reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE], &reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE],
@ -332,7 +337,7 @@ RadioVersionPage::RadioVersionPage():
{ {
} }
#if defined(PCBNV14) #if defined(PCBNV14) || defined(PCBPL18)
extern const char* boardLcdType; extern const char* boardLcdType;
#endif #endif
@ -355,7 +360,7 @@ void RadioVersionPage::build(FormWindow * window)
version += options[i]; version += options[i];
} }
#if defined(PCBNV14) && !defined(SIMU) #if (defined(PCBNV14) || defined(PCBPL18)) && !defined(SIMU)
version += nl; version += nl;
version += "LCD: "; version += "LCD: ";
version += boardLcdType; version += boardLcdType;

View file

@ -180,20 +180,21 @@ class SpecialFunctionEditPage : public Page
case FUNC_PLAY_TRACK: case FUNC_PLAY_TRACK:
case FUNC_BACKGND_MUSIC: case FUNC_BACKGND_MUSIC:
case FUNC_PLAY_SCRIPT: case FUNC_PLAY_SCRIPT:
case FUNC_RGB_LED:
new StaticText(line, rect_t{}, STR_VALUE, 0, COLOR_THEME_PRIMARY1); new StaticText(line, rect_t{}, STR_VALUE, 0, COLOR_THEME_PRIMARY1);
new FileChoice( new FileChoice(
line, rect_t{}, line, rect_t{},
func == FUNC_PLAY_SCRIPT func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED
? SCRIPTS_FUNCS_PATH ? (func == FUNC_PLAY_SCRIPT ? SCRIPTS_FUNCS_PATH : SCRIPTS_RGB_PATH)
: std::string(SOUNDS_PATH, SOUNDS_PATH_LNG_OFS) + : std::string(SOUNDS_PATH, SOUNDS_PATH_LNG_OFS) +
std::string(currentLanguagePack->id, 2), std::string(currentLanguagePack->id, 2),
func == FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, (func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED) ? SCRIPTS_EXT : SOUNDS_EXT,
sizeof(cfn->play.name), sizeof(cfn->play.name),
[=]() { return std::string(cfn->play.name, ZLEN(cfn->play.name)); }, [=]() { return std::string(cfn->play.name, ZLEN(cfn->play.name)); },
[=](std::string newValue) { [=](std::string newValue) {
strncpy(cfn->play.name, newValue.c_str(), sizeof(cfn->play.name)); strncpy(cfn->play.name, newValue.c_str(), sizeof(cfn->play.name));
SET_DIRTY(); SET_DIRTY();
if (func == FUNC_PLAY_SCRIPT) if (func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED)
LUA_LOAD_MODEL_SCRIPTS(); LUA_LOAD_MODEL_SCRIPTS();
}, },
true); // strip extension true); // strip extension

View file

@ -22,6 +22,8 @@
#include "key_driver.h" #include "key_driver.h"
#include "definitions.h" #include "definitions.h"
#include "dataconstants.h"
#include "hal_keys.inc" #include "hal_keys.inc"
uint32_t keysGetSupported() uint32_t keysGetSupported()

View file

@ -50,11 +50,7 @@ enum EnumKeys {
MAX_KEYS MAX_KEYS
}; };
#if defined(RADIO_T20)
#define MAX_TRIMS 8
#else
#define MAX_TRIMS 6
#endif
// returns a bit field with each key set as (1 << KEY_xxx) // returns a bit field with each key set as (1 << KEY_xxx)
uint32_t readKeys(); uint32_t readKeys();

View file

@ -30,11 +30,7 @@
#include "timers_driver.h" #include "timers_driver.h"
#include "hal/watchdog_driver.h" #include "hal/watchdog_driver.h"
#include "hal/rotary_encoder.h" #include "hal/rotary_encoder.h"
#include "dataconstants.h"
// required by watchdog macro..
#if !defined(SIMU)
#include "stm32_cmsis.h"
#endif
// long key press minimum duration (x10ms), // long key press minimum duration (x10ms),
// must be less than KEY_REPEAT_DELAY // must be less than KEY_REPEAT_DELAY

View file

@ -169,7 +169,13 @@ enum CurveRefType {
#define TRIM_ELE (-2) #define TRIM_ELE (-2)
#define TRIM_THR (-3) #define TRIM_THR (-3)
#define TRIM_AIL (-4) #define TRIM_AIL (-4)
#if defined(PCBHORUS) #if defined(PCBPL18)
#define TRIM_T5 (-5)
#define TRIM_T6 (-6)
#define TRIM_T7 (-7)
#define TRIM_T8 (-8)
#define TRIM_LAST TRIM_T8
#elif defined(PCBHORUS)
#define TRIM_T5 (-5) #define TRIM_T5 (-5)
#define TRIM_T6 (-6) #define TRIM_T6 (-6)
#define TRIM_LAST TRIM_T6 #define TRIM_LAST TRIM_T6

View file

@ -203,10 +203,6 @@ extern uint8_t heartbeat;
#include "keys.h" #include "keys.h"
#include "pwr.h" #include "pwr.h"
// #if defined(PCBFRSKY) || defined(PCBNV14)
// extern uint8_t potsPos[NUM_XPOTS];
// #endif
bool trimDown(uint8_t idx); bool trimDown(uint8_t idx);
#if defined(KEYS_GPIO_REG_BIND) #if defined(KEYS_GPIO_REG_BIND)

View file

@ -83,6 +83,7 @@ typedef uint32_t LcdFlags;
typedef uint16_t event_t; typedef uint16_t event_t;
typedef uint32_t tmr10ms_t; typedef uint32_t tmr10ms_t;
typedef int32_t rotenc_t;
typedef int32_t getvalue_t; typedef int32_t getvalue_t;
typedef uint32_t mixsrc_t; typedef uint32_t mixsrc_t;
typedef int32_t swsrc_t; typedef int32_t swsrc_t;

View file

@ -116,12 +116,9 @@ static void sendFailsafeChannels(uint8_t*& p_buf, uint8_t module)
static void setupPulsesMulti(uint8_t*& p_buf, uint8_t module) static void setupPulsesMulti(uint8_t*& p_buf, uint8_t module)
{ {
static int counter[2] = {0,0}; //TODO static int counter[2] = {0,0}; //TODO
static uint8_t invert[2] = {0x00, //internal static uint8_t invert[2] = {
#if defined(PCBTARANIS) || defined(PCBHORUS) || defined(PCBNV14) 0x00, //internal
0x08 //external 0x08 //external
#else
0x00 //external
#endif
}; };
uint8_t type=MULTI_NORMAL; uint8_t type=MULTI_NORMAL;

View file

@ -559,6 +559,8 @@ void sdDone()
f_mount(nullptr, "", 0); // unmount SD f_mount(nullptr, "", 0); // unmount SD
} }
storageDeInit();
} }
uint32_t sdMounted() uint32_t sdMounted()

View file

@ -348,7 +348,7 @@ long OpenTxSim::onMouseMove(FXObject*,FXSelector,void*v)
void OpenTxSim::updateKeysAndSwitches(bool start) void OpenTxSim::updateKeysAndSwitches(bool start)
{ {
static int keys[] = { static int keys[] = {
#if defined(PCBNV14) #if defined(PCBFLYSKY)
// no keys // no keys
#elif defined(PCBHORUS) #elif defined(PCBHORUS)
KEY_Page_Up, KEY_PAGEUP, KEY_Page_Up, KEY_PAGEUP,

View file

@ -20,6 +20,8 @@ elseif(PCB STREQUAL X10)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_x10.cpp) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_x10.cpp)
elseif(PCB STREQUAL NV14) elseif(PCB STREQUAL NV14)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_nv14.cpp) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_nv14.cpp)
elseif(PCB STREQUAL PL18)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_pl18.cpp)
elseif(PCB STREQUAL X7) elseif(PCB STREQUAL X7)
if(PCBREV STREQUAL TPRO) if(PCBREV STREQUAL TPRO)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_tpro.cpp) set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_tpro.cpp)

View file

@ -34,6 +34,8 @@
#include "yaml_datastructs_x10.cpp" #include "yaml_datastructs_x10.cpp"
#elif defined(PCBNV14) #elif defined(PCBNV14)
#include "yaml_datastructs_nv14.cpp" #include "yaml_datastructs_nv14.cpp"
#elif defined(PCBPL18)
#include "yaml_datastructs_pl18.cpp"
#elif defined(PCBX7) #elif defined(PCBX7)
#if defined(RADIO_TPRO) || defined(RADIO_TPROV2) #if defined(RADIO_TPRO) || defined(RADIO_TPROV2)
#include "yaml_datastructs_tpro.cpp" #include "yaml_datastructs_tpro.cpp"

View file

@ -38,7 +38,7 @@
// ======== // ========
// //
// If any of these static_assert() fails, you need to check that // If any of these static_assert() fails, you need to check that
// the functions bellow are still applicable. // the functions below are still applicable.
// //
// Please note that the sizes used here are those from the v220 format // Please note that the sizes used here are those from the v220 format
// (see storage/conversions/yaml/datastructs_220.h) // (see storage/conversions/yaml/datastructs_220.h)

View file

@ -0,0 +1,915 @@
// generated by generate_yaml.py
//
// Enums first
//
const struct YamlIdStr enum_HatsMode[] = {
{ HATSMODE_TRIMS_ONLY, "TRIMS_ONLY" },
{ HATSMODE_KEYS_ONLY, "KEYS_ONLY" },
{ HATSMODE_SWITCHABLE, "SWITCHABLE" },
{ HATSMODE_GLOBAL, "GLOBAL" },
{ 0, NULL }
};
const struct YamlIdStr enum_BacklightMode[] = {
{ e_backlight_mode_off, "backlight_mode_off" },
{ e_backlight_mode_keys, "backlight_mode_keys" },
{ e_backlight_mode_sticks, "backlight_mode_sticks" },
{ e_backlight_mode_all, "backlight_mode_all" },
{ e_backlight_mode_on, "backlight_mode_on" },
{ 0, NULL }
};
const struct YamlIdStr enum_AntennaModes[] = {
{ ANTENNA_MODE_INTERNAL, "MODE_INTERNAL" },
{ ANTENNA_MODE_ASK, "MODE_ASK" },
{ ANTENNA_MODE_PER_MODEL, "MODE_PER_MODEL" },
{ ANTENNA_MODE_EXTERNAL, "MODE_EXTERNAL" },
{ 0, NULL }
};
const struct YamlIdStr enum_ModuleType[] = {
{ MODULE_TYPE_NONE, "TYPE_NONE" },
{ MODULE_TYPE_PPM, "TYPE_PPM" },
{ MODULE_TYPE_XJT_PXX1, "TYPE_XJT_PXX1" },
{ MODULE_TYPE_ISRM_PXX2, "TYPE_ISRM_PXX2" },
{ MODULE_TYPE_DSM2, "TYPE_DSM2" },
{ MODULE_TYPE_CROSSFIRE, "TYPE_CROSSFIRE" },
{ MODULE_TYPE_MULTIMODULE, "TYPE_MULTIMODULE" },
{ MODULE_TYPE_R9M_PXX1, "TYPE_R9M_PXX1" },
{ MODULE_TYPE_R9M_PXX2, "TYPE_R9M_PXX2" },
{ MODULE_TYPE_R9M_LITE_PXX1, "TYPE_R9M_LITE_PXX1" },
{ MODULE_TYPE_R9M_LITE_PXX2, "TYPE_R9M_LITE_PXX2" },
{ MODULE_TYPE_GHOST, "TYPE_GHOST" },
{ MODULE_TYPE_R9M_LITE_PRO_PXX2, "TYPE_R9M_LITE_PRO_PXX2" },
{ MODULE_TYPE_SBUS, "TYPE_SBUS" },
{ MODULE_TYPE_XJT_LITE_PXX2, "TYPE_XJT_LITE_PXX2" },
{ MODULE_TYPE_FLYSKY_AFHDS2A, "TYPE_FLYSKY_AFHDS2A" },
{ MODULE_TYPE_FLYSKY_AFHDS3, "TYPE_FLYSKY_AFHDS3" },
{ MODULE_TYPE_LEMON_DSMP, "TYPE_LEMON_DSMP" },
{ 0, NULL }
};
const struct YamlIdStr enum_TrainerMultiplex[] = {
{ TRAINER_OFF, "OFF" },
{ TRAINER_ADD, "ADD" },
{ TRAINER_REPL, "REPL" },
{ 0, NULL }
};
const struct YamlIdStr enum_BeeperMode[] = {
{ e_mode_quiet, "mode_quiet" },
{ e_mode_alarms, "mode_alarms" },
{ e_mode_nokeys, "mode_nokeys" },
{ e_mode_all, "mode_all" },
{ 0, NULL }
};
const struct YamlIdStr enum_BluetoothModes[] = {
{ BLUETOOTH_OFF, "OFF" },
{ BLUETOOTH_TELEMETRY, "TELEMETRY" },
{ BLUETOOTH_TRAINER, "TRAINER" },
{ 0, NULL }
};
const struct YamlIdStr enum_Functions[] = {
{ FUNC_OVERRIDE_CHANNEL, "OVERRIDE_CHANNEL" },
{ FUNC_TRAINER, "TRAINER" },
{ FUNC_INSTANT_TRIM, "INSTANT_TRIM" },
{ FUNC_RESET, "RESET" },
{ FUNC_SET_TIMER, "SET_TIMER" },
{ FUNC_ADJUST_GVAR, "ADJUST_GVAR" },
{ FUNC_VOLUME, "VOLUME" },
{ FUNC_SET_FAILSAFE, "SET_FAILSAFE" },
{ FUNC_RANGECHECK, "RANGECHECK" },
{ FUNC_BIND, "BIND" },
{ FUNC_PLAY_SOUND, "PLAY_SOUND" },
{ FUNC_PLAY_TRACK, "PLAY_TRACK" },
{ FUNC_PLAY_VALUE, "PLAY_VALUE" },
{ FUNC_PLAY_SCRIPT, "PLAY_SCRIPT" },
{ FUNC_BACKGND_MUSIC, "BACKGND_MUSIC" },
{ FUNC_BACKGND_MUSIC_PAUSE, "BACKGND_MUSIC_PAUSE" },
{ FUNC_VARIO, "VARIO" },
{ FUNC_HAPTIC, "HAPTIC" },
{ FUNC_LOGS, "LOGS" },
{ FUNC_BACKLIGHT, "BACKLIGHT" },
{ FUNC_SCREENSHOT, "SCREENSHOT" },
{ FUNC_RACING_MODE, "RACING_MODE" },
{ FUNC_DISABLE_TOUCH, "DISABLE_TOUCH" },
{ FUNC_SET_SCREEN, "SET_SCREEN" },
{ FUNC_DISABLE_AUDIO_AMP, "DISABLE_AUDIO_AMP" },
{ FUNC_RGB_LED, "RGB_LED" },
{ FUNC_TEST, "TEST" },
{ 0, NULL }
};
const struct YamlIdStr enum_TimerModes[] = {
{ TMRMODE_OFF, "OFF" },
{ TMRMODE_ON, "ON" },
{ TMRMODE_START, "START" },
{ TMRMODE_THR, "THR" },
{ TMRMODE_THR_REL, "THR_REL" },
{ TMRMODE_THR_START, "THR_START" },
{ 0, NULL }
};
const struct YamlIdStr enum_MixerMultiplex[] = {
{ MLTPX_ADD, "ADD" },
{ MLTPX_MUL, "MUL" },
{ MLTPX_REPL, "REPL" },
{ 0, NULL }
};
const struct YamlIdStr enum_MixSources[] = {
{ MIXSRC_NONE, "NONE" },
{ MIXSRC_MIN, "MIN" },
{ MIXSRC_MAX, "MAX" },
{ MIXSRC_TrimRud, "TrimRud" },
{ MIXSRC_TrimEle, "TrimEle" },
{ MIXSRC_TrimThr, "TrimThr" },
{ MIXSRC_TrimAil, "TrimAil" },
{ MIXSRC_TrimT5, "TrimT5" },
{ MIXSRC_TrimT6, "TrimT6" },
{ MIXSRC_TrimT7, "TrimT7" },
{ MIXSRC_TrimT8, "TrimT8" },
{ MIXSRC_TX_VOLTAGE, "TX_VOLTAGE" },
{ MIXSRC_TX_TIME, "TX_TIME" },
{ MIXSRC_TX_GPS, "TX_GPS" },
{ 0, NULL }
};
const struct YamlIdStr enum_LogicalSwitchesFunctions[] = {
{ LS_FUNC_NONE, "FUNC_NONE" },
{ LS_FUNC_VEQUAL, "FUNC_VEQUAL" },
{ LS_FUNC_VALMOSTEQUAL, "FUNC_VALMOSTEQUAL" },
{ LS_FUNC_VPOS, "FUNC_VPOS" },
{ LS_FUNC_VNEG, "FUNC_VNEG" },
{ LS_FUNC_APOS, "FUNC_APOS" },
{ LS_FUNC_ANEG, "FUNC_ANEG" },
{ LS_FUNC_AND, "FUNC_AND" },
{ LS_FUNC_OR, "FUNC_OR" },
{ LS_FUNC_XOR, "FUNC_XOR" },
{ LS_FUNC_EDGE, "FUNC_EDGE" },
{ LS_FUNC_EQUAL, "FUNC_EQUAL" },
{ LS_FUNC_GREATER, "FUNC_GREATER" },
{ LS_FUNC_LESS, "FUNC_LESS" },
{ LS_FUNC_DIFFEGREATER, "FUNC_DIFFEGREATER" },
{ LS_FUNC_ADIFFEGREATER, "FUNC_ADIFFEGREATER" },
{ LS_FUNC_TIMER, "FUNC_TIMER" },
{ LS_FUNC_STICKY, "FUNC_STICKY" },
{ 0, NULL }
};
const struct YamlIdStr enum_SwashType[] = {
{ SWASH_TYPE_NONE, "TYPE_NONE" },
{ SWASH_TYPE_120, "TYPE_120" },
{ SWASH_TYPE_120X, "TYPE_120X" },
{ SWASH_TYPE_140, "TYPE_140" },
{ SWASH_TYPE_90, "TYPE_90" },
{ 0, NULL }
};
const struct YamlIdStr enum_SwitchSources[] = {
{ SWSRC_NONE, "NONE" },
{ SWSRC_TrimT7Down, "TrimT7Down" },
{ SWSRC_TrimT7Up, "TrimT7Up" },
{ SWSRC_TrimT8Down, "TrimT8Down" },
{ SWSRC_TrimT8Up, "TrimT8Up" },
{ SWSRC_ON, "ON" },
{ SWSRC_ONE, "ONE" },
{ SWSRC_TELEMETRY_STREAMING, "TELEMETRY_STREAMING" },
{ SWSRC_RADIO_ACTIVITY, "RADIO_ACTIVITY" },
{ SWSRC_TRAINER_CONNECTED, "TRAINER_CONNECTED" },
{ SWSRC_OFF, "OFF" },
{ 0, NULL }
};
const struct YamlIdStr enum_PotsWarnMode[] = {
{ POTS_WARN_OFF, "WARN_OFF" },
{ POTS_WARN_MANUAL, "WARN_MANUAL" },
{ POTS_WARN_AUTO, "WARN_AUTO" },
{ 0, NULL }
};
const struct YamlIdStr enum_ModelOverridableEnable[] = {
{ OVERRIDE_GLOBAL, "GLOBAL" },
{ OVERRIDE_OFF, "OFF" },
{ OVERRIDE_ON, "ON" },
{ 0, NULL }
};
const struct YamlIdStr enum_FailsafeModes[] = {
{ FAILSAFE_NOT_SET, "NOT_SET" },
{ FAILSAFE_HOLD, "HOLD" },
{ FAILSAFE_CUSTOM, "CUSTOM" },
{ FAILSAFE_NOPULSES, "NOPULSES" },
{ FAILSAFE_RECEIVER, "RECEIVER" },
{ 0, NULL }
};
const struct YamlIdStr enum_TelemetrySensorFormula[] = {
{ TELEM_FORMULA_ADD, "FORMULA_ADD" },
{ TELEM_FORMULA_AVERAGE, "FORMULA_AVERAGE" },
{ TELEM_FORMULA_MIN, "FORMULA_MIN" },
{ TELEM_FORMULA_MAX, "FORMULA_MAX" },
{ TELEM_FORMULA_MULTIPLY, "FORMULA_MULTIPLY" },
{ TELEM_FORMULA_TOTALIZE, "FORMULA_TOTALIZE" },
{ TELEM_FORMULA_CELL, "FORMULA_CELL" },
{ TELEM_FORMULA_CONSUMPTION, "FORMULA_CONSUMPTION" },
{ TELEM_FORMULA_DIST, "FORMULA_DIST" },
{ 0, NULL }
};
const struct YamlIdStr enum_TelemetrySensorType[] = {
{ TELEM_TYPE_CUSTOM, "TYPE_CUSTOM" },
{ TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" },
{ 0, NULL }
};
const struct YamlIdStr enum_ZoneOptionValueEnum[] = {
{ ZOV_Unsigned, "Unsigned" },
{ ZOV_Signed, "Signed" },
{ ZOV_Bool, "Bool" },
{ ZOV_String, "String" },
{ ZOV_Source, "Source" },
{ ZOV_Color, "Color" },
{ 0, NULL }
};
const struct YamlIdStr enum_USBJoystickIfMode[] = {
{ USBJOYS_JOYSTICK, "JOYSTICK" },
{ USBJOYS_GAMEPAD, "GAMEPAD" },
{ USBJOYS_MULTIAXIS, "MULTIAXIS" },
{ 0, NULL }
};
const struct YamlIdStr enum_USBJoystickCh[] = {
{ USBJOYS_CH_NONE, "CH_NONE" },
{ USBJOYS_CH_BUTTON, "CH_BUTTON" },
{ USBJOYS_CH_AXIS, "CH_AXIS" },
{ USBJOYS_CH_SIM, "CH_SIM" },
{ 0, NULL }
};
//
// Structs last
//
static const struct YamlNode struct_CalibData[] = {
YAML_IDX_CUST("calib",r_calib,w_calib),
YAML_SIGNED( "mid", 16 ),
YAML_SIGNED( "spanNeg", 16 ),
YAML_SIGNED( "spanPos", 16 ),
YAML_END
};
static const struct YamlNode struct_signed_16[] = {
YAML_IDX,
YAML_SIGNED( "val", 16 ),
YAML_END
};
static const struct YamlNode struct_TrainerMix[] = {
YAML_IDX,
YAML_UNSIGNED( "srcChn", 6 ),
YAML_ENUM("mode", 2, enum_TrainerMultiplex),
YAML_SIGNED( "studWeight", 8 ),
YAML_END
};
static const struct YamlNode struct_TrainerData[] = {
YAML_ARRAY("calib", 16, 4, struct_signed_16, NULL),
YAML_ARRAY("mix", 16, 4, struct_TrainerMix, NULL),
YAML_END
};
static const struct YamlNode struct_anonymous_1[] = {
YAML_STRING("name", 6),
YAML_END
};
static const struct YamlNode struct_anonymous_2[] = {
YAML_SIGNED( "val", 16 ),
YAML_UNSIGNED( "mode", 8 ),
YAML_UNSIGNED( "param", 8 ),
YAML_SIGNED( "spare", 16 ),
YAML_END
};
static const struct YamlNode struct_anonymous_3[] = {
YAML_SIGNED( "val1", 32 ),
YAML_SIGNED( "val2", 16 ),
YAML_END
};
static const struct YamlNode union_anonymous_0_elmts[] = {
YAML_STRUCT("play", 48, struct_anonymous_1, NULL),
YAML_STRUCT("all", 48, struct_anonymous_2, NULL),
YAML_STRUCT("clear", 48, struct_anonymous_3, NULL),
YAML_END
};
static const struct YamlNode struct_CustomFunctionData[] = {
YAML_IDX,
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_ENUM("func", 6, enum_Functions),
YAML_CUSTOM("def",r_customFn,w_customFn),
YAML_PADDING( 48 ),
YAML_PADDING( 1 ),
YAML_PADDING( 7 ),
YAML_END
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_ENUM("hatsMode", 2, enum_HatsMode),
YAML_UNSIGNED( "ppmunit", 2 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 20, struct_CalibData, NULL),
YAML_PADDING( 16 ),
YAML_SIGNED( "currModel", 8 ),
YAML_UNSIGNED( "contrast", 8 ),
YAML_UNSIGNED( "vBatWarn", 8 ),
YAML_SIGNED( "txVoltageCalibration", 8 ),
YAML_ENUM("backlightMode", 3, enum_BacklightMode),
YAML_ENUM("antennaMode", 2, enum_AntennaModes),
YAML_UNSIGNED( "disableRtcWarning", 1 ),
YAML_UNSIGNED( "keysBacklight", 1 ),
YAML_UNSIGNED( "dontPlayHello", 1 ),
YAML_ENUM("internalModule", 8, enum_ModuleType),
YAML_STRUCT("trainer", 128, struct_TrainerData, NULL),
YAML_UNSIGNED( "view", 8 ),
YAML_PADDING( 2 ),
YAML_UNSIGNED( "fai", 1 ),
YAML_SIGNED_CUST( "beepMode", 2, r_beeperMode, w_beeperMode ),
YAML_UNSIGNED( "alarmsFlash", 1 ),
YAML_UNSIGNED( "disableMemoryWarning", 1 ),
YAML_UNSIGNED( "disableAlarmWarning", 1 ),
YAML_UNSIGNED( "stickMode", 2 ),
YAML_SIGNED( "timezone", 5 ),
YAML_UNSIGNED( "adjustRTC", 1 ),
YAML_UNSIGNED( "inactivityTimer", 8 ),
YAML_CUSTOM("telemetryBaudrate",r_telemetryBaudrate,nullptr),
YAML_UNSIGNED( "internalModuleBaudrate", 3 ),
YAML_SIGNED( "splashMode", 3 ),
YAML_SIGNED_CUST( "hapticMode", 2, r_beeperMode, w_beeperMode ),
YAML_SIGNED( "switchesDelay", 8 ),
YAML_UNSIGNED( "lightAutoOff", 8 ),
YAML_UNSIGNED( "templateSetup", 8 ),
YAML_SIGNED( "PPM_Multiplier", 8 ),
YAML_SIGNED_CUST( "hapticLength", 8, r_5pos, w_5pos ),
YAML_SIGNED_CUST( "beepLength", 3, r_5pos, w_5pos ),
YAML_SIGNED_CUST( "hapticStrength", 3, r_5pos, w_5pos ),
YAML_UNSIGNED( "gpsFormat", 1 ),
YAML_PADDING( 1 ),
YAML_UNSIGNED_CUST( "speakerPitch", 8, r_spPitch, w_spPitch ),
YAML_SIGNED_CUST( "speakerVolume", 8, r_vol, w_vol ),
YAML_SIGNED_CUST( "vBatMin", 8, r_vbat_min, w_vbat_min ),
YAML_SIGNED_CUST( "vBatMax", 8, r_vbat_max, w_vbat_max ),
YAML_UNSIGNED( "backlightBright", 8 ),
YAML_UNSIGNED( "globalTimer", 32 ),
YAML_UNSIGNED( "bluetoothBaudrate", 4 ),
YAML_ENUM("bluetoothMode", 4, enum_BluetoothModes),
YAML_UNSIGNED( "countryCode", 2 ),
YAML_SIGNED( "pwrOnSpeed", 3 ),
YAML_SIGNED( "pwrOffSpeed", 3 ),
YAML_CUSTOM("jitterFilter",r_jitterFilter,nullptr),
YAML_UNSIGNED( "noJitterFilter", 1 ),
YAML_UNSIGNED( "imperial", 1 ),
YAML_UNSIGNED( "disableRssiPoweroffAlarm", 1 ),
YAML_UNSIGNED( "USBMode", 2 ),
YAML_UNSIGNED( "jackMode", 2 ),
YAML_PADDING( 1 ),
YAML_STRING("ttsLanguage", 2),
YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ),
YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ),
YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ),
YAML_SIGNED_CUST( "backgroundVolume", 4, r_5pos, w_5pos ),
YAML_SIGNED_CUST( "varioPitch", 8, r_vPitch, w_vPitch ),
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
YAML_SIGNED( "varioRepeat", 8 ),
YAML_ARRAY("customFn", 72, 64, struct_CustomFunctionData, cfn_is_active),
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
YAML_ARRAY("serialPort", 8, 4, struct_serialConfig, nullptr),
YAML_ARRAY("sticksConfig", 0, MAX_STICKS, struct_stickConfig, stick_name_valid),
YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr),
YAML_ARRAY("potsConfig", 4, 16, struct_potConfig, nullptr),
YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr),
YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid),
YAML_STRING("currModelFilename", 17),
YAML_UNSIGNED( "modelQuickSelect", 1 ),
YAML_UNSIGNED( "blOffBright", 7 ),
YAML_STRING("bluetoothName", 10),
YAML_STRING("ownerRegistrationID", 8),
YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr),
YAML_UNSIGNED( "rotEncMode", 2 ),
YAML_SIGNED( "uartSampleMode", 2 ),
YAML_PADDING( 3 ),
YAML_UNSIGNED( "audioMuteEnable", 1 ),
YAML_STRING("selectedTheme", 26),
YAML_UNSIGNED( "radioThemesDisabled", 1 ),
YAML_UNSIGNED( "radioGFDisabled", 1 ),
YAML_UNSIGNED( "radioTrainerDisabled", 1 ),
YAML_UNSIGNED( "modelHeliDisabled", 1 ),
YAML_UNSIGNED( "modelFMDisabled", 1 ),
YAML_UNSIGNED( "modelCurvesDisabled", 1 ),
YAML_UNSIGNED( "modelGVDisabled", 1 ),
YAML_UNSIGNED( "modelLSDisabled", 1 ),
YAML_UNSIGNED( "modelSFDisabled", 1 ),
YAML_UNSIGNED( "modelCustomScriptsDisabled", 1 ),
YAML_UNSIGNED( "modelTelemetryDisabled", 1 ),
YAML_END
};
static const struct YamlNode struct_unsigned_8[] = {
YAML_IDX,
YAML_UNSIGNED( "val", 8 ),
YAML_END
};
static const struct YamlNode struct_ModelHeader[] = {
YAML_STRING("name", 15),
YAML_ARRAY("modelId", 8, 2, struct_unsigned_8, NULL),
YAML_STRING("bitmap", 14),
YAML_STRING("labels", 100),
YAML_END
};
static const struct YamlNode struct_TimerData[] = {
YAML_IDX,
YAML_UNSIGNED( "start", 22 ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_SIGNED( "value", 22 ),
YAML_ENUM("mode", 3, enum_TimerModes),
YAML_UNSIGNED( "countdownBeep", 2 ),
YAML_UNSIGNED( "minuteBeep", 1 ),
YAML_UNSIGNED( "persistent", 2 ),
YAML_SIGNED( "countdownStart", 2 ),
YAML_UNSIGNED( "showElapsed", 1 ),
YAML_UNSIGNED( "extraHaptic", 1 ),
YAML_PADDING( 6 ),
YAML_STRING("name", 8),
YAML_END
};
static const struct YamlNode struct_CurveRef[] = {
YAML_UNSIGNED( "type", 8 ),
YAML_SIGNED_CUST( "value", 8, in_read_weight, in_write_weight ),
YAML_END
};
static const struct YamlNode struct_MixData[] = {
YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ),
YAML_UNSIGNED( "destCh", 5 ),
YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ),
YAML_UNSIGNED( "carryTrim", 1 ),
YAML_UNSIGNED( "mixWarn", 2 ),
YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
YAML_PADDING( 1 ),
YAML_SIGNED_CUST( "offset", 13, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
YAML_STRUCT("curve", 16, struct_CurveRef, NULL),
YAML_UNSIGNED( "delayUp", 8 ),
YAML_UNSIGNED( "delayDown", 8 ),
YAML_UNSIGNED( "speedUp", 8 ),
YAML_UNSIGNED( "speedDown", 8 ),
YAML_STRING("name", 6),
YAML_END
};
static const struct YamlNode struct_LimitData[] = {
YAML_IDX,
YAML_SIGNED_CUST( "min", 11, in_read_weight, in_write_weight ),
YAML_SIGNED_CUST( "max", 11, in_read_weight, in_write_weight ),
YAML_SIGNED( "ppmCenter", 10 ),
YAML_SIGNED_CUST( "offset", 11, in_read_weight, in_write_weight ),
YAML_UNSIGNED( "symetrical", 1 ),
YAML_UNSIGNED( "revert", 1 ),
YAML_PADDING( 3 ),
YAML_SIGNED( "curve", 8 ),
YAML_STRING("name", 6),
YAML_END
};
static const struct YamlNode struct_ExpoData[] = {
YAML_UNSIGNED( "mode", 2 ),
YAML_UNSIGNED( "scale", 14 ),
YAML_CUSTOM("carryTrim",r_carryTrim,nullptr),
YAML_SIGNED( "trimSource", 6 ),
YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ),
YAML_UNSIGNED( "chn", 5 ),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ),
YAML_STRING("name", 6),
YAML_SIGNED_CUST( "offset", 8, in_read_weight, in_write_weight ),
YAML_STRUCT("curve", 16, struct_CurveRef, NULL),
YAML_END
};
static const struct YamlNode struct_CurveHeader[] = {
YAML_IDX,
YAML_UNSIGNED( "type", 1 ),
YAML_UNSIGNED( "smooth", 1 ),
YAML_SIGNED( "points", 6 ),
YAML_STRING("name", 3),
YAML_END
};
static const struct YamlNode struct_signed_8[] = {
YAML_IDX,
YAML_SIGNED( "val", 8 ),
YAML_END
};
static const struct YamlNode struct_LogicalSwitchData[] = {
YAML_IDX,
YAML_ENUM("func", 8, enum_LogicalSwitchesFunctions),
YAML_CUSTOM("def",r_logicSw,w_logicSw),
YAML_PADDING( 10 ),
YAML_PADDING( 10 ),
YAML_SIGNED_CUST( "andsw", 10, r_swtchSrc, w_swtchSrc ),
YAML_PADDING( 1 ),
YAML_PADDING( 1 ),
YAML_PADDING( 16 ),
YAML_UNSIGNED( "delay", 8 ),
YAML_UNSIGNED( "duration", 8 ),
YAML_END
};
static const struct YamlNode struct_SwashRingData[] = {
YAML_ENUM("type", 8, enum_SwashType),
YAML_UNSIGNED( "value", 8 ),
YAML_UNSIGNED_CUST( "collectiveSource", 8, r_mixSrcRaw, w_mixSrcRaw ),
YAML_UNSIGNED_CUST( "aileronSource", 8, r_mixSrcRaw, w_mixSrcRaw ),
YAML_UNSIGNED_CUST( "elevatorSource", 8, r_mixSrcRaw, w_mixSrcRaw ),
YAML_SIGNED( "collectiveWeight", 8 ),
YAML_SIGNED( "aileronWeight", 8 ),
YAML_SIGNED( "elevatorWeight", 8 ),
YAML_END
};
static const struct YamlNode struct_trim_t[] = {
YAML_IDX,
YAML_SIGNED( "value", 11 ),
YAML_UNSIGNED( "mode", 5 ),
YAML_END
};
static const struct YamlNode struct_FlightModeData[] = {
YAML_IDX,
YAML_ARRAY("trim", 16, 8, struct_trim_t, NULL),
YAML_STRING("name", 10),
YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
YAML_PADDING( 6 ),
YAML_UNSIGNED( "fadeIn", 8 ),
YAML_UNSIGNED( "fadeOut", 8 ),
YAML_ARRAY("gvars", 16, 9, struct_signed_16, gvar_is_active),
YAML_END
};
static const struct YamlNode struct_GVarData[] = {
YAML_IDX,
YAML_STRING("name", 3),
YAML_UNSIGNED( "min", 12 ),
YAML_UNSIGNED( "max", 12 ),
YAML_UNSIGNED( "popup", 1 ),
YAML_UNSIGNED( "prec", 1 ),
YAML_UNSIGNED( "unit", 2 ),
YAML_PADDING( 4 ),
YAML_END
};
static const struct YamlNode struct_VarioData[] = {
YAML_UNSIGNED_CUST( "source", 7, r_tele_sensor, w_tele_sensor ),
YAML_UNSIGNED( "centerSilent", 1 ),
YAML_SIGNED( "centerMax", 8 ),
YAML_SIGNED( "centerMin", 8 ),
YAML_SIGNED( "min", 8 ),
YAML_SIGNED( "max", 8 ),
YAML_END
};
static const struct YamlNode struct_RssiAlarmData[] = {
YAML_CUSTOM("disabled",r_rssiDisabled,nullptr),
YAML_CUSTOM("warning",r_rssiWarning,nullptr),
YAML_CUSTOM("critical",r_rssiCritical,nullptr),
YAML_END
};
static const struct YamlNode struct_RFAlarmData[] = {
YAML_SIGNED( "warning", 8 ),
YAML_SIGNED( "critical", 8 ),
YAML_END
};
static const struct YamlNode struct_PpmModule[] = {
YAML_SIGNED( "delay", 6 ),
YAML_UNSIGNED( "pulsePol", 1 ),
YAML_UNSIGNED( "outputType", 1 ),
YAML_SIGNED( "frameLength", 8 ),
YAML_END
};
static const struct YamlNode struct_anonymous_5[] = {
YAML_PADDING( 8 ),
YAML_UNSIGNED( "disableTelemetry", 1 ),
YAML_UNSIGNED( "disableMapping", 1 ),
YAML_UNSIGNED( "autoBindMode", 1 ),
YAML_UNSIGNED( "lowPowerMode", 1 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_PADDING( 2 ),
YAML_SIGNED( "optionValue", 8 ),
YAML_END
};
static const struct YamlNode struct_anonymous_6[] = {
YAML_UNSIGNED( "power", 2 ),
YAML_PADDING( 2 ),
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
YAML_SIGNED( "antennaMode", 2 ),
YAML_PADDING( 8 ),
YAML_END
};
static const struct YamlNode struct_anonymous_7[] = {
YAML_PADDING( 6 ),
YAML_UNSIGNED( "noninverted", 1 ),
YAML_PADDING( 1 ),
YAML_SIGNED( "refreshRate", 8 ),
YAML_END
};
static const struct YamlNode struct_string_64[] = {
YAML_IDX,
YAML_STRING("val", 8),
YAML_END
};
static const struct YamlNode struct_anonymous_8[] = {
YAML_UNSIGNED( "receivers", 7 ),
YAML_UNSIGNED( "racingMode", 1 ),
YAML_ARRAY("receiverName", 64, 3, struct_string_64, NULL),
YAML_END
};
static const struct YamlNode struct_anonymous_9[] = {
YAML_ARRAY("rx_id", 8, 4, struct_unsigned_8, NULL),
YAML_UNSIGNED( "mode", 3 ),
YAML_UNSIGNED( "rfPower", 1 ),
YAML_UNSIGNED( "reserved", 4 ),
YAML_ARRAY("rx_freq", 8, 2, struct_unsigned_8, NULL),
YAML_END
};
static const struct YamlNode struct_anonymous_10[] = {
YAML_UNSIGNED( "emi", 2 ),
YAML_UNSIGNED( "telemetry", 1 ),
YAML_UNSIGNED( "phyMode", 3 ),
YAML_UNSIGNED( "reserved", 2 ),
YAML_UNSIGNED( "rfPower", 8 ),
YAML_END
};
static const struct YamlNode struct_anonymous_11[] = {
YAML_UNSIGNED( "raw12bits", 1 ),
YAML_UNSIGNED( "telemetryBaudrate", 3 ),
YAML_PADDING( 4 ),
YAML_END
};
static const struct YamlNode struct_anonymous_12[] = {
YAML_UNSIGNED( "telemetryBaudrate", 3 ),
YAML_END
};
static const struct YamlNode struct_anonymous_13[] = {
YAML_UNSIGNED( "flags", 8 ),
YAML_END
};
static const struct YamlNode union_anonymous_4_elmts[] = {
YAML_ARRAY("raw", 8, 25, struct_unsigned_8, NULL),
YAML_STRUCT("ppm", 16, struct_PpmModule, NULL),
YAML_STRUCT("multi", 24, struct_anonymous_5, NULL),
YAML_STRUCT("pxx", 16, struct_anonymous_6, NULL),
YAML_STRUCT("sbus", 16, struct_anonymous_7, NULL),
YAML_STRUCT("pxx2", 200, struct_anonymous_8, NULL),
YAML_STRUCT("flysky", 56, struct_anonymous_9, NULL),
YAML_STRUCT("afhds3", 16, struct_anonymous_10, NULL),
YAML_STRUCT("ghost", 8, struct_anonymous_11, NULL),
YAML_STRUCT("crsf", 8, struct_anonymous_12, NULL),
YAML_STRUCT("dsmp", 8, struct_anonymous_13, NULL),
YAML_END
};
static const struct YamlNode struct_ModuleData[] = {
YAML_IDX,
YAML_UNSIGNED_CUST( "type", 8, r_moduleType, w_moduleType ),
YAML_CUSTOM("subType",r_modSubtype,w_modSubtype),
YAML_UNSIGNED( "channelsStart", 8 ),
YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ),
YAML_ENUM("failsafeMode", 4, enum_FailsafeModes),
YAML_PADDING( 4 ),
YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type),
YAML_END
};
static const struct YamlNode struct_TrainerModuleData[] = {
YAML_UNSIGNED_CUST( "mode", 8, r_trainerMode, w_trainerMode ),
YAML_UNSIGNED( "channelsStart", 8 ),
YAML_SIGNED( "channelsCount", 8 ),
YAML_SIGNED( "frameLength", 8 ),
YAML_SIGNED( "delay", 6 ),
YAML_UNSIGNED( "pulsePol", 1 ),
YAML_PADDING( 1 ),
YAML_END
};
static const struct YamlNode union_ScriptDataInput_elmts[] = {
YAML_SIGNED( "value", 16 ),
YAML_UNSIGNED_CUST( "source", 16, r_mixSrcRaw, w_mixSrcRaw ),
YAML_END
};
static const struct YamlNode union_ScriptDataInput[] = {
YAML_IDX,
YAML_UNION("u", 16, union_ScriptDataInput_elmts, select_script_input),
YAML_END
};
static const struct YamlNode struct_ScriptData[] = {
YAML_IDX,
YAML_STRING("file", 6),
YAML_STRING("name", 6),
YAML_ARRAY("inputs", 16, 6, union_ScriptDataInput, NULL),
YAML_END
};
static const struct YamlNode struct_string_32[] = {
YAML_IDX,
YAML_STRING("val", 4),
YAML_END
};
static const struct YamlNode union_anonymous_14_elmts[] = {
YAML_UNSIGNED( "id", 16 ),
YAML_UNSIGNED( "persistentValue", 16 ),
YAML_END
};
static const struct YamlNode struct_anonymous_16[] = {
YAML_UNSIGNED( "physID", 5 ),
YAML_UNSIGNED( "rxIndex", 3 ),
YAML_END
};
static const struct YamlNode union_anonymous_15_elmts[] = {
YAML_STRUCT("frskyInstance", 8, struct_anonymous_16, NULL),
YAML_UNSIGNED( "instance", 8 ),
YAML_ENUM("formula", 8, enum_TelemetrySensorFormula),
YAML_END
};
static const struct YamlNode struct_anonymous_18[] = {
YAML_UNSIGNED( "ratio", 16 ),
YAML_SIGNED( "offset", 16 ),
YAML_END
};
static const struct YamlNode struct_anonymous_19[] = {
YAML_UNSIGNED( "source", 8 ),
YAML_UNSIGNED( "index", 8 ),
YAML_PADDING( 16 ),
YAML_END
};
static const struct YamlNode struct_anonymous_20[] = {
YAML_ARRAY("sources", 8, 4, struct_signed_8, NULL),
YAML_END
};
static const struct YamlNode struct_anonymous_21[] = {
YAML_UNSIGNED( "source", 8 ),
YAML_PADDING( 24 ),
YAML_END
};
static const struct YamlNode struct_anonymous_22[] = {
YAML_UNSIGNED( "gps", 8 ),
YAML_UNSIGNED( "alt", 8 ),
YAML_PADDING( 16 ),
YAML_END
};
static const struct YamlNode union_anonymous_17_elmts[] = {
YAML_STRUCT("custom", 32, struct_anonymous_18, NULL),
YAML_STRUCT("cell", 32, struct_anonymous_19, NULL),
YAML_STRUCT("calc", 32, struct_anonymous_20, NULL),
YAML_STRUCT("consumption", 32, struct_anonymous_21, NULL),
YAML_STRUCT("dist", 32, struct_anonymous_22, NULL),
YAML_UNSIGNED( "param", 32 ),
YAML_END
};
static const struct YamlNode struct_TelemetrySensor[] = {
YAML_IDX,
YAML_UNION("id1", 16, union_anonymous_14_elmts, select_id1),
YAML_UNION("id2", 8, union_anonymous_15_elmts, select_id2),
YAML_STRING("label", 4),
YAML_UNSIGNED( "subId", 8 ),
YAML_ENUM("type", 1, enum_TelemetrySensorType),
YAML_PADDING( 1 ),
YAML_UNSIGNED( "unit", 6 ),
YAML_UNSIGNED( "prec", 2 ),
YAML_UNSIGNED( "autoOffset", 1 ),
YAML_UNSIGNED( "filter", 1 ),
YAML_UNSIGNED( "logs", 1 ),
YAML_UNSIGNED( "persistent", 1 ),
YAML_UNSIGNED( "onlyPositive", 1 ),
YAML_PADDING( 1 ),
YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg),
YAML_END
};
static const struct YamlNode union_ZoneOptionValue_elmts[] = {
YAML_UNSIGNED( "unsignedValue", 32 ),
YAML_SIGNED( "signedValue", 32 ),
YAML_UNSIGNED( "boolValue", 32 ),
YAML_STRING("stringValue", 8),
YAML_CUSTOM("source",r_zov_source,w_zov_source),
YAML_CUSTOM("color",r_zov_color,w_zov_color),
YAML_END
};
static const struct YamlNode struct_ZoneOptionValueTyped[] = {
YAML_IDX,
YAML_ENUM("type", 32, enum_ZoneOptionValueEnum),
YAML_UNION("value", 64, union_ZoneOptionValue_elmts, select_zov),
YAML_END
};
static const struct YamlNode struct_WidgetPersistentData[] = {
YAML_ARRAY("options", 96, 5, struct_ZoneOptionValueTyped, NULL),
YAML_END
};
static const struct YamlNode struct_ZonePersistentData[] = {
YAML_IDX,
YAML_STRING("widgetName", 12),
YAML_STRUCT("widgetData", 480, struct_WidgetPersistentData, NULL),
YAML_END
};
static const struct YamlNode struct_LayoutPersistentData[] = {
YAML_ARRAY("zones", 576, 10, struct_ZonePersistentData, NULL),
YAML_ARRAY("options", 96, 10, struct_ZoneOptionValueTyped, NULL),
YAML_END
};
static const struct YamlNode struct_CustomScreenData[] = {
YAML_IDX,
YAML_STRING("LayoutId", 12),
YAML_STRUCT("layoutData", 6720, struct_LayoutPersistentData, NULL),
YAML_END
};
static const struct YamlNode struct_TopBarPersistentData[] = {
YAML_ARRAY("zones", 576, 6, struct_ZonePersistentData, NULL),
YAML_ARRAY("options", 96, 1, struct_ZoneOptionValueTyped, NULL),
YAML_END
};
static const struct YamlNode struct_USBJoystickChData[] = {
YAML_IDX,
YAML_ENUM("mode", 3, enum_USBJoystickCh),
YAML_UNSIGNED( "inversion", 1 ),
YAML_UNSIGNED( "param", 4 ),
YAML_UNSIGNED( "btn_num", 5 ),
YAML_UNSIGNED( "switch_npos", 3 ),
YAML_END
};
static const struct YamlNode struct_ModelData[] = {
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_STRUCT("header", 1048, struct_ModelHeader, NULL),
YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL),
YAML_UNSIGNED( "telemetryProtocol", 3 ),
YAML_UNSIGNED( "thrTrim", 1 ),
YAML_UNSIGNED( "noGlobalFunctions", 1 ),
YAML_UNSIGNED( "displayTrims", 2 ),
YAML_UNSIGNED( "ignoreSensorIds", 1 ),
YAML_SIGNED( "trimInc", 3 ),
YAML_UNSIGNED( "disableThrottleWarning", 1 ),
YAML_UNSIGNED( "displayChecklist", 1 ),
YAML_UNSIGNED( "extendedLimits", 1 ),
YAML_UNSIGNED( "extendedTrims", 1 ),
YAML_UNSIGNED( "throttleReversed", 1 ),
YAML_UNSIGNED( "enableCustomThrottleWarning", 1 ),
YAML_UNSIGNED( "disableTelemetryWarning", 1 ),
YAML_UNSIGNED( "showInstanceIds", 1 ),
YAML_UNSIGNED( "checklistInteractive", 1 ),
YAML_ENUM("hatsMode", 2, enum_HatsMode),
YAML_PADDING( 2 ),
YAML_SIGNED( "customThrottleWarningPosition", 8 ),
YAML_UNSIGNED( "beepANACenter", 16 ),
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL),
YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL),
YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL),
YAML_ARRAY("points", 8, 512, struct_signed_8, NULL),
YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL),
YAML_ARRAY("customFn", 72, 64, struct_CustomFunctionData, cfn_is_active),
YAML_STRUCT("swashR", 64, struct_SwashRingData, swash_is_active),
YAML_ARRAY("flightModeData", 384, 9, struct_FlightModeData, fmd_is_active),
YAML_UNSIGNED_CUST( "thrTraceSrc", 8, r_thrSrc, w_thrSrc ),
YAML_CUSTOM("switchWarningState",r_swtchWarn,w_swtchWarn),
YAML_PADDING( 64 ),
YAML_ARRAY("gvars", 56, 9, struct_GVarData, NULL),
YAML_STRUCT("varioData", 40, struct_VarioData, NULL),
YAML_UNSIGNED_CUST( "rssiSource", 8, r_tele_sensor, w_tele_sensor ),
YAML_STRUCT("rssiAlarms", 0, struct_RssiAlarmData, NULL),
YAML_STRUCT("rfAlarms", 16, struct_RFAlarmData, NULL),
YAML_UNSIGNED( "thrTrimSw", 3 ),
YAML_ENUM("potsWarnMode", 2, enum_PotsWarnMode),
YAML_ENUM("jitterFilter", 2, enum_ModelOverridableEnable),
YAML_PADDING( 1 ),
YAML_ARRAY("moduleData", 232, 2, struct_ModuleData, NULL),
YAML_ARRAY("failsafeChannels", 16, 32, struct_signed_16, NULL),
YAML_STRUCT("trainerData", 40, struct_TrainerModuleData, NULL),
YAML_ARRAY("scriptsData", 192, 9, struct_ScriptData, NULL),
YAML_ARRAY("inputNames", 32, 32, struct_string_32, NULL),
YAML_UNSIGNED( "potsWarnEnabled", 16 ),
YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL),
YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL),
YAML_ARRAY("screenData", 6816, 10, struct_CustomScreenData, NULL),
YAML_STRUCT("topbarData", 3552, struct_TopBarPersistentData, NULL),
YAML_UNSIGNED( "view", 8 ),
YAML_STRING("modelRegistrationID", 8),
YAML_UNSIGNED( "usbJoystickExtMode", 1 ),
YAML_ENUM("usbJoystickIfMode", 3, enum_USBJoystickIfMode),
YAML_UNSIGNED( "usbJoystickCircularCut", 4 ),
YAML_ARRAY("usbJoystickCh", 16, 26, struct_USBJoystickChData, NULL),
YAML_ENUM("radioThemesDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("radioGFDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("radioTrainerDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("modelHeliDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("modelFMDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("modelCurvesDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("modelGVDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("modelLSDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("modelSFDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("modelCustomScriptsDisabled", 2, enum_ModelOverridableEnable),
YAML_ENUM("modelTelemetryDisabled", 2, enum_ModelOverridableEnable),
YAML_END
};
static const struct YamlNode struct_PartialModel[] = {
YAML_STRUCT("header", 1048, struct_ModelHeader, NULL),
YAML_ARRAY("timers", 136, 3, struct_TimerData, NULL),
YAML_END
};
#define MAX_RADIODATA_MODELDATA_PARTIALMODEL_STR_LEN 29
static const struct YamlNode __RadioData_root_node = YAML_ROOT( struct_RadioData );
const YamlNode* get_radiodata_nodes()
{
return &__RadioData_root_node;
}
static const struct YamlNode __ModelData_root_node = YAML_ROOT( struct_ModelData );
const YamlNode* get_modeldata_nodes()
{
return &__ModelData_root_node;
}
static const struct YamlNode __PartialModel_root_node = YAML_ROOT( struct_PartialModel );
const YamlNode* get_partialmodel_nodes()
{
return &__PartialModel_root_node;
}

View file

@ -22,17 +22,19 @@ option(DEBUG_USB_INTERRUPTS "Count individual USB interrupts" OFF)
option(DEBUG_TIMERS "Time critical parts of the code" OFF) option(DEBUG_TIMERS "Time critical parts of the code" OFF)
option(DEBUG_BLUETOOTH "Debug Bluetooth" OFF) option(DEBUG_BLUETOOTH "Debug Bluetooth" OFF)
# option to select the default internal module if(INTERNAL_MODULES)
#set(DEFAULT_INTERNAL_MODULE NONE CACHE STRING "Default internal module") # option to select the default internal module
set_property(CACHE DEFAULT_INTERNAL_MODULE PROPERTY STRINGS ${INTERNAL_MODULES}) #set(DEFAULT_INTERNAL_MODULE NONE CACHE STRING "Default internal module")
set_property(CACHE DEFAULT_INTERNAL_MODULE PROPERTY STRINGS ${INTERNAL_MODULES})
# define variables for internal modules # define variables for internal modules
foreach(module ${INTERNAL_MODULES}) foreach(module ${INTERNAL_MODULES})
set(INTERNAL_MODULE_${module} ON CACHE BOOL "Support for ${module} internal module") set(INTERNAL_MODULE_${module} ON CACHE BOOL "Support for ${module} internal module")
if (INTERNAL_MODULE_${module}) if (INTERNAL_MODULE_${module})
message("-- Adding support for ${module} as internal module") message("-- Adding support for ${module} as internal module")
endif() endif()
endforeach() endforeach()
endif()
if(INTERNAL_MODULE_PXX1) if(INTERNAL_MODULE_PXX1)
add_definitions(-DHARDWARE_INTERNAL_MODULE) add_definitions(-DHARDWARE_INTERNAL_MODULE)

View file

@ -69,8 +69,7 @@ if(DEBUG_SEGGER_RTT)
) )
endif() endif()
if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14 OR PCB STREQUAL PL18)
if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14)
set(BOOTLOADER_SRC set(BOOTLOADER_SRC
${BOOTLOADER_SRC} ${BOOTLOADER_SRC}
../../../../../gui/colorlcd/fonts.cpp ../../../../../gui/colorlcd/fonts.cpp
@ -79,7 +78,6 @@ if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14)
../../../../../thirdparty/libopenui/src/bitmapbuffer.cpp ../../../../../thirdparty/libopenui/src/bitmapbuffer.cpp
../../../../../thirdparty/libopenui/thirdparty/lz4/lz4.c ../../../../../thirdparty/libopenui/thirdparty/lz4/lz4.c
../../../../../targets/common/arm/stm32/dma2d.cpp ../../../../../targets/common/arm/stm32/dma2d.cpp
../../../../../targets/common/arm/stm32/diskio_sdio.cpp
../../../../../targets/common/arm/stm32/rtc_driver.cpp ../../../../../targets/common/arm/stm32/rtc_driver.cpp
../../../../../targets/common/arm/stm32/diskio_spi_flash.cpp ../../../../../targets/common/arm/stm32/diskio_spi_flash.cpp
../../../../../targets/common/arm/stm32/spi_flash.cpp ../../../../../targets/common/arm/stm32/spi_flash.cpp
@ -90,12 +88,22 @@ if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14)
../../../../../targets/${TARGET_DIR}/haptic_driver.cpp ../../../../../targets/${TARGET_DIR}/haptic_driver.cpp
) )
if(NOT PCB STREQUAL PL18)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
../../../../../targets/common/arm/stm32/diskio_sdio.cpp
)
else()
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
../../../../../targets/pl18/key_driver.cpp
)
endif()
# Add LVGL sources # Add LVGL sources
foreach(LVGL_FILE ${LVGL_SRC_FILES_MINIMAL}) foreach(LVGL_FILE ${LVGL_SRC_FILES_MINIMAL})
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} ../../../../../${LVGL_FILE}) set(BOOTLOADER_SRC ${BOOTLOADER_SRC} ../../../../../${LVGL_FILE})
endforeach() endforeach()
if(NOT PCB STREQUAL NV14) if(NOT (PCB STREQUAL NV14 OR PCB STREQUAL PL18))
set(BOOTLOADER_SRC set(BOOTLOADER_SRC
${BOOTLOADER_SRC} ${BOOTLOADER_SRC}
../../../../../targets/${TARGET_DIR}/led_driver.cpp ../../../../../targets/${TARGET_DIR}/led_driver.cpp

View file

@ -56,12 +56,17 @@
#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE) #define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE)
#if defined(EEPROM) #if defined(EEPROM) || defined(SPI_FLASH)
#define MAIN_MENU_LEN 3 #define MAIN_MENU_LEN 3
#else #else
#define MAIN_MENU_LEN 2 #define MAIN_MENU_LEN 2
#endif #endif
#if defined(SPI_FLASH)
#include "spi_flash.h"
#define SEL_CLEAR_FLASH_STORAGE_MENU_LEN 2
#endif
typedef void (*voidFunction)(void); typedef void (*voidFunction)(void);
#define jumpTo(addr) do { \ #define jumpTo(addr) do { \
@ -369,6 +374,10 @@ int bootloaderMain()
memoryType = MEM_EEPROM; memoryType = MEM_EEPROM;
state = ST_DIR_CHECK; state = ST_DIR_CHECK;
break; break;
#elif defined(SPI_FLASH)
case 1:
state = ST_CLEAR_FLASH_CHECK;
break;
#endif #endif
default: default:
if(vpos < bootloaderGetMenuItemCount(MAIN_MENU_LEN-1)) if(vpos < bootloaderGetMenuItemCount(MAIN_MENU_LEN-1))
@ -511,6 +520,35 @@ int bootloaderMain()
else if (memoryType == MEM_EEPROM && eepromWritten >= EEPROM_SIZE) { else if (memoryType == MEM_EEPROM && eepromWritten >= EEPROM_SIZE) {
state = ST_FLASH_DONE; // Backstop state = ST_FLASH_DONE; // Backstop
} }
#endif
#if defined(SPI_FLASH)
} else if (state == ST_CLEAR_FLASH_CHECK) {
bootloaderDrawScreen(state, vpos);
if (event == EVT_KEY_REPT(KEY_DOWN) || event == EVT_KEY_FIRST(KEY_DOWN)) {
if (vpos < SEL_CLEAR_FLASH_STORAGE_MENU_LEN - 1) { vpos++; }
continue;
}
if (event == EVT_KEY_REPT(KEY_UP) || event == EVT_KEY_FIRST(KEY_UP)) {
if (vpos > 0) { vpos--; }
continue;
}
if (event == EVT_KEY_LONG(KEY_ENTER) && vpos == 0)
{
state = ST_CLEAR_FLASH;
} else if (event == EVT_KEY_BREAK(KEY_EXIT) ||
(event == EVT_KEY_BREAK(KEY_ENTER) && vpos == 1) ) {
vpos = 0;
state = ST_START;
continue;
}
} else if (state == ST_CLEAR_FLASH) {
bootloaderDrawScreen(state, 0);
lcdRefresh();
if(event != EVT_KEY_BREAK(KEY_ENTER))
continue;
flashSpiEraseAll();
vpos = 0;
state = ST_START;
#endif #endif
} else if (state == ST_RADIO_MENU) { } else if (state == ST_RADIO_MENU) {
if(bootloaderRadioMenu(radioMenuItem, event)) if(bootloaderRadioMenu(radioMenuItem, event))
@ -565,6 +603,6 @@ int bootloaderMain()
return 0; return 0;
} }
#if !defined(SIMU) && (defined(PCBHORUS) || defined(PCBNV14)) #if !defined(SIMU) && (defined(PCBHORUS) || defined(PCBFLYSKY))
void *__dso_handle = nullptr; void *__dso_handle = nullptr;
#endif #endif

View file

@ -54,6 +54,10 @@ enum BootloaderState {
ST_FLASH_DONE, ST_FLASH_DONE,
ST_RESTORE_MENU, ST_RESTORE_MENU,
ST_USB, ST_USB,
#if defined(SPI_FLASH)
ST_CLEAR_FLASH_CHECK,
ST_CLEAR_FLASH,
#endif
ST_RADIO_MENU, ST_RADIO_MENU,
ST_REBOOT, ST_REBOOT,
}; };

View file

@ -30,6 +30,7 @@
#include "drivers/frftl.h" #include "drivers/frftl.h"
static FrFTL _frftl; static FrFTL _frftl;
static bool frftlInitDone = false;
static bool flashRead(uint32_t addr, uint8_t* buf, uint32_t len) static bool flashRead(uint32_t addr, uint8_t* buf, uint32_t len)
{ {
@ -89,6 +90,7 @@ static DSTATUS spi_flash_initialize(BYTE lun)
if (!ftlInit(&_frftl, &_frftl_cb, flashSizeMB)) { if (!ftlInit(&_frftl, &_frftl_cb, flashSizeMB)) {
return STA_NOINIT; return STA_NOINIT;
} }
frftlInitDone = true;
#endif #endif
return 0; return 0;
@ -102,7 +104,7 @@ static DSTATUS spi_flash_status (BYTE lun)
static DRESULT spi_flash_read(BYTE lun, BYTE * buff, DWORD sector, UINT count) static DRESULT spi_flash_read(BYTE lun, BYTE * buff, DWORD sector, UINT count)
{ {
#if defined(USE_FLASH_FTL) #if defined(USE_FLASH_FTL)
while(count) { while(frftlInitDone && count) {
if(!ftlRead(&_frftl, sector, (uint8_t*)buff)) { if(!ftlRead(&_frftl, sector, (uint8_t*)buff)) {
return RES_ERROR; return RES_ERROR;
@ -122,7 +124,7 @@ static DRESULT spi_flash_read(BYTE lun, BYTE * buff, DWORD sector, UINT count)
static DRESULT spi_flash_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count) static DRESULT spi_flash_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{ {
#if defined(USE_FLASH_FTL) #if defined(USE_FLASH_FTL)
if (!ftlWrite(&_frftl, sector, count, (uint8_t*)buff)) { if (frftlInitDone && !ftlWrite(&_frftl, sector, count, (uint8_t*)buff)) {
return RES_ERROR; return RES_ERROR;
} }
#else #else
@ -166,7 +168,7 @@ static DRESULT spi_flash_ioctl(BYTE lun, BYTE ctrl, void *buff)
case CTRL_SYNC: case CTRL_SYNC:
#if defined(USE_FLASH_FTL) #if defined(USE_FLASH_FTL)
if (!ftlSync(&_frftl)) { if (frftlInitDone && !ftlSync(&_frftl)) {
res = RES_ERROR; res = RES_ERROR;
} }
#else #else
@ -176,7 +178,7 @@ static DRESULT spi_flash_ioctl(BYTE lun, BYTE ctrl, void *buff)
case CTRL_TRIM: case CTRL_TRIM:
#if defined(USE_FLASH_FTL) #if defined(USE_FLASH_FTL)
if (!ftlTrim(&_frftl, *(DWORD*)buff, 1 + *((DWORD*)buff + 1) - *(DWORD*)buff)) { if (frftlInitDone && !ftlTrim(&_frftl, *(DWORD*)buff, 1 + *((DWORD*)buff + 1) - *(DWORD*)buff)) {
res = RES_ERROR; res = RES_ERROR;
} }
#endif #endif

View file

@ -38,9 +38,11 @@ void pwrInit()
#endif #endif
// Internal module power // Internal module power
#if defined(HARDWARE_INTERNAL_MODULE)
INTERNAL_MODULE_OFF(); INTERNAL_MODULE_OFF();
GPIO_InitStructure.GPIO_Pin = INTMODULE_PWR_GPIO_PIN; GPIO_InitStructure.GPIO_Pin = INTMODULE_PWR_GPIO_PIN;
GPIO_Init(INTMODULE_PWR_GPIO, &GPIO_InitStructure); GPIO_Init(INTMODULE_PWR_GPIO, &GPIO_InitStructure);
#endif
// External module power // External module power
EXTERNAL_MODULE_PWR_OFF(); EXTERNAL_MODULE_PWR_OFF();

View file

@ -223,10 +223,19 @@ static bool flash_read_sfdp(SpiFlashDescriptor* desc)
return true; return true;
} }
void flashSpiSync()
{
uint8_t status;
do {
flash_do_cmd(FLASH_CMD_STATUS, 0, &status, 1);
} while (status & 0x01);
}
bool flashSpiInit(void) bool flashSpiInit(void)
{ {
stm32_spi_init(&_flash_spi); stm32_spi_init(&_flash_spi);
delay_ms(1); delay_ms(1);
flashSpiSync();
if (!flash_read_id(&_flashDescriptor)) { if (!flash_read_id(&_flashDescriptor)) {
return false; return false;
@ -239,14 +248,6 @@ bool flashSpiInit(void)
return true; return true;
} }
void flashSpiSync()
{
uint8_t status;
do {
flash_do_cmd(FLASH_CMD_STATUS, 0, &status, 1);
} while (status & 0x01);
}
uint32_t flashSpiGetSize() uint32_t flashSpiGetSize()
{ {
return (1UL << _flashDescriptor.log2Size); return (1UL << _flashDescriptor.log2Size);

View file

@ -26,10 +26,11 @@
#include "opentx.h" #include "opentx.h"
#define ADC_COMMON ((ADC_Common_TypeDef *) ADC_BASE) #define ADC_COMMON ((ADC_Common_TypeDef *)ADC_BASE)
#define MAX_ADC_INPUTS 32
#define OVERSAMPLING 4 #define OVERSAMPLING 4
#define SAMPLING_TIMEOUT_US 500
// Please note that we use the same prio for DMA TC and ADC IRQs // Please note that we use the same prio for DMA TC and ADC IRQs
// to avoid issues with preemption between these 2 // to avoid issues with preemption between these 2
#define ADC_IRQ_PRIO configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY #define ADC_IRQ_PRIO configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
@ -43,7 +44,7 @@ static volatile uint32_t _adc_inhibit_mask;
static uint16_t _adc_dma_buffer[MAX_ADC_INPUTS] __DMA; static uint16_t _adc_dma_buffer[MAX_ADC_INPUTS] __DMA;
// ADCs started // ADCs started
static uint8_t _adc_started_mask; static volatile uint8_t _adc_started_mask;
static volatile uint8_t _adc_completed; static volatile uint8_t _adc_completed;
static const stm32_adc_t* _adc_ADCs; static const stm32_adc_t* _adc_ADCs;
@ -532,8 +533,14 @@ void stm32_hal_adc_wait_completion(const stm32_adc_t* ADCs, uint8_t n_ADC,
(void)inputs; (void)inputs;
(void)n_inputs; (void)n_inputs;
auto timeout = timersGetUsTick();
while(!_adc_completed) { while(!_adc_completed) {
// busy wait // busy wait
if ((uint32_t)(timersGetUsTick() - timeout) >= SAMPLING_TIMEOUT_US) {
TRACE("ADC timeout");
_adc_started_mask = 0;
return;
}
} }
} }
@ -572,8 +579,7 @@ static void _adc_chain_conversions(const stm32_adc_t* adc)
void stm32_hal_adc_dma_isr(const stm32_adc_t* adc) void stm32_hal_adc_dma_isr(const stm32_adc_t* adc)
{ {
// Disable IRQ // Disable IRQ
auto dma_stream = _dma_get_stream(adc->DMAx, adc->DMA_Stream); adc_dma_clear_flags(adc->DMAx, adc->DMA_Stream);
CLEAR_BIT(dma_stream->CR, DMA_SxCR_TCIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE);
uint16_t* dma_buffer = _adc_dma_buffer + adc->offset; uint16_t* dma_buffer = _adc_dma_buffer + adc->offset;
copy_adc_values(dma_buffer, adc, _adc_inputs); copy_adc_values(dma_buffer, adc, _adc_inputs);

View file

@ -24,6 +24,7 @@
#include "stm32_hal_ll.h" #include "stm32_hal_ll.h"
#include "hal/adc_driver.h" #include "hal/adc_driver.h"
#define MAX_ADC_INPUTS 32
struct stm32_adc_input_t { struct stm32_adc_input_t {
GPIO_TypeDef* GPIOx; GPIO_TypeDef* GPIOx;

View file

@ -50,6 +50,7 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DM, USB_GPIO_AF); GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DM, USB_GPIO_AF);
GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DP, USB_GPIO_AF); GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DP, USB_GPIO_AF);
#if defined(USB_GPIO_PIN_VBUS)
/* Configure VBUS Pin */ /* Configure VBUS Pin */
GPIO_InitStructure.GPIO_Pin = USB_GPIO_PIN_VBUS; GPIO_InitStructure.GPIO_Pin = USB_GPIO_PIN_VBUS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
@ -57,6 +58,7 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(USB_GPIO, &GPIO_InitStructure); GPIO_Init(USB_GPIO, &GPIO_InitStructure);
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ; RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ;

View file

@ -29,6 +29,8 @@
#include "stm32f2xx.h" #include "stm32f2xx.h"
#endif #endif
#include "hal.h"
/* USB Core and PHY interface configuration. /* USB Core and PHY interface configuration.
Tip: To avoid modifying these defines each time you need to change the USB Tip: To avoid modifying these defines each time you need to change the USB
configuration, you can declare the needed define in your toolchain configuration, you can declare the needed define in your toolchain
@ -97,7 +99,9 @@
#endif #endif
/****************** USB OTG MISC CONFIGURATION ********************************/ /****************** USB OTG MISC CONFIGURATION ********************************/
#if defined(USB_GPIO_PIN_VBUS)
#define VBUS_SENSING_ENABLED #define VBUS_SENSING_ENABLED
#endif
/****************** USB OTG MODE CONFIGURATION ********************************/ /****************** USB OTG MODE CONFIGURATION ********************************/
//#define USE_HOST_MODE //#define USE_HOST_MODE

View file

@ -57,6 +57,7 @@ void setSelectedUsbMode(int mode)
selectedUsbMode = usbMode(mode); selectedUsbMode = usbMode(mode);
} }
#if defined(USB_GPIO_PIN_VBUS)
int usbPlugged() int usbPlugged()
{ {
static uint8_t debouncedState = 0; static uint8_t debouncedState = 0;
@ -71,6 +72,7 @@ int usbPlugged()
return debouncedState; return debouncedState;
} }
#endif
USB_OTG_CORE_HANDLE USB_OTG_dev; USB_OTG_CORE_HANDLE USB_OTG_dev;

View file

@ -158,7 +158,6 @@ add_definitions(-DPCBHORUS -DSTM32F429_439xx -DSTM32F429xx -DSDRAM -DCCMRAM -DCO
add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK) add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK)
add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE}) add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE})
add_definitions(-DPWR_BUTTON_${PWR_BUTTON}) add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
add_definitions(-DHARDWARE_TRAINER_JACK)
add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS) add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS)
set(SDRAM ON) set(SDRAM ON)

View file

@ -19,7 +19,6 @@ set(BITMAPS_DIR 480x272)
set(HARDWARE_EXTERNAL_MODULE YES) set(HARDWARE_EXTERNAL_MODULE YES)
set(TARGET_DIR nv14) set(TARGET_DIR nv14)
add_definitions(-DHARDWARE_TRAINER_JACK)
set(RTC_BACKUP_RAM YES) set(RTC_BACKUP_RAM YES)
set(PPM_LIMITS_SYMETRICAL YES) set(PPM_LIMITS_SYMETRICAL YES)

View file

@ -38,7 +38,6 @@
#include "flysky_gimbal_driver.h" #include "flysky_gimbal_driver.h"
#include "timers_driver.h" #include "timers_driver.h"
#include "lcd_driver.h"
#include "lcd_driver.h" #include "lcd_driver.h"
#include "battery_driver.h" #include "battery_driver.h"
#include "touch_driver.h" #include "touch_driver.h"
@ -73,7 +72,8 @@ void delay_self(int count)
for (; count > 0; count--); for (; count > 0; count--);
} }
} }
#define RCC_AHB1PeriphMinimum (PWR_RCC_AHB1Periph |\
#define RCC_AHB1PeriphMinimum (PWR_RCC_AHB1Periph | \
LCD_RCC_AHB1Periph |\ LCD_RCC_AHB1Periph |\
BACKLIGHT_RCC_AHB1Periph |\ BACKLIGHT_RCC_AHB1Periph |\
SDRAM_RCC_AHB1Periph \ SDRAM_RCC_AHB1Periph \

View file

@ -115,25 +115,17 @@ extern HardwareOptions hardwareOptions;
#endif // defined(SIMU) #endif // defined(SIMU)
#define EXTERNAL_MODULE_PWR_OFF EXTERNAL_MODULE_OFF #define EXTERNAL_MODULE_PWR_OFF EXTERNAL_MODULE_OFF
#define IS_UART_MODULE(port) (port == INTERNAL_MODULE)
#define IS_PXX2_INTERNAL_ENABLED() (false)
#if !defined(NUM_FUNCTIONS_SWITCHES) #if !defined(NUM_FUNCTIONS_SWITCHES)
#define NUM_FUNCTIONS_SWITCHES 0 #define NUM_FUNCTIONS_SWITCHES 0
#endif #endif
#define NUM_TRIMS_KEYS (NUM_TRIMS * 2)
#define DEFAULT_STICK_DEADZONE 2 #define DEFAULT_STICK_DEADZONE 2
// 2 pots without detent
#define DEFAULT_POTS_CONFIG \
(POT_WITHOUT_DETENT << 0) + \
(POT_WITHOUT_DETENT << 2)
#define BATTERY_WARN 36 // 3.6V #define BATTERY_WARN 36 // 3.6V
#define BATTERY_MIN 35 // 3.5V #define BATTERY_MIN 35 // 3.5V
#define BATTERY_MAX 42 // 4.2V #define BATTERY_MAX 42 // 4.2V
#define BATTERY_DIVIDER 2942
#if defined(__cplusplus) && !defined(SIMU) #if defined(__cplusplus) && !defined(SIMU)
extern "C" { extern "C" {
@ -275,6 +267,4 @@ bool touchPanelEventOccured();
struct TouchState touchPanelRead(); struct TouchState touchPanelRead();
struct TouchState getInternalTouchState(); struct TouchState getInternalTouchState();
#define BATTERY_DIVIDER 2942
#endif // _BOARD_H_ #endif // _BOARD_H_

View file

@ -0,0 +1,167 @@
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)
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
set(CPU_TYPE STM32F4)
set(HSE_VALUE 12000000)
set(SDCARD YES)
set(STORAGE_MODELSLIST YES)
set(HAPTIC YES)
set(GUI_DIR colorlcd)
set(BITMAPS_DIR 480x272)
set(TARGET_DIR pl18)
set(LINKER_SCRIPT targets/pl18/stm32f4_flash.ld)
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(WIRELESS_CHARGER YES)
#option(STICKS_DEAD_ZONE "Enable sticks dead zone" YES)
#option(AFHDS2 "Support for AFHDS2" OFF)
# for size report script
set(CPU_TYPE_FULL STM32F429xI)
set(TARGET_LINKER_DIR stm32f429_sdram)
set(TARGET_LINKER_PARAMS "-Wl,--defsym=__SDRAM_START__=0xC0000000")
set(SIZE_TARGET_MEM_DEFINE "MEM_SIZE_SDRAM1=8192")
#set(RF_BAUD_RATE 921600 230400 115200 57600 38400 19200 9600 4800 2400 1200)
#set(PCB_RF_BAUD 921600 CACHE STRING "INTERNAL_MODULE_BAUDRATE: ${RF_BAUD_RATE}")
#set_property(CACHE PCB_RF_BAUD PROPERTY STRINGS ${RF_BAUD_RATE})
add_definitions(-DPCBPL18 -DPCBFLYSKY)
add_definitions(-DBATTERY_CHARGE)
add_definitions(-DSOFTWARE_VOLUME)
add_definitions(-DSPI_FLASH)
add_definitions(-DSTM32_SUPPORT_32BIT_TIMERS)
if(PCBREV STREQUAL PL18EV)
set(FLAVOUR pl18ev)
add_definitions(-DRADIO_PL18EV)
else()
set(FLAVOUR pl18)
add_definitions(-DRADIO_PL18)
# Defines internal modules for PL18 via UART7
set(INTERNAL_MODULES MULTI CACHE STRING "Internal modules")
set(DEFAULT_INTERNAL_MODULE MULTIMODULE CACHE STRING "Default internal module")
endif()
set(BITMAPS_TARGET pl18_bitmaps)
set(FONTS_TARGET x12_fonts)
set(LCD_DRIVER lcd_driver.cpp)
set(TOUCH_DRIVER touch_driver.cpp)
set(HARDWARE_TOUCH YES)
set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} ${BITMAPS_TARGET})
set(FIRMWARE_DEPENDENCIES datacopy)
set(HARDWARE_TOUCH ON)
set(SOFTWARE_KEYBOARD ON)
set(FLYSKY_GIMBAL ON)
add_definitions(
-DSTM32F429_439xx -DSTM32F429xx
-DSDRAM -DCCMRAM -DCOLORLCD -DLIBOPENUI
-DHARDWARE_TOUCH -DHARDWARE_KEYS
-DSOFTWARE_KEYBOARD -DUSE_HATS_AS_KEYS)
set(SDRAM ON)
add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK)
add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE})
add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
add_definitions(-DCROSSFIRE_NATIVE)
add_definitions(-DHARDWARE_EXTERNAL_MODULE)
if(WIRELESS_CHARGER)
add_definitions(-DWIRELESS_CHARGER)
endif()
if(STICKS_DEAD_ZONE)
add_definitions(-DSTICK_DEAD_ZONE)
endif()
if(NOT UNEXPECTED_SHUTDOWN)
add_definitions(-DNO_UNEXPECTED_SHUTDOWN)
endif()
set(AFHDS3 ON)
# VCP CLI
set(ENABLE_SERIAL_PASSTHROUGH ON CACHE BOOL "Enable serial passthrough")
set(CLI ON CACHE BOOL "Enable CLI")
include_directories(${RADIO_SRC_DIR}/fonts/colorlcd gui/${GUI_DIR} gui/${GUI_DIR}/layouts)
file(GLOB THEMES_SRC RELATIVE ${RADIO_SRC_DIR}/gui/colorlcd ${RADIO_SRC_DIR}/gui/colorlcd/themes/*.cpp)
file(GLOB LAYOUTS_SRC RELATIVE ${RADIO_SRC_DIR}/gui/colorlcd ${RADIO_SRC_DIR}/gui/colorlcd/layouts/*.cpp)
file(GLOB WIDGETS_SRC RELATIVE ${RADIO_SRC_DIR}/gui/colorlcd ${RADIO_SRC_DIR}/gui/colorlcd/widgets/*.cpp)
set(SRC
${SRC}
io/frsky_firmware_update.cpp
)
set(GVAR_SCREEN model_gvars.cpp)
if(BOOTLOADER)
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
../common/arm/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()
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
${LCD_DRIVER}
${TOUCH_DRIVER}
board.cpp
key_driver.cpp
battery_driver.cpp
backlight_driver.cpp
led_driver.cpp
sdram_driver.c
)
set(FIRMWARE_SRC
${FIRMWARE_SRC}
targets/common/arm/stm32/audio_dac_driver.cpp
targets/common/arm/stm32/dma2d.cpp
targets/common/arm/stm32/spi_flash.cpp
targets/common/arm/stm32/diskio_spi_flash.cpp
targets/common/arm/stm32/stm32_ws2812.cpp
boards/generic_stm32/rgb_leds.cpp
drivers/frftl.cpp
)
# Make malloc() thread-safe
add_definitions(-DTHREADSAFE_MALLOC)
set(STM32LIB_SRC
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_sdio.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_fmc.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_ltdc.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_tim.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma2d.c
)

View file

@ -0,0 +1,95 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx_types.h"
#include "board.h"
#include "globals.h"
#include "lcd_driver.h"
void backlightLowInit( void )
{
RCC_AHB1PeriphClockCmd(BACKLIGHT_RCC_AHB1Periph, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = BACKLIGHT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(BACKLIGHT_GPIO, &GPIO_InitStructure);
GPIO_WriteBit( BACKLIGHT_GPIO, BACKLIGHT_GPIO_PIN, Bit_RESET );
}
void backlightInit()
{
// PIN init
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = BACKLIGHT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(BACKLIGHT_GPIO, &GPIO_InitStructure);
GPIO_PinAFConfig(BACKLIGHT_GPIO, BACKLIGHT_GPIO_PinSource, BACKLIGHT_GPIO_AF);
// TODO review this when the timer will be chosen
BACKLIGHT_TIMER->ARR = 100;
BACKLIGHT_TIMER->PSC = BACKLIGHT_TIMER_FREQ / 1000000 - 1; // 10kHz (same as FrOS)
BACKLIGHT_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE; // PWM mode 1
BACKLIGHT_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE;
BACKLIGHT_TIMER->CCR1 = 100; // 100% on init
BACKLIGHT_TIMER->EGR = TIM_EGR_UG;
BACKLIGHT_TIMER->CR1 |= TIM_CR1_CEN; // Counter enable
BACKLIGHT_TIMER->BDTR |= TIM_BDTR_MOE;
}
uint8_t lastDutyCycle = 0;
void backlightEnable(uint8_t dutyCycle)
{
BACKLIGHT_TIMER->CCR1 = dutyCycle;
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;
}

View file

@ -0,0 +1,436 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
#include "battery_driver.h"
#define __BATTERY_DRIVER_C__
#define BATTERY_W 140
#define BATTERY_H 200
#define BATTERY_TOP ((LCD_H - BATTERY_H)/2)
#define BATTERY_CONNECTOR_W 32
#define BATTERY_CONNECTOR_H 10
#define BATTERY_BORDER 4
#define BATTERY_W_INNER (BATTERY_W - 2*BATTERY_BORDER)
#define BATTERY_H_INNER (BATTERY_H - 2*BATTERY_BORDER)
#define BATTERY_TOP_INNER (BATTERY_TOP + BATTERY_BORDER)
#define UCHARGER_SAMPLING_CNT 10
#define UCHARGER_CHARGING_SAMPLING_CNT 10
#define WCHARGER_SAMPLING_CNT 30
#define WCHARGER_CHARGING_SAMPLING_CNT 10
#define WCHARGER_LOW_CURRENT_DELAY_CNT 6000
#define WCHARGER_HIGH_CURRENT_DELAY_CNT 24000
typedef struct
{
bool hasCharger : 1;
bool isChargeEnd : 1;
bool isChargerDetectionReady : 1;
bool isChargingDetectionReady : 1;
bool isHighCurrent : 1;
uint8_t chargerSamplingCount;
uint8_t chargingSamplingCount;
uint8_t chargeEndSamplingCount;
} STRUCT_BATTERY_CHARGER;
STRUCT_BATTERY_CHARGER uCharger; // USB charger
#if defined(WIRELESS_CHARGER)
STRUCT_BATTERY_CHARGER wCharger; // Wireless charger
uint16_t wirelessLowCurrentDelay = 0;
uint16_t wirelessHighCurrentDelay = 0;
#endif
void chargerDetection(STRUCT_BATTERY_CHARGER* charger, uint8_t chargerPinActive, uint8_t samplingCountThreshold)
{
if ((charger->hasCharger && chargerPinActive) || (!charger->hasCharger && !chargerPinActive))
{
charger->chargerSamplingCount = 0;
}
else
{
charger->chargerSamplingCount++;
if (charger->chargerSamplingCount >= samplingCountThreshold)
{
charger->chargerSamplingCount = 0;
charger->hasCharger = !charger->hasCharger;
charger->isChargerDetectionReady = true;
}
}
}
void resetChargeEndDetection(STRUCT_BATTERY_CHARGER* charger)
{
charger->isChargeEnd = false;
charger->isChargingDetectionReady = false;
charger->chargingSamplingCount = 0;
charger->isHighCurrent = false;
}
void chargeEndDetection(STRUCT_BATTERY_CHARGER* charger, uint8_t chargeEndPinActive, uint8_t samplingCountThreshold)
{
if (charger->isChargeEnd)
{
if (chargeEndPinActive)
{
charger->chargingSamplingCount = 0;
if (charger->isChargingDetectionReady)
{
charger->chargeEndSamplingCount = 0;
}
else
{
charger->chargeEndSamplingCount++;
if (charger->chargeEndSamplingCount >= samplingCountThreshold)
{
charger->chargeEndSamplingCount = 0;
charger->isChargingDetectionReady = true;
}
}
}
else
{
charger->chargeEndSamplingCount = 0;
charger->chargingSamplingCount++;
if (charger->chargingSamplingCount >= samplingCountThreshold)
{
charger->chargingSamplingCount = 0;
charger->isChargeEnd = false;
charger->isChargingDetectionReady = true;
}
}
}
else
{
if (!chargeEndPinActive)
{
charger->chargeEndSamplingCount = 0;
if (charger->isChargingDetectionReady)
{
charger->chargingSamplingCount = 0;
}
else
{
charger->chargingSamplingCount++;
if (charger->chargingSamplingCount >= samplingCountThreshold)
{
charger->chargingSamplingCount = 0;
charger->isChargingDetectionReady = true;
}
}
}
else
{
charger->chargingSamplingCount = 0;
charger->chargeEndSamplingCount++;
if (charger->chargeEndSamplingCount >= samplingCountThreshold)
{
charger->chargeEndSamplingCount = 0;
charger->isChargeEnd = true;
charger->isChargingDetectionReady = true;
}
}
}
}
uint16_t get_battery_charge_state()
{
uint16_t state = CHARGE_UNKNOWN;
chargerDetection(&uCharger, IS_UCHARGER_ACTIVE(), UCHARGER_SAMPLING_CNT);
if (uCharger.isChargerDetectionReady)
{
if (uCharger.hasCharger) // USB charger can be detected properly no matter it is enabled or not
{
ENABLE_UCHARGER();
chargeEndDetection(&uCharger, IS_UCHARGER_CHARGE_END_ACTIVE(), UCHARGER_CHARGING_SAMPLING_CNT);
if (uCharger.isChargingDetectionReady)
{
if (uCharger.isChargeEnd)
{
state = CHARGE_FINISHED;
}
else
{
state = CHARGE_STARTED;
}
}
}
else
{
resetChargeEndDetection(&uCharger);
// Disable USB charger if it is not present, so that wireless charger can be detected properly
DISABLE_UCHARGER();
}
}
#if defined(WIRELESS_CHARGER)
chargerDetection(&wCharger, IS_WCHARGER_ACTIVE(), WCHARGER_SAMPLING_CNT);
if (wCharger.isChargerDetectionReady)
{
if (wCharger.hasCharger) // Wireless charger can only be detected when USB charger is disabled
{
chargeEndDetection(&wCharger, IS_WCHARGER_CHARGE_END_ACTIVE(), WCHARGER_CHARGING_SAMPLING_CNT);
if (wCharger.isChargingDetectionReady)
{
if (wCharger.isChargeEnd)
{
state = CHARGE_FINISHED;
}
else
{
state = CHARGE_STARTED;
}
}
// Charge current control
wirelessLowCurrentDelay = 0;
if (wirelessHighCurrentDelay >= WCHARGER_HIGH_CURRENT_DELAY_CNT)
{
wCharger.isHighCurrent = true;
WCHARGER_CURRENT_HIGH();
}
else
{
wirelessHighCurrentDelay++;
}
}
else
{
resetChargeEndDetection(&wCharger);
// Charge current control
wirelessHighCurrentDelay = 0;
if (wirelessLowCurrentDelay >= WCHARGER_LOW_CURRENT_DELAY_CNT)
{
wCharger.isHighCurrent = false;
WCHARGER_CURRENT_LOW();
}
else
{
wirelessLowCurrentDelay++;
}
}
}
#endif
return state;
}
bool isChargerActive()
{
#if defined(WIRELESS_CHARGER)
while (!(uCharger.isChargerDetectionReady && wCharger.isChargerDetectionReady))
{
get_battery_charge_state();
delay_ms(10);
}
return uCharger.hasCharger || wCharger.hasCharger;
#else
while (!uCharger.isChargerDetectionReady)
{
get_battery_charge_state();
delay_ms(10);
}
return uCharger.hasCharger;
#endif
}
void battery_charge_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
// Input pins
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// USB charger status pins
GPIO_InitStructure.GPIO_Pin = UCHARGER_GPIO_PIN;
GPIO_Init(UCHARGER_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = UCHARGER_CHARGE_END_GPIO_PIN;
GPIO_Init(UCHARGER_CHARGE_END_GPIO, &GPIO_InitStructure);
#if defined(WIRELESS_CHARGER)
// Wireless charger status pins
GPIO_InitStructure.GPIO_Pin = WCHARGER_GPIO_PIN;
GPIO_Init(WCHARGER_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = WCHARGER_CHARGE_END_GPIO_PIN;
GPIO_Init(WCHARGER_CHARGE_END_GPIO, &GPIO_InitStructure);
#endif
// Output pins
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
// USB charger control pins
GPIO_InitStructure.GPIO_Pin = UCHARGER_EN_GPIO_PIN;
GPIO_Init(UCHARGER_EN_GPIO, &GPIO_InitStructure);
// USB charger state init
ENABLE_UCHARGER();
uCharger.hasCharger = !IS_UCHARGER_ACTIVE(); // Init for sampling count works
uCharger.isChargerDetectionReady = false;
resetChargeEndDetection(&uCharger);
#if defined(WIRELESS_CHARGER)
// Wireless charger control pins
GPIO_InitStructure.GPIO_Pin = WCHARGER_EN_GPIO_PIN;
GPIO_Init(WCHARGER_EN_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = WCHARGER_I_CONTROL_GPIO_PIN;
GPIO_Init(WCHARGER_I_CONTROL_GPIO, &GPIO_InitStructure);
// Wireless charger state init
ENABLE_WCHARGER();
WCHARGER_CURRENT_LOW();
wCharger.hasCharger = !IS_WCHARGER_ACTIVE(); // Init for sampling count works
wCharger.isChargerDetectionReady = false;
resetChargeEndDetection(&wCharger);
#endif
}
void drawChargingInfo(uint16_t chargeState) {
static int progress = 0;
const char* text = chargeState == CHARGE_STARTED ? STR_BATTERYCHARGING : STR_BATTERYFULL;
int h = 0;
LcdFlags color = 0;
if (CHARGE_STARTED == chargeState)
{
if (progress >= 100)
{
progress = 0;
}
else
{
progress += 25;
}
text = STR_BATTERYCHARGING;
h = ((BATTERY_H_INNER * progress) / 100);
color = COLOR_THEME_EDIT;
}
else if (CHARGE_FINISHED == chargeState)
{
text = STR_BATTERYFULL;
h = BATTERY_H_INNER;
color = COLOR_THEME_EDIT;
}
else
{
text = STR_BATTERYNONE;
h = BATTERY_H_INNER;
color = COLOR_THEME_PRIMARY1;
}
BACKLIGHT_ENABLE();
lcd->drawSizedText(LCD_W / 2, LCD_H - 50, text, strlen(text), CENTERED | COLOR_THEME_PRIMARY2);
lcd->drawFilledRect((LCD_W - BATTERY_W) / 2, BATTERY_TOP, BATTERY_W, BATTERY_H, SOLID, COLOR_THEME_PRIMARY2);
lcd->drawFilledRect((LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER, BATTERY_W_INNER, BATTERY_H_INNER, SOLID, COLOR_THEME_PRIMARY1);
lcd->drawFilledRect((LCD_W - BATTERY_W_INNER) / 2, BATTERY_TOP_INNER + BATTERY_H_INNER - h, BATTERY_W_INNER, h, SOLID, color);
lcd->drawFilledRect((LCD_W - BATTERY_CONNECTOR_W) / 2, BATTERY_TOP - BATTERY_CONNECTOR_H, BATTERY_CONNECTOR_W, BATTERY_CONNECTOR_H, SOLID, COLOR_THEME_PRIMARY2);
}
#define CHARGE_INFO_DURATION 500
//this method should be called by timer interrupt or by GPIO interrupt
void handle_battery_charge(uint32_t last_press_time)
{
#if !defined(SIMU)
static uint32_t updateTime = 0;
static uint16_t lastState = CHARGE_UNKNOWN;
static uint32_t info_until = 0;
static bool lcdInited = false;
uint32_t now = get_tmr10ms();
uint16_t chargeState = get_battery_charge_state();
if (chargeState != CHARGE_UNKNOWN) {
if (lastState != chargeState) {
//avoid positive check when none and unknown
if (lastState + chargeState > 1) {
//charge state changed - last state known
info_until = now + (CHARGE_INFO_DURATION);
}
}
//power buttons pressed
else if (now - last_press_time < POWER_ON_DELAY) {
info_until = now + CHARGE_INFO_DURATION;
}
lastState = chargeState;
}
if(now > info_until) {
info_until = 0;
lcd->clear();
BACKLIGHT_DISABLE();
if(lcdInited) {
lcdOff();
}
return;
}
if (updateTime == 0 || ((get_tmr10ms() - updateTime) >= 50))
{
if (!lcdInited) {
backlightInit();
lcdInit();
lcdInitDisplayDriver();
lcdInited = true;
}
else {
lcdOn();
}
updateTime = get_tmr10ms();
lcdInitDirectDrawing();
lcd->clear();
drawChargingInfo(chargeState);
// DEBUG INFO
#if 0
char buffer[1024];
sprintf(buffer, "%d,%d,%d,%d", uCharger.isChargerDetectionReady, uCharger.hasCharger, IS_UCHARGER_ACTIVE(), uCharger.chargerSamplingCount);
lcd->drawSizedText(100, 10, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2);
sprintf(buffer, "%d,%d,%d,%d,%d,", uCharger.isChargingDetectionReady, uCharger.isChargeEnd, IS_UCHARGER_CHARGE_END_ACTIVE(), uCharger.chargingSamplingCount, uCharger.chargeEndSamplingCount);
lcd->drawSizedText(100, 40, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2);
sprintf(buffer, "%d,%d,%d,%d,%d", wCharger.isChargerDetectionReady, wCharger.hasCharger, IS_WCHARGER_ACTIVE(), wCharger.chargerSamplingCount, wCharger.isHighCurrent);
lcd->drawSizedText(100, 70, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2);
sprintf(buffer, "%d,%d,%d,%d,%d,", wCharger.isChargingDetectionReady, wCharger.isChargeEnd, IS_WCHARGER_CHARGE_END_ACTIVE(), wCharger.chargingSamplingCount, wCharger.chargeEndSamplingCount);
lcd->drawSizedText(100, 100, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2);
sprintf(buffer, "%d", isChargerActive());
lcd->drawSizedText(100, 130, buffer, strlen(buffer), CENTERED | COLOR_THEME_PRIMARY2);
#endif
lcdRefresh();
}
#endif
}

View file

@ -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.
*/
/***************************************************************************************************
***************************************************************************************************/
#ifndef __BATTERY_DRIVER_H__
#define __BATTERY_DRIVER_H__
/***************************************************************************************************
***************************************************************************************************/
#include "board.h"
#include "hal.h"
enum ChargeState
{
CHARGE_UNKNOWN,
CHARGE_NONE,
CHARGE_STARTED,
CHARGE_FINISHED
};
#define IS_UCHARGER_ACTIVE() GPIO_ReadInputDataBit(UCHARGER_GPIO, UCHARGER_GPIO_PIN)
#define IS_UCHARGER_CHARGE_END_ACTIVE() GPIO_ReadInputDataBit(UCHARGER_CHARGE_END_GPIO, UCHARGER_CHARGE_END_GPIO_PIN)
#define ENABLE_UCHARGER() GPIO_SetBits(UCHARGER_EN_GPIO, UCHARGER_EN_GPIO_PIN)
#define DISABLE_UCHARGER() GPIO_ResetBits(UCHARGER_EN_GPIO, UCHARGER_EN_GPIO_PIN)
#define IS_WCHARGER_ACTIVE() GPIO_ReadInputDataBit(WCHARGER_GPIO, WCHARGER_GPIO_PIN)
#define IS_WCHARGER_CHARGE_END_ACTIVE() GPIO_ReadInputDataBit(WCHARGER_CHARGE_END_GPIO, WCHARGER_CHARGE_END_GPIO_PIN)
#define ENABLE_WCHARGER() GPIO_SetBits(WCHARGER_EN_GPIO, WCHARGER_EN_GPIO_PIN)
#define DISABLE_WCHARGER() GPIO_ResetBits(WCHARGER_EN_GPIO, WCHARGER_EN_GPIO_PIN)
#define WCHARGER_CURRENT_LOW() GPIO_ResetBits(WCHARGER_I_CONTROL_GPIO, WCHARGER_I_CONTROL_GPIO_PIN)
#define WCHARGER_CURRENT_HIGH() GPIO_SetBits(WCHARGER_I_CONTROL_GPIO, WCHARGER_I_CONTROL_GPIO_PIN)
extern void battery_charge_init();
extern void handle_battery_charge(uint32_t last_press_time);
extern uint16_t get_battery_charge_state();
extern uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps
extern bool isChargerActive();
#endif

View file

@ -0,0 +1,261 @@
/*
* 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_ws2812.h"
#include "boards/generic_stm32/rgb_leds.h"
#include "board.h"
#include "boards/generic_stm32/module_ports.h"
#include "hal/adc_driver.h"
#include "hal/trainer_driver.h"
#include "hal/switch_driver.h"
#include "hal/abnormal_reboot.h"
#include "hal/watchdog_driver.h"
#include "globals.h"
#include "sdcard.h"
#include "touch.h"
#include "debug.h"
#include "flysky_gimbal_driver.h"
#include "timers_driver.h"
#include "battery_driver.h"
#include "touch_driver.h"
#include "bitmapbuffer.h"
#include "colors.h"
#include <string.h>
#if defined(__cplusplus) && !defined(SIMU)
extern "C" {
#endif
#include "usb_dcd_int.h"
#include "usb_bsp.h"
#if defined(__cplusplus) && !defined(SIMU)
}
#endif
// common ADC driver
extern const etx_hal_adc_driver_t _adc_driver;
#if defined(SEMIHOSTING)
extern "C" void initialise_monitor_handles();
#endif
#if defined(SPI_FLASH)
extern "C" void flushFTL();
#endif
void delay_self(int count)
{
for (int i = 50000; i > 0; i--)
{
for (; count > 0; count--);
}
}
#define RCC_AHB1PeriphMinimum (PWR_RCC_AHB1Periph |\
LCD_RCC_AHB1Periph |\
BACKLIGHT_RCC_AHB1Periph |\
SDRAM_RCC_AHB1Periph \
)
#define RCC_AHB1PeriphOther (AUDIO_RCC_AHB1Periph |\
TELEMETRY_RCC_AHB1Periph |\
TRAINER_RCC_AHB1Periph |\
HAPTIC_RCC_AHB1Periph |\
EXTMODULE_RCC_AHB1Periph \
)
#define RCC_AHB3PeriphMinimum (SDRAM_RCC_AHB3Periph)
#define RCC_APB1PeriphMinimum (BACKLIGHT_RCC_APB1Periph)
#define RCC_APB1PeriphOther (TELEMETRY_RCC_APB1Periph |\
AUDIO_RCC_APB1Periph \
)
#define RCC_APB2PeriphMinimum (LCD_RCC_APB2Periph)
#define RCC_APB2PeriphOther (HAPTIC_RCC_APB2Periph)
void boardInit()
{
#if defined(SEMIHOSTING)
initialise_monitor_handles();
#endif
#if !defined(SIMU)
RCC_AHB1PeriphClockCmd(RCC_AHB1PeriphMinimum | RCC_AHB1PeriphOther, ENABLE);
RCC_AHB3PeriphClockCmd(RCC_AHB3PeriphMinimum, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1PeriphMinimum | RCC_APB1PeriphOther, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2PeriphMinimum | RCC_APB2PeriphOther, ENABLE);
// enable interrupts
__enable_irq();
#endif
#if defined(DEBUG)
serialSetMode(SP_AUX1, UART_MODE_DEBUG); // indicate AUX1 is used
serialInit(SP_AUX1, UART_MODE_DEBUG); // early AUX1 init
#endif
TRACE("\nPL18 board started :)");
delay_ms(10);
TRACE("RCC->CSR = %08x", RCC->CSR);
pwrInit();
boardInitModulePorts();
init_trainer();
battery_charge_init();
flysky_gimbal_init();
timersInit();
touchPanelInit();
usbInit();
extern const stm32_pulse_timer_t _led_timer;
ws2812_init(&_led_timer, LED_STRIP_LENGTH);
for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) {
ws2812_set_color(i, 0, 0, 0);
}
ws2812_update(&_led_timer);
uint32_t press_start = 0;
uint32_t press_end = 0;
if (UNEXPECTED_SHUTDOWN()) {
pwrOn();
} else if (isChargerActive()) {
while (true) {
pwrOn();
uint32_t now = get_tmr10ms();
if (pwrPressed()) {
press_end = now;
if (press_start == 0) press_start = now;
if ((now - press_start) > POWER_ON_DELAY) {
break;
}
} else if (!isChargerActive()) {
boardOff();
} else {
uint32_t press_end_touch = press_end;
if (touchPanelEventOccured()) {
touchPanelRead();
press_end_touch = get_tmr10ms();
}
press_start = 0;
handle_battery_charge(press_end_touch);
delay_ms(10);
press_end = 0;
}
}
}
keysInit();
switchInit();
audioInit();
adcInit(&_adc_driver);
hapticInit();
#if defined(RTCLOCK)
rtcInit(); // RTC must be initialized before rambackupRestore() is called
#endif
lcdSetInitalFrameBuffer(lcdFront->getData());
#if defined(DEBUG)
DBGMCU_APB1PeriphConfig(
DBGMCU_IWDG_STOP | DBGMCU_TIM1_STOP | DBGMCU_TIM2_STOP |
DBGMCU_TIM3_STOP | DBGMCU_TIM4_STOP | DBGMCU_TIM5_STOP |
DBGMCU_TIM6_STOP | DBGMCU_TIM7_STOP | DBGMCU_TIM8_STOP |
DBGMCU_TIM9_STOP | DBGMCU_TIM10_STOP | DBGMCU_TIM11_STOP |
DBGMCU_TIM12_STOP | DBGMCU_TIM13_STOP | DBGMCU_TIM14_STOP,
ENABLE);
#endif
}
extern void rtcDisableBackupReg();
void boardOff()
{
lcdOff();
while (pwrPressed()) {
WDG_RESET();
}
SysTick->CTRL = 0; // turn off systick
// Shutdown the Haptic
hapticDone();
rtcDisableBackupReg();
#if !defined(BOOT)
if (isChargerActive())
{
delay_ms(100); // Add a delay to wait for lcdOff
// RTC->BKP0R = SOFTRESET_REQUEST;
NVIC_SystemReset();
}
else
#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_CR_MRUDS) && defined(PWR_CR_LPUDS) && defined(PWR_CR_FPDS)
MODIFY_REG(PWR->CR, (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_FPDS | PWR_CR_LPUDS | PWR_CR_MRUDS), PDMode);
#elif defined(PWR_CR_MRLVDS) && defined(PWR_CR_LPLVDS) && defined(PWR_CR_FPDS)
MODIFY_REG(PWR->CR, (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_FPDS | PWR_CR_LPLVDS | PWR_CR_MRLVDS), PDMode);
#else
MODIFY_REG(PWR->CR, (PWR_CR_PDDS| PWR_CR_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) {
}
}
int usbPlugged()
{
static uint8_t debouncedState = 0;
static uint8_t lastState = 0;
uint8_t state = GPIO_ReadInputDataBit(UCHARGER_GPIO, UCHARGER_GPIO_PIN);
if (state == lastState)
debouncedState = state;
else
lastState = state;
return debouncedState;
}

View file

@ -0,0 +1,250 @@
/*
* 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 "opentx_constants.h"
#include "board_common.h"
#include "hal.h"
#include "hal/serial_port.h"
#include "hal/watchdog_driver.h"
#define FLASHSIZE 0x200000
#define BOOTLOADER_SIZE 0x20000
#define FIRMWARE_ADDRESS 0x08000000
#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
void SDRAM_Init();
// Pulses driver
#if !defined(SIMU)
#define INTERNAL_MODULE_ON() GPIO_SetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
#define INTERNAL_MODULE_OFF() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
#define EXTERNAL_MODULE_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
#define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
#define EXTERNAL_MODULE_PWR_OFF EXTERNAL_MODULE_OFF
#define BLUETOOTH_MODULE_ON() GPIO_ResetBits(BT_EN_GPIO, BT_EN_GPIO_PIN)
#define BLUETOOTH_MODULE_OFF() GPIO_SetBits(BT_EN_GPIO, BT_EN_GPIO_PIN)
#define IS_INTERNAL_MODULE_ON() (false)
#define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET)
#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(NUM_FUNCTIONS_SWITCHES)
#define NUM_FUNCTIONS_SWITCHES 0
#endif
#define NUM_TRIMS 8
#define DEFAULT_STICK_DEADZONE 2
#define BATTERY_WARN 37 // 3.7V
#define BATTERY_MIN 35 // 3.4V
#define BATTERY_MAX 43 // 4.3V
#define BATTERY_DIVIDER 962
#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(SIMU)
void usbJoystickUpdate();
#endif
#if defined(RADIO_PL18EV)
#define USB_NAME "FlySky PL18EV"
#define USB_MANUFACTURER 'F', 'l', 'y', 'S', 'k', 'y', ' ', ' ' /* 8 bytes */
#define USB_PRODUCT 'P', 'L', '1', '8', 'E', 'V', ' ', ' ' /* 8 Bytes */
#else
#define USB_NAME "FlySky PL18"
#define USB_MANUFACTURER 'F', 'l', 'y', 'S', 'k', 'y', ' ', ' ' /* 8 bytes */
#define USB_PRODUCT 'P', 'L', '1', '8', ' ', ' ', ' ', ' ' /* 8 Bytes */
#endif
#if defined(__cplusplus) && !defined(SIMU)
}
#endif
// Audio driver
void audioInit();
void audioConsumeCurrentBuffer();
void audioSpiWriteBuffer(const uint8_t * buffer, uint32_t size);
void audioSpiSetSpeed(uint8_t speed);
uint8_t audioHardReset();
uint8_t audioSoftReset();
void audioSendRiffHeader();
void audioOn();
void audioOff();
bool isAudioReady();
bool audioChipReset();
#define SPI_SPEED_2 0
#define SPI_SPEED_4 1
#define SPI_SPEED_8 2
#define SPI_SPEED_16 3
#define SPI_SPEED_32 4
#define SPI_SPEED_64 5
#define SPI_SPEED_128 6
#define SPI_SPEED_256 7
#define audioDisableIrq() // interrupts must stay enabled on Horus
#define audioEnableIrq() // interrupts must stay enabled on Horus
#if defined(PCBNV14)
#define setSampleRate(freq)
#else
void setSampleRate(uint32_t frequency);
#endif
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();
#endif // _BOARD_H_

View file

@ -0,0 +1,261 @@
/*
* 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 "board.h"
#include "fw_version.h"
#include "lcd.h"
#include "translations.h"
#include "../../common/arm/stm32/bootloader/boot.h"
#include "../../common/arm/stm32/bootloader/bin_files.h"
#include <lvgl/lvgl.h>
#define SELECTED_COLOR (INVERS | COLOR_THEME_SECONDARY1)
#define DEFAULT_PADDING 28
#define DOUBLE_PADDING 56
#define MESSAGE_TOP (LCD_H - (2*DOUBLE_PADDING))
const uint8_t __bmp_plug_usb[] {
#include "bmp_plug_usb.lbm"
};
LZ4Bitmap BMP_PLUG_USB(BMP_ARGB4444, __bmp_plug_usb);
const uint8_t __bmp_usb_plugged[] {
#include "bmp_usb_plugged.lbm"
};
LZ4Bitmap BMP_USB_PLUGGED(BMP_ARGB4444, __bmp_usb_plugged);
#define BL_GREEN COLOR2FLAGS(RGB(73, 219, 62))
#define BL_RED COLOR2FLAGS(RGB(229, 32, 30))
#define BL_BACKGROUND COLOR2FLAGS(BLACK)
#define BL_FOREGROUND COLOR2FLAGS(WHITE)
#define BL_SELECTED COLOR2FLAGS(RGB(11, 65, 244)) // deep blue
extern BitmapBuffer * lcd;
void bootloaderInitScreen()
{
lcdInitDisplayDriver();
backlightInit();
backlightEnable(100);
setHatsAsKeys(true);
}
static void bootloaderDrawTitle(const char* text)
{
lcd->drawText(LCD_W/2, DEFAULT_PADDING, text, CENTERED | BL_FOREGROUND);
lcd->drawSolidFilledRect(DEFAULT_PADDING, DOUBLE_PADDING, LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
}
static void bootloaderDrawFooter()
{
lcd->drawSolidFilledRect(DEFAULT_PADDING, LCD_H - (DEFAULT_PADDING + 10), LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
}
static void bootloaderDrawBackground()
{
lcd->clear(BL_BACKGROUND);
}
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
{
lcdInitDirectDrawing();
bootloaderDrawBackground();
int center = LCD_W/2;
if (st == ST_START) {
bootloaderDrawTitle(BOOTLOADER_TITLE);
lcd->drawText(102, 75, LV_SYMBOL_CHARGE, BL_FOREGROUND);
coord_t pos = lcd->drawText(124, 75, TR_BL_WRITE_FW, BL_FOREGROUND);
pos += 8;
#if defined(SPI_FLASH)
lcd->drawText(102, 110, LV_SYMBOL_SD_CARD, BL_FOREGROUND);
pos = lcd->drawText(124, 110, TR_BL_ERASE_FLASH, BL_FOREGROUND);
pos += 8;
lcd->drawText(100, 145, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
lcd->drawText(124, 145, TR_BL_EXIT, BL_FOREGROUND);
#else
lcd->drawText(100, 110, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
lcd->drawText(124, 110, TR_BL_EXIT, BL_FOREGROUND);
#endif
pos -= 92;
lcd->drawSolidRect(92, 72 + (opt * 35), pos, 26, 2, BL_SELECTED);
lcd->drawBitmap(60, 214, (const BitmapBuffer*)&BMP_PLUG_USB);
lcd->drawText(195, 223, TR_BL_USB_PLUGIN, BL_FOREGROUND);
lcd->drawText(195, 248, TR_BL_USB_MASS_STORE, BL_FOREGROUND);
bootloaderDrawFooter();
lcd->drawText(center, LCD_H - DEFAULT_PADDING, getFirmwareVersion(), CENTERED | BL_FOREGROUND);
}
#if defined(SPI_FLASH)
else if (st == ST_CLEAR_FLASH_CHECK) {
bootloaderDrawTitle(TR_BL_ERASE_INT_FLASH);
lcd->drawText(102, 75, LV_SYMBOL_SD_CARD, BL_FOREGROUND);
coord_t pos = lcd->drawText(124, 75, TR_BL_ERASE_FLASH, BL_FOREGROUND);
pos += 8;
lcd->drawText(100, 110, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
lcd->drawText(124, 110, TR_BL_EXIT, BL_FOREGROUND);
pos -= 92;
lcd->drawSolidRect(92, 72 + (opt * 35), pos, 26, 2, BL_SELECTED);
bootloaderDrawFooter();
lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING,
LV_SYMBOL_SD_CARD TR_BL_ERASE_KEY, BL_FOREGROUND);
lcd->drawText(305, LCD_H - DEFAULT_PADDING,
LV_SYMBOL_NEW_LINE TR_BL_EXIT_KEY, BL_FOREGROUND);
}
else if (st == ST_CLEAR_FLASH) {
bootloaderDrawTitle(TR_BL_ERASE_INT_FLASH);
lcd->drawText(center, 75, TR_BL_ERASE_FLASH_MSG, CENTERED | BL_FOREGROUND);
bootloaderDrawFooter();
}
#endif
else if (st == ST_USB) {
lcd->drawBitmap(center - 26, 98, (const BitmapBuffer*)&BMP_USB_PLUGGED);
lcd->drawText(center, 168, TR_BL_USB_CONNECTED, CENTERED | BL_FOREGROUND);
} else if (st == ST_FILE_LIST || st == ST_DIR_CHECK ||
st == ST_FLASH_CHECK || st == ST_FLASHING ||
st == ST_FLASH_DONE) {
bootloaderDrawTitle(LV_SYMBOL_SD_CARD " /FIRMWARE");
if (st == ST_FLASHING || st == ST_FLASH_DONE) {
LcdFlags color = BL_RED; // red
if (st == ST_FLASH_DONE) {
color = BL_GREEN /* green */;
opt = 100; // Completed > 100%
}
lcd->drawRect(DEFAULT_PADDING, 120, LCD_W - DOUBLE_PADDING, 31, 2,
SOLID, BL_SELECTED);
lcd->drawSolidFilledRect(DEFAULT_PADDING + 4, 124,
((LCD_W - DOUBLE_PADDING - 8) * opt) / 100, 23,
color);
} else if (st == ST_DIR_CHECK) {
if (opt == FR_NO_PATH) {
lcd->drawText(20, MESSAGE_TOP,
LV_SYMBOL_CLOSE TR_BL_DIR_MISSING, BL_FOREGROUND);
} else {
lcd->drawText(20, MESSAGE_TOP, LV_SYMBOL_CLOSE TR_BL_DIR_EMPTY,
BL_FOREGROUND);
}
} else if (st == ST_FLASH_CHECK) {
bootloaderDrawFilename(str, 0, true);
if (opt == FC_ERROR) {
lcd->drawText(20, MESSAGE_TOP,
LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE,
BL_FOREGROUND);
} else if (opt == FC_OK) {
VersionTag tag;
memset(&tag, 0, sizeof(tag));
extractFirmwareVersion(&tag);
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING,
MESSAGE_TOP - DEFAULT_PADDING,
TR_BL_FORK, RIGHT | BL_FOREGROUND);
lcd->drawSizedText(LCD_W / 4 + 6 + DEFAULT_PADDING,
MESSAGE_TOP - DEFAULT_PADDING, tag.fork, 6,
BL_FOREGROUND);
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING, MESSAGE_TOP,
TR_BL_VERSION, RIGHT | BL_FOREGROUND);
lcd->drawText(LCD_W / 4 + 6 + DEFAULT_PADDING, MESSAGE_TOP,
tag.version, BL_FOREGROUND);
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING,
MESSAGE_TOP + DEFAULT_PADDING,
TR_BL_RADIO, RIGHT | BL_FOREGROUND);
lcd->drawText(LCD_W / 4 + 6 + DEFAULT_PADDING,
MESSAGE_TOP + DEFAULT_PADDING, tag.flavour,
BL_FOREGROUND);
lcd->drawText(DOUBLE_PADDING, MESSAGE_TOP, LV_SYMBOL_OK, BL_GREEN);
}
}
bootloaderDrawFooter();
if (st != ST_DIR_CHECK && (st != ST_FLASH_CHECK || opt == FC_OK)) {
if (st == ST_FILE_LIST) {
lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING,
LV_SYMBOL_CHARGE TR_BL_SELECT_KEY, BL_FOREGROUND);
} else if (st == ST_FLASH_CHECK && opt == FC_OK) {
lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING,
LV_SYMBOL_CHARGE TR_BL_FLASH_KEY, BL_FOREGROUND);
} else if (st == ST_FLASHING) {
lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING,
LV_SYMBOL_CHARGE TR_BL_WRITING_FW, BL_FOREGROUND);
} else if (st == ST_FLASH_DONE) {
lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING,
LV_SYMBOL_CHARGE TR_BL_WRITING_COMPL, BL_FOREGROUND);
}
}
if (st != ST_FLASHING) {
lcd->drawText(305, LCD_H - DEFAULT_PADDING,
LV_SYMBOL_NEW_LINE TR_BL_EXIT_KEY, BL_FOREGROUND);
}
}
}
void bootloaderDrawFilename(const char* str, uint8_t line, bool selected)
{
lcd->drawText(DEFAULT_PADDING, 75 + (line * 25), LV_SYMBOL_FILE, BL_FOREGROUND);
lcd->drawText(DEFAULT_PADDING + 30, 75 + (line * 25), str, BL_FOREGROUND);
if (selected) {
lcd->drawSolidRect(DEFAULT_PADDING + 25, 72 + (line * 25),
LCD_W - (DEFAULT_PADDING + 25) - 28, 26, 2, BL_SELECTED);
}
}
uint32_t bootloaderGetMenuItemCount(int baseCount)
{
return baseCount;
}
bool bootloaderRadioMenu(uint32_t menuItem, event_t event)
{
return true;
}
void blExit(void)
{
lcdClear();
lcdRefresh();
lcdRefreshWait();
}

View file

@ -0,0 +1,49 @@
/*
* 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 "board.h"
void EXTERNAL_MODULE_ON()
{
GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
}
void EXTERNAL_MODULE_OFF()
{
GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
}
void extModuleInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_INVERT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(EXTMODULE_TX_INVERT_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = EXTMODULE_RX_INVERT_GPIO_PIN;
GPIO_Init(EXTMODULE_RX_INVERT_GPIO, &GPIO_InitStructure);
EXTMODULE_TX_INVERTED();
EXTMODULE_RX_INVERTED();
}

View file

@ -0,0 +1,719 @@
/*
* 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 _HAL_H_
#define _HAL_H_
#define CPU_FREQ 168000000
// HSI is at 168Mhz (over-drive is not enabled!)
#define PERI1_FREQUENCY 42000000
#define PERI2_FREQUENCY 84000000
#define TIMER_MULT_APB1 2
#define TIMER_MULT_APB2 2
/* Timers Allocation:
* TIM1 = Haptic
* TIM4 = Trainer
* TIM6 = Audio
* TIM7 = 2 MHz counter
*
*
* TIM14 = 5 ms counter
*/
/* DMA Allocation:
DMA/Stream/Channel
1/5/7 DAC/Audio
2/4/0 ADC1
2/0/2 ADC3
2/3/4 SDIO
*/
// Keys
// PL18/PL18EV only has virtual keys via trim buttons
// #define KEYS_GPIO_PIN_PGUP /* for activating PGUP in keys diagnose screen */
// Trims
#define TRIMS_GPIO_REG_LHL
#define TRIMS_GPIO_PIN_LHL
#define TRIMS_GPIO_REG_LHR
#define TRIMS_GPIO_PIN_LHR
#define TRIMS_GPIO_REG_LVD
#define TRIMS_GPIO_PIN_LVD
#define TRIMS_GPIO_REG_LVU
#define TRIMS_GPIO_PIN_LVU
#define TRIMS_GPIO_REG_RHL
#define TRIMS_GPIO_PIN_RHL
#define TRIMS_GPIO_REG_RHR
#define TRIMS_GPIO_PIN_RHR
#define TRIMS_GPIO_REG_RVD
#define TRIMS_GPIO_PIN_RVD
#define TRIMS_GPIO_REG_RVU
#define TRIMS_GPIO_PIN_RVU
#define TRIMS_GPIO_REG_LSD
#define TRIMS_GPIO_PIN_LSD
#define TRIMS_GPIO_REG_LSU
#define TRIMS_GPIO_PIN_LSU
#define TRIMS_GPIO_REG_RSD
#define TRIMS_GPIO_PIN_RSD
#define TRIMS_GPIO_REG_RSU
#define TRIMS_GPIO_PIN_RSU
#define TRIMS_GPIO_REG_T7L
#define TRIMS_GPIO_PIN_T7L
#define TRIMS_GPIO_REG_T7R
#define TRIMS_GPIO_PIN_T7R
#define TRIMS_GPIO_REG_T8D
#define TRIMS_GPIO_PIN_T8D
#define TRIMS_GPIO_REG_T8U
#define TRIMS_GPIO_PIN_T8U
#define TRIMS_GPIO_REG_TR1U GPIOH->IDR
#define TRIMS_GPIO_PIN_TR1U LL_GPIO_PIN_8 // PH.08
#define TRIMS_GPIO_REG_TR1D GPIOH->IDR
#define TRIMS_GPIO_PIN_TR1D LL_GPIO_PIN_9 // PH.09
#define TRIMS_GPIO_REG_TR2U GPIOH->IDR
#define TRIMS_GPIO_PIN_TR2U LL_GPIO_PIN_10 // PH.10
#define TRIMS_GPIO_REG_TR2D GPIOH->IDR
#define TRIMS_GPIO_PIN_TR2D LL_GPIO_PIN_11 // PH.11
// active 4x4 column/row based key-matrix to support up to 16 buttons with only 8 GPIOs
#define TRIMS_GPIO_OUT1 GPIOG
#define TRIMS_GPIO_OUT1_PIN LL_GPIO_PIN_2 // PG.02
#define TRIMS_GPIO_OUT2 GPIOG
#define TRIMS_GPIO_OUT2_PIN LL_GPIO_PIN_10 // PG.10
#define TRIMS_GPIO_OUT3 GPIOG
#define TRIMS_GPIO_OUT3_PIN LL_GPIO_PIN_11 // PG.11
// OUT4 routed on MCU PCB, but not attached to any physical buttons, free to use for extensions
#define TRIMS_GPIO_OUT4 GPIOH
#define TRIMS_GPIO_OUT4_PIN LL_GPIO_PIN_7 // PH.07
#define TRIMS_GPIO_REG_IN1 GPIOB->IDR
#define TRIMS_GPIO_PIN_IN1 LL_GPIO_PIN_15 // PB.15
#define TRIMS_GPIO_REG_IN2 GPIOC->IDR
#define TRIMS_GPIO_PIN_IN2 LL_GPIO_PIN_13 // PC.13
#define TRIMS_GPIO_REG_IN3 GPIOD->IDR
#define TRIMS_GPIO_PIN_IN3 LL_GPIO_PIN_7 // PD.07
#define TRIMS_GPIO_REG_IN4 GPIOJ->IDR
#define TRIMS_GPIO_PIN_IN4 LL_GPIO_PIN_12 // PJ.12
// Index of all trims
#define KEYS_GPIOB_PINS (LL_GPIO_PIN_15)
// PC8 allocated to SDIO D0, is not required to sample SWA !
#define KEYS_GPIOC_PINS (LL_GPIO_PIN_13)
#define KEYS_GPIOD_PINS (LL_GPIO_PIN_7)
#define KEYS_GPIOH_PINS \
(LL_GPIO_PIN_8 | LL_GPIO_PIN_9 | LL_GPIO_PIN_10 | LL_GPIO_PIN_11)
#define KEYS_GPIOJ_PINS (LL_GPIO_PIN_12)
#define KEYS_OUT_GPIOG_PINS (LL_GPIO_PIN_2 | LL_GPIO_PIN_10 | LL_GPIO_PIN_11)
#define KEYS_OUT_GPIOH_PINS (LL_GPIO_PIN_7)
// Monitor pin
// #define MONITOR_RCC_AHB1Periph (RCC_AHB1Periph_GPIOJ)
// #define VBUS_MONITOR_GPIO (GPIOJ)
// #define VBUS_MONITOR_PIN (LL_GPIO_PIN_14)
// Switches:
// Switches A and C on PL18/PL18EV are 2-position switches,
// so there is no NEED to configure two pins for Switches A and C.
//
// Especially, as on current dev. state, using PC8 for SDIO D0.
// (happy coincidence ;)
//
// #define SWITCHES_GPIO_REG_A_H GPIOC
// #define SWITCHES_GPIO_PIN_A_H LL_GPIO_PIN_8 // PC.08
// #define SWITCHES_GPIO_REG_A_L GPIOC
// #define SWITCHES_GPIO_PIN_A_L LL_GPIO_PIN_9 // PC.09
#define SWITCHES_GPIO_REG_A GPIOC
#define SWITCHES_GPIO_PIN_A LL_GPIO_PIN_9 // PC.09
// High rail of Switch C is not required and thus PC10 is free to use for
// customizations.
//
// #define SWITCHES_GPIO_REG_C_H GPIOC
// #define SWITCHES_GPIO_PIN_C_H LL_GPIO_PIN_10 // PC.10
// #define SWITCHES_GPIO_REG_C_L GPIOC
// #define SWITCHES_GPIO_PIN_C_L LL_GPIO_PIN_11 // PC.11
#define SWITCHES_GPIO_REG_C GPIOC
#define SWITCHES_GPIO_PIN_C LL_GPIO_PIN_11 // PC.11
// ADC
#define ADC_GPIO_PIN_STICK_LH
#define ADC_GPIO_PIN_STICK_LV
#define ADC_GPIO_PIN_STICK_RV
#define ADC_GPIO_PIN_STICK_RH
#define ADC_GPIO_PIN_POT1 LL_GPIO_PIN_6 // PA.06 VRA
#define ADC_GPIO_PIN_POT2 LL_GPIO_PIN_4 // PC.04 VRB
#define ADC_GPIO_PIN_POT3 LL_GPIO_PIN_8 // PF.08 VRC
#define ADC_GPIO_PIN_SLIDER1 LL_GPIO_PIN_9 // PF.09 VRD/LS
#define ADC_GPIO_PIN_SLIDER2 LL_GPIO_PIN_7 // PA.07 VRE/RS
#if defined(RADIO_PL18EV)
#define ADC_GPIO_PIN_EXT1 LL_GPIO_PIN_5 // PA.05
#define ADC_GPIO_PIN_EXT2 LL_GPIO_PIN_2 // PA.02
#define ADC_GPIO_PIN_EXT3 LL_GPIO_PIN_6 // PF.06
#define ADC_GPIO_PIN_EXT4 LL_GPIO_PIN_3 // PA.03
#endif
#define ADC_GPIO_PIN_SWB LL_GPIO_PIN_1 // PC.01
#define ADC_GPIO_PIN_SWD LL_GPIO_PIN_0 // PC.00
#define ADC_GPIO_PIN_SWE LL_GPIO_PIN_2 // PC.02
#define ADC_GPIO_PIN_SWF LL_GPIO_PIN_0 // PB.00
#define ADC_GPIO_PIN_SWG LL_GPIO_PIN_1 // PB.01
#define ADC_GPIO_PIN_SWH LL_GPIO_PIN_10 // PF.10
#define ADC_GPIO_PIN_BATT LL_GPIO_PIN_5 // PC.05
#define ADC_GPIOA_PINS (ADC_GPIO_PIN_POT1 | ADC_GPIO_PIN_SLIDER2 | \
ADC_GPIO_PIN_EXT1 | ADC_GPIO_PIN_EXT2 | ADC_GPIO_PIN_EXT4)
#define ADC_GPIOB_PINS (ADC_GPIO_PIN_SWF | ADC_GPIO_PIN_SWG)
#define ADC_GPIOC_PINS (ADC_GPIO_PIN_POT2 | ADC_GPIO_PIN_BATT | \
ADC_GPIO_PIN_SWB | ADC_GPIO_PIN_SWD | ADC_GPIO_PIN_SWE)
#define ADC_GPIOF_PINS (ADC_GPIO_PIN_POT3 | ADC_GPIO_PIN_SLIDER1 | \
ADC_GPIO_PIN_EXT3 | ADC_GPIO_PIN_SWH)
#define ADC_CHANNEL_STICK_LH
#define ADC_CHANNEL_STICK_LV
#define ADC_CHANNEL_STICK_RV
#define ADC_CHANNEL_STICK_RH
// Each ADC cannot map more than 8 channels, otherwise it will cause problems
#define ADC_CHANNEL_POT1 LL_ADC_CHANNEL_6 // ADC12_IN6 -> ADC1_IN6
#define ADC_CHANNEL_POT2 LL_ADC_CHANNEL_14 // ADC12_IN14 -> ADC1_IN14
#define ADC_CHANNEL_POT3 LL_ADC_CHANNEL_6 // ADC3_IN6 -> ADC3_IN6
#define ADC_CHANNEL_SLIDER1 LL_ADC_CHANNEL_7 // ADC3_IN7 -> ADC3_IN7
#define ADC_CHANNEL_SLIDER2 LL_ADC_CHANNEL_7 // ADC12_IN7 -> ADC1_IN7
#if defined(RADIO_PL18EV)
// Left, right stick end pot on PL18EV
#define ADC_CHANNEL_EXT1 LL_ADC_CHANNEL_5 // ADC12_IN5 -> ADC1_IN5
#define ADC_CHANNEL_EXT2 LL_ADC_CHANNEL_2 // ADC123_IN2 -> ADC1_IN2
// Left, right stick end buttons on PL18EV
#define ADC_CHANNEL_EXT3 LL_ADC_CHANNEL_4 // ADC3_IN4 -> ADC3_IN4
#define ADC_CHANNEL_EXT4 LL_ADC_CHANNEL_3 // ADC123_IN3 -> ADC3_IN3
#endif
// Analog switches
#define ADC_CHANNEL_SWB LL_ADC_CHANNEL_11 // ADC123_IN11 -> ADC3_IN11
#define ADC_CHANNEL_SWD LL_ADC_CHANNEL_10 // ADC123_IN10 -> ADC3_IN10
#define ADC_CHANNEL_SWE LL_ADC_CHANNEL_12 // ADC123_IN12 -> ADC3_IN12
#define ADC_CHANNEL_SWF LL_ADC_CHANNEL_8 // ADC12_IN8 -> ADC1_IN8
#define ADC_CHANNEL_SWG LL_ADC_CHANNEL_9 // ADC12_IN9 -> ADC1_IN9
#define ADC_CHANNEL_SWH LL_ADC_CHANNEL_8 // ADC3_IN8 -> ADC3_IN8
#define ADC_CHANNEL_BATT LL_ADC_CHANNEL_15 // ADC12_IN15 -> ADC1_IN15
#if !defined(RADIO_PL18EV)
// Disabled for PL18EV because 2 ADC 16 channels are fully mapped already
#define ADC_CHANNEL_RTC_BAT LL_ADC_CHANNEL_VBAT // ADC1_IN18
#endif
#define ADC_MAIN ADC1
#define ADC_EXT ADC3
#define ADC_EXT_CHANNELS \
{ ADC_CHANNEL_POT3, ADC_CHANNEL_SLIDER1, ADC_CHANNEL_EXT3, ADC_CHANNEL_EXT4, \
ADC_CHANNEL_SWB, ADC_CHANNEL_SWD, ADC_CHANNEL_SWE, ADC_CHANNEL_SWH \
}
#define ADC_SAMPTIME LL_ADC_SAMPLINGTIME_28CYCLES
#define ADC_DMA DMA2
#define ADC_DMA_CHANNEL LL_DMA_CHANNEL_0
#define ADC_DMA_STREAM LL_DMA_STREAM_4
#define ADC_DMA_STREAM_IRQ DMA2_Stream4_IRQn
#define ADC_DMA_STREAM_IRQHandler DMA2_Stream4_IRQHandler
#define ADC_EXT_DMA DMA2
#define ADC_EXT_DMA_CHANNEL LL_DMA_CHANNEL_2
#define ADC_EXT_DMA_STREAM LL_DMA_STREAM_0
#define ADC_EXT_DMA_STREAM_IRQ DMA2_Stream0_IRQn
#define ADC_EXT_DMA_STREAM_IRQHandler DMA2_Stream0_IRQHandler
#define ADC_EXT_SAMPTIME LL_ADC_SAMPLINGTIME_28CYCLES
#define ADC_VREF_PREC2 660
#if defined(RADIO_PL18EV)
#define ADC_DIRECTION { \
0,0,0,0, /* gimbals */ \
0,0,0, /* pots */ \
-1,-1, /* sliders */ \
0,0,0,0, /* ext1-4 */ \
0, /* vbat */ \
-1, /* SWB */ \
-1, /* SWD */ \
0, /* SWE */ \
0, /* SWF */ \
0, /* SWG */ \
0 /* SWH */ \
}
#else
#define ADC_DIRECTION { \
0,0,0,0, /* gimbals */ \
0,0,0, /* pots */ \
-1,-1, /* sliders */ \
0, /* vbat */ \
0, /* rtc_bat */ \
-1, /* SWB */ \
-1, /* SWD */ \
0, /* SWE */ \
0, /* SWF */ \
0, /* SWG */ \
0 /* SWH */ \
}
#endif
// Power
#define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOI
#define PWR_ON_GPIO GPIOI
#define PWR_SWITCH_GPIO GPIOI
#define PWR_SWITCH_GPIO_PIN GPIO_Pin_11 // PI.11
#define PWR_ON_GPIO_PIN GPIO_Pin_14 // PI.14
// Chargers (USB and wireless)
#define CHARGER_RCC_AHB1Periph ( RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI )
#define UCHARGER_GPIO GPIOB
#define UCHARGER_GPIO_PIN GPIO_Pin_14 // PB.14 input
#define UCHARGER_CHARGE_END_GPIO GPIOB
#define UCHARGER_CHARGE_END_GPIO_PIN GPIO_Pin_13 // PB.13 input
#define UCHARGER_EN_GPIO GPIOG
#define UCHARGER_EN_GPIO_PIN GPIO_Pin_3 // PG.03 output
#if defined (WIRELESS_CHARGER)
#define WCHARGER_GPIO GPIOI
#define WCHARGER_GPIO_PIN GPIO_Pin_9 // PI.09 input
#define WCHARGER_CHARGE_END_GPIO GPIOI
#define WCHARGER_CHARGE_END_GPIO_PIN GPIO_Pin_10 // PI.10 input
#define WCHARGER_EN_GPIO GPIOH
#define WCHARGER_EN_GPIO_PIN GPIO_Pin_4 // PH.04 output
#define WCHARGER_I_CONTROL_GPIO GPIOH
#define WCHARGER_I_CONTROL_GPIO_PIN GPIO_Pin_13 // PH.13 output
#endif
// TODO! Check IOLL1 to PI.01 connectivity!
// S.Port update connector
#define SPORT_MAX_BAUDRATE 400000
#define SPORT_UPDATE_RCC_AHB1Periph 0
#define HAS_SPORT_UPDATE_CONNECTOR() (false)
// Serial Port (DEBUG)
// We will temporarily used the PPM and the HEARTBEAT PINS
#define AUX_SERIAL_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE)
#define AUX_SERIAL_RCC_APB1Periph 0
#define AUX_SERIAL_RCC_APB2Periph RCC_APB2Periph_USART6
#define AUX_SERIAL_GPIO GPIOC
#define AUX_SERIAL_GPIO_PIN_TX GPIO_Pin_6 // PC.06
#define AUX_SERIAL_GPIO_PIN_RX GPIO_Pin_7 // PC.07
#define AUX_SERIAL_GPIO_PinSource_TX GPIO_PinSource6
#define AUX_SERIAL_GPIO_PinSource_RX GPIO_PinSource7
#define AUX_SERIAL_GPIO_AF GPIO_AF_USART6
#define AUX_SERIAL_USART USART6
#define AUX_SERIAL_USART_IRQHandler USART6_IRQHandler
#define AUX_SERIAL_USART_IRQn USART6_IRQn
#define AUX_SERIAL_TX_INVERT_GPIO GPIOE
#define AUX_SERIAL_TX_INVERT_GPIO_PIN GPIO_Pin_3 // PE.03
#define AUX_SERIAL_RX_INVERT_GPIO GPIOI
#define AUX_SERIAL_RX_INVERT_GPIO_PIN GPIO_Pin_15 // PI.15
//used in BOOTLOADER
#define SERIAL_RCC_AHB1Periph 0
#define SERIAL_RCC_APB1Periph 0
#define AUX2_SERIAL_RCC_AHB1Periph 0
#define AUX2_SERIAL_RCC_APB1Periph 0
#define AUX2_SERIAL_RCC_APB2Periph 0
#define KEYS_BACKLIGHT_RCC_AHB1Periph 0
// Telemetry
#define TELEMETRY_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_DMA1)
#define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2
#define TELEMETRY_REV_GPIO GPIOJ
#define TELEMETRY_RX_REV_GPIO_PIN GPIO_Pin_8 // PJ.08
#define TELEMETRY_TX_REV_GPIO_PIN GPIO_Pin_7 // PJ.07
#define TELEMETRY_DIR_GPIO GPIOJ
#define TELEMETRY_DIR_GPIO_PIN GPIO_Pin_13 // PJ.13
#define TELEMETRY_SET_INPUT 1
#define TELEMETRY_GPIO GPIOD
#define TELEMETRY_TX_GPIO_PIN GPIO_Pin_5 // PD.05
#define TELEMETRY_RX_GPIO_PIN GPIO_Pin_6 // PD.06
#define TELEMETRY_GPIO_PinSource_TX GPIO_PinSource5
#define TELEMETRY_GPIO_PinSource_RX GPIO_PinSource6
#define TELEMETRY_GPIO_AF GPIO_AF_USART2
#define TELEMETRY_USART USART2
#define TELEMETRY_DMA DMA1
#define TELEMETRY_DMA_Stream_TX LL_DMA_STREAM_6
#define TELEMETRY_DMA_Channel_TX DMA_Channel_4
#define TELEMETRY_DMA_TX_Stream_IRQ DMA1_Stream6_IRQn
#define TELEMETRY_DMA_TX_IRQHandler DMA1_Stream6_IRQHandler
#define TELEMETRY_DMA_TX_FLAG_TC DMA_IT_TCIF6
// #define TELEMETRY_DMA_Stream_RX LL_DMA_STREAM_5
// #define TELEMETRY_DMA_Channel_RX LL_DMA_CHANNEL_4
#define TELEMETRY_USART_IRQHandler USART2_IRQHandler
#define TELEMETRY_USART_IRQn USART2_IRQn
#define TELEMETRY_DIR_OUTPUT() TELEMETRY_DIR_GPIO->BSRRH = TELEMETRY_DIR_GPIO_PIN
#define TELEMETRY_DIR_INPUT() TELEMETRY_DIR_GPIO->BSRRL = TELEMETRY_DIR_GPIO_PIN
#define TELEMETRY_TX_POL_NORM() TELEMETRY_REV_GPIO->BSRRH = TELEMETRY_TX_REV_GPIO_PIN
#define TELEMETRY_TX_POL_INV() TELEMETRY_REV_GPIO->BSRRL = TELEMETRY_TX_REV_GPIO_PIN
#define TELEMETRY_RX_POL_NORM() TELEMETRY_REV_GPIO->BSRRH = TELEMETRY_RX_REV_GPIO_PIN
#define TELEMETRY_RX_POL_INV() TELEMETRY_REV_GPIO->BSRRL = TELEMETRY_RX_REV_GPIO_PIN
// Software IRQ (Prio 5 -> FreeRTOS compatible)
#define TELEMETRY_RX_FRAME_EXTI_LINE LL_EXTI_LINE_4
#define USE_EXTI4_IRQ
#define EXTI4_IRQ_Priority 5
// USB
#define USB_RCC_AHB1Periph_GPIO RCC_AHB1Periph_GPIOA
#define USB_GPIO GPIOA
// #define USB_GPIO_PIN_VBUS GPIO_Pin_9 // PA.09
#define USB_GPIO_PIN_ID GPIO_Pin_10 // PA.10
#define USB_GPIO_PIN_DM GPIO_Pin_11 // PA.11
#define USB_GPIO_PIN_DP GPIO_Pin_12 // PA.12
#define USB_GPIO_PinSource_DM GPIO_PinSource11
#define USB_GPIO_PinSource_DP GPIO_PinSource12
#define USB_GPIO_AF GPIO_AF_OTG1_FS
// LCD
#define LCD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_GPIOK | RCC_AHB1Periph_DMA2D)
#define LCD_RCC_APB1Periph 0
#define LCD_RCC_APB2Periph RCC_APB2Periph_LTDC
#define LCD_NRST_GPIO GPIOG
#define LCD_NRST_GPIO_PIN LL_GPIO_PIN_9 // PG.09
#define LCD_SPI_GPIO GPIOE
#define LCD_SPI_CS_GPIO_PIN LL_GPIO_PIN_4 // PE.04
#define LCD_SPI_SCK_GPIO_PIN LL_GPIO_PIN_2 // PE.02
#define LCD_SPI_MISO_GPIO_PIN LL_GPIO_PIN_5 // PE.05
#define LCD_SPI_MOSI_GPIO_PIN LL_GPIO_PIN_6 // PE.06
#define LTDC_IRQ_PRIO 4
#define DMA_SCREEN_IRQ_PRIO 6
// Backlight
// TODO TIM3, TIM8, TIM14, review the channel in backlight_driver.cpp according to the chosen timer
#define BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
#define BACKLIGHT_RCC_APB1Periph RCC_APB1Periph_TIM2
#define BACKLIGHT_RCC_APB2Periph 0
#define BACKLIGHT_GPIO GPIOA
#define BACKLIGHT_GPIO_PIN GPIO_Pin_15
#define BACKLIGHT_GPIO_PinSource GPIO_PinSource15
#define BACKLIGHT_TIMER TIM2
#define BACKLIGHT_GPIO_AF GPIO_AF_TIM2
#define BACKLIGHT_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
//used in BOOTLOADER
#define SERIAL_RCC_AHB1Periph 0
#define SERIAL_RCC_APB1Periph 0
#define ROTARY_ENCODER_RCC_APB1Periph 0
// SPI NOR Flash
#define FLASH_SPI SPI6
#define FLASH_SPI_CS_GPIO GPIOG
#define FLASH_SPI_CS_GPIO_PIN LL_GPIO_PIN_6 // PG.06
#define FLASH_SPI_GPIO GPIOG
#define FLASH_SPI_SCK_GPIO_PIN LL_GPIO_PIN_13 // PG.13
#define FLASH_SPI_MISO_GPIO_PIN LL_GPIO_PIN_12 // PG.12
#define FLASH_SPI_MOSI_GPIO_PIN LL_GPIO_PIN_14 // PG.14
// #define FLASH_SPI_DMA DMA2
// #define FLASH_SPI_DMA_CHANNEL LL_DMA_CHANNEL_1
// #define FLASH_SPI_DMA_TX_STREAM LL_DMA_STREAM_5
// #define FLASH_SPI_DMA_TX_IRQn DMA2_Stream5_IRQn
// #define FLASH_SPI_DMA_TX_IRQHandler DMA2_Stream5_IRQHandler
// #define FLASH_SPI_DMA_RX_STREAM LL_DMA_STREAM_6
// #define FLASH_SPI_DMA_RX_IRQn DMA2_Stream6_IRQn
// #define FLASH_SPI_DMA_RX_IRQHandler DMA2_Stream6_IRQHandler
#define STORAGE_USE_SPI_FLASH
// SDRAM
#define SDRAM_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH)
#define SDRAM_RCC_AHB3Periph RCC_AHB3Periph_FMC
// Audio
#define AUDIO_RCC_APB1Periph (RCC_APB1Periph_TIM6 | RCC_APB1Periph_DAC)
#define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1)
#define AUDIO_OUTPUT_GPIO GPIOA
#define AUDIO_OUTPUT_GPIO_PIN GPIO_Pin_4 // PA.04
#define AUDIO_GPIO_PinSource GPIO_PinSource4
#define AUDIO_DMA_Stream DMA1_Stream5
#define AUDIO_DMA_Stream_IRQn DMA1_Stream5_IRQn
#define AUDIO_TIM_IRQn TIM6_DAC_IRQn
#define AUDIO_TIM_IRQHandler TIM6_DAC_IRQHandler
#define AUDIO_DMA_Stream_IRQHandler DMA1_Stream5_IRQHandler
#define AUDIO_TIMER TIM6
#define AUDIO_DMA DMA1
// I2C Bus
#define I2C_B1 I2C1
#define I2C_B1_GPIO GPIOB
#define I2C_B1_SDA_GPIO_PIN LL_GPIO_PIN_7 // PB.07
#define I2C_B1_SCL_GPIO_PIN LL_GPIO_PIN_8 // PB.08
#define I2C_B1_GPIO_AF LL_GPIO_AF_4
// Touch
#define TOUCH_I2C_BUS I2C_Bus_1
#define TOUCH_I2C_CLK_RATE 400000
#define TOUCH_INT_GPIO GPIOB
#define TOUCH_INT_GPIO_PIN LL_GPIO_PIN_9 // PB.09
#define TOUCH_RST_GPIO GPIOB
#define TOUCH_RST_GPIO_PIN LL_GPIO_PIN_12 // PB.12
#define TOUCH_INT_EXTI_Line LL_EXTI_LINE_9
#define TOUCH_INT_EXTI_Port LL_SYSCFG_EXTI_PORTB
#define TOUCH_INT_EXTI_SysCfgLine LL_SYSCFG_EXTI_LINE9
// TOUCH_INT_EXTI IRQ
#if !defined(USE_EXTI9_5_IRQ)
#define USE_EXTI9_5_IRQ
#define EXTI9_5_IRQ_Priority 9
#endif
// Haptic: TIM1_CH1
#define HAPTIC_PWM
#define HAPTIC_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
#define HAPTIC_RCC_APB2Periph RCC_APB2ENR_TIM1EN
#define HAPTIC_GPIO GPIOA
#define HAPTIC_GPIO_PIN GPIO_Pin_8
#define HAPTIC_GPIO_TIMER TIM1
#define HAPTIC_GPIO_AF GPIO_AF_TIM1
#define HAPTIC_GPIO_PinSource GPIO_PinSource8
#define HAPTIC_TIMER_OUTPUT_ENABLE TIM_CCER_CC1E | TIM_CCER_CC1NE;
#define HAPTIC_TIMER_MODE TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE
#define HAPTIC_TIMER_COMPARE_VALUE HAPTIC_GPIO_TIMER->CCR1
// Flysky Hall Stick
#define FLYSKY_HALL_SERIAL_USART UART4
#define FLYSKY_HALL_SERIAL_GPIO GPIOA
#define FLYSKY_HALL_DMA_Channel LL_DMA_CHANNEL_4
#define FLYSKY_HALL_SERIAL_TX_GPIO_PIN LL_GPIO_PIN_0 // PA.00
#define FLYSKY_HALL_SERIAL_RX_GPIO_PIN LL_GPIO_PIN_1 // PA.01
#define FLYSKY_HALL_SERIAL_GPIO_AF LL_GPIO_AF_8
#define FLYSKY_HALL_RCC_AHB1Periph RCC_AHB1Periph_DMA1
#define FLYSKY_HALL_RCC_APB1Periph RCC_APB1Periph_UART4
#define FLYSKY_HALL_SERIAL_USART_IRQHandler UART4_IRQHandler
#define FLYSKY_HALL_SERIAL_USART_IRQn UART4_IRQn
#define FLYSKY_HALL_SERIAL_DMA DMA1
#define FLYSKY_HALL_DMA_Stream_RX LL_DMA_STREAM_2
#define FLYSKY_HALL_DMA_Stream_TX LL_DMA_STREAM_4
// LED Strip
#define LED_STRIP_LENGTH 4
#define LED_STRIP_GPIO GPIOH
#define LED_STRIP_GPIO_PIN_DATA LL_GPIO_PIN_12 // PH.12 / TIM5_CH3
#define LED_STRIP_GPIO_PIN_AF LL_GPIO_AF_2 // TIM3/4/5
#define LED_STRIP_TIMER TIM5
#define LED_STRIP_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#define LED_STRIP_TIMER_CHANNEL LL_TIM_CHANNEL_CH3
#define LED_STRIP_TIMER_DMA DMA1
#define LED_STRIP_TIMER_DMA_CHANNEL LL_DMA_CHANNEL_6
#define LED_STRIP_TIMER_DMA_STREAM LL_DMA_STREAM_0
#define LED_STRIP_TIMER_DMA_IRQn DMA1_Stream0_IRQn
#define LED_STRIP_TIMER_DMA_IRQHandler DMA1_Stream0_IRQHandler
#define LED_STRIP_REFRESH_PERIOD 50 //ms
#define STATUS_LEDS
// Internal Module
#if defined(RADIO_PL18)
#define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_DMA1)
#define INTMODULE_PWR_GPIO GPIOI
#define INTMODULE_PWR_GPIO_PIN GPIO_Pin_0 // PI.00
#define INTMODULE_GPIO GPIOF
#define INTMODULE_TX_GPIO_PIN LL_GPIO_PIN_7 // PF.07
#define INTMODULE_RX_GPIO_PIN LL_GPIO_PIN_6 // PF.06
#define INTMODULE_USART UART7
#define INTMODULE_GPIO_AF LL_GPIO_AF_8
#define INTMODULE_USART_IRQn UART7_IRQn
#define INTMODULE_USART_IRQHandler UART7_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_DMA_CHANNEL_5
#define INTMODULE_RX_DMA DMA1
#define INTMODULE_RX_DMA_STREAM LL_DMA_STREAM_3
#define INTMODULE_RX_DMA_CHANNEL LL_DMA_CHANNEL_5
// #define INTMODULE_RX_DMA_Stream_IRQn DMA1_Stream3_IRQn
// #define INTMODULE_RX_DMA_Stream_IRQHandler DMA1_Stream_IRQHandler
#define INTMODULE_TIMER TIM3
#define INTMODULE_TIMER_IRQn TIM3_IRQn
#define INTMODULE_TIMER_IRQHandler TIM3_IRQHandler
#define INTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#endif
// External Module
#define EXTMODULE
#define EXTMODULE_PULSES
#define EXTMODULE_PWR_GPIO GPIOD
#define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_11 // PD.11
#define EXTMODULE_RCC_AHB1Periph \
(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOC | \
RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_DMA2)
#define EXTMODULE_TX_GPIO GPIOC
#define EXTMODULE_TX_GPIO_PIN LL_GPIO_PIN_6 // PC.06
#define EXTMODULE_TX_GPIO_AF LL_GPIO_AF_3 // TIM8_CH1
#define EXTMODULE_TX_GPIO_AF_USART GPIO_AF_USART6
#define EXTMODULE_RX_GPIO GPIOC
#define EXTMODULE_RX_GPIO_PIN LL_GPIO_PIN_7 // PC.07
#define EXTMODULE_RX_GPIO_AF_USART GPIO_AF_USART6
#define EXTMODULE_TIMER TIM8
#define EXTMODULE_TIMER_Channel LL_TIM_CHANNEL_CH1
#define EXTMODULE_TIMER_IRQn TIM8_UP_TIM13_IRQn
#define EXTMODULE_TIMER_IRQHandler TIM8_UP_TIM13_IRQHandler
#define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
#define EXTMODULE_TIMER_TX_GPIO_AF LL_GPIO_AF_3
//USART
#define EXTMODULE_USART USART6
#define EXTMODULE_USART_GPIO GPIOC
#define EXTMODULE_USART_GPIO_AF GPIO_AF_USART6
#define EXTMODULE_USART_GPIO_AF_LL LL_GPIO_AF_8
#define EXTMODULE_USART_TX_DMA DMA2
#define EXTMODULE_USART_TX_DMA_CHANNEL LL_DMA_CHANNEL_5
#define EXTMODULE_USART_TX_DMA_STREAM DMA2_Stream7
#define EXTMODULE_USART_TX_DMA_STREAM_LL LL_DMA_STREAM_7
#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMA_CHANNEL_5
#define EXTMODULE_USART_RX_DMA_STREAM DMA2_Stream2
#define EXTMODULE_USART_RX_DMA_STREAM_LL LL_DMA_STREAM_2
#define EXTMODULE_USART_IRQHandler USART6_IRQHandler
#define EXTMODULE_USART_IRQn USART6_IRQn
//TIMER
#define EXTMODULE_TIMER_DMA_CHANNEL LL_DMA_CHANNEL_7
#define EXTMODULE_TIMER_DMA_STREAM DMA2_Stream1
#define EXTMODULE_TIMER_DMA DMA2
#define EXTMODULE_TIMER_DMA_STREAM_LL LL_DMA_STREAM_1
#define EXTMODULE_TIMER_DMA_STREAM_IRQn DMA2_Stream1_IRQn
#define EXTMODULE_TIMER_DMA_IRQHandler DMA2_Stream1_IRQHandler
#define EXTMODULE_TX_INVERT_GPIO GPIOE
#define EXTMODULE_TX_INVERT_GPIO_PIN GPIO_Pin_3 // PE.03
#define EXTMODULE_RX_INVERT_GPIO GPIOI
#define EXTMODULE_RX_INVERT_GPIO_PIN GPIO_Pin_15 // PI.15
#define EXTMODULE_TX_NORMAL() EXTMODULE_TX_INVERT_GPIO->BSRRH = EXTMODULE_TX_INVERT_GPIO_PIN
#define EXTMODULE_TX_INVERTED() EXTMODULE_TX_INVERT_GPIO->BSRRL = EXTMODULE_TX_INVERT_GPIO_PIN
#define EXTMODULE_RX_NORMAL() EXTMODULE_RX_INVERT_GPIO->BSRRH = EXTMODULE_RX_INVERT_GPIO_PIN
#define EXTMODULE_RX_INVERTED() EXTMODULE_RX_INVERT_GPIO->BSRRL = EXTMODULE_RX_INVERT_GPIO_PIN
// Trainer Port
#define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD)
#define TRAINER_GPIO GPIOD
#define TRAINER_IN_GPIO_PIN LL_GPIO_PIN_12 // PD.12
#define TRAINER_IN_TIMER_Channel LL_TIM_CHANNEL_CH1
#define TRAINER_OUT_GPIO_PIN LL_GPIO_PIN_13 // PD.13
#define TRAINER_OUT_TIMER_Channel LL_TIM_CHANNEL_CH2
#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 (PERI1_FREQUENCY * TIMER_MULT_APB1)
//ROTARY emulation for trims as buttons
#define ROTARY_ENCODER_NAVIGATION
//BLUETOOTH
#define BLUETOOTH_ON_RCC_AHB1Periph RCC_AHB1Periph_GPIOI
#define BT_EN_GPIO GPIOI
#define BT_EN_GPIO_PIN GPIO_Pin_8 // PI.8
#define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOH)
#define BT_RCC_APB1Periph (RCC_APB1Periph_USART3)
#define BT_RCC_APB2Periph 0
#define BT_USART USART3
#define BT_GPIO_AF GPIO_AF_USART3
#define BT_USART_IRQn USART3_IRQn
#define BT_GPIO_TXRX GPIOB
#define BT_TX_GPIO_PIN GPIO_Pin_10 // PB.10
#define BT_RX_GPIO_PIN GPIO_Pin_11 // PB.11
#define BT_TX_GPIO_PinSource GPIO_PinSource10
#define BT_RX_GPIO_PinSource GPIO_PinSource11
#define BT_USART_IRQHandler USART3_IRQHandler
#define BT_CONNECTED_GPIO GPIOJ
#define BT_CONNECTED_GPIO_PIN GPIO_Pin_1 // PJ.01
#define BT_CMD_MODE_GPIO GPIOH
#define BT_CMD_MODE_GPIO_PIN GPIO_Pin_6 // PH.6
// Millisecond timer
#define MS_TIMER TIM14
#define MS_TIMER_IRQn TIM8_TRG_COM_TIM14_IRQn
#define MS_TIMER_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler
// Mixer scheduler timer
#define MIXER_SCHEDULER_TIMER TIM12
#define MIXER_SCHEDULER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#define MIXER_SCHEDULER_TIMER_IRQn TIM8_BRK_TIM12_IRQn
#define MIXER_SCHEDULER_TIMER_IRQHandler TIM8_BRK_TIM12_IRQHandler
#define LCD_W 480
#define LCD_H 320
#define LCD_PHYS_W 320
#define LCD_PHYS_H 480
#define LCD_DEPTH 16
#define LCD_CONTRAST_DEFAULT 20
#endif // _HAL_H_

View file

@ -0,0 +1,63 @@
/*
* 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 "board.h"
void hapticOff(void)
{
HAPTIC_TIMER_COMPARE_VALUE = 0;
}
void hapticOn(uint32_t pwmPercent)
{
if (pwmPercent > 100) {
pwmPercent = 100;
}
HAPTIC_TIMER_COMPARE_VALUE = pwmPercent;
}
void hapticInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = HAPTIC_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(HAPTIC_GPIO, &GPIO_InitStructure);
GPIO_PinAFConfig(HAPTIC_GPIO, HAPTIC_GPIO_PinSource, HAPTIC_GPIO_AF);
HAPTIC_GPIO_TIMER->ARR = 100;
HAPTIC_GPIO_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 10000 - 1;
HAPTIC_GPIO_TIMER->CCMR1 = HAPTIC_TIMER_MODE; // PWM
HAPTIC_GPIO_TIMER->CCER = HAPTIC_TIMER_OUTPUT_ENABLE;
HAPTIC_GPIO_TIMER->CCR1 = 0;
HAPTIC_GPIO_TIMER->EGR = TIM_EGR_UG;
HAPTIC_GPIO_TIMER->CR1 = TIM_CR1_CEN; // counter enable
HAPTIC_GPIO_TIMER->BDTR |= TIM_BDTR_MOE;
}
void hapticDone(void)
{
hapticOff();
RCC_AHB1PeriphClockCmd(HAPTIC_RCC_AHB1Periph, DISABLE);
}

View file

@ -0,0 +1,220 @@
/*
* 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 "hal.h"
#include "delays_driver.h"
#include "keys.h"
/* The output bit-order has to be:
0 LHL TR7L (Left equals down)
1 LHR TR7R
2 LVD TR5D
3 LVU TR5U
4 RVD TR6D
5 RVU TR6U
6 RHL TR8L
7 RHR TR8R
8 LSD TR1D
9 LSU TR1U
10 RSD TR2D
11 RSU TR2U
12 EX1D TR3D
13 EX1U TR3U
14 EX2D TR4D
15 EX2U TR4U
*/
enum PhysicalTrims
{
TR7L = 0,
TR7R,
TR5D = 2,
TR5U,
TR6D = 4,
TR6U,
TR8L = 6,
TR8R,
TR1D = 8,
TR1U,
TR2D = 10,
TR2U,
TR3D = 12,
TR3U,
TR4D = 14,
TR4U,
};
void keysInit()
{
stm32_gpio_enable_clock(GPIOB);
stm32_gpio_enable_clock(GPIOC);
stm32_gpio_enable_clock(GPIOD);
stm32_gpio_enable_clock(GPIOF);
stm32_gpio_enable_clock(GPIOH);
stm32_gpio_enable_clock(GPIOJ);
LL_GPIO_InitTypeDef pinInit;
LL_GPIO_StructInit(&pinInit);
pinInit.Mode = LL_GPIO_MODE_INPUT;
pinInit.Pull = LL_GPIO_PULL_DOWN;
pinInit.Pin = KEYS_GPIOB_PINS;
LL_GPIO_Init(GPIOB, &pinInit);
pinInit.Pin = KEYS_GPIOC_PINS;
LL_GPIO_Init(GPIOC, &pinInit);
pinInit.Pin = KEYS_GPIOD_PINS;
LL_GPIO_Init(GPIOD, &pinInit);
pinInit.Pin = KEYS_GPIOH_PINS;
LL_GPIO_Init(GPIOH, &pinInit);
pinInit.Pin = KEYS_GPIOJ_PINS;
LL_GPIO_Init(GPIOJ, &pinInit);
// Matrix outputs
pinInit.Mode = LL_GPIO_MODE_OUTPUT;
pinInit.Pull = LL_GPIO_PULL_NO;
pinInit.Pin = KEYS_OUT_GPIOG_PINS;
LL_GPIO_Init(GPIOG, &pinInit);
pinInit.Pin = KEYS_OUT_GPIOH_PINS;
LL_GPIO_Init(GPIOH, &pinInit);
}
static uint32_t _readKeyMatrix()
{
// This function avoids concurrent matrix agitation
uint32_t result = 0;
/* Bit 0 - TR3 down
* Bit 1 - TR3 up
* Bit 2 - TR4 down
* Bit 3 - TR4 up
* Bit 4 - TR5 down
* Bit 5 - TR5 up
* Bit 6 - TR6 down
* Bit 7 - TR6 up
* Bit 8 - TR7 left
* Bit 9 - TR7 right
* Bit 10 - TR8 left
* Bit 11 - TR8 right
*/
volatile static struct
{
uint32_t oldResult = 0;
uint8_t ui8ReadInProgress = 0;
} syncelem;
if (syncelem.ui8ReadInProgress != 0) return syncelem.oldResult;
// ui8ReadInProgress was 0, increment it
syncelem.ui8ReadInProgress++;
// Double check before continuing, as non-atomic, non-blocking so far
// If ui8ReadInProgress is above 1, then there was concurrent task calling it, exit
if (syncelem.ui8ReadInProgress > 1) return syncelem.oldResult;
// If we land here, we have exclusive access to Matrix
LL_GPIO_ResetOutputPin(TRIMS_GPIO_OUT1, TRIMS_GPIO_OUT1_PIN);
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT2, TRIMS_GPIO_OUT2_PIN);
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT3, TRIMS_GPIO_OUT3_PIN);
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT4, TRIMS_GPIO_OUT4_PIN);
delay_us(10);
if (~TRIMS_GPIO_REG_IN1 & TRIMS_GPIO_PIN_IN1)
result |= 1 << TR7L;
if (~TRIMS_GPIO_REG_IN2 & TRIMS_GPIO_PIN_IN2)
result |= 1 << TR7R;
if (~TRIMS_GPIO_REG_IN3 & TRIMS_GPIO_PIN_IN3)
result |= 1 << TR5D;
if (~TRIMS_GPIO_REG_IN4 & TRIMS_GPIO_PIN_IN4)
result |= 1 << TR5U;
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT1, TRIMS_GPIO_OUT1_PIN);
LL_GPIO_ResetOutputPin(TRIMS_GPIO_OUT2, TRIMS_GPIO_OUT2_PIN);
delay_us(10);
if (~TRIMS_GPIO_REG_IN1 & TRIMS_GPIO_PIN_IN1)
result |= 1 << TR3D;
if (~TRIMS_GPIO_REG_IN2 & TRIMS_GPIO_PIN_IN2)
result |= 1 << TR3U;
if (~TRIMS_GPIO_REG_IN3 & TRIMS_GPIO_PIN_IN3)
result |= 1 << TR4U;
if (~TRIMS_GPIO_REG_IN4 & TRIMS_GPIO_PIN_IN4)
result |= 1 << TR4D;
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT2, TRIMS_GPIO_OUT2_PIN);
LL_GPIO_ResetOutputPin(TRIMS_GPIO_OUT3, TRIMS_GPIO_OUT3_PIN);
delay_us(10);
if (~TRIMS_GPIO_REG_IN1 & TRIMS_GPIO_PIN_IN1)
result |= 1 << TR6U;
if (~TRIMS_GPIO_REG_IN2 & TRIMS_GPIO_PIN_IN2)
result |= 1 << TR6D;
if (~TRIMS_GPIO_REG_IN3 & TRIMS_GPIO_PIN_IN3)
result |= 1 << TR8L;
if (~TRIMS_GPIO_REG_IN4 & TRIMS_GPIO_PIN_IN4)
result |= 1 << TR8R;
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT3, TRIMS_GPIO_OUT3_PIN);
syncelem.oldResult = result;
syncelem.ui8ReadInProgress = 0;
return result;
}
uint32_t readKeys()
{
uint32_t result = 0;
if (getHatsAsKeys()) {
uint32_t mkeys = _readKeyMatrix();
if (mkeys & (1 << TR4D)) result |= 1 << KEY_ENTER;
if (mkeys & (1 << TR4U)) result |= 1 << KEY_EXIT;
}
return result;
}
uint32_t readTrims()
{
uint32_t result = 0;
result |= _readKeyMatrix();
if (~TRIMS_GPIO_REG_TR1U & TRIMS_GPIO_PIN_TR1U)
result |= 1 << (TR1U);
if (~TRIMS_GPIO_REG_TR1D & TRIMS_GPIO_PIN_TR1D)
result |= 1 << (TR1D);
if (~TRIMS_GPIO_REG_TR2U & TRIMS_GPIO_PIN_TR2U)
result |= 1 << (TR2U);
if (~TRIMS_GPIO_REG_TR2D & TRIMS_GPIO_PIN_TR2D)
result |= 1 << (TR2D);
return result;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,92 @@
/*
* 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_GPIO, LCD_SPI_CS_GPIO_PIN)
#define LCD_CS_LOW() LL_GPIO_ResetOutputPin(LCD_SPI_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)
#if 1
#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 )
#else
#define HORIZONTAL_SYNC_WIDTH ( 4 )
#define HORIZONTAL_BACK_PORCH ( 20 )
#define HORIZONTAL_FRONT_PORCH ( 60 - HORIZONTAL_BACK_PORCH )
#define VERTICAL_SYNC_HEIGHT ( 2 )
#define VERTICAL_BACK_PORCH ( 6 )
#define VERTICAL_FRONT_PORCH ( 14 - VERTICAL_BACK_PORCH )
#endif
#endif

View file

@ -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 "board.h"
#include "boards/generic_stm32/rgb_leds.h"
void ledInit()
{
// Do nothing
}
void ledOff()
{
for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) {
rgbSetLedColor(i, 0, 0, 0);
}
rgbLedColorApply();
}
void ledRed()
{
for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) {
rgbSetLedColor(i, 50, 0, 0);
}
rgbLedColorApply();
}
void ledGreen()
{
for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) {
rgbSetLedColor(i, 0, 50, 0);
}
rgbLedColorApply();
}
void ledBlue()
{
for (uint8_t i = 0; i < LED_STRIP_LENGTH; i++) {
rgbSetLedColor(i, 0, 0, 50);
}
rgbLedColorApply();
}

View file

@ -0,0 +1,29 @@
/*
* 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
constexpr coord_t INPUT_EDIT_CURVE_WIDTH = 132;
constexpr coord_t INPUT_EDIT_CURVE_HEIGHT = INPUT_EDIT_CURVE_WIDTH;
constexpr coord_t MENUS_MAX_HEIGHT = (MENUS_LINE_HEIGHT * 8) + 8;
// Disable rotary encoder, as the PL18 does not have one
#define ROTARY_ENCODER_SPEED() 0

View file

@ -0,0 +1,257 @@
/*
* 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 "board.h"
#include "stm32f4xx_fmc.h"
#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)
void SDRAM_GPIOConfig(void)
{
/*
------------------------------------------------------------------------------------------------------------------------------------------------
PC3 <-> FMC_SDCKE0 | PD0 <-> FMC_D2 | PE0 <-> FMC_NBL0 | PF0 <-> FMC_A0 | PG0 <-> FMC_A10 | PH3 <-> FMC_SDNE0 | PI0 <-> FMC_D24
| PD1 <-> FMC_D3 | PE1 <-> FMC_NBL1 | PF1 <-> FMC_A1 | PG1 <-> FMC_A11 | PH5 <-> FMC_SDNWE | PI1 <-> FMC_D25
| PD8 <-> FMC_D13 | PE7 <-> FMC_D4 | PF2 <-> FMC_A2 | PG4 <-> FMC_BA0 | PH8 <-> FMC_D16 | PI2 <-> FMC_D26
| PD9 <-> FMC_D14 | PE8 <-> FMC_D5 | PF3 <-> FMC_A3 | PG5 <-> FMC_BA1 | PH9 <-> FMC_D17 | PI3 <-> FMC_D27
| PD10 <-> FMC_D15 | PE9 <-> FMC_D6 | PF4 <-> FMC_A4 | PG8 <-> FMC_SDCLK | PH10 <-> FMC_D18 | PI4 <-> FMC_NBL2
| PD14 <-> FMC_D0 | PE10 <-> FMC_D7 | PF5 <-> FMC_A5 | PG15 <-> FMC_NCAS | PH11 <-> FMC_D19 | PI5 <-> FMC_NBL3
| PD15 <-> FMC_D1 | PE11 <-> FMC_D8 | PF11 <-> FMC_NRAS | | PH12 <-> FMC_D20 | PI6 <-> FMC_D28
| | PE12 <-> FMC_D9 | PF12 <-> FMC_A6 | | PH13 <-> FMC_D21 | PI7 <-> FMC_D29
| | PE13 <-> FMC_D10 | PF13 <-> FMC_A7 | | PH14 <-> FMC_D22 | PI9 <-> FMC_D30
| | PE14 <-> FMC_D11 | PF14 <-> FMC_A8 | | PH15 <-> FMC_D23 | PI10 <-> FMC_D31
| | PE15 <-> FMC_D12 | PF15 <-> FMC_A9 | | |
*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
/* GPIOC configuration */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource3 , GPIO_AF_FMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* GPIOD configuration */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* GPIOE configuration */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* GPIOF configuration */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource0, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource1, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource2, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource3, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource4, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource5, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource11, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource12, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource13, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource14, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource15, GPIO_AF_FMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOF, &GPIO_InitStructure);
/* GPIOG configuration */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource0 , GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource1 , GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource4 , GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource5 , GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource8 , GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource15 , GPIO_AF_FMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_15;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/* GPIOH configuration */
GPIO_PinAFConfig(GPIOH, GPIO_PinSource3, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOH, GPIO_PinSource5, GPIO_AF_FMC);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5;
GPIO_Init(GPIOH, &GPIO_InitStructure);
}
void SDRAM_InitSequence(void)
{
FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
uint32_t tmpr = 0;
/* Step 3 --------------------------------------------------------------------*/
/* Configure a clock configuration enable command */
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) {
}
/* Send the command */
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
/* Step 4 --------------------------------------------------------------------*/
/* Insert 100 ms delay */
delay_ms(100);
/* Step 5 --------------------------------------------------------------------*/
/* Configure a PALL (precharge all) command */
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) {
}
/* Send the command */
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
/* Step 6 --------------------------------------------------------------------*/
/* Configure a Auto-Refresh command */
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 4;
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) {
}
/* Send the first command */
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) {
}
/* Send the second command */
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
/* 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.FMC_CommandMode = FMC_Command_Mode_LoadMode;
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) {
}
/* Send the command */
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
/* Step 8 --------------------------------------------------------------------*/
/* Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter */
FMC_SetRefreshCount(683);//904
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) {
}
}
void SDRAM_Init(void)
{
//delay funcion needed
delaysInit();
// Clocks must be enabled here, because the sdramInit is called before main
RCC_AHB1PeriphClockCmd(SDRAM_RCC_AHB1Periph, ENABLE);
RCC_AHB3PeriphClockCmd(SDRAM_RCC_AHB3Periph, ENABLE);
/* GPIO configuration for FMC SDRAM bank */
SDRAM_GPIOConfig();
/* FMC Configuration ---------------------------------------------------------*/
FMC_SDRAMInitTypeDef FMC_SDRAMInitStructure;
FMC_SDRAMTimingInitTypeDef FMC_SDRAMTimingInitStructure;
/* FMC SDRAM Bank configuration */
/* Timing configuration for 90 Mhz of SD clock frequency (168Mhz/2) */
/* TMRD: 2 Clock cycles */
FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2;
/* TXSR: min=70ns (7x11.11ns) */
FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;
/* TRAS: min=42ns (4x11.11ns) max=120k (ns) */
FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4;
/* TRC: min=70 (7x11.11ns) */
FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 7;
/* TWR: min=1+ 7ns (1+1x11.11ns) */
FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2;
/* TRP: 20ns => 2x11.11ns */
FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2;
/* TRCD: 20ns => 2x11.11ns */
FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;
/* FMC SDRAM control configuration */
FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank1_SDRAM;
/* Row addressing: [7:0] */
FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
/* Column addressing: [11:0] */
FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = FMC_SDMemory_Width_16b;
FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
FMC_SDRAMInitStructure.FMC_CASLatency = FMC_CAS_Latency_3;
FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
FMC_SDRAMInitStructure.FMC_SDClockPeriod = FMC_SDClock_Period_2;
FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_Enable;
FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1;
FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
/* FMC SDRAM bank initialization */
FMC_SDRAMInit(&FMC_SDRAMInitStructure);
/* FMC SDRAM device initialization sequence */
SDRAM_InitSequence();
}

View file

@ -0,0 +1,470 @@
/*
* 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_hal_ll.h"
#include "stm32_hal.h"
#include "stm32_i2c_driver.h"
#include "stm32_gpio_driver.h"
#include "stm32_exti_driver.h"
#include "hal.h"
#include "timers_driver.h"
#include "delays_driver.h"
#include "touch_driver.h"
#include "debug.h"
#define TAP_TIME 25
#define I2C_TIMEOUT_MAX 5 // 5 ms
// FT6236 definitions
#define TOUCH_FT6236_I2C_ADDRESS (0x70>>1)
#define TOUCH_FT6236_REG_TH_GROUP 0x80
#define TOUCH_FT6236_REG_PERIODACTIVE 0x88
#define TOUCH_FT6236_REG_LIB_VER_H 0xa1
#define TOUCH_FT6236_REG_LIB_VER_L 0xa2
#define TOUCH_FT6236_REG_CIPHER 0xa3
#define TOUCH_FT6236_REG_FIRMID 0xa6
#define TOUCH_FT6236_REG_FOCALTECH_ID 0xa8
#define TOUCH_FT6236_REG_RELEASE_CODE_ID 0xaf
#define TOUCH_FT6206_REG_TD_STAT 0x02
#define TOUCH_FT6206_REG_P1_XH 0x03
#define TOUCH_FT6206_EVT_SHIFT 6
#define TOUCH_FT6206_EVT_MASK (3 << TOUCH_FT6206_EVT_SHIFT)
#define TOUCH_FT6206_EVT_CONTACT 0x02
#define TOUCH_FT6206_MASK_TD_STAT 0x0f
// CST340 definitions
#define TOUCH_CST340_I2C_ADDRESS 0x1a
#define TOUCH_CST340_REG_FINGER1 0x00
#define TOUCH_CST340_EVT_CONTACT 0x06
// CHSC5448 definitions
#define TOUCH_CHSC5448_I2C_ADDRESS 0x2e
#define TOUCH_CHSC5448_REG_ADDR 0x2c000020
#define TOUCH_CHSC5448_EVT_CONTACT 0x08
#define TOUCH_CHSC5448_MAX_POINTS 5
typedef enum {TC_NONE, TC_FT6236, TC_CST340, TC_CHSC5448} TouchController;
#if defined(DEBUG)
const char TOUCH_CONTROLLER_STR[][10] = {"", "FT6236", "CST340", "CHSC5448"};
#endif
TouchController touchController = TC_NONE;
struct TouchControllerDescriptor
{
bool (*hasTouchEvent)();
bool (*touchRead)(uint16_t * X, uint16_t * Y);
void (*printDebugInfo)();
bool needTranspose;
};
union rpt_point_t
{
struct
{
unsigned char x_l8;
unsigned char y_l8;
unsigned char z;
unsigned char x_h4:4;
unsigned char y_h4:4;
unsigned char id:4;
unsigned char event:4;
}rp;
unsigned char data[5];
};
extern uint8_t TouchControllerType;
static const TouchControllerDescriptor *tcd = nullptr;
static TouchState internalTouchState = {};
volatile static bool touchEventOccured;
static tmr10ms_t downTime = 0;
static tmr10ms_t tapTime = 0;
static short tapCount = 0;
static void _touch_exti_isr(void)
{
touchEventOccured = true;
}
static void _touch_exti_stop(void)
{
stm32_exti_disable(TOUCH_INT_EXTI_Line);
}
static void _touch_exti_config(void)
{
__HAL_RCC_SYSCFG_CLK_ENABLE();
LL_SYSCFG_SetEXTISource(TOUCH_INT_EXTI_Port, TOUCH_INT_EXTI_SysCfgLine);
stm32_exti_enable(TOUCH_INT_EXTI_Line, LL_EXTI_TRIGGER_FALLING, _touch_exti_isr);
}
static void _touch_gpio_config(void)
{
LL_GPIO_InitTypeDef gpioInit;
LL_GPIO_StructInit(&gpioInit);
stm32_gpio_enable_clock(TOUCH_RST_GPIO);
stm32_gpio_enable_clock(TOUCH_INT_GPIO);
gpioInit.Mode = LL_GPIO_MODE_OUTPUT;
gpioInit.Speed = LL_GPIO_SPEED_FREQ_LOW;
gpioInit.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
gpioInit.Pull = LL_GPIO_PULL_NO;
gpioInit.Pin = TOUCH_RST_GPIO_PIN;
LL_GPIO_Init(TOUCH_RST_GPIO, &gpioInit);
LL_GPIO_SetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN);
gpioInit.Pin = TOUCH_INT_GPIO_PIN;
gpioInit.Mode = LL_GPIO_MODE_INPUT;
gpioInit.Pull = LL_GPIO_PULL_UP;
gpioInit.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
LL_GPIO_Init(TOUCH_INT_GPIO, &gpioInit);
LL_GPIO_SetOutputPin(TOUCH_INT_GPIO, TOUCH_INT_GPIO_PIN);
}
static void _touch_reset()
{
LL_GPIO_ResetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN);
delay_ms(10);
LL_GPIO_SetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN);
delay_ms(300);
}
static void _i2c_init(void)
{
TRACE("Touch I2C Init");
if (stm32_i2c_init(TOUCH_I2C_BUS, TOUCH_I2C_CLK_RATE) < 0) {
TRACE("Touch I2C Init ERROR: stm32_i2c_init failed");
return;
}
}
static void _i2c_reInit(void)
{
stm32_i2c_deinit(TOUCH_I2C_BUS);
_i2c_init();
}
static int _i2c_read(uint8_t addr, uint32_t reg, uint8_t regSize, uint8_t* data, uint16_t len, uint32_t timeout)
{
if (regSize > 2) {
if(stm32_i2c_master_tx(TOUCH_I2C_BUS, addr, (uint8_t*) &reg, regSize, 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;
} else {
return stm32_i2c_read(TOUCH_I2C_BUS, addr, reg, regSize, data, len, timeout);
}
}
static uint8_t _i2c_readRetry(uint8_t addr, uint32_t reg, uint8_t regSize)
{
uint8_t result;
uint8_t tryCount = 3;
while (_i2c_read(addr, reg, regSize, &result, 1, I2C_TIMEOUT_MAX) < 0) {
if (--tryCount == 0) break;
_i2c_reInit();
}
return result;
}
static uint16_t _i2c_readMultipleRetry(uint8_t addr, uint32_t reg, uint8_t regSize, uint8_t * buffer, uint16_t length)
{
uint8_t tryCount = 3;
while (_i2c_read(addr, reg, regSize, buffer, length, I2C_TIMEOUT_MAX) < 0) {
if (--tryCount == 0) break;
_i2c_reInit();
}
return length;
}
static bool ft6236TouchRead(uint16_t * X, uint16_t * Y)
{
// Read register FT6206_TD_STAT_REG to check number of touches detection
uint8_t nbTouch = _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6206_REG_TD_STAT, 1);
nbTouch &= TOUCH_FT6206_MASK_TD_STAT;
bool hasTouch = nbTouch > 0;
if (hasTouch) {
uint8_t dataxy[4];
// Read X and Y positions and event
_i2c_readMultipleRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6206_REG_P1_XH, 1, dataxy, sizeof(dataxy));
// Send back ready X position to caller
*X = ((dataxy[0] & 0x0f) << 8) | dataxy[1];
// Send back ready Y position to caller
*Y = ((dataxy[2] & 0x0f) << 8) | dataxy[3];
uint8_t event = (dataxy[0] & TOUCH_FT6206_EVT_MASK) >> TOUCH_FT6206_EVT_SHIFT;
return event == TOUCH_FT6206_EVT_CONTACT;
}
return false;
}
static bool ft6236HasTouchEvent()
{
return touchEventOccured;
}
static void ft6236PrintDebugInfo()
{
#if defined(DEBUG)
TRACE("ft6x36: thrhld = %d", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_TH_GROUP, 1) * 4);
TRACE("ft6x36: rep rate=", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_PERIODACTIVE, 1) * 10);
TRACE("ft6x36: fw lib 0x%02X %02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_LIB_VER_H, 1),
_i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_LIB_VER_L, 1));
TRACE("ft6x36: fw v 0x%02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_FIRMID, 1));
TRACE("ft6x36: CHIP ID 0x%02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_CIPHER, 1));
TRACE("ft6x36: CTPM ID 0x%02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_FOCALTECH_ID, 1));
TRACE("ft6x36: rel code 0x%02X", _i2c_readRetry(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_RELEASE_CODE_ID, 1));
#endif
}
static bool cst340TouchRead(uint16_t * X, uint16_t * Y)
{
uint8_t data[4];
// Read X and Y positions
_i2c_readMultipleRetry(TOUCH_CST340_I2C_ADDRESS, TOUCH_CST340_REG_FINGER1, 1, data, sizeof(data));
// Send back X position to caller
if (X) *X = ((data[1]<<4) + ((data[3]>>4)&0x0f));
// Send back Y position to caller
if (Y) *Y = ((data[2]<<4) + ((data[3])&0x0f));
return data[0] == TOUCH_CST340_EVT_CONTACT;
}
static bool cst340HasTouchEvent()
{
static bool lastHasTouch = false;
bool ret = touchEventOccured;
if (ret) {
uint8_t hasTouch = cst340TouchRead(nullptr, nullptr);
if (!hasTouch && !lastHasTouch) {
TRACE("Interrupt occurs without touch event!!");
touchEventOccured = false;
ret = false;
}
lastHasTouch = hasTouch;
}
return ret;
}
static void cst340PrintDebugInfo()
{
// TODO, when necessary
}
static bool chsc5448TouchRead(uint16_t * X, uint16_t * Y)
{
static uint8_t readbuffer[84];
const uint8_t reportSize = ((TOUCH_CHSC5448_MAX_POINTS * 5 + 2) + 3) & 0xfc;
int ptCnt = 0;
union rpt_point_t* ppt;
_i2c_readMultipleRetry(TOUCH_CHSC5448_I2C_ADDRESS, TOUCH_CHSC5448_REG_ADDR, 4, readbuffer, reportSize);
ptCnt = readbuffer[1] & 0x0f;
ppt = (union rpt_point_t*)&readbuffer[2];
*X = ((ppt->rp.x_h4 & 0x0f) << 8) | ppt->rp.x_l8;
*Y = ((ppt->rp.y_h4 & 0x0f) << 8) | ppt->rp.y_l8;
uint8_t event = ppt->rp.event;
return ptCnt > 0 && event == TOUCH_CHSC5448_EVT_CONTACT;
}
static bool chsc5448HasTouchEvent()
{
return touchEventOccured;
}
static void chsc5448PrintDebugInfo()
{
// TODO, when necessary
}
static const TouchControllerDescriptor FT6236 =
{
.hasTouchEvent = ft6236HasTouchEvent,
.touchRead = ft6236TouchRead,
.printDebugInfo = ft6236PrintDebugInfo,
.needTranspose = true,
};
static const TouchControllerDescriptor CST340 =
{
.hasTouchEvent = cst340HasTouchEvent,
.touchRead = cst340TouchRead,
.printDebugInfo = cst340PrintDebugInfo,
.needTranspose = true,
};
static const TouchControllerDescriptor CHSC5448 =
{
.hasTouchEvent = chsc5448HasTouchEvent,
.touchRead = chsc5448TouchRead,
.printDebugInfo = chsc5448PrintDebugInfo,
.needTranspose = false,
};
void _detect_touch_controller()
{
if (stm32_i2c_is_dev_ready(TOUCH_I2C_BUS, TOUCH_CST340_I2C_ADDRESS, 3, I2C_TIMEOUT_MAX) == 0) {
touchController = TC_CST340;
tcd = &CST340;
TouchControllerType = 0;
} else if (stm32_i2c_is_dev_ready(TOUCH_I2C_BUS, TOUCH_CHSC5448_I2C_ADDRESS, 3, I2C_TIMEOUT_MAX) == 0) {
touchController = TC_CHSC5448;
tcd = &CHSC5448;
TouchControllerType = 0;
} else {
touchController = TC_FT6236;
tcd = &FT6236;
TouchControllerType = 1;
}
}
void touchPanelDeInit()
{
_touch_exti_stop();
}
bool touchPanelInit()
{
_touch_gpio_config();
_i2c_init();
_touch_reset();
_detect_touch_controller();
_touch_exti_config();
tcd->printDebugInfo();
return touchController != TC_NONE;
}
bool touchPanelEventOccured()
{
return tcd->hasTouchEvent();
}
struct TouchState touchPanelRead()
{
if (!touchEventOccured) return internalTouchState;
touchEventOccured = false;
tmr10ms_t now = get_tmr10ms();
internalTouchState.tapCount = 0;
unsigned short touchX;
unsigned short touchY;
bool hasTouchContact = tcd->touchRead(&touchX, &touchY);
if (tcd->needTranspose) {
// Touch sensor is rotated by 90 deg
unsigned short tmp = touchY;
touchY = 319 - touchX;
touchX = tmp;
}
if (hasTouchContact) {
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;
}
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;
#if defined(DEBUG)
TRACE("%s: event=%d,X=%d,Y=%d", TOUCH_CONTROLLER_STR[touchController], ret.event, ret.x, ret.y);
#endif
return ret;
}
struct TouchState getInternalTouchState()
{
return internalTouchState;
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "touch.h"
extern void touchPanelDeInit();
extern bool touchPanelInit();
struct TouchState touchPanelRead();
bool touchPanelEventOccured();
struct TouchState getInternalTouchState();

View file

@ -0,0 +1,560 @@
/*
* 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_hal_ll.h"
#include "stm32_hal.h"
#include "stm32_i2c_driver.h"
#include "stm32_gpio_driver.h"
#include "stm32_exti_driver.h"
#include "hal.h"
#include "timers_driver.h"
#include "delays_driver.h"
#include "tp_cst340.h"
#include "debug.h"
#define TOUCH_FT6236_I2C_ADDRESS (0x70>>1)
#define TOUCH_CST340_I2C_ADDRESS 0x1A
extern uint8_t TouchControllerType;
volatile static bool touchEventOccured;
enum TouchControllers {TC_NONE, TC_FT6236, TC_CST340};
TouchControllers touchController = TC_NONE;
static tc_handle_TypeDef tc_handle = {0, 0};
tmr10ms_t downTime = 0;
tmr10ms_t tapTime = 0;
short tapCount = 0;
#define TAP_TIME 25
struct TouchControllerDescriptor
{
void (*read)(uint16_t * X, uint16_t * Y, uint32_t * event);
uint8_t (*detectTouch)();
void (*printDebugInfo)();
uint32_t contactEvent;
};
static const TouchControllerDescriptor *tc = nullptr;
static TouchState internalTouchState = {};
static void _cst340_exti_isr(void)
{
touchEventOccured = true;
}
static void TOUCH_AF_ExtiStop(void)
{
stm32_exti_disable(TOUCH_INT_EXTI_Line);
}
static void TOUCH_AF_ExtiConfig(void)
{
__HAL_RCC_SYSCFG_CLK_ENABLE();
LL_SYSCFG_SetEXTISource(TOUCH_INT_EXTI_Port, TOUCH_INT_EXTI_SysCfgLine);
stm32_exti_enable(TOUCH_INT_EXTI_Line,
LL_EXTI_TRIGGER_FALLING,
_cst340_exti_isr);
}
static void TOUCH_AF_GPIOConfig(void)
{
LL_GPIO_InitTypeDef gpioInit;
LL_GPIO_StructInit(&gpioInit);
stm32_gpio_enable_clock(TOUCH_RST_GPIO);
stm32_gpio_enable_clock(TOUCH_INT_GPIO);
gpioInit.Mode = LL_GPIO_MODE_OUTPUT;
gpioInit.Speed = LL_GPIO_SPEED_FREQ_LOW;
gpioInit.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
gpioInit.Pull = LL_GPIO_PULL_NO;
gpioInit.Pin = TOUCH_RST_GPIO_PIN;
LL_GPIO_Init(TOUCH_RST_GPIO, &gpioInit);
LL_GPIO_SetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN);
gpioInit.Pin = TOUCH_INT_GPIO_PIN;
gpioInit.Mode = LL_GPIO_MODE_INPUT;
gpioInit.Pull = LL_GPIO_PULL_UP;
gpioInit.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
LL_GPIO_Init(TOUCH_INT_GPIO, &gpioInit);
LL_GPIO_SetOutputPin(TOUCH_INT_GPIO, TOUCH_INT_GPIO_PIN);
}
void I2C_Init_Radio(void)
{
TRACE("CST340 I2C Init");
if (stm32_i2c_init(TOUCH_I2C_BUS, TOUCH_I2C_CLK_RATE) < 0) {
TRACE("CST340 ERROR: stm32_i2c_init failed");
return;
}
}
// void Touch_DeInit()
// {
// I2C_DeInit(I2C_B1);
// __HAL_RCC_I2C1_FORCE_RESET();
// delay_ms(150);
// __HAL_RCC_I2C1_RELEASE_RESET();
// }
#define I2C_TIMEOUT_MAX 5 // 5 ms
bool touch_i2c_read(uint8_t addr, uint8_t reg, uint8_t * data, uint8_t len)
{
// if(touchController == TC_CST836U)
// {
// 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;
// } else {
if (stm32_i2c_read(TOUCH_I2C_BUS, addr, reg, 1, data, len, I2C_TIMEOUT_MAX) < 0)
return false;
// }
return true;
}
#if 0
static bool touch_i2c_write(uint8_t addr, uint8_t reg, uint8_t * data, uint8_t len)
{
if (stm32_i2c_write(TOUCH_I2C_BUS, addr, reg, 1, data, len, I2C_TIMEOUT_MAX) < 0)
return false;
return true;
}
static void TS_IO_Write(uint8_t addr, uint8_t reg, uint8_t data)
{
uint8_t tryCount = 3;
while (!touch_i2c_write(addr, reg, &data, 1)) {
if (--tryCount == 0) break;
I2C_Init();
}
}
#endif
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;
I2C_Init_Radio();
// I2C_Init();
}
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;
I2C_Init_Radio();
// I2C_Init();
}
return 1;
}
static void touch_ft6236_debug_info(void)
{
#if defined(DEBUG)
TRACE("ft6x36: thrhld = %d", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_TH_GROUP) * 4);
TRACE("ft6x36: rep rate=", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_PERIODACTIVE) * 10);
TRACE("ft6x36: fw lib 0x%02X %02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_LIB_VER_H), TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_LIB_VER_L));
TRACE("ft6x36: fw v 0x%02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_FIRMID));
TRACE("ft6x36: CHIP ID 0x%02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_CIPHER));
TRACE("ft6x36: CTPM ID 0x%02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_FOCALTECH_ID));
TRACE("ft6x36: rel code 0x%02X", TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, TOUCH_FT6236_REG_RELEASE_CODE_ID));
#endif
}
/**
* @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 ft6x06_TS_DetectTouch()
{
volatile uint8_t nbTouch = 0;
/* Read register FT6206_TD_STAT_REG to check number of touches detection */
nbTouch = TS_IO_Read(TOUCH_FT6236_I2C_ADDRESS, FT6206_TD_STAT_REG);
nbTouch &= FT6206_TD_STAT_MASK;
if (nbTouch > FT6206_MAX_DETECTABLE_TOUCH) {
/* If invalid number of touch detected, set it to zero */
nbTouch = 0;
}
/* Update ft6x06 driver internal global : current number of active touches */
tc_handle.currActiveTouchNb = nbTouch;
/* Reset current active touch index on which to work on */
tc_handle.currActiveTouchIdx = 0;
return (nbTouch);
}
#if 0
/**
* @brief Get the touch detailed informations on touch number 'touchIdx' (0..1)
* This touch detailed information contains :
* - weight that was applied to this touch
* - sub-area of the touch in the touch panel
* - event of linked to the touch (press down, lift up, ...)
* @param DeviceAddr: Device address on communication Bus (I2C slave address of FT6x06).
* @param touchIdx : Passed index of the touch (0..1) on which we want to get the
* detailed information.
* @param pWeight : Pointer to to get the weight information of 'touchIdx'.
* @param pArea : Pointer to to get the sub-area information of 'touchIdx'.
* @param pEvent : Pointer to to get the event information of 'touchIdx'.
* @retval None.
*/
static void ft6x06_TS_GetTouchInfo(uint16_t DeviceAddr,
uint32_t touchIdx,
uint32_t * pWeight,
uint32_t * pArea,
uint32_t * pEvent)
{
uint8_t regAddress = 0;
uint8_t dataxy[3];
if (touchIdx < ft6x06_handle.currActiveTouchNb) {
switch (touchIdx) {
case 0 :
regAddress = FT6206_P1_WEIGHT_REG;
break;
case 1 :
regAddress = FT6206_P2_WEIGHT_REG;
break;
default :
break;
} /* end switch(touchIdx) */
/* Read weight, area and Event Id of touch index */
TS_IO_ReadMultiple(DeviceAddr, regAddress, dataxy, sizeof(dataxy));
/* Return weight of touch index */
*pWeight = (dataxy[0] & FT6206_TOUCH_WEIGHT_MASK) >> FT6206_TOUCH_WEIGHT_SHIFT;
/* Return area of touch index */
*pArea = (dataxy[1] & FT6206_TOUCH_AREA_MASK) >> FT6206_TOUCH_AREA_SHIFT;
/* Return Event Id of touch index */
*pEvent = (dataxy[2] & FT6206_TOUCH_EVT_FLAG_MASK) >> FT6206_TOUCH_EVT_FLAG_SHIFT;
} /* of if(touchIdx < ft6x06_handle.currActiveTouchNb) */
}
#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 ft6x06_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 = FT6206_P1_XH_REG;
break;
case 1 :
regAddress = FT6206_P2_XH_REG;
break;
default :
break;
}
/* Read X and Y positions */
TS_IO_ReadMultiple(TOUCH_FT6236_I2C_ADDRESS, regAddress, dataxy, sizeof(dataxy));
/* Send back ready X position to caller */
*X = ((dataxy[0] & FT6206_MSB_MASK) << 8) | (dataxy[1] & FT6206_LSB_MASK);
/* Send back ready Y position to caller */
*Y = ((dataxy[2] & FT6206_MSB_MASK) << 8) | (dataxy[3] & FT6206_LSB_MASK);
*event = (dataxy[0] & FT6206_TOUCH_EVT_FLAG_MASK) >> FT6206_TOUCH_EVT_FLAG_SHIFT;
/*
uint32_t weight;
uint32_t area;
ft6x06_TS_GetTouchInfo(DeviceAddr, ft6x06_handle.currActiveTouchIdx, &weight, &area, event);
*/
tc_handle.currActiveTouchIdx++;
}
}
static void touch_cst340_debug_info(void)
{
#if 0 // Disabled because cannot compile, will fix when necessary
#if defined(DEBUG)
uint8_t tmp[4];
if (!TS_IO_Write(CST340_MODE_DEBUG_INFO, tmp, 0))
TRACE("CST340 chip NOT FOUND");
// Check the value, expected ChipID
uint32_t chipId = tmp[0] << 8) + tmp[1];
if (!I2C_CST340_ReadRegister(CST340_FWVER_REG, tmp, 4))
TRACE("Error reading CST340 firmware version!");
uint32_t fwVersion = tmp[0] << 24 | tmp[1]<<16 | tmp[2]<<8 | tmp[0];
// Enter normal mode
if (!I2C_CST340_WriteRegister(CST340_MODE_NORMAL, tmp, 0))
TRACE("ERROR chaning CST340 mode back to normal!");
TRACE("cst340: fw ver 0x%08X", fwVersion);
TRACE("cst836u: chip id 0x%04X", chipId);
#endif
#endif
}
/**
* @brief Get the touch screen X and Y positions values
* @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 cst340_TS_GetXY(uint16_t * X, uint16_t * Y, uint32_t * event)
{
uint8_t dataxy[4];
/* Read X and Y positions */
TS_IO_ReadMultiple(TOUCH_CST340_I2C_ADDRESS, CST340_FINGER1_REG, dataxy, sizeof(dataxy));
/* Send back ready X position to caller */
*X = ((dataxy[1]<<4) + ((dataxy[3]>>4)&0x0f));
*Y = ((dataxy[2]<<4) + ((dataxy[3])&0x0f));
/* Send back ready Y position to caller */
*event = dataxy[0];
}
/**
* @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
*/
static uint8_t cst340_TS_DetectTouch()
{
uint8_t nbTouch;
uint8_t reg = TS_IO_Read(TOUCH_CST340_I2C_ADDRESS, CST340_FINGER1_REG);
if( reg == 0x06 )
nbTouch = 1;
else
nbTouch = 0;
tc_handle.currActiveTouchNb = nbTouch;
tc_handle.currActiveTouchIdx = 0;
return (nbTouch);
}
void TouchReset()
{
LL_GPIO_ResetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN);
delay_ms(10);
LL_GPIO_SetOutputPin(TOUCH_RST_GPIO, TOUCH_RST_GPIO_PIN);
delay_ms(300);
}
static const TouchControllerDescriptor FT6236 =
{
.read = ft6x06_TS_GetXY,
.detectTouch = ft6x06_TS_DetectTouch,
.printDebugInfo = touch_ft6236_debug_info,
.contactEvent = FT6206_TOUCH_EVT_FLAG_CONTACT
};
static const TouchControllerDescriptor CST340 =
{
.read = cst340_TS_GetXY,
.detectTouch = cst340_TS_DetectTouch,
.printDebugInfo = touch_cst340_debug_info,
.contactEvent = CST340_TOUCH_EVT_FLAG_CONTACT
};
void detectTouchController()
{
if( stm32_i2c_is_dev_ready(TOUCH_I2C_BUS, TOUCH_CST340_I2C_ADDRESS, 3, 5) == 0)
{
TouchControllerType = 0;
touchController = TC_CST340;
tc = &CST340;
} else {
TouchControllerType = 1;
touchController = TC_FT6236;
tc = &FT6236;
}
}
void TouchInit()
{
TOUCH_AF_GPIOConfig(); // SET RST=OUT INT=IN INT=HIGH
I2C_Init_Radio();
TouchReset();
detectTouchController();
TOUCH_AF_ExtiConfig();
tc->printDebugInfo();
}
void handleTouch()
{
unsigned short touchX;
unsigned short touchY;
uint32_t tEvent = 0;
tc->read(&touchX, &touchY, &tEvent);
#if defined(DEBUG)
TRACE("handleTouch: touchX=%d, touchY=%d, tEvent=%d", touchX, touchY, tEvent);
#endif
// touch sensor is rotated by 90 deg
unsigned short tmp = touchY;
touchY = 319 - touchX;
touchX = tmp;
if (tEvent == tc->contactEvent) {
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;
}
}
}
static bool lastHasTouch = false;
bool touchPanelEventOccured()
{
bool result = touchEventOccured;
uint8_t hasTouch = false;
if (touchEventOccured) {
hasTouch = tc->detectTouch();
if (!hasTouch && !lastHasTouch) {
touchEventOccured = false;
result = false;
}
lastHasTouch = hasTouch;
}
#if defined(DEBUG)
TRACE("TouchEvent: %d, %d, %d, %d", touchEventOccured, lastHasTouch, hasTouch, result);
#endif
return result;
}
TouchState touchPanelRead()
{
if (!touchEventOccured) return internalTouchState;
touchEventOccured = false;
tmr10ms_t now = get_tmr10ms();
internalTouchState.tapCount = 0;
if (tc->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;
#if defined(DEBUG)
TRACE("%s: Event = %d", touchController == TC_CST340 ? "CST340" : "FT6236", ret.event);
#endif
return ret;
}
TouchState getInternalTouchState()
{
return internalTouchState;
}

View file

@ -0,0 +1,289 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "touch.h"
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;
#define TOUCH_FT6236_MAX_TOUCH_POINTS 2
#define TOUCH_FT6236_REG_TH_GROUP 0x80
#define TOUCH_FT6236_REG_PERIODACTIVE 0x88
#define TOUCH_FT6236_REG_LIB_VER_H 0xa1
#define TOUCH_FT6236_REG_LIB_VER_L 0xa2
#define TOUCH_FT6236_REG_CIPHER 0xa3
#define TOUCH_FT6236_REG_FIRMID 0xa6
#define TOUCH_FT6236_REG_FOCALTECH_ID 0xa8
#define TOUCH_FT6236_REG_RELEASE_CODE_ID 0xaf
#define TOUCH_FT6236_EVENT_PRESS_DOWN 0
#define TOUCH_FT6236_EVENT_LIFT_UP 1
#define TOUCH_FT6236_EVENT_CONTACT 2
#define TOUCH_FT6236_EVENT_NO_EVENT 3
#define TOUCH_FT6236_GESTURE_MOVE_FLAG 0x10
#define TOUCH_FT6236_GESTURE_MOVE_UP 0x10
#define TOUCH_FT6236_GESTURE_MOVE_RIGHT 0x14
#define TOUCH_FT6236_GESTURE_MOVE_DOWN 0x18
#define TOUCH_FT6236_GESTURE_MOVE_LEFT 0x1C
#define TOUCH_FT6236_GESTURE_ZOOM_IN 0x48
#define TOUCH_FT6236_GESTURE_ZOOM_OUT 0x49
#define TOUCH_FT6236_GESTURE_NONE 0x00
#define TOUCH_GESTURE_UP ((TOUCH_FT6236_GESTURE_MOVE_UP & 0x0F)+1)
#define TOUCH_GESTURE_DOWN ((TOUCH_FT6236_GESTURE_MOVE_DOWN & 0x0F)+1)
#define TOUCH_GESTURE_LEFT ((TOUCH_FT6236_GESTURE_MOVE_LEFT & 0x0F)+1)
#define TOUCH_GESTURE_RIGHT ((TOUCH_FT6236_GESTURE_MOVE_RIGHT & 0x0F)+1)
#define TOUCH_GESTURE_MOUSE_DOWN (0x80+TOUCH_FT6236_EVENT_PRESS_DOWN)
#define TOUCH_GESTURE_MOUSE_UP (0x80+TOUCH_FT6236_EVENT_LIFT_UP)
#define TOUCH_GESTURE_MOUSE_MOVE (0x80+TOUCH_FT6236_EVENT_CONTACT)
#define TOUCH_GESTURE_MOUSE_NONE (0x80+TOUCH_FT6236_EVENT_NO_EVENT)
/* Maximum border values of the touchscreen pad */
#define FT_6206_MAX_WIDTH ((uint16_t)800) /* Touchscreen pad max width */
#define FT_6206_MAX_HEIGHT ((uint16_t)480) /* Touchscreen pad max height */
/* Possible values of driver functions return status */
#define FT6206_STATUS_OK 0
#define FT6206_STATUS_NOT_OK 1
/* Max detectable simultaneous touches */
#define FT6206_MAX_DETECTABLE_TOUCH 2
/**
* @brief : Definitions for FT6206 I2C register addresses on 8 bit
**/
/* Current mode register of the FT6206 (R/W) */
#define FT6206_DEV_MODE_REG 0x00
/* Possible values of FT6206_DEV_MODE_REG */
#define FT6206_DEV_MODE_WORKING 0x00
#define FT6206_DEV_MODE_FACTORY 0x04
#define FT6206_DEV_MODE_MASK 0x7
#define FT6206_DEV_MODE_SHIFT 4
/* Gesture ID register */
#define FT6206_GEST_ID_REG 0x01
/* Possible values of FT6206_GEST_ID_REG */
#define FT6206_GEST_ID_NO_GESTURE 0x00
#define FT6206_GEST_ID_MOVE_UP 0x10
#define FT6206_GEST_ID_MOVE_RIGHT 0x14
#define FT6206_GEST_ID_MOVE_DOWN 0x18
#define FT6206_GEST_ID_MOVE_LEFT 0x1C
#define FT6206_GEST_ID_ZOOM_IN 0x48
#define FT6206_GEST_ID_ZOOM_OUT 0x49
/* Touch Data Status register : gives number of active touch points (0..2) */
#define FT6206_TD_STAT_REG 0x02
/* Values related to FT6206_TD_STAT_REG */
#define FT6206_TD_STAT_MASK 0x0F
#define FT6206_TD_STAT_SHIFT 0x00
/* Values Pn_XH and Pn_YH related */
#define FT6206_TOUCH_EVT_FLAG_PRESS_DOWN 0x00
#define FT6206_TOUCH_EVT_FLAG_LIFT_UP 0x01
#define FT6206_TOUCH_EVT_FLAG_CONTACT 0x02
#define FT6206_TOUCH_EVT_FLAG_NO_EVENT 0x03
#define FT6206_TOUCH_EVT_FLAG_SHIFT 6
#define FT6206_TOUCH_EVT_FLAG_MASK (3 << FT6206_TOUCH_EVT_FLAG_SHIFT)
#define FT6206_MSB_MASK 0x0F
#define FT6206_MSB_SHIFT 0
/* Values Pn_XL and Pn_YL related */
#define FT6206_LSB_MASK 0xFF
#define FT6206_LSB_SHIFT 0
#define FT6206_P1_XH_REG 0x03
#define FT6206_P1_XL_REG 0x04
#define FT6206_P1_YH_REG 0x05
#define FT6206_P1_YL_REG 0x06
/* Touch Pressure register value (R) */
#define FT6206_P1_WEIGHT_REG 0x07
/* Values Pn_WEIGHT related */
#define FT6206_TOUCH_WEIGHT_MASK 0xFF
#define FT6206_TOUCH_WEIGHT_SHIFT 0
/* Touch area register */
#define FT6206_P1_MISC_REG 0x08
/* Values related to FT6206_Pn_MISC_REG */
#define FT6206_TOUCH_AREA_MASK (0x04 << 4)
#define FT6206_TOUCH_AREA_SHIFT 0x04
#define FT6206_P2_XH_REG 0x09
#define FT6206_P2_XL_REG 0x0A
#define FT6206_P2_YH_REG 0x0B
#define FT6206_P2_YL_REG 0x0C
#define FT6206_P2_WEIGHT_REG 0x0D
#define FT6206_P2_MISC_REG 0x0E
/* Threshold for touch detection */
#define FT6206_TH_GROUP_REG 0x80
/* Values FT6206_TH_GROUP_REG : threshold related */
#define FT6206_THRESHOLD_MASK 0xFF
#define FT6206_THRESHOLD_SHIFT 0
/* Filter function coefficients */
#define FT6206_TH_DIFF_REG 0x85
/* Control register */
#define FT6206_CTRL_REG 0x86
/* Values related to FT6206_CTRL_REG */
/* Will keep the Active mode when there is no touching */
#define FT6206_CTRL_KEEP_ACTIVE_MODE 0x00
/* Switching from Active mode to Monitor mode automatically when there is no touching */
#define FT6206_CTRL_KEEP_AUTO_SWITCH_MONITOR_MODE 0x01
/* The time period of switching from Active mode to Monitor mode when there is no touching */
#define FT6206_TIMEENTERMONITOR_REG 0x87
/* Report rate in Active mode */
#define FT6206_PERIODACTIVE_REG 0x88
/* Report rate in Monitor mode */
#define FT6206_PERIODMONITOR_REG 0x89
/* The value of the minimum allowed angle while Rotating gesture mode */
#define FT6206_RADIAN_VALUE_REG 0x91
/* Maximum offset while Moving Left and Moving Right gesture */
#define FT6206_OFFSET_LEFT_RIGHT_REG 0x92
/* Maximum offset while Moving Up and Moving Down gesture */
#define FT6206_OFFSET_UP_DOWN_REG 0x93
/* Minimum distance while Moving Left and Moving Right gesture */
#define FT6206_DISTANCE_LEFT_RIGHT_REG 0x94
/* Minimum distance while Moving Up and Moving Down gesture */
#define FT6206_DISTANCE_UP_DOWN_REG 0x95
/* Maximum distance while Zoom In and Zoom Out gesture */
#define FT6206_DISTANCE_ZOOM_REG 0x96
/* High 8-bit of LIB Version info */
#define FT6206_LIB_VER_H_REG 0xA1
/* Low 8-bit of LIB Version info */
#define FT6206_LIB_VER_L_REG 0xA2
/* Chip Selecting */
#define FT6206_CIPHER_REG 0xA3
/* Interrupt mode register (used when in interrupt mode) */
#define FT6206_GMODE_REG 0xA4
#define FT6206_G_MODE_INTERRUPT_MASK 0x03
#define FT6206_G_MODE_INTERRUPT_SHIFT 0x00
/* Possible values of FT6206_GMODE_REG */
#define FT6206_G_MODE_INTERRUPT_POLLING 0x00
#define FT6206_G_MODE_INTERRUPT_TRIGGER 0x01
/* Current power mode the FT6206 system is in (R) */
#define FT6206_PWR_MODE_REG 0xA5
/* FT6206 firmware version */
#define FT6206_FIRMID_REG 0xA6
/* FT6206 Chip identification register */
#define FT6206_CHIP_ID_REG 0xA8
/* Possible values of FT6206_CHIP_ID_REG */
#define FT6206_ID_VALUE 0x11
/* Release code version */
#define FT6206_RELEASE_CODE_ID_REG 0xAF
/* Current operating mode the FT6206 system is in (R) */
#define FT6206_STATE_REG 0xBC
#define HAS_TOUCH_PANEL() touchCST340Flag == true
#define CST340_MODE_DEBUG_INFO 0xD101 // To read out chip ID and firmware version
#define CST340_MODE_NORMAL 0xD109 // Normal mode
#define CST340_FINGER1_REG 0xD000 // Touch info register
#define CST340_CHIPTYPE_REG 0xD204 // uint16_t chip IC type & uint16_t project ID register
#define CST340_FWVER_REG 0xD208 // Firmware version register(uint8_t major, uint8_t minor, uint16_t build)
#define CST340_TOUCH_EVT_FLAG_CONTACT 6
#define CST340_CHIP_ID 0x011C // Expected answer to CST340_CHIPTYPE_REG query for the ChipID field
#define TOUCH_POINTS_MAX 5 // Max touch points
#define TOUCH_ACK 0
#define TOUCH_NACK 1
#define CST340_I2C_ADDR 0x1A
extern bool touchCST340Flag;
extern uint32_t touchI2Chiccups;
extern uint16_t touchICfwver;
void TouchInit();
struct TouchState touchPanelRead();
bool touchPanelEventOccured();
PACK(typedef struct {
uint8_t track;
uint16_t x;
uint16_t y;
uint16_t size;
uint8_t reserved;
}) TouchPoint;
PACK(struct TouchData {
union
{
TouchPoint points[TOUCH_POINTS_MAX];
uint8_t data[TOUCH_POINTS_MAX * sizeof(TouchPoint)];
};
});
#define TPRST_LOW() do { TOUCH_RST_GPIO->BSRRH = TOUCH_RST_GPIO_PIN; } while(0)
#define TPRST_HIGH() do { TOUCH_RST_GPIO->BSRRL = TOUCH_RST_GPIO_PIN; } while(0)

View file

@ -712,6 +712,8 @@ class OpenTxSimulatorFactory: public SimulatorFactory
return Board::BOARD_TARANIS_X9LITE; return Board::BOARD_TARANIS_X9LITE;
#elif defined(PCBNV14) #elif defined(PCBNV14)
return Board::BOARD_FLYSKY_NV14; return Board::BOARD_FLYSKY_NV14;
#elif defined(PCBPL18)
return Board::BOARD_FLYSKY_PL18;
#else #else
return Board::BOARD_TARANIS_X9D; return Board::BOARD_TARANIS_X9D;
#endif #endif

View file

@ -535,7 +535,7 @@ void boardOff()
void hapticOff() {} void hapticOff() {}
#if defined(PCBFRSKY) || defined(PCBFLYSKY) #if defined(PCBFRSKY) || defined(PCBNV14)
HardwareOptions hardwareOptions; HardwareOptions hardwareOptions;
#endif #endif

View file

@ -616,6 +616,7 @@ FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs)
#include "hal/storage.h" #include "hal/storage.h"
void storageInit() {} void storageInit() {}
void storageDeInit() {}
void storagePreMountHook() {} void storagePreMountHook() {}
bool storageIsPresent() { return true; } bool storageIsPresent() { return true; }

View file

@ -480,10 +480,6 @@ else()
message( FATAL_ERROR "Unknown CPU_TYPE_FULL" ) message( FATAL_ERROR "Unknown CPU_TYPE_FULL" )
endif() endif()
if(NOT PCB STREQUAL PCBXLITE)
add_definitions(-DHARDWARE_TRAINER_JACK)
endif()
if(ENABLE_SERIAL_PASSTHROUGH) if(ENABLE_SERIAL_PASSTHROUGH)
set(CLI ON "Enable CLI") set(CLI ON "Enable CLI")
endif() endif()

View file

@ -479,4 +479,12 @@ void setTopBatteryValue(uint32_t volts);
#define VOLTAGE_DROP 20 #define VOLTAGE_DROP 20
#endif #endif
#if defined(RADIO_T20)
#define NUM_TRIMS 8
#else
#define NUM_TRIMS 4
#endif
#define NUM_TRIMS_KEYS (NUM_TRIMS * 2)
#endif // _BOARD_H_ #endif // _BOARD_H_

View file

@ -30,8 +30,15 @@
#else #else
#define MENUS_STACK_SIZE 2000 #define MENUS_STACK_SIZE 2000
#endif #endif
#if !defined(DEBUG)
#define MIXER_STACK_SIZE 400 #define MIXER_STACK_SIZE 400
#define AUDIO_STACK_SIZE 400 #define AUDIO_STACK_SIZE 400
#else
#define MIXER_STACK_SIZE 512
#define AUDIO_STACK_SIZE 512
#endif
#define CLI_STACK_SIZE 1024 // only consumed with CLI build option #define CLI_STACK_SIZE 1024 // only consumed with CLI build option
#if defined(FREE_RTOS) #if defined(FREE_RTOS)

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Some files were not shown because too many files have changed in this diff Show more