feat: Major serial driver re-write - see #1089 for details
Serial refactor
This commit is contained in:
@@ -59,7 +59,7 @@ const YamlLookupTable bluetoothModeLut = {
|
||||
{ GeneralSettings::BLUETOOTH_MODE_TRAINER, "TRAINER" },
|
||||
};
|
||||
|
||||
const YamlLookupTable uartModeLut = {
|
||||
const YamlLookupTable oldUartModeLut = {
|
||||
{ GeneralSettings::AUX_SERIAL_OFF, "MODE_NONE" },
|
||||
{ GeneralSettings::AUX_SERIAL_TELE_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ GeneralSettings::AUX_SERIAL_TELE_IN, "MODE_TELEMETRY" },
|
||||
@@ -67,6 +67,23 @@ const YamlLookupTable uartModeLut = {
|
||||
{ GeneralSettings::AUX_SERIAL_LUA, "MODE_LUA" },
|
||||
};
|
||||
|
||||
const YamlLookupTable serialPortLut = {
|
||||
{ GeneralSettings::SP_AUX1, "AUX1" },
|
||||
{ GeneralSettings::SP_AUX2, "AUX2" },
|
||||
{ GeneralSettings::SP_VCP, "VCP" },
|
||||
};
|
||||
|
||||
const YamlLookupTable uartModeLut = {
|
||||
{ GeneralSettings::AUX_SERIAL_OFF, "NONE" },
|
||||
{ GeneralSettings::AUX_SERIAL_TELE_MIRROR, "TELEMETRY_MIRROR" },
|
||||
{ GeneralSettings::AUX_SERIAL_TELE_IN, "TELEMETRY" },
|
||||
{ GeneralSettings::AUX_SERIAL_SBUS_TRAINER, "SBUS_TRAINER" },
|
||||
{ GeneralSettings::AUX_SERIAL_LUA, "LUA" },
|
||||
{ GeneralSettings::AUX_SERIAL_CLI, "CLI" },
|
||||
{ GeneralSettings::AUX_SERIAL_GPS, "GPS" },
|
||||
{ GeneralSettings::AUX_SERIAL_DEBUG, "DEBUG" },
|
||||
};
|
||||
|
||||
const YamlLookupTable antennaModeLut = {
|
||||
{ GeneralSettings::ANTENNA_MODE_INTERNAL, "MODE_INTERNAL" },
|
||||
{ GeneralSettings::ANTENNA_MODE_ASK, "MODE_ASK" },
|
||||
@@ -195,8 +212,17 @@ Node convert<GeneralSettings>::encode(const GeneralSettings& rhs)
|
||||
node["varioRange"] = rhs.varioRange * 15;
|
||||
node["varioRepeat"] = rhs.varioRepeat;
|
||||
node["backgroundVolume"] = rhs.backgroundVolume + 2;
|
||||
node["auxSerialMode"] = uartModeLut << rhs.auxSerialMode;
|
||||
node["aux2SerialMode"] = uartModeLut << rhs.aux2SerialMode;
|
||||
|
||||
Node serialPort;
|
||||
for (int i = 0; i < GeneralSettings::SP_COUNT; i++) {
|
||||
if (rhs.serialPort[i] != UART_MODE_NONE) {
|
||||
Node mode = uartModeLut << rhs.serialPort[i];
|
||||
serialPort[LookupValue(serialPortLut, i)]["mode"] = mode;
|
||||
}
|
||||
}
|
||||
if (serialPort && serialPort.IsMap())
|
||||
node["serialPort"] = serialPort;
|
||||
|
||||
node["antennaMode"] = antennaModeLut << rhs.antennaMode;
|
||||
node["backlightColor"] = rhs.backlightColor;
|
||||
node["pwrOnSpeed"] = rhs.pwrOnSpeed;
|
||||
@@ -372,8 +398,31 @@ bool convert<GeneralSettings>::decode(const Node& node, GeneralSettings& rhs)
|
||||
node["varioRange"] >> ifactor<int>(rhs.varioRange, 15);
|
||||
node["varioRepeat"] >> rhs.varioRepeat;
|
||||
node["backgroundVolume"] >> ioffset_int(rhs.backgroundVolume, 2);
|
||||
node["auxSerialMode"] >> uartModeLut >> rhs.auxSerialMode;
|
||||
node["aux2SerialMode"] >> uartModeLut >> rhs.aux2SerialMode;
|
||||
|
||||
if (node["auxSerialMode"]) {
|
||||
node["auxSerialMode"] >> oldUartModeLut >>
|
||||
rhs.serialPort[GeneralSettings::SP_AUX1];
|
||||
}
|
||||
|
||||
if (node["aux2SerialMode"]) {
|
||||
node["aux2SerialMode"] >> oldUartModeLut >>
|
||||
rhs.serialPort[GeneralSettings::SP_AUX2];
|
||||
}
|
||||
|
||||
if (node["serialPort"]) {
|
||||
Node serialPort = node["serialPort"];
|
||||
if (serialPort.IsMap()) {
|
||||
for (const auto& port : serialPort) {
|
||||
YAML::Node port_nr = port.first >> serialPortLut;
|
||||
if (port_nr) {
|
||||
int p = port_nr.as<int>();
|
||||
if (p >= 0 && p < GeneralSettings::SP_COUNT && port.second.IsMap())
|
||||
port.second["mode"] >> uartModeLut >> rhs.serialPort[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node["antennaMode"] >> antennaModeLut >> rhs.antennaMode;
|
||||
node["backlightColor"] >> rhs.backlightColor;
|
||||
node["pwrOnSpeed"] >> rhs.pwrOnSpeed;
|
||||
|
||||
@@ -160,6 +160,7 @@ enum Capability {
|
||||
Sensors,
|
||||
HasAuxSerialMode,
|
||||
HasAux2SerialMode,
|
||||
HasVCPSerialMode,
|
||||
HasBluetooth,
|
||||
HasAntennaChoice,
|
||||
HasADCJitterFilter,
|
||||
|
||||
@@ -418,9 +418,12 @@ QString GeneralSettings::bluetoothModeToString() const
|
||||
return bluetoothModeToString(bluetoothMode);
|
||||
}
|
||||
|
||||
QString GeneralSettings::auxSerialModeToString() const
|
||||
QString GeneralSettings::serialPortModeToString(int port_nr) const
|
||||
{
|
||||
return auxSerialModeToString(auxSerialMode);
|
||||
if (port_nr < 0 || port_nr >= SP_COUNT)
|
||||
return QString();
|
||||
|
||||
return serialModeToString(serialPort[port_nr]);
|
||||
}
|
||||
|
||||
QString GeneralSettings::telemetryBaudrateToString() const
|
||||
@@ -467,7 +470,7 @@ QString GeneralSettings::bluetoothModeToString(int value)
|
||||
}
|
||||
|
||||
// static
|
||||
QString GeneralSettings::auxSerialModeToString(int value)
|
||||
QString GeneralSettings::serialModeToString(int value)
|
||||
{
|
||||
switch(value) {
|
||||
case AUX_SERIAL_OFF:
|
||||
@@ -480,6 +483,12 @@ QString GeneralSettings::auxSerialModeToString(int value)
|
||||
return tr("SBUS Trainer");
|
||||
case AUX_SERIAL_LUA:
|
||||
return tr("LUA");
|
||||
case AUX_SERIAL_CLI:
|
||||
return tr("CLI");
|
||||
case AUX_SERIAL_GPS:
|
||||
return tr("GPS");
|
||||
case AUX_SERIAL_DEBUG:
|
||||
return tr("Debug");
|
||||
default:
|
||||
return CPN_STR_UNKNOWN_ITEM;
|
||||
}
|
||||
@@ -546,13 +555,20 @@ AbstractStaticItemModel * GeneralSettings::bluetoothModeItemModel()
|
||||
}
|
||||
|
||||
// static
|
||||
AbstractStaticItemModel * GeneralSettings::auxSerialModeItemModel()
|
||||
AbstractStaticItemModel * GeneralSettings::serialModeItemModel(int port_nr)
|
||||
{
|
||||
AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
|
||||
mdl->setName(AIM_GS_AUXSERIALMODE);
|
||||
mdl->setName(QString(AIM_GS_SERIALMODE).arg(port_nr));
|
||||
|
||||
for (int i = 0; i < AUX_SERIAL_COUNT; i++) {
|
||||
mdl->appendToItemList(auxSerialModeToString(i), i);
|
||||
if (port_nr == SP_VCP &&
|
||||
(i == AUX_SERIAL_TELE_IN ||
|
||||
i == AUX_SERIAL_SBUS_TRAINER ||
|
||||
i == AUX_SERIAL_GPS)) {
|
||||
// These 3 are disabled on VCP
|
||||
continue;
|
||||
}
|
||||
mdl->appendToItemList(serialModeToString(i), i);
|
||||
}
|
||||
|
||||
mdl->loadItemList();
|
||||
|
||||
@@ -38,7 +38,7 @@ class AbstractStaticItemModel;
|
||||
// identiying names of static abstract item models
|
||||
constexpr char AIM_GS_ANTENNAMODE[] {"gs.antennamode"};
|
||||
constexpr char AIM_GS_BLUETOOTHMODE[] {"gs.bluetoothmode"};
|
||||
constexpr char AIM_GS_AUXSERIALMODE[] {"gs.auxserialmode"};
|
||||
constexpr char AIM_GS_SERIALMODE[] {"gs.serialmode%1"};
|
||||
constexpr char AIM_GS_TELEMETRYBAUDRATE[] {"gs.telemetrybaudrate"};
|
||||
constexpr char AIM_TRAINERMIX_MODE[] {"trainermix.mode"};
|
||||
constexpr char AIM_TRAINERMIX_SRC[] {"trainermix.src"};
|
||||
@@ -135,12 +135,22 @@ class GeneralSettings {
|
||||
AUX_SERIAL_TELE_IN,
|
||||
AUX_SERIAL_SBUS_TRAINER,
|
||||
AUX_SERIAL_LUA,
|
||||
AUX_SERIAL_CLI,
|
||||
AUX_SERIAL_GPS,
|
||||
AUX_SERIAL_DEBUG,
|
||||
AUX_SERIAL_COUNT
|
||||
};
|
||||
|
||||
enum TelemetryBaudrate {
|
||||
};
|
||||
|
||||
enum SerialPort {
|
||||
SP_AUX1,
|
||||
SP_AUX2,
|
||||
SP_VCP,
|
||||
SP_COUNT,
|
||||
};
|
||||
|
||||
GeneralSettings() { clear(); }
|
||||
void clear();
|
||||
void init();
|
||||
@@ -228,8 +238,7 @@ class GeneralSettings {
|
||||
int backgroundVolume;
|
||||
unsigned int mavbaud;
|
||||
unsigned int switchUnlockStates;
|
||||
unsigned int auxSerialMode;
|
||||
unsigned int aux2SerialMode;
|
||||
unsigned int serialPort[SP_COUNT];
|
||||
int antennaMode;
|
||||
unsigned int backlightColor;
|
||||
CustomFunctionData customFn[CPN_MAX_SPECIAL_FUNCTIONS];
|
||||
@@ -257,17 +266,17 @@ class GeneralSettings {
|
||||
bool isSliderAvailable(int index) const;
|
||||
QString antennaModeToString() const;
|
||||
QString bluetoothModeToString() const;
|
||||
QString auxSerialModeToString() const;
|
||||
QString serialPortModeToString(int port_nr) const;
|
||||
QString telemetryBaudrateToString() const;
|
||||
|
||||
static QString antennaModeToString(int value);
|
||||
static QString bluetoothModeToString(int value);
|
||||
static QString auxSerialModeToString(int value);
|
||||
static QString serialModeToString(int value);
|
||||
static QString telemetryBaudrateToString(int value);
|
||||
static FieldRange getPPM_MultiplierRange();
|
||||
static FieldRange getTxCurrentCalibration();
|
||||
static AbstractStaticItemModel * antennaModeItemModel();
|
||||
static AbstractStaticItemModel * bluetoothModeItemModel();
|
||||
static AbstractStaticItemModel * auxSerialModeItemModel();
|
||||
static AbstractStaticItemModel * serialModeItemModel(int port_nr);
|
||||
static AbstractStaticItemModel * telemetryBaudrateItemModel();
|
||||
};
|
||||
|
||||
@@ -1649,18 +1649,23 @@ bool ModelData::isTrainerModeAvailable(const GeneralSettings & generalSettings,
|
||||
|
||||
if (!IS_FLYSKY_NV14(board) && value == TRAINER_MODE_OFF)
|
||||
ret = false;
|
||||
else if (!IS_TARANIS(board) || IS_ACCESS_RADIO(board, Firmware::getCurrentVariant()->getId())) {
|
||||
if (value >= TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE && value <= TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
|
||||
ret = false;
|
||||
}
|
||||
else if (generalSettings.auxSerialMode != UART_MODE_SBUS_TRAINER && value == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
|
||||
else if (!IS_TARANIS(board) ||
|
||||
IS_ACCESS_RADIO(board, Firmware::getCurrentVariant()->getId())) {
|
||||
if (value >= TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE &&
|
||||
value <= TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
|
||||
ret = false;
|
||||
} else if (generalSettings.serialPort[GeneralSettings::SP_AUX1] !=
|
||||
UART_MODE_SBUS_TRAINER &&
|
||||
value == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
|
||||
ret = false;
|
||||
|
||||
if (generalSettings.bluetoothMode != GeneralSettings::BLUETOOTH_MODE_TRAINER && value >= TRAINER_MODE_MASTER_BLUETOOTH && value <= TRAINER_MODE_SLAVE_BLUETOOTH)
|
||||
ret = false;
|
||||
if (generalSettings.bluetoothMode !=
|
||||
GeneralSettings::BLUETOOTH_MODE_TRAINER &&
|
||||
value >= TRAINER_MODE_MASTER_BLUETOOTH &&
|
||||
value <= TRAINER_MODE_SLAVE_BLUETOOTH)
|
||||
ret = false;
|
||||
|
||||
if (!IS_RADIOMASTER_TX16S(board) && value == TRAINER_MODE_MULTI)
|
||||
ret = false;
|
||||
if (!IS_RADIOMASTER_TX16S(board) && value == TRAINER_MODE_MULTI) ret = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3168,9 +3168,9 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
|
||||
|
||||
if (IS_STM32(board)) {
|
||||
if (version >= 218) {
|
||||
internalField.Append(new UnsignedField<4>(this, generalData.auxSerialMode));
|
||||
internalField.Append(new UnsignedField<4>(this, generalData.serialPort[GeneralSettings::SP_AUX1]));
|
||||
if (IS_FAMILY_HORUS_OR_T16(board) && version >= 219) {
|
||||
internalField.Append(new UnsignedField<4>(this, generalData.aux2SerialMode));
|
||||
internalField.Append(new UnsignedField<4>(this, generalData.serialPort[GeneralSettings::SP_AUX2]));
|
||||
}
|
||||
else {
|
||||
for (uint8_t i=0; i<SLIDERS_CONFIG_SIZE(board,version); i++) {
|
||||
@@ -3179,7 +3179,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
|
||||
}
|
||||
}
|
||||
else {
|
||||
internalField.Append(new UnsignedField<6>(this, generalData.auxSerialMode));
|
||||
internalField.Append(new UnsignedField<6>(this, generalData.serialPort[GeneralSettings::SP_AUX1]));
|
||||
if (IS_TARANIS_X9E(board)) {
|
||||
internalField.Append(new UnsignedField<1>(this, generalData.sliderConfig[2]));
|
||||
internalField.Append(new UnsignedField<1>(this, generalData.sliderConfig[3]));
|
||||
|
||||
@@ -744,9 +744,14 @@ int OpenTxFirmware::getCapability(::Capability capability)
|
||||
else
|
||||
return 40;
|
||||
case HasAuxSerialMode:
|
||||
return (IS_FAMILY_HORUS_OR_T16(board) && !IS_TARANIS_SMALL(board)) ? true : false;
|
||||
return (IS_FAMILY_HORUS_OR_T16(board) && !IS_FLYSKY_NV14(board)) ||
|
||||
(IS_TARANIS_X9(board) && !IS_TARANIS_X9DP_2019(board)) ||
|
||||
IS_RADIOMASTER_ZORRO(board);
|
||||
case HasAux2SerialMode:
|
||||
return (IS_FAMILY_HORUS_OR_T16(board) && !IS_TARANIS_SMALL(board) && !IS_FLYSKY_NV14(board)) ? true : false;
|
||||
return IS_FAMILY_T16(board);
|
||||
case HasVCPSerialMode:
|
||||
return IS_FAMILY_HORUS_OR_T16(board) || IS_RADIOMASTER_ZORRO(board) ||
|
||||
IS_JUMPER_TPRO(board);
|
||||
case HasBluetooth:
|
||||
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)) ? true : false;
|
||||
case HasAntennaChoice:
|
||||
|
||||
@@ -35,6 +35,50 @@ constexpr char FIM_SWITCHTYPE2POS[] {"Switch Type 2 Pos"};
|
||||
constexpr char FIM_SWITCHTYPE3POS[] {"Switch Type 3 Pos"};
|
||||
constexpr char FIM_INTERNALMODULES[] {"Internal Modules"};
|
||||
|
||||
class ExclusiveComboGroup: public QObject
|
||||
{
|
||||
static constexpr auto _role = Qt::UserRole + 500;
|
||||
|
||||
QList<QComboBox*> combos;
|
||||
std::function<bool(const QVariant&)> filter;
|
||||
|
||||
public:
|
||||
ExclusiveComboGroup(QObject *parent, std::function<bool(const QVariant&)> filter) :
|
||||
QObject(parent), filter(std::move(filter))
|
||||
{
|
||||
}
|
||||
|
||||
void addCombo(QComboBox *comboBox)
|
||||
{
|
||||
connect(comboBox, QOverload<int>::of(&QComboBox::activated),
|
||||
[=](int index) { this->handleActivated(comboBox, index); });
|
||||
combos.append(comboBox);
|
||||
}
|
||||
|
||||
void handleActivated(QComboBox* target, int index) {
|
||||
auto data = target->itemData(index);
|
||||
auto targetidx = combos.indexOf(target);
|
||||
for (auto combo : combos) {
|
||||
if (target == combo) continue;
|
||||
auto view = dynamic_cast<QListView*>(combo->view());
|
||||
Q_ASSERT(view);
|
||||
|
||||
auto previous = combo->findData(targetidx, _role);
|
||||
if (previous >= 0) {
|
||||
view->setRowHidden(previous, false);
|
||||
combo->setItemData(previous, QVariant(), _role);
|
||||
}
|
||||
if (!filter(data)) {
|
||||
auto idx = combo->findData(data);
|
||||
if (idx >= 0) {
|
||||
view->setRowHidden(idx, true);
|
||||
combo->setItemData(idx, targetidx, _role);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels):
|
||||
GeneralPanel(parent, generalSettings, firmware),
|
||||
board(firmware->getBoard()),
|
||||
@@ -50,7 +94,8 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
|
||||
|
||||
int antmodelid = editorItemModels->registerItemModel(GeneralSettings::antennaModeItemModel());
|
||||
int btmodelid = editorItemModels->registerItemModel(GeneralSettings::bluetoothModeItemModel());
|
||||
int auxmodelid = editorItemModels->registerItemModel(GeneralSettings::auxSerialModeItemModel());
|
||||
int auxmodelid = editorItemModels->registerItemModel(GeneralSettings::serialModeItemModel(GeneralSettings::SP_AUX1));
|
||||
int vcpmodelid = editorItemModels->registerItemModel(GeneralSettings::serialModeItemModel(GeneralSettings::SP_VCP));
|
||||
int baudmodelid = editorItemModels->registerItemModel(GeneralSettings::telemetryBaudrateItemModel());
|
||||
|
||||
id = editorItemModels->registerItemModel(ModuleData::internalModuleItemModel());
|
||||
@@ -149,6 +194,10 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
|
||||
addParams(row, maxBaudRate);
|
||||
}
|
||||
|
||||
// All values except 0 are mutually exclusive
|
||||
ExclusiveComboGroup *exclGroup = new ExclusiveComboGroup(
|
||||
this, [=](const QVariant &value) { return value == 0; });
|
||||
|
||||
if (firmware->getCapability(HasAuxSerialMode)) {
|
||||
QString lbl = "Serial Port";
|
||||
if (IS_RADIOMASTER_TX16S(board))
|
||||
@@ -156,7 +205,8 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
|
||||
addLabel(tr("%1").arg(lbl), row, 0);
|
||||
AutoComboBox *serialPortMode = new AutoComboBox(this);
|
||||
serialPortMode->setModel(editorItemModels->getItemModel(auxmodelid));
|
||||
serialPortMode->setField(generalSettings.auxSerialMode);
|
||||
serialPortMode->setField(generalSettings.serialPort[GeneralSettings::SP_AUX1]);
|
||||
exclGroup->addCombo(serialPortMode);
|
||||
addParams(row, serialPortMode);
|
||||
}
|
||||
|
||||
@@ -165,10 +215,20 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
|
||||
if (IS_RADIOMASTER_TX16S(board))
|
||||
lbl.append(" (TTL)");
|
||||
addLabel(tr("%1").arg(lbl), row, 0);
|
||||
AutoComboBox *serialPort2Mode = new AutoComboBox(this);
|
||||
serialPort2Mode->setModel(editorItemModels->getItemModel(auxmodelid));
|
||||
serialPort2Mode->setField(generalSettings.aux2SerialMode);
|
||||
addParams(row, serialPort2Mode);
|
||||
AutoComboBox *serialPortMode = new AutoComboBox(this);
|
||||
serialPortMode->setModel(editorItemModels->getItemModel(auxmodelid));
|
||||
serialPortMode->setField(generalSettings.serialPort[GeneralSettings::SP_AUX2]);
|
||||
exclGroup->addCombo(serialPortMode);
|
||||
addParams(row, serialPortMode);
|
||||
}
|
||||
|
||||
if (firmware->getCapability(HasVCPSerialMode)) {
|
||||
addLabel(tr("Serial Port VCP"), row, 0);
|
||||
AutoComboBox *serialPortMode = new AutoComboBox(this);
|
||||
serialPortMode->setModel(editorItemModels->getItemModel(vcpmodelid));
|
||||
serialPortMode->setField(generalSettings.serialPort[GeneralSettings::SP_VCP]);
|
||||
exclGroup->addCombo(serialPortMode);
|
||||
addParams(row, serialPortMode);
|
||||
}
|
||||
|
||||
if (firmware->getCapability(HasADCJitterFilter)) {
|
||||
|
||||
@@ -509,7 +509,9 @@ void TelemetryPanel::setup()
|
||||
ui->telemetryProtocol->addItem(tr("FrSky S.PORT"), 0);
|
||||
ui->telemetryProtocol->addItem(tr("FrSky D"), 1);
|
||||
if (IS_9XRPRO(firmware->getBoard()) ||
|
||||
(IS_TARANIS(firmware->getBoard()) && generalSettings.auxSerialMode == 2)) {
|
||||
(IS_TARANIS(firmware->getBoard()) &&
|
||||
generalSettings.serialPort[GeneralSettings::SP_AUX1] ==
|
||||
GeneralSettings::AUX_SERIAL_TELE_IN)) {
|
||||
ui->telemetryProtocol->addItem(tr("FrSky D (cable)"), 2);
|
||||
}
|
||||
ui->telemetryProtocol->setCurrentIndex(model->telemetryProtocol);
|
||||
|
||||
@@ -474,6 +474,8 @@ set(SRC
|
||||
timers.cpp
|
||||
trainer.cpp
|
||||
model_init.cpp
|
||||
serial.cpp
|
||||
sbus.cpp
|
||||
)
|
||||
|
||||
if(GUI)
|
||||
|
||||
+319
-201
File diff suppressed because it is too large
Load Diff
+3
-8
@@ -22,17 +22,12 @@
|
||||
#ifndef _CLI_H_
|
||||
#define _CLI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <stream_buffer.h>
|
||||
|
||||
#include "cli_traces.h"
|
||||
#include "hal/serial_driver.h"
|
||||
|
||||
// CLI task function
|
||||
void cliStart();
|
||||
|
||||
// Called from receive ISR (either USB or UART)
|
||||
void cliReceiveData(uint8_t* buf, uint32_t len);
|
||||
// Connect serial driver to CLI
|
||||
void cliSetSerialDriver(void* ctx, const etx_serial_driver_t* drv);
|
||||
|
||||
#endif // _CLI_H_
|
||||
|
||||
+18
-36
@@ -177,7 +177,6 @@ enum BeeperMode {
|
||||
e_mode_all
|
||||
};
|
||||
|
||||
#if defined(PCBFRSKY) || defined(PCBNV14)
|
||||
enum ModuleIndex {
|
||||
INTERNAL_MODULE,
|
||||
EXTERNAL_MODULE,
|
||||
@@ -185,45 +184,32 @@ enum ModuleIndex {
|
||||
};
|
||||
|
||||
enum TrainerMode {
|
||||
#if defined(PCBNV14)
|
||||
TRAINER_MODE_OFF,
|
||||
#endif
|
||||
TRAINER_MODE_MASTER_TRAINER_JACK,
|
||||
TRAINER_MODE_SLAVE,
|
||||
#if defined(PCBTARANIS) || defined(PCBNV14)
|
||||
TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE,
|
||||
TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE,
|
||||
#endif
|
||||
#if defined(PCBTARANIS) || defined(AUX_SERIAL) || defined(AUX2_SERIAL)
|
||||
TRAINER_MODE_MASTER_BATTERY_COMPARTMENT,
|
||||
#endif
|
||||
TRAINER_MODE_MASTER_SERIAL,
|
||||
TRAINER_MODE_MASTER_BLUETOOTH,
|
||||
TRAINER_MODE_SLAVE_BLUETOOTH,
|
||||
TRAINER_MODE_MULTI,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define TRAINER_MODE_MIN() TRAINER_MODE_MASTER_TRAINER_JACK
|
||||
#define TRAINER_MODE_MIN() TRAINER_MODE_OFF
|
||||
#define TRAINER_MODE_MAX() TRAINER_MODE_MULTI
|
||||
|
||||
#if !defined(HARDWARE_EXTERNAL_MODULE)
|
||||
#define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE
|
||||
#elif defined(RADIO_T16) && !defined(INTERNAL_MODULE_MULTI)
|
||||
#if defined(BLUETOOTH)
|
||||
#define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE_BLUETOOTH
|
||||
#else
|
||||
#define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE
|
||||
#endif
|
||||
#elif defined(INTERNAL_MODULE_MULTI) || defined(ALLOW_TRAINER_MULTI)
|
||||
#define TRAINER_MODE_MAX() TRAINER_MODE_MULTI
|
||||
#elif defined(BLUETOOTH)
|
||||
#define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE_BLUETOOTH
|
||||
#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBNV14)
|
||||
#define TRAINER_MODE_MAX() TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE
|
||||
#elif defined(PCBTARANIS)
|
||||
#define TRAINER_MODE_MAX() (IS_TRAINER_AUX_SERIAL() ? TRAINER_MODE_MASTER_BATTERY_COMPARTMENT : TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)
|
||||
#else
|
||||
#define TRAINER_MODE_MAX() TRAINER_MODE_MASTER_BATTERY_COMPARTMENT
|
||||
#endif
|
||||
enum SerialPort {
|
||||
SP_AUX1=0,
|
||||
SP_AUX2,
|
||||
SP_VCP,
|
||||
MAX_SERIAL_PORTS SKIP,
|
||||
};
|
||||
|
||||
#define MAX_AUX_SERIAL (SP_AUX2 + 1)
|
||||
#define STORAGE_SERIAL_PORTS 4
|
||||
|
||||
// GPS
|
||||
#define PILOTPOS_MIN_HDOP 500
|
||||
|
||||
#if defined(HARDWARE_INTERNAL_MODULE)
|
||||
#define IS_INTERNAL_MODULE_ENABLED() (g_model.moduleData[INTERNAL_MODULE].type != MODULE_TYPE_NONE)
|
||||
@@ -241,21 +227,17 @@ enum TrainerMode {
|
||||
|
||||
enum UartModes {
|
||||
UART_MODE_NONE,
|
||||
#if defined(CLI) || defined(DEBUG)
|
||||
UART_MODE_DEBUG SKIP = UART_MODE_NONE,
|
||||
#endif
|
||||
UART_MODE_TELEMETRY_MIRROR,
|
||||
UART_MODE_TELEMETRY,
|
||||
UART_MODE_SBUS_TRAINER,
|
||||
UART_MODE_LUA,
|
||||
UART_MODE_CLI,
|
||||
UART_MODE_GPS,
|
||||
UART_MODE_DEBUG,
|
||||
UART_MODE_COUNT SKIP,
|
||||
UART_MODE_MAX SKIP = UART_MODE_COUNT-1
|
||||
};
|
||||
|
||||
#if defined(CLI) || defined(DEBUG)
|
||||
#define UART_MODE_NONE UART_MODE_DEBUG
|
||||
#endif
|
||||
|
||||
#define LEN_SWITCH_NAME 3
|
||||
#define LEN_ANA_NAME 3
|
||||
#define LEN_MODEL_FILENAME 16
|
||||
|
||||
@@ -116,29 +116,29 @@ static inline void check_struct()
|
||||
CHKSIZE(TrainerData, 16);
|
||||
|
||||
#if defined(PCBXLITES)
|
||||
CHKSIZE(RadioData, 857);
|
||||
CHKSIZE(RadioData, 859);
|
||||
CHKSIZE(ModelData, 6161);
|
||||
#elif defined(PCBXLITE)
|
||||
CHKSIZE(RadioData, 855);
|
||||
CHKSIZE(RadioData, 857);
|
||||
CHKSIZE(ModelData, 6161);
|
||||
#elif defined(RADIO_TPRO)
|
||||
CHKSIZE(RadioData, 838);
|
||||
CHKSIZE(RadioData, 840);
|
||||
CHKSIZE(ModelData, 6186);
|
||||
#elif defined(PCBX7)
|
||||
CHKSIZE(RadioData, 861);
|
||||
CHKSIZE(RadioData, 863);
|
||||
CHKSIZE(ModelData, 6161);
|
||||
#elif defined(PCBX9E)
|
||||
CHKSIZE(RadioData, 951);
|
||||
CHKSIZE(RadioData, 953);
|
||||
CHKSIZE(ModelData, 6613);
|
||||
#elif defined(PCBX9D) || defined(PCBX9DP)
|
||||
CHKSIZE(RadioData, 893);
|
||||
CHKSIZE(RadioData, 895);
|
||||
CHKSIZE(ModelData, 6605);
|
||||
#elif defined(PCBHORUS)
|
||||
#if defined(PCBX10)
|
||||
CHKSIZE(RadioData, 918);
|
||||
CHKSIZE(RadioData, 919);
|
||||
CHKSIZE(ModelData, 11025);
|
||||
#else
|
||||
CHKSIZE(RadioData, 900);
|
||||
CHKSIZE(RadioData, 901);
|
||||
CHKSIZE(ModelData, 11023);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -787,10 +787,8 @@ PACK(struct TrainerData {
|
||||
#define GYRO_FIELDS
|
||||
#endif
|
||||
|
||||
#if defined(PCBHORUS) || defined(PCBNV14)
|
||||
#if defined(COLORLCD)
|
||||
#define EXTRA_GENERAL_FIELDS \
|
||||
NOBACKUP(uint8_t auxSerialMode:4 ENUM(UartModes)); \
|
||||
NOBACKUP(uint8_t aux2SerialMode:4 ENUM(UartModes)); \
|
||||
CUST_ARRAY(sticksConfig, struct_sticksConfig, stick_name_valid); \
|
||||
swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr); \
|
||||
uint16_t potsConfig ARRAY(2,struct_potConfig,nullptr); /* two bits per pot */ \
|
||||
@@ -801,17 +799,17 @@ PACK(struct TrainerData {
|
||||
NOBACKUP(uint8_t spare5:1 SKIP); \
|
||||
NOBACKUP(uint8_t blOffBright:7); \
|
||||
NOBACKUP(char bluetoothName[LEN_BLUETOOTH_NAME]);
|
||||
#elif defined(PCBTARANIS)
|
||||
#else
|
||||
#if defined(STORAGE_BLUETOOTH)
|
||||
#define BLUETOOTH_FIELDS \
|
||||
uint8_t spare5 SKIP; \
|
||||
uint8_t spare6 SKIP; \
|
||||
char bluetoothName[LEN_BLUETOOTH_NAME];
|
||||
#else
|
||||
#define BLUETOOTH_FIELDS
|
||||
#endif
|
||||
#define EXTRA_GENERAL_FIELDS \
|
||||
uint8_t auxSerialMode:4 ENUM(UartModes); \
|
||||
uint8_t slidersConfig:4 ARRAY(1,struct_sliderConfig,nullptr); \
|
||||
uint8_t spare5:4 SKIP; \
|
||||
uint8_t potsConfig ARRAY(2,struct_potConfig,nullptr); /* two bits per pot */\
|
||||
uint8_t backlightColor; \
|
||||
CUST_ARRAY(sticksConfig, struct_sticksConfig, stick_name_valid); \
|
||||
@@ -819,8 +817,6 @@ PACK(struct TrainerData {
|
||||
char switchNames[STORAGE_NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES][LEN_SWITCH_NAME] SKIP; \
|
||||
char anaNames[NUM_STICKS+STORAGE_NUM_POTS+STORAGE_NUM_SLIDERS][LEN_ANA_NAME] SKIP; \
|
||||
BLUETOOTH_FIELDS
|
||||
#else
|
||||
#define EXTRA_GENERAL_FIELDS
|
||||
#endif
|
||||
|
||||
#if defined(COLORLCD) && !defined(BACKUP)
|
||||
@@ -912,6 +908,10 @@ PACK(struct RadioData {
|
||||
NOBACKUP(int8_t varioRepeat);
|
||||
CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS] FUNC(cfn_is_active);
|
||||
|
||||
CUST_ATTR(auxSerialMode, r_serialMode, nullptr);
|
||||
CUST_ATTR(aux2SerialMode, r_serialMode, nullptr);
|
||||
NOBACKUP(uint16_t serialPort ARRAY(STORAGE_SERIAL_PORTS,struct_serialConfig,nullptr));
|
||||
|
||||
EXTRA_GENERAL_FIELDS
|
||||
|
||||
THEME_DATA
|
||||
|
||||
+1
-7
@@ -33,9 +33,6 @@
|
||||
|
||||
extern volatile uint32_t g_tmr10ms;
|
||||
|
||||
uint8_t auxSerialTracesEnabled();
|
||||
uint8_t aux2SerialTracesEnabled();
|
||||
|
||||
#if defined(SIMU)
|
||||
typedef void (*traceCallbackFunc)(const char * text);
|
||||
extern traceCallbackFunc traceCallback;
|
||||
@@ -43,11 +40,8 @@ uint8_t aux2SerialTracesEnabled();
|
||||
#elif defined(SEMIHOSTING)
|
||||
#include <stdio.h>
|
||||
#define debugPrintf(...) printf(__VA_ARGS__)
|
||||
#elif defined(DEBUG) && defined(CLI)
|
||||
#include "cli_traces.h"
|
||||
#define debugPrintf(...) do { if (cliTracesEnabled) serialPrintf(__VA_ARGS__); } while(0)
|
||||
#elif defined(DEBUG)
|
||||
#define debugPrintf(...) do { serialPrintf(__VA_ARGS__); } while(0)
|
||||
#define debugPrintf(...) do { dbgSerialPrintf(__VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define debugPrintf(...)
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
#if defined(SIMU)
|
||||
#define dumpPrintf(...) debugPrintf(__VA_ARGS__)
|
||||
#else
|
||||
#define dumpPrintf(...) serialPrintf(__VA_ARGS__)
|
||||
#define dumpPrintf(...) dbgSerialPrintf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG) || defined(CLI)
|
||||
|
||||
+38
-7
@@ -320,10 +320,33 @@ void gpsNewData(uint8_t c)
|
||||
}
|
||||
}
|
||||
|
||||
static const etx_serial_driver_t* gpsSerialDrv = nullptr;
|
||||
static void* gpsSerialCtx = nullptr;
|
||||
|
||||
#if defined(DEBUG)
|
||||
uint8_t gpsTraceEnabled = false;
|
||||
#endif
|
||||
|
||||
void gpsSetSerialDriver(void* ctx, const etx_serial_driver_t* drv)
|
||||
{
|
||||
gpsSerialCtx = ctx;
|
||||
gpsSerialDrv = drv;
|
||||
}
|
||||
|
||||
void gpsWakeup()
|
||||
{
|
||||
if (!gpsSerialDrv) return;
|
||||
|
||||
auto _getByte = gpsSerialDrv->getByte;
|
||||
if (!_getByte) return;
|
||||
|
||||
uint8_t byte;
|
||||
while (gpsGetByte(&byte)) {
|
||||
while (_getByte(gpsSerialCtx, &byte)) {
|
||||
#if defined(DEBUG)
|
||||
if (gpsTraceEnabled) {
|
||||
dbgSerialPutc(byte);
|
||||
}
|
||||
#endif
|
||||
gpsNewData(byte);
|
||||
}
|
||||
}
|
||||
@@ -334,18 +357,26 @@ char hex(uint8_t b) {
|
||||
|
||||
void gpsSendFrame(const char * frame)
|
||||
{
|
||||
if (!gpsSerialDrv) return;
|
||||
|
||||
auto _sendByte = gpsSerialDrv->sendByte;
|
||||
if (!_sendByte) return;
|
||||
|
||||
// send given frame, add checksum and CRLF
|
||||
uint8_t parity = 0;
|
||||
TRACE_NOCRLF("gps> %s", frame);
|
||||
|
||||
while (*frame) {
|
||||
if (*frame != '$') parity ^= *frame;
|
||||
gpsSendByte(*frame);
|
||||
_sendByte(gpsSerialCtx, *frame);
|
||||
++frame;
|
||||
}
|
||||
gpsSendByte('*');
|
||||
gpsSendByte(hex(parity >> 4));
|
||||
gpsSendByte(hex(parity & 0x0F));
|
||||
gpsSendByte('\r');
|
||||
gpsSendByte('\n');
|
||||
|
||||
_sendByte(gpsSerialCtx, '*');
|
||||
_sendByte(gpsSerialCtx, hex(parity >> 4));
|
||||
_sendByte(gpsSerialCtx, hex(parity & 0x0F));
|
||||
_sendByte(gpsSerialCtx, '\r');
|
||||
_sendByte(gpsSerialCtx, '\n');
|
||||
|
||||
TRACE("*%02x", parity);
|
||||
}
|
||||
|
||||
@@ -39,8 +39,18 @@ struct gpsdata_t
|
||||
};
|
||||
|
||||
extern gpsdata_t gpsData;
|
||||
|
||||
#if defined(DEBUG)
|
||||
extern uint8_t gpsTraceEnabled;
|
||||
#endif
|
||||
|
||||
// Setup GPS serial port
|
||||
void gpsSetSerialDriver(void* ctx, const etx_serial_driver_t* drv);
|
||||
|
||||
// Periodic processing
|
||||
void gpsWakeup();
|
||||
|
||||
// Send a 0-terminated frame
|
||||
void gpsSendFrame(const char * frame);
|
||||
|
||||
#endif // _GPS_H_
|
||||
|
||||
@@ -163,18 +163,6 @@ void menuStatisticsDebug(event_t event)
|
||||
|
||||
uint8_t y = FH + 1;
|
||||
|
||||
#if defined(STM32) && !defined(SIMU) && defined(DEBUG)
|
||||
lcdDrawTextAlignedLeft(y, "Usb");
|
||||
lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, charsWritten, LEFT);
|
||||
lcdDrawText(lcdLastRightPos, y, " ");
|
||||
lcdDrawNumber(lcdLastRightPos, y, APP_Rx_ptr_in, LEFT);
|
||||
lcdDrawText(lcdLastRightPos, y, " ");
|
||||
lcdDrawNumber(lcdLastRightPos, y, APP_Rx_ptr_out, LEFT);
|
||||
lcdDrawText(lcdLastRightPos, y, " ");
|
||||
lcdDrawNumber(lcdLastRightPos, y, usbWraps, LEFT);
|
||||
y += FH;
|
||||
#endif
|
||||
|
||||
#if defined(STM32)
|
||||
lcdDrawTextAlignedLeft(y, "Free Mem");
|
||||
lcdDrawNumber(MENU_DEBUG_COL1_OFS, y, availableMemory(), LEFT);
|
||||
|
||||
@@ -34,7 +34,9 @@ TopbarImpl::TopbarImpl(Window * parent) :
|
||||
unsigned int TopbarImpl::getZonesCount() const
|
||||
{
|
||||
#if defined(INTERNAL_GPS)
|
||||
return MAX_TOPBAR_ZONES-1;
|
||||
if (hasSerialMode(UART_MODE_GPS)) {
|
||||
return MAX_TOPBAR_ZONES-1;
|
||||
}
|
||||
#endif
|
||||
return MAX_TOPBAR_ZONES;
|
||||
}
|
||||
@@ -96,13 +98,16 @@ void TopbarImpl::paint(BitmapBuffer * dc)
|
||||
dc->drawText(DATETIME_MIDDLE, DATETIME_LINE2, str, FONT(XS) | CENTERED | COLOR_THEME_PRIMARY2);
|
||||
|
||||
#if defined(INTERNAL_GPS)
|
||||
if (gpsData.fix) {
|
||||
char s[10];
|
||||
sprintf(s, "%d", gpsData.numSat);
|
||||
dc->drawText(GPS_X, 4, s, FONT(XS) | CENTERED | COLOR_THEME_PRIMARY2);
|
||||
if (hasSerialMode(UART_MODE_GPS) != -1) {
|
||||
if (gpsData.fix) {
|
||||
char s[10];
|
||||
sprintf(s, "%d", gpsData.numSat);
|
||||
dc->drawText(GPS_X, 4, s, FONT(XS) | CENTERED | COLOR_THEME_PRIMARY2);
|
||||
}
|
||||
dc->drawBitmapPattern(
|
||||
GPS_X - 10, 22, LBM_TOPMENU_GPS,
|
||||
(gpsData.fix) ? COLOR_THEME_PRIMARY2 : COLOR_THEME_PRIMARY3);
|
||||
}
|
||||
dc->drawBitmapPattern(GPS_X - 10, 22, LBM_TOPMENU_GPS,
|
||||
(gpsData.fix) ? COLOR_THEME_PRIMARY2 : COLOR_THEME_PRIMARY3);
|
||||
#endif
|
||||
|
||||
// USB icon
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "opentx.h"
|
||||
#include "libopenui.h"
|
||||
#include "hal/adc_driver.h"
|
||||
#include "aux_serial_driver.h"
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_GENERAL)
|
||||
|
||||
@@ -196,6 +197,56 @@ class BluetoothConfigWindow : public FormGroup
|
||||
};
|
||||
#endif
|
||||
|
||||
class SerialConfigWindow : public FormGroup
|
||||
{
|
||||
public:
|
||||
SerialConfigWindow(FormWindow *parent, const rect_t &rect) :
|
||||
FormGroup(parent, rect, FORWARD_SCROLL | FORM_FORWARD_FOCUS)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
FormGridLayout grid;
|
||||
#if LCD_W > LCD_H
|
||||
grid.setLabelWidth(180);
|
||||
#else
|
||||
grid.setLabelWidth(130);
|
||||
#endif
|
||||
clear();
|
||||
|
||||
bool display_ttl_warning = false;
|
||||
for (uint8_t port_nr = 0; port_nr < MAX_SERIAL_PORTS; port_nr++) {
|
||||
auto port = serialGetPort(port_nr);
|
||||
if (!port || !port->name) continue;
|
||||
|
||||
display_ttl_warning = true;
|
||||
new StaticText(this, grid.getLabelSlot(true), port->name, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
auto aux = new Choice(
|
||||
this, grid.getFieldSlot(), STR_AUX_SERIAL_MODES, 0,
|
||||
UART_MODE_MAX, [=]() { return serialGetMode(port_nr); },
|
||||
[=](int value) {
|
||||
serialSetMode(port_nr, value);
|
||||
serialInit(port_nr, value);
|
||||
SET_DIRTY();
|
||||
});
|
||||
aux->setAvailableHandler(
|
||||
[=](int value) { return isSerialModeAvailable(port_nr, value); });
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
if (display_ttl_warning) {
|
||||
new StaticText(this, grid.getFieldSlot(), STR_TTL_WARNING, 0,
|
||||
COLOR_THEME_WARNING);
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
getParent()->moveWindowsTop(top() + 1, adjustHeight());
|
||||
}
|
||||
};
|
||||
|
||||
void restartExternalModule()
|
||||
{
|
||||
if (!IS_EXTERNAL_MODULE_ON()) {
|
||||
@@ -372,38 +423,10 @@ void RadioHardwarePage::build(FormWindow * window)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
new StaticText(window, grid.getLabelSlot(), STR_AUX_SERIAL_MODE, 0, COLOR_THEME_PRIMARY1);
|
||||
auto aux =
|
||||
new Choice(window, grid.getFieldSlot(1, 0), STR_AUX_SERIAL_MODES, 0,
|
||||
UART_MODE_MAX, GET_DEFAULT(g_eeGeneral.auxSerialMode),
|
||||
[](int value) {
|
||||
g_eeGeneral.auxSerialMode = value;
|
||||
auxSerialInit(g_eeGeneral.auxSerialMode, modelTelemetryProtocol());
|
||||
SET_DIRTY();
|
||||
});
|
||||
aux->setAvailableHandler(isAuxModeAvailable);
|
||||
new Subtitle(window, grid.getLineSlot(), STR_AUX_SERIAL_MODE, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
#endif
|
||||
|
||||
#if defined(AUX2_SERIAL)
|
||||
new StaticText(window, grid.getLabelSlot(), STR_AUX2_SERIAL_MODE, 0, COLOR_THEME_PRIMARY1);
|
||||
auto aux2 =
|
||||
new Choice(window, grid.getFieldSlot(1, 0), STR_AUX_SERIAL_MODES, 0,
|
||||
UART_MODE_MAX, GET_DEFAULT(g_eeGeneral.aux2SerialMode),
|
||||
[](int value) {
|
||||
g_eeGeneral.aux2SerialMode = value;
|
||||
aux2SerialInit(g_eeGeneral.aux2SerialMode, modelTelemetryProtocol());
|
||||
SET_DIRTY();
|
||||
});
|
||||
aux2->setAvailableHandler(isAux2ModeAvailable);
|
||||
grid.nextLine();
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL) || defined(AUX2_SERIAL)
|
||||
new StaticText(window, grid.getFieldSlot(1,0), STR_TTL_WARNING, 0, COLOR_THEME_WARNING);
|
||||
grid.nextLine();
|
||||
#endif
|
||||
grid.addWindow(new SerialConfigWindow(window, {0, grid.getWindowHeight(), LCD_W, 0}));
|
||||
|
||||
// ADC filter
|
||||
new StaticText(window, grid.getLabelSlot(), STR_JITTER_FILTER, 0, COLOR_THEME_PRIMARY1);
|
||||
|
||||
@@ -418,7 +418,7 @@ void RadioSetupPage::build(FormWindow * window)
|
||||
|
||||
#if defined(INTERNAL_GPS)
|
||||
// GPS
|
||||
{
|
||||
if (hasSerialMode(UART_MODE_GPS)) {
|
||||
new Subtitle(window, grid.getLabelSlot(), STR_GPS, 0, COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
|
||||
|
||||
@@ -240,19 +240,21 @@ void DebugViewPage::build(FormWindow *window)
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_GPS)
|
||||
new StaticText(window, grid.getLabelSlot(), STR_INT_GPS_LABEL, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
new DynamicText(
|
||||
window, grid.getFieldSlot(3, 0),
|
||||
[] { return std::string(gpsData.fix ? "[Fix] Yes" : "[Fix] No"); },
|
||||
COLOR_THEME_PRIMARY1);
|
||||
new DebugInfoNumber<uint8_t>(
|
||||
window, grid.getFieldSlot(3, 1), [] { return gpsData.numSat; },
|
||||
COLOR_THEME_PRIMARY1, "[Sats] ", nullptr);
|
||||
new DebugInfoNumber<uint16_t>(
|
||||
window, grid.getFieldSlot(3, 2), [] { return gpsData.hdop; },
|
||||
COLOR_THEME_PRIMARY1, "[Hdop] ", nullptr);
|
||||
grid.nextLine();
|
||||
if (hasSerialMode(UART_MODE_GPS)) {
|
||||
new StaticText(window, grid.getLabelSlot(), STR_INT_GPS_LABEL, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
new DynamicText(
|
||||
window, grid.getFieldSlot(3, 0),
|
||||
[] { return std::string(gpsData.fix ? "[Fix] Yes" : "[Fix] No"); },
|
||||
COLOR_THEME_PRIMARY1);
|
||||
new DebugInfoNumber<uint8_t>(
|
||||
window, grid.getFieldSlot(3, 1), [] { return gpsData.numSat; },
|
||||
COLOR_THEME_PRIMARY1, "[Sats] ", nullptr);
|
||||
new DebugInfoNumber<uint16_t>(
|
||||
window, grid.getFieldSlot(3, 2), [] { return gpsData.hdop; },
|
||||
COLOR_THEME_PRIMARY1, "[Hdop] ", nullptr);
|
||||
grid.nextLine();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Reset
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <opentx.h>
|
||||
#include "hal/adc_driver.h"
|
||||
#include "aux_serial_driver.h"
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
enum {
|
||||
@@ -117,9 +118,13 @@ enum {
|
||||
ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA,
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
ITEM_RADIO_HARDWARE_AUX_SERIAL_MODE,
|
||||
#if defined(AUX_SERIAL) || defined(USB_SERIAL)
|
||||
ITEM_RADIO_HARDWARE_SERIAL_PORT_LABEL,
|
||||
ITEM_RADIO_HARDWARE_AUX1_SERIAL_MODE,
|
||||
ITEM_RADIO_HARDWARE_AUX2_SERIAL_MODE,
|
||||
ITEM_RADIO_HARDWARE_VCP_SERIAL_MODE,
|
||||
#endif
|
||||
|
||||
ITEM_RADIO_HARDWARE_JITTER_FILTER,
|
||||
ITEM_RADIO_HARDWARE_RAS,
|
||||
#if defined(SPORT_UPDATE_PWR_GPIO)
|
||||
@@ -239,10 +244,17 @@ enum {
|
||||
|
||||
#define SERIAL_SAMPLE_MODE_ROWS 0,
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
#define AUX_SERIAL_ROWS 0,
|
||||
#if defined(AUX_SERIAL) || defined(USB_SERIAL)
|
||||
static uint8_t _dispSerialPort(uint8_t port_nr)
|
||||
{
|
||||
auto port = serialGetPort(port_nr);
|
||||
if (!port || !port->name) return HIDDEN_ROW;
|
||||
return 0;
|
||||
}
|
||||
#define SERIAL_PORT_ROWS \
|
||||
0, _dispSerialPort(SP_AUX1), _dispSerialPort(SP_AUX2), _dispSerialPort(SP_VCP),
|
||||
#else
|
||||
#define AUX_SERIAL_ROWS
|
||||
#define SERIAL_PORT_ROWS
|
||||
#endif
|
||||
|
||||
#if LCD_W >= 212
|
||||
@@ -285,6 +297,14 @@ void restartExternalModule()
|
||||
resumeMixerCalculations();
|
||||
}
|
||||
|
||||
static bool _isAux1ModeAvailable(int m) { return isSerialModeAvailable(SP_AUX1, m); }
|
||||
static bool _isAux2ModeAvailable(int m) { return isSerialModeAvailable(SP_AUX2, m); }
|
||||
static bool _isVCPModeAvailable(int m) { return isSerialModeAvailable(SP_VCP, m); }
|
||||
|
||||
static const IsValueAvailable _isSerialModeAvailable[MAX_SERIAL_PORTS] = {
|
||||
_isAux1ModeAvailable, _isAux2ModeAvailable, _isVCPModeAvailable
|
||||
};
|
||||
|
||||
void menuRadioHardware(event_t event)
|
||||
{
|
||||
uint8_t old_editMode = s_editMode;
|
||||
@@ -307,7 +327,7 @@ void menuRadioHardware(event_t event)
|
||||
SERIAL_SAMPLE_MODE_ROWS
|
||||
BLUETOOTH_ROWS
|
||||
EXTERNAL_ANTENNA_ROW
|
||||
AUX_SERIAL_ROWS
|
||||
SERIAL_PORT_ROWS
|
||||
0 /* ADC filter */,
|
||||
READONLY_ROW /* RAS */,
|
||||
SPORT_POWER_ROWS
|
||||
@@ -595,13 +615,28 @@ void menuRadioHardware(event_t event)
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
case ITEM_RADIO_HARDWARE_AUX_SERIAL_MODE:
|
||||
g_eeGeneral.auxSerialMode = editChoice(HW_SETTINGS_COLUMN2, y, STR_AUX_SERIAL_MODE, STR_AUX_SERIAL_MODES, g_eeGeneral.auxSerialMode, 0, UART_MODE_MAX, attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
auxSerialInit(g_eeGeneral.auxSerialMode, modelTelemetryProtocol());
|
||||
}
|
||||
#if defined(AUX_SERIAL) || defined(USB_SERIAL)
|
||||
case ITEM_RADIO_HARDWARE_SERIAL_PORT_LABEL:
|
||||
lcdDrawTextAlignedLeft(y, STR_AUX_SERIAL_MODE);
|
||||
break;
|
||||
case ITEM_RADIO_HARDWARE_AUX1_SERIAL_MODE:
|
||||
case ITEM_RADIO_HARDWARE_AUX2_SERIAL_MODE:
|
||||
case ITEM_RADIO_HARDWARE_VCP_SERIAL_MODE:
|
||||
{
|
||||
auto port_nr = k - ITEM_RADIO_HARDWARE_AUX1_SERIAL_MODE;
|
||||
auto port = serialGetPort(port_nr);
|
||||
lcdDrawText(INDENT_WIDTH, y, port->name);
|
||||
|
||||
auto mode = serialGetMode(port_nr);
|
||||
mode = editChoice(HW_SETTINGS_COLUMN2, y, nullptr,
|
||||
STR_AUX_SERIAL_MODES, mode, 0, UART_MODE_MAX, attr,
|
||||
event, _isSerialModeAvailable[port_nr]);
|
||||
|
||||
if (attr && checkIncDec_Ret) {
|
||||
serialSetMode(port_nr, mode);
|
||||
serialInit(port_nr, mode);
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
case ITEM_RADIO_HARDWARE_JITTER_FILTER:
|
||||
g_eeGeneral.noJitterFilter = 1 - editCheckBox(1 - g_eeGeneral.noJitterFilter, HW_SETTINGS_COLUMN2, y, STR_JITTER_FILTER, attr, event);
|
||||
|
||||
@@ -367,29 +367,52 @@ bool isSwitchAvailable(int swtch, SwitchContext context)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isAuxModeAvailable(int mode)
|
||||
int hasSerialMode(int mode)
|
||||
{
|
||||
#if defined(AUX2_SERIAL)
|
||||
if (mode == UART_MODE_SBUS_TRAINER)
|
||||
return g_eeGeneral.aux2SerialMode != UART_MODE_SBUS_TRAINER;
|
||||
#if defined(RADIO_TX16S)
|
||||
else
|
||||
return (g_model.trainerData.mode != TRAINER_MODE_MASTER_BATTERY_COMPARTMENT || g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER);
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
for (int p = 0; p < MAX_SERIAL_PORTS; p++) {
|
||||
if (serialGetMode(p) == mode) return p;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool isAux2ModeAvailable(int mode)
|
||||
bool isSerialModeAvailable(uint8_t port_nr, int mode)
|
||||
{
|
||||
#if defined(AUX_SERIAL)
|
||||
if (mode == UART_MODE_SBUS_TRAINER)
|
||||
return g_eeGeneral.auxSerialMode != UART_MODE_SBUS_TRAINER;
|
||||
#if defined(RADIO_TX16S)
|
||||
else
|
||||
return (g_model.trainerData.mode != TRAINER_MODE_MASTER_BATTERY_COMPARTMENT || g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER);
|
||||
if (mode == UART_MODE_NONE)
|
||||
return true;
|
||||
|
||||
#if !defined(DEBUG)
|
||||
if (mode == UART_MODE_DEBUG)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if !defined(CLI)
|
||||
if (mode == UART_MODE_CLI)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if !defined(INTERNAL_GPS)
|
||||
if (mode == UART_MODE_GPS)
|
||||
return false;
|
||||
#elif defined(USB_SERIAL)
|
||||
// GPS is not supported on VCP
|
||||
if (port_nr == SP_VCP && mode == UART_MODE_GPS)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if !defined(LUA)
|
||||
if (mode == UART_MODE_LUA)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if defined(USB_SERIAL)
|
||||
// Telemetry input & SBUS trainer on VCP is not yet supported
|
||||
if (port_nr == SP_VCP &&
|
||||
(mode == UART_MODE_TELEMETRY || mode == UART_MODE_SBUS_TRAINER))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
auto p = hasSerialMode(mode);
|
||||
if (p >= 0 && p != port_nr) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -755,7 +778,8 @@ bool isRfProtocolAvailable(int protocol)
|
||||
bool isTelemetryProtocolAvailable(int protocol)
|
||||
{
|
||||
#if defined(PCBTARANIS)
|
||||
if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY && g_eeGeneral.auxSerialMode != UART_MODE_TELEMETRY) {
|
||||
if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY &&
|
||||
hasSerialMode(UART_MODE_TELEMETRY) < 0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -791,51 +815,50 @@ bool isTelemetryProtocolAvailable(int protocol)
|
||||
|
||||
bool isTrainerModeAvailable(int mode)
|
||||
{
|
||||
#if defined(PCBTARANIS)
|
||||
if (IS_EXTERNAL_MODULE_ENABLED() && (mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || mode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if defined(PCBX9E)
|
||||
if (g_eeGeneral.bluetoothMode && mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE) {
|
||||
if (g_eeGeneral.bluetoothMode &&
|
||||
mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE) {
|
||||
// bluetooth uses the same USART than SBUS
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RADIO_TX16S) && defined(TRAINER_BATTERY_COMPARTMENT)
|
||||
if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
|
||||
return (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER || g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER);
|
||||
#elif defined(PCBTARANIS) && !defined(TRAINER_BATTERY_COMPARTMENT)
|
||||
if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
|
||||
return false;
|
||||
#elif defined(PCBTARANIS)
|
||||
if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
|
||||
return g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER;
|
||||
#endif
|
||||
|
||||
#if defined(BLUETOOTH) && !defined(PCBX9E)
|
||||
if (g_eeGeneral.bluetoothMode != BLUETOOTH_TRAINER && (mode == TRAINER_MODE_MASTER_BLUETOOTH || mode == TRAINER_MODE_SLAVE_BLUETOOTH))
|
||||
return false;
|
||||
if (mode == TRAINER_MODE_MASTER_SERIAL) {
|
||||
#if defined(SBUS_TRAINER)
|
||||
return hasSerialMode(UART_MODE_SBUS_TRAINER) >= 0;
|
||||
#else
|
||||
if (mode == TRAINER_MODE_MASTER_BLUETOOTH || mode == TRAINER_MODE_SLAVE_BLUETOOTH)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((mode == TRAINER_MODE_MASTER_BLUETOOTH ||
|
||||
mode == TRAINER_MODE_SLAVE_BLUETOOTH)
|
||||
#if defined(BLUETOOTH) && !defined(PCBX9E)
|
||||
&& g_eeGeneral.bluetoothMode != BLUETOOTH_TRAINER
|
||||
#endif
|
||||
)
|
||||
return false;
|
||||
|
||||
#if defined(PCBXLITE) && !defined(PCBXLITES)
|
||||
if (mode == TRAINER_MODE_MASTER_TRAINER_JACK || mode == TRAINER_MODE_SLAVE)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS) || defined(PCBNV14)
|
||||
#if !defined(TRAINER_MODULE_CPPM)
|
||||
#if !defined(TRAINER_MODULE_CPPM)
|
||||
if (mode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)
|
||||
return false;
|
||||
#endif
|
||||
#if !defined(TRAINER_MODULE_SBUS)
|
||||
#endif
|
||||
|
||||
#if !defined(TRAINER_MODULE_SBUS)
|
||||
if (mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE)
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(TRAINER_MODULE_CPPM) || defined(TRAINER_MODULE_SBUS)
|
||||
if (IS_EXTERNAL_MODULE_ENABLED() &&
|
||||
(mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE ||
|
||||
mode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
@@ -86,8 +86,8 @@ bool isSourceAvailableInCustomSwitches(int source);
|
||||
bool isSourceAvailableInResetSpecialFunction(int index);
|
||||
bool isSourceAvailableInGlobalResetSpecialFunction(int index);
|
||||
bool isSwitchAvailable(int swtch, SwitchContext context);
|
||||
bool isAuxModeAvailable(int mode);
|
||||
bool isAux2ModeAvailable(int mode);
|
||||
bool isSerialModeAvailable(uint8_t port_nr, int mode);
|
||||
int hasSerialMode(int mode);
|
||||
bool isSwitchAvailableInLogicalSwitches(int swtch);
|
||||
bool isSwitchAvailableInCustomFunctions(int swtch);
|
||||
bool isSwitchAvailableInMixes(int swtch);
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
enum ChannelsProtocols {
|
||||
PROTOCOL_CHANNELS_UNINITIALIZED,
|
||||
PROTOCOL_CHANNELS_NONE,
|
||||
PROTOCOL_CHANNELS_PPM,
|
||||
PROTOCOL_CHANNELS_PXX1_PULSES,
|
||||
PROTOCOL_CHANNELS_PXX1_SERIAL,
|
||||
PROTOCOL_CHANNELS_DSM2_LP45,
|
||||
PROTOCOL_CHANNELS_DSM2_DSM2,
|
||||
PROTOCOL_CHANNELS_DSM2_DSMX,
|
||||
PROTOCOL_CHANNELS_CROSSFIRE,
|
||||
PROTOCOL_CHANNELS_MULTIMODULE,
|
||||
PROTOCOL_CHANNELS_SBUS,
|
||||
PROTOCOL_CHANNELS_PXX2_LOWSPEED,
|
||||
PROTOCOL_CHANNELS_PXX2_HIGHSPEED,
|
||||
PROTOCOL_CHANNELS_AFHDS2A,
|
||||
PROTOCOL_CHANNELS_AFHDS3,
|
||||
PROTOCOL_CHANNELS_GHOST
|
||||
};
|
||||
|
||||
struct etx_module_driver_t {
|
||||
|
||||
// Protocol implemented by this module driver
|
||||
ChannelsProtocols protocol;
|
||||
|
||||
// Init module communication
|
||||
void* (*init)(uint8_t module);
|
||||
|
||||
// // Default pulse period in microseconds
|
||||
// uint16_t (*get_default_period)(uint8_t module);
|
||||
|
||||
// De-Init module communication
|
||||
void (*deinit)(void* context);
|
||||
|
||||
// Prepare the pulses to be sent
|
||||
void (*setupPulses)(void* context, int16_t* channels, uint8_t nChannels);
|
||||
|
||||
// Send the pulses
|
||||
void (*sendPulses)(void* context);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
enum SerialParity {
|
||||
ETX_Parity_None,
|
||||
ETX_Parity_Even,
|
||||
ETX_Parity_Odd,
|
||||
};
|
||||
|
||||
enum SerialStopBits {
|
||||
ETX_StopBits_One,
|
||||
ETX_StopBits_OneAndHalf,
|
||||
ETX_StopBits_Two,
|
||||
};
|
||||
|
||||
enum SerialWordLength {
|
||||
ETX_WordLength_8,
|
||||
ETX_WordLength_9,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t baudrate; // = 0;
|
||||
uint8_t parity; // = ETX_Parity_None;
|
||||
uint8_t stop_bits; // = ETX_StopBits_One;
|
||||
uint8_t word_length; // = ETX_WordLength_8;
|
||||
uint8_t rx_enable; // = false;
|
||||
|
||||
void (*on_receive)(uint8_t data); // = nullptr;
|
||||
void (*on_error)(); // = nullptr;
|
||||
} etx_serial_init;
|
||||
|
||||
struct etx_serial_callbacks_t {
|
||||
uint8_t (*on_send)(uint8_t* data);
|
||||
void (*on_receive)(uint8_t data);
|
||||
void (*on_error)();
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
||||
// Init serial communication
|
||||
void* (*init)(const etx_serial_init* params);
|
||||
|
||||
// De-Init serial communication
|
||||
void (*deinit)(void* ctx);
|
||||
|
||||
// Send a single byte
|
||||
void (*sendByte)(void* ctx, uint8_t byte);
|
||||
|
||||
// Send a buffer
|
||||
void (*sendBuffer)(void* ctx, const uint8_t* data, uint8_t size);
|
||||
|
||||
// Wait for last send operation to complete
|
||||
void (*waitForTxCompleted)(void* ctx);
|
||||
|
||||
// Fetch byte from internal buffer
|
||||
int (*getByte)(void* ctx, uint8_t* data);
|
||||
|
||||
// Get current baudrate
|
||||
uint32_t (*getBaudrate)(void*);
|
||||
|
||||
// Callbacks
|
||||
void (*setReceiveCb)(void* ctx, void (*on_receive)(uint8_t*, uint32_t));
|
||||
void (*setBaudrateCb)(void* ctx, void (*on_set_baudrate)(uint32_t));
|
||||
|
||||
} etx_serial_driver_t;
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 "serial_driver.h"
|
||||
|
||||
typedef void etx_pwr_driver;
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
const etx_serial_driver_t* uart;
|
||||
void (*set_pwr)(uint8_t on);
|
||||
} etx_serial_port_t;
|
||||
@@ -175,7 +175,7 @@ const uint8_t * FrskyDeviceFirmwareUpdate::readHalfDuplexFrame(uint32_t timeout)
|
||||
{
|
||||
for (int i = timeout; i >= 0; i--) {
|
||||
uint8_t byte ;
|
||||
while (telemetryGetByte(&byte)) {
|
||||
while (sportGetByte(&byte)) {
|
||||
if (pushFrskyTelemetryData(byte)) {
|
||||
return telemetryRxBuffer;
|
||||
}
|
||||
@@ -251,11 +251,14 @@ void FrskyDeviceFirmwareUpdate::sendFrame()
|
||||
switch (module) {
|
||||
#if defined(INTERNAL_MODULE_PXX2)
|
||||
case INTERNAL_MODULE:
|
||||
return intmoduleSendBuffer(outputTelemetryBuffer.data, ptr - outputTelemetryBuffer.data);
|
||||
IntmoduleSerialDriver.sendBuffer(uart_ctx, outputTelemetryBuffer.data,
|
||||
ptr - outputTelemetryBuffer.data);
|
||||
return;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return sportSendBuffer(outputTelemetryBuffer.data, ptr - outputTelemetryBuffer.data);
|
||||
sportSendBuffer(outputTelemetryBuffer.data, ptr - outputTelemetryBuffer.data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,6 +309,18 @@ const char * FrskyDeviceFirmwareUpdate::sendReqVersion()
|
||||
// X9D / X9D+ / X9E / XLite IXJT = use S.PORT @ 57600 bauds
|
||||
// XLite PRO / X9Lite / X9D+ 2019 ISRM = use TX + RX @ 57600 bauds
|
||||
|
||||
#if defined(INTMODULE_USART)
|
||||
static const etx_serial_init serialInitParams = {
|
||||
.baudrate = 0,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = true,
|
||||
.on_receive = intmoduleFifoReceive,
|
||||
.on_error = intmoduleFifoError,
|
||||
};
|
||||
#endif
|
||||
|
||||
const char * FrskyDeviceFirmwareUpdate::doFlashFirmware(const char * filename, ProgressHandler progressHandler)
|
||||
{
|
||||
FIL file;
|
||||
@@ -335,10 +350,9 @@ const char * FrskyDeviceFirmwareUpdate::doFlashFirmware(const char * filename, P
|
||||
INTERNAL_MODULE_ON();
|
||||
RTOS_WAIT_MS(1);
|
||||
|
||||
etx_serial_init params;
|
||||
etx_serial_init params(serialInitParams);
|
||||
params.baudrate = 38400;
|
||||
params.rx_enable = true;
|
||||
intmoduleSerialStart(¶ms);
|
||||
uart_ctx = IntmoduleSerialDriver.init(¶ms);
|
||||
|
||||
GPIO_SetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN);
|
||||
result = uploadFileToHorusXJT(filename, &file, progressHandler);
|
||||
@@ -352,10 +366,9 @@ const char * FrskyDeviceFirmwareUpdate::doFlashFirmware(const char * filename, P
|
||||
switch (module) {
|
||||
#if defined(INTERNAL_MODULE_PXX2)
|
||||
case INTERNAL_MODULE: {
|
||||
etx_serial_init params;
|
||||
etx_serial_init params(serialInitParams);
|
||||
params.baudrate = 57600;
|
||||
params.rx_enable = true;
|
||||
intmoduleSerialStart(¶ms);
|
||||
uart_ctx = IntmoduleSerialDriver.init(¶ms);
|
||||
} break;
|
||||
#endif
|
||||
|
||||
@@ -387,14 +400,14 @@ const char * FrskyDeviceFirmwareUpdate::uploadFileToHorusXJT(const char * filena
|
||||
return STR_DEVICE_NO_RESPONSE;
|
||||
}
|
||||
|
||||
intmoduleSendByte(0x81);
|
||||
IntmoduleSerialDriver.sendByte(uart_ctx, 0x81);
|
||||
readBuffer(frame, 1, 100);
|
||||
|
||||
if (!readBuffer(frame, 8, 100) || frame[0] != 0x02) {
|
||||
return STR_DEVICE_NO_RESPONSE;
|
||||
}
|
||||
|
||||
intmoduleSendByte(0x82);
|
||||
IntmoduleSerialDriver.sendByte(uart_ctx, 0x82);
|
||||
readBuffer(frame, 1, 100);
|
||||
|
||||
uint8_t index = 0;
|
||||
@@ -412,7 +425,7 @@ const char * FrskyDeviceFirmwareUpdate::uploadFileToHorusXJT(const char * filena
|
||||
return STR_DEVICE_WRONG_REQUEST;
|
||||
|
||||
if (count == 0) {
|
||||
intmoduleSendByte(0xA1);
|
||||
IntmoduleSerialDriver.sendByte(uart_ctx, 0xA1);
|
||||
RTOS_WAIT_MS(50);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -420,15 +433,15 @@ const char * FrskyDeviceFirmwareUpdate::uploadFileToHorusXJT(const char * filena
|
||||
if (count < 1024)
|
||||
memset(((uint8_t *)buffer) + count, 0, 1024 - count);
|
||||
|
||||
intmoduleSendByte(frame[0] + 0x80);
|
||||
intmoduleSendByte(frame[1]);
|
||||
IntmoduleSerialDriver.sendByte(uart_ctx, frame[0] + 0x80);
|
||||
IntmoduleSerialDriver.sendByte(uart_ctx, frame[1]);
|
||||
|
||||
uint16_t crc_16 = crc16(CRC_1189, (uint8_t *)buffer, 1024, crc16(CRC_1189, &frame[1], 1));
|
||||
for (size_t i = 0; i < sizeof(buffer); i++) {
|
||||
intmoduleSendByte(((uint8_t *)buffer)[i]);
|
||||
IntmoduleSerialDriver.sendByte(uart_ctx, ((uint8_t *)buffer)[i]);
|
||||
}
|
||||
intmoduleSendByte(crc_16 >> 8);
|
||||
intmoduleSendByte(crc_16);
|
||||
IntmoduleSerialDriver.sendByte(uart_ctx, crc_16 >> 8);
|
||||
IntmoduleSerialDriver.sendByte(uart_ctx, crc_16);
|
||||
|
||||
index++;
|
||||
}
|
||||
@@ -582,7 +595,7 @@ const char * FrskyChipFirmwareUpdate::waitAnswer(uint8_t & status)
|
||||
for (uint8_t i = 0; i < sizeof(buffer); i++) {
|
||||
uint32_t retry = 0;
|
||||
while (true) {
|
||||
if (telemetryGetByte(&buffer[i])) {
|
||||
if (sportGetByte(&buffer[i])) {
|
||||
if ((i == 0 && buffer[0] != 0x7F) ||
|
||||
(i == 1 && buffer[1] != 0xFE) ||
|
||||
(i == 10 && buffer[10] != 0x0D) ||
|
||||
|
||||
@@ -137,6 +137,7 @@ class FrskyDeviceFirmwareUpdate {
|
||||
uint32_t address = 0;
|
||||
ModuleIndex module;
|
||||
uint8_t frame[12];
|
||||
void* uart_ctx = nullptr;
|
||||
|
||||
void startFrame(uint8_t command);
|
||||
void sendFrame();
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
#include "multi_firmware_update.h"
|
||||
#include "stk500.h"
|
||||
#include "debug.h"
|
||||
#include "timers_driver.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if defined(LIBOPENUI)
|
||||
#include "libopenui.h"
|
||||
@@ -41,50 +44,66 @@
|
||||
#include "intmodule_serial_driver.h"
|
||||
#endif
|
||||
|
||||
#include "extmodule_driver.h"
|
||||
|
||||
#define UPDATE_MULTI_EXT_BIN ".bin"
|
||||
|
||||
class MultiFirmwareUpdateDriver
|
||||
{
|
||||
public:
|
||||
MultiFirmwareUpdateDriver() {}
|
||||
const char * flashFirmware(FIL * file, const char * label, ProgressHandler progressHandler) const;
|
||||
virtual ~MultiFirmwareUpdateDriver() {}
|
||||
const char* flashFirmware(FIL* file, const char* label,
|
||||
ProgressHandler progressHandler);
|
||||
|
||||
protected:
|
||||
virtual void moduleOn() const = 0;
|
||||
virtual void init(bool inverted) const = 0;
|
||||
virtual void init(bool inverted) = 0;
|
||||
virtual bool getByte(uint8_t & byte) const = 0;
|
||||
virtual void sendByte(uint8_t byte) const = 0;
|
||||
virtual void clear() const = 0;
|
||||
virtual void deinit(bool inverted) const {}
|
||||
virtual void deinit(bool inverted) {}
|
||||
|
||||
private:
|
||||
bool getRxByte(uint8_t & byte) const;
|
||||
bool checkRxByte(uint8_t byte) const;
|
||||
const char * waitForInitialSync(bool& inverted) const;
|
||||
const char * waitForInitialSync(bool& inverted);
|
||||
const char * getDeviceSignature(uint8_t * signature) const;
|
||||
const char * loadAddress(uint32_t offset) const;
|
||||
const char * progPage(uint8_t * buffer, uint16_t size) const;
|
||||
void leaveProgMode(bool inverted) const;
|
||||
void leaveProgMode(bool inverted);
|
||||
};
|
||||
|
||||
#if defined(INTERNAL_MODULE_MULTI)
|
||||
|
||||
static const etx_serial_init serialInitParams = {
|
||||
.baudrate = 0,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = true,
|
||||
.on_receive = intmoduleFifoReceive,
|
||||
.on_error = intmoduleFifoError,
|
||||
};
|
||||
|
||||
class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
{
|
||||
public:
|
||||
MultiInternalUpdateDriver() {}
|
||||
|
||||
protected:
|
||||
void* uart_ctx = nullptr;
|
||||
|
||||
void moduleOn() const override
|
||||
{
|
||||
INTERNAL_MODULE_ON();
|
||||
}
|
||||
|
||||
void init(bool inverted) const override
|
||||
void init(bool inverted) override
|
||||
{
|
||||
etx_serial_init params;
|
||||
etx_serial_init params(serialInitParams);
|
||||
params.baudrate = 57600;
|
||||
params.rx_enable = true;
|
||||
intmoduleSerialStart(¶ms);
|
||||
uart_ctx = IntmoduleSerialDriver.init(¶ms);
|
||||
}
|
||||
|
||||
bool getByte(uint8_t & byte) const override
|
||||
@@ -94,7 +113,7 @@ class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
|
||||
void sendByte(uint8_t byte) const override
|
||||
{
|
||||
intmoduleSendByte(byte);
|
||||
IntmoduleSerialDriver.sendByte(uart_ctx, byte);
|
||||
}
|
||||
|
||||
void clear() const override
|
||||
@@ -102,13 +121,13 @@ class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
intmoduleFifo.clear();
|
||||
}
|
||||
|
||||
void deinit(bool inverted) const override
|
||||
void deinit(bool inverted) override
|
||||
{
|
||||
IntmoduleSerialDriver.deinit(uart_ctx);
|
||||
uart_ctx = nullptr;
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
static const MultiInternalUpdateDriver multiInternalUpdateDriver;
|
||||
#endif
|
||||
|
||||
class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
@@ -122,7 +141,7 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
EXTERNAL_MODULE_ON();
|
||||
}
|
||||
|
||||
void init(bool inverted) const override
|
||||
void init(bool inverted) override
|
||||
{
|
||||
#if !defined(EXTMODULE_USART)
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
@@ -142,7 +161,7 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
|
||||
bool getByte(uint8_t & byte) const override
|
||||
{
|
||||
return telemetryGetByte(&byte);
|
||||
return sportGetByte(&byte);
|
||||
}
|
||||
|
||||
void sendByte(uint8_t byte) const override
|
||||
@@ -157,7 +176,7 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
telemetryClearFifo();
|
||||
}
|
||||
|
||||
void deinit(bool inverted) const override
|
||||
void deinit(bool inverted) override
|
||||
{
|
||||
if (inverted)
|
||||
telemetryPortInvertedInit(0);
|
||||
@@ -168,8 +187,6 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
}
|
||||
};
|
||||
|
||||
static const MultiExternalUpdateDriver multiExternalUpdateDriver;
|
||||
|
||||
class MultiExtSportUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
{
|
||||
public:
|
||||
@@ -181,14 +198,14 @@ class MultiExtSportUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
EXTERNAL_MODULE_ON();
|
||||
}
|
||||
|
||||
void init(bool inverted) const override
|
||||
void init(bool inverted) override
|
||||
{
|
||||
telemetryPortInit(57600, TELEMETRY_SERIAL_WITHOUT_DMA);
|
||||
}
|
||||
|
||||
bool getByte(uint8_t & byte) const override
|
||||
{
|
||||
return telemetryGetByte(&byte);
|
||||
return sportGetByte(&byte);
|
||||
}
|
||||
|
||||
void sendByte(uint8_t byte) const override
|
||||
@@ -202,15 +219,13 @@ class MultiExtSportUpdateDriver: public MultiFirmwareUpdateDriver
|
||||
telemetryClearFifo();
|
||||
}
|
||||
|
||||
void deinit(bool inverted) const override
|
||||
void deinit(bool inverted) override
|
||||
{
|
||||
telemetryPortInit(0, 0);
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
static const MultiExtSportUpdateDriver multiExtSportUpdateDriver;
|
||||
|
||||
bool MultiFirmwareUpdateDriver::getRxByte(uint8_t & byte) const
|
||||
{
|
||||
uint16_t time;
|
||||
@@ -236,7 +251,7 @@ bool MultiFirmwareUpdateDriver::checkRxByte(uint8_t byte) const
|
||||
return getRxByte(rxchar) ? rxchar == byte : false;
|
||||
}
|
||||
|
||||
const char * MultiFirmwareUpdateDriver::waitForInitialSync(bool & inverted) const
|
||||
const char * MultiFirmwareUpdateDriver::waitForInitialSync(bool & inverted)
|
||||
{
|
||||
uint8_t byte;
|
||||
int retries = 200;
|
||||
@@ -360,7 +375,7 @@ const char * MultiFirmwareUpdateDriver::progPage(uint8_t * buffer, uint16_t size
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MultiFirmwareUpdateDriver::leaveProgMode(bool inverted) const
|
||||
void MultiFirmwareUpdateDriver::leaveProgMode(bool inverted)
|
||||
{
|
||||
sendByte(STK_LEAVE_PROGMODE);
|
||||
sendByte(CRC_EOP);
|
||||
@@ -370,7 +385,8 @@ void MultiFirmwareUpdateDriver::leaveProgMode(bool inverted) const
|
||||
deinit(inverted);
|
||||
}
|
||||
|
||||
const char * MultiFirmwareUpdateDriver::flashFirmware(FIL * file, const char * label, ProgressHandler progressHandler) const
|
||||
const char* MultiFirmwareUpdateDriver::flashFirmware(
|
||||
FIL* file, const char* label, ProgressHandler progressHandler)
|
||||
{
|
||||
#if defined(SIMU)
|
||||
for (uint16_t i = 0; i < 100; i++) {
|
||||
@@ -601,13 +617,15 @@ bool MultiDeviceFirmwareUpdate::flashFirmware(const char * filename, ProgressHan
|
||||
}
|
||||
}
|
||||
|
||||
const MultiFirmwareUpdateDriver * driver = &multiExternalUpdateDriver;
|
||||
std::unique_ptr<MultiFirmwareUpdateDriver> driver;
|
||||
if (module == EXTERNAL_MODULE)
|
||||
driver.reset(new MultiExternalUpdateDriver());
|
||||
#if defined(INTERNAL_MODULE_MULTI)
|
||||
if (module == INTERNAL_MODULE)
|
||||
driver = &multiInternalUpdateDriver;
|
||||
else if (module == INTERNAL_MODULE)
|
||||
driver.reset(new MultiInternalUpdateDriver());
|
||||
#endif
|
||||
if (type == MULTI_TYPE_ELRS)
|
||||
driver = &multiExtSportUpdateDriver;
|
||||
else if (type == MULTI_TYPE_ELRS)
|
||||
driver.reset(new MultiExtSportUpdateDriver());
|
||||
|
||||
pausePulses();
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "api_filesystem.h"
|
||||
#include "telemetry/frsky.h"
|
||||
#include "telemetry/multi.h"
|
||||
#include "aux_serial_driver.h"
|
||||
|
||||
#if defined(LIBOPENUI)
|
||||
#include "libopenui.h"
|
||||
@@ -90,9 +91,61 @@
|
||||
{ "EVT_"#xxx"_LONG", EVT_KEY_LONG(yyy) }, \
|
||||
{ "EVT_"#xxx"_REPT", EVT_KEY_REPT(yyy) }
|
||||
|
||||
#if defined(LUA) && !defined(CLI)
|
||||
Fifo<uint8_t, LUA_FIFO_SIZE> * luaRxFifo = nullptr;
|
||||
#endif
|
||||
// Note:
|
||||
// - luaRxFifo & luaReceiveData are used only for USB serial
|
||||
// - otherwise, the AUX serial buffer is used directly
|
||||
//
|
||||
static Fifo<uint8_t, LUA_FIFO_SIZE>* luaRxFifo = nullptr;
|
||||
|
||||
static int luaRxFifoGetByte(void*, uint8_t* data)
|
||||
{
|
||||
if (!luaRxFifo) return -1;
|
||||
return luaRxFifo->pop(*data);
|
||||
}
|
||||
|
||||
void luaAllocRxFifo()
|
||||
{
|
||||
if (!luaRxFifo) {
|
||||
auto fifo = new Fifo<uint8_t, LUA_FIFO_SIZE>();
|
||||
luaRxFifo = fifo;
|
||||
luaSetGetSerialByte(nullptr, luaRxFifoGetByte);
|
||||
}
|
||||
}
|
||||
|
||||
void luaFreeRxFifo()
|
||||
{
|
||||
auto fifo = luaRxFifo;
|
||||
luaSetGetSerialByte(nullptr, nullptr);
|
||||
luaRxFifo = nullptr;
|
||||
delete(fifo);
|
||||
}
|
||||
|
||||
void luaReceiveData(uint8_t* buf, uint32_t len)
|
||||
{
|
||||
if (luaRxFifo) {
|
||||
while(len--) luaRxFifo->push(*buf++);
|
||||
}
|
||||
}
|
||||
|
||||
static void (*luaSendDataCb)(void*, uint8_t) = nullptr;
|
||||
static void* luaSendDataCtx = nullptr;
|
||||
|
||||
void luaSetSendCb(void* ctx, void (*cb)(void*, uint8_t))
|
||||
{
|
||||
luaSendDataCb = nullptr;
|
||||
luaSendDataCtx = ctx;
|
||||
luaSendDataCb = cb;
|
||||
}
|
||||
|
||||
static int (*luaGetSerialByte)(void*, uint8_t*) = nullptr;
|
||||
static void* luaGetSerialByteCtx = nullptr;
|
||||
|
||||
void luaSetGetSerialByte(void* ctx, int (*fct)(void*, uint8_t*))
|
||||
{
|
||||
luaGetSerialByte = nullptr;
|
||||
luaGetSerialByteCtx = ctx;
|
||||
luaGetSerialByte = fct;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function getVersion()
|
||||
@@ -1881,22 +1934,23 @@ Set baudrate for serial port(s) affected to LUA
|
||||
*/
|
||||
static int luaSetSerialBaudrate(lua_State * L)
|
||||
{
|
||||
#if defined(AUX_SERIAL) || defined(AUX2_SERIAL)
|
||||
unsigned int baudrate = luaL_checkunsigned(L, 1);
|
||||
#endif
|
||||
// #if defined(AUX_SERIAL) || defined(AUX2_SERIAL)
|
||||
// unsigned int baudrate = luaL_checkunsigned(L, 1);
|
||||
// #endif
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
if (auxSerialMode == UART_MODE_LUA) {
|
||||
auxSerialStop();
|
||||
auxSerialSetup(baudrate, false);
|
||||
}
|
||||
#endif
|
||||
#if defined(AUX2_SERIAL)
|
||||
if (aux2SerialMode == UART_MODE_LUA) {
|
||||
aux2SerialStop();
|
||||
aux2SerialSetup(baudrate, false);
|
||||
}
|
||||
#endif
|
||||
// TODO: add some callbacks for serial settings
|
||||
// #if defined(AUX_SERIAL)
|
||||
// if (auxSerialMode == UART_MODE_LUA) {
|
||||
// auxSerialStop();
|
||||
// auxSerialSetup(baudrate, false);
|
||||
// }
|
||||
// #endif
|
||||
// #if defined(AUX2_SERIAL)
|
||||
// if (aux2SerialMode == UART_MODE_LUA) {
|
||||
// aux2SerialStop();
|
||||
// aux2SerialSetup(baudrate, false);
|
||||
// }
|
||||
// #endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1916,30 +1970,15 @@ static int luaSerialWrite(lua_State * L)
|
||||
if (!str || len < 1)
|
||||
return 0;
|
||||
|
||||
#if defined(USB_SERIAL)
|
||||
if (getSelectedUsbMode() == USB_SERIAL_MODE) {
|
||||
auto _sendCb = luaSendDataCb;
|
||||
auto _ctx = luaSendDataCtx;
|
||||
|
||||
if (_sendCb) {
|
||||
size_t wr_len = len;
|
||||
const char* p = str;
|
||||
while(wr_len--) usbSerialPutc(*p++);
|
||||
while(wr_len--) _sendCb(_ctx, *p++);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
if (auxSerialMode == UART_MODE_LUA) {
|
||||
size_t wr_len = len;
|
||||
const char* p = str;
|
||||
while(wr_len--) auxSerialPutc(*p++);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AUX2_SERIAL)
|
||||
if (aux2SerialMode == UART_MODE_LUA) {
|
||||
size_t wr_len = len;
|
||||
const char* p = str;
|
||||
while(wr_len--) aux2SerialPutc(*p++);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1961,30 +2000,29 @@ static int luaSerialRead(lua_State * L)
|
||||
#if defined(LUA) && !defined(CLI)
|
||||
int num = luaL_optunsigned(L, 1, 0);
|
||||
|
||||
if (!luaRxFifo) {
|
||||
luaRxFifo = new Fifo<uint8_t, LUA_FIFO_SIZE>();
|
||||
if (!luaRxFifo) {
|
||||
lua_pushlstring(L, "", 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
uint8_t str[LUA_FIFO_SIZE];
|
||||
uint8_t *p = str;
|
||||
while (luaRxFifo->pop(*p)) {
|
||||
p++; // increment only when pop was successful
|
||||
if (p - str >= LUA_FIFO_SIZE) {
|
||||
// buffer full
|
||||
break;
|
||||
}
|
||||
if (num == 0) {
|
||||
if (*(p - 1) == '\n' || *(p - 1) == '\r') {
|
||||
// found newline
|
||||
|
||||
auto _getByte = luaGetSerialByte;
|
||||
auto _ctx = luaGetSerialByteCtx;
|
||||
|
||||
if (_getByte) {
|
||||
while (_getByte(_ctx, p) > 0) {
|
||||
p++; // increment only when pop was successful
|
||||
if (p - str >= LUA_FIFO_SIZE) {
|
||||
// buffer full
|
||||
break;
|
||||
}
|
||||
if (num == 0) {
|
||||
if (*(p - 1) == '\n' || *(p - 1) == '\r') {
|
||||
// found newline
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (p - str >= num) {
|
||||
// requested number of characters reached
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (p - str >= num) {
|
||||
// requested number of characters reached
|
||||
break;
|
||||
}
|
||||
}
|
||||
lua_pushlstring(L, (const char*)str, p - str);
|
||||
|
||||
@@ -48,10 +48,14 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(CLI) || defined(AUX2_SERIAL)
|
||||
// LUA serial connection
|
||||
#define LUA_FIFO_SIZE 256
|
||||
extern Fifo<uint8_t, LUA_FIFO_SIZE> * luaRxFifo;
|
||||
#endif
|
||||
void luaAllocRxFifo();
|
||||
void luaFreeRxFifo();
|
||||
void luaReceiveData(uint8_t* buf, uint32_t len);
|
||||
|
||||
void luaSetSendCb(void* ctx, void (*cb)(void*, uint8_t));
|
||||
void luaSetGetSerialByte(void* ctx, int (*fct)(void*, uint8_t*));
|
||||
|
||||
extern lua_State * lsScripts;
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include "libopenui.h"
|
||||
#endif
|
||||
|
||||
#if defined(CLI)
|
||||
#include "cli.h"
|
||||
#endif
|
||||
|
||||
uint8_t currentSpeakerVolume = 255;
|
||||
uint8_t requiredSpeakerVolume = 255;
|
||||
uint8_t currentBacklightBright = 0;
|
||||
@@ -90,9 +94,11 @@ void onUSBConnectMenu(const char *result)
|
||||
else if (result == STR_USB_JOYSTICK) {
|
||||
setSelectedUsbMode(USB_JOYSTICK_MODE);
|
||||
}
|
||||
#if defined(USB_SERIAL)
|
||||
else if (result == STR_USB_SERIAL) {
|
||||
setSelectedUsbMode(USB_SERIAL_MODE);
|
||||
}
|
||||
#endif
|
||||
else if (result == STR_EXIT) {
|
||||
_usbDisabled = true;
|
||||
}
|
||||
@@ -153,6 +159,11 @@ void handleUsbConnection()
|
||||
opentxClose(false);
|
||||
usbPluggedIn();
|
||||
}
|
||||
#if defined(USB_SERIAL)
|
||||
else if (getSelectedUsbMode() == USB_SERIAL_MODE) {
|
||||
serialInit(SP_VCP, serialGetMode(SP_VCP));
|
||||
}
|
||||
#endif
|
||||
|
||||
usbStart();
|
||||
TRACE("USB started");
|
||||
@@ -165,6 +176,8 @@ void handleUsbConnection()
|
||||
if (getSelectedUsbMode() == USB_MASS_STORAGE_MODE) {
|
||||
opentxResume();
|
||||
pushEvent(EVT_ENTRY);
|
||||
} else if (getSelectedUsbMode() == USB_SERIAL_MODE) {
|
||||
serialStop(SP_VCP);
|
||||
}
|
||||
TRACE("reset selected USB mode");
|
||||
setSelectedUsbMode(USB_UNSELECTED_MODE);
|
||||
|
||||
@@ -22,6 +22,32 @@
|
||||
#include "opentx.h"
|
||||
#include "mixer_scheduler.h"
|
||||
|
||||
bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs)
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
uint32_t ulNotificationValue;
|
||||
const TickType_t xMaxBlockTime = pdMS_TO_TICKS( timeoutMs );
|
||||
|
||||
/* Wait to be notified that the transmission is complete. Note
|
||||
the first parameter is pdTRUE, which has the effect of clearing
|
||||
the task's notification value back to 0, making the notification
|
||||
value act like a binary (rather than a counting) semaphore. */
|
||||
ulNotificationValue = ulTaskNotifyTake( pdTRUE, xMaxBlockTime );
|
||||
|
||||
if( ulNotificationValue == 1 ) {
|
||||
/* The transmission ended as expected. */
|
||||
return false;
|
||||
|
||||
} else {
|
||||
/* The call to ulTaskNotifyTake() timed out. */
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
simuSleep(timeoutMs);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(SIMU)
|
||||
|
||||
// Global trigger flag
|
||||
@@ -72,27 +98,6 @@ void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs)
|
||||
mixerSchedules[moduleIdx].period = periodUs;
|
||||
}
|
||||
|
||||
bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs)
|
||||
{
|
||||
uint32_t ulNotificationValue;
|
||||
const TickType_t xMaxBlockTime = pdMS_TO_TICKS( timeoutMs );
|
||||
|
||||
/* Wait to be notified that the transmission is complete. Note
|
||||
the first parameter is pdTRUE, which has the effect of clearing
|
||||
the task's notification value back to 0, making the notification
|
||||
value act like a binary (rather than a counting) semaphore. */
|
||||
ulNotificationValue = ulTaskNotifyTake( pdTRUE, xMaxBlockTime );
|
||||
|
||||
if( ulNotificationValue == 1 ) {
|
||||
/* The transmission ended as expected. */
|
||||
return false;
|
||||
|
||||
} else {
|
||||
/* The call to ulTaskNotifyTake() timed out. */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void mixerSchedulerISRTrigger()
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _MIXER_SCHEDULER_H_
|
||||
#define _MIXER_SCHEDULER_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MIXER_SCHEDULER_DEFAULT_PERIOD_US 4000u // 4ms
|
||||
#define MIXER_SCHEDULER_JOYSTICK_PERIOD_US 2000u // 2ms
|
||||
@@ -45,12 +46,6 @@ void mixerSchedulerResetTimer();
|
||||
// Set the scheduling period for a given module
|
||||
void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs);
|
||||
|
||||
// Clear the flag before waiting
|
||||
|
||||
// Wait for the scheduler timer to trigger
|
||||
// returns true if timeout, false otherwise
|
||||
bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs);
|
||||
|
||||
// Enable the timer trigger
|
||||
void mixerSchedulerEnableTrigger();
|
||||
|
||||
@@ -72,12 +67,6 @@ void mixerSchedulerISRTrigger();
|
||||
#define mixerSchedulerSetPeriod(m,p)
|
||||
#define mixerSchedulerClearTrigger()
|
||||
|
||||
static inline bool mixerSchedulerWaitForTrigger(uint8_t timeout)
|
||||
{
|
||||
simuSleep(timeout);
|
||||
return false;
|
||||
}
|
||||
|
||||
#define mixerSchedulerEnableTrigger()
|
||||
#define mixerSchedulerDisableTrigger()
|
||||
|
||||
@@ -86,4 +75,6 @@ static inline bool mixerSchedulerWaitForTrigger(uint8_t timeout)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
// Wait for the scheduler timer to trigger
|
||||
// returns true if timeout, false otherwise
|
||||
bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs);
|
||||
|
||||
@@ -44,8 +44,6 @@
|
||||
#define IS_TRAINER_EXTERNAL_MODULE() false
|
||||
#endif
|
||||
|
||||
#define IS_TRAINER_AUX_SERIAL() (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER)
|
||||
|
||||
#define IS_PLAY_FUNC(func) ((func) >= FUNC_PLAY_SOUND && func <= FUNC_PLAY_VALUE)
|
||||
|
||||
#if defined(GVARS)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "opentx.h"
|
||||
#include "io/frsky_firmware_update.h"
|
||||
#include "hal/adc_driver.h"
|
||||
#include "aux_serial_driver.h"
|
||||
|
||||
#if defined(LIBOPENUI)
|
||||
#include "libopenui.h"
|
||||
@@ -1868,14 +1869,8 @@ void opentxInit()
|
||||
#endif
|
||||
#endif // #if !defined(EEPROM)
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
auxSerialInit(g_eeGeneral.auxSerialMode, modelTelemetryProtocol());
|
||||
#endif
|
||||
|
||||
#if defined(AUX2_SERIAL)
|
||||
aux2SerialInit(g_eeGeneral.aux2SerialMode, modelTelemetryProtocol());
|
||||
#endif
|
||||
|
||||
initSerialPorts();
|
||||
|
||||
currentSpeakerVolume = requiredSpeakerVolume = g_eeGeneral.speakerVolume + VOLUME_LEVEL_DEF;
|
||||
currentBacklightBright = requiredBacklightBright = g_eeGeneral.backlightBright;
|
||||
#if !defined(SOFTWARE_VOLUME)
|
||||
|
||||
@@ -582,14 +582,6 @@ void flightReset(uint8_t check=true);
|
||||
#define RESET_THR_TRACE() s_timeCum16ThrP = s_timeCumThr = 0
|
||||
#endif
|
||||
|
||||
#if defined(SIMU)
|
||||
uint16_t getTmr2MHz();
|
||||
uint16_t getTmr16KHz();
|
||||
#else
|
||||
static inline uint16_t getTmr2MHz() { return TIMER_2MHz_TIMER->CNT; }
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(SPLASH)
|
||||
void doSplash();
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,15 @@
|
||||
*/
|
||||
|
||||
#include "afhds2.h"
|
||||
#include "flysky.h"
|
||||
|
||||
#include "intmodule_serial_driver.h"
|
||||
#include "mixer_scheduler.h"
|
||||
|
||||
// solely for 'intmoduleFifo'
|
||||
// TODO: remove this non-sense
|
||||
#include "opentx.h"
|
||||
#include "pulses/pxx2.h"
|
||||
|
||||
afhds2::afhds2() {
|
||||
// TODO Auto-generated constructor stub
|
||||
@@ -30,3 +39,69 @@ afhds2::~afhds2() {
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
const etx_serial_init afhds2SerialInitParams = {
|
||||
.baudrate = INTMODULE_USART_AFHDS2_BAUDRATE,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = true,
|
||||
.on_receive = intmoduleFifoReceive,
|
||||
.on_error = intmoduleFifoError,
|
||||
};
|
||||
|
||||
static void* afhds2Init(uint8_t module)
|
||||
{
|
||||
(void)module;
|
||||
|
||||
// serial port setup
|
||||
resetPulsesAFHDS2();
|
||||
intmoduleFifo.clear();
|
||||
IntmoduleSerialDriver.init(&afhds2SerialInitParams);
|
||||
|
||||
// mixer setup
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, AFHDS2_PERIOD);
|
||||
INTERNAL_MODULE_ON();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void afhds2DeInit(void* context)
|
||||
{
|
||||
INTERNAL_MODULE_OFF();
|
||||
intmoduleFifo.clear();
|
||||
IntmoduleSerialDriver.deinit(context);
|
||||
|
||||
// mixer setup
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
|
||||
}
|
||||
|
||||
static void afhds2SetupPulses(void* context, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
(void)context;
|
||||
|
||||
// TODO:
|
||||
(void)channels;
|
||||
(void)nChannels;
|
||||
|
||||
ModuleSyncStatus& status = getModuleSyncStatus(INTERNAL_MODULE);
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, status.isValid()
|
||||
? status.getAdjustedRefreshRate()
|
||||
: AFHDS2_PERIOD);
|
||||
status.invalidate();
|
||||
setupPulsesAFHDS2();
|
||||
}
|
||||
|
||||
static void afhds2SendPulses(void* context)
|
||||
{
|
||||
uint8_t* data = (uint8_t*)intmodulePulsesData.flysky.pulses;
|
||||
uint16_t size = intmodulePulsesData.flysky.ptr - data;
|
||||
IntmoduleSerialDriver.sendBuffer(context, data, size);
|
||||
}
|
||||
|
||||
const etx_module_driver_t Afhds2InternalDriver = {
|
||||
.protocol = PROTOCOL_CHANNELS_AFHDS2A,
|
||||
.init = afhds2Init,
|
||||
.deinit = afhds2DeInit,
|
||||
.setupPulses = afhds2SetupPulses,
|
||||
.sendPulses = afhds2SendPulses,
|
||||
};
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include "hal/serial_driver.h"
|
||||
#include "hal/module_driver.h"
|
||||
|
||||
#define AFHDS2_PERIOD (2 * 1000) /* us */
|
||||
|
||||
struct FlySkySerialPulsesData {
|
||||
@@ -56,4 +59,7 @@ public:
|
||||
virtual ~afhds2();
|
||||
};
|
||||
|
||||
extern const etx_serial_init afhds2SerialInitParams;
|
||||
extern const etx_module_driver_t Afhds2InternalDriver;
|
||||
|
||||
#endif /* PULSES_AFHDS2_H_ */
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "mixer_scheduler.h"
|
||||
#include "hal/module_driver.h"
|
||||
|
||||
#if defined(INTMODULE_USART)
|
||||
#include "intmodule_serial_driver.h"
|
||||
#endif
|
||||
|
||||
#define CROSSFIRE_CH_BITS 11
|
||||
#define CROSSFIRE_CENTER 0x3E0
|
||||
@@ -71,7 +77,8 @@ uint8_t createCrossfireChannelsFrame(uint8_t * frame, int16_t * pulses)
|
||||
}
|
||||
|
||||
static void setupPulsesCrossfire(uint8_t idx, CrossfirePulsesData* p_data,
|
||||
uint8_t endpoint)
|
||||
uint8_t endpoint, int16_t* channels,
|
||||
uint8_t nChannels)
|
||||
{
|
||||
#if defined(LUA)
|
||||
if (outputTelemetryBuffer.destination == endpoint) {
|
||||
@@ -88,18 +95,136 @@ static void setupPulsesCrossfire(uint8_t idx, CrossfirePulsesData* p_data,
|
||||
} else {
|
||||
p_data->length = createCrossfireChannelsFrame(
|
||||
p_data->pulses,
|
||||
&channelOutputs[g_model.moduleData[idx].channelsStart]);
|
||||
channels /*TODO: nChannels*/);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setupPulsesCrossfire(uint8_t idx)
|
||||
static void crossfireSetupMixerScheduler(uint8_t module)
|
||||
{
|
||||
if (idx == INTERNAL_MODULE) {
|
||||
auto* p_data = &intmodulePulsesData.crossfire;
|
||||
setupPulsesCrossfire(idx, p_data, 0);
|
||||
} else if (telemetryProtocol == PROTOCOL_TELEMETRY_CROSSFIRE) {
|
||||
auto* p_data = &extmodulePulsesData.crossfire;
|
||||
setupPulsesCrossfire(idx, p_data, TELEMETRY_ENDPOINT_SPORT);
|
||||
ModuleSyncStatus& status = getModuleSyncStatus(module);
|
||||
if (status.isValid()) {
|
||||
mixerSchedulerSetPeriod(module, status.getAdjustedRefreshRate());
|
||||
} else {
|
||||
mixerSchedulerSetPeriod(module, CROSSFIRE_PERIOD);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(INTERNAL_MODULE_CRSF)
|
||||
static void intmoduleCRSF_rx(uint8_t data)
|
||||
{
|
||||
intmoduleFifo.push(data);
|
||||
|
||||
#if !defined(SIMU)
|
||||
// wakeup mixer when rx buffer is quarter full (16 bytes)
|
||||
if (intmoduleFifo.size() >= 16) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xTaskNotifyFromISR(mixerTaskId.rtos_handle, 0, eNoAction,
|
||||
&xHigherPriorityTaskWoken);
|
||||
|
||||
// might effect a context switch on ISR exit
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static const etx_serial_init intmoduleCrossfireInitParams = {
|
||||
.baudrate = 0,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = true,
|
||||
.on_receive = intmoduleCRSF_rx,
|
||||
.on_error = nullptr,
|
||||
};
|
||||
|
||||
static void* crossfireInitInternal(uint8_t module)
|
||||
{
|
||||
(void)module;
|
||||
|
||||
// serial port setup
|
||||
etx_serial_init params(intmoduleCrossfireInitParams);
|
||||
params.baudrate = CROSSFIRE_BAUDRATE;
|
||||
|
||||
// wakeup mixer when rx buffer is quarter full (16 bytes)
|
||||
params.on_receive = intmoduleCRSF_rx;
|
||||
|
||||
intmoduleFifo.clear();
|
||||
IntmoduleSerialDriver.init(¶ms);
|
||||
INTERNAL_MODULE_ON();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void crossfireDeInitInternal(void* context)
|
||||
{
|
||||
(void)context;
|
||||
|
||||
INTERNAL_MODULE_OFF();
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
|
||||
intmoduleStop();
|
||||
intmoduleFifo.clear();
|
||||
}
|
||||
|
||||
static void crossfireSetupPulsesInternal(void* context, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
auto* p_data = &intmodulePulsesData.crossfire;
|
||||
crossfireSetupMixerScheduler(INTERNAL_MODULE);
|
||||
setupPulsesCrossfire(INTERNAL_MODULE, p_data, 0, channels, nChannels);
|
||||
}
|
||||
|
||||
static void crossfireSendPulsesInternal(void* context)
|
||||
{
|
||||
IntmoduleSerialDriver.sendBuffer(context, intmodulePulsesData.crossfire.pulses,
|
||||
intmodulePulsesData.crossfire.length);
|
||||
}
|
||||
|
||||
etx_module_driver_t CrossfireInternalDriver = {
|
||||
.protocol = PROTOCOL_CHANNELS_CROSSFIRE,
|
||||
.init = crossfireInitInternal,
|
||||
.deinit = crossfireDeInitInternal,
|
||||
.setupPulses = crossfireSetupPulsesInternal,
|
||||
.sendPulses = crossfireSendPulsesInternal,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void* crossfireInitExternal(uint8_t module)
|
||||
{
|
||||
telemetryInit(PROTOCOL_TELEMETRY_CROSSFIRE);
|
||||
mixerSchedulerSetPeriod(module, CROSSFIRE_PERIOD);
|
||||
EXTERNAL_MODULE_ON();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void crossfireDeInitExternal(void* context)
|
||||
{
|
||||
(void)context;
|
||||
telemetryProtocol = 0xFF;
|
||||
|
||||
EXTERNAL_MODULE_OFF();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
|
||||
}
|
||||
|
||||
static void crossfireSetupPulsesExternal(void* context, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
auto* p_data = &extmodulePulsesData.crossfire;
|
||||
crossfireSetupMixerScheduler(EXTERNAL_MODULE);
|
||||
setupPulsesCrossfire(EXTERNAL_MODULE, p_data, TELEMETRY_ENDPOINT_SPORT,
|
||||
channels, nChannels);
|
||||
}
|
||||
|
||||
static void crossfireSendPulsesExternal(void* context)
|
||||
{
|
||||
(void)context;
|
||||
|
||||
sportSendBuffer(extmodulePulsesData.crossfire.pulses,
|
||||
extmodulePulsesData.crossfire.length);
|
||||
}
|
||||
|
||||
etx_module_driver_t CrossfireExternalDriver = {
|
||||
.protocol = PROTOCOL_CHANNELS_CROSSFIRE,
|
||||
.init = crossfireInitExternal,
|
||||
.deinit = crossfireDeInitExternal,
|
||||
.setupPulses = crossfireSetupPulsesExternal,
|
||||
.sendPulses = crossfireSendPulsesExternal
|
||||
};
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 "hal/module_driver.h"
|
||||
|
||||
extern etx_module_driver_t CrossfireInternalDriver;
|
||||
extern etx_module_driver_t CrossfireExternalDriver;
|
||||
@@ -66,9 +66,9 @@ void sendByteDsm2(uint8_t b) // max 10 changes 0 10 10 10 10 1
|
||||
void putDsm2Flush()
|
||||
{
|
||||
if (extmodulePulsesData.dsm2.index & 1)
|
||||
*extmodulePulsesData.dsm2.ptr++ = 60000;
|
||||
*extmodulePulsesData.dsm2.ptr++ = 255;
|
||||
else
|
||||
*(extmodulePulsesData.dsm2.ptr - 1) = 60000;
|
||||
*(extmodulePulsesData.dsm2.ptr - 1) = 255;
|
||||
}
|
||||
|
||||
// This is the data stream to send, prepare after 19.5 mS
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "io/multi_protolist.h"
|
||||
#include "telemetry/multi.h"
|
||||
#include "mixer_scheduler.h"
|
||||
|
||||
// for the MULTI protocol definition
|
||||
// see https://github.com/pascallanger/DIY-Multiprotocol-TX-Module
|
||||
@@ -50,6 +51,20 @@ static void sendConfig(uint8_t moduleIdx);
|
||||
static void sendDSM(uint8_t moduleIdx);
|
||||
#endif
|
||||
|
||||
#if defined(INTMODULE_USART)
|
||||
#include "intmodule_serial_driver.h"
|
||||
|
||||
etx_serial_init multiSerialInitParams = {
|
||||
.baudrate = MULTIMODULE_BAUDRATE,
|
||||
.parity = ETX_Parity_Even,
|
||||
.stop_bits = ETX_StopBits_Two,
|
||||
.word_length = ETX_WordLength_9,
|
||||
.rx_enable = true,
|
||||
.on_receive = intmoduleFifoReceive,
|
||||
.on_error = intmoduleFifoError,
|
||||
};
|
||||
#endif
|
||||
|
||||
void multiPatchCustom(uint8_t moduleIdx)
|
||||
{
|
||||
if (g_model.moduleData[moduleIdx].multi.customProto) {
|
||||
@@ -235,6 +250,66 @@ void setupPulsesMultiInternalModule()
|
||||
intmodulePulsesData.multi.initFrame();
|
||||
setupPulsesMulti(INTERNAL_MODULE);
|
||||
}
|
||||
|
||||
static void* multiInit(uint8_t module)
|
||||
{
|
||||
(void)module;
|
||||
|
||||
// serial port setup
|
||||
intmodulePulsesData.multi.initFrame();
|
||||
intmoduleFifo.clear();
|
||||
void* uart_ctx = IntmoduleSerialDriver.init(&multiSerialInitParams);
|
||||
|
||||
// mixer setup
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD);
|
||||
INTERNAL_MODULE_ON();
|
||||
|
||||
// reset status
|
||||
getMultiModuleStatus(INTERNAL_MODULE).failsafeChecked = false;
|
||||
getMultiModuleStatus(INTERNAL_MODULE).flags = 0;
|
||||
|
||||
#if defined(MULTI_PROTOLIST)
|
||||
TRACE("enablePulsesInternalModule(): trigger scan");
|
||||
MultiRfProtocols::instance(INTERNAL_MODULE)->triggerScan();
|
||||
TRACE("counter = %d", moduleState[INTERNAL_MODULE].counter);
|
||||
#endif
|
||||
|
||||
return uart_ctx;
|
||||
}
|
||||
|
||||
static void multiDeInit(void* context)
|
||||
{
|
||||
INTERNAL_MODULE_OFF();
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
|
||||
IntmoduleSerialDriver.deinit(context);
|
||||
}
|
||||
|
||||
static void multiSetupPulses(void* context, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
(void)context;
|
||||
// TODO:
|
||||
(void)channels;
|
||||
(void)nChannels;
|
||||
|
||||
intmodulePulsesData.multi.initFrame();
|
||||
setupPulsesMulti(INTERNAL_MODULE);
|
||||
}
|
||||
|
||||
static void multiSendPulses(void* context)
|
||||
{
|
||||
IntmoduleSerialDriver.sendBuffer(context, intmodulePulsesData.multi.getData(),
|
||||
intmodulePulsesData.multi.getSize());
|
||||
}
|
||||
|
||||
#include "hal/module_driver.h"
|
||||
|
||||
const etx_module_driver_t MultiInternalDriver = {
|
||||
.protocol = PROTOCOL_CHANNELS_MULTIMODULE,
|
||||
.init = multiInit,
|
||||
.deinit = multiDeInit,
|
||||
.setupPulses = multiSetupPulses,
|
||||
.sendPulses = multiSendPulses
|
||||
};
|
||||
#endif
|
||||
|
||||
void sendChannels(uint8_t moduleIdx)
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#define _MULTI_PULSES_H_
|
||||
|
||||
#include "pulses_common.h"
|
||||
#include "hal/serial_driver.h"
|
||||
#include "hal/module_driver.h"
|
||||
|
||||
void multiPatchCustom(uint8_t moduleIdx);
|
||||
void convertEtxProtocolToMulti(int *protocol, int *subprotocol);
|
||||
@@ -43,4 +45,7 @@ class UartMultiPulses: public DataBuffer<uint8_t, 64>
|
||||
}
|
||||
};
|
||||
|
||||
extern etx_serial_init multiSerialInitParams;
|
||||
extern const etx_module_driver_t MultiInternalDriver;
|
||||
|
||||
#endif
|
||||
|
||||
+30
-17
@@ -22,46 +22,59 @@
|
||||
#include "opentx.h"
|
||||
|
||||
template<class T>
|
||||
void setupPulsesPPM(PpmPulsesData<T> * ppmPulsesData, uint8_t channelsStart, int8_t channelsCount, int8_t frameLength)
|
||||
void setupPulsesPPM(PpmPulsesData<T> * ppmPulsesData, uint8_t channelsStart, int8_t channelsCount)
|
||||
{
|
||||
int16_t PPM_range = g_model.extendedLimits ? (512*LIMIT_EXT_PERCENT/100) * 2 : 512 * 2; // range of 0.7 .. 1.7msec
|
||||
int16_t PPM_range = g_model.extendedLimits ?
|
||||
// range of 0.7 .. 1.7msec
|
||||
(512*LIMIT_EXT_PERCENT/100) * 2 : 512 * 2;
|
||||
|
||||
// Total frame length = 22.5msec
|
||||
// each pulse is 0.7..1.7ms long with a 0.3ms stop tail
|
||||
// The pulse ISR is 2mhz that's why everything is multiplied by 2
|
||||
|
||||
uint8_t firstCh = channelsStart;
|
||||
uint8_t lastCh = min<uint8_t>(MAX_OUTPUT_CHANNELS, firstCh + 8 + channelsCount);
|
||||
uint8_t lastCh =
|
||||
min<uint8_t>(MAX_OUTPUT_CHANNELS, firstCh + 8 + channelsCount);
|
||||
|
||||
ppmPulsesData->ptr = ppmPulsesData->pulses;
|
||||
|
||||
int32_t rest = 22500u * 2;
|
||||
rest += int32_t(frameLength) * 1000;
|
||||
for (uint32_t i=firstCh; i<lastCh; i++) {
|
||||
int16_t v = limit((int16_t)-PPM_range, channelOutputs[i], (int16_t)PPM_range) + 2*PPM_CH_CENTER(i);
|
||||
rest -= v;
|
||||
*ppmPulsesData->ptr++ = v; /* as Pat MacKenzie suggests */
|
||||
for (uint32_t i = firstCh; i < lastCh; i++) {
|
||||
int16_t v =
|
||||
limit((int16_t)-PPM_range, channelOutputs[i], (int16_t)PPM_range) +
|
||||
2 * PPM_CH_CENTER(i);
|
||||
*ppmPulsesData->ptr++ = v;
|
||||
}
|
||||
rest = limit<int32_t>(9000, rest, 65535); /* avoids that CCR2 is bigger than ARR which would cause reboot */
|
||||
*ppmPulsesData->ptr++ = rest;
|
||||
*ppmPulsesData->ptr = 0; // it's needed in case PPM is sent without DMA (we stop when we reach this 0)
|
||||
|
||||
// Set the final period to the max
|
||||
// (a new transfer is issued before it expires)
|
||||
// debug: set the last period to the ppm_delay
|
||||
*ppmPulsesData->ptr++ = 2000;
|
||||
//*ppmPulsesData->ptr++ = 65535;
|
||||
|
||||
// it's needed in case PPM is sent without DMA
|
||||
// (we stop when we reach this 0)
|
||||
*ppmPulsesData->ptr = 0;
|
||||
}
|
||||
|
||||
void setupPulsesPPMTrainer()
|
||||
{
|
||||
setupPulsesPPM<trainer_pulse_duration_t>(&trainerPulsesData.ppm, g_model.trainerData.channelsStart, g_model.trainerData.channelsCount, g_model.trainerData.frameLength);
|
||||
setupPulsesPPM<trainer_pulse_duration_t>(
|
||||
&trainerPulsesData.ppm, g_model.trainerData.channelsStart,
|
||||
g_model.trainerData.channelsCount);
|
||||
}
|
||||
|
||||
#if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM)
|
||||
void setupPulsesPPMInternalModule()
|
||||
{
|
||||
setupPulsesPPM(&intmodulePulsesData.ppm, g_model.moduleData[INTERNAL_MODULE].channelsStart, g_model.moduleData[INTERNAL_MODULE].channelsCount, g_model.moduleData[INTERNAL_MODULE].ppm.frameLength);
|
||||
setupPulsesPPM(&intmodulePulsesData.ppm,
|
||||
g_model.moduleData[INTERNAL_MODULE].channelsStart,
|
||||
g_model.moduleData[INTERNAL_MODULE].channelsCount);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setupPulsesPPMExternalModule()
|
||||
{
|
||||
setupPulsesPPM(&extmodulePulsesData.ppm, g_model.moduleData[EXTERNAL_MODULE].channelsStart, g_model.moduleData[EXTERNAL_MODULE].channelsCount, g_model.moduleData[EXTERNAL_MODULE].ppm.frameLength);
|
||||
setupPulsesPPM(&extmodulePulsesData.ppm,
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsStart,
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+273
-320
@@ -21,9 +21,9 @@
|
||||
|
||||
#include "opentx.h"
|
||||
#include "mixer_scheduler.h"
|
||||
#include "heartbeat_driver.h"
|
||||
|
||||
#include "io/frsky_pxx2.h"
|
||||
#include "io/multi_protolist.h"
|
||||
#include "pulses/pxx2.h"
|
||||
#include "pulses/flysky.h"
|
||||
|
||||
@@ -33,6 +33,22 @@
|
||||
#include "intmodule_pulses_driver.h"
|
||||
#endif
|
||||
|
||||
#include "extmodule_serial_driver.h"
|
||||
#include "extmodule_driver.h"
|
||||
|
||||
#if defined(CROSSFIRE)
|
||||
#include "pulses/crossfire.h"
|
||||
#endif
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
#include "io/multi_protolist.h"
|
||||
#include "pulses/multi.h"
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS2)
|
||||
#include "pulses/afhds2.h"
|
||||
#endif
|
||||
|
||||
uint8_t s_pulses_paused = 0;
|
||||
ModuleState moduleState[NUM_MODULES];
|
||||
InternalModulePulsesData intmodulePulsesData __DMA;
|
||||
@@ -272,10 +288,183 @@ uint8_t getRequiredProtocol(uint8_t module)
|
||||
return protocol;
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_INTERNAL_MODULE)
|
||||
static void* internalModuleContext = nullptr;
|
||||
static const etx_module_driver_t* internalModuleDriver = nullptr;
|
||||
|
||||
static void enablePulsesInternalModule(uint8_t protocol)
|
||||
{
|
||||
// start new protocol hardware here
|
||||
if (internalModuleDriver) {
|
||||
internalModuleDriver->deinit(internalModuleContext);
|
||||
internalModuleContext = nullptr;
|
||||
internalModuleDriver = nullptr;
|
||||
} else {
|
||||
intmoduleStop();
|
||||
}
|
||||
|
||||
switch (protocol) {
|
||||
#if defined(PXX1) && !defined(INTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX1_PULSES:
|
||||
intmodulePxx1PulsesStart();
|
||||
#if defined(INTMODULE_HEARTBEAT)
|
||||
init_intmodule_heartbeat();
|
||||
#endif
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PXX1) && defined(INTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX1_SERIAL:
|
||||
internalModuleContext = Pxx1InternalSerialDriver.init(INTERNAL_MODULE);
|
||||
internalModuleDriver = &Pxx1InternalSerialDriver;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PXX2)
|
||||
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
|
||||
internalModuleContext = Pxx2InternalDriver.init(INTERNAL_MODULE);
|
||||
internalModuleDriver = &Pxx2InternalDriver;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_MULTI)
|
||||
case PROTOCOL_CHANNELS_MULTIMODULE:
|
||||
internalModuleContext = MultiInternalDriver.init(INTERNAL_MODULE);
|
||||
internalModuleDriver = &MultiInternalDriver;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_CRSF)
|
||||
case PROTOCOL_CHANNELS_CROSSFIRE:
|
||||
internalModuleContext = CrossfireInternalDriver.init(INTERNAL_MODULE);
|
||||
internalModuleDriver = &CrossfireInternalDriver;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_PPM)
|
||||
case PROTOCOL_CHANNELS_PPM:
|
||||
intmodulePpmStart();
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, PPM_PERIOD(INTERNAL_MODULE));
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_AFHDS2A)
|
||||
case PROTOCOL_CHANNELS_AFHDS2A:
|
||||
internalModuleContext = Afhds2InternalDriver.init(INTERNAL_MODULE);
|
||||
internalModuleDriver = &Afhds2InternalDriver;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
// internal module stopped, use default mixer period
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool setupPulsesInternalModule(uint8_t protocol)
|
||||
{
|
||||
uint8_t channelStart = g_model.moduleData[INTERNAL_MODULE].channelsStart;
|
||||
int16_t* channels = &channelOutputs[channelStart];
|
||||
uint8_t nChannels = 16; // TODO: MAX_CHANNELS - channelsStart
|
||||
|
||||
if (internalModuleDriver) {
|
||||
internalModuleDriver->setupPulses(internalModuleContext,
|
||||
channels, nChannels);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (protocol) {
|
||||
#if defined(HARDWARE_INTERNAL_MODULE) && defined(PXX1) && !defined(INTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX1_PULSES:
|
||||
intmodulePulsesData.pxx.setupFrame(INTERNAL_MODULE);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM)
|
||||
case PROTOCOL_CHANNELS_PPM:
|
||||
setupPulsesPPMInternalModule();
|
||||
return true;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void stopPulsesInternalModule()
|
||||
{
|
||||
if (moduleState[INTERNAL_MODULE].protocol != PROTOCOL_CHANNELS_UNINITIALIZED) {
|
||||
if (internalModuleDriver) {
|
||||
internalModuleDriver->deinit(internalModuleContext);
|
||||
internalModuleDriver = nullptr;
|
||||
internalModuleContext = nullptr;
|
||||
} else {
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
|
||||
intmoduleStop();
|
||||
}
|
||||
moduleState[INTERNAL_MODULE].protocol = PROTOCOL_CHANNELS_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void intmoduleSendNextFrame()
|
||||
{
|
||||
if (internalModuleDriver) {
|
||||
internalModuleDriver->sendPulses(internalModuleContext);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (moduleState[INTERNAL_MODULE].protocol) {
|
||||
|
||||
#if defined(INTERNAL_MODULE_PPM)
|
||||
case PROTOCOL_CHANNELS_PPM:
|
||||
intmoduleSendNextFramePPM(
|
||||
intmodulePulsesData.ppm.pulses,
|
||||
intmodulePulsesData.ppm.ptr - intmodulePulsesData.ppm.pulses);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PXX1) && !defined(INTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX1_PULSES:
|
||||
intmoduleSendNextFramePxx1(intmodulePulsesData.pxx.getData(),
|
||||
intmodulePulsesData.pxx.getSize());
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool setupPulsesInternalModule()
|
||||
{
|
||||
uint8_t protocol = getRequiredProtocol(INTERNAL_MODULE);
|
||||
|
||||
heartbeat |= (HEART_TIMER_PULSES << INTERNAL_MODULE);
|
||||
|
||||
if (moduleState[INTERNAL_MODULE].protocol != protocol) {
|
||||
enablePulsesInternalModule(protocol);
|
||||
moduleState[INTERNAL_MODULE].protocol = protocol;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return setupPulsesInternalModule(protocol);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_EXTERNAL_MODULE)
|
||||
static void* externalModuleContext = nullptr;
|
||||
static const etx_module_driver_t* externalModuleDriver = nullptr;
|
||||
|
||||
void enablePulsesExternalModule(uint8_t protocol)
|
||||
{
|
||||
// start new protocol hardware here
|
||||
if (externalModuleDriver) {
|
||||
externalModuleDriver->deinit(externalModuleContext);
|
||||
externalModuleDriver = nullptr;
|
||||
externalModuleContext = nullptr;
|
||||
} else {
|
||||
extmoduleStop();
|
||||
}
|
||||
|
||||
switch (protocol) {
|
||||
#if defined(PXX1)
|
||||
@@ -287,8 +476,8 @@ void enablePulsesExternalModule(uint8_t protocol)
|
||||
|
||||
#if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
|
||||
case PROTOCOL_CHANNELS_PXX1_SERIAL:
|
||||
extmodulePxx1SerialStart();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, EXTMODULE_PXX1_SERIAL_PERIOD);
|
||||
externalModuleContext = Pxx1ExternalSerialDriver.init(EXTERNAL_MODULE);
|
||||
externalModuleDriver = &Pxx1ExternalSerialDriver;
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -296,15 +485,19 @@ void enablePulsesExternalModule(uint8_t protocol)
|
||||
case PROTOCOL_CHANNELS_DSM2_LP45:
|
||||
case PROTOCOL_CHANNELS_DSM2_DSM2:
|
||||
case PROTOCOL_CHANNELS_DSM2_DSMX:
|
||||
#if defined(PCBSKY9X)
|
||||
extmoduleSerialStart(DSM2_BAUDRATE, DSM2_PERIOD * 2000, false);
|
||||
#else
|
||||
extmoduleSerialStart();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, DSM2_PERIOD);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(CROSSFIRE)
|
||||
case PROTOCOL_CHANNELS_CROSSFIRE:
|
||||
EXTERNAL_MODULE_ON();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, CROSSFIRE_PERIOD);
|
||||
externalModuleContext = CrossfireExternalDriver.init(EXTERNAL_MODULE);
|
||||
externalModuleDriver = &CrossfireExternalDriver;
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -317,13 +510,13 @@ void enablePulsesExternalModule(uint8_t protocol)
|
||||
|
||||
#if defined(PXX2) && defined(EXTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
|
||||
extmoduleInvertedSerialStart(PXX2_HIGHSPEED_BAUDRATE);
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX2_NO_HEARTBEAT_PERIOD);
|
||||
externalModuleContext = Pxx2ExternalDriver.init(EXTERNAL_MODULE);
|
||||
externalModuleDriver = &Pxx2ExternalDriver;
|
||||
break;
|
||||
|
||||
case PROTOCOL_CHANNELS_PXX2_LOWSPEED:
|
||||
extmoduleInvertedSerialStart(PXX2_LOWSPEED_BAUDRATE);
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX2_NO_HEARTBEAT_PERIOD);
|
||||
externalModuleContext = Pxx2LowSpeedExternalDriver.init(EXTERNAL_MODULE);
|
||||
externalModuleDriver = &Pxx2LowSpeedExternalDriver;
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -341,20 +534,27 @@ void enablePulsesExternalModule(uint8_t protocol)
|
||||
|
||||
#if defined(SBUS)
|
||||
case PROTOCOL_CHANNELS_SBUS:
|
||||
#if defined(PCBSKY9X)
|
||||
extmoduleSerialStart(SBUS_BAUDRATE, SBUS_PERIOD_HALF_US, false);
|
||||
#else
|
||||
extmoduleSerialStart();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, SBUS_PERIOD);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PPM)
|
||||
case PROTOCOL_CHANNELS_PPM:
|
||||
extmodulePpmStart();
|
||||
extmodulePpmStart(
|
||||
GET_MODULE_PPM_DELAY(EXTERNAL_MODULE),
|
||||
GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE));
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, PPM_PERIOD(EXTERNAL_MODULE));
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS3)
|
||||
case PROTOCOL_CHANNELS_AFHDS3:
|
||||
// convert to serial module interface
|
||||
extmodulePulsesData.afhds3.init(EXTERNAL_MODULE);
|
||||
extmoduleSerialStart();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, AFHDS3_COMMAND_TIMEOUT * 1000 /* us */);
|
||||
@@ -370,6 +570,16 @@ void enablePulsesExternalModule(uint8_t protocol)
|
||||
|
||||
bool setupPulsesExternalModule(uint8_t protocol)
|
||||
{
|
||||
uint8_t channelStart = g_model.moduleData[EXTERNAL_MODULE].channelsStart;
|
||||
int16_t* channels = &channelOutputs[channelStart];
|
||||
uint8_t nChannels = 16; // TODO: MAX_CHANNELS - channelsStart
|
||||
|
||||
if (externalModuleDriver) {
|
||||
externalModuleDriver->setupPulses(externalModuleContext,
|
||||
channels, nChannels);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (protocol) {
|
||||
|
||||
#if defined(PXX1)
|
||||
@@ -378,19 +588,6 @@ bool setupPulsesExternalModule(uint8_t protocol)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
|
||||
case PROTOCOL_CHANNELS_PXX1_SERIAL:
|
||||
extmodulePulsesData.pxx_uart.setupFrame(EXTERNAL_MODULE);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(PXX2)
|
||||
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
|
||||
case PROTOCOL_CHANNELS_PXX2_LOWSPEED:
|
||||
extmodulePulsesData.pxx2.setupFrame(EXTERNAL_MODULE);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(SBUS)
|
||||
case PROTOCOL_CHANNELS_SBUS:
|
||||
setupPulsesSbus();
|
||||
@@ -407,19 +604,6 @@ bool setupPulsesExternalModule(uint8_t protocol)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(CROSSFIRE)
|
||||
case PROTOCOL_CHANNELS_CROSSFIRE:
|
||||
{
|
||||
ModuleSyncStatus& status = getModuleSyncStatus(EXTERNAL_MODULE);
|
||||
if (status.isValid())
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, status.getAdjustedRefreshRate());
|
||||
else
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, CROSSFIRE_PERIOD);
|
||||
setupPulsesCrossfire(EXTERNAL_MODULE);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GHOST)
|
||||
case PROTOCOL_CHANNELS_GHOST:
|
||||
{
|
||||
@@ -462,314 +646,84 @@ bool setupPulsesExternalModule(uint8_t protocol)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_INTERNAL_MODULE)
|
||||
|
||||
#if defined(INTERNAL_MODULE_CRSF)
|
||||
static void intmoduleCRSF_rx(uint8_t data)
|
||||
void extmoduleSendNextFrame()
|
||||
{
|
||||
intmoduleFifo.push(data);
|
||||
|
||||
#if !defined(SIMU)
|
||||
// wakeup mixer when rx buffer is quarter full (16 bytes)
|
||||
if (intmoduleFifo.size() >= 16) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xTaskNotifyFromISR(mixerTaskId.rtos_handle, 0, eNoAction,
|
||||
&xHigherPriorityTaskWoken);
|
||||
|
||||
// might effect a context switch on ISR exit
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
if (externalModuleDriver) {
|
||||
externalModuleDriver->sendPulses(externalModuleContext);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void enablePulsesInternalModule(uint8_t protocol)
|
||||
{
|
||||
// start new protocol hardware here
|
||||
switch (moduleState[EXTERNAL_MODULE].protocol) {
|
||||
|
||||
switch (protocol) {
|
||||
#if defined(PXX1) && !defined(INTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX1_PULSES:
|
||||
intmodulePxx1PulsesStart();
|
||||
#if defined(INTMODULE_HEARTBEAT)
|
||||
init_intmodule_heartbeat();
|
||||
#endif
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PXX1) && defined(INTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX1_SERIAL:
|
||||
intmodulePxx1SerialStart();
|
||||
#if defined(INTMODULE_HEARTBEAT)
|
||||
init_intmodule_heartbeat();
|
||||
#endif
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PXX2)
|
||||
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: {
|
||||
etx_serial_init params;
|
||||
params.baudrate = PXX2_HIGHSPEED_BAUDRATE;
|
||||
params.rx_enable = true;
|
||||
|
||||
intmoduleFifo.clear();
|
||||
intmoduleSerialStart(¶ms);
|
||||
resetAccessAuthenticationCount();
|
||||
|
||||
#if defined(INTMODULE_HEARTBEAT)
|
||||
// use backup trigger (1 ms later)
|
||||
init_intmodule_heartbeat();
|
||||
#endif
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD);
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_MULTI)
|
||||
case PROTOCOL_CHANNELS_MULTIMODULE: {
|
||||
|
||||
// serial port setup
|
||||
etx_serial_init params;
|
||||
params.baudrate = MULTIMODULE_BAUDRATE;
|
||||
params.rx_enable = true;
|
||||
params.parity = USART_Parity_Even;
|
||||
params.stop_bits = USART_StopBits_2;
|
||||
params.word_length = USART_WordLength_9b;
|
||||
|
||||
intmodulePulsesData.multi.initFrame();
|
||||
intmoduleFifo.clear();
|
||||
intmoduleSerialStart(¶ms);
|
||||
|
||||
// mixer setup
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD);
|
||||
|
||||
// reset status
|
||||
getMultiModuleStatus(INTERNAL_MODULE).failsafeChecked = false;
|
||||
getMultiModuleStatus(INTERNAL_MODULE).flags = 0;
|
||||
|
||||
#if defined(MULTI_PROTOLIST)
|
||||
TRACE("enablePulsesInternalModule(): trigger scan");
|
||||
MultiRfProtocols::instance(INTERNAL_MODULE)->triggerScan();
|
||||
TRACE("counter = %d", moduleState[INTERNAL_MODULE].counter);
|
||||
#endif
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_CRSF)
|
||||
case PROTOCOL_CHANNELS_CROSSFIRE: {
|
||||
|
||||
// serial port setup
|
||||
etx_serial_init params;
|
||||
params.baudrate = CROSSFIRE_BAUDRATE;
|
||||
params.rx_enable = true;
|
||||
|
||||
// wakeup mixer when rx buffer is quarter full (16 bytes)
|
||||
params.on_receive = intmoduleCRSF_rx;
|
||||
|
||||
intmoduleFifo.clear();
|
||||
intmoduleSerialStart(¶ms);
|
||||
|
||||
// mixer setup
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, CROSSFIRE_PERIOD);
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_PPM)
|
||||
case PROTOCOL_CHANNELS_PPM:
|
||||
intmodulePpmStart();
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, PPM_PERIOD(INTERNAL_MODULE));
|
||||
extmoduleSendNextFramePpm(
|
||||
extmodulePulsesData.ppm.pulses,
|
||||
extmodulePulsesData.ppm.ptr - extmodulePulsesData.ppm.pulses,
|
||||
GET_MODULE_PPM_DELAY(EXTERNAL_MODULE),
|
||||
GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE));
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, PPM_PERIOD(EXTERNAL_MODULE));
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS2)
|
||||
case PROTOCOL_CHANNELS_AFHDS2A: {
|
||||
|
||||
// serial port setup
|
||||
etx_serial_init params;
|
||||
params.baudrate = INTMODULE_USART_AFHDS2_BAUDRATE;
|
||||
params.rx_enable = true;
|
||||
|
||||
resetPulsesAFHDS2();
|
||||
intmoduleFifo.clear();
|
||||
intmoduleSerialStart(¶ms);
|
||||
|
||||
// mixer setup
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, AFHDS2_PERIOD);
|
||||
} break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
// internal module stopped, use default mixer period
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool setupPulsesInternalModule(uint8_t protocol)
|
||||
{
|
||||
switch (protocol) {
|
||||
#if defined(HARDWARE_INTERNAL_MODULE) && defined(PXX1) && !defined(INTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX1_PULSES:
|
||||
intmodulePulsesData.pxx.setupFrame(INTERNAL_MODULE);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(PXX1) && defined(INTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX1_SERIAL:
|
||||
intmodulePulsesData.pxx_uart.setupFrame(INTERNAL_MODULE);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(PXX2)
|
||||
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
|
||||
{
|
||||
bool result = intmodulePulsesData.pxx2.setupFrame(INTERNAL_MODULE);
|
||||
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER || moduleState[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER) {
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_TOOLS_PERIOD);
|
||||
}
|
||||
else {
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM)
|
||||
case PROTOCOL_CHANNELS_PPM:
|
||||
setupPulsesPPMInternalModule();
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_CRSF)
|
||||
case PROTOCOL_CHANNELS_CROSSFIRE:
|
||||
{
|
||||
ModuleSyncStatus& status = getModuleSyncStatus(INTERNAL_MODULE);
|
||||
if (status.isValid())
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, status.getAdjustedRefreshRate());
|
||||
else
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, CROSSFIRE_PERIOD);
|
||||
setupPulsesCrossfire(INTERNAL_MODULE);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_MULTI)
|
||||
case PROTOCOL_CHANNELS_MULTIMODULE:
|
||||
setupPulsesMultiInternalModule();
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, MULTIMODULE_PERIOD);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS2)
|
||||
case PROTOCOL_CHANNELS_AFHDS2A:
|
||||
{
|
||||
ModuleSyncStatus& status = getModuleSyncStatus(INTERNAL_MODULE);
|
||||
mixerSchedulerSetPeriod(
|
||||
INTERNAL_MODULE,
|
||||
status.isValid() ? status.getAdjustedRefreshRate() : AFHDS2_PERIOD);
|
||||
status.invalidate();
|
||||
setupPulsesAFHDS2();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void stopPulsesInternalModule()
|
||||
{
|
||||
if (moduleState[INTERNAL_MODULE].protocol != PROTOCOL_CHANNELS_UNINITIALIZED) {
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
|
||||
intmoduleStop();
|
||||
moduleState[INTERNAL_MODULE].protocol = PROTOCOL_CHANNELS_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void intmoduleSendNextFrame()
|
||||
{
|
||||
switch (moduleState[INTERNAL_MODULE].protocol) {
|
||||
#if defined(PXX2)
|
||||
case PROTOCOL_CHANNELS_PXX2_HIGHSPEED:
|
||||
intmoduleSendBuffer(intmodulePulsesData.pxx2.getData(),
|
||||
intmodulePulsesData.pxx2.getSize());
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_PPM)
|
||||
case PROTOCOL_CHANNELS_PPM:
|
||||
intmoduleSendNextFramePPM(
|
||||
intmodulePulsesData.ppm.pulses,
|
||||
intmodulePulsesData.ppm.ptr - intmodulePulsesData.ppm.pulses);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PXX1)
|
||||
#if defined(INTMODULE_USART)
|
||||
case PROTOCOL_CHANNELS_PXX1_SERIAL:
|
||||
intmoduleSendBuffer(intmodulePulsesData.pxx_uart.getData(),
|
||||
intmodulePulsesData.pxx_uart.getSize());
|
||||
break;
|
||||
#else
|
||||
case PROTOCOL_CHANNELS_PXX1_PULSES:
|
||||
intmoduleSendNextFramePxx1(intmodulePulsesData.pxx.getData(),
|
||||
intmodulePulsesData.pxx.getSize());
|
||||
extmoduleSendNextFramePxx1(extmodulePulsesData.pxx.getData(),
|
||||
extmodulePulsesData.pxx.getSize());
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS3)
|
||||
case PROTOCOL_CHANNELS_AFHDS3:
|
||||
#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO)
|
||||
extmoduleSendBuffer(extmodulePulsesData.afhds3.getData(),
|
||||
extmodulePulsesData.afhds3.getSize());
|
||||
#else
|
||||
extmoduleSendNextFrameSoftSerial(extmodulePulsesData.afhds3.getData(),
|
||||
extmodulePulsesData.afhds3.getSize(),
|
||||
false);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_MULTI)
|
||||
#if defined(SBUS) || defined(DSM2) || defined(MULTIMODULE)
|
||||
case PROTOCOL_CHANNELS_SBUS:
|
||||
extmoduleSendNextFrameSoftSerial(
|
||||
extmodulePulsesData.dsm2.pulses,
|
||||
extmodulePulsesData.dsm2.ptr - extmodulePulsesData.dsm2.pulses,
|
||||
GET_SBUS_POLARITY(EXTERNAL_MODULE));
|
||||
break;
|
||||
|
||||
case PROTOCOL_CHANNELS_DSM2_LP45:
|
||||
case PROTOCOL_CHANNELS_DSM2_DSM2:
|
||||
case PROTOCOL_CHANNELS_DSM2_DSMX:
|
||||
case PROTOCOL_CHANNELS_MULTIMODULE:
|
||||
intmoduleSendBuffer(intmodulePulsesData.multi.getData(),
|
||||
intmodulePulsesData.multi.getSize());
|
||||
extmoduleSendNextFrameSoftSerial(
|
||||
extmodulePulsesData.dsm2.pulses,
|
||||
extmodulePulsesData.dsm2.ptr - extmodulePulsesData.dsm2.pulses);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_MODULE_CRSF)
|
||||
case PROTOCOL_CHANNELS_CROSSFIRE:
|
||||
intmoduleSendBuffer(intmodulePulsesData.crossfire.pulses,
|
||||
intmodulePulsesData.crossfire.length);
|
||||
#if defined(GHOST)
|
||||
case PROTOCOL_CHANNELS_GHOST:
|
||||
sportSendBuffer(extmodulePulsesData.ghost.pulses,
|
||||
extmodulePulsesData.ghost.length);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS2)
|
||||
case PROTOCOL_CHANNELS_AFHDS2A: {
|
||||
uint8_t* data = (uint8_t*)intmodulePulsesData.flysky.pulses;
|
||||
uint16_t size = intmodulePulsesData.flysky.ptr - data;
|
||||
intmoduleSendBuffer(data, size);
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool setupPulsesInternalModule()
|
||||
{
|
||||
uint8_t protocol = getRequiredProtocol(INTERNAL_MODULE);
|
||||
|
||||
heartbeat |= (HEART_TIMER_PULSES << INTERNAL_MODULE);
|
||||
|
||||
if (moduleState[INTERNAL_MODULE].protocol != protocol) {
|
||||
intmoduleStop();
|
||||
enablePulsesInternalModule(protocol);
|
||||
moduleState[INTERNAL_MODULE].protocol = protocol;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return setupPulsesInternalModule(protocol);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_EXTERNAL_MODULE)
|
||||
void stopPulsesExternalModule()
|
||||
{
|
||||
if (moduleState[EXTERNAL_MODULE].protocol != PROTOCOL_CHANNELS_UNINITIALIZED) {
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
|
||||
extmoduleStop();
|
||||
if (moduleState[EXTERNAL_MODULE].protocol !=
|
||||
PROTOCOL_CHANNELS_UNINITIALIZED) {
|
||||
if (externalModuleDriver) {
|
||||
externalModuleDriver->deinit(externalModuleContext);
|
||||
externalModuleDriver = nullptr;
|
||||
externalModuleContext = nullptr;
|
||||
} else {
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
|
||||
extmoduleStop();
|
||||
}
|
||||
moduleState[EXTERNAL_MODULE].protocol = PROTOCOL_CHANNELS_NONE;
|
||||
}
|
||||
}
|
||||
@@ -781,7 +735,6 @@ bool setupPulsesExternalModule()
|
||||
heartbeat |= (HEART_TIMER_PULSES << EXTERNAL_MODULE);
|
||||
|
||||
if (moduleState[EXTERNAL_MODULE].protocol != protocol) {
|
||||
extmoduleStop();
|
||||
enablePulsesExternalModule(protocol);
|
||||
moduleState[EXTERNAL_MODULE].protocol = protocol;
|
||||
return false;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "afhds2.h"
|
||||
#include "modules_helpers.h"
|
||||
#include "ff.h"
|
||||
#include "hal/module_driver.h"
|
||||
|
||||
|
||||
#if defined(DSM2)
|
||||
@@ -230,6 +231,7 @@ void intmoduleSendNextFrame();
|
||||
#if defined(HARDWARE_EXTERNAL_MODULE)
|
||||
bool setupPulsesExternalModule();
|
||||
void stopPulsesExternalModule();
|
||||
void extmoduleSendNextFrame();
|
||||
#endif
|
||||
void setupPulsesDSM2();
|
||||
void setupPulsesCrossfire(uint8_t idx);
|
||||
@@ -276,25 +278,6 @@ inline void startPulses()
|
||||
#endif
|
||||
}
|
||||
|
||||
enum ChannelsProtocols {
|
||||
PROTOCOL_CHANNELS_UNINITIALIZED,
|
||||
PROTOCOL_CHANNELS_NONE,
|
||||
PROTOCOL_CHANNELS_PPM,
|
||||
PROTOCOL_CHANNELS_PXX1_PULSES,
|
||||
PROTOCOL_CHANNELS_PXX1_SERIAL,
|
||||
PROTOCOL_CHANNELS_DSM2_LP45,
|
||||
PROTOCOL_CHANNELS_DSM2_DSM2,
|
||||
PROTOCOL_CHANNELS_DSM2_DSMX,
|
||||
PROTOCOL_CHANNELS_CROSSFIRE,
|
||||
PROTOCOL_CHANNELS_MULTIMODULE,
|
||||
PROTOCOL_CHANNELS_SBUS,
|
||||
PROTOCOL_CHANNELS_PXX2_LOWSPEED,
|
||||
PROTOCOL_CHANNELS_PXX2_HIGHSPEED,
|
||||
PROTOCOL_CHANNELS_AFHDS2A,
|
||||
PROTOCOL_CHANNELS_AFHDS3,
|
||||
PROTOCOL_CHANNELS_GHOST
|
||||
};
|
||||
|
||||
inline void stopPulses()
|
||||
{
|
||||
s_pulses_paused = true;
|
||||
|
||||
@@ -107,25 +107,22 @@ class SerialPxxBitTransport: public DataBuffer<uint8_t, 64> {
|
||||
|
||||
class PwmPxxBitTransport: public PulsesBuffer<pulse_duration_t, 200> {
|
||||
protected:
|
||||
uint16_t rest;
|
||||
|
||||
void initFrame(uint32_t period)
|
||||
{
|
||||
initBuffer();
|
||||
rest = period * 2000; // 0.5uS (2Mhz)
|
||||
}
|
||||
|
||||
void addPart(uint8_t value)
|
||||
{
|
||||
pulse_duration_t duration = value ? 47 : 31;
|
||||
*ptr++ = duration;
|
||||
rest -= duration + 1;
|
||||
}
|
||||
|
||||
void addTail()
|
||||
{
|
||||
// rest min value is 18000 - 200 * 48 = 8400 (4.2ms)
|
||||
*(ptr - 1) = 60000;
|
||||
*(ptr - 1) = 255;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "opentx.h"
|
||||
#include "pulses/pxx1.h"
|
||||
#include "mixer_scheduler.h"
|
||||
#include "heartbeat_driver.h"
|
||||
|
||||
template <class PxxTransport>
|
||||
void Pxx1Pulses<PxxTransport>::addFlag1(uint8_t module, uint8_t sendFailsafe)
|
||||
@@ -219,3 +221,122 @@ void Pxx1Pulses<PxxTransport>::setupFrame(uint8_t module)
|
||||
template class Pxx1Pulses<StandardPxx1Transport<PwmPxxBitTransport> >;
|
||||
template class Pxx1Pulses<StandardPxx1Transport<SerialPxxBitTransport> >;
|
||||
template class Pxx1Pulses<UartPxx1Transport>;
|
||||
|
||||
#if defined(INTMODULE_USART)
|
||||
#include "intmodule_serial_driver.h"
|
||||
|
||||
static const etx_serial_init pxx1SerialInit = {
|
||||
.baudrate = INTMODULE_PXX1_SERIAL_BAUDRATE,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = false,
|
||||
.on_receive = intmoduleFifoReceive,
|
||||
.on_error = intmoduleFifoError,
|
||||
};
|
||||
|
||||
static void* pxx1InitInternal(uint8_t module)
|
||||
{
|
||||
void* uart_ctx = IntmoduleSerialDriver.init(&pxx1SerialInit);
|
||||
|
||||
#if defined(INTMODULE_HEARTBEAT)
|
||||
init_intmodule_heartbeat();
|
||||
#endif
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD);
|
||||
INTERNAL_MODULE_ON();
|
||||
|
||||
return uart_ctx;
|
||||
}
|
||||
|
||||
static void pxx1DeInitInternal(void* context)
|
||||
{
|
||||
INTERNAL_MODULE_OFF();
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
|
||||
#if defined(INTMODULE_HEARTBEAT)
|
||||
stop_intmodule_heartbeat();
|
||||
#endif
|
||||
IntmoduleSerialDriver.deinit(context);
|
||||
}
|
||||
|
||||
static void pxx1SetupPulsesInternal(void* context, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
(void)context;
|
||||
|
||||
// TODO:
|
||||
(void)channels;
|
||||
(void)nChannels;
|
||||
intmodulePulsesData.pxx_uart.setupFrame(INTERNAL_MODULE);
|
||||
}
|
||||
|
||||
static void pxx1SendPulsesInternal(void* context)
|
||||
{
|
||||
IntmoduleSerialDriver.sendBuffer(context, intmodulePulsesData.pxx_uart.getData(),
|
||||
intmodulePulsesData.pxx_uart.getSize());
|
||||
}
|
||||
|
||||
const etx_module_driver_t Pxx1InternalSerialDriver = {
|
||||
.protocol = PROTOCOL_CHANNELS_PXX1_SERIAL,
|
||||
.init = pxx1InitInternal,
|
||||
.deinit = pxx1DeInitInternal,
|
||||
.setupPulses = pxx1SetupPulsesInternal,
|
||||
.sendPulses = pxx1SendPulsesInternal,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(EXTMODULE_USART) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
|
||||
#include "extmodule_serial_driver.h"
|
||||
|
||||
static const etx_serial_init pxx1ExtSerialInit = {
|
||||
.baudrate = EXTMODULE_PXX1_SERIAL_BAUDRATE,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = false,
|
||||
.on_receive = extmoduleFifoReceive,
|
||||
.on_error = extmoduleFifoError,
|
||||
};
|
||||
|
||||
static void* pxx1InitExternal(uint8_t module)
|
||||
{
|
||||
void* uart_ctx = ExtmoduleSerialDriver.init(&pxx1ExtSerialInit);
|
||||
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, EXTMODULE_PXX1_SERIAL_PERIOD);
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
return uart_ctx;
|
||||
}
|
||||
|
||||
static void pxx1DeInitExternal(void* context)
|
||||
{
|
||||
EXTERNAL_MODULE_OFF();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
|
||||
ExtmoduleSerialDriver.deinit(context);
|
||||
}
|
||||
|
||||
static void pxx1SetupPulsesExternal(void* context, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
(void)context;
|
||||
|
||||
// TODO:
|
||||
(void)channels;
|
||||
(void)nChannels;
|
||||
|
||||
extmodulePulsesData.pxx_uart.setupFrame(EXTERNAL_MODULE);
|
||||
}
|
||||
|
||||
static void pxx1SendPulsesExternal(void* context)
|
||||
{
|
||||
ExtmoduleSerialDriver.sendBuffer(context, extmodulePulsesData.pxx_uart.getData(),
|
||||
extmodulePulsesData.pxx_uart.getSize());
|
||||
}
|
||||
|
||||
const etx_module_driver_t Pxx1ExternalSerialDriver = {
|
||||
.protocol = PROTOCOL_CHANNELS_PXX1_SERIAL,
|
||||
.init = pxx1InitExternal,
|
||||
.deinit = pxx1DeInitExternal,
|
||||
.setupPulses = pxx1SetupPulsesExternal,
|
||||
.sendPulses = pxx1SendPulsesExternal,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+9
-13
@@ -25,19 +25,7 @@
|
||||
#include "pxx.h"
|
||||
#include "crc.h"
|
||||
|
||||
#if defined(INTMODULE_HEARTBEAT_GPIO)
|
||||
struct HeartbeatCapture {
|
||||
#if !defined(INTMODULE_USART)
|
||||
uint32_t timestamp;
|
||||
#endif
|
||||
#if defined(DEBUG_LATENCY)
|
||||
uint32_t count;
|
||||
#endif
|
||||
uint8_t valid;
|
||||
};
|
||||
|
||||
extern volatile HeartbeatCapture heartbeatCapture;
|
||||
#endif
|
||||
#include "hal/module_driver.h"
|
||||
|
||||
class Pxx1CrcMixin {
|
||||
protected:
|
||||
@@ -180,4 +168,12 @@ typedef Pxx1Pulses<UartPxx1Transport> UartPxx1Pulses;
|
||||
typedef Pxx1Pulses<StandardPxx1Transport<PwmPxxBitTransport>> PwmPxx1Pulses;
|
||||
typedef Pxx1Pulses<StandardPxx1Transport<SerialPxxBitTransport>> SerialPxx1Pulses;
|
||||
|
||||
#if defined(INTMODULE_USART)
|
||||
extern const etx_module_driver_t Pxx1InternalSerialDriver;
|
||||
#endif
|
||||
|
||||
#if defined(EXTMODULE_USART)
|
||||
extern const etx_module_driver_t Pxx1ExternalSerialDriver;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+166
-16
@@ -24,6 +24,22 @@
|
||||
#include "pulses/pxx2.h"
|
||||
#include "io/frsky_firmware_update.h"
|
||||
#include "libopenui/src/libopenui_file.h"
|
||||
#include "mixer_scheduler.h"
|
||||
#include "heartbeat_driver.h"
|
||||
|
||||
#if defined(INTMODULE_USART)
|
||||
#include "intmodule_serial_driver.h"
|
||||
|
||||
const etx_serial_init pxx2SerialInitParams = {
|
||||
.baudrate = PXX2_HIGHSPEED_BAUDRATE,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = true,
|
||||
.on_receive = intmoduleFifoReceive,
|
||||
.on_error = intmoduleFifoError,
|
||||
};
|
||||
#endif
|
||||
|
||||
bool isPXX2PowerAvailable(const PXX2HardwareInformation& info, int value)
|
||||
{
|
||||
@@ -110,7 +126,7 @@ void Pxx2Pulses::addPulsesValues(uint16_t low, uint16_t high)
|
||||
Pxx2Transport::addByte(high >> 4u); // High byte of channel
|
||||
}
|
||||
|
||||
void Pxx2Pulses::addChannels(uint8_t module)
|
||||
void Pxx2Pulses::addChannels(uint8_t module, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
uint16_t pulseValue = 0;
|
||||
uint16_t pulseValueLow = 0;
|
||||
@@ -119,7 +135,7 @@ void Pxx2Pulses::addChannels(uint8_t module)
|
||||
uint8_t count = sentModuleChannels(module);
|
||||
|
||||
for (int8_t i = 0; i < count; i++, channel++) {
|
||||
int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
|
||||
int value = channels[i] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
|
||||
pulseValue = limit(1, (value * 512 / 682) + 1024, 2046);
|
||||
#if defined(DEBUG_LATENCY_RF_ONLY)
|
||||
if (latencyToggleSwitch)
|
||||
@@ -169,7 +185,7 @@ void Pxx2Pulses::addFailsafe(uint8_t module)
|
||||
}
|
||||
}
|
||||
|
||||
void Pxx2Pulses::setupChannelsFrame(uint8_t module)
|
||||
void Pxx2Pulses::setupChannelsFrame(uint8_t module, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_CHANNELS);
|
||||
|
||||
@@ -183,7 +199,7 @@ void Pxx2Pulses::setupChannelsFrame(uint8_t module)
|
||||
if (flag0 & PXX2_CHANNELS_FLAG0_FAILSAFE)
|
||||
addFailsafe(module);
|
||||
else
|
||||
addChannels(module);
|
||||
addChannels(module, channels, nChannels);
|
||||
}
|
||||
|
||||
void Pxx2Pulses::setupTelemetryFrame(uint8_t module)
|
||||
@@ -195,7 +211,7 @@ void Pxx2Pulses::setupTelemetryFrame(uint8_t module)
|
||||
}
|
||||
}
|
||||
|
||||
void Pxx2Pulses::setupHardwareInfoFrame(uint8_t module)
|
||||
void Pxx2Pulses::setupHardwareInfoFrame(uint8_t module, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
ModuleInformation * destination = moduleState[module].moduleInformation;
|
||||
|
||||
@@ -208,12 +224,12 @@ void Pxx2Pulses::setupHardwareInfoFrame(uint8_t module)
|
||||
}
|
||||
else {
|
||||
moduleState[module].mode = MODULE_MODE_NORMAL;
|
||||
setupChannelsFrame(module);
|
||||
setupChannelsFrame(module, channels, nChannels);
|
||||
}
|
||||
}
|
||||
else {
|
||||
destination->timeout--;
|
||||
setupChannelsFrame(module);
|
||||
setupChannelsFrame(module, channels, nChannels);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +252,7 @@ void Pxx2Pulses::setupRegisterFrame(uint8_t module)
|
||||
}
|
||||
}
|
||||
|
||||
void Pxx2Pulses::setupModuleSettingsFrame(uint8_t module)
|
||||
void Pxx2Pulses::setupModuleSettingsFrame(uint8_t module, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
ModuleSettings * destination = moduleState[module].moduleSettings;
|
||||
|
||||
@@ -256,11 +272,11 @@ void Pxx2Pulses::setupModuleSettingsFrame(uint8_t module)
|
||||
destination->timeout = get_tmr10ms() + 200/*next try in 2s*/;
|
||||
}
|
||||
else {
|
||||
setupChannelsFrame(module);
|
||||
setupChannelsFrame(module, channels, nChannels);
|
||||
}
|
||||
}
|
||||
|
||||
void Pxx2Pulses::setupReceiverSettingsFrame(uint8_t module)
|
||||
void Pxx2Pulses::setupReceiverSettingsFrame(uint8_t module, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
if (get_tmr10ms() > reusableBuffer.hardwareAndSettings.receiverSettings.timeout) {
|
||||
addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_RX_SETTINGS);
|
||||
@@ -291,7 +307,7 @@ void Pxx2Pulses::setupReceiverSettingsFrame(uint8_t module)
|
||||
reusableBuffer.hardwareAndSettings.receiverSettings.timeout = get_tmr10ms() + 200/*next try in 2s*/;
|
||||
}
|
||||
else {
|
||||
setupChannelsFrame(module);
|
||||
setupChannelsFrame(module, channels, nChannels);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,7 +458,7 @@ void Pxx2Pulses::setupAuthenticationFrame(uint8_t module, uint8_t mode, const ui
|
||||
endFrame();
|
||||
}
|
||||
|
||||
bool Pxx2Pulses::setupFrame(uint8_t module)
|
||||
bool Pxx2Pulses::setupFrame(uint8_t module, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
if (moduleState[module].mode == MODULE_MODE_OTA_UPDATE)
|
||||
return false;
|
||||
@@ -456,13 +472,13 @@ bool Pxx2Pulses::setupFrame(uint8_t module)
|
||||
|
||||
switch (moduleState[module].mode) {
|
||||
case MODULE_MODE_GET_HARDWARE_INFO:
|
||||
setupHardwareInfoFrame(module);
|
||||
setupHardwareInfoFrame(module, channels, nChannels);
|
||||
break;
|
||||
case MODULE_MODE_MODULE_SETTINGS:
|
||||
setupModuleSettingsFrame(module);
|
||||
setupModuleSettingsFrame(module, channels, nChannels);
|
||||
break;
|
||||
case MODULE_MODE_RECEIVER_SETTINGS:
|
||||
setupReceiverSettingsFrame(module);
|
||||
setupReceiverSettingsFrame(module, channels, nChannels);
|
||||
break;
|
||||
case MODULE_MODE_REGISTER:
|
||||
setupRegisterFrame(module);
|
||||
@@ -495,7 +511,7 @@ bool Pxx2Pulses::setupFrame(uint8_t module)
|
||||
outputTelemetryBuffer.reset();
|
||||
}
|
||||
else {
|
||||
setupChannelsFrame(module);
|
||||
setupChannelsFrame(module, channels, nChannels);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -630,3 +646,137 @@ void Pxx2OtaUpdate::flashFirmware(const char * filename, ProgressHandler progres
|
||||
|
||||
resumePulses();
|
||||
}
|
||||
|
||||
static void* pxx2InitInternal(uint8_t moduleType)
|
||||
{
|
||||
intmoduleFifo.clear();
|
||||
void* uart_ctx = IntmoduleSerialDriver.init(&pxx2SerialInitParams);
|
||||
resetAccessAuthenticationCount();
|
||||
|
||||
#if defined(INTMODULE_HEARTBEAT)
|
||||
// use backup trigger (1 ms later)
|
||||
init_intmodule_heartbeat();
|
||||
#endif
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD);
|
||||
INTERNAL_MODULE_ON();
|
||||
|
||||
return uart_ctx;
|
||||
}
|
||||
|
||||
static void pxx2DeInitInternal(void* context)
|
||||
{
|
||||
INTERNAL_MODULE_OFF();
|
||||
IntmoduleSerialDriver.deinit(context);
|
||||
#if defined(INTMODULE_HEARTBEAT)
|
||||
stop_intmodule_heartbeat();
|
||||
#endif
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, 0);
|
||||
}
|
||||
|
||||
static bool pxx2InternalSendNextFrame = true;
|
||||
|
||||
static void pxx2SetupPulsesInternal(void* context, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
(void)context;
|
||||
|
||||
pxx2InternalSendNextFrame =
|
||||
intmodulePulsesData.pxx2.setupFrame(INTERNAL_MODULE, channels, nChannels);
|
||||
|
||||
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER ||
|
||||
moduleState[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER) {
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_TOOLS_PERIOD);
|
||||
} else {
|
||||
mixerSchedulerSetPeriod(INTERNAL_MODULE, PXX2_PERIOD);
|
||||
}
|
||||
}
|
||||
|
||||
static void pxx2SendPulsesInternal(void* context)
|
||||
{
|
||||
if (pxx2InternalSendNextFrame) {
|
||||
IntmoduleSerialDriver.sendBuffer(context, intmodulePulsesData.pxx2.getData(),
|
||||
intmodulePulsesData.pxx2.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
#include "hal/module_driver.h"
|
||||
|
||||
const etx_module_driver_t Pxx2InternalDriver = {
|
||||
.protocol = PROTOCOL_CHANNELS_PXX2_HIGHSPEED,
|
||||
.init = pxx2InitInternal,
|
||||
.deinit = pxx2DeInitInternal,
|
||||
.setupPulses = pxx2SetupPulsesInternal,
|
||||
.sendPulses = pxx2SendPulsesInternal,
|
||||
};
|
||||
|
||||
#if defined(EXTMODULE_USART)
|
||||
#include "extmodule_serial_driver.h"
|
||||
|
||||
static const etx_serial_init pxx2ExtSerialInitParams = {
|
||||
.baudrate = 0,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = true,
|
||||
.on_receive = extmoduleFifoReceive,
|
||||
.on_error = extmoduleFifoError,
|
||||
};
|
||||
|
||||
static void* pxx2InitLowSpeed(uint8_t module)
|
||||
{
|
||||
etx_serial_init params(pxx2ExtSerialInitParams);
|
||||
params.baudrate = PXX2_LOWSPEED_BAUDRATE;
|
||||
ExtmoduleSerialDriver.init(¶ms);
|
||||
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX2_NO_HEARTBEAT_PERIOD);
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void* pxx2InitExternal(uint8_t module)
|
||||
{
|
||||
etx_serial_init params(pxx2ExtSerialInitParams);
|
||||
params.baudrate = PXX2_HIGHSPEED_BAUDRATE;
|
||||
void* uart_ctx = ExtmoduleSerialDriver.init(¶ms);
|
||||
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, PXX2_NO_HEARTBEAT_PERIOD);
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
return uart_ctx;
|
||||
}
|
||||
|
||||
static void pxx2DeInitExternal(void* context)
|
||||
{
|
||||
EXTERNAL_MODULE_OFF();
|
||||
mixerSchedulerSetPeriod(EXTERNAL_MODULE, 0);
|
||||
ExtmoduleSerialDriver.deinit(context);
|
||||
}
|
||||
|
||||
static void pxx2SetupPulsesExternal(void* context, int16_t* channels, uint8_t nChannels)
|
||||
{
|
||||
(void)context;
|
||||
extmodulePulsesData.pxx2.setupFrame(EXTERNAL_MODULE, channels, nChannels);
|
||||
}
|
||||
|
||||
static void pxx2SendPulsesExternal(void* context)
|
||||
{
|
||||
ExtmoduleSerialDriver.sendBuffer(context, extmodulePulsesData.pxx2.getData(),
|
||||
extmodulePulsesData.pxx2.getSize());
|
||||
}
|
||||
|
||||
const etx_module_driver_t Pxx2ExternalDriver = {
|
||||
.protocol = PROTOCOL_CHANNELS_PXX2_HIGHSPEED,
|
||||
.init = pxx2InitExternal,
|
||||
.deinit = pxx2DeInitExternal,
|
||||
.setupPulses = pxx2SetupPulsesExternal,
|
||||
.sendPulses = pxx2SendPulsesExternal,
|
||||
};
|
||||
|
||||
const etx_module_driver_t Pxx2LowSpeedExternalDriver = {
|
||||
.protocol = PROTOCOL_CHANNELS_PXX2_LOWSPEED,
|
||||
.init = pxx2InitLowSpeed,
|
||||
.deinit = pxx2DeInitExternal,
|
||||
.setupPulses = pxx2SetupPulsesExternal,
|
||||
.sendPulses = pxx2SendPulsesExternal,
|
||||
};
|
||||
#endif
|
||||
|
||||
+15
-6
@@ -27,6 +27,9 @@
|
||||
#include "popups.h"
|
||||
#include "./pxx.h"
|
||||
|
||||
#include "hal/serial_driver.h"
|
||||
#include "hal/module_driver.h"
|
||||
|
||||
#define PXX2_TYPE_C_MODULE 0x01
|
||||
#define PXX2_TYPE_ID_REGISTER 0x01
|
||||
#define PXX2_TYPE_ID_BIND 0x02
|
||||
@@ -465,11 +468,11 @@ class Pxx2Pulses: public Pxx2Transport {
|
||||
friend class Pxx2OtaUpdate;
|
||||
|
||||
public:
|
||||
bool setupFrame(uint8_t module);
|
||||
bool setupFrame(uint8_t module, int16_t* channels, uint8_t nChannels);
|
||||
void setupAuthenticationFrame(uint8_t module, uint8_t mode, const uint8_t * outputMessage);
|
||||
|
||||
protected:
|
||||
void setupHardwareInfoFrame(uint8_t module);
|
||||
void setupHardwareInfoFrame(uint8_t module, int16_t* channels, uint8_t nChannels);
|
||||
|
||||
void setupRegisterFrame(uint8_t module);
|
||||
|
||||
@@ -481,11 +484,11 @@ class Pxx2Pulses: public Pxx2Transport {
|
||||
|
||||
void setupShareMode(uint8_t module);
|
||||
|
||||
void setupModuleSettingsFrame(uint8_t module);
|
||||
void setupModuleSettingsFrame(uint8_t module, int16_t* channels, uint8_t nChannels);
|
||||
|
||||
void setupReceiverSettingsFrame(uint8_t module);
|
||||
void setupReceiverSettingsFrame(uint8_t module, int16_t* channels, uint8_t nChannels);
|
||||
|
||||
void setupChannelsFrame(uint8_t module);
|
||||
void setupChannelsFrame(uint8_t module, int16_t* channels, uint8_t nChannels);
|
||||
|
||||
void setupTelemetryFrame(uint8_t module);
|
||||
|
||||
@@ -517,7 +520,7 @@ class Pxx2Pulses: public Pxx2Transport {
|
||||
|
||||
void addPulsesValues(uint16_t low, uint16_t high);
|
||||
|
||||
void addChannels(uint8_t module);
|
||||
void addChannels(uint8_t module, int16_t* channels, uint8_t nChannels);
|
||||
|
||||
void addFailsafe(uint8_t module);
|
||||
|
||||
@@ -575,4 +578,10 @@ class Pxx2OtaUpdate {
|
||||
const char * nextStep(uint8_t step, const char * rxName, uint32_t address, const uint8_t * buffer);
|
||||
};
|
||||
|
||||
extern const etx_serial_init pxx2SerialInitParams;
|
||||
|
||||
extern const etx_module_driver_t Pxx2InternalDriver;
|
||||
extern const etx_module_driver_t Pxx2ExternalDriver;
|
||||
extern const etx_module_driver_t Pxx2LowSpeedExternalDriver;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -92,9 +92,9 @@ inline int getChannelValue(uint8_t port, int channel)
|
||||
static void sbusFlush()
|
||||
{
|
||||
if (extmodulePulsesData.dsm2.index & 1)
|
||||
*extmodulePulsesData.dsm2.ptr++ = 60000;
|
||||
*extmodulePulsesData.dsm2.ptr++ = 255;
|
||||
else
|
||||
*(extmodulePulsesData.dsm2.ptr - 1) = 60000;
|
||||
*(extmodulePulsesData.dsm2.ptr - 1) = 255;
|
||||
}
|
||||
|
||||
void setupPulsesSbus()
|
||||
|
||||
+54
-17
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "opentx.h"
|
||||
#include "sbus.h"
|
||||
#include "timers_driver.h"
|
||||
|
||||
#define SBUS_FRAME_GAP_DELAY 1000 // 500uS
|
||||
|
||||
@@ -35,14 +36,45 @@
|
||||
|
||||
#define SBUS_CH_CENTER 0x3E0
|
||||
|
||||
static int (*_sbusAuxGetByte)(void*, uint8_t*) = nullptr;
|
||||
static void* _sbusAuxGetByteCtx = nullptr;
|
||||
|
||||
void sbusSetAuxGetByte(void* ctx, int (*fct)(void*, uint8_t*))
|
||||
{
|
||||
_sbusAuxGetByte = nullptr;
|
||||
_sbusAuxGetByteCtx = ctx;
|
||||
_sbusAuxGetByte = fct;
|
||||
}
|
||||
|
||||
int sbusAuxGetByte(uint8_t* byte)
|
||||
{
|
||||
auto _getByte = _sbusAuxGetByte;
|
||||
auto _ctx = _sbusAuxGetByteCtx;
|
||||
|
||||
if (_getByte) {
|
||||
return _getByte(_ctx, byte);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int (*sbusGetByte)(uint8_t*) = nullptr;
|
||||
|
||||
void sbusSetGetByte(int (*fct)(uint8_t*))
|
||||
{
|
||||
sbusGetByte = fct;
|
||||
}
|
||||
|
||||
// Range for pulses (ppm input) is [-512:+512]
|
||||
void processSbusFrame(uint8_t * sbus, int16_t * pulses, uint32_t size)
|
||||
{
|
||||
if (size != SBUS_FRAME_SIZE || sbus[0] != SBUS_START_BYTE || sbus[SBUS_FRAME_SIZE-1] != SBUS_END_BYTE) {
|
||||
return; // not a valid SBUS frame
|
||||
if (size != SBUS_FRAME_SIZE || sbus[0] != SBUS_START_BYTE ||
|
||||
sbus[SBUS_FRAME_SIZE - 1] != SBUS_END_BYTE) {
|
||||
return; // not a valid SBUS frame
|
||||
}
|
||||
if ((sbus[SBUS_FLAGS_IDX] & (1<<SBUS_FAILSAFE_BIT)) || (sbus[SBUS_FLAGS_IDX] & (1<<SBUS_FRAMELOST_BIT))) {
|
||||
return; // SBUS invalid frame or failsafe mode
|
||||
if ((sbus[SBUS_FLAGS_IDX] & (1 << SBUS_FAILSAFE_BIT)) ||
|
||||
(sbus[SBUS_FLAGS_IDX] & (1 << SBUS_FRAMELOST_BIT))) {
|
||||
return; // SBUS invalid frame or failsafe mode
|
||||
}
|
||||
|
||||
sbus++; // skip start byte
|
||||
@@ -64,31 +96,36 @@ void processSbusFrame(uint8_t * sbus, int16_t * pulses, uint32_t size)
|
||||
|
||||
void processSbusInput()
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
uint8_t rxchar;
|
||||
uint32_t active = 0;
|
||||
|
||||
// TODO: place this outside of the function
|
||||
static uint8_t SbusIndex = 0;
|
||||
static uint16_t SbusTimer;
|
||||
static uint8_t SbusFrame[SBUS_FRAME_SIZE];
|
||||
|
||||
while (sbusGetByte(&rxchar)) {
|
||||
uint32_t active = 0;
|
||||
|
||||
// Drain input first (if existing)
|
||||
uint8_t rxchar;
|
||||
auto _getByte = sbusGetByte;
|
||||
while (_getByte && (_getByte(&rxchar) > 0)) {
|
||||
active = 1;
|
||||
if (SbusIndex > SBUS_FRAME_SIZE-1) {
|
||||
SbusIndex = SBUS_FRAME_SIZE-1;
|
||||
if (SbusIndex > SBUS_FRAME_SIZE - 1) {
|
||||
SbusIndex = SBUS_FRAME_SIZE - 1;
|
||||
}
|
||||
SbusFrame[SbusIndex++] = rxchar;
|
||||
}
|
||||
|
||||
// Data has been received
|
||||
if (active) {
|
||||
SbusTimer = getTmr2MHz();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (SbusIndex) {
|
||||
if ((uint16_t) (getTmr2MHz() - SbusTimer) > SBUS_FRAME_GAP_DELAY) {
|
||||
processSbusFrame(SbusFrame, ppmInput, SbusIndex);
|
||||
SbusIndex = 0;
|
||||
}
|
||||
|
||||
// Check if end-of-frame is detected
|
||||
if (SbusIndex) {
|
||||
if ((uint16_t)(getTmr2MHz() - SbusTimer) > SBUS_FRAME_GAP_DELAY) {
|
||||
processSbusFrame(SbusFrame, ppmInput, SbusIndex);
|
||||
SbusIndex = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -25,6 +25,17 @@
|
||||
#define SBUS_BAUDRATE 100000
|
||||
#define SBUS_FRAME_SIZE 25
|
||||
|
||||
// Setup SBUS AUX serial input
|
||||
void sbusSetAuxGetByte(void* ctx, int (*fct)(void*, uint8_t*));
|
||||
|
||||
// SBUS AUX serial getter:
|
||||
// if set, it will fetch data from the handler set
|
||||
// with sbusSetAuxGetByte()
|
||||
int sbusAuxGetByte(uint8_t* byte);
|
||||
|
||||
// Setup general SBUS input source
|
||||
void sbusSetGetByte(int (*fct)(uint8_t*));
|
||||
|
||||
void processSbusInput();
|
||||
|
||||
#endif // _SBUS_H_
|
||||
|
||||
+327
-19
@@ -23,42 +23,350 @@
|
||||
#include "serial.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "aux_serial_driver.h"
|
||||
#include "hal/serial_port.h"
|
||||
//#include "cli.h"
|
||||
|
||||
#define PRINTF_BUFFER_SIZE 128
|
||||
|
||||
void serialPutc(char c) {
|
||||
#if !defined(BOOT) && defined(USB_SERIAL)
|
||||
if (getSelectedUsbMode() == USB_SERIAL_MODE)
|
||||
usbSerialPutc(c);
|
||||
#endif
|
||||
#if defined(AUX_SERIAL)
|
||||
if (auxSerialTracesEnabled())
|
||||
auxSerialPutc(c);
|
||||
#endif
|
||||
#if defined(AUX2_SERIAL)
|
||||
if (aux2SerialTracesEnabled())
|
||||
aux2SerialPutc(c);
|
||||
#endif
|
||||
static void (*dbg_serial_putc)(void*, uint8_t) = nullptr;
|
||||
static void* dbg_serial_ctx = nullptr;
|
||||
|
||||
void (*dbgSerialGetSendCb())(void*, uint8_t)
|
||||
{
|
||||
return dbg_serial_putc;
|
||||
}
|
||||
|
||||
void serialPrintf(const char * format, ...)
|
||||
void* dbgSerialGetSendCbCtx()
|
||||
{
|
||||
return dbg_serial_ctx;
|
||||
}
|
||||
|
||||
void dbgSerialSetSendCb(void* ctx, void (*cb)(void*, uint8_t))
|
||||
{
|
||||
dbg_serial_putc = nullptr;
|
||||
dbg_serial_ctx = ctx;
|
||||
dbg_serial_putc = cb;
|
||||
}
|
||||
|
||||
extern "C" void dbgSerialPutc(char c)
|
||||
{
|
||||
auto _putc = dbg_serial_putc;
|
||||
auto _ctx = dbg_serial_ctx;
|
||||
if (_putc) _putc(_ctx, c);
|
||||
}
|
||||
|
||||
extern "C" void dbgSerialPrintf(const char * format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
char tmp[PRINTF_BUFFER_SIZE+1];
|
||||
|
||||
// no need to do anything if we don't have an output
|
||||
if (!dbg_serial_putc) return;
|
||||
|
||||
va_start(arglist, format);
|
||||
vsnprintf(tmp, PRINTF_BUFFER_SIZE, format, arglist);
|
||||
tmp[PRINTF_BUFFER_SIZE] = '\0';
|
||||
va_end(arglist);
|
||||
|
||||
const char *t = tmp;
|
||||
while (*t) {
|
||||
serialPutc(*t++);
|
||||
while (*t && dbg_serial_putc) {
|
||||
dbg_serial_putc(dbg_serial_ctx, *t++);
|
||||
}
|
||||
}
|
||||
|
||||
void serialCrlf()
|
||||
extern "C" void dbgSerialCrlf()
|
||||
{
|
||||
serialPutc('\r');
|
||||
serialPutc('\n');
|
||||
dbgSerialPutc('\r');
|
||||
dbgSerialPutc('\n');
|
||||
}
|
||||
|
||||
int8_t getSerialPortMode(uint8_t port_nr)
|
||||
{
|
||||
#if !defined(BOOT)
|
||||
if (port_nr < MAX_SERIAL_PORTS) {
|
||||
auto cfg = g_eeGeneral.serialPort;
|
||||
cfg >>= port_nr * 4; // 4 bits per port
|
||||
return cfg & 0xF;
|
||||
}
|
||||
#endif
|
||||
|
||||
return UART_MODE_NONE;
|
||||
}
|
||||
|
||||
struct SerialPortState
|
||||
{
|
||||
uint8_t mode;
|
||||
const etx_serial_port_t* port;
|
||||
void* usart_ctx;
|
||||
};
|
||||
|
||||
static SerialPortState serialPortStates[MAX_SERIAL_PORTS];
|
||||
|
||||
static SerialPortState* getSerialPortState(uint8_t port_nr)
|
||||
{
|
||||
if (port_nr >= MAX_SERIAL_PORTS) return nullptr;
|
||||
return &serialPortStates[port_nr];
|
||||
}
|
||||
|
||||
// TODO: replace serialSetupCallBacks & serialSetupPort
|
||||
// with usage based handlers.
|
||||
//
|
||||
static void serialSetCallBacks(int mode, void* ctx, const etx_serial_port_t* port)
|
||||
{
|
||||
void (*sendByte)(void*, uint8_t) = nullptr;
|
||||
int (*getByte)(void*, uint8_t*) = nullptr;
|
||||
void (*setRxCb)(void*, void (*)(uint8_t*, uint32_t)) = nullptr;
|
||||
|
||||
const etx_serial_driver_t* drv = nullptr;
|
||||
if (port) {
|
||||
drv = port->uart;
|
||||
if (drv) {
|
||||
sendByte = drv->sendByte;
|
||||
getByte = drv->getByte;
|
||||
setRxCb = drv->setReceiveCb;
|
||||
}
|
||||
}
|
||||
|
||||
// prevent compiler warnings
|
||||
(void)sendByte;
|
||||
(void)getByte;
|
||||
(void)setRxCb;
|
||||
|
||||
switch(mode) {
|
||||
#if defined(DEBUG)
|
||||
case UART_MODE_DEBUG:
|
||||
// TODO: should we handle 2 outputs?
|
||||
dbgSerialSetSendCb(ctx, sendByte);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !defined(BOOT)
|
||||
#if defined(LUA)
|
||||
case UART_MODE_LUA:
|
||||
luaSetSendCb(ctx, sendByte);
|
||||
if (getByte) {
|
||||
luaSetGetSerialByte(ctx, getByte);
|
||||
} else if (setRxCb) {
|
||||
luaAllocRxFifo();
|
||||
setRxCb(ctx, luaReceiveData);
|
||||
} else {
|
||||
luaFreeRxFifo();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(SBUS_TRAINER)
|
||||
case UART_MODE_SBUS_TRAINER:
|
||||
sbusSetAuxGetByte(ctx, getByte);
|
||||
// TODO: setRxCb (see MODE_LUA)
|
||||
break;
|
||||
#endif
|
||||
|
||||
case UART_MODE_TELEMETRY:
|
||||
telemetrySetGetByte(ctx, getByte);
|
||||
// TODO: setRxCb (see MODE_LUA)
|
||||
// de we really need telemetry
|
||||
// input over USB VCP?
|
||||
break;
|
||||
|
||||
case UART_MODE_TELEMETRY_MIRROR:
|
||||
telemetrySetMirrorCb(ctx, sendByte);
|
||||
break;
|
||||
|
||||
#if defined(CLI)
|
||||
case UART_MODE_CLI:
|
||||
cliSetSerialDriver(ctx, drv);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_GPS)
|
||||
case UART_MODE_GPS:
|
||||
gpsSetSerialDriver(ctx, drv);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void serialSetupPort(int mode, etx_serial_init& params, bool& power_required)
|
||||
{
|
||||
switch (mode) {
|
||||
|
||||
#if defined(DEBUG) || defined(CLI)
|
||||
case UART_MODE_DEBUG:
|
||||
case UART_MODE_CLI:
|
||||
params.baudrate = DEBUG_BAUDRATE;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !defined(BOOT)
|
||||
case UART_MODE_TELEMETRY_MIRROR:
|
||||
// TODO: query telemetry baudrate / add setting for module
|
||||
power_required = true;
|
||||
#if defined(CROSSFIRE)
|
||||
if (modelTelemetryProtocol() == PROTOCOL_TELEMETRY_CROSSFIRE) {
|
||||
params.baudrate = CROSSFIRE_TELEM_MIRROR_BAUDRATE;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
params.baudrate = FRSKY_TELEM_MIRROR_BAUDRATE;
|
||||
break;
|
||||
|
||||
case UART_MODE_TELEMETRY:
|
||||
if (modelTelemetryProtocol() == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
|
||||
params.baudrate = FRSKY_D_BAUDRATE;
|
||||
params.rx_enable = true;
|
||||
power_required = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case UART_MODE_SBUS_TRAINER:
|
||||
params.baudrate = SBUS_BAUDRATE;
|
||||
params.word_length = ETX_WordLength_9;
|
||||
params.parity = ETX_Parity_Even;
|
||||
params.stop_bits = ETX_StopBits_Two;
|
||||
params.rx_enable = true;
|
||||
power_required = true;
|
||||
break;
|
||||
|
||||
#if defined(LUA)
|
||||
case UART_MODE_LUA:
|
||||
params.baudrate = LUA_DEFAULT_BAUDRATE;
|
||||
params.rx_enable = true;
|
||||
power_required = true;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_GPS)
|
||||
case UART_MODE_GPS:
|
||||
params.baudrate = GPS_USART_BAUDRATE;
|
||||
params.rx_enable = true;
|
||||
power_required = true;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
const etx_serial_port_t* serialGetPort(uint8_t port_nr)
|
||||
{
|
||||
const etx_serial_port_t* port = nullptr;
|
||||
if (port_nr != SP_VCP) {
|
||||
port = auxSerialGetPort(port_nr);
|
||||
}
|
||||
#if defined(USB_SERIAL)
|
||||
else {
|
||||
port = &UsbSerialPort;
|
||||
}
|
||||
#endif
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
void serialInit(uint8_t port_nr, int mode)
|
||||
{
|
||||
auto state = getSerialPortState(port_nr);
|
||||
if (!state) return;
|
||||
|
||||
const etx_serial_port_t* port = serialGetPort(port_nr);
|
||||
if (!port) return;
|
||||
|
||||
if (state->port) {
|
||||
auto drv = state->port->uart;
|
||||
if (drv && drv->deinit) {
|
||||
drv->deinit(state->usart_ctx);
|
||||
}
|
||||
if (state->mode != 0) {
|
||||
// Clear callbacks
|
||||
serialSetCallBacks(state->mode, nullptr, nullptr);
|
||||
}
|
||||
memset(state, 0, sizeof(SerialPortState));
|
||||
}
|
||||
|
||||
etx_serial_init params = {
|
||||
.baudrate = 0,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = false,
|
||||
.on_receive = nullptr,
|
||||
.on_error = nullptr,
|
||||
};
|
||||
|
||||
bool power_required = false;
|
||||
serialSetupPort(mode, params, power_required);
|
||||
|
||||
if (params.baudrate != 0) {
|
||||
state->mode = mode;
|
||||
state->port = port;
|
||||
|
||||
if (port) {
|
||||
if (port->uart && port->uart->init)
|
||||
state->usart_ctx = port->uart->init(¶ms);
|
||||
|
||||
// Set power on/off
|
||||
if (port->set_pwr) {
|
||||
port->set_pwr(power_required);
|
||||
}
|
||||
}
|
||||
|
||||
// Update callbacks once the port is setup
|
||||
serialSetCallBacks(mode, state->usart_ctx, state->port);
|
||||
}
|
||||
}
|
||||
|
||||
void initSerialPorts()
|
||||
{
|
||||
memset(serialPortStates, 0, sizeof(serialPortStates));
|
||||
|
||||
for (uint8_t port_nr = 0; port_nr < MAX_AUX_SERIAL; port_nr++) {
|
||||
auto mode = getSerialPortMode(port_nr);
|
||||
serialInit(port_nr, mode);
|
||||
}
|
||||
}
|
||||
|
||||
int serialGetMode(uint8_t port_nr)
|
||||
{
|
||||
return getSerialPortMode(port_nr);
|
||||
}
|
||||
|
||||
void serialSetMode(uint8_t port_nr, int mode)
|
||||
{
|
||||
if (port_nr >= MAX_SERIAL_PORTS) return;
|
||||
uint16_t m = mode & 0xF;
|
||||
g_eeGeneral.serialPort =
|
||||
(g_eeGeneral.serialPort & ~(0xF << port_nr * 4)) | (m << port_nr * 4);
|
||||
}
|
||||
|
||||
// uint8_t serialTracesEnabled(int port_nr)
|
||||
// {
|
||||
// #if defined(DEBUG)
|
||||
// return serialGetMode(port_nr) == UART_MODE_DEBUG;
|
||||
// #else
|
||||
// return false;
|
||||
// #endif
|
||||
// }
|
||||
|
||||
void serialStop(uint8_t port_nr)
|
||||
{
|
||||
auto state = getSerialPortState(port_nr);
|
||||
if (!state) return;
|
||||
|
||||
if (state->port) {
|
||||
auto port = state->port;
|
||||
auto drv = port->uart;
|
||||
if (drv && drv->deinit) {
|
||||
drv->deinit(state->usart_ctx);
|
||||
}
|
||||
if (port->set_pwr) {
|
||||
// Power OFF
|
||||
port->set_pwr(0);
|
||||
}
|
||||
if (state->mode != 0) {
|
||||
// Clear callbacks
|
||||
serialSetCallBacks(state->mode, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
memset(state, 0, sizeof(SerialPortState));
|
||||
}
|
||||
|
||||
+25
-4
@@ -22,19 +22,40 @@
|
||||
#ifndef _SERIAL_H_
|
||||
#define _SERIAL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hal/serial_port.h"
|
||||
|
||||
const etx_serial_port_t* serialGetPort(uint8_t port_nr);
|
||||
int serialGetMode(uint8_t port_nr);
|
||||
void serialSetMode(uint8_t port_nr, int mode);
|
||||
|
||||
void initSerialPorts();
|
||||
void serialInit(uint8_t port_nr, int mode);
|
||||
void serialStop(uint8_t port_nr);
|
||||
|
||||
//
|
||||
// Functions used by debug.h
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void serialPutc(char c);
|
||||
void serialPrintf(const char *format, ...);
|
||||
void serialCrlf();
|
||||
void dbgSerialPutc(char c);
|
||||
void dbgSerialPrintf(const char *format, ...);
|
||||
void dbgSerialCrlf();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define serialPrint(...) do { serialPrintf(__VA_ARGS__); serialCrlf(); } while(0)
|
||||
#define dbgSerialPrint(...) do { dbgSerialPrintf(__VA_ARGS__); dbgSerialCrlf(); } while(0)
|
||||
|
||||
// Debug serial callback
|
||||
void dbgSerialSetSendCb(void* ctx, void (*cb)(void*, uint8_t));
|
||||
|
||||
// Query debug callback
|
||||
void (*dbgSerialGetSendCb())(void*, uint8_t);
|
||||
void* dbgSerialGetSendCbCtx();
|
||||
|
||||
#endif // _SERIAL_H_
|
||||
|
||||
|
||||
@@ -711,7 +711,6 @@ bool w_vPitch(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opa
|
||||
return wf(opaque, s, strlen(s));
|
||||
}
|
||||
|
||||
extern const struct YamlIdStr enum_TrainerMode[];
|
||||
const struct YamlIdStr enum_TrainerMode[] = {
|
||||
#if defined(PCBNV14)
|
||||
{ TRAINER_MODE_OFF, "OFF" },
|
||||
@@ -733,8 +732,8 @@ const struct YamlIdStr enum_TrainerMode[] = {
|
||||
|
||||
#define r_trainerMode nullptr
|
||||
|
||||
bool w_trainerMode(const YamlNode* node, uint32_t val,
|
||||
yaml_writer_func wf, void* opaque)
|
||||
static bool w_trainerMode(const YamlNode* node, uint32_t val,
|
||||
yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
const char* str = nullptr;
|
||||
str = yaml_output_enum(val, enum_TrainerMode);
|
||||
@@ -1168,3 +1167,6 @@ bool w_channelsCount(const YamlNode* node, uint32_t val, yaml_writer_func wf, vo
|
||||
const char* str = yaml_signed2str(sval);
|
||||
return wf(opaque,str,strlen(str));
|
||||
}
|
||||
|
||||
// force storage class
|
||||
extern const struct YamlIdStr enum_UartModes[];
|
||||
|
||||
@@ -82,6 +82,17 @@ void postRadioSettingsLoad()
|
||||
setDefaultOwnerId();
|
||||
}
|
||||
#endif
|
||||
#if defined(PCBX12S)
|
||||
// AUX2 is hardwired to AUX2 on X12S
|
||||
serialSetMode(SP_AUX2, UART_MODE_GPS);
|
||||
#endif
|
||||
#if defined(USB_SERIAL)
|
||||
// default VCP to CLI if not configured
|
||||
// to something else as NONE.
|
||||
if (serialGetMode(SP_VCP) == UART_MODE_NONE) {
|
||||
serialSetMode(SP_VCP, UART_MODE_CLI);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(EXTERNAL_ANTENNA) && defined(INTERNAL_MODULE_PXX1)
|
||||
|
||||
@@ -58,10 +58,6 @@ namespace yaml_conv_220 {
|
||||
bool w_spPitch(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque);
|
||||
bool w_vPitch(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque);
|
||||
|
||||
extern const struct YamlIdStr enum_TrainerMode[];
|
||||
bool w_trainerMode(const YamlNode* node, uint32_t val,
|
||||
yaml_writer_func wf, void* opaque);
|
||||
|
||||
extern const char* _tele_screen_type_lookup[];
|
||||
bool w_tele_screen_type(void* user, uint8_t* data, uint32_t bitoffs,
|
||||
yaml_writer_func wf, void* opaque);
|
||||
@@ -99,6 +95,7 @@ namespace yaml_conv_220 {
|
||||
bool w_channelsCount(const YamlNode* node, uint32_t val, yaml_writer_func wf,
|
||||
void* opaque);
|
||||
|
||||
extern const struct YamlIdStr enum_UartModes[];
|
||||
};
|
||||
|
||||
//
|
||||
@@ -1029,15 +1026,36 @@ static bool w_vPitch(const YamlNode* node, uint32_t val, yaml_writer_func wf, vo
|
||||
return yaml_conv_220::w_vPitch(node, val, wf, opaque);
|
||||
}
|
||||
|
||||
static const struct YamlIdStr enum_TrainerMode[] = {
|
||||
{ TRAINER_MODE_OFF, "OFF" },
|
||||
{ TRAINER_MODE_MASTER_TRAINER_JACK, "MASTER_TRAINER_JACK" },
|
||||
{ TRAINER_MODE_SLAVE, "SLAVE" },
|
||||
{ TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE, "MASTER_SBUS_EXT" },
|
||||
{ TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, "MASTER_CPPM_EXT" },
|
||||
{ TRAINER_MODE_MASTER_SERIAL, "MASTER_SERIAL" },
|
||||
{ TRAINER_MODE_MASTER_SERIAL, "MASTER_BATT_COMP" },
|
||||
{ TRAINER_MODE_MASTER_BLUETOOTH, "MASTER_BT" },
|
||||
{ TRAINER_MODE_SLAVE_BLUETOOTH, "SLAVE_BT" },
|
||||
{ TRAINER_MODE_MULTI, "MASTER_MULTI" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static uint32_t r_trainerMode(const YamlNode* node, const char* val, uint8_t val_len)
|
||||
{
|
||||
return yaml_parse_enum(yaml_conv_220::enum_TrainerMode, val, val_len);
|
||||
return yaml_parse_enum(enum_TrainerMode, val, val_len);
|
||||
}
|
||||
|
||||
static bool w_trainerMode(const YamlNode* node, uint32_t val,
|
||||
yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
return yaml_conv_220::w_trainerMode(node, val, wf, opaque);
|
||||
const char* str = nullptr;
|
||||
str = yaml_output_enum(val, enum_TrainerMode);
|
||||
|
||||
if (str) {
|
||||
return wf(opaque, str, strlen(str));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined(COLORLCD)
|
||||
@@ -1733,3 +1751,70 @@ static void r_jitterFilter(void* user, uint8_t* data, uint32_t bitoffs,
|
||||
uint32_t i = yaml_str2uint(val, val_len);
|
||||
yaml_put_bits(data, i, bitoffs, 1);
|
||||
}
|
||||
|
||||
//struct_serialConfig
|
||||
static const struct YamlIdStr enum_SerialPort[] = {
|
||||
{ SP_AUX1, "AUX1" },
|
||||
{ SP_AUX2, "AUX2" },
|
||||
{ SP_VCP, "VCP" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "TELEMETRY_IN" },
|
||||
{ UART_MODE_SBUS_TRAINER, "SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "LUA" },
|
||||
{ UART_MODE_CLI, "CLI" },
|
||||
{ UART_MODE_GPS, "GPS" },
|
||||
{ UART_MODE_DEBUG, "DEBUG" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static uint32_t port_read(void* user, const char* val, uint8_t val_len)
|
||||
{
|
||||
(void)user;
|
||||
uint32_t port = yaml_parse_enum(enum_SerialPort, val, val_len);
|
||||
if (port < MAX_SERIAL_PORTS) return port;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool port_write(void* user, yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
auto tw = reinterpret_cast<YamlTreeWalker*>(user);
|
||||
uint16_t idx = tw->getElmts();
|
||||
|
||||
const char* str = yaml_output_enum(idx, enum_SerialPort);
|
||||
return str ? wf(opaque, str, strlen(str)) : true;
|
||||
}
|
||||
|
||||
static const struct YamlNode struct_serialConfig[] = {
|
||||
YAML_IDX_CUST( "port", port_read, port_write),
|
||||
YAML_ENUM( "mode", 4, enum_UartModes),
|
||||
YAML_END
|
||||
};
|
||||
|
||||
static void r_serialMode(void* user, uint8_t* data, uint32_t bitoffs,
|
||||
const char* val, uint8_t val_len)
|
||||
{
|
||||
auto tw = reinterpret_cast<YamlTreeWalker*>(user);
|
||||
|
||||
auto node = tw->getAttr();
|
||||
if (!node || node->tag_len < 4) return;
|
||||
|
||||
uint8_t port_nr;
|
||||
if (node->tag[3] == 'S')
|
||||
port_nr = SP_AUX1;
|
||||
else if (node->tag[3] == '2')
|
||||
port_nr = SP_AUX2;
|
||||
else
|
||||
return;
|
||||
|
||||
auto m = yaml_parse_enum(yaml_conv_220::enum_UartModes, val, val_len);
|
||||
if (!m) return;
|
||||
|
||||
auto serialPort = reinterpret_cast<uint16_t*>(data);
|
||||
*serialPort = (*serialPort & ~(0xF << port_nr * 4)) | (m << port_nr * 4);
|
||||
}
|
||||
|
||||
@@ -85,14 +85,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_DISABLE_TOUCH, "DISABLE_TOUCH" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_ZoneOptionValueEnum[] = {
|
||||
{ ZOV_Unsigned, "Unsigned" },
|
||||
{ ZOV_Signed, "Signed" },
|
||||
@@ -427,8 +419,9 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 72, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_ENUM("aux2SerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
YAML_ARRAY("switchConfig", 2, 16, struct_switchConfig, nullptr),
|
||||
YAML_ARRAY("potsConfig", 2, 8, struct_potConfig, nullptr),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -398,8 +390,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -398,8 +390,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -398,8 +390,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -406,8 +398,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -398,8 +390,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -85,14 +85,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_DISABLE_TOUCH, "DISABLE_TOUCH" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_ZoneOptionValueEnum[] = {
|
||||
{ ZOV_Unsigned, "Unsigned" },
|
||||
{ ZOV_Signed, "Signed" },
|
||||
@@ -448,8 +440,9 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 72, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_ENUM("aux2SerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
YAML_ARRAY("switchConfig", 2, 16, struct_switchConfig, nullptr),
|
||||
YAML_ARRAY("potsConfig", 2, 8, struct_potConfig, nullptr),
|
||||
|
||||
@@ -85,14 +85,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_DISABLE_TOUCH, "DISABLE_TOUCH" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_ZoneOptionValueEnum[] = {
|
||||
{ ZOV_Unsigned, "Unsigned" },
|
||||
{ ZOV_Signed, "Signed" },
|
||||
@@ -446,8 +438,9 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 72, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_ENUM("aux2SerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
YAML_ARRAY("switchConfig", 2, 16, struct_switchConfig, nullptr),
|
||||
YAML_ARRAY("potsConfig", 2, 8, struct_potConfig, nullptr),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -398,8 +390,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -405,8 +397,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -444,8 +436,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -385,8 +377,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -393,8 +385,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -390,8 +382,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -392,8 +384,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -84,14 +84,6 @@ const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_RACING_MODE, "RACING_MODE" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_UartModes[] = {
|
||||
{ UART_MODE_NONE, "MODE_NONE" },
|
||||
{ UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
|
||||
{ UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
|
||||
{ UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
|
||||
{ UART_MODE_LUA, "MODE_LUA" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_TimerModes[] = {
|
||||
{ TMRMODE_OFF, "OFF" },
|
||||
{ TMRMODE_ON, "ON" },
|
||||
@@ -398,8 +390,11 @@ static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_ENUM("auxSerialMode", 4, enum_UartModes),
|
||||
YAML_CUSTOM("auxSerialMode",r_serialMode,nullptr),
|
||||
YAML_CUSTOM("aux2SerialMode",r_serialMode,nullptr),
|
||||
YAML_ARRAY("serialPort", 4, 4, struct_serialConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
|
||||
YAML_UNSIGNED( "backlightColor", 8 ),
|
||||
YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
|
||||
|
||||
@@ -164,7 +164,7 @@ endif()
|
||||
if(HAPTIC)
|
||||
add_definitions(-DHAPTIC)
|
||||
set(SRC ${SRC} haptic.cpp)
|
||||
set(TARGET_SRC ${TARGET_SRC} haptic_driver.cpp)
|
||||
set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} haptic_driver.cpp)
|
||||
endif()
|
||||
|
||||
# Protocols supported
|
||||
@@ -268,6 +268,7 @@ add_definitions(-g)
|
||||
add_definitions(-DCPUARM)
|
||||
add_definitions(-DGPS)
|
||||
add_definitions(-DBATTGRAPH -DTHRTRACE)
|
||||
add_definitions(-DSBUS_TRAINER)
|
||||
|
||||
include_directories(${RTOS_DIR}/include)
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ set(STM32USB_SRC
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
${FIRMWARE_TARGET_SRC}
|
||||
../common/arm/stm32/rtc_driver.cpp
|
||||
${AUX_SERIAL_DRIVER}
|
||||
../common/arm/stm32/delays_driver.cpp
|
||||
../common/arm/stm32/usb_bsp.c
|
||||
../common/arm/stm32/usbd_desc.c
|
||||
@@ -40,6 +39,18 @@ set(FIRMWARE_TARGET_SRC
|
||||
../common/arm/stm32/usbd_hid_joystick.c
|
||||
)
|
||||
|
||||
if(AUX_SERIAL OR AUX2_SERIAL)
|
||||
set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC}
|
||||
../common/arm/stm32/aux_serial_driver.cpp
|
||||
)
|
||||
if(AUX_SERIAL)
|
||||
add_definitions(-DAUX_SERIAL)
|
||||
endif()
|
||||
if(AUX2_SERIAL)
|
||||
add_definitions(-DAUX2_SERIAL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DEBUG OR CLI OR USB_SERIAL)
|
||||
set(STM32USB_SRC
|
||||
${STM32USB_SRC}
|
||||
@@ -70,7 +81,6 @@ endif()
|
||||
|
||||
set(FIRMWARE_SRC
|
||||
${FIRMWARE_SRC}
|
||||
serial.cpp
|
||||
syscalls.c
|
||||
)
|
||||
|
||||
|
||||
@@ -19,415 +19,259 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "stm32_hal_ll.h"
|
||||
#include "stm32_usart_driver.h"
|
||||
|
||||
#include "opentx.h"
|
||||
#include "targets/horus/board.h"
|
||||
#include "aux_serial_driver.h"
|
||||
|
||||
#include "fifo.h"
|
||||
#include "dmafifo.h"
|
||||
|
||||
#define AUX_SERIAL_TX_BUFFER 512
|
||||
|
||||
#if defined(SDRAM)
|
||||
#define AUX_SERIAL_RX_BUFFER 128
|
||||
#else
|
||||
#define AUX_SERIAL_RX_BUFFER 32
|
||||
#endif
|
||||
|
||||
typedef Fifo<uint8_t, AUX_SERIAL_TX_BUFFER> TxFifo;
|
||||
typedef DMAFifo<AUX_SERIAL_RX_BUFFER> RxFifo;
|
||||
|
||||
struct SerialState
|
||||
{
|
||||
TxFifo* txFifo;
|
||||
RxFifo* rxFifo;
|
||||
|
||||
const stm32_usart_t* usart;
|
||||
};
|
||||
|
||||
static void* aux_serial_init(const SerialState* st, const etx_serial_init* params)
|
||||
{
|
||||
stm32_usart_init(st->usart, params);
|
||||
|
||||
if (params->rx_enable && st->usart->rxDMA && !params->on_receive) {
|
||||
st->rxFifo->clear();
|
||||
stm32_usart_init_rx_dma(st->usart, st->rxFifo->buffer(), st->rxFifo->size());
|
||||
}
|
||||
|
||||
return (void*)st;
|
||||
}
|
||||
|
||||
static void aux_serial_putc(void* ctx, uint8_t c)
|
||||
{
|
||||
auto st = (const SerialState*)ctx;
|
||||
if (st->txFifo->isFull()) return;
|
||||
st->txFifo->push(c);
|
||||
|
||||
// Send is based on IRQ, so that this
|
||||
// only enables the corresponding IRQ
|
||||
stm32_usart_send_buffer(st->usart, &c, 1);
|
||||
}
|
||||
|
||||
static void aux_serial_send_buffer(void* ctx, const uint8_t* data, uint8_t size)
|
||||
{
|
||||
while(size > 0) {
|
||||
aux_serial_putc(ctx, *data++);
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
static void aux_wait_tx_completed(void* ctx)
|
||||
{
|
||||
// TODO
|
||||
(void)ctx;
|
||||
}
|
||||
|
||||
static int aux_get_byte(void* ctx, uint8_t* data)
|
||||
{
|
||||
auto st = (const SerialState*)ctx;
|
||||
if (!st->rxFifo) return -1;
|
||||
return st->rxFifo->pop(*data);
|
||||
}
|
||||
|
||||
void aux_serial_deinit(void* ctx)
|
||||
{
|
||||
auto st = (const SerialState*)ctx;
|
||||
stm32_usart_deinit(st->usart);
|
||||
}
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
uint8_t auxSerialMode = UART_MODE_COUNT; // Prevent debug output before port is setup
|
||||
Fifo<uint8_t, 512> auxSerialTxFifo;
|
||||
|
||||
#if defined(AUX_SERIAL_DMA_Stream_RX)
|
||||
AuxSerialRxFifo auxSerialRxFifo __DMA (AUX_SERIAL_DMA_Stream_RX);
|
||||
#else
|
||||
AuxSerialRxFifo auxSerialRxFifo;
|
||||
#endif
|
||||
static TxFifo auxSerialTxFifo;
|
||||
static RxFifo auxSerialRxFifo __DMA (AUX_SERIAL_DMA_Stream_RX);
|
||||
|
||||
void auxSerialSetup(unsigned int baudrate, bool dma, uint16_t length, uint16_t parity, uint16_t stop)
|
||||
static const LL_GPIO_InitTypeDef auxUSARTPinInit = {
|
||||
.Pin = AUX_SERIAL_GPIO_PIN_TX | AUX_SERIAL_GPIO_PIN_RX,
|
||||
.Mode = LL_GPIO_MODE_ALTERNATE,
|
||||
.Speed = LL_GPIO_SPEED_FREQ_LOW,
|
||||
.OutputType = LL_GPIO_OUTPUT_PUSHPULL,
|
||||
.Pull = LL_GPIO_PULL_UP,
|
||||
.Alternate = AUX_SERIAL_GPIO_AF_LL,
|
||||
};
|
||||
|
||||
static const stm32_usart_t auxUSART = {
|
||||
.USARTx = AUX_SERIAL_USART,
|
||||
.GPIOx = AUX_SERIAL_GPIO,
|
||||
.pinInit = &auxUSARTPinInit,
|
||||
.IRQn = AUX_SERIAL_USART_IRQn,
|
||||
.IRQ_Prio = 7, // TODO: define constant
|
||||
.txDMA = nullptr,
|
||||
.txDMA_Stream = 0,
|
||||
.txDMA_Channel = 0,
|
||||
.rxDMA = AUX_SERIAL_DMA_RX,
|
||||
.rxDMA_Stream = AUX_SERIAL_DMA_Stream_RX_LL,
|
||||
.rxDMA_Channel = AUX_SERIAL_DMA_Channel_RX,
|
||||
};
|
||||
|
||||
static const SerialState auxSerialState = {
|
||||
.txFifo = &auxSerialTxFifo,
|
||||
.rxFifo = &auxSerialRxFifo,
|
||||
.usart = &auxUSART,
|
||||
};
|
||||
|
||||
// TODO: grab context to get buffer
|
||||
static uint8_t auxSerialOnSend(uint8_t* data)
|
||||
{
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
GPIO_PinAFConfig(AUX_SERIAL_GPIO, AUX_SERIAL_GPIO_PinSource_RX, AUX_SERIAL_GPIO_AF);
|
||||
GPIO_PinAFConfig(AUX_SERIAL_GPIO, AUX_SERIAL_GPIO_PinSource_TX, AUX_SERIAL_GPIO_AF);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = AUX_SERIAL_GPIO_PIN_TX | AUX_SERIAL_GPIO_PIN_RX;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_Init(AUX_SERIAL_GPIO, &GPIO_InitStructure);
|
||||
|
||||
#if defined(AUX_SERIAL_PWR_GPIO)
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_InitStructure.GPIO_Pin = AUX_SERIAL_PWR_GPIO_PIN;
|
||||
GPIO_Init(AUX_SERIAL_PWR_GPIO, &GPIO_InitStructure);
|
||||
#endif
|
||||
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
USART_InitStructure.USART_WordLength = length;
|
||||
USART_InitStructure.USART_StopBits = stop;
|
||||
USART_InitStructure.USART_Parity = parity;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
|
||||
USART_Init(AUX_SERIAL_USART, &USART_InitStructure);
|
||||
|
||||
#if defined(AUX_SERIAL_TX_INVERT_GPIO_PIN)
|
||||
GPIO_InitStructure.GPIO_Pin = AUX_SERIAL_TX_INVERT_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_Init(AUX_SERIAL_TX_INVERT_GPIO, &GPIO_InitStructure);
|
||||
GPIO_ResetBits(AUX_SERIAL_TX_INVERT_GPIO, AUX_SERIAL_TX_INVERT_GPIO_PIN);
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL_RX_INVERT_GPIO_PIN)
|
||||
GPIO_InitStructure.GPIO_Pin = AUX_SERIAL_RX_INVERT_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_Init(AUX_SERIAL_RX_INVERT_GPIO, &GPIO_InitStructure);
|
||||
GPIO_ResetBits(AUX_SERIAL_RX_INVERT_GPIO, AUX_SERIAL_RX_INVERT_GPIO_PIN);
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL_DMA_Stream_RX)
|
||||
if (dma) {
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
auxSerialRxFifo.clear();
|
||||
USART_ITConfig(AUX_SERIAL_USART, USART_IT_RXNE, DISABLE);
|
||||
USART_ITConfig(AUX_SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
DMA_InitStructure.DMA_Channel = AUX_SERIAL_DMA_Channel_RX;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&AUX_SERIAL_USART->DR);
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(auxSerialRxFifo.buffer());
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
DMA_InitStructure.DMA_BufferSize = auxSerialRxFifo.size();
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(AUX_SERIAL_DMA_Stream_RX, &DMA_InitStructure);
|
||||
USART_DMACmd(AUX_SERIAL_USART, USART_DMAReq_Rx, ENABLE);
|
||||
USART_Cmd(AUX_SERIAL_USART, ENABLE);
|
||||
DMA_Cmd(AUX_SERIAL_DMA_Stream_RX, ENABLE);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// no DMA ...
|
||||
USART_Cmd(AUX_SERIAL_USART, ENABLE);
|
||||
USART_ITConfig(AUX_SERIAL_USART, USART_IT_RXNE, ENABLE);
|
||||
USART_ITConfig(AUX_SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
NVIC_SetPriority(AUX_SERIAL_USART_IRQn, 7);
|
||||
NVIC_EnableIRQ(AUX_SERIAL_USART_IRQn);
|
||||
return auxSerialTxFifo.pop(*data);
|
||||
}
|
||||
|
||||
void auxSerialInit(unsigned int mode, unsigned int protocol)
|
||||
// TODO: add to state
|
||||
static etx_serial_callbacks_t auxSerialCb = {
|
||||
.on_send = auxSerialOnSend,
|
||||
.on_receive = nullptr,
|
||||
.on_error = nullptr,
|
||||
};
|
||||
|
||||
static void* auxSerialInit(const etx_serial_init* params)
|
||||
{
|
||||
auxSerialStop();
|
||||
return aux_serial_init(&auxSerialState, params);
|
||||
}
|
||||
|
||||
auxSerialMode = mode;
|
||||
static void (*aux1RxCb)(uint8_t*, uint32_t);
|
||||
|
||||
switch (mode) {
|
||||
case UART_MODE_TELEMETRY_MIRROR:
|
||||
#if defined(CROSSFIRE)
|
||||
if (protocol == PROTOCOL_TELEMETRY_CROSSFIRE) {
|
||||
auxSerialSetup(CROSSFIRE_TELEM_MIRROR_BAUDRATE, false);
|
||||
AUX_SERIAL_POWER_ON();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
auxSerialSetup(FRSKY_TELEM_MIRROR_BAUDRATE, false);
|
||||
AUX_SERIAL_POWER_ON();
|
||||
break;
|
||||
static void aux1_on_rx_byte(uint8_t data)
|
||||
{
|
||||
if (aux1RxCb) aux1RxCb(&data, 1);
|
||||
}
|
||||
|
||||
#if defined(DEBUG) || defined(CLI)
|
||||
case UART_MODE_DEBUG:
|
||||
auxSerialSetup(DEBUG_BAUDRATE, false);
|
||||
AUX_SERIAL_POWER_OFF();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case UART_MODE_TELEMETRY:
|
||||
if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
|
||||
auxSerialSetup(FRSKY_D_BAUDRATE, true);
|
||||
AUX_SERIAL_POWER_ON();
|
||||
}
|
||||
break;
|
||||
|
||||
case UART_MODE_SBUS_TRAINER:
|
||||
auxSerialSetup(SBUS_BAUDRATE, true, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // USART_WordLength_9b due to parity bit
|
||||
AUX_SERIAL_POWER_ON();
|
||||
break;
|
||||
|
||||
case UART_MODE_LUA:
|
||||
auxSerialSetup(LUA_DEFAULT_BAUDRATE, false);
|
||||
AUX_SERIAL_POWER_ON();
|
||||
static void aux1SetRxCb(void*, void (*cb)(uint8_t*, uint32_t))
|
||||
{
|
||||
aux1RxCb = cb;
|
||||
if (aux1RxCb) {
|
||||
auxSerialCb.on_receive = aux1_on_rx_byte;
|
||||
stm32_usart_deinit_rx_dma(&auxUSART);
|
||||
} else {
|
||||
auxSerialCb.on_receive = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void auxSerialPutc(char c)
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
if (auxSerialTxFifo.isFull()) return;
|
||||
auxSerialTxFifo.push(c);
|
||||
USART_ITConfig(AUX_SERIAL_USART, USART_IT_TXE, ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void auxSerialSbusInit()
|
||||
{
|
||||
auxSerialInit(UART_MODE_SBUS_TRAINER, 0);
|
||||
}
|
||||
|
||||
void auxSerialStop()
|
||||
{
|
||||
#if defined(AUX_SERIAL_DMA_Stream_RX)
|
||||
DMA_DeInit(AUX_SERIAL_DMA_Stream_RX);
|
||||
#endif
|
||||
|
||||
USART_DeInit(AUX_SERIAL_USART);
|
||||
}
|
||||
|
||||
uint8_t auxSerialTracesEnabled()
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
return (auxSerialMode == UART_MODE_DEBUG);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
const etx_serial_driver_t AuxSerialDriver = {
|
||||
.init = auxSerialInit,
|
||||
.deinit = aux_serial_deinit,
|
||||
.sendByte = aux_serial_putc,
|
||||
.sendBuffer = aux_serial_send_buffer,
|
||||
.waitForTxCompleted = aux_wait_tx_completed,
|
||||
.getByte = aux_get_byte,
|
||||
.getBaudrate = nullptr,
|
||||
.setReceiveCb = aux1SetRxCb,
|
||||
.setBaudrateCb = nullptr,
|
||||
};
|
||||
|
||||
extern "C" void AUX_SERIAL_USART_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_SER2);
|
||||
|
||||
// Send
|
||||
if (USART_GetITStatus(AUX_SERIAL_USART, USART_IT_TXE) != RESET) {
|
||||
uint8_t txchar;
|
||||
if (auxSerialTxFifo.pop(txchar)) {
|
||||
/* Write one byte to the transmit data register */
|
||||
USART_SendData(AUX_SERIAL_USART, txchar);
|
||||
}
|
||||
else {
|
||||
USART_ITConfig(AUX_SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CLI)
|
||||
if (getSelectedUsbMode() != USB_SERIAL_MODE) {
|
||||
// Receive
|
||||
uint32_t status = AUX_SERIAL_USART->SR;
|
||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||
uint8_t data = AUX_SERIAL_USART->DR;
|
||||
if (!(status & USART_FLAG_ERRORS)) {
|
||||
switch (auxSerialMode) {
|
||||
case UART_MODE_DEBUG:
|
||||
cliReceiveData(&data, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
status = AUX_SERIAL_USART->SR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Receive
|
||||
uint32_t status = AUX_SERIAL_USART->SR;
|
||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||
uint8_t data = AUX_SERIAL_USART->DR;
|
||||
UNUSED(data);
|
||||
if (!(status & USART_FLAG_ERRORS)) {
|
||||
#if defined(LUA) & !defined(CLI)
|
||||
if (luaRxFifo && auxSerialMode == UART_MODE_LUA)
|
||||
luaRxFifo->push(data);
|
||||
#endif
|
||||
}
|
||||
status = AUX_SERIAL_USART->SR;
|
||||
}
|
||||
stm32_usart_isr(&auxUSART, &auxSerialCb);
|
||||
}
|
||||
|
||||
#endif // AUX_SERIAL
|
||||
|
||||
#if defined(AUX2_SERIAL)
|
||||
uint8_t aux2SerialMode = UART_MODE_COUNT; // Prevent debug output before port is setup
|
||||
Fifo<uint8_t, 512> aux2SerialTxFifo;
|
||||
AuxSerialRxFifo aux2SerialRxFifo __DMA (AUX2_SERIAL_DMA_Stream_RX);
|
||||
|
||||
void aux2SerialSetup(unsigned int baudrate, bool dma, uint16_t length, uint16_t parity, uint16_t stop)
|
||||
static TxFifo aux2SerialTxFifo;
|
||||
static RxFifo aux2SerialRxFifo __DMA (AUX2_SERIAL_DMA_Stream_RX);
|
||||
|
||||
static const LL_GPIO_InitTypeDef aux2USARTPinInit = {
|
||||
.Pin = AUX2_SERIAL_GPIO_PIN_TX | AUX2_SERIAL_GPIO_PIN_RX,
|
||||
.Mode = LL_GPIO_MODE_ALTERNATE,
|
||||
.Speed = LL_GPIO_SPEED_FREQ_LOW,
|
||||
.OutputType = LL_GPIO_OUTPUT_PUSHPULL,
|
||||
.Pull = LL_GPIO_PULL_UP,
|
||||
.Alternate = AUX2_SERIAL_GPIO_AF_LL,
|
||||
};
|
||||
|
||||
static const stm32_usart_t aux2USART = {
|
||||
.USARTx = AUX2_SERIAL_USART,
|
||||
.GPIOx = AUX2_SERIAL_GPIO,
|
||||
.pinInit = &aux2USARTPinInit,
|
||||
.IRQn = AUX2_SERIAL_USART_IRQn,
|
||||
.IRQ_Prio = 7, // TODO: define constant
|
||||
.txDMA = nullptr,
|
||||
.txDMA_Stream = 0,
|
||||
.txDMA_Channel = 0,
|
||||
.rxDMA = AUX2_SERIAL_DMA_RX,
|
||||
.rxDMA_Stream = AUX2_SERIAL_DMA_Stream_RX_LL,
|
||||
.rxDMA_Channel = AUX2_SERIAL_DMA_Channel_RX,
|
||||
};
|
||||
|
||||
static const SerialState aux2SerialState = {
|
||||
.txFifo = &aux2SerialTxFifo,
|
||||
.rxFifo = &aux2SerialRxFifo,
|
||||
.usart = &aux2USART,
|
||||
};
|
||||
|
||||
static uint8_t aux2SerialOnSend(uint8_t* data)
|
||||
{
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
return aux2SerialTxFifo.pop(*data);
|
||||
}
|
||||
|
||||
GPIO_PinAFConfig(AUX2_SERIAL_GPIO, AUX2_SERIAL_GPIO_PinSource_RX, AUX2_SERIAL_GPIO_AF);
|
||||
GPIO_PinAFConfig(AUX2_SERIAL_GPIO, AUX2_SERIAL_GPIO_PinSource_TX, AUX2_SERIAL_GPIO_AF);
|
||||
static etx_serial_callbacks_t aux2SerialCb = {
|
||||
.on_send = aux2SerialOnSend,
|
||||
.on_receive = nullptr,
|
||||
.on_error = nullptr,
|
||||
};
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = AUX2_SERIAL_GPIO_PIN_TX | AUX2_SERIAL_GPIO_PIN_RX;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_Init(AUX2_SERIAL_GPIO, &GPIO_InitStructure);
|
||||
static void* aux2SerialInit(const etx_serial_init* params)
|
||||
{
|
||||
return aux_serial_init(&aux2SerialState, params);
|
||||
}
|
||||
|
||||
#if defined(AUX2_SERIAL_PWR_GPIO)
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_InitStructure.GPIO_Pin = AUX2_SERIAL_PWR_GPIO_PIN;
|
||||
GPIO_Init(AUX2_SERIAL_PWR_GPIO, &GPIO_InitStructure);
|
||||
#endif
|
||||
static void (*aux2RxCb)(uint8_t*, uint32_t);
|
||||
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
USART_InitStructure.USART_WordLength = length;
|
||||
USART_InitStructure.USART_StopBits = stop;
|
||||
USART_InitStructure.USART_Parity = parity;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
|
||||
USART_Init(AUX2_SERIAL_USART, &USART_InitStructure);
|
||||
static void aux2_on_rx_byte(uint8_t data)
|
||||
{
|
||||
if (aux2RxCb) aux2RxCb(&data, 1);
|
||||
}
|
||||
|
||||
if (dma) {
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
aux2SerialRxFifo.clear();
|
||||
USART_ITConfig(AUX2_SERIAL_USART, USART_IT_RXNE, DISABLE);
|
||||
USART_ITConfig(AUX2_SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
DMA_InitStructure.DMA_Channel = AUX2_SERIAL_DMA_Channel_RX;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&AUX2_SERIAL_USART->DR);
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(aux2SerialRxFifo.buffer());
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
DMA_InitStructure.DMA_BufferSize = aux2SerialRxFifo.size();
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(AUX2_SERIAL_DMA_Stream_RX, &DMA_InitStructure);
|
||||
USART_DMACmd(AUX2_SERIAL_USART, USART_DMAReq_Rx, ENABLE);
|
||||
USART_Cmd(AUX2_SERIAL_USART, ENABLE);
|
||||
DMA_Cmd(AUX2_SERIAL_DMA_Stream_RX, ENABLE);
|
||||
static void aux2SetRxCb(void*, void (*cb)(uint8_t*, uint32_t))
|
||||
{
|
||||
aux2RxCb = cb;
|
||||
if (aux2RxCb) {
|
||||
aux2SerialCb.on_receive = aux2_on_rx_byte;
|
||||
stm32_usart_deinit_rx_dma(&aux2USART);
|
||||
} else {
|
||||
aux2SerialCb.on_receive = nullptr;
|
||||
}
|
||||
else {
|
||||
USART_Cmd(AUX2_SERIAL_USART, ENABLE);
|
||||
USART_ITConfig(AUX2_SERIAL_USART, USART_IT_RXNE, ENABLE);
|
||||
USART_ITConfig(AUX2_SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
NVIC_SetPriority(AUX2_SERIAL_USART_IRQn, 7);
|
||||
NVIC_EnableIRQ(AUX2_SERIAL_USART_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
void aux2SerialInit(unsigned int mode, unsigned int protocol)
|
||||
{
|
||||
aux2SerialStop();
|
||||
|
||||
aux2SerialMode = mode;
|
||||
|
||||
switch (mode) {
|
||||
case UART_MODE_TELEMETRY_MIRROR:
|
||||
#if defined(CROSSFIRE)
|
||||
if (protocol == PROTOCOL_TELEMETRY_CROSSFIRE) {
|
||||
aux2SerialSetup(CROSSFIRE_TELEM_MIRROR_BAUDRATE, false);
|
||||
AUX2_SERIAL_POWER_ON();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
aux2SerialSetup(FRSKY_TELEM_MIRROR_BAUDRATE, false);
|
||||
AUX2_SERIAL_POWER_ON();
|
||||
break;
|
||||
|
||||
#if defined(DEBUG) || defined(CLI)
|
||||
case UART_MODE_DEBUG:
|
||||
aux2SerialSetup(DEBUG_BAUDRATE, false);
|
||||
AUX2_SERIAL_POWER_OFF();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case UART_MODE_TELEMETRY:
|
||||
if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
|
||||
aux2SerialSetup(FRSKY_D_BAUDRATE, true);
|
||||
AUX2_SERIAL_POWER_ON();
|
||||
}
|
||||
break;
|
||||
|
||||
case UART_MODE_SBUS_TRAINER:
|
||||
aux2SerialSetup(SBUS_BAUDRATE, true, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b
|
||||
AUX2_SERIAL_POWER_ON();
|
||||
break;
|
||||
|
||||
case UART_MODE_LUA:
|
||||
aux2SerialSetup(LUA_DEFAULT_BAUDRATE, false);
|
||||
AUX2_SERIAL_POWER_ON();
|
||||
}
|
||||
}
|
||||
|
||||
void aux2SerialPutc(char c)
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
if (aux2SerialTxFifo.isFull()) return;
|
||||
aux2SerialTxFifo.push(c);
|
||||
USART_ITConfig(AUX2_SERIAL_USART, USART_IT_TXE, ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aux2SerialSbusInit()
|
||||
{
|
||||
aux2SerialInit(UART_MODE_SBUS_TRAINER, 0);
|
||||
}
|
||||
|
||||
void aux2SerialStop()
|
||||
{
|
||||
DMA_DeInit(AUX2_SERIAL_DMA_Stream_RX);
|
||||
USART_DeInit(AUX2_SERIAL_USART);
|
||||
}
|
||||
|
||||
uint8_t aux2SerialTracesEnabled()
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
return (aux2SerialMode == UART_MODE_DEBUG);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void AUX2_SERIAL_USART_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_SER2);
|
||||
|
||||
// Send
|
||||
if (USART_GetITStatus(AUX2_SERIAL_USART, USART_IT_TXE) != RESET) {
|
||||
uint8_t txchar;
|
||||
if (aux2SerialTxFifo.pop(txchar)) {
|
||||
/* Write one byte to the transmit data register */
|
||||
USART_SendData(AUX2_SERIAL_USART, txchar);
|
||||
}
|
||||
else {
|
||||
USART_ITConfig(AUX2_SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CLI)
|
||||
if (getSelectedUsbMode() != USB_SERIAL_MODE) {
|
||||
// Receive
|
||||
uint32_t status = AUX2_SERIAL_USART->SR;
|
||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||
uint8_t data = AUX2_SERIAL_USART->DR;
|
||||
if (!(status & USART_FLAG_ERRORS)) {
|
||||
switch (aux2SerialMode) {
|
||||
case UART_MODE_DEBUG:
|
||||
cliReceiveData(&data, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
status = AUX2_SERIAL_USART->SR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Receive
|
||||
uint32_t status = AUX2_SERIAL_USART->SR;
|
||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||
uint8_t data = AUX2_SERIAL_USART->DR;
|
||||
UNUSED(data);
|
||||
if (!(status & USART_FLAG_ERRORS)) {
|
||||
#if defined(LUA) & !defined(CLI)
|
||||
if (luaRxFifo && aux2SerialMode == UART_MODE_LUA) {
|
||||
luaRxFifo->push(data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
status = AUX2_SERIAL_USART->SR;
|
||||
}
|
||||
stm32_usart_isr(&aux2USART, &aux2SerialCb);
|
||||
}
|
||||
|
||||
const etx_serial_driver_t Aux2SerialDriver = {
|
||||
.init = aux2SerialInit,
|
||||
.deinit = aux_serial_deinit,
|
||||
.sendByte = aux_serial_putc,
|
||||
.sendBuffer = aux_serial_send_buffer,
|
||||
.waitForTxCompleted = aux_wait_tx_completed,
|
||||
.getByte = aux_get_byte,
|
||||
.getBaudrate = nullptr,
|
||||
.setReceiveCb = aux2SetRxCb,
|
||||
.setBaudrateCb = nullptr,
|
||||
};
|
||||
|
||||
#endif // AUX2_SERIAL
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hal/serial_driver.h"
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
extern const etx_serial_driver_t AuxSerialDriver;
|
||||
#endif
|
||||
|
||||
#if defined(AUX2_SERIAL)
|
||||
extern const etx_serial_driver_t Aux2SerialDriver;
|
||||
#endif
|
||||
|
||||
@@ -80,26 +80,8 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && !defined(SIMU)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "usb_driver.h"
|
||||
|
||||
#if !defined(SIMU)
|
||||
#include "usbd_cdc_core.h"
|
||||
#include "usbd_msc_core.h"
|
||||
#include "usbd_hid_core.h"
|
||||
#include "usbd_usr.h"
|
||||
#include "usbd_desc.h"
|
||||
#include "usb_conf.h"
|
||||
#include "usbd_conf.h"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && !defined(SIMU)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SIMU)
|
||||
#include "../simu/simpgmspace.h"
|
||||
#endif
|
||||
|
||||
@@ -144,6 +144,7 @@ if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14)
|
||||
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_usart.c
|
||||
../../../../../serial.cpp
|
||||
../../../../../targets/common/arm/stm32/aux_serial_driver.cpp
|
||||
../../../../../targets/common/arm/stm32/stm32_usart_driver.cpp
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
|
||||
@@ -244,12 +244,9 @@ int main()
|
||||
#endif
|
||||
|
||||
delaysInit(); // needed for lcdInit()
|
||||
|
||||
#if defined(DEBUG) && defined(AUX_SERIAL)
|
||||
auxSerialInit(UART_MODE_DEBUG, 0); // default serial mode (None if DEBUG not defined)
|
||||
#endif
|
||||
#if defined(DEBUG) && defined(AUX2_SERIAL)
|
||||
aux2SerialInit(UART_MODE_DEBUG, 0); // default serial mode (None if DEBUG not defined)
|
||||
|
||||
#if defined(DEBUG)
|
||||
initSerialPorts();
|
||||
#endif
|
||||
|
||||
__enable_irq();
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "definitions.h"
|
||||
|
||||
void getCPUUniqueID(char * s);
|
||||
EXTERN_C(void getCPUUniqueID(char * s));
|
||||
|
||||
#define LEN_CPU_UID (3*8+2)
|
||||
|
||||
@@ -29,4 +30,4 @@ void getCPUUniqueID(char * s);
|
||||
extern const uint32_t cpu_uid[3];
|
||||
#else
|
||||
extern const uint32_t * cpu_uid;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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 "extmodule_driver.h"
|
||||
#include "stm32_pulse_driver.h"
|
||||
|
||||
#include "hal.h"
|
||||
#include "timers_driver.h"
|
||||
|
||||
static const stm32_pulse_timer_t extmoduleTimer = {
|
||||
.GPIOx = EXTMODULE_TX_GPIO,
|
||||
.GPIO_Pin = EXTMODULE_TX_GPIO_PIN,
|
||||
.GPIO_Alternate = EXTMODULE_TIMER_TX_GPIO_AF,
|
||||
.TIMx = EXTMODULE_TIMER,
|
||||
.TIM_Prescaler = __LL_TIM_CALC_PSC(EXTMODULE_TIMER_FREQ, 2000000),
|
||||
.TIM_Channel = EXTMODULE_TIMER_Channel,
|
||||
.TIM_IRQn = EXTMODULE_TIMER_IRQn,
|
||||
.DMAx = EXTMODULE_TIMER_DMA,
|
||||
.DMA_Stream = EXTMODULE_TIMER_DMA_STREAM_LL,
|
||||
.DMA_Channel = EXTMODULE_TIMER_DMA_CHANNEL,
|
||||
.DMA_IRQn = EXTMODULE_TIMER_DMA_STREAM_IRQn,
|
||||
};
|
||||
|
||||
// Make sure the timer channel is supported
|
||||
static_assert(__STM32_PULSE_IS_TIMER_CHANNEL_SUPPORTED(EXTMODULE_TIMER_Channel),
|
||||
"Unsupported timer channel");
|
||||
|
||||
// Make sure the DMA channel is supported
|
||||
static_assert(__STM32_PULSE_IS_DMA_STREAM_SUPPORTED(EXTMODULE_TIMER_DMA_STREAM_LL),
|
||||
"Unsupported DMA stream");
|
||||
|
||||
#if !defined(EXTMODULE_TIMER_DMA_IRQHandler)
|
||||
#error "Missing EXTMODULE_TIMER_DMA_IRQHandler definition"
|
||||
#endif
|
||||
|
||||
extern "C" void EXTMODULE_TIMER_DMA_IRQHandler()
|
||||
{
|
||||
stm32_pulse_dma_tc_isr(&extmoduleTimer);
|
||||
}
|
||||
|
||||
#if !defined(EXTMODULE_TIMER_IRQHandler)
|
||||
#error "Missing EXTMODULE_TIMER_IRQHandler definition"
|
||||
#endif
|
||||
|
||||
extern "C" void EXTMODULE_TIMER_IRQHandler()
|
||||
{
|
||||
stm32_pulse_tim_update_isr(&extmoduleTimer);
|
||||
}
|
||||
|
||||
void extmoduleStop()
|
||||
{
|
||||
EXTERNAL_MODULE_OFF();
|
||||
stm32_pulse_deinit(&extmoduleTimer);
|
||||
}
|
||||
|
||||
static void config_ppm_output(uint16_t ppm_delay, bool polarity)
|
||||
{
|
||||
// PPM generation principle:
|
||||
//
|
||||
// Hardware timer in PWM mode is used for PPM generation
|
||||
// Output is OFF if CNT<CCR1(delay) and ON if bigger
|
||||
// CCR1 register defines duration of pulse length and is constant
|
||||
// AAR register defines duration of each pulse, it is
|
||||
// updated after every pulse in Update interrupt handler.
|
||||
|
||||
stm32_pulse_config_output(&extmoduleTimer, !polarity, LL_TIM_OCMODE_PWM1,
|
||||
ppm_delay * 2);
|
||||
}
|
||||
|
||||
void extmodulePpmStart(uint16_t ppm_delay, bool polarity)
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
stm32_pulse_init(&extmoduleTimer);
|
||||
config_ppm_output(ppm_delay, polarity);
|
||||
}
|
||||
|
||||
void extmoduleSendNextFramePpm(void* pulses, uint16_t length,
|
||||
uint16_t ppm_delay, bool polarity)
|
||||
{
|
||||
if (!stm32_pulse_if_not_running_disable(&extmoduleTimer))
|
||||
return;
|
||||
|
||||
// Set polarity
|
||||
stm32_pulse_set_polarity(&extmoduleTimer, !polarity);
|
||||
|
||||
// Start DMA request and re-enable timer
|
||||
stm32_pulse_start_dma_req(&extmoduleTimer, pulses, length,
|
||||
LL_TIM_OCMODE_PWM1, ppm_delay * 2);
|
||||
}
|
||||
|
||||
#if defined(PXX1)
|
||||
void extmodulePxx1PulsesStart()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
stm32_pulse_config_output(&extmoduleTimer, false, LL_TIM_OCMODE_PWM1, 9 * 2);
|
||||
stm32_pulse_init(&extmoduleTimer);
|
||||
}
|
||||
|
||||
void extmoduleSendNextFramePxx1(const void* pulses, uint16_t length)
|
||||
{
|
||||
if (!stm32_pulse_if_not_running_disable(&extmoduleTimer)) return;
|
||||
|
||||
// Start DMA request and re-enable timer
|
||||
stm32_pulse_start_dma_req(&extmoduleTimer, pulses, length, LL_TIM_OCMODE_PWM1,
|
||||
9 * 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: polarity?
|
||||
void extmoduleSerialStart()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
stm32_pulse_init(&extmoduleTimer);
|
||||
stm32_pulse_config_output(&extmoduleTimer, true, LL_TIM_OCMODE_TOGGLE, 0);
|
||||
}
|
||||
|
||||
void extmoduleSendNextFrameSoftSerial(const void* pulses, uint16_t length, bool polarity)
|
||||
{
|
||||
if (!stm32_pulse_if_not_running_disable(&extmoduleTimer))
|
||||
return;
|
||||
|
||||
// Set polarity
|
||||
stm32_pulse_set_polarity(&extmoduleTimer, polarity);
|
||||
|
||||
// Start DMA request and re-enable timer
|
||||
stm32_pulse_start_dma_req(&extmoduleTimer, pulses, length, LL_TIM_OCMODE_TOGGLE, 0);
|
||||
}
|
||||
|
||||
// Delay based byte sending @ 57600 bps
|
||||
void extmoduleSendInvertedByte(uint8_t byte)
|
||||
{
|
||||
uint16_t time;
|
||||
uint32_t i;
|
||||
|
||||
__disable_irq();
|
||||
time = getTmr2MHz();
|
||||
LL_GPIO_SetOutputPin(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN);
|
||||
while ((uint16_t) (getTmr2MHz() - time) < 34) {
|
||||
// wait
|
||||
}
|
||||
time += 34;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (byte & 1) {
|
||||
LL_GPIO_ResetOutputPin(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN);
|
||||
}
|
||||
else {
|
||||
LL_GPIO_SetOutputPin(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN);
|
||||
}
|
||||
byte >>= 1 ;
|
||||
while ((uint16_t) (getTmr2MHz() - time) < 35) {
|
||||
// wait
|
||||
}
|
||||
time += 35 ;
|
||||
}
|
||||
LL_GPIO_ResetOutputPin(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN);
|
||||
__enable_irq(); // No need to wait for the stop bit to complete
|
||||
while ((uint16_t) (getTmr2MHz() - time) < 34) {
|
||||
// wait
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
void extmoduleStop();
|
||||
void extmodulePpmStart(uint16_t ppm_delay, bool polarity);
|
||||
|
||||
#if defined(PXX1)
|
||||
void extmodulePxx1PulsesStart();
|
||||
void extmoduleSendNextFramePxx1(const void* pulses, uint16_t length);
|
||||
#endif
|
||||
|
||||
// Soft serial on PPM pin
|
||||
void extmoduleSerialStart();
|
||||
|
||||
void extmoduleSendNextFramePpm(void* pulses, uint16_t length,
|
||||
uint16_t ppm_delay, bool polarity);
|
||||
|
||||
void extmoduleSendNextFrameSoftSerial(const void* pulses, uint16_t length,
|
||||
bool polarity = true);
|
||||
|
||||
// Bitbang serial
|
||||
void extmoduleSendInvertedByte(uint8_t byte);
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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 "extmodule_serial_driver.h"
|
||||
#include "board.h"
|
||||
|
||||
#if defined(EXTMODULE_USART)
|
||||
#include "stm32_usart_driver.h"
|
||||
|
||||
#include "io/frsky_pxx2.h"
|
||||
ModuleFifo extmoduleFifo;
|
||||
|
||||
static etx_serial_callbacks_t extmodule_driver = {
|
||||
nullptr, nullptr, nullptr
|
||||
};
|
||||
|
||||
void extmoduleFifoReceive(uint8_t data)
|
||||
{
|
||||
extmoduleFifo.push(data);
|
||||
}
|
||||
|
||||
void extmoduleFifoError()
|
||||
{
|
||||
extmoduleFifo.errors++;
|
||||
}
|
||||
|
||||
static const etx_serial_init extmoduleSerialParams = {
|
||||
.baudrate = 0,
|
||||
.parity = ETX_Parity_None,
|
||||
.stop_bits = ETX_StopBits_One,
|
||||
.word_length = ETX_WordLength_8,
|
||||
.rx_enable = true,
|
||||
.on_receive = extmoduleFifoReceive,
|
||||
.on_error = extmoduleFifoError,
|
||||
};
|
||||
|
||||
static const LL_GPIO_InitTypeDef extmoduleUSART_PinDef = {
|
||||
.Pin = EXTMODULE_TX_GPIO_PIN | EXTMODULE_RX_GPIO_PIN,
|
||||
.Mode = LL_GPIO_MODE_ALTERNATE,
|
||||
.Speed = LL_GPIO_SPEED_FREQ_LOW,
|
||||
.OutputType = LL_GPIO_OUTPUT_PUSHPULL,
|
||||
.Pull = LL_GPIO_PULL_UP,
|
||||
.Alternate = EXTMODULE_USART_GPIO_AF_LL,
|
||||
};
|
||||
|
||||
static const stm32_usart_t extmoduleUSART = {
|
||||
.USARTx = EXTMODULE_USART,
|
||||
.GPIOx = EXTMODULE_TX_GPIO,
|
||||
.pinInit = &extmoduleUSART_PinDef,
|
||||
.IRQn = EXTMODULE_USART_IRQn,
|
||||
.IRQ_Prio = EXTMODULE_USART_IRQ_PRIORITY,
|
||||
.txDMA = EXTMODULE_USART_TX_DMA,
|
||||
.txDMA_Stream = EXTMODULE_USART_TX_DMA_STREAM_LL,
|
||||
.txDMA_Channel = EXTMODULE_USART_TX_DMA_CHANNEL,
|
||||
.rxDMA = nullptr,
|
||||
.rxDMA_Stream = 0,
|
||||
.rxDMA_Channel = 0,
|
||||
};
|
||||
|
||||
static void* extmoduleSerialStart(const etx_serial_init* params)
|
||||
{
|
||||
if (!params) return nullptr;
|
||||
|
||||
extmodule_driver.on_receive = params->on_receive;
|
||||
extmodule_driver.on_error = params->on_error;
|
||||
|
||||
// UART config
|
||||
stm32_usart_init(&extmoduleUSART, params);
|
||||
extmoduleFifo.clear();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void extmoduleInvertedSerialStart(uint32_t baudrate)
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
etx_serial_init params(extmoduleSerialParams);
|
||||
params.baudrate = baudrate;
|
||||
extmoduleSerialStart(¶ms);
|
||||
}
|
||||
|
||||
#if defined(PXX1)
|
||||
void extmodulePxx1SerialStart()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
etx_serial_init params(extmoduleSerialParams);
|
||||
params.baudrate = EXTMODULE_PXX1_SERIAL_BAUDRATE;
|
||||
ExtmoduleSerialDriver.init(¶ms);
|
||||
}
|
||||
#endif
|
||||
|
||||
void extmoduleSerialStop(void*)
|
||||
{
|
||||
stm32_usart_deinit(&extmoduleUSART);
|
||||
|
||||
// reset callbacks
|
||||
extmodule_driver.on_receive = nullptr;
|
||||
extmodule_driver.on_error = nullptr;
|
||||
}
|
||||
|
||||
static void extmoduleSendByte(void*, uint8_t byte)
|
||||
{
|
||||
stm32_usart_send_byte(&extmoduleUSART, byte);
|
||||
}
|
||||
|
||||
static void extmoduleSendBuffer(void*, const uint8_t * data, uint8_t size)
|
||||
{
|
||||
if (size == 0) return;
|
||||
stm32_usart_send_buffer(&extmoduleUSART, data, size);
|
||||
}
|
||||
|
||||
static void extmoduleWaitForTxCompleted(void*)
|
||||
{
|
||||
stm32_usart_wait_for_tx_dma(&extmoduleUSART);
|
||||
}
|
||||
|
||||
const etx_serial_driver_t ExtmoduleSerialDriver = {
|
||||
.init = extmoduleSerialStart,
|
||||
.deinit = extmoduleSerialStop,
|
||||
.sendByte = extmoduleSendByte,
|
||||
.sendBuffer = extmoduleSendBuffer,
|
||||
.waitForTxCompleted = extmoduleWaitForTxCompleted,
|
||||
.getByte = nullptr,
|
||||
.getBaudrate = nullptr,
|
||||
.setReceiveCb = nullptr,
|
||||
.setBaudrateCb = nullptr,
|
||||
};
|
||||
|
||||
extern "C" void EXTMODULE_USART_IRQHandler(void)
|
||||
{
|
||||
stm32_usart_isr(&extmoduleUSART, &extmodule_driver);
|
||||
}
|
||||
|
||||
#endif // defined(EXTMODULE_USART)
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
#include "hal/serial_driver.h"
|
||||
|
||||
#define EXTMODULE_USART_IRQ_PRIORITY 6
|
||||
|
||||
// Callbacks using intmoduleFifo
|
||||
void extmoduleFifoReceive(uint8_t data);
|
||||
void extmoduleFifoError();
|
||||
|
||||
// void extmoduleSerialStart();
|
||||
// void extmoduleInvertedSerialStart(uint32_t baudrate);
|
||||
// void extmoduleSendBuffer(const uint8_t * data, uint8_t size);
|
||||
// void extmoduleSendNextFrame();
|
||||
|
||||
#if defined(PXX1)
|
||||
void extmodulePxx1SerialStart();
|
||||
#endif
|
||||
|
||||
extern const etx_serial_driver_t ExtmoduleSerialDriver;
|
||||
@@ -1,11 +1,31 @@
|
||||
set(CPU_FAMILY STM32)
|
||||
set(MCU cortex-m3)
|
||||
set(FPU_FLAGS "")
|
||||
set(STM32LIB_DIR ${THIRDPARTY_DIR}/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries)
|
||||
|
||||
# STM32 HAL/LL library
|
||||
set(STM32CUBE_DIR ${THIRDPARTY_DIR}/STM32F2xx_HAL_Driver)
|
||||
|
||||
add_library(stm32cube_ll OBJECT EXCLUDE_FROM_ALL
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_ll_gpio.c
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_ll_tim.c
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_ll_dma.c
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_ll_usart.c
|
||||
${STM32CUBE_DIR}/Src/stm32f2xx_ll_rcc.c
|
||||
)
|
||||
|
||||
target_compile_options(stm32cube_ll PRIVATE -DUSE_FULL_LL_DRIVER)
|
||||
target_include_directories(stm32cube_ll PRIVATE
|
||||
${STM32CUBE_DIR}/Inc
|
||||
${THIRDPARTY_DIR}/CMSIS/Device/ST/STM32F2xx/Include
|
||||
${THIRDPARTY_DIR}/CMSIS/Include)
|
||||
|
||||
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:stm32cube_ll>)
|
||||
|
||||
# StdPeriph library
|
||||
set(STM32LIB_DIR ${THIRDPARTY_DIR}/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries)
|
||||
include_directories(${STM32LIB_DIR}/STM32F2xx_StdPeriph_Driver/inc)
|
||||
include_directories(${STM32LIB_DIR}/CMSIS/Device/ST/STM32F2xx/Include)
|
||||
include_directories(${STM32LIB_DIR}/CMSIS/include)
|
||||
include_directories(${STM32LIB_DIR}/CMSIS/Include)
|
||||
|
||||
add_definitions(-DSTM32F2)
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
uint32_t SystemCoreClock = 120000000;
|
||||
|
||||
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
__I uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -1,8 +1,29 @@
|
||||
set(CPU_FAMILY STM32)
|
||||
set(MCU cortex-m4)
|
||||
set(FPU_FLAGS "-mfloat-abi=hard -mfpu=fpv4-sp-d16")
|
||||
set(STM32LIB_DIR ${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries)
|
||||
|
||||
# STM32 HAL/LL library
|
||||
set(STM32CUBE_DIR ${THIRDPARTY_DIR}/STM32F4xx_HAL_Driver)
|
||||
|
||||
add_library(stm32cube_ll OBJECT EXCLUDE_FROM_ALL
|
||||
${STM32CUBE_DIR}/Src/stm32f4xx_ll_gpio.c
|
||||
${STM32CUBE_DIR}/Src/stm32f4xx_ll_tim.c
|
||||
${STM32CUBE_DIR}/Src/stm32f4xx_ll_dma.c
|
||||
${STM32CUBE_DIR}/Src/stm32f4xx_ll_usart.c
|
||||
${STM32CUBE_DIR}/Src/stm32f4xx_ll_rcc.c
|
||||
)
|
||||
|
||||
target_compile_options(stm32cube_ll PRIVATE -DUSE_FULL_LL_DRIVER)
|
||||
target_include_directories(stm32cube_ll PRIVATE
|
||||
${STM32CUBE_DIR}/Inc
|
||||
${THIRDPARTY_DIR}/CMSIS/Device/ST/STM32F4xx/Include
|
||||
${THIRDPARTY_DIR}/CMSIS/Include)
|
||||
|
||||
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:stm32cube_ll>)
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:stm32cube_ll>)
|
||||
|
||||
# StdPeriph library
|
||||
set(STM32LIB_DIR ${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries)
|
||||
include_directories(${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/inc)
|
||||
include_directories(${STM32LIB_DIR}/CMSIS/Device/ST/STM32F4xx/Include)
|
||||
include_directories(${STM32LIB_DIR}/CMSIS/Include)
|
||||
|
||||
@@ -182,6 +182,7 @@
|
||||
uint32_t SystemCoreClock = 168000000;
|
||||
|
||||
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
__I uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -19,8 +19,12 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "mixer_scheduler.h"
|
||||
#include "board.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "heartbeat_driver.h"
|
||||
#include "timers_driver.h"
|
||||
|
||||
#if defined(INTMODULE_HEARTBEAT_GPIO)
|
||||
|
||||
@@ -79,9 +83,7 @@ void stop_intmodule_heartbeat()
|
||||
void check_intmodule_heartbeat()
|
||||
{
|
||||
if (EXTI_GetITStatus(INTMODULE_HEARTBEAT_EXTI_LINE) != RESET) {
|
||||
#if !defined(INTMODULE_USART)
|
||||
heartbeatCapture.timestamp = getTmr2MHz();
|
||||
#endif
|
||||
#if defined(DEBUG_LATENCY)
|
||||
heartbeatCapture.count++;
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
struct HeartbeatCapture {
|
||||
uint32_t timestamp;
|
||||
uint8_t valid;
|
||||
#if defined(DEBUG_LATENCY)
|
||||
uint32_t count;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern volatile HeartbeatCapture heartbeatCapture;
|
||||
|
||||
void init_intmodule_heartbeat();
|
||||
void check_intmodule_heartbeat();
|
||||
void stop_intmodule_heartbeat();
|
||||
@@ -19,217 +19,147 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "stm32_hal_ll.h"
|
||||
#include "intmodule_serial_driver.h"
|
||||
#include "stm32_usart_driver.h"
|
||||
#include "board.h"
|
||||
|
||||
#include "io/frsky_pxx2.h"
|
||||
ModuleFifo intmoduleFifo;
|
||||
|
||||
#if !defined(INTMODULE_DMA_STREAM)
|
||||
uint8_t * intmoduleTxBufferData;
|
||||
volatile uint8_t intmoduleTxBufferRemaining;
|
||||
static uint8_t * intmoduleTxBufferData;
|
||||
static volatile uint8_t intmoduleTxBufferRemaining;
|
||||
|
||||
uint8_t intmoduleTxBufferSend(uint8_t* data)
|
||||
{
|
||||
if (intmoduleTxBufferRemaining) {
|
||||
*data = *(intmoduleTxBufferData++);
|
||||
intmoduleTxBufferRemaining--;
|
||||
return true;
|
||||
}
|
||||
|
||||
// buffer is empty
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct etx_serial_driver {
|
||||
void (*on_receive)(uint8_t data);
|
||||
void (*on_error)();
|
||||
static etx_serial_callbacks_t intmodule_driver = {
|
||||
#if !defined(INTMODULE_DMA_STREAM)
|
||||
intmoduleTxBufferSend,
|
||||
#else
|
||||
nullptr,
|
||||
#endif
|
||||
nullptr, nullptr
|
||||
};
|
||||
|
||||
static etx_serial_driver intmodule_driver = { nullptr, nullptr };
|
||||
|
||||
// TODO: move this somewhere else
|
||||
static void intmoduleFifoReceive(uint8_t data)
|
||||
void intmoduleFifoReceive(uint8_t data)
|
||||
{
|
||||
intmoduleFifo.push(data);
|
||||
}
|
||||
|
||||
static void intmoduleFifoError()
|
||||
void intmoduleFifoError()
|
||||
{
|
||||
intmoduleFifo.errors++;
|
||||
}
|
||||
|
||||
etx_serial_init::etx_serial_init():
|
||||
baudrate(0),
|
||||
parity(USART_Parity_No),
|
||||
stop_bits(USART_StopBits_1),
|
||||
word_length(USART_WordLength_8b),
|
||||
rx_enable(false),
|
||||
// TODO: this should not be needed
|
||||
on_receive(intmoduleFifoReceive),
|
||||
on_error(intmoduleFifoError)
|
||||
{
|
||||
}
|
||||
static const LL_GPIO_InitTypeDef intmoduleUSART_PinDef = {
|
||||
.Pin = INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN,
|
||||
.Mode = LL_GPIO_MODE_ALTERNATE,
|
||||
.Speed = LL_GPIO_SPEED_FREQ_LOW,
|
||||
.OutputType = LL_GPIO_OUTPUT_PUSHPULL,
|
||||
.Pull = LL_GPIO_PULL_UP,
|
||||
.Alternate = INTMODULE_GPIO_AF_LL,
|
||||
};
|
||||
|
||||
static const stm32_usart_t intmoduleUSART = {
|
||||
.USARTx = INTMODULE_USART,
|
||||
.GPIOx = INTMODULE_GPIO,
|
||||
.pinInit = &intmoduleUSART_PinDef,
|
||||
.IRQn = INTMODULE_USART_IRQn,
|
||||
.IRQ_Prio = INTMODULE_USART_IRQ_PRIORITY,
|
||||
.txDMA = INTMODULE_DMA,
|
||||
.txDMA_Stream = INTMODULE_DMA_STREAM_LL,
|
||||
.txDMA_Channel = INTMODULE_DMA_CHANNEL,
|
||||
.rxDMA = nullptr,
|
||||
.rxDMA_Stream = 0,
|
||||
.rxDMA_Channel = 0,
|
||||
};
|
||||
|
||||
void intmoduleStop()
|
||||
{
|
||||
GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN);
|
||||
|
||||
#if defined(INTMODULE_DMA_STREAM)
|
||||
INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
#endif
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_Init(INTMODULE_GPIO, &GPIO_InitStructure);
|
||||
|
||||
USART_DeInit(INTMODULE_USART);
|
||||
|
||||
GPIO_ResetBits(INTMODULE_GPIO, INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN);
|
||||
stm32_usart_deinit(&intmoduleUSART);
|
||||
|
||||
// reset callbacks
|
||||
intmodule_driver.on_receive = nullptr;
|
||||
intmodule_driver.on_error = nullptr;
|
||||
}
|
||||
|
||||
void intmodulePxx1SerialStart()
|
||||
static void intmoduleStop(void* ctx)
|
||||
{
|
||||
etx_serial_init params;
|
||||
params.baudrate = INTMODULE_PXX1_SERIAL_BAUDRATE;
|
||||
intmoduleSerialStart(¶ms);
|
||||
(void)ctx;
|
||||
intmoduleStop();
|
||||
}
|
||||
|
||||
void intmoduleSerialStart(const etx_serial_init* params)
|
||||
void* intmoduleSerialStart(const etx_serial_init* params)
|
||||
{
|
||||
if (!params) return;
|
||||
|
||||
INTERNAL_MODULE_ON();
|
||||
if (!params) return nullptr;
|
||||
|
||||
// TODO: sanity check parameters
|
||||
// - the UART seems to block when initialised with baudrate = 0
|
||||
|
||||
// init callbacks
|
||||
intmodule_driver.on_receive = params->on_receive;
|
||||
intmodule_driver.on_error = params->on_error;
|
||||
|
||||
uint32_t baudrate = params->baudrate;
|
||||
|
||||
#if !defined(INTMODULE_DMA_STREAM)
|
||||
// IRQ based TX
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_USART_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
// rco: workaround for high baudrate not supported with
|
||||
// IRQ based TX.
|
||||
if (baudrate > 1870000) {
|
||||
TRACE("limiting baudrate to 1.87 MBit/s");
|
||||
baudrate = 1870000;
|
||||
}
|
||||
#endif
|
||||
|
||||
GPIO_PinAFConfig(INTMODULE_GPIO, INTMODULE_GPIO_PinSource_TX, INTMODULE_GPIO_AF);
|
||||
GPIO_PinAFConfig(INTMODULE_GPIO, INTMODULE_GPIO_PinSource_RX, INTMODULE_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(INTMODULE_GPIO, &GPIO_InitStructure);
|
||||
|
||||
USART_DeInit(INTMODULE_USART);
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
USART_InitStructure.USART_Parity = params->parity;
|
||||
USART_InitStructure.USART_StopBits = params->stop_bits;
|
||||
USART_InitStructure.USART_WordLength = params->word_length;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
|
||||
USART_Init(INTMODULE_USART, &USART_InitStructure);
|
||||
USART_Cmd(INTMODULE_USART, ENABLE);
|
||||
|
||||
if (params->rx_enable) {
|
||||
USART_ITConfig(INTMODULE_USART, USART_IT_RXNE, ENABLE);
|
||||
NVIC_SetPriority(INTMODULE_USART_IRQn, 6);
|
||||
NVIC_EnableIRQ(INTMODULE_USART_IRQn);
|
||||
}
|
||||
stm32_usart_init(&intmoduleUSART, params);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
|
||||
extern "C" void INTMODULE_USART_IRQHandler(void)
|
||||
{
|
||||
#if !defined(INTMODULE_DMA_STREAM)
|
||||
// Send
|
||||
if (USART_GetITStatus(INTMODULE_USART, USART_IT_TXE) != RESET) {
|
||||
if (intmoduleTxBufferRemaining) {
|
||||
USART_SendData(INTMODULE_USART, intmoduleTxBufferData[0]);
|
||||
intmoduleTxBufferData++;
|
||||
intmoduleTxBufferRemaining--;
|
||||
}
|
||||
else {
|
||||
USART_ITConfig(INTMODULE_USART, USART_IT_TXE, DISABLE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Receive
|
||||
uint32_t status = INTMODULE_USART->SR;
|
||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||
uint8_t data = INTMODULE_USART->DR;
|
||||
if (status & USART_FLAG_ERRORS) {
|
||||
if (intmodule_driver.on_error)
|
||||
intmodule_driver.on_error();
|
||||
}
|
||||
else {
|
||||
if (intmodule_driver.on_receive)
|
||||
intmodule_driver.on_receive(data);
|
||||
}
|
||||
status = INTMODULE_USART->SR;
|
||||
}
|
||||
stm32_usart_isr(&intmoduleUSART, &intmodule_driver);
|
||||
}
|
||||
|
||||
void intmoduleSendByte(uint8_t byte)
|
||||
void intmoduleSendByte(void* ctx, uint8_t byte)
|
||||
{
|
||||
while (!(INTMODULE_USART->SR & USART_SR_TXE));
|
||||
USART_SendData(INTMODULE_USART, byte);
|
||||
(void)ctx;
|
||||
stm32_usart_send_byte(&intmoduleUSART, byte);
|
||||
}
|
||||
|
||||
void intmoduleSendBuffer(const uint8_t * data, uint8_t size)
|
||||
void intmoduleSendBuffer(void* ctx, const uint8_t * data, uint8_t size)
|
||||
{
|
||||
(void)ctx;
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
#if defined(INTMODULE_DMA_STREAM)
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
DMA_DeInit(INTMODULE_DMA_STREAM);
|
||||
DMA_InitStructure.DMA_Channel = INTMODULE_DMA_CHANNEL;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&INTMODULE_USART->DR);
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(data);
|
||||
DMA_InitStructure.DMA_BufferSize = size;
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(INTMODULE_DMA_STREAM, &DMA_InitStructure);
|
||||
DMA_Cmd(INTMODULE_DMA_STREAM, ENABLE);
|
||||
USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE);
|
||||
#else
|
||||
#if !defined(INTMODULE_DMA_STREAM)
|
||||
intmoduleTxBufferData = (uint8_t *)data;
|
||||
intmoduleTxBufferRemaining = size;
|
||||
USART_ITConfig(INTMODULE_USART, USART_IT_TXE, ENABLE);
|
||||
#endif
|
||||
stm32_usart_send_buffer(&intmoduleUSART, data, size);
|
||||
}
|
||||
|
||||
void intmoduleWaitForTxCompleted()
|
||||
void intmoduleWaitForTxCompleted(void* ctx)
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
(void)ctx;
|
||||
#if defined(INTMODULE_DMA_STREAM)
|
||||
if (DMA_GetCmdStatus(INTMODULE_DMA_STREAM) == ENABLE) {
|
||||
while(DMA_GetFlagStatus(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC) == RESET);
|
||||
DMA_ClearFlag(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC);
|
||||
}
|
||||
stm32_usart_wait_for_tx_dma(&intmoduleUSART);
|
||||
#else
|
||||
while (intmoduleTxBufferRemaining > 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
const etx_serial_driver_t IntmoduleSerialDriver = {
|
||||
.init = intmoduleSerialStart,
|
||||
.deinit = intmoduleStop,
|
||||
.sendByte = intmoduleSendByte,
|
||||
.sendBuffer = intmoduleSendBuffer,
|
||||
.waitForTxCompleted = intmoduleWaitForTxCompleted,
|
||||
.getByte = nullptr,
|
||||
.getBaudrate = nullptr,
|
||||
.setReceiveCb = nullptr,
|
||||
.setBaudrateCb = nullptr,
|
||||
};
|
||||
|
||||
@@ -22,22 +22,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hal/serial_driver.h"
|
||||
|
||||
struct etx_serial_init {
|
||||
uint32_t baudrate;
|
||||
uint16_t parity;
|
||||
uint16_t stop_bits;
|
||||
uint16_t word_length;
|
||||
bool rx_enable;
|
||||
void (*on_receive)(uint8_t data);
|
||||
void (*on_error)();
|
||||
#define INTMODULE_USART_IRQ_PRIORITY 6
|
||||
|
||||
etx_serial_init();
|
||||
};
|
||||
// Callbacks using intmoduleFifo
|
||||
void intmoduleFifoReceive(uint8_t data);
|
||||
void intmoduleFifoError();
|
||||
|
||||
void intmoduleSerialStart(const etx_serial_init* params);
|
||||
void intmoduleSerialStop();
|
||||
|
||||
void intmoduleSendByte(uint8_t byte);
|
||||
void intmoduleSendBuffer(const uint8_t* data, uint8_t size);
|
||||
void intmoduleWaitForTxCompleted();
|
||||
extern const etx_serial_driver_t IntmoduleSerialDriver;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user