diff --git a/DONATIONS.txt b/DONATIONS.txt
index 18f2aefd8..0105cfd13 100644
--- a/DONATIONS.txt
+++ b/DONATIONS.txt
@@ -26,7 +26,6 @@ Chris Guy
Adrien Gravouille
Thomas Black
Marc Lucht
-Michel Baily
Zdenek Trojanek
Martin Hotar
Stefan Grundevik
@@ -113,7 +112,6 @@ Erhard Werner
Stig Jøran Moen
Keith Hertzog
Christophe Dauvergne
-Michel Baily
Tauno Rautakorpi
Sven Assmus
Paul Dittman
@@ -417,7 +415,6 @@ Andrea Montefusco
Paul Luby
Donald L Webster
Kenneth Frehafer
-Peter McHenry
Matthias Hase
Markus Wolf
Andrew Fazio
@@ -588,7 +585,6 @@ Dietmar Drees
Jürgen Monden
David Morgan
Andrew Fernie
-Michel Baily
Donald Burke
Ronald Donker
Fredie Singh
@@ -837,3 +833,20 @@ Jay Warren
Marian Matej
Alastair Smith
Timothy Senecal
+Dietmar Drees
+Bruce Jones
+Adil Busaidy
+Herman Hofman
+Jean Paul Michel
+Peter McHenry
+Julien lecoquierre
+Jean-Marie Clay
+Robert Nicoll
+Dan Nixon
+Ewald Moehring
+Giovanni Carnesecchi
+Paul Dumsday
+Tadeusz Adamowski
+Andrew Newton
+Neil Horne
+Kerstin Appelqvist
diff --git a/companion/releasenotes.txt b/companion/releasenotes.txt
index 4e8071e95..fdd0c0b1e 100644
--- a/companion/releasenotes.txt
+++ b/companion/releasenotes.txt
@@ -1,4 +1,14 @@
-
Version 2.1.4 /
+Version 2.1.6 / 2015-11-11
+[Taranis]
+
+Telemetry custom screen changes didn't emit modified signal (#3029 )
+Hide D8/LR12 when eu firmware option is selected
+
+
+
+Version 2.1.5 / 2015-11-05
+
+Notice: version 2.1.4 was skipped by the OpenTX team to avoid confusion with FrSky's release of OpenTX 2.1.4
Fixed: changing any setting on the telemetry panel does not set the file as being modified (#2875 )
@@ -11,10 +21,17 @@
Fixed wrong import of Logical switches from OpenTX 2.0.x version (#2942 )
Fixed a problem with updates path on Windows (#2876 )
Edge representation unified (changed from "no release" to "instant") (#2837 )
+Added channel names on failsafe sliders (#3021 )
+Corrected failsafe mapping when using Custom failsafe mode, D16 protocol and channel range different from from 1-8.
+ Users with such setups are advised to re-check their failsafe settings (#2975 )
+Various texts and translations corrections
+Various small bug-fixes: #2994 ,
+ #3016 ,
+ #3012
+
-
Version 2.1.3 / 2015-09-09
diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt
index d090613a7..8b46c7b0f 100644
--- a/companion/src/CMakeLists.txt
+++ b/companion/src/CMakeLists.txt
@@ -103,6 +103,11 @@ ELSE( )
LINK_DIRECTORIES( /usr/local/lib )
ENDIF( )
+IF( MSVC )
+ MESSAGE( STATUS "Adding include C:/Programs/dirent/include for dirent.h" )
+ INCLUDE_DIRECTORIES( C:/Programs/dirent/include )
+ENDIF( )
+
set(RADIO_SRC_DIRECTORY ${PROJECT_SOURCE_DIR}/../../radio/src)
set(SIMU_SRC_DIRECTORY ${PROJECT_SOURCE_DIR}/simulation)
set(COMPANION_SRC_DIRECTORY ${PROJECT_SOURCE_DIR})
@@ -274,7 +279,6 @@ NOW(TIME)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/translations.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc @ONLY)
-CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/firmwares/opentx/stamp-opentx.h.in ${CMAKE_CURRENT_BINARY_DIR}/stamp-opentx.h @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/companion.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/companion.desktop @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/simulator.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/simulator.desktop @ONLY)
@@ -446,7 +450,11 @@ ENDIF()
SET(CPACK_PACKAGE_NAME "companion${C9X_NAME_SUFFIX}")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Models and settings editor for the OpenTx open source firmware")
string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_PACKAGE_NAME_LOWERCASE)
-SET( CPACK_STRIP_FILES TRUE )
+
+# The file stripping is deliberately disabled, with the stripped file we get
+# very poor trace-backs from the users when they report Companion crash
+SET(CPACK_STRIP_FILES FALSE)
+
find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
if(DPKG_PROGRAM)
SET(CPACK_GENERATOR "DEB")
diff --git a/companion/src/apppreferencesdialog.ui b/companion/src/apppreferencesdialog.ui
index 60f31a918..7975a3253 100644
--- a/companion/src/apppreferencesdialog.ui
+++ b/companion/src/apppreferencesdialog.ui
@@ -627,7 +627,7 @@ Mode 4:
-
- Open Folder
+ Select Folder
@@ -637,7 +637,7 @@ Mode 4:
The profile specific folder, if set, will override general Backup folder
- Open Folder
+ Select Folder
@@ -854,7 +854,7 @@ Mode 4:
-
- Open Folder
+ Select Folder
@@ -874,14 +874,14 @@ Mode 4:
-
- Find Executable
+ Select Executable
-
- Open Folder
+ Select Folder
@@ -1001,7 +1001,7 @@ Mode 4:
-
- Open Folder
+ Select Folder
false
diff --git a/companion/src/companion.cpp b/companion/src/companion.cpp
index a60b19fea..0d62fdf3a 100644
--- a/companion/src/companion.cpp
+++ b/companion/src/companion.cpp
@@ -156,7 +156,8 @@ int main(int argc, char *argv[])
delete splash;
delete mainWin;
- unregisterFirmwares();
+ unregisterSimulators();
+ unregisterOpenTxFirmwares();
unregisterEEpromInterfaces();
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
diff --git a/companion/src/eeprominterface.cpp b/companion/src/eeprominterface.cpp
index e619bd4b6..a4a483d16 100644
--- a/companion/src/eeprominterface.cpp
+++ b/companion/src/eeprominterface.cpp
@@ -783,7 +783,7 @@ QString CustomFunctionData::funcToString() const
else if (func == FuncPlayScript)
return QObject::tr("Play Script");
else if (func == FuncLogs)
- return QObject::tr("Start Logs");
+ return QObject::tr("SD Logs");
else if (func == FuncVolume)
return QObject::tr("Volume");
else if (func == FuncBacklight)
@@ -1628,13 +1628,6 @@ QList firmwares;
Firmware * default_firmware_variant;
Firmware * current_firmware_variant;
-void unregisterFirmwares()
-{
- foreach (Firmware * f, firmwares) {
- delete f;
- }
-}
-
void ShowEepromErrors(QWidget *parent, const QString &title, const QString &mainMessage, unsigned long errorsFound)
{
std::bitset errors((unsigned long long)errorsFound);
diff --git a/companion/src/eeprominterface.h b/companion/src/eeprominterface.h
index 348cc7a39..129bd57c5 100644
--- a/companion/src/eeprominterface.h
+++ b/companion/src/eeprominterface.h
@@ -755,6 +755,22 @@ enum TelemetryCurrentSources {
TELEMETRY_CURRENT_SOURCE_FAS
};
+enum UartModes {
+ UART_MODE_NONE,
+ UART_MODE_TELEMETRY_MIRROR,
+ UART_MODE_TELEMETRY,
+ UART_MODE_SBUS_TRAINER,
+ UART_MODE_DEBUG
+};
+
+enum TrainerMode {
+ TRAINER_MODE_MASTER_TRAINER_JACK,
+ TRAINER_MODE_SLAVE,
+ TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE,
+ TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE,
+ TRAINER_MODE_MASTER_BATTERY_COMPARTMENT,
+};
+
class FrSkyData {
public:
FrSkyData() { clear(); }
@@ -1284,7 +1300,6 @@ enum Capability {
HasExpoNames,
HasNoExpo,
HasMixerNames,
- HasChNames,
HasCvNames,
HasPxxCountry,
HasPPMStart,
@@ -1376,8 +1391,6 @@ class EEPROMInterface
virtual int getSize(const GeneralSettings &) = 0;
- virtual int isAvailable(PulsesProtocol proto, int port=0) = 0;
-
virtual const int getEEpromSize() = 0;
virtual const int getMaxModels() = 0;
@@ -1489,7 +1502,7 @@ inline void applyStickModeToModel(ModelData &model, unsigned int mode)
void registerEEpromInterfaces();
void unregisterEEpromInterfaces();
void registerOpenTxFirmwares();
-void unregisterFirmwares();
+void unregisterOpenTxFirmwares();
enum EepromLoadErrors {
NO_ERROR,
@@ -1613,6 +1626,8 @@ class Firmware {
virtual bool isTelemetrySourceAvailable(int source) = 0;
+ virtual int isAvailable(PulsesProtocol proto, int port=0) = 0;
+
public:
QList languages;
QList ttslanguages;
diff --git a/companion/src/file.cpp b/companion/src/file.cpp
index d633fa4f8..c1c613f19 100644
--- a/companion/src/file.cpp
+++ b/companion/src/file.cpp
@@ -121,20 +121,16 @@ PACK(struct EepromFileHeader
bool RleFile::searchFat()
{
- int bestFatIndex = -1;
+ eepromFatHeader = NULL;
+ uint32_t bestFatIndex = 0;
for (int i=0; imark == EEPROM_MARK && (int)header->index >= bestFatIndex) {
- bestFatIndex = i;
+ eepromFatHeader = header;
+ bestFatIndex = header->index;
}
}
- if (bestFatIndex >= 0) {
- eepromFatHeader = (EepromHeader *)(eeprom+bestFatIndex*EEPROM_FAT_SIZE);;
- return true;
- }
- else {
- return false;
- }
+ return (eepromFatHeader != NULL);
}
bool RleFile::EeFsOpen(uint8_t *eeprom, int size, BoardEnum board)
diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp
index a62d97025..0afbd9991 100644
--- a/companion/src/firmwares/opentx/opentxeeprom.cpp
+++ b/companion/src/firmwares/opentx/opentxeeprom.cpp
@@ -392,8 +392,8 @@ template
class SwitchField: public ConversionField< SignedField > {
public:
SwitchField(RawSwitch & sw, BoardEnum board, unsigned int version, unsigned long flags=0):
- ConversionField< SignedField >(_switch, SwitchesConversionTable::getInstance(board, version, flags), "Switch",
- "Switch "+ sw.toString()+" cannot be exported on this board!"),
+ ConversionField< SignedField >(_switch, SwitchesConversionTable::getInstance(board, version, flags), QObject::tr("Switch").toAscii(),
+ QObject::tr("Switch ").toAscii()+ sw.toString()+ QObject::tr(" cannot be exported on this board!").toAscii()),
sw(sw),
_switch(0)
{
diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp
index b6fcfc331..295c6ac64 100644
--- a/companion/src/firmwares/opentx/opentxinterface.cpp
+++ b/companion/src/firmwares/opentx/opentxinterface.cpp
@@ -586,8 +586,6 @@ int OpenTxFirmware::getCapability(const Capability capability)
return (IS_TARANIS(board) ? 10 : 6);
case GvarsName:
return (IS_9X(board) ? 0 : 6);
- case HasChNames:
- return (IS_TARANIS(board) ? 1 : 0);
case GvarsInCS:
case HasFAIMode:
return 1;
@@ -807,7 +805,7 @@ int OpenTxFirmware::getCapability(const Capability capability)
case MixersMonitor:
return id.contains("mixersmon") ? 1 : 0;
case HasBatMeterRange:
- return (IS_TARANIS(board) ? true : false);
+ return (IS_TARANIS(board) ? true : id.contains("battgraph"));
case DangerousFunctions:
return id.contains("danger") ? 1 : 0;
default:
@@ -826,7 +824,7 @@ bool OpenTxFirmware::isTelemetrySourceAvailable(int source)
return true;
}
-int OpenTxEepromInterface::isAvailable(PulsesProtocol proto, int port)
+int OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
{
if (IS_TARANIS(board)) {
switch (port) {
@@ -834,9 +832,12 @@ int OpenTxEepromInterface::isAvailable(PulsesProtocol proto, int port)
switch (proto) {
case PULSES_OFF:
case PULSES_PXX_XJT_X16:
+ return 1;
case PULSES_PXX_XJT_D8:
case PULSES_PXX_XJT_LR12:
- return 1;
+ return id.contains("eu") ? 0 : 1;
+ case PULSES_PPM:
+ return id.contains("internalppm") ? 1 : 0;
default:
return 0;
}
@@ -903,7 +904,7 @@ int OpenTxEepromInterface::isAvailable(PulsesProtocol proto, int port)
case PULSES_DSMX:
case PULSES_LP45:
case PULSES_DSM2:
- case PULSES_PXX_DJT:
+ // case PULSES_PXX_DJT: // Unavailable for now
case PULSES_PPM16:
case PULSES_PPMSIM:
return 1;
@@ -1452,3 +1453,9 @@ void registerOpenTxFirmwares()
current_firmware_variant = default_firmware_variant;
}
+void unregisterOpenTxFirmwares()
+{
+ foreach (Firmware * f, firmwares) {
+ delete f;
+ }
+}
diff --git a/companion/src/firmwares/opentx/opentxinterface.h b/companion/src/firmwares/opentx/opentxinterface.h
index e7db6737a..41c1bf6a2 100644
--- a/companion/src/firmwares/opentx/opentxinterface.h
+++ b/companion/src/firmwares/opentx/opentxinterface.h
@@ -45,8 +45,6 @@ class OpenTxEepromInterface : public EEPROMInterface
virtual int getSize(const GeneralSettings &);
- virtual int isAvailable(PulsesProtocol proto, int port=0);
-
protected:
const char * getName();
@@ -123,6 +121,8 @@ class OpenTxFirmware: public Firmware {
virtual bool isTelemetrySourceAvailable(int source);
+ virtual int isAvailable(PulsesProtocol proto, int port=0);
+
protected:
QString getFirmwareBaseUrl();
@@ -130,5 +130,6 @@ class OpenTxFirmware: public Firmware {
};
void registerOpenTxFirmwares();
+void unregisterOpenTxFirmwares();
#endif
diff --git a/companion/src/firmwares/opentx/simulator/CMakeLists.txt b/companion/src/firmwares/opentx/simulator/CMakeLists.txt
index f0ebe02cb..d2d2a2def 100644
--- a/companion/src/firmwares/opentx/simulator/CMakeLists.txt
+++ b/companion/src/firmwares/opentx/simulator/CMakeLists.txt
@@ -31,9 +31,9 @@ add_custom_target(commondeps
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${RADIO_SRC_DIRECTORY}/stamp-opentx.h)
add_custom_target(lua_exports
- COMMAND make PCB=TARANIS lua_exports_taranis.inc
- COMMAND make PCB=FLAMENCO lua_exports_flamenco.inc
- COMMAND make PCB=HORUS lua_exports_horus.inc
+ COMMAND make PCB=TARANIS lua/lua_exports_taranis.inc
+ COMMAND make PCB=FLAMENCO lua/lua_exports_flamenco.inc
+ COMMAND make PCB=HORUS lua/lua_exports_horus.inc
DEPENDS ${RADIO_SRC_DIRECTORY}/myeeprom.h
WORKING_DIRECTORY ${RADIO_SRC_DIRECTORY}
)
diff --git a/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp b/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp
index 68b002b1d..706b0e39d 100644
--- a/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp
+++ b/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp
@@ -387,7 +387,10 @@ namespace NAMESPACE {
#endif
#if defined(LUA)
-#include "radio/src/lua_api.cpp"
+#include "radio/src/lua/interface.cpp"
+#include "radio/src/lua/api_general.cpp"
+#include "radio/src/lua/api_lcd.cpp"
+#include "radio/src/lua/api_model.cpp"
#include "radio/src/thirdparty/Lua/src/lapi.c"
#include "radio/src/thirdparty/Lua/src/lcode.c"
#include "radio/src/thirdparty/Lua/src/lctype.c"
diff --git a/companion/src/firmwares/opentx/stamp-opentx.h.in b/companion/src/firmwares/opentx/stamp-opentx.h.in
deleted file mode 100644
index 31e946aa4..000000000
--- a/companion/src/firmwares/opentx/stamp-opentx.h.in
+++ /dev/null
@@ -1,4 +0,0 @@
-// Automatically generated file (CMake) - do not edit
-#define DATE_STR "@DATE@"
-#define TIME_STR "@TIME@"
-#define VERS_STR "@VERSION@"
diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp
index 44dde3f44..ee5ce7715 100644
--- a/companion/src/modeledit/setup.cpp
+++ b/companion/src/modeledit/setup.cpp
@@ -137,6 +137,9 @@ ModulePanel::ModulePanel(QWidget *parent, ModelData & model, ModuleData & module
QString label;
if (moduleIdx < 0) {
label = tr("Trainer Port");
+ if (generalSettings.hw_uartMode != UART_MODE_SBUS_TRAINER) {
+ ui->trainerMode->setItemData(TRAINER_MODE_MASTER_BATTERY_COMPARTMENT, 0, Qt::UserRole - 1);
+ }
ui->trainerMode->setCurrentIndex(model.trainerMode);
if (!IS_TARANIS(firmware->getBoard())) {
ui->label_trainerMode->hide();
@@ -168,7 +171,7 @@ ModulePanel::ModulePanel(QWidget *parent, ModelData & model, ModuleData & module
// The protocols available on this board
for (int i=0; iisAvailable((PulsesProtocol)i, moduleIdx)) {
+ if (firmware->isAvailable((PulsesProtocol)i, moduleIdx)) {
ui->protocol->addItem(ModelPrinter::printModuleProtocol(i), (QVariant)i);
if (i == module.protocol) ui->protocol->setCurrentIndex(ui->protocol->count()-1);
}
@@ -190,12 +193,12 @@ ModulePanel::ModulePanel(QWidget *parent, ModelData & model, ModuleData & module
spinbox->setDecimals(1);
label->setProperty("index", i);
spinbox->setProperty("index", i);
- failsafeSpins << spinbox;
ui->failsafesLayout->addWidget(label, 3*(i/8), i%8, Qt::AlignHCenter);
ui->failsafesLayout->addWidget(combo, 1+3*(i/8), i%8, Qt::AlignHCenter);
ui->failsafesLayout->addWidget(spinbox, 2+3*(i/8), i%8, Qt::AlignHCenter);
failsafeGroups[i].combo = combo;
failsafeGroups[i].spinbox = spinbox;
+ failsafeGroups[i].label = label;
updateFailsafe(i);
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onFailsafeComboIndexChanged(int)));
connect(spinbox, SIGNAL(valueChanged(double)), this, SLOT(onFailsafeSpinChanged(double)));
@@ -234,7 +237,8 @@ void ModulePanel::update()
case PULSES_PXX_XJT_LR12:
case PULSES_PXX_DJT:
mask |= MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
- if ((protocol==PULSES_PXX_XJT_X16) || (protocol==PULSES_PXX_XJT_LR12)) mask |= MASK_FAILSAFES | MASK_RX_NUMBER;
+ if (protocol==PULSES_PXX_XJT_X16) mask |= MASK_FAILSAFES | MASK_RX_NUMBER;
+ if (protocol==PULSES_PXX_XJT_LR12) mask |= MASK_RX_NUMBER;
break;
case PULSES_LP45:
case PULSES_DSM2:
@@ -255,15 +259,8 @@ void ModulePanel::update()
}
}
else if (IS_TARANIS(firmware->getBoard())) {
- switch(model->trainerMode) {
- case TRAINER_MASTER_JACK:
- break;
- case TRAINER_SLAVE_JACK:
- mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
- break;
- default:
- mask |= MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
- break;
+ if (model->trainerMode == TRAINER_SLAVE_JACK) {
+ mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
}
}
else if (model->trainerMode != TRAINER_MASTER_JACK) {
@@ -306,6 +303,17 @@ void ModulePanel::update()
ui->failsafeMode->setVisible(mask & MASK_FAILSAFES);
ui->failsafeMode->setCurrentIndex(module.failsafeMode);
ui->failsafesFrame->setEnabled(module.failsafeMode == FAILSAFE_CUSTOM);
+ if (firmware->getCapability(ChannelsName) > 0) {
+ for(int i=0; ilimitData[i+module.channelsStart].name).trimmed();
+ if (!name.isEmpty()) {
+ failsafeGroups[i].label->setText(name);
+ }
+ else {
+ failsafeGroups[i].label->setText(QString::number(i+1));
+ }
+ }
+ }
}
else {
mask = 0;
@@ -313,6 +321,11 @@ void ModulePanel::update()
ui->failsafesLayoutLabel->setVisible(mask & MASK_FAILSAFES);
ui->failsafesFrame->setVisible(mask & MASK_FAILSAFES);
+
+ if (mask & MASK_CHANNELS_RANGE) {
+ ui->channelsStart->setMaximum(32 - ui->channelsCount->value());
+ ui->channelsCount->setMaximum(qMin(16, 32-ui->channelsStart->value()));
+ }
}
void ModulePanel::on_trainerMode_currentIndexChanged(int index)
@@ -656,6 +669,7 @@ SetupPanel::SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & gen
if (firmware->getCapability(ModelTrainerEnable)) {
modules[C9X_NUM_MODULES] = new ModulePanel(this, model, model.moduleData[C9X_NUM_MODULES], generalSettings, firmware, -1);
ui->modulesLayout->addWidget(modules[C9X_NUM_MODULES]);
+ connect(modules[C9X_NUM_MODULES], SIGNAL(modified()), this, SLOT(onChildModified()));
}
disableMouseScrolling();
diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h
index 2f732be1a..0e4c9d7f8 100644
--- a/companion/src/modeledit/setup.h
+++ b/companion/src/modeledit/setup.h
@@ -45,6 +45,7 @@ class ModulePanel : public ModelPanel
struct ChannelFailsafeWidgetsGroup {
QComboBox * combo;
QDoubleSpinBox * spinbox;
+ QLabel * label;
};
Q_OBJECT
@@ -75,7 +76,6 @@ class ModulePanel : public ModelPanel
ModuleData & module;
int moduleIdx;
Ui::Module *ui;
- QVector failsafeSpins;
ChannelFailsafeWidgetsGroup failsafeGroups[maxChannels];
};
diff --git a/companion/src/modeledit/setup_module.ui b/companion/src/modeledit/setup_module.ui
index df8e420e0..ed8c4c0c3 100644
--- a/companion/src/modeledit/setup_module.ui
+++ b/companion/src/modeledit/setup_module.ui
@@ -67,12 +67,12 @@
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
- 6
-
0
+
+ 6
+
-
@@ -353,7 +353,7 @@
- 1
+ 4
16
diff --git a/companion/src/modeledit/telemetry.cpp b/companion/src/modeledit/telemetry.cpp
index 72722a7dc..5966a5f3d 100644
--- a/companion/src/modeledit/telemetry.cpp
+++ b/companion/src/modeledit/telemetry.cpp
@@ -745,6 +745,7 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware);
ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i+1));
telemetryCustomScreens[i] = tab;
+ connect(tab, SIGNAL(modified()), this, SLOT(onModified()));
}
disableMouseScrolling();
diff --git a/companion/src/modelprinter.cpp b/companion/src/modelprinter.cpp
index fd4c851ab..31d73dbdb 100644
--- a/companion/src/modelprinter.cpp
+++ b/companion/src/modelprinter.cpp
@@ -57,7 +57,7 @@ QString ModelPrinter::printChannelName(int idx)
QString ModelPrinter::printOutputName(int idx)
{
QString name = QString(model.limitData[idx].name).trimmed();
- if (firmware->getCapability(HasChNames) && !name.isEmpty()) {
+ if (firmware->getCapability(ChannelsName) > 0 && !name.isEmpty()) {
return name;
}
else {
@@ -313,7 +313,7 @@ QString ModelPrinter::printInputLine(const ExpoData & input)
QString ModelPrinter::printMixerName(int curDest)
{
QString str = printChannelName(curDest-1) + " ";
- if (firmware->getCapability(HasChNames)) {
+ if (firmware->getCapability(ChannelsName) > 0) {
QString name = model.limitData[curDest-1].name;
if (!name.isEmpty()) {
name = QString("(") + name + QString(")");
diff --git a/companion/src/mountlist.cpp b/companion/src/mountlist.cpp
index 5c1408c9e..e041a5fe0 100644
--- a/companion/src/mountlist.cpp
+++ b/companion/src/mountlist.cpp
@@ -922,4 +922,19 @@ read_file_system_list (bool need_fs_type)
}
}
+void free_file_system_list(struct mount_entry * mount_list)
+{
+ struct mount_entry * me;
+ while (mount_list)
+ {
+ me = mount_list->me_next;
+ free (mount_list->me_devname);
+ free (mount_list->me_mountdir);
+ if (mount_list->me_type_malloced)
+ free (mount_list->me_type);
+ free (mount_list);
+ mount_list = me;
+ }
+}
+
#endif
diff --git a/companion/src/mountlist.h b/companion/src/mountlist.h
index 8d8c3cbf4..a6caad729 100644
--- a/companion/src/mountlist.h
+++ b/companion/src/mountlist.h
@@ -49,4 +49,6 @@ struct mount_entry
struct mount_entry *read_file_system_list (bool need_fs_type);
+void free_file_system_list(struct mount_entry * mount_list);
+
#endif
diff --git a/companion/src/multimodelprinter.cpp b/companion/src/multimodelprinter.cpp
index c559967f7..2b126282e 100644
--- a/companion/src/multimodelprinter.cpp
+++ b/companion/src/multimodelprinter.cpp
@@ -270,7 +270,7 @@ QString MultiModelPrinter::printLimits()
columns.append("" \
"" \
" " + tr("Channel") + " " \
- " " + (firmware->getCapability(HasChNames) ? tr("Name") : "") + " " \
+ " " + (firmware->getCapability(ChannelsName) > 0 ? tr("Name") : "") + " " \
" " + tr("Offset") + " " \
" " + tr("Min") + " " \
" " + tr("Max") + " " \
diff --git a/companion/src/radiointerface.cpp b/companion/src/radiointerface.cpp
index 47b37668e..1626523df 100644
--- a/companion/src/radiointerface.cpp
+++ b/companion/src/radiointerface.cpp
@@ -411,7 +411,8 @@ QString findMassstoragePath(const QString &filename)
}
#else
struct mount_entry *entry;
- entry = read_file_system_list(true);
+ struct mount_entry *firstEntry;
+ firstEntry = entry = read_file_system_list(true);
while (entry != NULL) {
if (!drives.contains(entry->me_devname)) {
drives.append(entry->me_devname);
@@ -426,11 +427,13 @@ QString findMassstoragePath(const QString &filename)
#else
if (QFile::exists(eepromfile)) {
#endif
+ free_file_system_list(firstEntry);
return eepromfile;
}
}
entry = entry->me_next;
}
+ free_file_system_list(firstEntry);
#endif
return QString();
diff --git a/companion/src/simulation/simulatorinterface.cpp b/companion/src/simulation/simulatorinterface.cpp
index cfb0fe358..641ce188b 100644
--- a/companion/src/simulation/simulatorinterface.cpp
+++ b/companion/src/simulation/simulatorinterface.cpp
@@ -6,6 +6,9 @@
#include
#include
#include "version.h"
+#if defined WIN32 || !defined __GNUC__
+ #include
+#endif
QMap registered_simulators;
@@ -47,10 +50,15 @@ void registerSimulators()
simulatorsFound = true;
}
-#if defined(__APPLE__) || !( (!defined __GNUC__) || (defined __CYGWIN__) )
if (!simulatorsFound) {
#if defined(__APPLE__)
dir = QLibraryInfo::location(QLibraryInfo::PrefixPath) + "/Resources";
+#elif (!defined __GNUC__)
+ char name[MAX_PATH];
+ GetModuleFileName(NULL, name, MAX_PATH);
+ QString path(name);
+ path.truncate(path.lastIndexOf('\\'));
+ dir.setPath(path);
#else
dir = SIMULATOR_LIB_SEARCH_PATH;
#endif
@@ -59,7 +67,6 @@ void registerSimulators()
simulatorsFound = true;
}
}
-#endif
}
SimulatorFactory *getSimulatorFactory(const QString &name)
@@ -81,3 +88,9 @@ SimulatorFactory *getSimulatorFactory(const QString &name)
return NULL;
}
+void unregisterSimulators()
+{
+ foreach(SimulatorFactory *factory, registered_simulators) {
+ delete factory;
+ }
+}
diff --git a/companion/src/simulation/simulatorinterface.h b/companion/src/simulation/simulatorinterface.h
index 48c67a4be..a19753ba6 100644
--- a/companion/src/simulation/simulatorinterface.h
+++ b/companion/src/simulation/simulatorinterface.h
@@ -118,6 +118,7 @@ class SimulatorFactory {
};
void registerSimulators();
+void unregisterSimulators();
SimulatorFactory *getSimulatorFactory(const QString &name);
extern QMap registered_simulators;
diff --git a/companion/src/simulator.cpp b/companion/src/simulator.cpp
index 3f923be7d..9257d68df 100644
--- a/companion/src/simulator.cpp
+++ b/companion/src/simulator.cpp
@@ -180,6 +180,9 @@ int main(int argc, char *argv[])
delete dialog;
+ unregisterSimulators();
+ unregisterOpenTxFirmwares();
+
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
SDL_Quit();
#endif
diff --git a/companion/src/translations/companion_cs.ts b/companion/src/translations/companion_cs.ts
index dd2a5dbd1..e283c6cfe 100644
--- a/companion/src/translations/companion_cs.ts
+++ b/companion/src/translations/companion_cs.ts
@@ -69,15 +69,6 @@
Radio Profile
Profil rádia
-
-
-
-
-
-
- Open Folder
- Vybrat složku
-
Default Channel Order
@@ -315,6 +306,20 @@ Mode 4:
A T E R
K P V S
+
+
+
+
+
+
+ Select Folder
+ Vybrat složku
+
+
+
+ Select Executable
+ Vybrat
+
Use OpenTX firmware nightly builds
@@ -423,11 +428,6 @@ Může být jiná než verze firmwaru
Files to keep
Velikost historie souborů
-
-
- Find Executable
- Najít
-
Google Earth Executable
@@ -1441,92 +1441,93 @@ Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe)
EepromInterface
-
+
Possible causes for this:
-
+ Možné příčiny:
+
+
+
+ - Eeprom is from a newer version of OpenTX
+ - eeprom pochází z novější verze OpenTX
+
+
+
+ - Eeprom is not from OpenTX
+ - eeprom nepochází z OpenTX
+
+
+
+ - Eeprom is not from Th9X
+ - eeprom nepochází z Th9X
+
+
+
+ - Eeprom is not from Gruvin9X
+ - eeprom nepochází z Gruvin9X
+
+
+
+ - Eeprom is not from ErSky9X
+ - eeprom nepochází z Ersky9X
+
+
+
+ - Eeprom is not from Er9X
+ - eeprom nepochází z Er9X
+
+
+
+ - Eeprom size is invalid
+ - velikost eeprom není platná
- - Eeprom is from a newer version of OpenTX
-
+ - Eeprom file system is invalid
+ - eeprom struktura souboru je poškozená
- - Eeprom is not from OpenTX
-
+ - Eeprom is from a unknown board
+ - eeprom pochází z neznámé hw platformy
- - Eeprom is not from Th9X
-
+ - Eeprom is from the wrong board
+ - eeprom pochází z jiné desky
- - Eeprom is not from Gruvin9X
-
-
-
-
- - Eeprom is not from ErSky9X
-
+ - Eeprom backup not supported
+ - záloha eeprom není podporována
- - Eeprom is not from Er9X
-
-
-
-
- - Eeprom size is invalid
-
-
-
-
- - Eeprom file system is invalid
-
+ - Something that couldn't be guessed, sorry
+ - problém který neumíme určit, bohužel
- - Eeprom is from a unknown board
-
+ Warning:
+ Varování:
- - Eeprom is from the wrong board
-
-
-
-
- - Eeprom backup not supported
-
-
-
-
- - Something that couldn't be guessed, sorry
-
-
-
-
- Warning:
-
-
-
-
-
+
- Your radio probably uses a wrong firmware,
eeprom size is 4096 but only the first 2048 are used
-
+ Vaše rádio možná používá jiný firmware než by mělo, velikost eeprom je 4096, ale jen polovina je používána
-
+
- Your eeprom is from an old version of OpenTX, upgrading!
You should 'save as' to keep the old file as a backup.
-
+ - Vaše eeprom pochází ze starší verze openTX, aktualizuji!
+Měl byste ji 'Uložit jako' pro uchování starší verze jako zálohy.
-
+
Warnings!
-
+ Pozor!
@@ -3543,6 +3544,12 @@ Opravdu to takto chcete ?
L%1
+
+
+
+ (instant)
+
+
&Delete
@@ -3558,12 +3565,6 @@ Opravdu to takto chcete ?
&Copy
&Kopírovat
-
-
-
- (no release)
-
-
(infinite)
@@ -3751,9 +3752,9 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
MainWindow
-
-
-
+
+
+
File loaded
Soubor byl načten
@@ -3774,112 +3775,111 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
-
-
+
Save As
Uložit jako
-
+
Executable (*.exe)
Spustitelný (*.exe)
-
+
New release available
Je dostupné nové vydání
-
-
+
+
No updates available at this time.
Žádné aktualizace nejsou nyní dostupné.
-
+
Would you like to launch the installer?
Chcete spustit instalátor?
-
-
+
+
Error
Chyba
-
+
Error opening file %1:
%2.
Chyba při otevírání souboru %1:
%2.
-
+
Compilation server termporary failure, try later
Server companion je dočasně nedostupný, zkuste to později
-
+
A new release of Companion is available, please check the OpenTX website!
Je dostupná nová verze Companion, prosím navštivte internetové stránky OpenTX!
-
+
Not enough memory for all the selected firmware options
Není dostatek paměti pro všechny zvolené vlastnosti firmwaru
-
+
Compilation server too busy, try later
Server companion je zaneprázdněn, zkuste to později
-
+
Unknown server failure, try later
Neznámá chyba serveru, zkuste to později
-
+
Do you want to write the firmware to the radio now ?
Chcete zapsat firmware do rádia nyní?
-
-
+
+
Yes
Ano
-
-
+
+
No
Ne
-
-
+
+
Release Notes
Poznámky k vydání
-
-
+
+
Do you want to download release %1 now ?
Chcete nyní stáhnout vydání %1 ?
-
-
+
+
File saved
Soubor byl uložen
-
+
Firmware updates
Aktualizace firmwaru
-
+
Current firmware does not provide release notes informations.
K tomuto firmwaru nejsou poznámky k vydání.
@@ -3889,123 +3889,123 @@ The columns for altitude "GAlt" and for speed "GSpd" are opt
Je dostupná nová verze Companion (verze %1)<br>Chcete ji nyní stáhnout?
-
+
Compilation server requires registration, please check OpenTX web site
Kompilační server vyžaduje registraci, prosím navštivte internetové stránky OpenTX
-
+
Ignore this release %1?
Ignorovat tuto verzi %1?
-
+
The selected language will be used the next time you start Companion.
Zvolený jazyk bude použit při příštím spuštění Companion.
-
+
The new theme will be loaded the next time you start Companion.
Nové téma bude použito při příštím spuštění Companion.
-
+
The icon size will be used the next time you start Companion.
Zvolená velikost ikon bude použita při příštím spuštění Companion.
-
+
The OpenTX Companion project was originally forked from <a href='%1'>eePe</a>
Projekt OpenTX Companion vznikl oddělením z <a href='%1'>eePe</a>
-
+
Load backup from file
Načíst zálohu ze souboru
-
-
+
+
Open Models and Settings file
Otevřít soubor modelů a nastavení
-
+
Read Models and Settings From Radio
Načíst modely a nastavení z rádia
-
+
Save Radio Backup to File
Uložit zálohu rádia do souboru
-
+
Read Radio Firmware to File
Načíst firmware rádia do souboru
-
+
OpenTX Home Page: <a href='%1'>%1</a>
Internetová stránka OpenTX : <a href='%1'>%1</a>
-
+
If you've found this program useful, please support by <a href='%1'>donating</a>
Pokud vám byl tento program užitečný, podpořte jej <a href='%1'>darem</a>
-
+
Copyright OpenTX Team
-
+
About Companion
O aplikaci Companion
-
+
New
Nový
-
+
Open...
Otevřít
-
+
Save
Uložit
-
+
Save As...
Uložit jako...
-
+
Copy Model
Kopírovat model
-
+
Paste Model
Vložit model
-
+
Compare models
Porovnat modely
-
+
Exit the application
Ukončit aplikaci
-
+
Firmware %1 does not seem to have ever been downloaded.
Release %2 is available.
Do you want to download it now?
@@ -4018,7 +4018,7 @@ Chcete ho stáhnout nyní?
Doporučujeme prohlédnout poznámky k vydání, pomocí tlačítka níže se dozvíte o případných změnách, které mohou být pro vás důležité.
-
+
A new version of %1 firmware is available:
- current is %2
- newer is %3
@@ -4035,574 +4035,574 @@ Chcete firmware stáhnout nyní?
Doporučujeme prohlédnout poznámky k vydání, pomocí tlačítka níže se dozvíte o případných změnách, které mohou být pro vás důležité.
-
-
+
+
Synchronize SD
Synchronizace SD
-
+
A monochrome black icon theme
Černé mono téma
-
+
A monochrome white icon theme
Bílé mono téma
-
+
A monochrome blue icon theme
Modré mono téma
-
+
Small
Malá
-
+
Use small toolbar icons
Použít malé ikony nástrojové lišty
-
+
Use normal size toolbar icons
Použít normální velikost ikon nástrojové lišty
-
+
Normal
Normální
-
+
Use big toolbar icons
Použít velké ikony nástrojové lišty
-
+
Big
Velká
-
+
Use huge toolbar icons
Použít největší ikony nástrojové lišty
-
+
Huge
Největší
-
+
Create a new Models and Settings file
Vytvořit nový soubor modelů a nastavení
-
-
+
+
Save Models and Settings file
Uložit soubor modelů a nastavení
-
+
Exit
Ukončit
-
+
Cut Model
Vyjmout model
-
+
Cut current model to the clipboard
Vyjmout aktuální model a uložit do schránky
-
+
Copy current model to the clipboard
Kopírovat aktuální model do schránky
-
+
Paste model from clipboard
Vložit obsah schránky na aktuální pozici
-
+
Classical
Klasik9x
-
+
The classic companion9x icon theme
Původní téma companion9x
-
+
Yerico
-
+
Yellow round honey sweet icon theme
Žluté medové téma
-
+
Monochrome
Mono
-
+
MonoWhite
Mono-bílé
-
+
MonoBlue
Mono-modré
-
+
System language
Výchozí jazyk prostředí
-
+
Use system language in menus
Použít systémový jazyk
-
+
Czech
Čeština
-
+
Use Czech in menus
Aplikace v českém jazyce
-
+
German
-
+
Use German in menus
-
+
English
-
+
Use English in menus
-
+
Finnish
-
+
Use Finnish in menus
-
+
French
-
+
Use French in menus
-
+
Italian
-
+
Use Italian in menus
-
+
Polish
-
+
Use Polish in menus
-
+
Spanish
-
+
Use Spanish in menus
-
+
Swedish
-
+
Use Swedish in menus
-
+
About...
O aplikaci
-
+
Print...
Tisk
-
+
Print current model
Vytisknout zvolený model
-
+
Simulate...
Simulace
-
+
Simulate current model
Simulace vybraného modelu
-
+
Alt+S
-
+
Load Backup...
Načíst zálohu...
-
+
View Log File...
Zobrazit Log
-
+
Open and view log file
Otevře a zobrazí soubor logu rádia
-
+
Settings...
Předvolby...
-
+
Edit Settings
Upravit nastavení předvoleb
-
+
Download...
Stáhnout
-
+
Download firmware and voice files
Stáhnout firmware a hlasové soubory
-
+
Check for Updates...
Zkontrolovat aktualizace
-
+
Check OpenTX and Companion updates
Zkontrolovat aktualizace OpenTX a Companion
-
+
Companion Changes...
Změny Companion
-
+
Show Companion change log
Zobrazí seznam změn jednotlivých vydání Companion
-
+
Firmware Changes...
Změny Firmwaru
-
+
Show firmware change log
Zobrazí seznam změn jednotlivých vydání Firmware
-
+
Compare Models...
Porovnat modely...
-
+
Edit Radio Splash Image...
Upravit úvodní logo rádia...
-
+
Edit the splash image of your Radio
Upravit úvodní grafické logo rádia
-
+
List programmers...
Seznam programátorů...
-
+
Fuses...
Pojistky mikrokontroléru...
-
-
+
+
Read Firmware from Radio
Načíst firmware z rádia
-
+
Read firmware from Radio
Načíst firmware z rádia
-
-
+
+
Write Firmware to Radio
Zapsat firmware do rádia
-
+
Write firmware to Radio
Zapsat firmware do rádia
-
+
Add Radio Profile
Nový profil rádia
-
+
Create a new Radio Setting Profile
Vytvořit nový profil nastavení rádia
-
+
Manuals and other Documents
Manuály a jiné dokumenty
-
+
Open the OpenTX document page in a web browser
Otevřít stránku s dokumenty OpenTX v prohlížeči
-
+
Write Models and Settings To Radio
Zapsat modely a nastavení do rádia
-
-
+
+
Write Models and Settings to Radio
Zapsat modely a nastavení do rádia
-
-
-
+
+
+
Companion
-
-
+
+
Read Models and Settings from Radio
Načíst modely a nastavení z rádia
-
+
OpenTX Companion %1 - Radio: %2 - Profile: %3
OpenTX Companion %1 - Rádio: %2 - Profil: %3
-
+
Configure Communications...
Nastavení propojení
-
+
Configure software for communicating with the Radio
Nastavení softwaru pro komunikaci s rádiem
-
+
Write Backup to Radio
Zapsat zálohu do rádia
-
+
Write Backup from file to Radio
Zapsat zálohu ze souboru do rádia
-
+
Backup Radio to File
Zálohovat rádio do souboru
-
+
Save a complete backup file of all settings and model data in the Radio
Uložit kompletní zálohu modelů a nastavení rádia
-
+
Contributors...
Přispěvatelé
-
+
A tribute to those who have contributed to OpenTX and Companion
Hold těm, kteří přispěli k OpenTX a Companion
-
+
SD card synchronization
Syncronizace SD karty se složkou s daty
-
+
Recent Files
Nedávné soubory
-
+
Recent Models+Settings
Nedávné modely a nastavení
-
+
Set Icon Theme
Téma ikon
-
+
Set Icon Size
Velikost ikon
-
+
Show the list of radio profiles
Výběr profilů rádia
-
+
Write
Zápis
-
+
New Radio
Nové rádio
-
+
List available programmers
Seznam použitelných programátorů
-
+
Show fuses dialog
Zobrazit dialog nastavení pojistek mikrokontroléru
-
+
Show the application's About box
O aplikaci Companion
-
+
Set Menu Language
Nastavení jazyka
-
-
+
+
File
Soubor
-
-
+
+
Edit
Úpravy
-
+
Settings
Nastavení
-
+
Read/Write
Čtení/Zápis
-
-
+
+
Help
Nápověda
-
-
+
+
Radio Profile
Profil rádia
-
+
Show recent Models+Settings documents
Nedávné dokumenty modelů a nastavení rádia
-
+
Ready
Připraven
-
+
%2
@@ -4731,7 +4731,7 @@ Chcete ho uložit?
Warning
- Varování
+ Varování
@@ -5355,17 +5355,17 @@ p, li { white-space: pre-wrap; }
Offset(%1)
- Ofset(%1)
+ Ofset(%1)
Delay(u%1:d%2)
-
+ Zpoždění(u%1:d%2)
Slow(u%1:d%2)
-
+ Zpomalení(u%1:d%2)
@@ -5390,17 +5390,22 @@ p, li { white-space: pre-wrap; }
Edge(%1, [%2:%3])
-
+
+
+
+
+ instant
+
Sticky(%1, %2)
-
+
Timer(%1, %2)
-
+
@@ -5732,38 +5737,38 @@ p, li { white-space: pre-wrap; }
Port Trenér
-
+
Internal Radio System
Interní vysílací modul
-
+
External Radio Module
Externí vysílací modul
-
-
+
+
Radio System
Vysílací modul
-
+
Extra Radio System
Extra modul
-
+
Value
Hodnota
-
+
Hold
Držet hodnotu
-
+
No Pulse
Žádné pulzy
@@ -6104,53 +6109,53 @@ p, li { white-space: pre-wrap; }
-
+
P1
Potenciometr P1
-
+
P2
Potenciometr P2
-
+
P3
Potenciometr P3
-
-
+
+
S1
-
-
+
+
S2
-
-
+
+
LS
-
-
+
+
RS
@@ -6232,7 +6237,7 @@ p, li { white-space: pre-wrap; }
°F
-
+
@@ -6419,7 +6424,7 @@ p, li { white-space: pre-wrap; }
-
+
THR
Plyn
@@ -6590,52 +6595,52 @@ FAI je soutěžní mód (www.fai.org), zablokuje vario, zobrazení telemetrie a
Support for a third timer
-
+ Přidá třetí stopky
Instead of Joystick emulation, USB connection is Mass Storage (as in the Bootloader)
-
+ Místo emulace joisticku je USB připojeno v režimu přenosu souborů (jako v Bootloaderu)
Instead of Joystick emulation, USB connection is Command Line Interface
-
+ Místo emulace joisticku je USB připojeno v režimu CLI (textová konzole)
Removes D8 and LR12 FrSky protocols that are not legal for use in the EU on radios sold after Jan 1st, 2015
-
+ Odstraní volby pro Frsky protokoly D8 a LR12 která nejsou legální pro rádia zakoupená po 1.1.2015
Support for PPM internal module hack
-
+ Podpora pro upravený vnitřní modul v režimu PPM
ST7565P LCD or compatible
-
+ ST7565P LCD a kompatibilní
ST7565R LCD or compatible
-
+ ST7565R LCD a kompatibilní
ERC12864FSF LCD
-
+
ST7920 LCD
-
+
9X board
-
+ 9X základní deska
@@ -6682,43 +6687,43 @@ To je nutné zejména pro osazení FrSky kniplů do 9X.
Power management by soft-off circuitry
-
+ Ovládání napájení pomocí soft-off obvodu
ar9x board / 9X
-
+ ar9x deska / 9X
9XR-PRO
-
+
FrSky Taranis
-
+
FrSky Taranis Plus
-
+
FrSky Taranis X9E
-
+
Confirmation before radio shutdown
-
+ Přidá potvrzování před vypnutím rádia
Adds mixers output view to the CHANNELS MONITOR screen, pressing [ENT] switches between the views
-
+ Přidá monitor výstupu mixů k monitoru kanálů, stiskem [ENT] přepnete z jednoho do druhého
@@ -6836,22 +6841,22 @@ se provádí jeho sepnutím
M128 / 9X board
-
+ M128 / 9X základní deska
9XR
-
+
9XR with M128 chip
-
+ 9XR s čipem M128
Gruvin9x board / 9X
-
+ Gruvin9x deska / 9X
@@ -6989,12 +6994,12 @@ zobrazeny normálním písmem
MEGA2560 board
-
+ MEGA2560 deska
Sky9x board / 9X
-
+ Sky9x deska / 9X
@@ -7282,31 +7287,31 @@ Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Fun
-
+
F1
-
+
F2
-
+
F3
-
+
F4
-
+
S3
@@ -7315,7 +7320,7 @@ Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Fun
Timer3
- Stopky3
+ Stopky3
@@ -7937,12 +7942,7 @@ Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Fun
Play Script
-
-
-
-
- Start Logs
- Začít logovat
+ Spustit skript
@@ -7957,7 +7957,7 @@ Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Fun
Screenshot
-
+ Snímek LCD
@@ -7967,32 +7967,32 @@ Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Fun
SetFailsafe Int. Module
-
+ Nastavit Failsafe vnitř. modulu
SetFailsafe Ext. Module
-
+ Nastavit Failsafe ext. modulu
RangeCheck Int. Module
-
+ Test dosahu vnitř. modulu
RangeCheck Ext. Module
-
+ Test dosahu ext. modulu
Bind Int. Module
-
+ Bind vnitř. modulu
Bind Ext. Module
-
+ Bind ext. modulu
@@ -8004,17 +8004,17 @@ Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Fun
played once, not during startup
-
+ přehrát jednou, ale ne po startu
repeat(%1s)
-
+ opakovat(%1s)
DISABLED
- ZAKÁZÁN
+ ZAKÁZÁN
@@ -8162,6 +8162,11 @@ Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Fun
Edge
+
+
+ SD Logs
+ SD logy
+
Telemetry
@@ -8215,7 +8220,7 @@ Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Fun
Flight
-
+ Let
@@ -8268,43 +8273,58 @@ Nastavení hodnoty se provádí přímo v seznamu proměnných, nebo pomocí Fun
Současné použití expa a křivek již není podporováno
-
- Source %1 cannot be exported on this board!
-
+
+ Switch
+ Spínač
-
+
+ Switch
+ Spínač
+
+
+
+ cannot be exported on this board!
+ -na této desce nelze exportovat!
+
+
+
+ Source %1 cannot be exported on this board!
+ Zdroj %1 nelze na této desce exportovat!
+
+
+
OpenTX only accepts %1 points in all curves
V OpenTX je možné zadat pouze %1 bodů dohromady ve všech křivkách
-
+
OpenTx only accepts %1 points in all curves
V OpenTX je možné zadat pouze %1 bodů dohromady ve všech křivkách
-
-
-
-
-
+
+
+
+
+
OpenTX on this board doesn't accept this function
OpenTX nepodporuje tuto funkci na této zákl. desce
-
+
OpenTX doesn't accept this telemetry protocol
OpenTX nepodporuje tento protokol
-
-
-
+
+
+
OpenTX doesn't accept this radio protocol
OpenTX nepodporuje tento protokol
-
+
OpenTX doesn't allow this number of channels
V OpenTX nelze použít tento počet kanálů
@@ -8368,94 +8388,94 @@ Tým OpenTX.
GP
-
-
+
+
Synchronization error
-
+ Chyba synchronizace
-
+
No SD directory configured!
-
+ Složka SD karty nebyla nastavena!
-
+
No Radio connected!
-
+ Není připojeno rádio!
-%1
-
+
The directory '%1' doesn't exist!
-
+ Složka '%1' neexistuje!
Create '%1' failed
-
+ Vytvoření '%1' selhalo
Copy '%1' to '%2' failed
-
+ Kopírování '%1' do '%2' selhalo
Open '%1' failed
-
+ Otevření '%1' selhalo
Write '%1' failed
-
+ Zápis '%1' selhal
Error
- Chyba
+ Chyba
Cannot write file %1:
%2.
- Nelze zapsat soubor %1:
+ Nelze zapsat soubor %1:
%2.
Companion
-
+
<b><u>WARNING!</u></b><br>This will reset the fuses of %1 to the factory settings.<br>Writing fuses can mess up your radio.<br>Do this only if you are sure they are wrong!<br>Are you sure you want to continue?
- <b><u>POZOR!</u></b><br>Toto nastaví pojistky %1 do továrního nastavení.<br>Zápis pojistek může poškodit vaše rádio.<br>Proveďte pouze pokud jste si jist že jsou nastaveny špatně!<br>Jste si opravdu jist, že chcete pokračovat?
+ <b><u>POZOR!</u></b><br>Toto nastaví pojistky %1 do továrního nastavení.<br>Zápis pojistek může poškodit vaše rádio.<br>Proveďte pouze pokud jste si jist že jsou nastaveny špatně!<br>Jste si opravdu jist, že chcete pokračovat?
Could not delete temporary file: %1
- Nelze odstarnit dočasný soubor: %1
+ Nelze odstarnit dočasný soubor: %1
Radio type
-
+ Typ rádia
Which radio type do you want to simulate?
-
+ Jaký typ rádia chcete simulovat?
@@ -8620,7 +8640,7 @@ Tým OpenTX.
Top LCD Timer
-
+ Stopky na horním LCD
@@ -8683,7 +8703,7 @@ Funkce trimu bude opačná, stejně tak i varování polohy páky plynu.
SetupPanel
-
+
Timer %1
@@ -9322,99 +9342,99 @@ Funkce trimu bude opačná, stejně tak i varování polohy páky plynu.
TelemetryPanel
-
+
Telemetry screen %1
Stránka telemetrie %1
-
+
Low Alarm
Nízký alarm
-
+
Critical Alarm
Kriticky alarm
-
+
Winged Shadow How High
-
+
Winged Shadow How High (not supported)
Winged Shadow How High (nepodporován)
-
-
+
+
A1
Telem. vstup A1
-
+
Alti
-
+
FrSky S.PORT
-
+
FrSky D
-
+
FrSky D (cable)
FrSky D (kabel)
-
+
Alti+
-
+
VSpeed
-
-
+
+
A2
Telem. vstup A2
-
-
+
+
A3
Telem. vstup A3
-
-
+
+
A4
Telem. vstup A4
-
-
+
+
FAS
-
+
Cells
-
+
---
diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts
index ac77cfd88..e0b34fa85 100644
--- a/companion/src/translations/companion_fr.ts
+++ b/companion/src/translations/companion_fr.ts
@@ -69,15 +69,6 @@
Radio Profile
Profil de radio
-
-
-
-
-
-
- Open Folder
- Ouvrir le répertoire
-
Default Channel Order
@@ -315,6 +306,20 @@ Manche Droit: Profondeur, Direction
A T E R
A G P D
+
+
+
+
+
+
+ Select Folder
+ Sélectionner dossier
+
+
+
+ Select Executable
+ Sélectionner exécutable
+
Use OpenTX firmware nightly builds
@@ -423,11 +428,6 @@ Peut être différente de la langue du firmware
Files to keep
Fichiers à conserver
-
-
- Find Executable
- Parcourir...
-
Google Earth Executable
@@ -1439,92 +1439,95 @@ Extra long : bips extra longs.
EepromInterface
-
+
Possible causes for this:
-
+ Causes possibles:
+
+
+
+ - Eeprom is from a newer version of OpenTX
+ - L'EEPROM peut avoir été créée avec une version d'OpenTX plus récente
+
+
+
+ - Eeprom is not from OpenTX
+ - L'EEPROM peut avoir été créée avec un firmware autre qu'OpenTX
+
+
+
+ - Eeprom is not from Th9X
+ - L'EEPROM n'est pas une EEPROM TX9X
+
+
+
+ - Eeprom is not from Gruvin9X
+ - L'EEPROM n'est pas une EEPROM Gruvin9X
+
+
+
+ - Eeprom is not from ErSky9X
+ - L'EEPROM n'est pas une EEPROM ErSky9X
+
+
+
+ - Eeprom is not from Er9X
+ - L'EEPROM n'est pas une EEPROM ER9X
+
+
+
+ - Eeprom size is invalid
+ - La taille de l'EEPROM est invalide
- - Eeprom is from a newer version of OpenTX
-
+ - Eeprom file system is invalid
+ - Le système de fichier de l'EEPROM est invalide
- - Eeprom is not from OpenTX
-
+ - Eeprom is from a unknown board
+ - L'EEPROM ne correspond à aucune carte supportée
- - Eeprom is not from Th9X
-
+ - Eeprom is from the wrong board
+ L'EEPROM ne correspond pas au type de radio sélectionné
- - Eeprom is not from Gruvin9X
-
-
-
-
- - Eeprom is not from ErSky9X
-
+ - Eeprom backup not supported
+ - Sauvegarde d'EEPROM non supportée
- - Eeprom is not from Er9X
-
-
-
-
- - Eeprom size is invalid
-
-
-
-
- - Eeprom file system is invalid
-
+ - Something that couldn't be guessed, sorry
+ - Erreur inconnue...
- - Eeprom is from a unknown board
-
+ Warning:
+ Avertissement:
- - Eeprom is from the wrong board
-
-
-
-
- - Eeprom backup not supported
-
-
-
-
- - Something that couldn't be guessed, sorry
-
-
-
-
- Warning:
-
-
-
-
-
+
- Your radio probably uses a wrong firmware,
eeprom size is 4096 but only the first 2048 are used
-
+ - Le firmware de la radio est probablement incorrect,
+la taille de l'EEPROM est de 4096 mais seulement 2048 bytes sont utilisés.
+Vérifier la sélection (M64/M128).
-
+
- Your eeprom is from an old version of OpenTX, upgrading!
You should 'save as' to keep the old file as a backup.
-
+ - Le fichier qui vient d'être ouvert provient d'une ancienne verison d'OpenTX et a été converti.
+Il est recommandé d'"Enregistrer Sous" au plus vite pour ne pas risquer d'écraser votre ancien fichier.
-
+
Warnings!
-
+ Avertissements!
@@ -1540,6 +1543,223 @@ Extra long : bips extra longs.
Deuxième voie d'élevons:
+
+ Er9x::Templates
+
+
+ Simple 4-CH
+ 4 canaux simple
+
+
+
+ T-Cut
+ Coupure moteur
+
+
+
+ Sticky T-Cut
+ Coupure moteur protégée
+
+
+
+ V-Tail
+ Empennage en V
+
+
+
+ Elevon\Delta
+
+
+
+
+ Heli Setup
+ Configuration hélico
+
+
+
+ Heli Setup with gyro gain control
+ Configuration héllico avec contrôle du gyro
+
+
+
+ Gyro gain control
+ Contrôle du gain du gyro
+
+
+
+ Heli Setup (Futaba's channel assignment style)
+ Configuration hélico (canaux style Futaba)
+
+
+
+ Heli Setup with gyro gain control (Futaba's channel assignment style)
+ Configuration héllico avec contrôle du gyro (canaux style Futaba)
+
+
+
+ Gyro gain control (Futaba's channel assignment style)
+ Contrôle du gain du gyro (canaux style Futaba)
+
+
+
+ Servo Test
+ Test servo
+
+
+
+ MultiCopter
+ Multicoptère
+
+
+
+ Use Model Config Wizard
+ Utiliser l'assistant de configuration de modèle
+
+
+
+ Apply Template?
+ Appliquer le gabarit?
+
+
+
+ Apply template "%1"?
+ Appliquer le gabarit "%1"?
+
+
+
+
+
+
+
+
+
+ RUD
+ DIR
+
+
+
+
+
+
+
+
+
+
+
+
+ ELE
+ PRF
+
+
+
+
+
+ THR
+ Gaz
+
+
+
+
+
+
+
+
+
+
+ AIL
+
+
+
+
+
+
+
+ AIL2
+
+
+
+
+
+
+
+ ELE2
+ PRF2
+
+
+
+
+
+
+
+
+ FLAPS
+ VOLETS
+
+
+
+
+
+
+
+
+ FLAP%1
+ VOLETS%1
+
+
+
+
+
+
+ PITCH
+ PAS
+
+
+
+
+
+
+
+
+
+
+ GYRO
+
+
+
+
+
+ SPOIL
+
+
+
+
+
+ SPOIL%1
+
+
+
+
+
+ RUD2
+ DIR2
+
+
+
+
+ Clear Mixes?
+ Effacer tous les mixages ?
+
+
+
+ Really clear existing mixes on CH6?
+ Vraiment effacer tous les mixages sur CH6?
+
+
+
+ Really clear existing mixes on CH5?
+ Vraiment effacer tous les mixages sur CH5?
+
+
ExpoDialog
@@ -3590,6 +3810,12 @@ Are you sure ?
L%1
+
+
+
+ (instant)
+
+
&Delete
@@ -3605,12 +3831,6 @@ Are you sure ?
&Copy
&Copier
-
-
-
- (no release)
- (pas de relâchement)
-
(infinite)
@@ -3799,14 +4019,14 @@ Les colonnes contenant l'altitude "GAlt" et la vitesse "GSpd
MainWindow
-
-
+
+
Edit
Edition
-
-
+
+
File
Fichier
@@ -3816,99 +4036,99 @@ Les colonnes contenant l'altitude "GAlt" et la vitesse "GSpd
Afficher les alertes précédentes lors du prochain démarrage ?
-
+
New release available
Nouvelle version disponible
-
-
+
+
Error
Erreur
-
+
Error opening file %1:
%2.
Erreur à l'ouverture du fichier %1:
%2.
-
+
Compilation server termporary failure, try later
Erreur temporaire du serveur de compilation, veuillez réessayer plus tard
-
+
Compilation server too busy, try later
Serveur de compilation trop occupé, veuillez réessayer plus tard
-
+
Unknown server failure, try later
Erreur inconnue du serveur de compilation, veuillez réessayer plus tard
-
+
Do you want to write the firmware to the radio now ?
Voulez vous transférer le firmware à la radio maintenant?
-
-
+
+
Yes
Oui
-
-
+
+
No
Non
-
-
+
+
Release Notes
Notes de version
-
-
+
+
Do you want to download release %1 now ?
Voulez-vous télécharger la version %1 maintenant?
-
+
Firmware updates
Mises à jour de firmware
-
+
Current firmware does not provide release notes informations.
Le firmware actuel ne contient pas de notes de version.
-
+
Load backup from file
Charger une sauvegarde à partir du fichier
-
+
Compare models
Comparer les modèles
-
+
Show fuses dialog
Afficher les réglages des fusibles
-
+
A monochrome black icon theme
Thème avec icônes monochromes noires
-
+
Firmware %1 does not seem to have ever been downloaded.
Release %2 is available.
Do you want to download it now?
@@ -3921,7 +4141,7 @@ Voulez-vous la télécharger maintenant ?
Nous recommandons de lire attentivement les notes de version à l'aide du bouton ci-dessous, celles-ci peuvent contenir des infos importantes concernant les changements effectués depuis la version précéente.
-
+
A new version of %1 firmware is available:
- current is %2
- newer is %3
@@ -3938,294 +4158,294 @@ Voulez vous la télécharger maintenant ?
Nous recommandons de lire attentivement les notes de version à l'aide du bouton ci-dessous, celles-ci peuvent contenir des infos importantes concernant les changements effectués depuis la version précéente.
-
-
+
+
Synchronize SD
Synchroniser la carte SD
-
+
New
Nouveau
-
+
Open...
Ouvrir...
-
+
Copy Model
Copier le modèle
-
+
A monochrome white icon theme
Thème avec icônes monochromes blanches
-
+
A monochrome blue icon theme
Thème avec icônes monochromes bleues
-
+
Small
Petites
-
+
Use small toolbar icons
Petites icônes de barre d'outils
-
+
Use normal size toolbar icons
Icônes de barre d'outils normales
-
+
Normal
Normales
-
+
Use big toolbar icons
Grosses icônes de barre d'outils
-
+
Big
Grandes
-
+
Use huge toolbar icons
Immenses icônes de barre d'outils
-
+
Huge
Immenses
-
+
Czech
Tchèque
-
+
Use Czech in menus
Menus en Tchèque
-
+
German
Allemand
-
+
Use German in menus
Menus en Allemand
-
+
English
Anglais
-
+
Use English in menus
Menus en Anglais
-
+
French
Français
-
+
Use French in menus
Menus en Français
-
+
Italian
Italien
-
+
Use Italian in menus
Menus en Italien
-
+
Polish
Polonais
-
+
Use Polish in menus
Menus en Polonais
-
+
Swedish
Suédois
-
+
Use Swedish in menus
Menus en Suédois
-
+
List programmers...
Lister les programmateurs...
-
+
Fuses...
Fusibles...
-
-
+
+
Read Firmware from Radio
Lire le firmware de la radio
-
+
Read firmware from Radio
Lire le firmware de la radio
-
-
+
+
Write Firmware to Radio
Transférer le firmware à la radio
-
+
Write firmware to Radio
Transférer le firmware à la radio
-
+
Add Radio Profile
Ajouter un profil de radio
-
+
Create a new Radio Setting Profile
Créér un nouveau profil de radio
-
+
Manuals and other Documents
Manuels et documents
-
+
Open the OpenTX document page in a web browser
Ouvre la page de documentation d'OpenTX dans un navigateur
-
+
Write Models and Settings To Radio
Transférer les réglages et modèles à la radio
-
-
+
+
Write Models and Settings to Radio
Transférer les réglages et modèles à la radio
-
-
-
+
+
+
Companion
-
-
+
+
Read Models and Settings from Radio
Lire les réglages et modèles depuis la radio
-
+
OpenTX Companion %1 - Radio: %2 - Profile: %3
OpenTX Companion %1 - Radio: %2 - Profil: %3
-
+
Configure Communications...
Configurer les communications...
-
+
Configure software for communicating with the Radio
Configurer le programme gérant les communications avec la radio
-
+
Write Backup to Radio
Transférer une sauvegarde à la radio
-
+
Write Backup from file to Radio
Transférer une sauvegarde à la radio
-
+
Backup Radio to File
Sauvegarder la radio
-
+
Save a complete backup file of all settings and model data in the Radio
Créer une copie de sauvegarde de tous les réglages et modèles de la radio
-
+
Contributors...
Contributeurs...
-
+
A tribute to those who have contributed to OpenTX and Companion
Remerciements à tout ceux qui ont contribué à OpenTX et Companion
-
+
SD card synchronization
Synchronisation de la carte SD
-
+
Recent Files
Fichiers récents
-
+
Recent Models+Settings
Fichiers de réglages et modèles récents
-
+
Set Icon Theme
Choisir le thème d'icônes
-
+
Set Icon Size
Choisir la taille des icônes
-
+
Write
Ecrire
@@ -4235,346 +4455,345 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b
Une nouvelle version de Companion est disponible (version %1)<br>Voulez-vous la télécharger?
-
+
Compilation server requires registration, please check OpenTX web site
Le serveur de compilation requiert l'enregistrement, veuillez vous référer au site web d'OpenTX
-
+
OpenTX Home Page: <a href='%1'>%1</a>
Page d'accueil d'OpenTX: <a href='%1'>%1</a>
-
+
If you've found this program useful, please support by <a href='%1'>donating</a>
Si vous trouvez ce programme utile, merci de le supporter par une <a href='%1'>donation</a>
-
+
Show the list of radio profiles
Voir la liste des profils de radio
-
+
Ready
Prêt
-
+
Show the application's About box
Afficher la fenêtre "A propos" de l'application
-
-
-
+
+
+
File loaded
Fichier chargé
-
+
A new release of Companion is available, please check the OpenTX website!
Une nouvelle version de Companion est disponible, veuillez vous référer au site web d'OpenTX!
-
+
Not enough memory for all the selected firmware options
Pas assez de mémoire disponible pour toutes les options sélectionnées
-
-
+
+
Open Models and Settings file
Ouvrir un fichier de réglages et modèles
-
-
+
+
File saved
Fichier sauvegardé
-
+
Read Models and Settings From Radio
Lire les réglages et modèles depuis la radio
-
+
Ignore this release %1?
Ignorer la version %1?
-
+
Save Radio Backup to File
Sauvegarder la radio
-
+
Read Radio Firmware to File
Sauvegarder le firmware de la radio
-
+
The OpenTX Companion project was originally forked from <a href='%1'>eePe</a>
Le projet OpenTX Companion a été créé à partir d'<a href='%1'>eePe</a>
-
+
Copyright OpenTX Team
-
+
Create a new Models and Settings file
Créer un nouveau fichier de réglages et modèles
-
-
+
+
Save Models and Settings file
Enregistrer le fichier de réglages et modèles
-
+
Save
Enregistrer
-
+
Save As...
Enregistrer sous...
-
+
Exit the application
Quitter l'application
-
+
Exit
Quitter
-
+
Cut Model
Couper le modèle
-
+
Cut current model to the clipboard
Couper le modèle courant dans le presse-papier
-
+
Copy current model to the clipboard
Copier le modèle courant dans le presse-papier
-
+
Paste model from clipboard
Coller le modèle depuis le presse-papier
-
+
Paste Model
Coller le modèle
-
+
Classical
Classique
-
+
The classic companion9x icon theme
Thème d'icônes classique de Companion
-
+
Yerico
-
+
Yellow round honey sweet icon theme
Thème d'icônes rondes jaunes
-
+
Monochrome
-
+
MonoWhite
-
+
MonoBlue
-
+
System language
Langue du système
-
+
Use system language in menus
Utiliser la langue système dans les menus
-
+
Finnish
Finlandais
-
+
Use Finnish in menus
Menus en Finlandais
-
+
Spanish
Espagnol
-
+
Use Spanish in menus
Menus en espagnol
-
+
About...
A propos...
-
+
Print...
Imprimer...
-
+
Print current model
Imprimer le modèle courant
-
+
Simulate...
Simuler...
-
+
Simulate current model
Simuler le modèle courant
-
+
Alt+S
-
+
Load Backup...
Ouvrir la sauvegarde...
-
+
View Log File...
Ouvrir un log...
-
+
Open and view log file
Ouvrir et visualiser un log
-
+
Settings...
Préférences...
-
+
Edit Settings
Modifier les réglages
-
+
Download...
Télécharger...
-
+
Download firmware and voice files
Télécharger firmware et fichiers son
-
+
Check for Updates...
Vérifier les mises à jour...
-
+
Check OpenTX and Companion updates
Vérifier les mises à jour d'OpenTX et Companion
-
+
Companion Changes...
Changements de Companion...
-
+
Show Companion change log
Voir l'historique des changements de Companion
-
+
Firmware Changes...
Changements du firmware...
-
+
Show firmware change log
Voir l'historique des changements du firmware
-
+
Compare Models...
Comparer 2 modèles...
-
+
Edit Radio Splash Image...
Modifier l'écran d'accueil de la radio...
-
+
Edit the splash image of your Radio
Modifier l'écran d'accueil de la radio
-
+
List available programmers
Lister les programmateurs supportés
-
-
+
Save As
Enregistrer Sous
-
+
Executable (*.exe)
Exécutable (*.exe)
-
-
+
+
No updates available at this time.
Aucune mise à jour disponible.
@@ -4584,13 +4803,13 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b
Impossible de rechercher des mises à jour.
-
+
Would you like to launch the installer?
Voulez-vous lancer l'installation ?
-
-
+
+
Help
Aide
@@ -4600,58 +4819,58 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b
Recherche de mises à jour
-
+
The selected language will be used the next time you start Companion.
La langue sélectionnée sera utilisée lors du prochain lancement de Companion.
-
+
The new theme will be loaded the next time you start Companion.
Le nouveau thème sera utilisé lors du prochain lancement de Companion.
-
+
The icon size will be used the next time you start Companion.
La nouvelle taille d'icônes sera utilisée lors du prochain lancement de Companion.
-
+
About Companion
A propos de Companion
-
+
Set Menu Language
Choisir la langue des menus
-
+
Settings
Réglages
-
+
Read/Write
Transfert
-
-
+
+
Radio Profile
Profil de radio
-
+
Show recent Models+Settings documents
Voir les fichiers récents
-
+
%2
-
+
New Radio
Nouvelle radio
@@ -4773,7 +4992,7 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b
Warning
- Avertissement
+ Avertissement
@@ -5431,6 +5650,11 @@ Mixage actif par défaut si non-renseigné.
Edge(%1, [%2:%3])
Flanc(%1, [%2:%3])
+
+
+ instant
+
+
Sticky(%1, %2)
@@ -5772,38 +5996,38 @@ Mixage actif par défaut si non-renseigné.
Port écolage
-
+
Internal Radio System
Module HF interne
-
+
External Radio Module
Module HF externe
-
-
+
+
Radio System
Module HF
-
+
Extra Radio System
Module HF supplémentaire
-
+
Value
Valeur
-
+
Hold
Maintien
-
+
No Pulse
Pas d'impulsion
@@ -6192,11 +6416,6 @@ Mixage actif par défaut si non-renseigné.
Play Sound
Jouer Son
-
-
- Start Logs
- Démarrer les Logs
-
Haptic
@@ -6204,7 +6423,7 @@ Mixage actif par défaut si non-renseigné.
-
+
S3
@@ -6695,15 +6914,20 @@ Mixage actif par défaut si non-renseigné.
Unknown
Inconnu
+
+
+ SD Logs
+ Logs SD
+
played once, not during startup
-
+ Lu une fois, mais pas à la mise en route
repeat(%1s)
-
+ Répéter chaque %1s
@@ -6984,32 +7208,32 @@ Mixage actif par défaut si non-renseigné.
SetFailsafe Int. Module
-
+ Déf. failsafe module interne
SetFailsafe Ext. Module
-
+ Déf. failsafe module externe
RangeCheck Int. Module
-
+ Test portée module interne
RangeCheck Ext. Module
-
+ Test portée module externe
Bind Int. Module
-
+ Bind module interne
Bind Ext. Module
-
+ Bind module externe
@@ -7082,7 +7306,7 @@ Mixage actif par défaut si non-renseigné.
-
+
THR
Gaz
@@ -7100,7 +7324,7 @@ Mixage actif par défaut si non-renseigné.
-
+
P1
@@ -7203,14 +7427,14 @@ Mixage actif par défaut si non-renseigné.
-
+
P2
-
+
P3
@@ -7411,8 +7635,8 @@ Mixage actif par défaut si non-renseigné.
-
-
+
+
S1
@@ -7474,48 +7698,48 @@ Mixage actif par défaut si non-renseigné.
-
-
+
+
S2
-
-
+
+
LS
-
-
+
+
RS
-
+
F1
-
+
F2
-
+
F3
-
+
F4
@@ -8272,43 +8496,58 @@ Mixage actif par défaut si non-renseigné.
th9x ne supporte pas d'encodeurs rotatifs sur cette carte
-
+
+ Switch
+ Inter
+
+
+
+ Switch
+ L'inter
+
+
+
+ cannot be exported on this board!
+ n'est pas supporté sur cette carte!
+
+
+
Source %1 cannot be exported on this board!
La source %1 n'est pas supportée sur cette plateforme!
-
+
OpenTX only accepts %1 points in all curves
OpenTX n'accepte que %1 points au maximum entre toutes les courbes
-
+
OpenTx only accepts %1 points in all curves
OpenTX n'accepte que %1 points au maximum entre toutes les courbes
-
-
-
-
-
+
+
+
+
+
OpenTX on this board doesn't accept this function
OpenTX ne supporte pas cette fonction sur cette carte
-
+
OpenTX doesn't accept this telemetry protocol
OpenTX ne supporte pas ce protocole de télémesure
-
-
-
+
+
+
OpenTX doesn't accept this radio protocol
OpenTX ne supporte pas ce protocole radio
-
+
OpenTX doesn't allow this number of channels
OpenTX ne supporte pas ce nombre de voies
@@ -8362,8 +8601,8 @@ The OpenTX Team.
L'équipe OpenTX.
-
-
+
+
@@ -8371,12 +8610,12 @@ L'équipe OpenTX.
Erreur de synchronisation
-
+
No SD directory configured!
Aucun dossier SD configuré!
-
+
No Radio connected!
Aucune radio connectée!
@@ -8456,6 +8695,16 @@ L'équipe OpenTX.
Which radio type do you want to simulate?
Quel type de radio souhaite-vous simuler?
+
+
+ Positive
+
+
+
+
+ Negative
+ Négative
+
RadioNotFoundDialog
@@ -8619,7 +8868,7 @@ L'équipe OpenTX.
Top LCD Timer
-
+ Chrono LCD supérieur
@@ -8681,9 +8930,9 @@ Si cette option est cochée, la voie des gaz est inversée: le ralenti est &apo
SetupPanel
-
+
Timer %1
-
+ Chrono %1
@@ -9320,99 +9569,99 @@ Si cette option est cochée, la voie des gaz est inversée: le ralenti est &apo
TelemetryPanel
-
+
FrSky S.PORT
-
+
FrSky D
-
+
FrSky D (cable)
FrSky D (câble)
-
+
Telemetry screen %1
Ecran de télémesure %1
-
+
Low Alarm
Alarme basse
-
+
Critical Alarm
Alarme critique
-
+
Winged Shadow How High
Winged Shadow How High
-
+
Winged Shadow How High (not supported)
Winged Shadow How High (non supporté)
-
+
Alti
Alti
-
+
Alti+
Alti+
-
+
VSpeed
Vitesse V
-
-
+
+
A1
-
-
+
+
A2
-
-
+
+
A3
-
-
+
+
A4
-
-
+
+
FAS
-
+
Cells
Velm
-
+
---
diff --git a/companion/src/translations/companion_pl.ts b/companion/src/translations/companion_pl.ts
index d130310aa..e6a09149d 100644
--- a/companion/src/translations/companion_pl.ts
+++ b/companion/src/translations/companion_pl.ts
@@ -3792,12 +3792,6 @@ Jesteś pewien ?
L%1
L%1
-
-
-
- (no release)
- (brak wydania)
-
(infinite)
@@ -3818,6 +3812,12 @@ Jesteś pewien ?
&Copy
&Kopiuj
+
+
+
+ (instant)
+ (natychmistowy)
+
Ctrl+C
@@ -4002,9 +4002,9 @@ Kolumny wysokości "GAlt" i prędkości "GSpd" są opcjonaln
MainWindow
-
-
-
+
+
+
File loaded
Plik załadowany
@@ -4025,543 +4025,542 @@ Kolumny wysokości "GAlt" i prędkości "GSpd" są opcjonaln
-
-
+
Save As
Zapisz jako
-
+
Executable (*.exe)
Wykonywalny (*.exe)
-
+
New release available
Dostępne jest nowe wydanie
-
-
+
+
No updates available at this time.
Brak aktualizacji dostępnych teraz.
-
+
Would you like to launch the installer?
Chcesz uruchomić instalator?
-
-
+
+
Error
Błąd
-
+
Error opening file %1:
%2.
Błąd otwarcia pliku %1:
%2.
-
+
Compilation server termporary failure, try later
Serwer kompilacji chwilowo nieczynny, spróbuj później
-
+
A new release of Companion is available, please check the OpenTX website!
Nowe wydanie Companion jest dostępne, proszę sprawdzić stronę OpenTX!
-
+
Not enough memory for all the selected firmware options
Za mało pamięci dla wybranej konfiguracji firmware
-
+
Compilation server too busy, try later
Serwer kompilacji zbyt zajęty, spróbuj później
-
+
Unknown server failure, try later
Nieznany błąd serwera, spróbuj później
-
-
+
+
Yes
Tak
-
-
+
+
No
Nie
-
-
+
+
Release Notes
Informacje o wydaniu
-
-
+
+
Do you want to download release %1 now ?
Chcesz pobrać wydanie %1 teraz?
-
-
+
+
File saved
Plik zapisany
-
+
Firmware updates
Aktualizacja firmware
-
+
Current firmware does not provide release notes informations.
Aktualny firmware nie zawiera opisu wydania.
-
+
The OpenTX Companion project was originally forked from <a href='%1'>eePe</a>
Projekt Companion odłączony z oryginalnego <a href='%1'>eePe</a>
-
+
New
Nowy
-
+
Open...
Otwórz...
-
+
Save
Zapisz
-
+
Save As...
Zapisz jako...
-
+
Copy Model
Kopiuj Model
-
+
Paste Model
Wklej Model
-
+
About...
O aplikacji...
-
+
Print...
Drukuj...
-
+
Simulate...
Symulacja...
-
+
Simulate current model
Symulacja aktualnego modelu
-
+
Alt+S
Alt+S
-
+
Load Backup...
Załaduj backup...
-
+
View Log File...
Obejrzyj plik logów...
-
+
Open and view log file
Otwórz i obejrzyj plik logów
-
+
Edit Settings
Edycja Ustawień
-
+
Settings...
Ustawienia...
-
+
Download firmware and voice files
Pobierz firmware i pliki dźwiękowe
-
+
Create a new Radio Setting Profile
Utwórz nowy Profil Ustawień Radia
-
+
A monochrome black icon theme
Monochromatyczny czarny wygląd ikon
-
+
Do you want to write the firmware to the radio now ?
Chcesz wgrać firmware do radia teraz?
-
+
Ignore this release %1?
Zignorować to wydanie %1?
-
-
+
+
Open Models and Settings file
Otwórz plik Modeli i Ustawień
-
+
Read Models and Settings From Radio
Wczytaj Modele i Ustawienia z radia
-
+
Save Radio Backup to File
Zapisz Backup radia do pliku
-
+
Read Radio Firmware to File
Odczytaj Firmware radia do pliku
-
+
Create a new Models and Settings file
Utwórz nowy plik Modeli i Ustawień
-
-
+
+
Save Models and Settings file
Zapisz plik Modeli i Ustawień
-
+
Cut Model
Wytnij Model
-
+
Cut current model to the clipboard
Wytnij aktualny model do schowka
-
+
Copy current model to the clipboard
Wytnij aktualny model do schowka
-
+
Paste model from clipboard
Wklej Model ze schowka
-
+
The classic companion9x icon theme
Klasyczny zestaw ikon Companion
-
+
A monochrome white icon theme
Monochromatyczny biały wygląd ikon
-
+
A monochrome blue icon theme
Monochromatyczny niebieski wygląd ikon
-
+
Small
Małe
-
+
Use small toolbar icons
Użyj małych ikon paska narzędzi
-
+
Use normal size toolbar icons
Użyj normalnych ikon paska narzędzi
-
+
Normal
Normalne
-
+
Use big toolbar icons
Użyj dużych ikon paska narzędzi
-
+
Big
Duże
-
+
Use huge toolbar icons
Użyj olbrzymich ikon paska narzędzi
-
+
Huge
Olbrzymie
-
+
Czech
Czeski
-
+
Use Czech in menus
Użyj Czeskiego w menu
-
+
German
Niemiecki
-
+
Use German in menus
Użyj Niemieckiego w menu
-
+
English
Angielski
-
+
Use English in menus
Użyj Angielskiego w menu
-
+
Finnish
Fiński
-
+
Use Finnish in menus
Użyj Fińskiego w menu
-
+
French
Francuski
-
+
Use French in menus
Użyj Francuskiego w menu
-
+
Italian
Włoski
-
+
Use Italian in menus
Użyj Włoskiego w menu
-
+
Polish
Polski
-
+
Use Polish in menus
Użyj Polskiego w menu
-
+
Spanish
Hiszpański
-
+
Use Spanish in menus
Użyj hiszpańskiego w menu
-
+
Swedish
Szwedzki
-
+
Use Swedish in menus
Użyj Szwedzkiego w menu
-
+
Edit Radio Splash Image...
Edytor ekranu startowego radia...
-
+
Edit the splash image of your Radio
Edytuj ekran startowy swojego radia
-
-
+
+
Read Firmware from Radio
Odczytaj Firmware z radia
-
+
Read firmware from Radio
Odczytaj Firmware z radia
-
-
+
+
Write Firmware to Radio
Zapisz firmware do radia
-
+
Write firmware to Radio
Zapisz firmware do radia
-
+
Write Models and Settings To Radio
Zapisz Modele i Ustawienia do radia
-
-
+
+
Write Models and Settings to Radio
Zapisz Modele i Ustawienia do radia
-
-
+
+
Read Models and Settings from Radio
Wczytaj Modele i Ustawienia z radia
-
+
Configure software for communicating with the Radio
Ustaw oprogramowanie komunikacyjne z radiem
-
+
Write Backup to Radio
Zapisz Backup do radia
-
+
Backup Radio to File
Zbackupuj radio do pliku
-
+
Save a complete backup file of all settings and model data in the Radio
Zachowaj kompletny plik backup wszystkich ustawień i danych modeli z radia
-
+
Recent Files
Ostatnie Pliki
-
+
Show recent Models+Settings documents
Pokaż ostatnie dokumenty Modeli i Ustawień
-
+
Print current model
Drukuj aktualny model
-
+
Check OpenTX and Companion updates
Sprawdź aktualizacje OpenTX i Companion
-
+
Fuses...
Bezpieczniki...
-
+
Manuals and other Documents
Podręcznik i dokumentacja
-
+
Open the OpenTX document page in a web browser
Otwórz stronę dokumentacji OpenTX w przeglądarce
-
+
A tribute to those who have contributed to OpenTX and Companion
Hołd dla tych, którzy przyczynili się do rozwoju OpenTX i Companion
-
+
Contributors...
Współpracownicy...
-
+
Recent Models+Settings
Ostatnie Modele+Ustawienia
-
+
Set Icon Theme
Ustaw wygląd ikon
-
+
Set Icon Size
Ustaw wielkość ikon
@@ -4571,52 +4570,52 @@ Kolumny wysokości "GAlt" i prędkości "GSpd" są opcjonaln
Dostępna jest nowy Companion (wersja %1)<br>Chcesz ją pobrać ?
-
+
Compilation server requires registration, please check OpenTX web site
Serwer kompilacji wymaga rejestracji, proszę odwiedzić stronę OpenTX
-
+
The selected language will be used the next time you start Companion.
Wybrany język będzie użyty po ponownym uruchomieniu Comapnion.
-
+
The new theme will be loaded the next time you start Companion.
Wybrany wygląd będzie użyty po ponownym uruchomieniu Comapnion.
-
+
The icon size will be used the next time you start Companion.
Wybrana wielkość ikon będzie użyta po ponownym uruchomieniu Comapnion.
-
+
OpenTX Home Page: <a href='%1'>%1</a>
Strona domowa OpenTX: <a href='%1'>%1</a>
-
+
If you've found this program useful, please support by <a href='%1'>donating</a>
Jeśli uważasz, że ten program jest użyteczny, wesprzyj poprzez <a href='%1'>donację</a>
-
+
About Companion
O aplikacji Companion
-
+
Load backup from file
Załaduj backup z pliku
-
+
Exit
Zakończ
-
+
Firmware %1 does not seem to have ever been downloaded.
Release %2 is available.
Do you want to download it now?
@@ -4629,7 +4628,7 @@ Czy chcesz teraz je pobrać?
Zalecamy przeczytanie informacji o wydaniu (przycisk poniżej) w celu poznania zmian które mogą być istotne dla Ciebie.
-
+
A new version of %1 firmware is available:
- current is %2
- newer is %3
@@ -4645,214 +4644,214 @@ Czy chcesz teraz pobrać ?
Zalecamy przeczytanie informacji o wydaniu (przycisk poniżej) w celu poznania zmian które mogą być istotne dla Ciebie.
-
-
-
+
+
+
Companion
Companion
-
-
+
+
Synchronize SD
Zsynchronizuj kartę pamięci
-
+
OpenTX Companion %1 - Radio: %2 - Profile: %3
OpenTX Companion %1 - Radio: %2 - Profil: %3
-
+
Monochrome
Monochromatyczny
-
+
MonoWhite
Mono-Biały
-
+
MonoBlue
Mono-Niebieski
-
+
System language
Język systemu
-
+
Use system language in menus
Użyj języka systemu w menu
-
+
Download...
Pobieranie...
-
+
Check for Updates...
Sprawdź aktualizacje...
-
+
Companion Changes...
Zmiany w Companion...
-
+
Show Companion change log
Pokaż log zmian Companion
-
+
Firmware Changes...
Zmiany w Firmware...
-
+
Show firmware change log
Pokaż log zmian Firmware
-
+
Compare Models...
Porównaj modele...
-
+
List programmers...
Lista programistów...
-
+
Add Radio Profile
Dodaj profil radia
-
+
Configure Communications...
Ustaw komunikację...
-
+
Yerico
-
+
Yellow round honey sweet icon theme
Żółty zaokrąglony miodowy motyw ikon
-
-
+
+
Radio Profile
Profil radia
-
+
Write
Zapis
-
+
%2
%2
-
+
Compare models
Porównaj modele
-
+
Exit the application
Zakończ aplikację companion9x
-
+
List available programmers
Lista dostępnych programatorów
-
+
Show fuses dialog
Pokaż okno ustawień mikro-kontrolera
-
+
Show the application's About box
O aplikacji companion9x
-
+
Copyright OpenTX Team
Prawa Zespół OpenTX
-
+
Classical
Klasyczny
-
+
Write Backup from file to Radio
Zapisz Backup z pliku do radia
-
+
SD card synchronization
Synchronizacja karty SD
-
+
Set Menu Language
Ustaw język menu
-
-
+
+
File
Plik
-
-
+
+
Edit
Edycja
-
+
Settings
Ustawienia
-
+
Read/Write
Odczyt/Zapis
-
-
+
+
Help
Pomoc
-
+
Show the list of radio profiles
Pokaż listę profili radia
-
+
Ready
Gotowe
-
+
New Radio
Nowe Radio
@@ -5642,6 +5641,11 @@ p, li { white-space: pre-wrap; }
Edge(%1, [%2:%3])
Brzeg(%1, [%2:%3])
+
+
+ instant
+ natychmiastowy
+
Sticky(%1, %2)
@@ -8484,43 +8488,43 @@ p, li { white-space: pre-wrap; }
Równoległe użycie expo i krzywych nie jest dłużej wspierane
-
+
Source %1 cannot be exported on this board!
Źródło %1 nie może być wyeksportowane na tę płytę!
-
+
OpenTX only accepts %1 points in all curves
OpenTX zezwala tylko na %1 punktów we wszystkich krzywych
-
+
OpenTx only accepts %1 points in all curves
OpenTX zezwala tylko na %1 punktów we wszystkich krzywych
-
-
-
-
-
+
+
+
+
+
OpenTX on this board doesn't accept this function
OpenTX na tej platformie nie dopuszcza tej funkcji
-
+
OpenTX doesn't accept this telemetry protocol
OpenTX nie obsługuje tego protokołu telemetrii
-
-
-
+
+
+
OpenTX doesn't accept this radio protocol
OpenTX nie obsługuje tego protokołu radiowego
-
+
OpenTX doesn't allow this number of channels
OpenTX nie obsługuje tej ilości kanałów
@@ -8584,8 +8588,8 @@ Zespół OpenTX.
ZG
-
-
+
+
@@ -8593,12 +8597,12 @@ Zespół OpenTX.
Błąd synchronizacji
-
+
No SD directory configured!
Nieskonfigurowany katalog karty SD!
-
+
No Radio connected!
Radio niepodłączone!
@@ -9546,99 +9550,99 @@ Wolne obroty będą na górze, trymer i ostrzeżenie o otwartym gazie również
TelemetryPanel
-
+
Telemetry screen %1
Panel Telemetrii %1
-
+
Low Alarm
Alarm niski
-
+
Critical Alarm
Alarm krytyczny
-
+
Winged Shadow How High
Winged Shadow How High
-
+
Winged Shadow How High (not supported)
Winged Shadow How High (Nie obsługiwane)
-
-
+
+
A1
A1
-
+
Alti
Wysokościomierz
-
+
FrSky S.PORT
-
+
FrSky D
FrSky D
-
+
FrSky D (cable)
FrSky D (kabel)
-
+
Alti+
Wysokościomierz+
-
+
VSpeed
Prędkość Pionowa
-
-
+
+
A2
A2
-
-
+
+
A3
A3
-
-
+
+
A4
A4
-
-
+
+
FAS
FAS
-
+
Cells
Cele
-
+
---
---
diff --git a/doc/Mega2560/MEGA2560.sch b/doc/Mega2560/MEGA2560.sch
index 3d016fc4d..1f54b3989 100644
--- a/doc/Mega2560/MEGA2560.sch
+++ b/doc/Mega2560/MEGA2560.sch
@@ -36,7 +36,7 @@ $Descr A4 11693 8268
encoding utf-8
Sheet 1 1
Title "OpenTX board based on Arduino MEGA2560"
-Date "18 jun 2015"
+Date "21 oct 2015"
Rev "0"
Comp "Copyright 2015 F. Aguerre"
Comment1 ""
@@ -1057,13 +1057,13 @@ Text Label 5650 5850 2 42 ~ 0
SW_Trn
Text GLabel 4850 5850 2 42 Input ~ 0
port L 7 (1)
-Text GLabel 4850 6250 2 42 Output ~ 0
+Text GLabel 4850 6250 2 42 Input ~ 0
port B 3 (1)
Text Label 5650 6250 2 42 ~ 0
SD_MISO
Text Label 6600 6250 2 42 ~ 0
SD_MOSI
-Text GLabel 5800 6250 2 42 Input ~ 0
+Text GLabel 5800 6250 2 42 Output ~ 0
port B 2 (1)
Text GLabel 5800 6350 2 42 Input ~ 0
port B 0 (1)
@@ -1278,7 +1278,7 @@ PPM_OUT
Text GLabel 2100 4600 1 42 Output ~ 0
port B 6 (0)
Text GLabel 2000 4600 1 42 Input ~ 0
-port B 7 (0)
+port E 7 (0)
Text Label 5650 4850 2 42 ~ 0
LCD_DATA0
Text GLabel 4850 4850 2 42 Output ~ 0
@@ -41110,7 +41110,7 @@ CA 3B B1 B4 D6 FB 76 3A 4D 11 32 4D 1E A1 3D 78 1C 8B 1E 14 74 10 57 46 8C 97 FB
33 B3 93 2C A5 90 EC 7D 2B A5 BC 7A F5 EA E1 E1 5E 44 C8 BD 2E 90 84 08 60 87 C2 BB D7 FD 40 85
4A 52 6F 3D D0 6D 9E 6E 41 36 CA 77 04 97 99 83 92 6E D1 7C 20 6D 2C 33 D2 7F 5B 16 F2 83 51 39
A0 3F CF F3 A7 9F 7E FA CB 5F FE F5 EB D7 AF 45 64 59 96 6D DB F6 23 3E B3 52 CA B3 1B C5 00 F7
-08 C0 CC FE 1F 15 4F 30 6D 3D C2 80 DE 00 00 00 00 49 45 4E 44 AE 42 60 82 00 $EndBitmap
+08 C0 CC FE 1F 15 4F 30 6D 3D C2 80 DE 00 00 00 00 49 45 4E 44 AE 42 60 82 04 $EndBitmap
EndData
$EndBitmap
$Comp
@@ -41427,7 +41427,7 @@ Wire Wire Line
Wire Wire Line
2100 4750 2100 4600
Wire Wire Line
- 2000 4750 2000 4600
+ 2000 4600 2000 5550
Wire Wire Line
4700 4850 4850 4850
Wire Wire Line
@@ -41863,4 +41863,8 @@ Wire Wire Line
5300 7500 5300 7600
Wire Wire Line
4800 7500 5300 7500
+Wire Wire Line
+ 2000 5550 2500 5550
+Text Notes 2550 5550 0 50 ~ 0
+Pin 9, can be soldered\nwith pin 8 (unused)
$EndSCHEMATC
diff --git a/doc/Mega2560/MEGA2560_SCH.pdf b/doc/Mega2560/MEGA2560_SCH.pdf
index 6060a3d54..90f6d4393 100644
Binary files a/doc/Mega2560/MEGA2560_SCH.pdf and b/doc/Mega2560/MEGA2560_SCH.pdf differ
diff --git a/doc/Mega2560/MEGA2560_bootloader.rar b/doc/Mega2560/MEGA2560_bootloader.rar
deleted file mode 100644
index 215c50495..000000000
Binary files a/doc/Mega2560/MEGA2560_bootloader.rar and /dev/null differ
diff --git a/radio/releasenotes.txt b/radio/releasenotes.txt
index bfd270c0c..8246af3c6 100644
--- a/radio/releasenotes.txt
+++ b/radio/releasenotes.txt
@@ -1,4 +1,14 @@
-Version 2.1.4 /
+Version 2.1.6 / 2015-11-11
+[Taranis]
+
+Fix for some X9E units which could not shutdown properly
+Fixed a bug with negative altitudes in the Top bar (#3047 )
+
+
+
+Version 2.1.5 / 2015-11-05
+
+Notice: version 2.1.4 was skipped by the OpenTX team to avoid confusion with FrSky's release of OpenTX 2.1.4
[Taranis]
@@ -10,6 +20,11 @@
Trainer mode fixes for X9E (#2913 )
Fixed a bug that caused no servo movement when certain firmware option combinations were used (#2945 )
Fixed missing arrows on RS, LS2, RS2 pot warnings on X9E (#2961 )
+Fixed erroneous haptic feedback when using high powered UHF RF modules (#2722 )
+The trainer icon will be shown only if valid PPM is received
+Several Lua io library fixes (#3001 , #3003 )
+Corrected failsafe mapping when using Custom failsafe mode, D16 protocol and channel range different from from 1-8.
+ Users with such setups are advised to re-check their failsafe settings (#2975 )
[ARM boards]
@@ -24,6 +39,8 @@
[Sky9x / 9XR-PRO / AR9X]
Fixed navigation problem in Telemetry setup (#2951 )
+Fixed: Model Restore broken (#2797 )
+Fixed battery indicator graphics (#2989 )
[AVR boards]
@@ -31,6 +48,11 @@
Mavlink build option was not working (#2950 )
+[Mega2560]
+
+Fixed : mixer update rate was too slow (#2750 )
+
+
Version 2.1.3 / 2015-09-09
@@ -691,4 +713,4 @@ Nothing new (only Companion fixes)
New menu in Main Views / Telemetry Views
Vario sounds improved!
SD Folders renamed. "9XSOUNDS" becomes "SOUNDS", don't forget to update your SD card!
-
\ No newline at end of file
+
diff --git a/radio/src/Makefile b/radio/src/Makefile
index 289049eb9..ffdcfdfd3 100644
--- a/radio/src/Makefile
+++ b/radio/src/Makefile
@@ -379,6 +379,10 @@ WATCHDOG_TEST = NO
# Values = NO, YES
WARNINGS_AS_ERRORS = NO
+# Enable saving of Lua byte-code of all loaded scripts
+# Values = NO, YES
+LUA_COMPILER = NO
+
#------- END BUILD OPTIONS ---------------------------
# Define programs and commands.
@@ -1029,12 +1033,12 @@ ifeq ($(PCB), TARANIS)
endif
CPPDEFS += -DLUA
INCDIRS += $(LUADIR)
- CPPSRC += lua_api.cpp
+ CPPSRC += lua/interface.cpp lua/api_general.cpp lua/api_lcd.cpp lua/api_model.cpp
LUASRC = $(LUADIR)/lapi.c $(LUADIR)/lcode.c $(LUADIR)/lctype.c $(LUADIR)/ldebug.c $(LUADIR)/ldo.c $(LUADIR)/ldump.c $(LUADIR)/lfunc.c $(LUADIR)/lgc.c $(LUADIR)/llex.c $(LUADIR)/lmem.c \
$(LUADIR)/lobject.c $(LUADIR)/lopcodes.c $(LUADIR)/lparser.c $(LUADIR)/lstate.c $(LUADIR)/lstring.c $(LUADIR)/ltable.c $(LUADIR)/lrotable.c $(LUADIR)/ltm.c $(LUADIR)/lundump.c $(LUADIR)/lvm.c $(LUADIR)/lzio.c \
$(LUADIR)/lbaselib.c $(LUADIR)/linit.c $(LUADIR)/lmathlib.c $(LUADIR)/lbitlib.c $(LUADIR)/loadlib.c $(LUADIR)/lauxlib.c $(LUADIR)/ltablib.c $(LUADIR)/lcorolib.c $(LUADIR)/liolib.c
SRC += $(LUASRC)
- LUADEP = lua_exports_taranis.inc
+ LUADEP = lua/lua_exports_taranis.inc
ifeq ($(USE_BIN_ALLOCATOR), YES)
CPPDEFS += -DUSE_BIN_ALLOCATOR
CPPSRC += bin_allocator.cpp
@@ -1157,7 +1161,7 @@ ifeq ($(PCB), FLAMENCO)
$(LUADIR)/lobject.c $(LUADIR)/lopcodes.c $(LUADIR)/lparser.c $(LUADIR)/lstate.c $(LUADIR)/lstring.c $(LUADIR)/ltable.c $(LUADIR)/lrotable.c $(LUADIR)/ltm.c $(LUADIR)/lundump.c $(LUADIR)/lvm.c $(LUADIR)/lzio.c \
$(LUADIR)/lbaselib.c $(LUADIR)/linit.c $(LUADIR)/lmathlib.c $(LUADIR)/lbitlib.c $(LUADIR)/loadlib.c $(LUADIR)/lauxlib.c $(LUADIR)/ltablib.c $(LUADIR)/lcorolib.c $(LUADIR)/liolib.c
SRC += $(LUASRC)
- LUADEP = lua_exports_flamenco.inc
+ LUADEP = lua/lua_exports_flamenco.inc
endif
EXTRABOARDSRC += $(FATFSDIR)/ff.c $(FATFSDIR)/fattime.c $(FATFSDIR)/option/ccsbcs.c targets/Flamenco/diskio.cpp
@@ -1287,7 +1291,7 @@ ifeq ($(PCB), HORUS)
$(LUADIR)/lobject.c $(LUADIR)/lopcodes.c $(LUADIR)/lparser.c $(LUADIR)/lstate.c $(LUADIR)/lstring.c $(LUADIR)/ltable.c $(LUADIR)/lrotable.c $(LUADIR)/ltm.c $(LUADIR)/lundump.c $(LUADIR)/lvm.c $(LUADIR)/lzio.c \
$(LUADIR)/lbaselib.c $(LUADIR)/linit.c $(LUADIR)/lmathlib.c $(LUADIR)/lbitlib.c $(LUADIR)/loadlib.c $(LUADIR)/lauxlib.c $(LUADIR)/ltablib.c $(LUADIR)/lcorolib.c $(LUADIR)/liolib.c
SRC += $(LUASRC)
- LUADEP = lua_exports_horus.inc
+ LUADEP = lua/lua_exports_horus.inc
endif
EXTRABOARDSRC += $(FATFSDIR)/ff.c $(FATFSDIR)/fattime.c $(FATFSDIR)/option/ccsbcs.c targets/Horus/diskio.cpp
@@ -1667,6 +1671,10 @@ ifeq ($(IRPROTOS), YES)
CPPDEFS += -DIRPROTOS
endif
+ifeq ($(LUA_COMPILER), YES)
+ CPPDEFS += -DLUA_COMPILER
+endif
+
#---------------- Compiler Options C++ ----------------
# -g*: generate debugging information
# -O*: optimization level
@@ -1924,25 +1932,25 @@ else
PARSER = gcc -E -x c++
endif
-lua_exports_taranis.inc: myeeprom.h ../util/luaexport.py
+lua/lua_exports_taranis.inc: myeeprom.h ../util/luaexport.py
@echo "Generating a list of Lua exported constants in lua_exports_taranis.txt"
@$(PARSER) -DPCBTARANIS -DCPUARM -DCPUSTM32 -DLUA -DEXPORT myeeprom.h | grep LEXP > lua_exports_taranis.txt
- @echo "Parsing and generating C Lua exports in lua_exports_taranis.inc"
- @$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_taranis.txt lua_exports_taranis.inc lua_fields_taranis.txt
+ @echo "Parsing and generating C Lua exports in lua/lua_exports_taranis.inc"
+ @$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_taranis.txt lua/lua_exports_taranis.inc lua_fields_taranis.txt
@rm lua_exports_taranis.txt
-lua_exports_horus.inc: myeeprom.h ../util/luaexport.py
+lua/lua_exports_horus.inc: myeeprom.h ../util/luaexport.py
@echo "Generating a list of Lua exported constants in lua_exports_horus.txt"
@$(PARSER) -DPCBHORUS -DCPUARM -DCPUSTM32 -DLUA -DEXPORT myeeprom.h | grep LEXP > lua_exports_horus.txt
- @echo "Parsing and generating C Lua exports in lua_exports_horus.inc"
- @$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_horus.txt lua_exports_horus.inc lua_fields_horus.txt
+ @echo "Parsing and generating C Lua exports in lua/lua_exports_horus.inc"
+ @$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_horus.txt lua/lua_exports_horus.inc lua_fields_horus.txt
@rm lua_exports_horus.txt
-lua_exports_flamenco.inc: myeeprom.h ../util/luaexport.py
+lua/lua_exports_flamenco.inc: myeeprom.h ../util/luaexport.py
@echo "Generating a list of Lua exported constants in lua_exports_flamenco.txt"
@$(PARSER) -DPCBFLAMENCO -DCPUARM -DCPUSTM32 -DLUA -DEXPORT myeeprom.h | grep LEXP > lua_exports_flamenco.txt
- @echo "Parsing and generating C Lua exports in lua_exports_flamenco.inc"
- @$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_flamenco.txt lua_exports_flamenco.inc lua_fields_flamenco.txt
+ @echo "Parsing and generating C Lua exports in lua/lua_exports_flamenco.inc"
+ @$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_flamenco.txt lua/lua_exports_flamenco.inc lua_fields_flamenco.txt
@rm lua_exports_flamenco.txt
# Eye candy.
@@ -2101,7 +2109,7 @@ clean_list :
$(REMOVE) bitmaps/*.lbm
$(REMOVE) bitmaps/*/*.lbm
$(REMOVE) fonts/*/*.lbm
- $(REMOVE) lua_exports* lua_fields.txt
+ $(REMOVE) lua_exports*.txt lua_fields.txt lua/lua_exports*.inc
$(MAKE) -C targets/Taranis/bootloader clean
#### Install
diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp
index 422b17171..76dbc244f 100644
--- a/radio/src/cli.cpp
+++ b/radio/src/cli.cpp
@@ -441,8 +441,8 @@ void cliTask(void * pdata)
else if (c == 127) {
// backspace
if (pos) {
- line[--pos] = '\0';
- serialPutc(c);
+ line[--pos] = '\0';
+ serialPutc(c);
}
}
else if (c == '\r' || c == '\n') {
diff --git a/radio/src/functions.cpp b/radio/src/functions.cpp
index c75648b2b..6d0e8b213 100644
--- a/radio/src/functions.cpp
+++ b/radio/src/functions.cpp
@@ -367,8 +367,10 @@ void evalFunctions()
}
#if defined(CPUARM)
if (CFN_PARAM(cfn)>=FUNC_RESET_PARAM_FIRST_TELEM) {
- TelemetryItem * telemetryItem = & telemetryItems[CFN_PARAM(cfn)-FUNC_RESET_PARAM_FIRST_TELEM];
- telemetryItem->clear();
+ uint8_t item = CFN_PARAM(cfn)-FUNC_RESET_PARAM_FIRST_TELEM;
+ if (item < MAX_SENSORS) {
+ telemetryItems[item].clear();
+ }
}
#endif
break;
diff --git a/radio/src/gui/9X/lcd.cpp b/radio/src/gui/9X/lcd.cpp
index ac6901f43..8fa0d523e 100644
--- a/radio/src/gui/9X/lcd.cpp
+++ b/radio/src/gui/9X/lcd.cpp
@@ -881,6 +881,7 @@ void displayGpsCoords(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFl
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, lcdint_t value, LcdFlags att)
{
+ if (channel >= MAX_SENSORS) return;
TelemetryItem & telemetryItem = telemetryItems[channel];
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[channel];
if (telemetrySensor.unit == UNIT_DATETIME) {
@@ -1096,7 +1097,7 @@ void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, lcdint_t v
case TELEM_TX_VOLTAGE-1:
lcd_outdezAtt(x, y, val, (att|PREC1) & (~NO_UNIT));
if (!(att & NO_UNIT))
- lcd_putc(lcdLastPos/*+1*/, y, 'v');
+ lcd_putc(lcdLastPos/*+1*/, y, 'V');
break;
}
}
diff --git a/radio/src/gui/9X/lcd.h b/radio/src/gui/9X/lcd.h
index 6a1e7ba86..14a27318a 100644
--- a/radio/src/gui/9X/lcd.h
+++ b/radio/src/gui/9X/lcd.h
@@ -262,6 +262,13 @@ void lcdInit();
void lcdRefresh();
+#if defined(LCD_ST7920)
+uint8_t lcdRefresh_ST7920(uint8_t full);
+#define IS_LCD_REFRESH_ALLOWED() (0==lcdstate)
+#else
+#define IS_LCD_REFRESH_ALLOWED() (1)
+#endif
+
#if defined(BOOT)
#define BLINK_ON_PHASE (0)
#else
diff --git a/radio/src/gui/9X/menu_model_logical_switches.cpp b/radio/src/gui/9X/menu_model_logical_switches.cpp
index bcb04b521..a66dbcd90 100644
--- a/radio/src/gui/9X/menu_model_logical_switches.cpp
+++ b/radio/src/gui/9X/menu_model_logical_switches.cpp
@@ -185,7 +185,11 @@ void menuModelLogicalSwitchOne(uint8_t event)
else {
#if defined(FRSKY)
if (v1_val >= MIXSRC_FIRST_TELEM) {
+#if defined(CPUARM)
+ putsChannelValue(CSWONE_2ND_COLUMN, y, v1_val, convertLswTelemValue(cs), attr|LEFT);
+#else
putsTelemetryChannelValue(CSWONE_2ND_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), attr|LEFT);
+#endif
v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1);
if (cs->func == LS_FUNC_DIFFEGREATER)
v2_min = -v2_max;
@@ -295,7 +299,11 @@ void menuModelLogicalSwitches(uint8_t event)
uint8_t v1 = cs->v1;
putsMixerSource(CSW_2ND_COLUMN, y, v1, 0);
if (v1 >= MIXSRC_FIRST_TELEM) {
+#if defined(CPUARM)
+ putsChannelValue(CSW_3RD_COLUMN, y, v1, convertLswTelemValue(cs), LEFT);
+#else
putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1 - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT);
+#endif
}
else {
lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT);
diff --git a/radio/src/gui/9X/view_main.cpp b/radio/src/gui/9X/view_main.cpp
index 4e0343530..7241e9a21 100644
--- a/radio/src/gui/9X/view_main.cpp
+++ b/radio/src/gui/9X/view_main.cpp
@@ -42,7 +42,7 @@
#define RBOX_CENTERX (3*LCD_W/4 - 10)
#define MODELNAME_X (2*FW-2)
#define MODELNAME_Y (0)
-#define PHASE_X (6*FW)
+#define PHASE_X (6*FW-1)
#define PHASE_Y (2*FH)
#define PHASE_FLAGS 0
#define VBATT_X (6*FW)
@@ -206,13 +206,13 @@ void displayBattVoltage()
{
#if defined(BATTGRAPH)
putsVBat(VBATT_X-8, VBATT_Y+1, 0);
- drawFilledRect(VBATT_X-25, VBATT_Y+9, 22, 5);
- lcd_vline(VBATT_X-3, VBATT_Y+10, 3);
+ drawFilledRect(VBATT_X-25, VBATT_Y+9, 21, 5);
+ lcd_vline(VBATT_X-4, VBATT_Y+10, 3);
uint8_t count = GET_TXBATT_BARS();
for (uint8_t i=0; i= MAX_SENSORS) return; //Lua luaLcdDrawChannel() can call us with a bad value
TelemetryItem & telemetryItem = telemetryItems[channel];
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[channel];
if (telemetrySensor.unit == UNIT_DATETIME) {
diff --git a/radio/src/gui/Taranis/menu_model_flightmodes.cpp b/radio/src/gui/Taranis/menu_model_flightmodes.cpp
index ad73278d1..72889197a 100644
--- a/radio/src/gui/Taranis/menu_model_flightmodes.cpp
+++ b/radio/src/gui/Taranis/menu_model_flightmodes.cpp
@@ -120,8 +120,10 @@ void menuModelFlightModesAll(uint8_t event)
break;
case ITEM_FLIGHT_MODES_SWITCH:
- putsSwitches((5+LEN_FLIGHT_MODE_NAME)*FW+FW/2, y, p->swtch, attr);
- if (active) CHECK_INCDEC_MODELSWITCH(event, p->swtch, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, isSwitchAvailableInMixes);
+ if (k>0) {
+ putsSwitches((5+LEN_FLIGHT_MODE_NAME)*FW+FW/2, y, p->swtch, attr);
+ if (active) CHECK_INCDEC_MODELSWITCH(event, p->swtch, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, isSwitchAvailableInMixes);
+ }
break;
case ITEM_FLIGHT_MODES_TRIM_RUD:
diff --git a/radio/src/gui/Taranis/menu_model_setup.cpp b/radio/src/gui/Taranis/menu_model_setup.cpp
index 7a5793fab..f79f0e9c8 100644
--- a/radio/src/gui/Taranis/menu_model_setup.cpp
+++ b/radio/src/gui/Taranis/menu_model_setup.cpp
@@ -645,17 +645,14 @@ void menuModelSetup(uint8_t event)
if (checkIncDec_Ret) {
g_model.moduleData[INTERNAL_MODULE].rfProtocol = 0;
g_model.moduleData[INTERNAL_MODULE].channelsStart = 0;
- if (g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_PPM)
- g_model.moduleData[INTERNAL_MODULE].channelsCount = 0;
- else
- g_model.moduleData[INTERNAL_MODULE].channelsCount = MAX_INTERNAL_MODULE_CHANNELS();
+ g_model.moduleData[INTERNAL_MODULE].channelsCount = 0;
}
break;
case 1:
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[INTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST);
if (checkIncDec_Ret) {
g_model.moduleData[INTERNAL_MODULE].channelsStart = 0;
- g_model.moduleData[INTERNAL_MODULE].channelsCount = MAX_INTERNAL_MODULE_CHANNELS();
+ g_model.moduleData[INTERNAL_MODULE].channelsCount = 0;
}
}
}
@@ -667,6 +664,7 @@ void menuModelSetup(uint8_t event)
if (attr) {
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].rfProtocol, RF_PROTO_OFF, RF_PROTO_LAST);
if (checkIncDec_Ret) {
+ g_model.moduleData[0].type = MODULE_TYPE_XJT;
g_model.moduleData[0].channelsStart = 0;
g_model.moduleData[0].channelsCount = 0;
}
@@ -695,10 +693,8 @@ void menuModelSetup(uint8_t event)
if (checkIncDec_Ret) {
g_model.moduleData[EXTERNAL_MODULE].rfProtocol = 0;
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
- if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM)
- g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0;
- else
- g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_EXTERNAL_MODULE_CHANNELS();
+ g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0;
+
}
break;
case 1:
@@ -708,7 +704,7 @@ void menuModelSetup(uint8_t event)
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST);
if (checkIncDec_Ret) {
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
- g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_EXTERNAL_MODULE_CHANNELS();
+ g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0;
}
}
}
@@ -785,7 +781,7 @@ void menuModelSetup(uint8_t event)
else {
horzpos_t l_posHorz = m_posHorz;
coord_t xOffsetBind = MODEL_SETUP_BIND_OFS;
- if (IS_MODULE_XJT(moduleIdx) && !HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[moduleIdx].rfProtocol)) {
+ if (IS_MODULE_XJT(moduleIdx) && g_model.moduleData[moduleIdx].rfProtocol == RF_PROTO_D8) {
xOffsetBind = 0;
lcd_putsLeft(y, INDENT "Receiver");
if (attr) l_posHorz += 1;
@@ -871,14 +867,16 @@ void menuModelFailsafe(uint8_t event)
static bool longNames = false;
bool newLongNames = false;
uint8_t ch = 0;
+ uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart;
if (event == EVT_KEY_LONG(KEY_ENTER)) {
killEvents(event);
event = 0;
if (s_editMode) {
- g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert];
+ g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert+channelStart];
storageDirty(EE_MODEL);
AUDIO_WARNING1();
+ s_editMode = 0;
SEND_FAILSAFE_NOW(g_moduleIdx);
}
else {
@@ -888,14 +886,14 @@ void menuModelFailsafe(uint8_t event)
else if (failsafe == FAILSAFE_CHANNEL_HOLD)
failsafe = FAILSAFE_CHANNEL_NOPULSE;
else
- failsafe = channelOutputs[m_posVert];
+ failsafe = 0;
storageDirty(EE_MODEL);
AUDIO_WARNING1();
SEND_FAILSAFE_NOW(g_moduleIdx);
}
}
- SIMPLE_SUBMENU_NOTITLE(NUM_CHNOUT);
+ SIMPLE_SUBMENU_NOTITLE(NUM_CHANNELS(g_moduleIdx));
SET_SCROLLBAR_X(0);
@@ -904,10 +902,6 @@ void menuModelFailsafe(uint8_t event)
// Column separator
lcd_vline(LCD_W/2, FH, LCD_H-FH);
- if (m_posVert >= 16) {
- ch = 16;
- }
-
lcd_putsCenter(0*FH, FAILSAFESET);
lcd_invert_line(0);
@@ -919,77 +913,78 @@ void menuModelFailsafe(uint8_t event)
// Channels
for (uint8_t line=0; line<8; line++) {
coord_t y = 9+line*7;
- int32_t channelValue = channelOutputs[ch];
+ int32_t channelValue = channelOutputs[ch+channelStart];
int32_t failsafeValue = 0;
bool failsafeEditable = false;
uint8_t ofs = (col ? 0 : 1);
- if (ch >= g_model.moduleData[g_moduleIdx].channelsStart && ch < NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart) {
+ if (ch < NUM_CHANNELS(g_moduleIdx)) {
failsafeValue = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line];
failsafeEditable = true;
}
- // Channel name if present, number if not
- uint8_t lenLabel = ZLEN(g_model.limitData[ch].name);
- if (lenLabel > 4) {
- newLongNames = longNames = true;
- }
+ if (failsafeEditable) {
+ // Channel name if present, number if not
+ uint8_t lenLabel = ZLEN(g_model.limitData[ch+channelStart].name);
+ if (lenLabel > 4) {
+ newLongNames = longNames = true;
+ }
- if (lenLabel > 0)
- lcdDrawTextWithLen(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE);
- else
- putsChn(x+1-ofs, y, ch+1, SMLSIZE);
+ if (lenLabel > 0)
+ lcdDrawTextWithLen(x+1-ofs, y, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR | SMLSIZE);
+ else
+ putsChn(x+1-ofs, y, ch+1, SMLSIZE);
- // Value
- LcdFlags flags = TINSIZE;
- if (m_posVert == ch) {
- flags |= INVERS;
- if (s_editMode) {
- if (!failsafeEditable || failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- s_editMode = 0;
- }
- else {
- flags |= BLINK;
- CHECK_INCDEC_MODELVAR(event, g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line], -lim, +lim);
+ // Value
+ LcdFlags flags = TINSIZE;
+ if (m_posVert == ch) {
+ flags |= INVERS;
+ if (s_editMode) {
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ s_editMode = 0;
+ }
+ else {
+ flags |= BLINK;
+ CHECK_INCDEC_MODELVAR(event, g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line], -lim, +lim);
+ }
}
}
- }
#if defined(PPM_UNIT_PERCENT_PREC1)
- uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6);
+ uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6);
#else
- uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
+ uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
#endif
- if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
- lcdDrawText(x+COL_W-4-wbar-ofs-16, y, "HOLD", flags);
- failsafeValue = 0;
- }
- else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- lcdDrawText(x+COL_W-4-wbar-ofs-16, y, "NONE", flags);
- failsafeValue = 0;
- }
- else {
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
+ lcdDrawText(x+COL_W-4-wbar-ofs-16, y, "HOLD", flags);
+ failsafeValue = 0;
+ }
+ else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ lcdDrawText(x+COL_W-4-wbar-ofs-16, y, "NONE", flags);
+ failsafeValue = 0;
+ }
+ else {
#if defined(PPM_UNIT_US)
- lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+failsafeValue/2, flags);
+ lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+failsafeValue/2, flags);
#elif defined(PPM_UNIT_PERCENT_PREC1)
- lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue), PREC1|flags);
+ lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue), PREC1|flags);
#else
- lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue)/10, flags);
+ lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue)/10, flags);
#endif
- }
-
- // Gauge
- lcdDrawRect(x+COL_W-3-wbar-ofs, y, wbar+1, 6);
- unsigned int lenChannel = limit((uint8_t)1, uint8_t((abs(channelValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2));
- unsigned int lenFailsafe = limit((uint8_t)1, uint8_t((abs(failsafeValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2));
- coord_t xChannel = (channelValue>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-lenChannel;
- coord_t xFailsafe = (failsafeValue>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-lenFailsafe;
- lcdDrawHorizontalLine(xChannel, y+1, lenChannel, DOTTED, 0);
- lcdDrawHorizontalLine(xChannel, y+2, lenChannel, DOTTED, 0);
- lcd_hline(xFailsafe, y+3, lenFailsafe);
- lcd_hline(xFailsafe, y+4, lenFailsafe);
-
+ }
+
+ // Gauge
+ lcdDrawRect(x+COL_W-3-wbar-ofs, y, wbar+1, 6);
+ unsigned int lenChannel = limit((uint8_t)1, uint8_t((abs(channelValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2));
+ unsigned int lenFailsafe = limit((uint8_t)1, uint8_t((abs(failsafeValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2));
+ coord_t xChannel = (channelValue>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-lenChannel;
+ coord_t xFailsafe = (failsafeValue>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-lenFailsafe;
+ lcdDrawHorizontalLine(xChannel, y+1, lenChannel, DOTTED, 0);
+ lcdDrawHorizontalLine(xChannel, y+2, lenChannel, DOTTED, 0);
+ lcd_hline(xFailsafe, y+3, lenFailsafe);
+ lcd_hline(xFailsafe, y+4, lenFailsafe);
+ }
ch++;
}
}
diff --git a/radio/src/gui/Taranis/menu_model_telemetry.cpp b/radio/src/gui/Taranis/menu_model_telemetry.cpp
index 9edb46800..5370cbc2f 100644
--- a/radio/src/gui/Taranis/menu_model_telemetry.cpp
+++ b/radio/src/gui/Taranis/menu_model_telemetry.cpp
@@ -164,12 +164,8 @@ enum SensorFields {
bool isSensorUnit(int sensor, uint8_t unit)
{
- if (sensor == 0)
- return true;
-
- sensor -= 1;
-
- return g_model.telemetrySensors[sensor].unit == unit;
+ if (sensor <= 0 || sensor > MAX_SENSORS ) return true;
+ return g_model.telemetrySensors[--sensor].unit == unit;
}
bool isCellsSensor(int sensor)
@@ -184,7 +180,7 @@ bool isGPSSensor(int sensor)
bool isAltSensor(int sensor)
{
- return isSensorUnit(sensor, UNIT_DIST);
+ return isSensorUnit(sensor, UNIT_DIST) || isSensorUnit(sensor, UNIT_FEET);
}
bool isVoltsSensor(int sensor)
diff --git a/radio/src/gui/Taranis/view_main.cpp b/radio/src/gui/Taranis/view_main.cpp
index ef4a30465..6d9526d59 100644
--- a/radio/src/gui/Taranis/view_main.cpp
+++ b/radio/src/gui/Taranis/view_main.cpp
@@ -236,22 +236,26 @@ void displayTopBar()
/* Rx voltage */
altitude_icon_x = batt_icon_x+7*FW+3;
if (g_model.frsky.voltsSource) {
- TelemetryItem & voltsItem = telemetryItems[g_model.frsky.voltsSource-1];
- if (voltsItem.isAvailable()) {
- putsTelemetryChannelValue(batt_icon_x+7*FW+2, BAR_Y+1, g_model.frsky.voltsSource-1, voltsItem.value, LEFT);
- altitude_icon_x = lcdLastPos+1;
+ uint8_t item = g_model.frsky.voltsSource-1;
+ if (item < MAX_SENSORS) {
+ TelemetryItem & voltsItem = telemetryItems[item];
+ if (voltsItem.isAvailable()) {
+ putsTelemetryChannelValue(batt_icon_x+7*FW+2, BAR_Y+1, item, voltsItem.value, LEFT);
+ altitude_icon_x = lcdLastPos+1;
+ }
}
}
/* Altitude */
if (g_model.frsky.altitudeSource) {
- TelemetryItem & altitudeItem = telemetryItems[g_model.frsky.altitudeSource-1];
- if (altitudeItem.isAvailable()) {
- LCD_ICON(altitude_icon_x, BAR_Y, ICON_ALTITUDE);
- int32_t value = altitudeItem.value;
- TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1];
- if (sensor.prec) value /= sensor.prec == 2 ? 100 : 10;
- putsValueWithUnit(altitude_icon_x+2*FW-1, BAR_Y+1, value, UNIT_METERS, LEFT);
+ uint8_t item = g_model.frsky.altitudeSource-1;
+ if (item < MAX_SENSORS) {
+ TelemetryItem & altitudeItem = telemetryItems[item];
+ if (altitudeItem.isAvailable()) {
+ LCD_ICON(altitude_icon_x, BAR_Y, ICON_ALTITUDE);
+ int32_t value = altitudeItem.value / g_model.telemetrySensors[item].getPrecDivisor();
+ putsValueWithUnit(altitude_icon_x+2*FW-1, BAR_Y+1, value, g_model.telemetrySensors[item].unit, LEFT);
+ }
}
}
}
@@ -271,11 +275,12 @@ void displayTopBar()
if (TRAINER_CONNECTED()) {
if (SLAVE_MODE()) {
LCD_NOTIF_ICON(x, ICON_TRAINEE);
+ x -= 12;
}
- else {
+ else if (IS_TRAINER_INPUT_VALID()) {
LCD_NOTIF_ICON(x, ICON_TRAINER);
+ x -= 12;
}
- x -= 12;
}
if (isFunctionActive(FUNCTION_LOGS)) {
diff --git a/radio/src/lua/.gitignore b/radio/src/lua/.gitignore
new file mode 100644
index 000000000..38bbdd34f
--- /dev/null
+++ b/radio/src/lua/.gitignore
@@ -0,0 +1 @@
+/lua_exports_*.inc
diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp
new file mode 100644
index 000000000..19ca96d79
--- /dev/null
+++ b/radio/src/lua/api_general.cpp
@@ -0,0 +1,749 @@
+/*
+ * Authors (alphabetical order)
+ * - Andre Bernet
+ * - Andreas Weitl
+ * - Bertrand Songis
+ * - Bryan J. Rentoul (Gruvin)
+ * - Cameron Weeks
+ * - Erez Raviv
+ * - Gabriel Birkus
+ * - Jean-Pierre Parisy
+ * - Karl Szmutny
+ * - Michael Blandford
+ * - Michal Hlavinka
+ * - Pat Mackenzie
+ * - Philip Moss
+ * - Rob Thomson
+ * - Romolo Manfredini
+ * - Thomas Husterer
+ *
+ * opentx is based on code named
+ * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
+ * er9x by Erez Raviv: http://code.google.com/p/er9x/,
+ * and the original (and ongoing) project by
+ * Thomas Husterer, th9x: http://code.google.com/p/th9x/
+ *
+ * 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
+#include
+#include "opentx.h"
+#include "stamp-opentx.h"
+#include "lua/lua_api.h"
+
+#if defined(PCBHORUS)
+#include "lua/lua_exports_horus.inc" // this line must be after lua headers
+#elif defined(PCBFLAMENCO)
+#include "lua/lua_exports_flamenco.inc"
+#elif defined(PCBTARANIS)
+#include "lua/lua_exports_taranis.inc"
+#endif
+
+#if defined(PCBTARANIS) && defined(REV9E)
+ #define RADIO "taranisx9e"
+#elif defined(PCBTARANIS) && defined(REVPLUS)
+ #define RADIO "taranisplus"
+#elif defined(PCBTARANIS)
+ #define RADIO "taranis"
+#else
+#error "Unknown board"
+#endif
+
+#if defined(SIMU)
+ #define RADIO_VERSION RADIO"-simu"
+#else
+ #define RADIO_VERSION RADIO
+#endif
+
+#define FIND_FIELD_DESC 0x01
+
+struct LuaField {
+ uint16_t id;
+ char desc[50];
+};
+
+/*luadoc
+@function getVersion()
+
+Returns OpenTX version
+
+@retval string OpenTX version (ie "2.1.5")
+
+@retval list (available since OpenTX 2.1.7) returns two values:
+ * `string` OpenTX version (ie "2.1.5")
+ * `string` radio version: `taranisx9e`, `taranisplus` or `taranis`.
+If running in simulator the "-simu" is added
+
+@status current Introduced in 2.0.0, expanded in 2.1.7
+
+### Example
+
+This example also runs in OpenTX versions where the radio version was not available:
+
+```lua
+local function run(event)
+ local ver, radio = getVersion()
+ print("version: "..ver)
+ if radio then print ("radio: "..radio) end
+ return 1
+end
+
+return { run=run }
+```
+Output of above script in simulator:
+```
+version: 2.1.7
+radio: taranis-simu
+Script finished with status 1
+```
+*/
+static int luaGetVersion(lua_State *L)
+{
+ lua_pushstring(L, VERS_STR);
+ lua_pushstring(L, RADIO_VERSION);
+ return 2;
+}
+
+/*luadoc
+@function getTime()
+
+Returns the time since the radio was started in multiple of 10ms
+
+@retval number Number of 10ms ticks since the radio was started Example:
+run time: 12.54 seconds, return value: 1254
+
+@status current Introduced in 2.0.0
+*/
+static int luaGetTime(lua_State *L)
+{
+ lua_pushunsigned(L, get_tmr10ms());
+ return 1;
+}
+
+static void luaPushDateTime(lua_State *L, uint32_t year, uint32_t mon, uint32_t day,
+ uint32_t hour, uint32_t min, uint32_t sec)
+{
+ lua_createtable(L, 0, 6);
+ lua_pushtableinteger(L, "year", year);
+ lua_pushtableinteger(L, "mon", mon);
+ lua_pushtableinteger(L, "day", day);
+ lua_pushtableinteger(L, "hour", hour);
+ lua_pushtableinteger(L, "min", min);
+ lua_pushtableinteger(L, "sec", sec);
+}
+
+/*luadoc
+@function getDateTime()
+
+Returns current system date and time that is kept by the RTC unit
+
+@retval table current date and time, table elements:
+ * `year` year
+ * `mon` month
+ * `day` day of month
+ * `hour` hours
+ * `min` minutes
+ * `sec` seconds
+*/
+static int luaGetDateTime(lua_State *L)
+{
+ struct gtm utm;
+ gettime(&utm);
+ luaPushDateTime(L, utm.tm_year + 1900, utm.tm_mon + 1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec);
+ return 1;
+}
+
+static void luaPushLatLon(TelemetrySensor & telemetrySensor, TelemetryItem & telemetryItem)
+/* result is lua table containing members ["lat"] and ["lon"] as lua_Number (doubles) in decimal degrees */
+{
+ lua_Number lat = 0.0;
+ lua_Number lon = 0.0;
+ uint32_t gpsLat = 0;
+ uint32_t gpsLon = 0;
+
+ telemetryItem.gps.extractLatitudeLongitude(&gpsLat, &gpsLon); /* close, but not the format we want */
+ lat = gpsLat / 1000000.0;
+ if (telemetryItem.gps.latitudeNS == 'S') lat = -lat;
+ lon = gpsLon / 1000000.0;
+ if (telemetryItem.gps.longitudeEW == 'W') lon = -lon;
+
+ lua_createtable(L, 0, 2);
+ lua_pushtablenumber(L, "lat", lat);
+ lua_pushtablenumber(L, "lon", lon);
+}
+
+static void luaPushTelemetryDateTime(TelemetrySensor & telemetrySensor, TelemetryItem & telemetryItem)
+{
+ luaPushDateTime(L, telemetryItem.datetime.year + 2000, telemetryItem.datetime.month, telemetryItem.datetime.day,
+ telemetryItem.datetime.hour, telemetryItem.datetime.min, telemetryItem.datetime.sec);
+}
+
+static void luaPushCells(TelemetrySensor & telemetrySensor, TelemetryItem & telemetryItem)
+{
+ if (telemetryItem.cells.count == 0)
+ lua_pushinteger(L, (int)0); // returns zero if no cells
+ else {
+ lua_createtable(L, telemetryItem.cells.count, 0);
+ for (int i = 0; i < telemetryItem.cells.count; i++) {
+ lua_pushnumber(L, i + 1);
+ lua_pushnumber(L, telemetryItem.cells.values[i].value / 100.0);
+ lua_settable(L, -3);
+ }
+ }
+}
+
+void luaGetValueAndPush(int src)
+{
+ getvalue_t value = getValue(src); // ignored for GPS, DATETIME, and CELLS
+
+ if (src >= MIXSRC_FIRST_TELEM && src <= MIXSRC_LAST_TELEM) {
+ src = (src-MIXSRC_FIRST_TELEM) / 3;
+ // telemetry values
+ if (TELEMETRY_STREAMING() && telemetryItems[src].isAvailable()) {
+ TelemetrySensor & telemetrySensor = g_model.telemetrySensors[src];
+ switch (telemetrySensor.unit) {
+ case UNIT_GPS:
+ luaPushLatLon(telemetrySensor, telemetryItems[src]);
+ break;
+ case UNIT_DATETIME:
+ luaPushTelemetryDateTime(telemetrySensor, telemetryItems[src]);
+ break;
+ case UNIT_CELLS:
+ luaPushCells(telemetrySensor, telemetryItems[src]);
+ break;
+ default:
+ if (telemetrySensor.prec > 0)
+ lua_pushnumber(L, float(value)/telemetrySensor.getPrecDivisor());
+ else
+ lua_pushinteger(L, value);
+ break;
+ }
+ }
+ else {
+ // telemetry not working, return zero for telemetry sources
+ lua_pushinteger(L, (int)0);
+ }
+ }
+ else if (src == MIXSRC_TX_VOLTAGE) {
+ lua_pushnumber(L, float(value)/10.0);
+ }
+ else {
+ lua_pushinteger(L, value);
+ }
+}
+
+/**
+ Return field data for a given field name
+*/
+bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags=0)
+{
+ // TODO better search method (binary lookup)
+ for (unsigned int n=0; n
+ * - Andreas Weitl
+ * - Bertrand Songis
+ * - Bryan J. Rentoul (Gruvin)
+ * - Cameron Weeks
+ * - Erez Raviv
+ * - Gabriel Birkus
+ * - Jean-Pierre Parisy
+ * - Karl Szmutny
+ * - Michael Blandford
+ * - Michal Hlavinka
+ * - Pat Mackenzie
+ * - Philip Moss
+ * - Rob Thomson
+ * - Romolo Manfredini
+ * - Thomas Husterer
+ *
+ * opentx is based on code named
+ * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
+ * er9x by Erez Raviv: http://code.google.com/p/er9x/,
+ * and the original (and ongoing) project by
+ * Thomas Husterer, th9x: http://code.google.com/p/th9x/
+ *
+ * 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
+#include
+#include "opentx.h"
+#include "lua/lua_api.h"
+
+/*luadoc
+@function lcd.lock()
+
+@notice This function has no effect in OpenTX 2.1
+*/
+static int luaLcdLock(lua_State *L)
+{
+ // disabled in opentx 2.1
+ // TODO: remove this function completely in opentx 2.2
+ return 0;
+}
+
+/*luadoc
+@function lcd.clear()
+
+Erases all contents of LCD.
+
+@notice This function only works in stand-alone and telemetry scripts.
+*/
+static int luaLcdClear(lua_State *L)
+{
+ if (luaLcdAllowed) lcdClear();
+ return 0;
+}
+
+/*luadoc
+@function lcd.drawPoint(x, y)
+
+Draws a single pixel on LCD
+
+@param x (positive number) x position, starts from 0 in top left corner.
+
+@param y (positive number) y position, starts from 0 in top left corner and goes down.
+
+@notice Drawing on an existing black pixel produces white pixel (TODO check this!)
+*/
+static int luaLcdDrawPoint(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ lcd_plot(x, y);
+ return 0;
+}
+
+/*luadoc
+@function lcd.drawLine(x1, y1, x2, y2, pattern, flags)
+
+Draws a straight line on LCD
+
+@param x1,y1 (positive numbers) starting coordinate
+
+@param x2,y2 (positive numbers) end coordinate
+
+@param pattern TODO
+
+@param flags TODO
+
+@notice If the start or the end of the line is outside the LCD dimensions, then the
+whole line will not be drawn (starting from OpenTX 2.1.5)
+*/
+static int luaLcdDrawLine(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x1 = luaL_checkinteger(L, 1);
+ int y1 = luaL_checkinteger(L, 2);
+ int x2 = luaL_checkinteger(L, 3);
+ int y2 = luaL_checkinteger(L, 4);
+ int pat = luaL_checkinteger(L, 5);
+ int flags = luaL_checkinteger(L, 6);
+ lcdDrawLine(x1, y1, x2, y2, pat, flags);
+ return 0;
+}
+
+static int luaLcdGetLastPos(lua_State *L)
+{
+ lua_pushinteger(L, lcdLastPos);
+ return 1;
+}
+
+static int luaLcdDrawText(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ const char * s = luaL_checkstring(L, 3);
+ unsigned int att = luaL_optunsigned(L, 4, 0);
+ lcdDrawText(x, y, s, att);
+ return 0;
+}
+
+static int luaLcdDrawTimer(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ int seconds = luaL_checkinteger(L, 3);
+ unsigned int att = luaL_optunsigned(L, 4, 0);
+#if defined(PCBFLAMENCO)
+ putsTimer(x, y, seconds, att|LEFT);
+#else
+ putsTimer(x, y, seconds, att|LEFT, att);
+#endif
+ return 0;
+}
+
+static int luaLcdDrawNumber(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ float val = luaL_checknumber(L, 3);
+ unsigned int att = luaL_optunsigned(L, 4, 0);
+ int n;
+ if ((att & PREC2) == PREC2)
+ n = val * 100;
+ else if ((att & PREC1) == PREC1)
+ n = val * 10;
+ else
+ n = val;
+ lcd_outdezAtt(x, y, n, att);
+ return 0;
+}
+
+static int luaLcdDrawChannel(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ int channel = -1;
+ if (lua_isnumber(L, 3)) {
+ channel = luaL_checkinteger(L, 3);
+ }
+ else {
+ const char * what = luaL_checkstring(L, 3);
+ LuaField field;
+ bool found = luaFindFieldByName(what, field);
+ if (found) {
+ channel = field.id;
+ }
+ }
+ unsigned int att = luaL_optunsigned(L, 4, 0);
+ getvalue_t value = getValue(channel);
+ putsTelemetryChannelValue(x, y, (channel-MIXSRC_FIRST_TELEM)/3, value, att);
+ return 0;
+}
+
+static int luaLcdDrawSwitch(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ int s = luaL_checkinteger(L, 3);
+ unsigned int att = luaL_optunsigned(L, 4, 0);
+ putsSwitches(x, y, s, att);
+ return 0;
+}
+
+static int luaLcdDrawSource(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ int s = luaL_checkinteger(L, 3);
+ unsigned int att = luaL_optunsigned(L, 4, 0);
+ putsMixerSource(x, y, s, att);
+ return 0;
+}
+
+#if !defined(COLORLCD)
+static int luaLcdDrawPixmap(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ const char * filename = luaL_checkstring(L, 3);
+ uint8_t bitmap[BITMAP_BUFFER_SIZE(LCD_W/2, LCD_H)]; // width max is LCD_W/2 pixels for saving stack and avoid a malloc here
+ const pm_char * error = bmpLoad(bitmap, filename, LCD_W/2, LCD_H);
+ if (!error) {
+ lcd_bmp(x, y, bitmap);
+ }
+ return 0;
+}
+#endif
+
+static int luaLcdDrawRectangle(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ int w = luaL_checkinteger(L, 3);
+ int h = luaL_checkinteger(L, 4);
+ unsigned int flags = luaL_optunsigned(L, 5, 0);
+ lcdDrawRect(x, y, w, h, 0xff, flags);
+ return 0;
+}
+
+static int luaLcdDrawFilledRectangle(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ int w = luaL_checkinteger(L, 3);
+ int h = luaL_checkinteger(L, 4);
+ unsigned int flags = luaL_optunsigned(L, 5, 0);
+ drawFilledRect(x, y, w, h, SOLID, flags);
+ return 0;
+}
+
+static int luaLcdDrawGauge(lua_State *L)
+{
+ if (!luaLcdAllowed) return 0;
+ int x = luaL_checkinteger(L, 1);
+ int y = luaL_checkinteger(L, 2);
+ int w = luaL_checkinteger(L, 3);
+ int h = luaL_checkinteger(L, 4);
+ int num = luaL_checkinteger(L, 5);
+ int den = luaL_checkinteger(L, 6);
+ // int flags = luaL_checkinteger(L, 7);
+ lcdDrawRect(x, y, w, h);
+ uint8_t len = limit((uint8_t)1, uint8_t(w*num/den), uint8_t(w));
+ for (int i=1; i= count) {
+ // TODO error
+ }
+ if (flags & BLINK) {
+ drawFilledRect(x, y, w-9, count*9+2, SOLID, ERASE);
+ lcdDrawRect(x, y, w-9, count*9+2);
+ for (int i=0; i
+ * - Andreas Weitl
+ * - Bertrand Songis
+ * - Bryan J. Rentoul (Gruvin)
+ * - Cameron Weeks
+ * - Erez Raviv
+ * - Gabriel Birkus
+ * - Jean-Pierre Parisy
+ * - Karl Szmutny
+ * - Michael Blandford
+ * - Michal Hlavinka
+ * - Pat Mackenzie
+ * - Philip Moss
+ * - Rob Thomson
+ * - Romolo Manfredini
+ * - Thomas Husterer
+ *
+ * opentx is based on code named
+ * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
+ * er9x by Erez Raviv: http://code.google.com/p/er9x/,
+ * and the original (and ongoing) project by
+ * Thomas Husterer, th9x: http://code.google.com/p/th9x/
+ *
+ * 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
+#include
+#include "opentx.h"
+#include "lua/lua_api.h"
+#include "timers.h"
+
+static int luaModelGetInfo(lua_State *L)
+{
+ lua_newtable(L);
+ lua_pushtablezstring(L, "name", g_model.header.name);
+ lua_pushtablenzstring(L, "bitmap", g_model.header.bitmap);
+ return 1;
+}
+
+static int luaModelSetInfo(lua_State *L)
+{
+ luaL_checktype(L, -1, LUA_TTABLE);
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ luaL_checktype(L, -2, LUA_TSTRING); // key is string
+ const char * key = luaL_checkstring(L, -2);
+ if (!strcmp(key, "name")) {
+ const char * name = luaL_checkstring(L, -1);
+ str2zchar(g_model.header.name, name, sizeof(g_model.header.name));
+ memcpy(modelHeaders[g_eeGeneral.currModel].name, g_model.header.name, sizeof(g_model.header.name));
+ }
+ else if (!strcmp(key, "bitmap")) {
+ const char * name = luaL_checkstring(L, -1);
+ strncpy(g_model.header.bitmap, name, sizeof(g_model.header.bitmap));
+ }
+ }
+ storageDirty(EE_MODEL);
+ return 0;
+}
+
+static int luaModelGetModule(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < NUM_MODULES) {
+ ModuleData & module = g_model.moduleData[idx];
+ lua_newtable(L);
+ lua_pushtableinteger(L, "rfProtocol", module.rfProtocol);
+ lua_pushtableinteger(L, "modelId", g_model.header.modelId[idx]);
+ lua_pushtableinteger(L, "firstChannel", module.channelsStart);
+ lua_pushtableinteger(L, "channelsCount", module.channelsCount + 8);
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int luaModelSetModule(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+
+ if (idx < NUM_MODULES) {
+ ModuleData & module = g_model.moduleData[idx];
+ luaL_checktype(L, -1, LUA_TTABLE);
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ luaL_checktype(L, -2, LUA_TSTRING); // key is string
+ const char * key = luaL_checkstring(L, -2);
+ if (!strcmp(key, "rfProtocol")) {
+ module.rfProtocol = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "modelId")) {
+ g_model.header.modelId[idx] = modelHeaders[g_eeGeneral.currModel].modelId[idx] = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "firstChannel")) {
+ module.channelsStart = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "channelsCount")) {
+ module.channelsCount = luaL_checkinteger(L, -1) - 8;
+ }
+ }
+ storageDirty(EE_MODEL);
+ }
+ return 0;
+}
+
+static int luaModelGetTimer(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < MAX_TIMERS) {
+ TimerData & timer = g_model.timers[idx];
+ lua_newtable(L);
+ lua_pushtableinteger(L, "mode", timer.mode);
+ lua_pushtableinteger(L, "start", timer.start);
+ lua_pushtableinteger(L, "value", timersStates[idx].val);
+ lua_pushtableinteger(L, "countdownBeep", timer.countdownBeep);
+ lua_pushtableboolean(L, "minuteBeep", timer.minuteBeep);
+ lua_pushtableinteger(L, "persistent", timer.persistent);
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int luaModelSetTimer(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+
+ if (idx < MAX_TIMERS) {
+ TimerData & timer = g_model.timers[idx];
+ luaL_checktype(L, -1, LUA_TTABLE);
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ luaL_checktype(L, -2, LUA_TSTRING); // key is string
+ const char * key = luaL_checkstring(L, -2);
+ if (!strcmp(key, "mode")) {
+ timer.mode = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "start")) {
+ timer.start = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "value")) {
+ timersStates[idx].val = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "countdownBeep")) {
+ timer.countdownBeep = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "minuteBeep")) {
+ timer.minuteBeep = lua_toboolean(L, -1);
+ }
+ else if (!strcmp(key, "persistent")) {
+ timer.persistent = luaL_checkinteger(L, -1);
+ }
+ }
+ storageDirty(EE_MODEL);
+ }
+ return 0;
+}
+
+static int luaModelResetTimer(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < MAX_TIMERS) {
+ timerReset(idx);
+ }
+ return 0;
+}
+
+static unsigned int getFirstInput(unsigned int chn)
+{
+ for (unsigned int i=0; isrcRaw || expo->chn >= chn) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+static unsigned int getInputsCountFromFirst(unsigned int chn, unsigned int first)
+{
+ unsigned int count = 0;
+ for (unsigned int i=first; isrcRaw || expo->chn!=chn) break;
+ count++;
+ }
+ return count;
+}
+
+static unsigned int getInputsCount(unsigned int chn)
+{
+ return getInputsCountFromFirst(chn, getFirstInput(chn));
+}
+
+/*luadoc
+@function model.getInputsCount(input)
+
+Returns number of lines for given input
+
+@param input (unsigned number) input number (use 0 for Input1)
+
+@retval number number of configured lines for given input
+
+@status current Introduced in 2.0.0
+*/
+static int luaModelGetInputsCount(lua_State *L)
+{
+ unsigned int chn = luaL_checkunsigned(L, 1);
+ int count = getInputsCount(chn);
+ lua_pushinteger(L, count);
+ return 1;
+}
+
+/*luadoc
+@function model.getInput(input, line)
+
+Returns input data for given input and line number
+
+@param input (unsigned number) input number (use 0 for Input1)
+
+@param line (unsigned number) input line (use 0 for first line)
+
+@retval nil requested input or line does not exist
+
+@retval table input data:
+ * `name` (string) input line name
+ * `source` (number) input source index
+ * `weight` (number) input weight
+ * `offset` (number) input offset
+ * `switch` (number) input switch index
+
+@status current Introduced in 2.0.0, `switch` added in TODO
+*/
+static int luaModelGetInput(lua_State *L)
+{
+ unsigned int chn = luaL_checkunsigned(L, 1);
+ unsigned int idx = luaL_checkunsigned(L, 2);
+ unsigned int first = getFirstInput(chn);
+ unsigned int count = getInputsCountFromFirst(chn, first);
+ if (idx < count) {
+ ExpoData * expo = expoAddress(first+idx);
+ lua_newtable(L);
+ lua_pushtablezstring(L, "name", expo->name);
+ lua_pushtableinteger(L, "source", expo->srcRaw);
+ lua_pushtableinteger(L, "weight", expo->weight);
+ lua_pushtableinteger(L, "offset", expo->offset);
+ lua_pushtableinteger(L, "switch", expo->swtch);
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/*luadoc
+@function model.insertInput(input, line, value)
+
+Inserts an Input at specified line
+
+@param input (unsigned number) input number (use 0 for Input1)
+
+@param line (unsigned number) input line (use 0 for first line)
+
+@param value (table) input data, see model.getInput()
+
+@status current Introduced in 2.0.0, `switch` added in TODO
+*/
+static int luaModelInsertInput(lua_State *L)
+{
+ unsigned int chn = luaL_checkunsigned(L, 1);
+ unsigned int idx = luaL_checkunsigned(L, 2);
+
+ unsigned int first = getFirstInput(chn);
+ unsigned int count = getInputsCountFromFirst(chn, first);
+
+ if (chnname, name, sizeof(expo->name));
+ }
+ else if (!strcmp(key, "source")) {
+ expo->srcRaw = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "weight")) {
+ expo->weight = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "offset")) {
+ expo->offset = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "switch")) {
+ expo->swtch = luaL_checkinteger(L, -1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*luadoc
+@function model.deleteInput(input, line)
+
+Delete line from specified input
+
+@param input (unsigned number) input number (use 0 for Input1)
+
+@param line (unsigned number) input line (use 0 for first line)
+
+@status current Introduced in 2.0.0
+*/
+static int luaModelDeleteInput(lua_State *L)
+{
+ unsigned int chn = luaL_checkunsigned(L, 1);
+ unsigned int idx = luaL_checkunsigned(L, 2);
+
+ int first = getFirstInput(chn);
+ unsigned int count = getInputsCountFromFirst(chn, first);
+
+ if (idx < count) {
+ deleteExpoMix(1, first+idx);
+ }
+
+ return 0;
+}
+
+/*luadoc
+@function model.deleteInputs()
+
+Delete all Inputs
+
+@status current Introduced in 2.0.0
+*/
+static int luaModelDeleteInputs(lua_State *L)
+{
+ clearInputs();
+ return 0;
+}
+
+/*luadoc
+@function model.defaultInputs()
+
+Set all inputs to defaults
+
+@status current Introduced in 2.0.0
+*/
+static int luaModelDefaultInputs(lua_State *L)
+{
+ defaultInputs();
+ return 0;
+}
+
+static unsigned int getFirstMix(unsigned int chn)
+{
+ for (unsigned int i=0; isrcRaw || mix->destCh>=chn) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+static unsigned int getMixesCountFromFirst(unsigned int chn, unsigned int first)
+{
+ unsigned int count = 0;
+ for (unsigned int i=first; isrcRaw || mix->destCh!=chn) break;
+ count++;
+ }
+ return count;
+}
+
+static unsigned int getMixesCount(unsigned int chn)
+{
+ return getMixesCountFromFirst(chn, getFirstMix(chn));
+}
+
+static int luaModelGetMixesCount(lua_State *L)
+{
+ unsigned int chn = luaL_checkunsigned(L, 1);
+ unsigned int count = getMixesCount(chn);
+ lua_pushinteger(L, count);
+ return 1;
+}
+
+static int luaModelGetMix(lua_State *L)
+{
+ unsigned int chn = luaL_checkunsigned(L, 1);
+ unsigned int idx = luaL_checkunsigned(L, 2);
+ unsigned int first = getFirstMix(chn);
+ unsigned int count = getMixesCountFromFirst(chn, first);
+ if (idx < count) {
+ MixData * mix = mixAddress(first+idx);
+ lua_newtable(L);
+ lua_pushtablezstring(L, "name", mix->name);
+ lua_pushtableinteger(L, "source", mix->srcRaw);
+ lua_pushtableinteger(L, "weight", mix->weight);
+ lua_pushtableinteger(L, "offset", mix->offset);
+ lua_pushtableinteger(L, "switch", mix->swtch);
+ lua_pushtableinteger(L, "curveType", mix->curve.type);
+ lua_pushtableinteger(L, "curveValue", mix->curve.value);
+ lua_pushtableinteger(L, "multiplex", mix->mltpx);
+ lua_pushtableinteger(L, "flightModes", mix->flightModes);
+ lua_pushtableboolean(L, "carryTrim", mix->carryTrim);
+ lua_pushtableinteger(L, "mixWarn", mix->mixWarn);
+ lua_pushtableinteger(L, "delayUp", mix->delayUp);
+ lua_pushtableinteger(L, "delayDown", mix->delayDown);
+ lua_pushtableinteger(L, "speedUp", mix->speedUp);
+ lua_pushtableinteger(L, "speedDown", mix->speedDown);
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int luaModelInsertMix(lua_State *L)
+{
+ unsigned int chn = luaL_checkunsigned(L, 1);
+ unsigned int idx = luaL_checkunsigned(L, 2);
+
+ unsigned int first = getFirstMix(chn);
+ unsigned int count = getMixesCountFromFirst(chn, first);
+
+ if (chnname, name, sizeof(mix->name));
+ }
+ else if (!strcmp(key, "source")) {
+ mix->srcRaw = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "weight")) {
+ mix->weight = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "offset")) {
+ mix->offset = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "switch")) {
+ mix->swtch = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "curveType")) {
+ mix->curve.type = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "curveValue")) {
+ mix->curve.value = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "multiplex")) {
+ mix->mltpx = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "flightModes")) {
+ mix->flightModes = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "carryTrim")) {
+ mix->carryTrim = lua_toboolean(L, -1);
+ }
+ else if (!strcmp(key, "mixWarn")) {
+ mix->mixWarn = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "delayUp")) {
+ mix->delayUp = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "delayDown")) {
+ mix->delayDown = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "speedUp")) {
+ mix->speedUp = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "speedDown")) {
+ mix->speedDown = luaL_checkinteger(L, -1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int luaModelDeleteMix(lua_State *L)
+{
+ unsigned int chn = luaL_checkunsigned(L, 1);
+ unsigned int idx = luaL_checkunsigned(L, 2);
+
+ unsigned int first = getFirstMix(chn);
+ unsigned int count = getMixesCountFromFirst(chn, first);
+
+ if (idx < count) {
+ deleteExpoMix(0, first+idx);
+ }
+
+ return 0;
+}
+
+static int luaModelDeleteMixes(lua_State *L)
+{
+ memset(g_model.mixData, 0, sizeof(g_model.mixData));
+ return 0;
+}
+
+static int luaModelGetLogicalSwitch(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < NUM_LOGICAL_SWITCH) {
+ LogicalSwitchData * sw = lswAddress(idx);
+ lua_newtable(L);
+ lua_pushtableinteger(L, "func", sw->func);
+ lua_pushtableinteger(L, "v1", sw->v1);
+ lua_pushtableinteger(L, "v2", sw->v2);
+ lua_pushtableinteger(L, "v3", sw->v3);
+ lua_pushtableinteger(L, "and", sw->andsw);
+ lua_pushtableinteger(L, "delay", sw->delay);
+ lua_pushtableinteger(L, "duration", sw->duration);
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int luaModelSetLogicalSwitch(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < NUM_LOGICAL_SWITCH) {
+ LogicalSwitchData * sw = lswAddress(idx);
+ memclear(sw, sizeof(LogicalSwitchData));
+ luaL_checktype(L, -1, LUA_TTABLE);
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ luaL_checktype(L, -2, LUA_TSTRING); // key is string
+ const char * key = luaL_checkstring(L, -2);
+ if (!strcmp(key, "func")) {
+ sw->func = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "v1")) {
+ sw->v1 = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "v2")) {
+ sw->v2 = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "v3")) {
+ sw->v3 = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "and")) {
+ sw->andsw = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "delay")) {
+ sw->delay = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "duration")) {
+ sw->duration = luaL_checkinteger(L, -1);
+ }
+ }
+ storageDirty(EE_MODEL);
+ }
+
+ return 0;
+}
+
+static int luaModelGetCurve(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < MAX_CURVES) {
+ CurveInfo & curveInfo = g_model.curves[idx];
+ lua_newtable(L);
+ lua_pushtablezstring(L, "name", g_model.curveNames[idx]);
+ lua_pushtableinteger(L, "type", curveInfo.type);
+ lua_pushtableboolean(L, "smooth", curveInfo.smooth);
+ lua_pushtableinteger(L, "points", curveInfo.points+5);
+ lua_pushstring(L, "y");
+ lua_newtable(L);
+ int8_t * point = curveAddress(idx);
+ for (int i=0; iplay.name);
+ }
+ else {
+ lua_pushtableinteger(L, "value", cfn->all.val);
+ lua_pushtableinteger(L, "mode", cfn->all.mode);
+ lua_pushtableinteger(L, "param", cfn->all.param);
+ }
+ lua_pushtableinteger(L, "active", CFN_ACTIVE(cfn));
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+static int luaModelSetCustomFunction(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < NUM_CFN) {
+ CustomFunctionData * cfn = &g_model.customFn[idx];
+ memclear(cfn, sizeof(CustomFunctionData));
+ luaL_checktype(L, -1, LUA_TTABLE);
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ luaL_checktype(L, -2, LUA_TSTRING); // key is string
+ const char * key = luaL_checkstring(L, -2);
+ if (!strcmp(key, "switch")) {
+ CFN_SWITCH(cfn) = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "func")) {
+ CFN_FUNC(cfn) = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "name")) {
+ const char * name = luaL_checkstring(L, -1);
+ strncpy(cfn->play.name, name, sizeof(cfn->play.name));
+ }
+ else if (!strcmp(key, "value")) {
+ cfn->all.val = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "mode")) {
+ cfn->all.mode = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "param")) {
+ cfn->all.param = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "active")) {
+ CFN_ACTIVE(cfn) = luaL_checkinteger(L, -1);
+ }
+ }
+ storageDirty(EE_MODEL);
+ }
+
+ return 0;
+}
+
+static int luaModelGetOutput(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < NUM_CHNOUT) {
+ LimitData * limit = limitAddress(idx);
+ lua_newtable(L);
+ lua_pushtablezstring(L, "name", limit->name);
+ lua_pushtableinteger(L, "min", limit->min-1000);
+ lua_pushtableinteger(L, "max", limit->max+1000);
+ lua_pushtableinteger(L, "offset", limit->offset);
+ lua_pushtableinteger(L, "ppmCenter", limit->ppmCenter);
+ lua_pushtableinteger(L, "symetrical", limit->symetrical);
+ lua_pushtableinteger(L, "revert", limit->revert);
+ if (limit->curve)
+ lua_pushtableinteger(L, "curve", limit->curve-1);
+ else
+ lua_pushtablenil(L, "curve");
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/*luadoc
+@function model.setOutput(index, value)
+
+Sets current global variable value. See also model.getGlobalVariable()
+
+@param index zero based output index, use 0 for CH1, 31 for CH32
+
+@param value new value for output. The `value` is a table with following items:
+ * `name` name of the output (channel)
+ * `min` negative limit
+ * `max` positive limit
+ * `offset` subtrim value
+ * `ppmCenter` ppm center value
+ * `symetrical` 1 for symmetric limits, 0 for normal
+ * `revert` 1 for inverted output, 0 for normal
+ * `curve` curve reference (zero based index, 0 means Curve 1)
+*/
+static int luaModelSetOutput(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ if (idx < NUM_CHNOUT) {
+ LimitData * limit = limitAddress(idx);
+ luaL_checktype(L, -1, LUA_TTABLE);
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ luaL_checktype(L, -2, LUA_TSTRING); // key is string
+ const char * key = luaL_checkstring(L, -2);
+ if (!strcmp(key, "name")) {
+ const char * name = luaL_checkstring(L, -1);
+ str2zchar(limit->name, name, sizeof(limit->name));
+ }
+ else if (!strcmp(key, "min")) {
+ limit->min = luaL_checkinteger(L, -1)+1000;
+ }
+ else if (!strcmp(key, "max")) {
+ limit->max = luaL_checkinteger(L, -1)-1000;
+ }
+ else if (!strcmp(key, "offset")) {
+ limit->offset = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "ppmCenter")) {
+ limit->ppmCenter = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "symetrical")) {
+ limit->symetrical = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "revert")) {
+ limit->revert = luaL_checkinteger(L, -1);
+ }
+ else if (!strcmp(key, "curve")) {
+ if (lua_isnil(L, -1))
+ limit->curve = 0;
+ else
+ limit->curve = luaL_checkinteger(L, -1) + 1;
+ }
+ }
+ storageDirty(EE_MODEL);
+ }
+
+ return 0;
+}
+
+/*luadoc
+@function model.getGlobalVariable(index [, phase])
+
+Returns current global variable value.
+See also model.setGlobalVariable()
+
+@notice a simple warning or notice
+
+@param index zero based global variable index, use 0 for GV1, 8 for GV9
+
+@param phase zero based phase index, use 0 for Phase 1, 5 for Phase 6
+
+@retval nil requested global variable does not exist
+
+@retval number current value of global variable
+
+Example:
+
+```lua
+ -- get GV3 (index = 2) from flight phase 1 (phase = 0)
+ val = model.getGlobalVariable(2, 0)
+```
+*/
+static int luaModelGetGlobalVariable(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ unsigned int phase = luaL_checkunsigned(L, 2);
+ if (phase < MAX_FLIGHT_MODES && idx < MAX_GVARS)
+ lua_pushinteger(L, g_model.flightModeData[phase].gvars[idx]);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+/*luadoc
+@function model.setGlobalVariable(index, phase, value)
+
+Sets current global variable value. See also model.getGlobalVariable()
+
+@param index zero based global variable index, use 0 for GV1, 8 for GV9
+
+@param phase zero based phase index, use 0 for Phase 1, 5 for Phase 6
+
+@param value new value for global variable. Permitted range is
+from -1024 to 1024.
+
+
+@notice Global variable can only store integer values,
+any floating point value is converted (todo check how) into integer value.
+*/
+static int luaModelSetGlobalVariable(lua_State *L)
+{
+ unsigned int idx = luaL_checkunsigned(L, 1);
+ unsigned int phase = luaL_checkunsigned(L, 2);
+ int value = luaL_checkinteger(L, 3);
+ if (phase < MAX_FLIGHT_MODES && idx < MAX_GVARS && value >= -GVAR_MAX && value <= GVAR_MAX) {
+ g_model.flightModeData[phase].gvars[idx] = value;
+ storageDirty(EE_MODEL);
+ }
+ return 0;
+}
+
+const luaL_Reg modelLib[] = {
+ { "getInfo", luaModelGetInfo },
+ { "setInfo", luaModelSetInfo },
+ { "getModule", luaModelGetModule },
+ { "setModule", luaModelSetModule },
+ { "getTimer", luaModelGetTimer },
+ { "setTimer", luaModelSetTimer },
+ { "resetTimer", luaModelResetTimer },
+ { "getInputsCount", luaModelGetInputsCount },
+ { "getInput", luaModelGetInput },
+ { "insertInput", luaModelInsertInput },
+ { "deleteInput", luaModelDeleteInput },
+ { "deleteInputs", luaModelDeleteInputs },
+ { "defaultInputs", luaModelDefaultInputs },
+ { "getMixesCount", luaModelGetMixesCount },
+ { "getMix", luaModelGetMix },
+ { "insertMix", luaModelInsertMix },
+ { "deleteMix", luaModelDeleteMix },
+ { "deleteMixes", luaModelDeleteMixes },
+ { "getLogicalSwitch", luaModelGetLogicalSwitch },
+ { "setLogicalSwitch", luaModelSetLogicalSwitch },
+ { "getCustomFunction", luaModelGetCustomFunction },
+ { "setCustomFunction", luaModelSetCustomFunction },
+ { "getCurve", luaModelGetCurve },
+ { "getOutput", luaModelGetOutput },
+ { "setOutput", luaModelSetOutput },
+ { "getGlobalVariable", luaModelGetGlobalVariable },
+ { "setGlobalVariable", luaModelSetGlobalVariable },
+ { NULL, NULL } /* sentinel */
+};
diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp
new file mode 100644
index 000000000..99075a7d4
--- /dev/null
+++ b/radio/src/lua/interface.cpp
@@ -0,0 +1,786 @@
+/*
+ * Authors (alphabetical order)
+ * - Andre Bernet
+ * - Andreas Weitl
+ * - Bertrand Songis
+ * - Bryan J. Rentoul (Gruvin)
+ * - Cameron Weeks
+ * - Erez Raviv
+ * - Gabriel Birkus
+ * - Jean-Pierre Parisy
+ * - Karl Szmutny
+ * - Michael Blandford
+ * - Michal Hlavinka
+ * - Pat Mackenzie
+ * - Philip Moss
+ * - Rob Thomson
+ * - Romolo Manfredini
+ * - Thomas Husterer
+ *
+ * opentx is based on code named
+ * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
+ * er9x by Erez Raviv: http://code.google.com/p/er9x/,
+ * and the original (and ongoing) project by
+ * Thomas Husterer, th9x: http://code.google.com/p/th9x/
+ *
+ * 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
+#include
+#include "opentx.h"
+#include "bin_allocator.h"
+#include "lua/lua_api.h"
+
+#if defined(LUA_COMPILER) && defined(SIMU)
+ #include
+ #include
+#endif
+
+#define PERMANENT_SCRIPTS_MAX_INSTRUCTIONS (10000/100)
+#define MANUAL_SCRIPTS_MAX_INSTRUCTIONS (20000/100)
+#define SET_LUA_INSTRUCTIONS_COUNT(x) (instructionsPercent=0, lua_sethook(L, hook, LUA_MASKCOUNT, x))
+#define LUA_WARNING_INFO_LEN 64
+
+lua_State *L = NULL;
+uint8_t luaState = 0;
+uint8_t luaScriptsCount = 0;
+ScriptInternalData scriptInternalData[MAX_SCRIPTS] = { { SCRIPT_NOFILE, 0 } };
+ScriptInputsOutputs scriptInputsOutputs[MAX_SCRIPTS] = { {0} };
+ScriptInternalData standaloneScript = { SCRIPT_NOFILE, 0 };
+uint16_t maxLuaInterval = 0;
+uint16_t maxLuaDuration = 0;
+bool luaLcdAllowed;
+int instructionsPercent = 0;
+char lua_warning_info[LUA_WARNING_INFO_LEN+1];
+struct our_longjmp * global_lj = 0;
+
+/* custom panic handler */
+static int custom_lua_atpanic(lua_State *lua)
+{
+ TRACE("PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1));
+ if (global_lj) {
+ longjmp(global_lj->b, 1);
+ /* will never return */
+ }
+ return 0;
+}
+
+void hook(lua_State* L, lua_Debug *ar)
+{
+ instructionsPercent++;
+ if (instructionsPercent > 100) {
+ // From now on, as soon as a line is executed, error
+ // keep erroring until you're script reaches the top
+ lua_sethook(L, hook, LUA_MASKLINE, 0);
+ luaL_error(L, "");
+ }
+}
+
+int luaGetInputs(ScriptInputsOutputs & sid)
+{
+ if (!lua_istable(L, -1))
+ return -1;
+
+ sid.inputsCount = 0;
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ luaL_checktype(L, -2, LUA_TNUMBER); // key is number
+ luaL_checktype(L, -1, LUA_TTABLE); // value is table
+ if (sid.inputsCounttop - 1), luaDumpWriter, &D, 1);
+ lua_unlock(L);
+ TRACE("Saved Lua bytecode to file %s", bytecodeName);
+ }
+ }
+ UNPROTECT_LUA();
+ f_close(&D);
+}
+#endif
+
+int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs * sio=NULL)
+{
+ int init = 0;
+
+ sid.instructions = 0;
+ sid.state = SCRIPT_OK;
+
+#if 0
+ // not needed, we just called luaInit
+ luaFree(sid);
+#endif
+
+ if (luaState == INTERPRETER_PANIC) {
+ return SCRIPT_PANIC;
+ }
+
+#if defined(LUA_COMPILER) && defined(SIMU)
+ luaCompileAndSave(filename);
+#endif
+
+ SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS);
+
+ PROTECT_LUA() {
+ if (luaL_loadfile(L, filename) == 0 &&
+ lua_pcall(L, 0, 1, 0) == 0 &&
+ lua_istable(L, -1)) {
+
+ luaL_checktype(L, -1, LUA_TTABLE);
+
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ const char *key = lua_tostring(L, -2);
+ if (!strcmp(key, "init")) {
+ init = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushnil(L);
+ }
+ else if (!strcmp(key, "run")) {
+ sid.run = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushnil(L);
+ }
+ else if (!strcmp(key, "background")) {
+ sid.background = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushnil(L);
+ }
+ else if (sio && !strcmp(key, "input")) {
+ luaGetInputs(*sio);
+ }
+ else if (sio && !strcmp(key, "output")) {
+ luaGetOutputs(*sio);
+ }
+ }
+
+ if (init) {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, init);
+ if (lua_pcall(L, 0, 0, 0) != 0) {
+ TRACE("Error in script %s init: %s", filename, lua_tostring(L, -1));
+ sid.state = SCRIPT_SYNTAX_ERROR;
+ }
+ luaL_unref(L, LUA_REGISTRYINDEX, init);
+ lua_gc(L, LUA_GCCOLLECT, 0);
+ }
+ }
+ else {
+ TRACE("Error in script %s: %s", filename, lua_tostring(L, -1));
+ sid.state = SCRIPT_SYNTAX_ERROR;
+ }
+ }
+ else {
+ luaDisable();
+ return SCRIPT_PANIC;
+ }
+ UNPROTECT_LUA();
+
+ if (sid.state != SCRIPT_OK) {
+ luaFree(sid);
+ }
+
+ return sid.state;
+}
+
+bool luaLoadMixScript(uint8_t index)
+{
+ ScriptData & sd = g_model.scriptsData[index];
+
+ if (ZEXIST(sd.file)) {
+ ScriptInternalData & sid = scriptInternalData[luaScriptsCount++];
+ ScriptInputsOutputs * sio = &scriptInputsOutputs[index];
+ sid.reference = SCRIPT_MIX_FIRST+index;
+ sid.state = SCRIPT_NOFILE;
+ char filename[sizeof(SCRIPTS_MIXES_PATH)+sizeof(sd.file)+sizeof(SCRIPTS_EXT)] = SCRIPTS_MIXES_PATH "/";
+ strncpy(filename+sizeof(SCRIPTS_MIXES_PATH), sd.file, sizeof(sd.file));
+ filename[sizeof(SCRIPTS_MIXES_PATH)+sizeof(sd.file)] = '\0';
+ strcat(filename+sizeof(SCRIPTS_MIXES_PATH), SCRIPTS_EXT);
+ if (luaLoad(filename, sid, sio) == SCRIPT_PANIC) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool luaLoadFunctionScript(uint8_t index)
+{
+ CustomFunctionData & fn = g_model.customFn[index];
+
+ if (fn.func == FUNC_PLAY_SCRIPT && ZEXIST(fn.play.name)) {
+ if (luaScriptsCount < MAX_SCRIPTS) {
+ ScriptInternalData & sid = scriptInternalData[luaScriptsCount++];
+ sid.reference = SCRIPT_FUNC_FIRST+index;
+ sid.state = SCRIPT_NOFILE;
+ char filename[sizeof(SCRIPTS_FUNCS_PATH)+sizeof(fn.play.name)+sizeof(SCRIPTS_EXT)] = SCRIPTS_FUNCS_PATH "/";
+ strncpy(filename+sizeof(SCRIPTS_FUNCS_PATH), fn.play.name, sizeof(fn.play.name));
+ filename[sizeof(SCRIPTS_FUNCS_PATH)+sizeof(fn.play.name)] = '\0';
+ strcat(filename+sizeof(SCRIPTS_FUNCS_PATH), SCRIPTS_EXT);
+ if (luaLoad(filename, sid) == SCRIPT_PANIC) {
+ return false;
+ }
+ }
+ else {
+ POPUP_WARNING(STR_TOO_MANY_LUA_SCRIPTS);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool luaLoadTelemetryScript(uint8_t index)
+{
+ TelemetryScreenType screenType = TELEMETRY_SCREEN_TYPE(index);
+
+ if (screenType == TELEMETRY_SCREEN_TYPE_SCRIPT) {
+ TelemetryScriptData & script = g_model.frsky.screens[index].script;
+ if (ZEXIST(script.file)) {
+ if (luaScriptsCount < MAX_SCRIPTS) {
+ ScriptInternalData & sid = scriptInternalData[luaScriptsCount++];
+ sid.reference = SCRIPT_TELEMETRY_FIRST+index;
+ sid.state = SCRIPT_NOFILE;
+ char filename[sizeof(SCRIPTS_TELEM_PATH)+sizeof(script.file)+sizeof(SCRIPTS_EXT)] = SCRIPTS_TELEM_PATH "/";
+ strncpy(filename+sizeof(SCRIPTS_TELEM_PATH), script.file, sizeof(script.file));
+ filename[sizeof(SCRIPTS_TELEM_PATH)+sizeof(script.file)] = '\0';
+ strcat(filename+sizeof(SCRIPTS_TELEM_PATH), SCRIPTS_EXT);
+ if (luaLoad(filename, sid) == SCRIPT_PANIC) {
+ return false;
+ }
+ }
+ else {
+ POPUP_WARNING(STR_TOO_MANY_LUA_SCRIPTS);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+uint8_t isTelemetryScriptAvailable(uint8_t index)
+{
+ for (int i=0; i 100) {
+ TRACE("Script killed");
+ standaloneScript.state = SCRIPT_KILLED;
+ luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
+ }
+ else if (lua_isstring(L, -1)) {
+ char nextScript[_MAX_LFN+1];
+ strncpy(nextScript, lua_tostring(L, -1), _MAX_LFN);
+ nextScript[_MAX_LFN] = '\0';
+ luaExec(nextScript);
+ }
+ else {
+ TRACE("Script run function returned unexpected value");
+ standaloneScript.state = SCRIPT_SYNTAX_ERROR;
+ luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
+ }
+ }
+ else {
+ int scriptResult = lua_tointeger(L, -1);
+ lua_pop(L, 1); /* pop returned value */
+ if (scriptResult != 0) {
+ TRACE("Script finished with status %d", scriptResult);
+ standaloneScript.state = SCRIPT_NOFILE;
+ luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
+ return;
+ }
+ else if (luaDisplayStatistics) {
+ lcd_hline(0, 7*FH-1, lcdLastPos+6, ERASE);
+ lcd_puts(0, 7*FH, "GV Use: ");
+ lcd_outdezAtt(lcdLastPos, 7*FH, luaGetMemUsed(), LEFT);
+ lcd_putc(lcdLastPos, 7*FH, 'b');
+ lcd_hline(0, 7*FH-2, lcdLastPos+6, FORCE);
+ lcdDrawVerticalLine(lcdLastPos+6, 7*FH-2, FH+2, SOLID, FORCE);
+ }
+ }
+ }
+ else {
+ TRACE("Script error: %s", lua_tostring(L, -1));
+ standaloneScript.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR);
+ luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
+ }
+
+ if (standaloneScript.state != SCRIPT_OK) {
+ luaError(standaloneScript.state);
+ luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
+ }
+
+ if (evt == EVT_KEY_LONG(KEY_EXIT)) {
+ TRACE("Script force exit");
+ killEvents(evt);
+ standaloneScript.state = SCRIPT_NOFILE;
+ luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
+ }
+ else if (evt == EVT_KEY_LONG(KEY_MENU)) {
+ killEvents(evt);
+ luaDisplayStatistics = !luaDisplayStatistics;
+ }
+ }
+}
+
+bool luaDoOneRunPermanentScript(uint8_t evt, int i, uint32_t scriptType)
+{
+ ScriptInternalData & sid = scriptInternalData[i];
+ if (sid.state != SCRIPT_OK) return false;
+
+ SET_LUA_INSTRUCTIONS_COUNT(PERMANENT_SCRIPTS_MAX_INSTRUCTIONS);
+ int inputsCount = 0;
+#if defined(SIMU) || defined(DEBUG)
+ const char *filename;
+#endif
+ ScriptInputsOutputs * sio = NULL;
+#if SCRIPT_MIX_FIRST > 0
+ if ((scriptType & RUN_MIX_SCRIPT) && (sid.reference >= SCRIPT_MIX_FIRST && sid.reference <= SCRIPT_MIX_LAST)) {
+#else
+ if ((scriptType & RUN_MIX_SCRIPT) && (sid.reference <= SCRIPT_MIX_LAST)) {
+#endif
+ ScriptData & sd = g_model.scriptsData[sid.reference-SCRIPT_MIX_FIRST];
+ sio = &scriptInputsOutputs[sid.reference-SCRIPT_MIX_FIRST];
+ inputsCount = sio->inputsCount;
+#if defined(SIMU) || defined(DEBUG)
+ filename = sd.file;
+#endif
+ lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
+ for (int j=0; jinputsCount; j++) {
+ if (sio->inputs[j].type == 1)
+ luaGetValueAndPush((uint8_t)sd.inputs[j]);
+ else
+ lua_pushinteger(L, sd.inputs[j] + sio->inputs[j].def);
+ }
+ }
+ else if ((scriptType & RUN_FUNC_SCRIPT) && (sid.reference >= SCRIPT_FUNC_FIRST && sid.reference <= SCRIPT_FUNC_LAST)) {
+ CustomFunctionData & fn = g_model.customFn[sid.reference-SCRIPT_FUNC_FIRST];
+ if (!getSwitch(fn.swtch)) return false;
+#if defined(SIMU) || defined(DEBUG)
+ filename = fn.play.name;
+#endif
+ lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
+ }
+ else {
+#if defined(SIMU) || defined(DEBUG)
+ TelemetryScriptData & script = g_model.frsky.screens[sid.reference-SCRIPT_TELEMETRY_FIRST].script;
+ filename = script.file;
+#endif
+ if ((scriptType & RUN_TELEM_FG_SCRIPT) &&
+#if defined(PCBFLAMENCO)
+ (g_menuStack[0]==menuMainView && sid.reference==SCRIPT_TELEMETRY_FIRST+g_eeGeneral.view-VIEW_TELEM1)) {
+#else
+ (g_menuStack[0]==menuTelemetryFrsky && sid.reference==SCRIPT_TELEMETRY_FIRST+s_frsky_view)) {
+#endif
+ lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
+ lua_pushinteger(L, evt);
+ inputsCount = 1;
+ }
+ else if ((scriptType & RUN_TELEM_BG_SCRIPT) && (sid.background)) {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, sid.background);
+ }
+ else {
+ return false;
+ }
+ }
+
+ if (lua_pcall(L, inputsCount, sio ? sio->outputsCount : 0, 0) == 0) {
+ if (sio) {
+ for (int j=sio->outputsCount-1; j>=0; j--) {
+ if (!lua_isnumber(L, -1)) {
+ sid.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR);
+ TRACE("Script %8s disabled", filename);
+ break;
+ }
+ sio->outputs[j].value = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ }
+ }
+ }
+ else {
+ if (instructionsPercent > 100) {
+ TRACE("Script %8s killed", filename);
+ sid.state = SCRIPT_KILLED;
+ }
+ else {
+ TRACE("Script %8s error: %s", filename, lua_tostring(L, -1));
+ sid.state = SCRIPT_SYNTAX_ERROR;
+ }
+ }
+
+ if (sid.state != SCRIPT_OK) {
+ luaFree(sid);
+ }
+ else {
+ if (instructionsPercent > sid.instructions) {
+ sid.instructions = instructionsPercent;
+ }
+ }
+ return true;
+}
+
+void luaDoGc()
+{
+ if (L) {
+ PROTECT_LUA() {
+ lua_gc(L, LUA_GCCOLLECT, 0);
+#if defined(SIMU) || defined(DEBUG)
+ static int lastgc = 0;
+ int gc = luaGetMemUsed();
+ if (gc != lastgc) {
+ lastgc = gc;
+ TRACE("GC Use: %dbytes", gc);
+ }
+#endif
+ }
+ else {
+ // we disable Lua for the rest of the session
+ luaDisable();
+ }
+ UNPROTECT_LUA();
+ }
+}
+
+bool luaTask(uint8_t evt, uint8_t scriptType, bool allowLcdUsage)
+{
+ if (luaState == INTERPRETER_PANIC) return false;
+ luaLcdAllowed = allowLcdUsage;
+ bool scriptWasRun = false;
+
+ // we run either standalone script or permanent scripts
+ if (luaState & INTERPRETER_RUNNING_STANDALONE_SCRIPT) {
+ // run standalone script
+ if ((scriptType & RUN_STNDAL_SCRIPT) == 0) return false;
+ PROTECT_LUA() {
+ luaDoOneRunStandalone(evt);
+ scriptWasRun = true;
+ }
+ else {
+ luaDisable();
+ return false;
+ }
+ UNPROTECT_LUA();
+ }
+ else {
+ // run permanent scripts
+ if (luaState & INTERPRETER_RELOAD_PERMANENT_SCRIPTS) {
+ luaState = 0;
+ luaInit();
+ if (luaState == INTERPRETER_PANIC) return false;
+ luaLoadPermanentScripts();
+ if (luaState == INTERPRETER_PANIC) return false;
+ }
+
+ for (int i=0; i
+ #include
+ #include
+ #include
+#if !defined(SIMU)
+}
+#endif
+
+ extern lua_State *L;
+ extern bool luaLcdAllowed;
+
+ #define lua_registernumber(L, n, i) (lua_pushnumber(L, (i)), lua_setglobal(L, (n)))
+ #define lua_registerint(L, n, i) (lua_pushinteger(L, (i)), lua_setglobal(L, (n)))
+ #define lua_pushtablenil(L, k) (lua_pushstring(L, (k)), lua_pushnil(L), lua_settable(L, -3))
+ #define lua_pushtableboolean(L, k, v) (lua_pushstring(L, (k)), lua_pushboolean(L, (v)), lua_settable(L, -3))
+ #define lua_pushtableinteger(L, k, v) (lua_pushstring(L, (k)), lua_pushinteger(L, (v)), lua_settable(L, -3))
+ #define lua_pushtablenumber(L, k, v) (lua_pushstring(L, (k)), lua_pushnumber(L, (v)), lua_settable(L, -3))
+ #define lua_pushtablestring(L, k, v) (lua_pushstring(L, (k)), lua_pushstring(L, (v)), lua_settable(L, -3))
+ #define lua_pushtablenzstring(L, k, v) { char tmp[sizeof(v)+1]; strncpy(tmp, (v), sizeof(v)); tmp[sizeof(v)] = '\0'; lua_pushstring(L, (k)); lua_pushstring(L, tmp); lua_settable(L, -3); }
+ #define lua_pushtablezstring(L, k, v) { char tmp[sizeof(v)+1]; zchar2str(tmp, (v), sizeof(v)); lua_pushstring(L, (k)); lua_pushstring(L, tmp); lua_settable(L, -3); }
+ #define lua_registerlib(L, name, tab) (luaL_newmetatable(L, name), luaL_setfuncs(L, tab, 0), lua_setglobal(L, name))
+
+ #define RUN_MIX_SCRIPT (1 << 0)
+ #define RUN_FUNC_SCRIPT (1 << 1)
+ #define RUN_TELEM_BG_SCRIPT (1 << 2)
+ #define RUN_TELEM_FG_SCRIPT (1 << 3)
+ #define RUN_STNDAL_SCRIPT (1 << 4)
+
struct ScriptInput {
const char *name;
uint8_t type;
@@ -98,11 +122,11 @@
void luaExec(const char * filename);
void luaError(uint8_t error, bool acknowledge=true);
int luaGetMemUsed();
+ void luaGetValueAndPush(int src);
#define luaGetCpuUsed(idx) scriptInternalData[idx].instructions
uint8_t isTelemetryScriptAvailable(uint8_t index);
#define LUA_LOAD_MODEL_SCRIPTS() luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
#define LUA_LOAD_MODEL_SCRIPT(idx) luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
- #define LUA_STANDALONE_SCRIPT_RUNNING() (luaState == INTERPRETER_RUNNING_STANDALONE_SCRIPT)
// Lua PROTECT/UNPROTECT
#include
struct our_longjmp {
@@ -119,10 +143,11 @@
extern uint16_t maxLuaInterval;
extern uint16_t maxLuaDuration;
-#else // #if defined(LUA)
- #define LUA_LOAD_MODEL_SCRIPTS()
- #define LUA_LOAD_MODEL_SCRIPT(idx)
- #define LUA_STANDALONE_SCRIPT_RUNNING() (0)
-#endif
-#endif // #ifndef luaapi_h
+#else // #if defined(LUA)
+
+ #define LUA_LOAD_MODEL_SCRIPTS()
+
+#endif // #if defined(LUA)
+
+#endif // #ifndef lua_api_h
\ No newline at end of file
diff --git a/radio/src/lua_api.cpp b/radio/src/lua_api.cpp
deleted file mode 100644
index ac0322004..000000000
--- a/radio/src/lua_api.cpp
+++ /dev/null
@@ -1,2206 +0,0 @@
-/*
- * Authors (alphabetical order)
- * - Andre Bernet
- * - Andreas Weitl
- * - Bertrand Songis
- * - Bryan J. Rentoul (Gruvin)
- * - Cameron Weeks
- * - Erez Raviv
- * - Gabriel Birkus
- * - Jean-Pierre Parisy
- * - Karl Szmutny
- * - Michael Blandford
- * - Michal Hlavinka
- * - Pat Mackenzie
- * - Philip Moss
- * - Rob Thomson
- * - Romolo Manfredini
- * - Thomas Husterer
- *
- * opentx is based on code named
- * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
- * er9x by Erez Raviv: http://code.google.com/p/er9x/,
- * and the original (and ongoing) project by
- * Thomas Husterer, th9x: http://code.google.com/p/th9x/
- *
- * 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
-#include
-#include "opentx.h"
-#include "stamp-opentx.h"
-#include "bin_allocator.h"
-#include "timers.h"
-
-#if !defined(SIMU)
-extern "C" {
-#endif
- #include
- #include
- #include
- #include
-#if !defined(SIMU)
-}
-#endif
-
-#if defined(PCBHORUS)
- #include "lua_exports_horus.inc" // this line must be after lua headers
-#elif defined(PCBFLAMENCO)
- #include "lua_exports_flamenco.inc" // this line must be after lua headers
-#elif defined(PCBTARANIS)
- #include "lua_exports_taranis.inc" // this line must be after lua headers
-#endif
-
-#define lua_registernumber(L, n, i) (lua_pushnumber(L, (i)), lua_setglobal(L, (n)))
-#define lua_registerint(L, n, i) (lua_pushinteger(L, (i)), lua_setglobal(L, (n)))
-#define lua_pushtablenil(L, k) (lua_pushstring(L, (k)), lua_pushnil(L), lua_settable(L, -3))
-#define lua_pushtableboolean(L, k, v) (lua_pushstring(L, (k)), lua_pushboolean(L, (v)), lua_settable(L, -3))
-#define lua_pushtableinteger(L, k, v) (lua_pushstring(L, (k)), lua_pushinteger(L, (v)), lua_settable(L, -3))
-#define lua_pushtablenumber(L, k, v) (lua_pushstring(L, (k)), lua_pushnumber(L, (v)), lua_settable(L, -3))
-#define lua_pushtablestring(L, k, v) (lua_pushstring(L, (k)), lua_pushstring(L, (v)), lua_settable(L, -3))
-#define lua_pushtablenzstring(L, k, v) { char tmp[sizeof(v)+1]; strncpy(tmp, (v), sizeof(v)); tmp[sizeof(v)] = '\0'; lua_pushstring(L, (k)); lua_pushstring(L, tmp); lua_settable(L, -3); }
-#define lua_pushtablezstring(L, k, v) { char tmp[sizeof(v)+1]; zchar2str(tmp, (v), sizeof(v)); lua_pushstring(L, (k)); lua_pushstring(L, tmp); lua_settable(L, -3); }
-#define lua_registerlib(L, name, tab) (luaL_newmetatable(L, name), luaL_setfuncs(L, tab, 0), lua_setglobal(L, name))
-
-lua_State *L = NULL;
-uint8_t luaState = 0;
-uint8_t luaScriptsCount = 0;
-ScriptInternalData scriptInternalData[MAX_SCRIPTS] = { { SCRIPT_NOFILE, 0 } };
-ScriptInputsOutputs scriptInputsOutputs[MAX_SCRIPTS] = { {0} };
-ScriptInternalData standaloneScript = { SCRIPT_NOFILE, 0 };
-uint16_t maxLuaInterval = 0;
-uint16_t maxLuaDuration = 0;
-bool luaLcdAllowed;
-
-#define PERMANENT_SCRIPTS_MAX_INSTRUCTIONS (10000/100)
-#define MANUAL_SCRIPTS_MAX_INSTRUCTIONS (20000/100)
-#define SET_LUA_INSTRUCTIONS_COUNT(x) (instructionsPercent=0, lua_sethook(L, hook, LUA_MASKCOUNT, x))
-
-struct our_longjmp * global_lj = 0;
-
-/* custom panic handler */
-static int custom_lua_atpanic(lua_State *lua)
-{
- TRACE("PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1));
- if (global_lj) {
- longjmp(global_lj->b, 1);
- /* will never return */
- }
- return 0;
-}
-
-static int instructionsPercent = 0;
-void hook(lua_State* L, lua_Debug *ar)
-{
- instructionsPercent++;
- if (instructionsPercent > 100) {
- // From now on, as soon as a line is executed, error
- // keep erroring until you're script reaches the top
- lua_sethook(L, hook, LUA_MASKLINE, 0);
- luaL_error(L, "");
- }
-}
-
-static int luaGetVersion(lua_State *L)
-{
- lua_pushstring(L, VERS_STR);
- return 1;
-}
-
-static int luaGetTime(lua_State *L)
-{
- lua_pushunsigned(L, get_tmr10ms());
- return 1;
-}
-
-static void luaPushDateTime(lua_State *L, uint32_t year, uint32_t mon, uint32_t day,
- uint32_t hour, uint32_t min, uint32_t sec)
-{
- lua_createtable(L, 0, 6);
- lua_pushtableinteger(L, "year", year);
- lua_pushtableinteger(L, "mon", mon);
- lua_pushtableinteger(L, "day", day);
- lua_pushtableinteger(L, "hour", hour);
- lua_pushtableinteger(L, "min", min);
- lua_pushtableinteger(L, "sec", sec);
-}
-
-static int luaGetDateTime(lua_State *L)
-{
- struct gtm utm;
- gettime(&utm);
- luaPushDateTime(L, utm.tm_year + 1900, utm.tm_mon + 1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec);
- return 1;
-}
-
-static void luaPushLatLon(TelemetrySensor & telemetrySensor, TelemetryItem & telemetryItem)
-/* result is lua table containing members ["lat"] and ["lon"] as lua_Number (doubles) in decimal degrees */
-{
- lua_Number lat = 0.0;
- lua_Number lon = 0.0;
- uint32_t gpsLat = 0;
- uint32_t gpsLon = 0;
-
- telemetryItem.gps.extractLatitudeLongitude(&gpsLat, &gpsLon); /* close, but not the format we want */
- lat = gpsLat / 1000000.0;
- if (telemetryItem.gps.latitudeNS == 'S') lat = -lat;
- lon = gpsLon / 1000000.0;
- if (telemetryItem.gps.longitudeEW == 'W') lon = -lon;
-
- lua_createtable(L, 0, 2);
- lua_pushtablenumber(L, "lat", lat);
- lua_pushtablenumber(L, "lon", lon);
-}
-
-static void luaPushTelemetryDateTime(TelemetrySensor & telemetrySensor, TelemetryItem & telemetryItem)
-{
- luaPushDateTime(L, telemetryItem.datetime.year + 2000, telemetryItem.datetime.month, telemetryItem.datetime.day,
- telemetryItem.datetime.hour, telemetryItem.datetime.min, telemetryItem.datetime.sec);
-}
-
-static void luaPushCells(TelemetrySensor & telemetrySensor, TelemetryItem & telemetryItem)
-{
- if (telemetryItem.cells.count == 0)
- lua_pushinteger(L, (int)0); // returns zero if no cells
- else {
- lua_createtable(L, telemetryItem.cells.count, 0);
- for (int i = 0; i < telemetryItem.cells.count; i++) {
- lua_pushnumber(L, i + 1);
- lua_pushnumber(L, telemetryItem.cells.values[i].value / 100.0);
- lua_settable(L, -3);
- }
- }
-}
-
-static void luaGetValueAndPush(int src)
-{
- getvalue_t value = getValue(src); // ignored for GPS, DATETIME, and CELLS
-
- if (src >= MIXSRC_FIRST_TELEM && src <= MIXSRC_LAST_TELEM) {
- src = (src-MIXSRC_FIRST_TELEM) / 3;
- // telemetry values
- if (TELEMETRY_STREAMING() && telemetryItems[src].isAvailable()) {
- TelemetrySensor & telemetrySensor = g_model.telemetrySensors[src];
- switch (telemetrySensor.unit) {
- case UNIT_GPS:
- luaPushLatLon(telemetrySensor, telemetryItems[src]);
- break;
- case UNIT_DATETIME:
- luaPushTelemetryDateTime(telemetrySensor, telemetryItems[src]);
- break;
- case UNIT_CELLS:
- luaPushCells(telemetrySensor, telemetryItems[src]);
- break;
- default:
- if (telemetrySensor.prec > 0)
- lua_pushnumber(L, float(value)/(telemetrySensor.prec == 2 ? 100.0 : 10.0));
- else
- lua_pushinteger(L, value);
- break;
- }
- }
- else {
- // telemetry not working, return zero for telemetry sources
- lua_pushinteger(L, (int)0);
- }
- }
- else if (src == MIXSRC_TX_VOLTAGE) {
- lua_pushnumber(L, float(value)/10.0);
- }
- else {
- lua_pushinteger(L, value);
- }
-}
-
-struct LuaField {
- uint16_t id;
- char desc[50];
-};
-
-#define FIND_FIELD_DESC 0x01
-
-/**
- Return field data for a given field name
-*/
-bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags=0)
-{
- // TODO better search method (binary lookup)
- for (unsigned int n=0; n= count) {
- // TODO error
- }
- if (flags & BLINK) {
- drawFilledRect(x, y, w-9, count*9+2, SOLID, ERASE);
- lcdDrawRect(x, y, w-9, count*9+2);
- for (int i=0; isrcRaw || expo->chn >= chn) {
- return i;
- }
- }
- return 0;
-}
-
-static unsigned int getInputsCountFromFirst(unsigned int chn, unsigned int first)
-{
- unsigned int count = 0;
- for (unsigned int i=first; isrcRaw || expo->chn!=chn) break;
- count++;
- }
- return count;
-}
-
-static unsigned int getInputsCount(unsigned int chn)
-{
- return getInputsCountFromFirst(chn, getFirstInput(chn));
-}
-
-static int luaModelGetInputsCount(lua_State *L)
-{
- unsigned int chn = luaL_checkunsigned(L, 1);
- int count = getInputsCount(chn);
- lua_pushinteger(L, count);
- return 1;
-}
-
-static int luaModelGetInput(lua_State *L)
-{
- unsigned int chn = luaL_checkunsigned(L, 1);
- unsigned int idx = luaL_checkunsigned(L, 2);
- unsigned int first = getFirstInput(chn);
- unsigned int count = getInputsCountFromFirst(chn, first);
- if (idx < count) {
- ExpoData * expo = expoAddress(first+idx);
- lua_newtable(L);
- lua_pushtablezstring(L, "name", expo->name);
- lua_pushtableinteger(L, "source", expo->srcRaw);
- lua_pushtableinteger(L, "weight", expo->weight);
- lua_pushtableinteger(L, "offset", expo->offset);
- lua_pushtableinteger(L, "switch", expo->swtch);
- }
- else {
- lua_pushnil(L);
- }
- return 1;
-}
-
-static int luaModelInsertInput(lua_State *L)
-{
- unsigned int chn = luaL_checkunsigned(L, 1);
- unsigned int idx = luaL_checkunsigned(L, 2);
-
- unsigned int first = getFirstInput(chn);
- unsigned int count = getInputsCountFromFirst(chn, first);
-
- if (chnname, name, sizeof(expo->name));
- }
- else if (!strcmp(key, "source")) {
- expo->srcRaw = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "weight")) {
- expo->weight = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "offset")) {
- expo->offset = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "switch")) {
- expo->swtch = luaL_checkinteger(L, -1);
- }
- }
- }
-
- return 0;
-}
-
-static int luaModelDeleteInput(lua_State *L)
-{
- unsigned int chn = luaL_checkunsigned(L, 1);
- unsigned int idx = luaL_checkunsigned(L, 2);
-
- int first = getFirstInput(chn);
- unsigned int count = getInputsCountFromFirst(chn, first);
-
- if (idx < count) {
- deleteExpoMix(1, first+idx);
- }
-
- return 0;
-}
-
-static int luaModelDeleteInputs(lua_State *L)
-{
- clearInputs();
- return 0;
-}
-
-static int luaModelDefaultInputs(lua_State *L)
-{
- defaultInputs();
- return 0;
-}
-
-static unsigned int getFirstMix(unsigned int chn)
-{
- for (unsigned int i=0; isrcRaw || mix->destCh>=chn) {
- return i;
- }
- }
- return 0;
-}
-
-static unsigned int getMixesCountFromFirst(unsigned int chn, unsigned int first)
-{
- unsigned int count = 0;
- for (unsigned int i=first; isrcRaw || mix->destCh!=chn) break;
- count++;
- }
- return count;
-}
-
-static unsigned int getMixesCount(unsigned int chn)
-{
- return getMixesCountFromFirst(chn, getFirstMix(chn));
-}
-
-static int luaModelGetMixesCount(lua_State *L)
-{
- unsigned int chn = luaL_checkunsigned(L, 1);
- unsigned int count = getMixesCount(chn);
- lua_pushinteger(L, count);
- return 1;
-}
-
-static int luaModelGetMix(lua_State *L)
-{
- unsigned int chn = luaL_checkunsigned(L, 1);
- unsigned int idx = luaL_checkunsigned(L, 2);
- unsigned int first = getFirstMix(chn);
- unsigned int count = getMixesCountFromFirst(chn, first);
- if (idx < count) {
- MixData * mix = mixAddress(first+idx);
- lua_newtable(L);
- lua_pushtablezstring(L, "name", mix->name);
- lua_pushtableinteger(L, "source", mix->srcRaw);
- lua_pushtableinteger(L, "weight", mix->weight);
- lua_pushtableinteger(L, "offset", mix->offset);
- lua_pushtableinteger(L, "switch", mix->swtch);
- lua_pushtableinteger(L, "curveType", mix->curve.type);
- lua_pushtableinteger(L, "curveValue", mix->curve.value);
- lua_pushtableinteger(L, "multiplex", mix->mltpx);
- lua_pushtableinteger(L, "flightModes", mix->flightModes);
- lua_pushtableboolean(L, "carryTrim", mix->carryTrim);
- lua_pushtableinteger(L, "mixWarn", mix->mixWarn);
- lua_pushtableinteger(L, "delayUp", mix->delayUp);
- lua_pushtableinteger(L, "delayDown", mix->delayDown);
- lua_pushtableinteger(L, "speedUp", mix->speedUp);
- lua_pushtableinteger(L, "speedDown", mix->speedDown);
- }
- else {
- lua_pushnil(L);
- }
- return 1;
-}
-
-static int luaModelInsertMix(lua_State *L)
-{
- unsigned int chn = luaL_checkunsigned(L, 1);
- unsigned int idx = luaL_checkunsigned(L, 2);
-
- unsigned int first = getFirstMix(chn);
- unsigned int count = getMixesCountFromFirst(chn, first);
-
- if (chnname, name, sizeof(mix->name));
- }
- else if (!strcmp(key, "source")) {
- mix->srcRaw = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "weight")) {
- mix->weight = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "offset")) {
- mix->offset = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "switch")) {
- mix->swtch = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "curveType")) {
- mix->curve.type = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "curveValue")) {
- mix->curve.value = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "multiplex")) {
- mix->mltpx = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "flightModes")) {
- mix->flightModes = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "carryTrim")) {
- mix->carryTrim = lua_toboolean(L, -1);
- }
- else if (!strcmp(key, "mixWarn")) {
- mix->mixWarn = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "delayUp")) {
- mix->delayUp = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "delayDown")) {
- mix->delayDown = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "speedUp")) {
- mix->speedUp = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "speedDown")) {
- mix->speedDown = luaL_checkinteger(L, -1);
- }
- }
- }
-
- return 0;
-}
-
-static int luaModelDeleteMix(lua_State *L)
-{
- unsigned int chn = luaL_checkunsigned(L, 1);
- unsigned int idx = luaL_checkunsigned(L, 2);
-
- unsigned int first = getFirstMix(chn);
- unsigned int count = getMixesCountFromFirst(chn, first);
-
- if (idx < count) {
- deleteExpoMix(0, first+idx);
- }
-
- return 0;
-}
-
-static int luaModelDeleteMixes(lua_State *L)
-{
- memset(g_model.mixData, 0, sizeof(g_model.mixData));
- return 0;
-}
-
-static int luaModelGetLogicalSwitch(lua_State *L)
-{
- unsigned int idx = luaL_checkunsigned(L, 1);
- if (idx < NUM_LOGICAL_SWITCH) {
- LogicalSwitchData * sw = lswAddress(idx);
- lua_newtable(L);
- lua_pushtableinteger(L, "func", sw->func);
- lua_pushtableinteger(L, "v1", sw->v1);
- lua_pushtableinteger(L, "v2", sw->v2);
- lua_pushtableinteger(L, "v3", sw->v3);
- lua_pushtableinteger(L, "and", sw->andsw);
- lua_pushtableinteger(L, "delay", sw->delay);
- lua_pushtableinteger(L, "duration", sw->duration);
- }
- else {
- lua_pushnil(L);
- }
- return 1;
-}
-
-static int luaModelSetLogicalSwitch(lua_State *L)
-{
- unsigned int idx = luaL_checkunsigned(L, 1);
- if (idx < NUM_LOGICAL_SWITCH) {
- LogicalSwitchData * sw = lswAddress(idx);
- memclear(sw, sizeof(LogicalSwitchData));
- luaL_checktype(L, -1, LUA_TTABLE);
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- luaL_checktype(L, -2, LUA_TSTRING); // key is string
- const char * key = luaL_checkstring(L, -2);
- if (!strcmp(key, "func")) {
- sw->func = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "v1")) {
- sw->v1 = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "v2")) {
- sw->v2 = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "v3")) {
- sw->v3 = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "and")) {
- sw->andsw = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "delay")) {
- sw->delay = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "duration")) {
- sw->duration = luaL_checkinteger(L, -1);
- }
- }
- storageDirty(EE_MODEL);
- }
-
- return 0;
-}
-
-static int luaModelGetCurve(lua_State *L)
-{
- unsigned int idx = luaL_checkunsigned(L, 1);
- if (idx < MAX_CURVES) {
- CurveInfo & curveInfo = g_model.curves[idx];
- lua_newtable(L);
- lua_pushtablezstring(L, "name", g_model.curveNames[idx]);
- lua_pushtableinteger(L, "type", curveInfo.type);
- lua_pushtableboolean(L, "smooth", curveInfo.smooth);
- lua_pushtableinteger(L, "points", curveInfo.points+5);
- lua_pushstring(L, "y");
- lua_newtable(L);
- int8_t * point = curveAddress(idx);
- for (int i=0; iplay.name);
- }
- else {
- lua_pushtableinteger(L, "value", cfn->all.val);
- lua_pushtableinteger(L, "mode", cfn->all.mode);
- lua_pushtableinteger(L, "param", cfn->all.param);
- }
- lua_pushtableinteger(L, "active", CFN_ACTIVE(cfn));
- }
- else {
- lua_pushnil(L);
- }
- return 1;
-}
-
-static int luaModelSetCustomFunction(lua_State *L)
-{
- unsigned int idx = luaL_checkunsigned(L, 1);
- if (idx < NUM_CFN) {
- CustomFunctionData * cfn = &g_model.customFn[idx];
- memclear(cfn, sizeof(CustomFunctionData));
- luaL_checktype(L, -1, LUA_TTABLE);
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- luaL_checktype(L, -2, LUA_TSTRING); // key is string
- const char * key = luaL_checkstring(L, -2);
- if (!strcmp(key, "switch")) {
- CFN_SWITCH(cfn) = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "func")) {
- CFN_FUNC(cfn) = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "name")) {
- const char * name = luaL_checkstring(L, -1);
- strncpy(cfn->play.name, name, sizeof(cfn->play.name));
- }
- else if (!strcmp(key, "value")) {
- cfn->all.val = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "mode")) {
- cfn->all.mode = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "param")) {
- cfn->all.param = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "active")) {
- CFN_ACTIVE(cfn) = luaL_checkinteger(L, -1);
- }
- }
- storageDirty(EE_MODEL);
- }
-
- return 0;
-}
-
-static int luaModelGetOutput(lua_State *L)
-{
- unsigned int idx = luaL_checkunsigned(L, 1);
- if (idx < NUM_CHNOUT) {
- LimitData * limit = limitAddress(idx);
- lua_newtable(L);
- lua_pushtablezstring(L, "name", limit->name);
- lua_pushtableinteger(L, "min", limit->min-1000);
- lua_pushtableinteger(L, "max", limit->max+1000);
- lua_pushtableinteger(L, "offset", limit->offset);
- lua_pushtableinteger(L, "ppmCenter", limit->ppmCenter);
- lua_pushtableinteger(L, "symetrical", limit->symetrical);
- lua_pushtableinteger(L, "revert", limit->revert);
- if (limit->curve)
- lua_pushtableinteger(L, "curve", limit->curve-1);
- else
- lua_pushtablenil(L, "curve");
- }
- else {
- lua_pushnil(L);
- }
- return 1;
-}
-
-static int luaModelSetOutput(lua_State *L)
-{
- unsigned int idx = luaL_checkunsigned(L, 1);
- if (idx < NUM_CHNOUT) {
- LimitData * limit = limitAddress(idx);
- luaL_checktype(L, -1, LUA_TTABLE);
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- luaL_checktype(L, -2, LUA_TSTRING); // key is string
- const char * key = luaL_checkstring(L, -2);
- if (!strcmp(key, "name")) {
- const char * name = luaL_checkstring(L, -1);
- str2zchar(limit->name, name, sizeof(limit->name));
- }
- else if (!strcmp(key, "min")) {
- limit->min = luaL_checkinteger(L, -1)+1000;
- }
- else if (!strcmp(key, "max")) {
- limit->max = luaL_checkinteger(L, -1)-1000;
- }
- else if (!strcmp(key, "offset")) {
- limit->offset = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "ppmCenter")) {
- limit->ppmCenter = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "symetrical")) {
- limit->symetrical = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "revert")) {
- limit->revert = luaL_checkinteger(L, -1);
- }
- else if (!strcmp(key, "curve")) {
- if (lua_isnil(L, -1))
- limit->curve = 0;
- else
- limit->curve = luaL_checkinteger(L, -1) + 1;
- }
- }
- storageDirty(EE_MODEL);
- }
-
- return 0;
-}
-
-static int luaModelGetGlobalVariable(lua_State *L)
-{
- unsigned int idx = luaL_checkunsigned(L, 1);
- unsigned int phase = luaL_checkunsigned(L, 2);
- if (phase < MAX_FLIGHT_MODES && idx < MAX_GVARS)
- lua_pushinteger(L, g_model.flightModeData[phase].gvars[idx]);
- else
- lua_pushnil(L);
- return 1;
-}
-
-static int luaModelSetGlobalVariable(lua_State *L)
-{
- unsigned int idx = luaL_checkunsigned(L, 1);
- unsigned int phase = luaL_checkunsigned(L, 2);
- int value = luaL_checkinteger(L, 3);
- if (phase < MAX_FLIGHT_MODES && idx < MAX_GVARS && value >= -GVAR_MAX && value <= GVAR_MAX) {
- g_model.flightModeData[phase].gvars[idx] = value;
- storageDirty(EE_MODEL);
- }
- return 0;
-}
-
-static int luaPopupInput(lua_State *L)
-{
- uint8_t event = luaL_checkinteger(L, 2);
- s_warning_input_value = luaL_checkinteger(L, 3);
- s_warning_input_min = luaL_checkinteger(L, 4);
- s_warning_input_max = luaL_checkinteger(L, 5);
- s_warning = luaL_checkstring(L, 1);
- s_warning_type = WARNING_TYPE_INPUT;
- displayWarning(event);
- if (s_warning_result) {
- s_warning_result = 0;
- lua_pushstring(L, "OK");
- }
- else if (!s_warning) {
- lua_pushstring(L, "CANCEL");
- }
- else {
- lua_pushinteger(L, s_warning_input_value);
- }
- s_warning = NULL;
- return 1;
-}
-
-static int luaDefaultStick(lua_State *L)
-{
- uint8_t channel = luaL_checkinteger(L, 1);
- lua_pushinteger(L, channel_order(channel+1)-1);
- return 1;
-}
-
-static int luaDefaultChannel(lua_State *L)
-{
- uint8_t stick = luaL_checkinteger(L, 1);
- for (int i=1; i<=4; i++) {
- int tmp = channel_order(i) - 1;
- if (tmp == stick) {
- lua_pushinteger(L, i-1);
- return 1;
- }
- }
- lua_pushnil(L);
- return 1;
-}
-
-int luaGetInputs(ScriptInputsOutputs & sid)
-{
- if (!lua_istable(L, -1))
- return -1;
-
- sid.inputsCount = 0;
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- luaL_checktype(L, -2, LUA_TNUMBER); // key is number
- luaL_checktype(L, -1, LUA_TTABLE); // value is table
- if (sid.inputsCount 100) {
- TRACE("Script killed");
- standaloneScript.state = SCRIPT_KILLED;
- luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
- }
- else if (lua_isstring(L, -1)) {
- char nextScript[_MAX_LFN+1];
- strncpy(nextScript, lua_tostring(L, -1), _MAX_LFN);
- nextScript[_MAX_LFN] = '\0';
- luaExec(nextScript);
- }
- else {
- TRACE("Script run function returned unexpected value");
- standaloneScript.state = SCRIPT_SYNTAX_ERROR;
- luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
- }
- }
- else {
- int scriptResult = lua_tointeger(L, -1);
- lua_pop(L, 1); /* pop returned value */
- if (scriptResult != 0) {
- TRACE("Script finished with status %d", scriptResult);
- standaloneScript.state = SCRIPT_NOFILE;
- luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
- return;
- }
- else if (luaDisplayStatistics) {
- lcd_hline(0, 7*FH-1, lcdLastPos+6, ERASE);
- lcd_puts(0, 7*FH, "GV Use: ");
- lcd_outdezAtt(lcdLastPos, 7*FH, luaGetMemUsed(), LEFT);
- lcd_putc(lcdLastPos, 7*FH, 'b');
- lcd_hline(0, 7*FH-2, lcdLastPos+6, FORCE);
- lcdDrawVerticalLine(lcdLastPos+6, 7*FH-2, FH+2, SOLID, FORCE);
- }
- }
- }
- else {
- TRACE("Script error: %s", lua_tostring(L, -1));
- standaloneScript.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR);
- luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
- }
-
- if (standaloneScript.state != SCRIPT_OK) {
- luaError(standaloneScript.state);
- luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
- }
-
- if (evt == EVT_KEY_LONG(KEY_EXIT)) {
- TRACE("Script force exit");
- killEvents(evt);
- standaloneScript.state = SCRIPT_NOFILE;
- luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
- }
- else if (evt == EVT_KEY_LONG(KEY_MENU)) {
- killEvents(evt);
- luaDisplayStatistics = !luaDisplayStatistics;
- }
- }
-}
-
-bool luaDoOneRunPermanentScript(uint8_t evt, int i, uint32_t scriptType)
-{
- ScriptInternalData & sid = scriptInternalData[i];
- if (sid.state != SCRIPT_OK) return false;
-
- SET_LUA_INSTRUCTIONS_COUNT(PERMANENT_SCRIPTS_MAX_INSTRUCTIONS);
- int inputsCount = 0;
-#if defined(SIMU) || defined(DEBUG)
- const char *filename;
-#endif
- ScriptInputsOutputs * sio = NULL;
-#if SCRIPT_MIX_FIRST > 0
- if ((scriptType & RUN_MIX_SCRIPT) && (sid.reference >= SCRIPT_MIX_FIRST && sid.reference <= SCRIPT_MIX_LAST)) {
-#else
- if ((scriptType & RUN_MIX_SCRIPT) && (sid.reference <= SCRIPT_MIX_LAST)) {
-#endif
- ScriptData & sd = g_model.scriptsData[sid.reference-SCRIPT_MIX_FIRST];
- sio = &scriptInputsOutputs[sid.reference-SCRIPT_MIX_FIRST];
- inputsCount = sio->inputsCount;
-#if defined(SIMU) || defined(DEBUG)
- filename = sd.file;
-#endif
- lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
- for (int j=0; jinputsCount; j++) {
- if (sio->inputs[j].type == 1)
- luaGetValueAndPush((uint8_t)sd.inputs[j]);
- else
- lua_pushinteger(L, sd.inputs[j] + sio->inputs[j].def);
- }
- }
- else if ((scriptType & RUN_FUNC_SCRIPT) && (sid.reference >= SCRIPT_FUNC_FIRST && sid.reference <= SCRIPT_FUNC_LAST)) {
- CustomFunctionData & fn = g_model.customFn[sid.reference-SCRIPT_FUNC_FIRST];
- if (!getSwitch(fn.swtch)) return false;
-#if defined(SIMU) || defined(DEBUG)
- filename = fn.play.name;
-#endif
- lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
- }
- else {
-#if defined(SIMU) || defined(DEBUG)
- TelemetryScriptData & script = g_model.frsky.screens[sid.reference-SCRIPT_TELEMETRY_FIRST].script;
- filename = script.file;
-#endif
- if ((scriptType & RUN_TELEM_FG_SCRIPT) &&
-#if defined(PCBFLAMENCO)
- (g_menuStack[0]==menuMainView && sid.reference==SCRIPT_TELEMETRY_FIRST+g_eeGeneral.view-VIEW_TELEM1)) {
-#else
- (g_menuStack[0]==menuTelemetryFrsky && sid.reference==SCRIPT_TELEMETRY_FIRST+s_frsky_view)) {
-#endif
- lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
- lua_pushinteger(L, evt);
- inputsCount = 1;
- }
- else if ((scriptType & RUN_TELEM_BG_SCRIPT) && (sid.background)) {
- lua_rawgeti(L, LUA_REGISTRYINDEX, sid.background);
- }
- else {
- return false;
- }
- }
-
- if (lua_pcall(L, inputsCount, sio ? sio->outputsCount : 0, 0) == 0) {
- if (sio) {
- for (int j=sio->outputsCount-1; j>=0; j--) {
- if (!lua_isnumber(L, -1)) {
- sid.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR);
- TRACE("Script %8s disabled", filename);
- break;
- }
- sio->outputs[j].value = lua_tointeger(L, -1);
- lua_pop(L, 1);
- }
- }
- }
- else {
- if (instructionsPercent > 100) {
- TRACE("Script %8s killed", filename);
- sid.state = SCRIPT_KILLED;
- }
- else {
- TRACE("Script %8s error: %s", filename, lua_tostring(L, -1));
- sid.state = SCRIPT_SYNTAX_ERROR;
- }
- }
-
- if (sid.state != SCRIPT_OK) {
- luaFree(sid);
- }
- else {
- if (instructionsPercent > sid.instructions) {
- sid.instructions = instructionsPercent;
- }
- }
- return true;
-}
-
-void luaDoGc()
-{
- if (L) {
- PROTECT_LUA() {
- lua_gc(L, LUA_GCCOLLECT, 0);
-#if defined(SIMU) || defined(DEBUG)
- static int lastgc = 0;
- int gc = luaGetMemUsed();
- if (gc != lastgc) {
- lastgc = gc;
- TRACE("GC Use: %dbytes", gc);
- }
-#endif
- }
- else {
- // we disable Lua for the rest of the session
- luaDisable();
- }
- UNPROTECT_LUA();
- }
-}
-
-bool luaTask(uint8_t evt, uint8_t scriptType, bool allowLcdUsage)
-{
- if (luaState == INTERPRETER_PANIC) return false;
- luaLcdAllowed = allowLcdUsage;
- bool scriptWasRun = false;
-
- // we run either standalone script or permanent scripts
- if (luaState & INTERPRETER_RUNNING_STANDALONE_SCRIPT) {
- // run standalone script
- if ((scriptType & RUN_STNDAL_SCRIPT) == 0) return false;
- PROTECT_LUA() {
- luaDoOneRunStandalone(evt);
- scriptWasRun = true;
- }
- else {
- luaDisable();
- return false;
- }
- UNPROTECT_LUA();
- }
- else {
- // run permanent scripts
- if (luaState & INTERPRETER_RELOAD_PERMANENT_SCRIPTS) {
- luaState = 0;
- luaInit();
- if (luaState == INTERPRETER_PANIC) return false;
- luaLoadPermanentScripts();
- if (luaState == INTERPRETER_PANIC) return false;
- }
-
- for (int i=0; iLOW signals end of mixer interrupt
#endif
}
diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h
index 7910f5ece..74db54f83 100644
--- a/radio/src/myeeprom.h
+++ b/radio/src/myeeprom.h
@@ -560,7 +560,7 @@ enum PotsWarnMode {
TRAINER_MODULE
};
enum TrainerMode {
- TRAINER_MODE_MASTER,
+ TRAINER_MODE_MASTER_TRAINER_JACK,
TRAINER_MODE_SLAVE,
TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE,
TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE,
@@ -1426,10 +1426,12 @@ PACK(typedef struct {
};
void init(const char *label, uint8_t unit=UNIT_RAW, uint8_t prec=0);
void init(uint16_t id);
- bool isAvailable();
+ bool isAvailable() const;
int32_t getValue(int32_t value, uint8_t unit, uint8_t prec) const;
- bool isConfigurable();
- bool isPrecConfigurable();
+ bool isConfigurable() const;
+ bool isPrecConfigurable() const;
+ int32_t getPrecMultiplier() const;
+ int32_t getPrecDivisor() const;
}) TelemetrySensor;
#endif
@@ -2201,11 +2203,7 @@ enum RFProtocols {
#endif
};
-#if defined(MODULE_D16_EU_ONLY_SUPPORT)
- #define HAS_RF_PROTOCOL_FAILSAFE(protocol) ((protocol) == RF_PROTO_X16)
-#else
- #define HAS_RF_PROTOCOL_FAILSAFE(protocol) ((protocol) == RF_PROTO_X16 || (protocol) == RF_PROTO_LR12)
-#endif
+#define HAS_RF_PROTOCOL_FAILSAFE(protocol) ((protocol) == RF_PROTO_X16)
enum DSM2Protocols {
DSM2_PROTO_LP45,
diff --git a/radio/src/opentx.h b/radio/src/opentx.h
index 9618e564b..f5f72af69 100644
--- a/radio/src/opentx.h
+++ b/radio/src/opentx.h
@@ -1173,10 +1173,10 @@ extern const char vers_stamp[];
#endif
extern uint8_t g_vbat100mV;
-#if defined(CPUARM)
- #define GET_TXBATT_BARS() (min(10, 10 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin)))
+#if defined(PCBTARANIS)
+ #define GET_TXBATT_BARS() (limit(0, 10 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin), 10))
#else
- #define GET_TXBATT_BARS() (limit(2, 20 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin), 20))
+ #define GET_TXBATT_BARS() (limit(2, 20 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin), 20))
#endif
#define IS_TXBATT_WARNING() (g_vbat100mV <= g_eeGeneral.vBatWarn)
@@ -1783,7 +1783,7 @@ void varioWakeup();
extern void usbPluggedIn();
#endif
-#include "lua_api.h"
+#include "lua/lua_api.h"
#if defined(SDCARD)
enum ClipboardType {
diff --git a/radio/src/pulses/pxx_arm.cpp b/radio/src/pulses/pxx_arm.cpp
index 99faa62d5..58f0b9719 100644
--- a/radio/src/pulses/pxx_arm.cpp
+++ b/radio/src/pulses/pxx_arm.cpp
@@ -231,8 +231,7 @@ void setupPulsesPXX(unsigned int port)
}
else {
if (i < sendUpperChannels) {
- int channel = 8 + g_model.moduleData[port].channelsStart + i;
- int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[channel];
+ int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[8+i];
if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
pulseValue = 4095;
}
@@ -240,13 +239,12 @@ void setupPulsesPXX(unsigned int port)
pulseValue = 2048;
}
else {
- failsafeValue += 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
+ failsafeValue += 2*PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER;
pulseValue = limit(2049, (failsafeValue * 512 / 682) + 3072, 4094);
}
}
else {
- int channel = g_model.moduleData[port].channelsStart + i;
- int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[channel];
+ int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[i];
if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
pulseValue = 2047;
}
@@ -254,7 +252,7 @@ void setupPulsesPXX(unsigned int port)
pulseValue = 0;
}
else {
- failsafeValue += 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
+ failsafeValue += 2*PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER;
pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046);
}
}
@@ -289,7 +287,7 @@ void setupPulsesPXX(unsigned int port)
/* CRC16 */
putPcmByte(0, port);
pulseValue = modulePulsesData[port].pxx.pcmCrc;
- putPcmByte(pulseValue>>8, port);
+ putPcmByte(pulseValue >> 8, port);
putPcmByte(pulseValue, port);
/* Sync */
diff --git a/radio/src/sdcard.cpp b/radio/src/sdcard.cpp
index 9ba7d7f02..39bb2fa74 100644
--- a/radio/src/sdcard.cpp
+++ b/radio/src/sdcard.cpp
@@ -60,11 +60,7 @@ const char * sdCheckAndCreateDirectory(const char * path)
bool isFileAvailable(const char * path)
{
- FILINFO info;
- TCHAR lfn[_MAX_LFN + 1];
- info.lfname = lfn;
- info.lfsize = sizeof(lfn);
- return f_stat(path, &info) == FR_OK;
+ return f_stat(path, 0) == FR_OK;
}
bool isFileAvailable(const char * filename, const char * directory)
diff --git a/radio/src/storage/eeprom_raw.cpp b/radio/src/storage/eeprom_raw.cpp
index 078b9c0ab..022c07cdd 100644
--- a/radio/src/storage/eeprom_raw.cpp
+++ b/radio/src/storage/eeprom_raw.cpp
@@ -611,22 +611,25 @@ const pm_char * eeRestoreModel(uint8_t i_fileDst, char *model_name)
eepromEraseBlock(address+EEPROM_BLOCK_SIZE);
// write header
- EepromFileHeader header = { uint16_t(i_fileDst+1), size };
- eepromWrite(address, (uint8_t *)&header, sizeof(header));
- address += sizeof(header);
+ EepromFileHeader * header = (EepromFileHeader *)eepromWriteBuffer;
+ header->fileIndex = i_fileDst+1;
+ header->size = size;
+
+ int offset = 4;
// write model
- while (size > 0) {
- uint16_t blockSize = min(size, EEPROM_BUFFER_SIZE);
- result = f_read(&restoreFile, eepromWriteBuffer, blockSize, &read);
+ do {
+ uint16_t blockSize = min(size, EEPROM_BUFFER_SIZE-offset);
+ result = f_read(&restoreFile, eepromWriteBuffer+offset, blockSize, &read);
if (result != FR_OK || read != blockSize) {
f_close(&g_oLogFile);
return SDCARD_ERROR(result);
}
- eepromWrite(address, eepromWriteBuffer, blockSize);
+ eepromWrite(address, eepromWriteBuffer, blockSize+offset);
size -= blockSize;
- address += blockSize;
- }
+ address += EEPROM_BUFFER_SIZE;
+ offset = 0;
+ } while (size > 0);
// write FAT
eepromHeader.files[i_fileDst+1].exists = 1;
diff --git a/radio/src/targets/9x/lcd_driver.cpp b/radio/src/targets/9x/lcd_driver.cpp
index 1f9821913..9ed7eda31 100644
--- a/radio/src/targets/9x/lcd_driver.cpp
+++ b/radio/src/targets/9x/lcd_driver.cpp
@@ -150,17 +150,65 @@ void lcdSetRefVolt(uint8_t val)
#endif
}
+#if defined(LCD_ST7920)
+void lcdRefresh(){
+ lcdRefresh_ST7920(1);
+}
+
+uint8_t lcdRefresh_ST7920(uint8_t full)
+{
+#else
void lcdRefresh()
{
+#endif
LCD_LOCK();
#if defined(LCD_ST7920)
+ static uint8_t state;
+ uint8_t yst,yend;
uint8_t x_addr = 0;
uint8_t y_addr = 0;
uint16_t line_offset = 0;
uint8_t col_offset = 0;
- uint16_t byte_offset = 0;
uint8_t bit_count = 0;
- for (uint8_t y=0; y<64; y++) {
+ uint8_t result;
+ uint8_t *p;
+ if(full!=0){
+ yst=0;
+ yend=64;
+ state=0;
+ }
+ else{
+ switch (state){//Since writing to ST7920 is too slow we need to split it to five bands.
+ default:
+ case 0:
+ yst=0;
+ yend=13;
+ state=1;
+ break;
+ case 1:
+ yst=13;
+ yend=26;
+ state=2;
+ break;
+ case 2:
+ yst=26;
+ yend=39;
+ state=3;
+ break;
+ case 3:
+ yst=39;
+ yend=52;
+ state=4;
+ break;
+ case 4:
+ yst=52;
+ yend=64;
+ state=0;
+ break;
+ }
+ }
+
+ for (uint8_t y=yst; y 31) {
@@ -170,20 +218,28 @@ void lcdRefresh()
else {
y_addr = y;
}
- lcdSendCtl( 0x80 | y_addr ); //Set Vertical Address
+ lcdSendCtl( 0x80 | y_addr ); //Set Vertical Address
_delay_us(49);
- lcdSendCtl( 0x80 | x_addr ); //Set Horizontal Address
+ lcdSendCtl( 0x80 | x_addr ); //Set Horizontal Address
_delay_us(49);
- PORTC_LCD_CTRL |= (1< 0=0, 1=1..7=7, 8=0, 9=1...
col_offset = 1 << bit_count; //Build a value for a AND operation with the vorrect bitposition
line_offset = ( y / 8 ) * 128; //On the ST7565 there are 8 lines with each 128 bytes width
for (coord_t x=0; x<16; x++) { //Walk through 16 bytes form left to right (128 Pixel)
- byte_offset = line_offset + ( x * 8 ); //Calculate the position of the first byte im array
- // adressing the bytes sequential and shift the bits at the correct position, afterwards a OR operation to get all bits in one byte
- // the position of the LSB is the left-most position of the byte to the ST7920
- PORTA_LCD_DAT = (((displayBuf[byte_offset] & col_offset) >> bit_count) << 7) | (((displayBuf[byte_offset + 1] & col_offset) >> bit_count) << 6) | (((displayBuf[byte_offset + 2] & col_offset) >> bit_count ) << 5) | (((displayBuf[byte_offset + 3] & col_offset) >> bit_count ) << 4) | (((displayBuf[byte_offset + 4] & col_offset) >> bit_count ) << 3) | (((displayBuf[byte_offset + 5] & col_offset) >> bit_count ) << 2) | (((displayBuf[byte_offset + 6] & col_offset) >> bit_count ) << 1) | (((displayBuf[byte_offset + 7] & col_offset) >> bit_count ) << 0);
+ p=displayBuf + line_offset + ( x * 8 ); //Calculate the position of the first byte im array
+ // adressing the bytes sequential and set the bits at the correct position merging them with an OR operation to get all bits in one byte
+ // the position of the LSB is the right-most position of the byte to the ST7920
+ result = ((*p++ & col_offset)!=0?0x80:0);
+ result|= ((*p++ & col_offset)!=0?0x40:0);
+ result|= ((*p++ & col_offset)!=0?0x20:0);
+ result|= ((*p++ & col_offset)!=0?0x10:0);
+ result|= ((*p++ & col_offset)!=0?0x08:0);
+ result|= ((*p++ & col_offset)!=0?0x04:0);
+ result|= ((*p++ & col_offset) !=0?0x02:0);
+ result|= ((*p++ & col_offset)!=0?0x01:0);
+ PORTA_LCD_DAT = result;
PORTC_LCD_CTRL |= (1<© COPYRIGHT 2012 STMicroelectronics
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+
+#ifndef __USB_DESC_H
+#define __USB_DESC_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Core/inc/usbd_def.h"
+
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+ * @{
+ */
+
+/** @defgroup USB_DESC
+ * @brief general defines for the usb device library file
+ * @{
+ */
+
+/** @defgroup USB_DESC_Exported_Defines
+ * @{
+ */
+#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
+#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
+#define USB_STRING_DESCRIPTOR_TYPE 0x03
+#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
+#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
+#define USB_SIZ_DEVICE_DESC 18
+#define USB_SIZ_STRING_LANGID 4
+
+/**
+ * @}
+ */
+
+
+/** @defgroup USBD_DESC_Exported_TypesDefinitions
+ * @{
+ */
+/**
+ * @}
+ */
+
+
+
+/** @defgroup USBD_DESC_Exported_Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/** @defgroup USBD_DESC_Exported_Variables
+ * @{
+ */
+extern const uint8_t USBD_DeviceDesc [USB_SIZ_DEVICE_DESC];
+extern uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ];
+extern const uint8_t USBD_OtherSpeedCfgDesc[USB_LEN_CFG_DESC];
+extern const uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC];
+extern const uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID];
+extern const USBD_DEVICE USR_desc;
+/**
+ * @}
+ */
+
+/** @defgroup USBD_DESC_Exported_FunctionsPrototype
+ * @{
+ */
+
+
+uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length);
+uint8_t * USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length);
+uint8_t * USBD_USR_ManufacturerStrDescriptor ( uint8_t speed , uint16_t *length);
+uint8_t * USBD_USR_ProductStrDescriptor ( uint8_t speed , uint16_t *length);
+uint8_t * USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length);
+uint8_t * USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length);
+uint8_t * USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length);
+
+#ifdef USB_SUPPORT_USER_STRING_DESC
+uint8_t * USBD_USR_USRStringDesc (uint8_t speed, uint8_t idx , uint16_t *length);
+#endif /* USB_SUPPORT_USER_STRING_DESC */
+
+/**
+ * @}
+ */
+
+#endif /* __USBD_DESC_H */
+
+/**
+ * @}
+ */
+
+/**
+* @}
+*/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/radio/src/targets/Mega2560/00readme.txt b/radio/src/targets/Mega2560/00readme.txt
index ee442fd66..af74f9829 100644
--- a/radio/src/targets/Mega2560/00readme.txt
+++ b/radio/src/targets/Mega2560/00readme.txt
@@ -4,6 +4,5 @@ MEGA2560 board
DIY radio wih :
- Arduino MEGA2560 or compatible
- Gruvin9x features (soft-off, SD-Card, RTC, haptic, voice, rotary encoders)
-- LCD 128x64 Artronic (ST7565R) or Zolen (ST7565P)
-- Aurora9 or T9X gimballs
+- LCD 128x64 8 bits parallel mode
- home made case
\ No newline at end of file
diff --git a/radio/src/targets/Mega2560/board_mega2560.cpp b/radio/src/targets/Mega2560/board_mega2560.cpp
index d153186df..cf5e11233 100644
--- a/radio/src/targets/Mega2560/board_mega2560.cpp
+++ b/radio/src/targets/Mega2560/board_mega2560.cpp
@@ -42,13 +42,17 @@ inline void boardInit()
{
// Set up I/O port data directions and initial states (unused pin setting : input, pull-up on)
DDRA = 0b11111111; PORTA = 0b00000000; // LCD data
- DDRB = 0b01110111; PORTB = 0b00101111; // 7:PPM_IN 6:PPM_OUT, 5:SimCTRL, 4:Buzzer, SDCARD[3:MISO 2:MOSI 1:SCK 0:CS]
+ DDRB = 0b01110111; PORTB = 0b10101111; // 7:N/A 6:PPM_OUT, 5:SimCTRL, 4:Buzzer, SDCARD[3:MISO 2:MOSI 1:SCK 0:CS]
DDRC = 0b11111100; PORTC = 0b00000011; // 7-3:LCD, 2:BackLight, 1:ID2_SW, 0:ID1_SW
DDRD = 0b00000000; PORTD = 0b11111100; // 7:AilDR_SW, 6:N/A, 5:N/A, 4:N/A, 3:RENC2_B, 2:RENC2_A, 1:I2C_SDA, 0:I2C_SCL
- DDRE = 0b00000010; PORTE = 0b11111100; // 7:N/A, 6:N/A, 5:RENC1_B, 4:RENC1_A, 3:N/A, 2:N/A, 1:TELEM_TX, 0:TELEM_RX
+ DDRE = 0b00000010; PORTE = 0b01111100; // 7:PPM_IN, 6:N/A, 5:RENC1_B, 4:RENC1_A, 3:N/A, 2:N/A, 1:TELEM_TX, 0:TELEM_RX
DDRF = 0b00000000; PORTF = 0b11111111; // 7-0:Trim switch inputs
DDRG = 0b00000000; PORTG = 0b11111111; // 7:N/A, 6:N/A, 5:N/A, 4:N/A, 3:N/A, 2:TCut_SW, 1:Gear_SW, 0: RudDr_SW
+#if defined(PCBMEGA2560) && defined(DEBUG)
+ DDRH = 0b01011000; PORTH = 0b11110110; // 7:N/A, 6:RF_Activated, 5:DSC_Activated, 4:Hold_Power, 3:Speaker, 2:N/A, 1:N/A, 0:Haptic
+#else
DDRH = 0b00011000; PORTH = 0b11110110; // 7:N/A, 6:RF_Activated, 5:DSC_Activated, 4:Hold_Power, 3:Speaker, 2:N/A, 1:N/A, 0:Haptic
+#endif
DDRJ = 0b00000000; PORTJ = 0b11111111; // 7:N/A, 6:N/A, 5:N/A, 4:N/A, 3:N/A, 2:N/A, 1:RENC2_push, 0:RENC1_push
DDRK = 0b00000000; PORTK = 0b00000000; // Analogic input (no pull-ups)
DDRL = 0b00000000; PORTL = 0b11111111; // 7:TRN_SW 6:EleDR_SW, 5:ESC, 4:MENU 3:Keyb_Left, 2:Keyb_Right, 1:Keyb_Up, 0:Keyb_Down
diff --git a/radio/src/targets/Mega2560/board_mega2560.h b/radio/src/targets/Mega2560/board_mega2560.h
index bb084c767..4b8cad5f7 100644
--- a/radio/src/targets/Mega2560/board_mega2560.h
+++ b/radio/src/targets/Mega2560/board_mega2560.h
@@ -111,7 +111,7 @@ void sdPoll10ms(void);
# define INP_L_Trainer 7
// Servitudes driver
-# define INP_B_PPM_IN 7
+//#define INP_E_PPM_IN 7 //reserved PPM_IN
# define OUT_B_PPM 6
# define OUT_B_SIM_CTL 5
# define OUT_B_BUZZER 4
diff --git a/radio/src/targets/Sky9x/lcd_driver.cpp b/radio/src/targets/Sky9x/lcd_driver.cpp
index 4bbedc638..f22e3bdfe 100644
--- a/radio/src/targets/Sky9x/lcd_driver.cpp
+++ b/radio/src/targets/Sky9x/lcd_driver.cpp
@@ -51,7 +51,7 @@
// LCD_D6 PC2
// LCD_D7 PC1
-#define LCD_DATA 0x000000FFL
+#define LCD_DATA 0x000000FFL
#if !defined(REVA)
#define LCD_A0 0x00000080L
#else
@@ -66,111 +66,105 @@
#if defined(REVA)
const uint8_t Lcd_lookup[] =
{
-0x00,0x01,0x80,0x81,0x40,0x41,0xC0,0xC1,0x20,0x21,0xA0,0xA1,0x60,0x61,0xE0,0xE1,
-0x10,0x11,0x90,0x91,0x50,0x51,0xD0,0xD1,0x30,0x31,0xB0,0xB1,0x70,0x71,0xF0,0xF1,
-0x08,0x09,0x88,0x89,0x48,0x49,0xC8,0xC9,0x28,0x29,0xA8,0xA9,0x68,0x69,0xE8,0xE9,
-0x18,0x19,0x98,0x99,0x58,0x59,0xD8,0xD9,0x38,0x39,0xB8,0xB9,0x78,0x79,0xF8,0xF9,
-0x04,0x05,0x84,0x85,0x44,0x45,0xC4,0xC5,0x24,0x25,0xA4,0xA5,0x64,0x65,0xE4,0xE5,
-0x14,0x15,0x94,0x95,0x54,0x55,0xD4,0xD5,0x34,0x35,0xB4,0xB5,0x74,0x75,0xF4,0xF5,
-0x0C,0x0D,0x8C,0x8D,0x4C,0x4D,0xCC,0xCD,0x2C,0x2D,0xAC,0xAD,0x6C,0x6D,0xEC,0xED,
-0x1C,0x1D,0x9C,0x9D,0x5C,0x5D,0xDC,0xDD,0x3C,0x3D,0xBC,0xBD,0x7C,0x7D,0xFC,0xFD,
-0x02,0x03,0x82,0x83,0x42,0x43,0xC2,0xC3,0x22,0x23,0xA2,0xA3,0x62,0x63,0xE2,0xE3,
-0x12,0x13,0x92,0x93,0x52,0x53,0xD2,0xD3,0x32,0x33,0xB2,0xB3,0x72,0x73,0xF2,0xF3,
-0x0A,0x0B,0x8A,0x8B,0x4A,0x4B,0xCA,0xCB,0x2A,0x2B,0xAA,0xAB,0x6A,0x6B,0xEA,0xEB,
-0x1A,0x1B,0x9A,0x9B,0x5A,0x5B,0xDA,0xDB,0x3A,0x3B,0xBA,0xBB,0x7A,0x7B,0xFA,0xFB,
-0x06,0x07,0x86,0x87,0x46,0x47,0xC6,0xC7,0x26,0x27,0xA6,0xA7,0x66,0x67,0xE6,0xE7,
-0x16,0x17,0x96,0x97,0x56,0x57,0xD6,0xD7,0x36,0x37,0xB6,0xB7,0x76,0x77,0xF6,0xF7,
-0x0E,0x0F,0x8E,0x8F,0x4E,0x4F,0xCE,0xCF,0x2E,0x2F,0xAE,0xAF,0x6E,0x6F,0xEE,0xEF,
-0x1E,0x1F,0x9E,0x9F,0x5E,0x5F,0xDE,0xDF,0x3E,0x3F,0xBE,0xBF,0x7E,0x7F,0xFE,0xFF
-} ;
+ 0x00,0x01,0x80,0x81,0x40,0x41,0xC0,0xC1,0x20,0x21,0xA0,0xA1,0x60,0x61,0xE0,0xE1,
+ 0x10,0x11,0x90,0x91,0x50,0x51,0xD0,0xD1,0x30,0x31,0xB0,0xB1,0x70,0x71,0xF0,0xF1,
+ 0x08,0x09,0x88,0x89,0x48,0x49,0xC8,0xC9,0x28,0x29,0xA8,0xA9,0x68,0x69,0xE8,0xE9,
+ 0x18,0x19,0x98,0x99,0x58,0x59,0xD8,0xD9,0x38,0x39,0xB8,0xB9,0x78,0x79,0xF8,0xF9,
+ 0x04,0x05,0x84,0x85,0x44,0x45,0xC4,0xC5,0x24,0x25,0xA4,0xA5,0x64,0x65,0xE4,0xE5,
+ 0x14,0x15,0x94,0x95,0x54,0x55,0xD4,0xD5,0x34,0x35,0xB4,0xB5,0x74,0x75,0xF4,0xF5,
+ 0x0C,0x0D,0x8C,0x8D,0x4C,0x4D,0xCC,0xCD,0x2C,0x2D,0xAC,0xAD,0x6C,0x6D,0xEC,0xED,
+ 0x1C,0x1D,0x9C,0x9D,0x5C,0x5D,0xDC,0xDD,0x3C,0x3D,0xBC,0xBD,0x7C,0x7D,0xFC,0xFD,
+ 0x02,0x03,0x82,0x83,0x42,0x43,0xC2,0xC3,0x22,0x23,0xA2,0xA3,0x62,0x63,0xE2,0xE3,
+ 0x12,0x13,0x92,0x93,0x52,0x53,0xD2,0xD3,0x32,0x33,0xB2,0xB3,0x72,0x73,0xF2,0xF3,
+ 0x0A,0x0B,0x8A,0x8B,0x4A,0x4B,0xCA,0xCB,0x2A,0x2B,0xAA,0xAB,0x6A,0x6B,0xEA,0xEB,
+ 0x1A,0x1B,0x9A,0x9B,0x5A,0x5B,0xDA,0xDB,0x3A,0x3B,0xBA,0xBB,0x7A,0x7B,0xFA,0xFB,
+ 0x06,0x07,0x86,0x87,0x46,0x47,0xC6,0xC7,0x26,0x27,0xA6,0xA7,0x66,0x67,0xE6,0xE7,
+ 0x16,0x17,0x96,0x97,0x56,0x57,0xD6,0xD7,0x36,0x37,0xB6,0xB7,0x76,0x77,0xF6,0xF7,
+ 0x0E,0x0F,0x8E,0x8F,0x4E,0x4F,0xCE,0xCF,0x2E,0x2F,0xAE,0xAF,0x6E,0x6F,0xEE,0xEF,
+ 0x1E,0x1F,0x9E,0x9F,0x5E,0x5F,0xDE,0xDF,0x3E,0x3F,0xBE,0xBF,0x7E,0x7F,0xFE,0xFF
+};
#endif
void lcdSendCtl(uint8_t val)
{
- register Pio *pioptr ;
+ register Pio *pioptr;
#if defined(REVA)
- pioptr = PIOC ;
- pioptr->PIO_CODR = LCD_CS1 ; // Select LCD
- pioptr->PIO_CODR = LCD_A0 ; // Control
- pioptr->PIO_CODR = LCD_RnW ; // Write
- pioptr->PIO_ODSR = Lcd_lookup[val] ;
+ pioptr = PIOC;
+ pioptr->PIO_CODR = LCD_CS1; // Select LCD
+ pioptr->PIO_CODR = LCD_A0; // Control
+ pioptr->PIO_CODR = LCD_RnW; // Write
+ pioptr->PIO_ODSR = Lcd_lookup[val];
#else
- pioptr = PIOC ;
+ pioptr = PIOC;
#if !defined(REVX)
- pioptr->PIO_CODR = LCD_CS1 ; // Select LCD
+ pioptr->PIO_CODR = LCD_CS1; // Select LCD
#endif
- PIOA->PIO_CODR = LCD_A0 ;
+ PIOA->PIO_CODR = LCD_A0;
#if !defined(REVX)
- pioptr->PIO_CODR = LCD_RnW ; // Write
+ pioptr->PIO_CODR = LCD_RnW; // Write
#endif
- pioptr->PIO_ODSR = val ;
+ pioptr->PIO_ODSR = val;
#endif
- pioptr->PIO_SODR = LCD_E ; // Start E pulse
+ pioptr->PIO_SODR = LCD_E; // Start E pulse
// Need a delay here (250nS)
- TC0->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
+ TC0->TC_CHANNEL[0].TC_CCR = 5; // Enable clock and trigger it (may only need trigger)
while ( TC0->TC_CHANNEL[0].TC_CV < 9 ) // Value depends on MCK/2 (used 18MHz)
{
// Wait
}
- pioptr->PIO_CODR = LCD_E ; // End E pulse
+ pioptr->PIO_CODR = LCD_E; // End E pulse
#if defined(REVA)
- pioptr->PIO_SODR = LCD_A0 ; // Data
+ pioptr->PIO_SODR = LCD_A0; // Data
#else
- PIOA->PIO_SODR = LCD_A0 ; // Data
+ PIOA->PIO_SODR = LCD_A0; // Data
#endif
#if !defined(REVX)
- pioptr->PIO_SODR = LCD_CS1 ; // Deselect LCD
+ pioptr->PIO_SODR = LCD_CS1; // Deselect LCD
#endif
}
void lcdInit()
{
- register Pio *pioptr ;
+ register Pio *pioptr;
// /home/thus/txt/datasheets/lcd/KS0713.pdf
// ~/txt/flieger/ST7565RV17.pdf from http://www.glyn.de/content.asp?wdid=132&sid=
// read the inputs, and lock the LCD lines
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
- lcdLock = 1 ;
+ lcdLock = 1;
#if defined(REVA)
- pioptr = PIOC ;
- pioptr->PIO_PER = 0x0C00B0FFL ; // Enable bits 27,26,15,13,12,7-0
- pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_A0 ;
- pioptr->PIO_SODR = LCD_RES | LCD_CS1 ;
- pioptr->PIO_OER = 0x0C00B0FFL ; // Set bits 27,26,15,13,12,7-0 output
- pioptr->PIO_OWER = 0x000000FFL ; // Allow write to ls 8 bits in ODSR
+ pioptr = PIOC;
+ pioptr->PIO_PER = 0x0C00B0FFL; // Enable bits 27,26,15,13,12,7-0
+ pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_A0;
+ pioptr->PIO_SODR = LCD_RES | LCD_CS1;
+ pioptr->PIO_OER = 0x0C00B0FFL; // Set bits 27,26,15,13,12,7-0 output
+ pioptr->PIO_OWER = 0x000000FFL; // Allow write to ls 8 bits in ODSR
#else
- configure_pins( LCD_A0, PIN_ENABLE | PIN_LOW | PIN_OUTPUT | PIN_PORTA | PIN_NO_PULLUP ) ;
- pioptr = PIOC ;
- #if defined(REVX)
- pioptr->PIO_PER = PIO_PC27 | PIO_PC12 | 0xFF ;
- pioptr->PIO_CODR = LCD_E ;
- pioptr->PIO_CODR = LCD_RnW | LCD_CS1 ; // No longer needed, used elsewhere
- #else
- pioptr->PIO_PER = PIO_PC27 | PIO_PC26 | PIO_PC13 | PIO_PC12 | 0xFF ;
- pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_CS1 ;
- #endif
- pioptr->PIO_SODR = LCD_RES ;
- pioptr->PIO_OER = PIO_PC27 | PIO_PC26 | PIO_PC13 | PIO_PC12 | 0xFF ; // Set bits 27,26,13,12,7-0 output
- pioptr->PIO_OWER = 0x000000FFL ; // Allow write to ls 8 bits in ODSR
+ configure_pins( LCD_A0, PIN_ENABLE | PIN_LOW | PIN_OUTPUT | PIN_PORTA | PIN_NO_PULLUP );
+ pioptr = PIOC;
+#if defined(REVX)
+ pioptr->PIO_PER = PIO_PC27 | PIO_PC12 | 0xFF;
+ pioptr->PIO_CODR = LCD_E;
+ pioptr->PIO_CODR = LCD_RnW | LCD_CS1; // No longer needed, used elsewhere
+#else
+ pioptr->PIO_PER = PIO_PC27 | PIO_PC26 | PIO_PC13 | PIO_PC12 | 0xFF;
+ pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_CS1;
+#endif
+ pioptr->PIO_SODR = LCD_RES;
+ pioptr->PIO_OER = PIO_PC27 | PIO_PC26 | PIO_PC13 | PIO_PC12 | 0xFF; // Set bits 27,26,13,12,7-0 output
+ pioptr->PIO_OWER = 0x000000FFL; // Allow write to ls 8 bits in ODSR
#endif
- pioptr->PIO_CODR = LCD_RES ; // Reset LCD
- TC0->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
- while ( TC0->TC_CHANNEL[0].TC_CV < 200 ) // > 10us, Value depends on MCK/2 (used 18MHz)
- {
- // Wait
- }
- pioptr->PIO_SODR = LCD_RES ; // Remove LCD reset
- TC0->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
- while ( TC0->TC_CHANNEL[0].TC_CV < 27000 ) // 1500us, Value depends on MCK/2 (used 18MHz)
- {
- // Wait
- }
+ TC0->TC_CHANNEL[0].TC_CCR = 5; // Enable clock and trigger it (may only need trigger)
+ pioptr->PIO_CODR = LCD_RES; // Reset LCD
+ while ( TC0->TC_CHANNEL[0].TC_CV < 500 ) ; // > 10us, Value depends on MCK/2 (used 18MHz)
+ TC0->TC_CHANNEL[0].TC_CCR = 5; // Enable clock and trigger it (may only need trigger)
+ pioptr->PIO_SODR = LCD_RES; // Remove LCD reset
+ while ( TC0->TC_CHANNEL[0].TC_CV < 27000 ) ; // 1500us, Value depends on MCK/2 (used 18MHz)
lcdSendCtl(0xe2); //Initialize the internal functions
lcdSendCtl(0xae); //DON = 0: display OFF
lcdSendCtl(0xa1); //ADC = 1: reverse direction(SEG132->SEG1)
@@ -182,50 +176,63 @@ void lcdInit()
lcdSendCtl(0x25); //Select int resistance ratio R2 R1 R0 =5
lcdSendCtl(0x81); //Set reference voltage Mode
lcdSendCtl(0x22); // 24 SV5 SV4 SV3 SV2 SV1 SV0 = 0x18
- lcdSendCtl(0xAF); //DON = 1: display ON
- // g_eeGeneral.contrast = 0x22;
-#if defined(REVA)
- pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
- pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
- pioptr->PIO_ODSR = 0 ; // Drive D0 low
-#else
- pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
- pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
- pioptr->PIO_ODSR = 0 ; // Drive D0 low
+#if defined(REVX)
+ // 200mS delay (only if not wdt reset)
+ if ( ( ( ResetReason & RSTC_SR_RSTTYP ) != (2 << 8) ) && !unexpectedShutdown ) {
+ for (uint32_t j = 0; j < 100; j += 1 ) {
+ TC0->TC_CHANNEL[0].TC_CCR = 5; // Enable clock and trigger it (may only need trigger)
+ while ( TC0->TC_CHANNEL[0].TC_CV < 36000 ) {
+ // Value depends on MCK/2 (used 18MHz) give 2mS delay
+ wdt_reset(); // Wait
+ }
+ }
+ }
#endif
- lcdLock = 0 ;
+ lcdSendCtl(0xAF); // DON = 1: display ON
+
+#if defined(REVA)
+ pioptr->PIO_ODR = 0x0000003CL; // Set bits 2, 3, 4, 5 input
+ pioptr->PIO_PUER = 0x0000003CL; // Set bits 2, 3, 4, 5 with pullups
+ pioptr->PIO_ODSR = 0; // Drive D0 low
+#else
+ pioptr->PIO_ODR = 0x0000003AL; // Set bits 1, 3, 4, 5 input
+ pioptr->PIO_PUER = 0x0000003AL; // Set bits 1, 3, 4, 5 with pullups
+ pioptr->PIO_ODSR = 0; // Drive D0 low
+#endif
+
+ lcdLock = 0;
}
void lcdSetRefVolt(uint8_t val)
{
- register Pio *pioptr ;
- pioptr = PIOC ;
+ register Pio *pioptr;
+ pioptr = PIOC;
// read the inputs, and lock the LCD lines
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
- lcdLock = 1 ;
+ lcdLock = 1;
- pioptr->PIO_OER = 0x0C00B0FFL ; // Set bits 27,26,15,13,12,7-0 output
+ pioptr->PIO_OER = 0x0C00B0FFL; // Set bits 27,26,15,13,12,7-0 output
lcdSendCtl(0x81);
if ( val == 0 )
{
- val = 0x22 ;
+ val = 0x22;
}
lcdSendCtl(val);
#if defined(REVA)
- pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
- pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
+ pioptr->PIO_ODR = 0x000000FEL; // Set bits 2, 3, 4, 5 input
+ pioptr->PIO_PUER = 0x000000FEL; // Set bits 2, 3, 4, 5 with pullups
#else
- pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
- pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
+ pioptr->PIO_ODR = 0x000000FEL; // Set bits 1, 3, 4, 5 input
+ pioptr->PIO_PUER = 0x000000FEL; // Set bits 1, 3, 4, 5 with pullups
#endif
- pioptr->PIO_ODSR = lcdInputs; // Drive D0 low
- lcdLock = 0 ;
+ pioptr->PIO_ODSR = 0; // Drive D0 low
+ lcdLock = 0;
}
void lcdRefresh()
@@ -251,7 +258,7 @@ void lcdRefresh()
// read the inputs, and lock the LCD lines
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
- lcdLock = 1 ;
+ lcdLock = 1;
pioptr = PIOC;
#if defined(REVA)
@@ -264,13 +271,13 @@ void lcdRefresh()
lcdSendCtl(0x10); //column addr 0
lcdSendCtl(y | 0xB0); //page addr y
- #if !defined(REVX)
- pioptr->PIO_CODR = LCD_CS1; // Select LCD
- #endif
+#if !defined(REVX)
+ pioptr->PIO_CODR = LCD_CS1; // Select LCD
+#endif
PIOA->PIO_SODR = LCD_A0; // Data
- #if !defined(REVX)
- pioptr->PIO_CODR = LCD_RnW; // Write
- #endif
+#if !defined(REVX)
+ pioptr->PIO_CODR = LCD_RnW; // Write
+#endif
#if defined(REVA)
x = lookup[*p];
@@ -278,16 +285,6 @@ void lcdRefresh()
x = *p;
#endif
for (z = 0; z < LCD_W; z += 1) {
-
-// The following 7 lines replaces by a lookup table
-// x = __RBIT( *p++ ) ;
-// x >>= 23 ;
-// if ( x & 0x00000100 )
-// {
-// x |= 1 ;
-// }
-// pioptr->PIO_ODSR = x ;
-
pioptr->PIO_ODSR = x;
pioptr->PIO_SODR = ebit; // Start E pulse
// Need a delay here (250nS)
@@ -297,27 +294,27 @@ void lcdRefresh()
#else
x = *p;
#endif
-// TC0->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
+// TC0->TC_CHANNEL[0].TC_CCR = 5; // Enable clock and trigger it (may only need trigger)
// while ( TC0->TC_CHANNEL[0].TC_CV < 3 ) // Value depends on MCK/2 (used 6MHz)
// {
// // Wait
// }
pioptr->PIO_CODR = ebit; // End E pulse
}
- #if !defined(REVX)
- pioptr->PIO_SODR = LCD_CS1; // Deselect LCD
- #endif
+#if !defined(REVX)
+ pioptr->PIO_SODR = LCD_CS1; // Deselect LCD
+#endif
}
- pioptr->PIO_ODSR = 0xFF ; // Drive lines high
+ pioptr->PIO_ODSR = 0xFF; // Drive lines high
#if defined(REVA)
- pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
- pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
+ pioptr->PIO_PUER = 0x000000FEL; // Set bits 2, 3, 4, 5 with pullups
+ pioptr->PIO_ODR = 0x000000FEL; // Set bits 2, 3, 4, 5 input
#else
- pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
- pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
+ pioptr->PIO_PUER = 0x000000FEL; // Set bits 1, 3, 4, 5 with pullups
+ pioptr->PIO_ODR = 0x000000FEL; // Set bits 1, 3, 4, 5 input
#endif
- pioptr->PIO_ODSR = lcdInputs; // Drive D0 low
+ pioptr->PIO_ODSR = 0xFE; // Drive D0 low
lcdLock = 0;
}
diff --git a/radio/src/targets/Taranis/board_taranis.cpp b/radio/src/targets/Taranis/board_taranis.cpp
index c78b31eee..15dd5e705 100644
--- a/radio/src/targets/Taranis/board_taranis.cpp
+++ b/radio/src/targets/Taranis/board_taranis.cpp
@@ -131,7 +131,11 @@ void boardInit()
RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | INTERRUPT_5MS_APB1Periph | TIMER_2MHz_APB1Periph | I2C_RCC_APB1Periph | SD_RCC_APB1Periph | TRAINER_RCC_APB1Periph | TELEMETRY_RCC_APB1Periph | SERIAL_RCC_APB1Periph, ENABLE);
RCC_APB2PeriphClockCmd(BACKLIGHT_RCC_APB2Periph | ADC_RCC_APB2Periph | HAPTIC_RCC_APB2Periph | INTMODULE_RCC_APB2Periph | EXTMODULE_RCC_APB2Periph | HEARTBEAT_RCC_APB2Periph, ENABLE);
+#if !defined(REV9E)
+ // some REV9E boards need that the pwrInit() is moved a little bit later
pwrInit();
+#endif
+
keysInit();
adcInit();
delaysInit();
@@ -179,6 +183,7 @@ void boardInit()
else {
if (pwr_on != 1) {
pwr_on = 1;
+ pwrInit();
backlightInit();
haptic.play(15, 3, PLAY_NOW);
}
@@ -191,6 +196,7 @@ void boardInit()
}
}
else {
+ pwrInit();
backlightInit();
}
toplcdInit();
@@ -264,7 +270,7 @@ void checkTrainerSettings()
uint8_t requiredTrainerMode = g_model.trainerMode;
if (requiredTrainerMode != currentTrainerMode) {
switch (currentTrainerMode) {
- case TRAINER_MODE_MASTER:
+ case TRAINER_MODE_MASTER_TRAINER_JACK:
stop_trainer_capture();
break;
case TRAINER_MODE_SLAVE:
diff --git a/radio/src/targets/Taranis/board_taranis.h b/radio/src/targets/Taranis/board_taranis.h
index 1be5ca851..bfe416943 100644
--- a/radio/src/targets/Taranis/board_taranis.h
+++ b/radio/src/targets/Taranis/board_taranis.h
@@ -143,7 +143,12 @@ void configure_pins( uint32_t pins, uint16_t config );
extern uint16_t sessionTimer;
#define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE)
+
+#if defined(REV9E)
+#define TRAINER_CONNECTED() (true)
+#else
#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_GPIO_DETECT, TRAINER_GPIO_PIN_DETECT) == Bit_RESET)
+#endif
#ifdef __cplusplus
extern "C" {
diff --git a/radio/src/targets/Taranis/trainer_driver.cpp b/radio/src/targets/Taranis/trainer_driver.cpp
index c7b9b5ac6..2cd62551b 100644
--- a/radio/src/targets/Taranis/trainer_driver.cpp
+++ b/radio/src/targets/Taranis/trainer_driver.cpp
@@ -127,13 +127,15 @@ extern "C" void TIM3_IRQHandler()
if ( (TRAINER_TIMER->DIER & TIM_DIER_CC3IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC3IF ) ) {
// capture mode on trainer jack
capture = TRAINER_TIMER->CCR3 ;
- doCapture = true;
+ if (TRAINER_CONNECTED() && currentTrainerMode == TRAINER_MODE_MASTER_TRAINER_JACK)
+ doCapture = true;
}
if ( ( TRAINER_TIMER->DIER & TIM_DIER_CC2IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC2IF ) ) {
// capture mode on heartbeat pin (external module)
capture = TRAINER_TIMER->CCR2 ;
- doCapture = true ;
+ if (currentTrainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)
+ doCapture = true ;
}
if (doCapture) {
@@ -247,8 +249,10 @@ extern "C" void HEARTBEAT_USART_IRQHandler()
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
data = HEARTBEAT_USART->DR;
- if (!(status & USART_FLAG_ERRORS))
- sbusFifo.push(data);
+ if (!(status & USART_FLAG_ERRORS)) {
+ if (currentTrainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE)
+ sbusFifo.push(data);
+ }
status = HEARTBEAT_USART->SR;
}
diff --git a/radio/src/targets/mega2560/board_mega2560_stk500v2bootloader.c b/radio/src/targets/mega2560/board_mega2560_stk500v2bootloader.c
new file mode 100644
index 000000000..1b4a2a367
--- /dev/null
+++ b/radio/src/targets/mega2560/board_mega2560_stk500v2bootloader.c
@@ -0,0 +1,2132 @@
+/*****************************************************************************
+Title: STK500v2 compatible bootloader
+Author: Peter Fleury http://jump.to/fleury
+File: $Id: stk500boot.c,v 1.11 2006/06/25 12:39:17 peter Exp $
+Compiler: avr-gcc 3.4.5 or 4.1 / avr-libc 1.4.3
+Hardware: All AVRs with bootloader support, tested with ATmega8
+License: GNU General Public License
+
+Modified: tmrttmrt - JivaroFAD
+Date: 21 October 2015
+Description: OpenTX - MEGA2560 board
+Recommended fuse setting: low 0xFF, hight 0xD8, extended 0xFD, lock 0x0F
+
+DESCRIPTION:
+ This program allows an AVR with bootloader capabilities to
+ read/write its own Flash/EEprom. To enter Programming mode
+ an input pin is checked. If this pin is pulled low, programming mode
+ is entered. If not, normal execution is done from $0000
+ "reset" vector in Application area.
+ Size fits into a 1024 word bootloader section
+ when compiled with avr-gcc 4.1
+ (direct replace on Wiring Board without fuse setting changed)
+
+USAGE:
+ - Set AVR MCU type and clock-frequency (F_CPU) in the Makefile.
+ - Set baud rate below (AVRISP only works with 115200 bps)
+ - compile/link the bootloader with the supplied Makefile
+ - program the "Boot Flash section size" (BOOTSZ fuses),
+ for boot-size 1024 words: program BOOTSZ01
+ - enable the BOOT Reset Vector (program BOOTRST)
+ - Upload the hex file to the AVR using any ISP programmer
+ - Program Boot Lock Mode 3 (program BootLock 11 and BootLock 12 lock bits) // (leave them)
+ - Reset your AVR while keeping PROG_PIN pulled low // (for enter bootloader by switch)
+ - Start AVRISP Programmer (AVRStudio/Tools/Program AVR)
+ - AVRISP will detect the bootloader
+ - Program your application FLASH file and optional EEPROM file using AVRISP
+
+Note:
+ Erasing the device without flashing, through AVRISP GUI button "Erase Device"
+ is not implemented, due to AVRStudio limitations.
+ Flash is always erased before programming.
+
+ AVRdude:
+ Please uncomment #define REMOVE_CMD_SPI_MULTI when using AVRdude.
+ Comment #define REMOVE_PROGRAM_LOCK_BIT_SUPPORT to reduce code size
+ Read Fuse Bits and Read/Write Lock Bits is not supported
+
+NOTES:
+ Based on Atmel Application Note AVR109 - Self-programming
+ Based on Atmel Application Note AVR068 - STK500v2 Protocol
+
+LICENSE:
+ Copyright (C) 2006 Peter Fleury
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*****************************************************************************/
+
+//************************************************************************
+//* Edit History
+//************************************************************************
+//* Jul 7, 2010 = Mark Sproul msproul@skycharoit.com
+//* Jul 7, 2010 Working on mega2560. No Auto-restart
+//* Jul 7, 2010 Switched to 8K bytes (4K words) so that we have room for the monitor
+//* Jul 8, 2010 Found older version of source that had auto restart, put that code back in
+//* Jul 8, 2010 Adding monitor code
+//* Jul 11, 2010 Added blinking LED while waiting for download to start
+//* Jul 11, 2010 Added EEPROM test
+//* Jul 29, 2010 Added recchar_timeout for timing out on bootloading
+//* Aug 23, 2010 Added support for atmega2561
+//* Aug 26, 2010 Removed support for BOOT_BY_SWITCH
+//* Sep 8, 2010 Added support for atmega16
+//* Nov 9, 2010 Issue 392:Fixed bug that 3 !!! in code would cause it to jump to monitor
+//* Jun 24, 2011 Removed analogRead (was not used)
+//* Dec 29, 2011 Issue 181: added watch dog timmer support
+//* Dec 29, 2011 Issue 505: bootloader is comparing the seqNum to 1 or the current sequence
+//* Jan 1, 2012 Issue 543: CMD_CHIP_ERASE_ISP now returns STATUS_CMD_FAILED instead of STATUS_CMD_OK
+//* Jan 1, 2012 Issue 543: Write EEPROM now does something (NOT TESTED)
+//* Jan 1, 2012 Issue 544: stk500v2 bootloader doesn't support reading fuses
+//************************************************************************
+
+//************************************************************************
+//* these are used to test issues
+//* http://code.google.com/p/arduino/issues/detail?id=505
+//* Reported by mark.stubbs, Mar 14, 2011
+//* The STK500V2 bootloader is comparing the seqNum to 1 or the current sequence
+//* (IE: Requiring the sequence to be 1 or match seqNum before continuing).
+//* The correct behavior is for the STK500V2 to accept the PC's sequence number, and echo it back for the reply message.
+#define _FIX_ISSUE_505_
+//************************************************************************
+//* Issue 181: added watch dog timmer support
+#define _FIX_ISSUE_181_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "command.h"
+
+
+#if defined(_MEGA_BOARD_) || defined(_BOARD_AMBER128_) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \
+ || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1284P__) || defined(ENABLE_MONITOR)
+ #undef ENABLE_MONITOR
+ #define ENABLE_MONITOR
+ static void RunMonitor(void);
+#endif
+
+#ifndef EEWE
+ #define EEWE 1
+#endif
+#ifndef EEMWE
+ #define EEMWE 2
+#endif
+
+//#define _DEBUG_SERIAL_
+//#define _DEBUG_WITH_LEDS_
+
+
+/*
+ * Uncomment the following lines to save code space
+ */
+//#define REMOVE_PROGRAM_LOCK_BIT_SUPPORT // disable program lock bits
+//#define REMOVE_BOOTLOADER_LED // no LED to show active bootloader
+//#define REMOVE_CMD_SPI_MULTI // disable processing of SPI_MULTI commands, Remark this line for AVRDUDE
+//
+
+
+
+//************************************************************************
+//* LED on pin "PROGLED_PIN" on port "PROGLED_PORT"
+//* indicates that bootloader is active
+//* PG2 -> LED on Wiring board
+//************************************************************************
+#define BLINK_LED_WHILE_WAITING
+
+#ifdef _MEGA_BOARD_
+ #define PROGLED_PORT PORTB
+ #define PROGLED_DDR DDRB
+ #define PROGLED_PIN PINB7
+#elif defined( _BOARD_AMBER128_ )
+ //* this is for the amber 128 http://www.soc-robotics.com/
+ //* onbarod led is PORTE4
+ #define PROGLED_PORT PORTD
+ #define PROGLED_DDR DDRD
+ #define PROGLED_PIN PINE7
+#elif defined( _CEREBOTPLUS_BOARD_ ) || defined(_CEREBOT_II_BOARD_)
+ //* this is for the Cerebot 2560 board and the Cerebot-ii
+ //* onbarod leds are on PORTE4-7
+ #define PROGLED_PORT PORTE
+ #define PROGLED_DDR DDRE
+ #define PROGLED_PIN PINE7
+#elif defined( _PENGUINO_ )
+ //* this is for the Penguino
+ //* onbarod led is PORTE4
+ #define PROGLED_PORT PORTC
+ #define PROGLED_DDR DDRC
+ #define PROGLED_PIN PINC6
+#elif defined( _ANDROID_2561_ ) || defined( __AVR_ATmega2561__ )
+ //* this is for the Boston Android 2561
+ //* onbarod led is PORTE4
+ #define PROGLED_PORT PORTA
+ #define PROGLED_DDR DDRA
+ #define PROGLED_PIN PINA3
+#elif defined( _BOARD_MEGA16 )
+ //* onbarod led is PORTA7
+ #define PROGLED_PORT PORTA
+ #define PROGLED_DDR DDRA
+ #define PROGLED_PIN PINA7
+ #define UART_BAUDRATE_DOUBLE_SPEED 0
+
+#elif defined( _BOARD_BAHBOT_ )
+ //* dosent have an onboard LED but this is what will probably be added to this port
+ #define PROGLED_PORT PORTB
+ #define PROGLED_DDR DDRB
+ #define PROGLED_PIN PINB0
+
+#elif defined( _BOARD_ROBOTX_ )
+ #define PROGLED_PORT PORTB
+ #define PROGLED_DDR DDRB
+ #define PROGLED_PIN PINB6
+#elif defined( _BOARD_CUSTOM1284_BLINK_B0_ )
+ #define PROGLED_PORT PORTB
+ #define PROGLED_DDR DDRB
+ #define PROGLED_PIN PINB0
+#elif defined( _BOARD_CUSTOM1284_ )
+ #define PROGLED_PORT PORTD
+ #define PROGLED_DDR DDRD
+ #define PROGLED_PIN PIND5
+#elif defined( _AVRLIP_ )
+ #define PROGLED_PORT PORTB
+ #define PROGLED_DDR DDRB
+ #define PROGLED_PIN PINB5
+#elif defined( _BOARD_STK500_ )
+ #define PROGLED_PORT PORTA
+ #define PROGLED_DDR DDRA
+ #define PROGLED_PIN PINA7
+#elif defined( _BOARD_STK502_ )
+ #define PROGLED_PORT PORTB
+ #define PROGLED_DDR DDRB
+ #define PROGLED_PIN PINB5
+#elif defined( _BOARD_STK525_ )
+ #define PROGLED_PORT PORTB
+ #define PROGLED_DDR DDRB
+ #define PROGLED_PIN PINB7
+#else
+ #define PROGLED_PORT PORTG
+ #define PROGLED_DDR DDRG
+ #define PROGLED_PIN PING2
+#endif
+
+
+
+/*
+ * define CPU frequency in Mhz here if not defined in Makefile
+ */
+#ifndef F_CPU
+ #define F_CPU 16000000UL
+#endif
+
+#define _BLINK_LOOP_COUNT_ (F_CPU / 2250)
+/*
+ * UART Baudrate, AVRStudio AVRISP only accepts 115200 bps
+ */
+
+#ifndef BAUDRATE
+ #define BAUDRATE 115200
+#endif
+
+/*
+ * Enable (1) or disable (0) USART double speed operation
+ */
+#ifndef UART_BAUDRATE_DOUBLE_SPEED
+ #if defined (__AVR_ATmega32__)
+ #define UART_BAUDRATE_DOUBLE_SPEED 0
+ #else
+ #define UART_BAUDRATE_DOUBLE_SPEED 1
+ #endif
+#endif
+
+/*
+ * HW and SW version, reported to AVRISP, must match version of AVRStudio
+ */
+#define CONFIG_PARAM_BUILD_NUMBER_LOW 0
+#define CONFIG_PARAM_BUILD_NUMBER_HIGH 0
+#define CONFIG_PARAM_HW_VER 0x0F
+#define CONFIG_PARAM_SW_MAJOR 2
+#define CONFIG_PARAM_SW_MINOR 0x0A
+
+/*
+ * Calculate the address where the bootloader starts from FLASHEND and BOOTSIZE
+ * (adjust BOOTSIZE below and BOOTLOADER_ADDRESS in Makefile if you want to change the size of the bootloader)
+ */
+//#define BOOTSIZE 1024
+#if FLASHEND > 0x0F000
+ #define BOOTSIZE 8192
+#else
+ #define BOOTSIZE 2048
+#endif
+
+#define MAX_ERR_COUNT 10
+#define APP_END (FLASHEND -(2*BOOTSIZE) + 1)
+
+/*
+ * Signature bytes are not available in avr-gcc io_xxx.h
+ */
+#if defined (__AVR_ATmega8__)
+ #define SIGNATURE_BYTES 0x1E9307
+#elif defined (__AVR_ATmega16__)
+ #define SIGNATURE_BYTES 0x1E9403
+#elif defined (__AVR_ATmega32__)
+ #define SIGNATURE_BYTES 0x1E9502
+#elif defined (__AVR_ATmega8515__)
+ #define SIGNATURE_BYTES 0x1E9306
+#elif defined (__AVR_ATmega8535__)
+ #define SIGNATURE_BYTES 0x1E9308
+#elif defined (__AVR_ATmega162__)
+ #define SIGNATURE_BYTES 0x1E9404
+#elif defined (__AVR_ATmega128__)
+ #define SIGNATURE_BYTES 0x1E9702
+#elif defined (__AVR_ATmega1280__)
+ #define SIGNATURE_BYTES 0x1E9703
+#elif defined (__AVR_ATmega2560__)
+ #define SIGNATURE_BYTES 0x1E9801
+#elif defined (__AVR_ATmega2561__)
+ #define SIGNATURE_BYTES 0x1e9802
+#elif defined (__AVR_ATmega1284P__)
+ #define SIGNATURE_BYTES 0x1e9705
+#elif defined (__AVR_ATmega640__)
+ #define SIGNATURE_BYTES 0x1e9608
+#elif defined (__AVR_ATmega64__)
+ #define SIGNATURE_BYTES 0x1E9602
+#elif defined (__AVR_ATmega169__)
+ #define SIGNATURE_BYTES 0x1e9405
+#elif defined (__AVR_AT90USB1287__)
+ #define SIGNATURE_BYTES 0x1e9782
+#else
+ #error "no signature definition for MCU available"
+#endif
+
+
+#if defined(_BOARD_ROBOTX_) || defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__)
+ #define UART_BAUD_RATE_LOW UBRR1L
+ #define UART_STATUS_REG UCSR1A
+ #define UART_CONTROL_REG UCSR1B
+ #define UART_ENABLE_TRANSMITTER TXEN1
+ #define UART_ENABLE_RECEIVER RXEN1
+ #define UART_TRANSMIT_COMPLETE TXC1
+ #define UART_RECEIVE_COMPLETE RXC1
+ #define UART_DATA_REG UDR1
+ #define UART_DOUBLE_SPEED U2X1
+
+#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
+ || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__)
+ /* ATMega8 with one USART */
+ #define UART_BAUD_RATE_LOW UBRRL
+ #define UART_STATUS_REG UCSRA
+ #define UART_CONTROL_REG UCSRB
+ #define UART_ENABLE_TRANSMITTER TXEN
+ #define UART_ENABLE_RECEIVER RXEN
+ #define UART_TRANSMIT_COMPLETE TXC
+ #define UART_RECEIVE_COMPLETE RXC
+ #define UART_DATA_REG UDR
+ #define UART_DOUBLE_SPEED U2X
+
+#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega162__) \
+ || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
+ /* ATMega with two USART, use UART0 */
+ #define UART_BAUD_RATE_LOW UBRR0L
+ #define UART_STATUS_REG UCSR0A
+ #define UART_CONTROL_REG UCSR0B
+ #define UART_ENABLE_TRANSMITTER TXEN0
+ #define UART_ENABLE_RECEIVER RXEN0
+ #define UART_TRANSMIT_COMPLETE TXC0
+ #define UART_RECEIVE_COMPLETE RXC0
+ #define UART_DATA_REG UDR0
+ #define UART_DOUBLE_SPEED U2X0
+#elif defined(UBRR0L) && defined(UCSR0A) && defined(TXEN0)
+ /* ATMega with two USART, use UART0 */
+ #define UART_BAUD_RATE_LOW UBRR0L
+ #define UART_STATUS_REG UCSR0A
+ #define UART_CONTROL_REG UCSR0B
+ #define UART_ENABLE_TRANSMITTER TXEN0
+ #define UART_ENABLE_RECEIVER RXEN0
+ #define UART_TRANSMIT_COMPLETE TXC0
+ #define UART_RECEIVE_COMPLETE RXC0
+ #define UART_DATA_REG UDR0
+ #define UART_DOUBLE_SPEED U2X0
+#elif defined(UBRRL) && defined(UCSRA) && defined(UCSRB) && defined(TXEN) && defined(RXEN)
+ //* catch all
+ #define UART_BAUD_RATE_LOW UBRRL
+ #define UART_STATUS_REG UCSRA
+ #define UART_CONTROL_REG UCSRB
+ #define UART_ENABLE_TRANSMITTER TXEN
+ #define UART_ENABLE_RECEIVER RXEN
+ #define UART_TRANSMIT_COMPLETE TXC
+ #define UART_RECEIVE_COMPLETE RXC
+ #define UART_DATA_REG UDR
+ #define UART_DOUBLE_SPEED U2X
+#else
+ #error "no UART definition for MCU available"
+#endif
+
+
+
+/*
+ * Macro to calculate UBBR from XTAL and baudrate
+ */
+#if defined(__AVR_ATmega32__) && UART_BAUDRATE_DOUBLE_SPEED
+ #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu / 4 / baudRate - 1) / 2)
+#elif defined(__AVR_ATmega32__)
+ #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu / 8 / baudRate - 1) / 2)
+#elif UART_BAUDRATE_DOUBLE_SPEED
+ #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1.0+0.5)
+#else
+ #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*16.0)-1.0+0.5)
+#endif
+
+
+/*
+ * States used in the receive state machine
+ */
+#define ST_START 0
+#define ST_GET_SEQ_NUM 1
+#define ST_MSG_SIZE_1 2
+#define ST_MSG_SIZE_2 3
+#define ST_GET_TOKEN 4
+#define ST_GET_DATA 5
+#define ST_GET_CHECK 6
+#define ST_PROCESS 7
+
+/*
+ * use 16bit address variable for ATmegas with <= 64K flash
+ */
+#if defined(RAMPZ)
+ typedef uint32_t address_t;
+#else
+ typedef uint16_t address_t;
+#endif
+
+/*
+ * function prototypes
+ */
+static void sendchar(char c);
+static unsigned char recchar(void);
+
+/*
+ * since this bootloader is not linked against the avr-gcc crt1 functions,
+ * to reduce the code size, we need to provide our own initialization
+ */
+void __jumpMain (void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
+#include
+
+//#define SPH_REG 0x3E
+//#define SPL_REG 0x3D
+
+//*****************************************************************************
+void __jumpMain(void)
+{
+//* July 17, 2010 Added stack pointer initialzation
+//* the first line did not do the job on the ATmega128
+
+ asm volatile ( ".set __stack, %0" :: "i" (RAMEND) );
+
+//* set stack pointer to top of RAM
+
+ asm volatile ( "ldi 16, %0" :: "i" (RAMEND >> 8) );
+ asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_HI_ADDR) );
+
+ asm volatile ( "ldi 16, %0" :: "i" (RAMEND & 0x0ff) );
+ asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_LO_ADDR) );
+
+ asm volatile ( "clr __zero_reg__" ); // GCC depends on register r1 set to 0
+ asm volatile ( "out %0, __zero_reg__" :: "I" (_SFR_IO_ADDR(SREG)) ); // set SREG to 0
+ asm volatile ( "jmp main"); // jump to main()
+}
+
+
+//*****************************************************************************
+void delay_ms(unsigned int timedelay)
+{
+ unsigned int i;
+ for (i=0;i> 1)
+//*****************************************************************************
+static unsigned char recchar_timeout(void)
+{
+uint32_t count = 0;
+
+ while (!(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE)))
+ {
+ // wait for data
+ count++;
+ if (count > MAX_TIME_COUNT)
+ {
+ unsigned int data;
+ #if (FLASHEND > 0x10000)
+ data = pgm_read_word_far(0); //* get the first word of the user program
+ #else
+ data = pgm_read_word_near(0); //* get the first word of the user program
+ #endif
+ if (data != 0xffff) //* make sure its valid before jumping to it.
+ {
+ asm volatile(
+ "clr r30 \n\t"
+ "clr r31 \n\t"
+ "ijmp \n\t"
+ );
+ }
+ count = 0;
+ }
+ }
+ return UART_DATA_REG;
+}
+
+//* for watch dog timer startup
+void (*app_start)(void) = 0x0000;
+
+
+//*****************************************************************************
+int main(void)
+{
+ address_t address = 0;
+ address_t eraseAddress = 0;
+ unsigned char msgParseState;
+ unsigned int ii = 0;
+ unsigned char checksum = 0;
+ unsigned char seqNum = 0;
+ unsigned int msgLength = 0;
+ unsigned char msgBuffer[285];
+ unsigned char c, *p;
+ unsigned char isLeave = 0;
+ unsigned char errCnt = 0;
+
+ unsigned long boot_timeout;
+ unsigned long boot_timer;
+ unsigned int boot_state;
+#ifdef ENABLE_MONITOR
+ unsigned int exPointCntr = 0;
+ unsigned int rcvdCharCntr = 0;
+#endif
+
+ //* some chips dont set the stack properly
+ asm volatile ( ".set __stack, %0" :: "i" (RAMEND) );
+ asm volatile ( "ldi 16, %0" :: "i" (RAMEND >> 8) );
+ asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_HI_ADDR) );
+ asm volatile ( "ldi 16, %0" :: "i" (RAMEND & 0x0ff) );
+ asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_LO_ADDR) );
+
+#ifdef _FIX_ISSUE_181_
+ //************************************************************************
+ //* Dec 29, 2011 Issue #181, added watch dog timmer support
+ //* handle the watch dog timer
+ uint8_t mcuStatusReg;
+ mcuStatusReg = MCUSR;
+
+ __asm__ __volatile__ ("cli");
+ __asm__ __volatile__ ("wdr");
+ MCUSR = 0;
+ WDTCSR |= _BV(WDCE) | _BV(WDE);
+ WDTCSR = 0;
+ __asm__ __volatile__ ("sei");
+ // check if WDT generated the reset, if so, go straight to app
+ if (mcuStatusReg & _BV(WDRF))
+ {
+ app_start();
+ }
+ //************************************************************************
+#endif
+
+
+ boot_timer = 0;
+ boot_state = 0;
+
+#ifdef BLINK_LED_WHILE_WAITING
+// boot_timeout = 90000; //* should be about 4 seconds
+// boot_timeout = 170000;
+ boot_timeout = 20000; //* should be about 1 second
+#else
+ boot_timeout = 3500000; // 7 seconds , approx 2us per step when optimize "s"
+#endif
+ /*
+ * Branch to bootloader or application code ?
+ */
+
+#ifndef REMOVE_BOOTLOADER_LED
+ /* PROG_PIN pulled low, indicate with LED that bootloader is active */
+ PROGLED_DDR |= (1< boot_timeout)
+ {
+ boot_state = 1; // (after ++ -> boot_state=2 bootloader timeout, jump to main 0x00000 )
+ }
+ #ifdef BLINK_LED_WHILE_WAITING
+ if ((boot_timer % _BLINK_LOOP_COUNT_) == 0)
+ {
+ //* toggle the LED
+ PROGLED_PORT ^= (1< MAX_ERR_COUNT)
+ {
+ msgBuffer[0]=CMD_LEAVE_PROGMODE_ISP;
+ msgParseState=ST_PROCESS;
+ }
+ }
+ break;
+
+ case ST_GET_SEQ_NUM:
+ #ifdef _FIX_ISSUE_505_
+ seqNum = c;
+ msgParseState = ST_MSG_SIZE_1;
+ checksum ^= c;
+ #else
+ if ( (c == 1) || (c == seqNum) )
+ {
+ seqNum = c;
+ msgParseState = ST_MSG_SIZE_1;
+ checksum ^= c;
+ }
+ else
+ {
+ msgParseState = ST_START;
+ }
+ #endif
+ break;
+
+ case ST_MSG_SIZE_1:
+ msgLength = c<<8;
+ msgParseState = ST_MSG_SIZE_2;
+ checksum ^= c;
+ break;
+
+ case ST_MSG_SIZE_2:
+ msgLength |= c;
+ msgParseState = ST_GET_TOKEN;
+ checksum ^= c;
+ break;
+
+ case ST_GET_TOKEN:
+ if ( c == TOKEN )
+ {
+ msgParseState = ST_GET_DATA;
+ checksum ^= c;
+ ii = 0;
+ }
+ else
+ {
+ msgParseState = ST_START;
+ }
+ break;
+
+ case ST_GET_DATA:
+ msgBuffer[ii++] = c;
+ checksum ^= c;
+ if (ii == msgLength )
+ {
+ msgParseState = ST_GET_CHECK;
+ }
+ break;
+
+ case ST_GET_CHECK:
+ if ( c == checksum )
+ {
+ msgParseState = ST_PROCESS;
+ }
+ else
+ {
+ msgParseState = ST_START;
+ }
+ break;
+ } // switch
+ } // while(msgParseState)
+
+ /*
+ * Now process the STK500 commands, see Atmel Appnote AVR068
+ */
+
+ switch (msgBuffer[0])
+ {
+ #ifndef REMOVE_CMD_SPI_MULTI
+ case CMD_SPI_MULTI:
+ {
+ unsigned char answerByte;
+ unsigned char flag=0;
+
+ if ( msgBuffer[4]== 0x30 )
+ {
+ unsigned char signatureIndex = msgBuffer[6];
+
+ if ( signatureIndex == 0 )
+ {
+ answerByte = (SIGNATURE_BYTES >> 16) & 0x000000FF;
+ }
+ else if ( signatureIndex == 1 )
+ {
+ answerByte = (SIGNATURE_BYTES >> 8) & 0x000000FF;
+ }
+ else
+ {
+ answerByte = SIGNATURE_BYTES & 0x000000FF;
+ }
+ }
+ else if ( msgBuffer[4] & 0x50 )
+ {
+ //* Issue 544: stk500v2 bootloader doesn't support reading fuses
+ //* I cant find the docs that say what these are supposed to be but this was figured out by trial and error
+ // answerByte = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
+ // answerByte = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
+ // answerByte = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
+ if (msgBuffer[4] == 0x50)
+ {
+ answerByte = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
+ }
+ else if (msgBuffer[4] == 0x58)
+ {
+ answerByte = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
+ }
+ else
+ {
+ answerByte = 0;
+ }
+ }
+ else
+ {
+ answerByte = 0; // for all others command are not implemented, return dummy value for AVRDUDE happy
+ }
+ if ( !flag )
+ {
+ msgLength = 7;
+ msgBuffer[1] = STATUS_CMD_OK;
+ msgBuffer[2] = 0;
+ msgBuffer[3] = msgBuffer[4];
+ msgBuffer[4] = 0;
+ msgBuffer[5] = answerByte;
+ msgBuffer[6] = STATUS_CMD_OK;
+ }
+ }
+ break;
+ #endif
+ case CMD_SIGN_ON:
+ msgLength = 11;
+ msgBuffer[1] = STATUS_CMD_OK;
+ msgBuffer[2] = 8;
+ msgBuffer[3] = 'A';
+ msgBuffer[4] = 'V';
+ msgBuffer[5] = 'R';
+ msgBuffer[6] = 'I';
+ msgBuffer[7] = 'S';
+ msgBuffer[8] = 'P';
+ msgBuffer[9] = '_';
+ msgBuffer[10] = '2';
+ break;
+
+ case CMD_GET_PARAMETER:
+ {
+ unsigned char value;
+
+ switch(msgBuffer[1])
+ {
+ case PARAM_BUILD_NUMBER_LOW:
+ value = CONFIG_PARAM_BUILD_NUMBER_LOW;
+ break;
+ case PARAM_BUILD_NUMBER_HIGH:
+ value = CONFIG_PARAM_BUILD_NUMBER_HIGH;
+ break;
+ case PARAM_HW_VER:
+ value = CONFIG_PARAM_HW_VER;
+ break;
+ case PARAM_SW_MAJOR:
+ value = CONFIG_PARAM_SW_MAJOR;
+ break;
+ case PARAM_SW_MINOR:
+ value = CONFIG_PARAM_SW_MINOR;
+ break;
+ default:
+ value = 0;
+ break;
+ }
+ msgLength = 3;
+ msgBuffer[1] = STATUS_CMD_OK;
+ msgBuffer[2] = value;
+ }
+ break;
+
+ case CMD_LEAVE_PROGMODE_ISP:
+ isLeave = 1;
+ //* fall thru
+
+ case CMD_SET_PARAMETER:
+ case CMD_ENTER_PROGMODE_ISP:
+ msgLength = 2;
+ msgBuffer[1] = STATUS_CMD_OK;
+ break;
+
+ case CMD_READ_SIGNATURE_ISP:
+ {
+ unsigned char signatureIndex = msgBuffer[4];
+ unsigned char signature;
+
+ if ( signatureIndex == 0 )
+ signature = (SIGNATURE_BYTES >>16) & 0x000000FF;
+ else if ( signatureIndex == 1 )
+ signature = (SIGNATURE_BYTES >> 8) & 0x000000FF;
+ else
+ signature = SIGNATURE_BYTES & 0x000000FF;
+
+ msgLength = 4;
+ msgBuffer[1] = STATUS_CMD_OK;
+ msgBuffer[2] = signature;
+ msgBuffer[3] = STATUS_CMD_OK;
+ }
+ break;
+
+ case CMD_READ_LOCK_ISP:
+ msgLength = 4;
+ msgBuffer[1] = STATUS_CMD_OK;
+ msgBuffer[2] = boot_lock_fuse_bits_get( GET_LOCK_BITS );
+ msgBuffer[3] = STATUS_CMD_OK;
+ break;
+
+ case CMD_READ_FUSE_ISP:
+ {
+ unsigned char fuseBits;
+
+ if ( msgBuffer[2] == 0x50 )
+ {
+ if ( msgBuffer[3] == 0x08 )
+ fuseBits = boot_lock_fuse_bits_get( GET_EXTENDED_FUSE_BITS );
+ else
+ fuseBits = boot_lock_fuse_bits_get( GET_LOW_FUSE_BITS );
+ }
+ else
+ {
+ fuseBits = boot_lock_fuse_bits_get( GET_HIGH_FUSE_BITS );
+ }
+ msgLength = 4;
+ msgBuffer[1] = STATUS_CMD_OK;
+ msgBuffer[2] = fuseBits;
+ msgBuffer[3] = STATUS_CMD_OK;
+ }
+ break;
+
+ #ifndef REMOVE_PROGRAM_LOCK_BIT_SUPPORT
+ case CMD_PROGRAM_LOCK_ISP:
+ {
+ unsigned char lockBits = msgBuffer[4];
+
+ lockBits = (~lockBits) & 0x3C; // mask BLBxx bits
+ boot_lock_bits_set(lockBits); // and program it
+ boot_spm_busy_wait();
+
+ msgLength = 3;
+ msgBuffer[1] = STATUS_CMD_OK;
+ msgBuffer[2] = STATUS_CMD_OK;
+ }
+ break;
+ #endif
+ case CMD_CHIP_ERASE_ISP:
+ eraseAddress = 0;
+ msgLength = 2;
+ // msgBuffer[1] = STATUS_CMD_OK;
+ msgBuffer[1] = STATUS_CMD_FAILED; //* isue 543, return FAILED instead of OK
+ break;
+
+ case CMD_LOAD_ADDRESS:
+ #if defined(RAMPZ)
+ address = ( ((address_t)(msgBuffer[1])<<24)|((address_t)(msgBuffer[2])<<16)|((address_t)(msgBuffer[3])<<8)|(msgBuffer[4]) )<<1;
+ #else
+ address = ( ((msgBuffer[3])<<8)|(msgBuffer[4]) )<<1; //convert word to byte address
+ #endif
+ msgLength = 2;
+ msgBuffer[1] = STATUS_CMD_OK;
+ break;
+
+ case CMD_PROGRAM_FLASH_ISP:
+ case CMD_PROGRAM_EEPROM_ISP:
+ {
+ unsigned int size = ((msgBuffer[1])<<8) | msgBuffer[2];
+ unsigned char *p = msgBuffer+10;
+ unsigned int data;
+ unsigned char highByte, lowByte;
+ address_t tempaddress = address;
+
+
+ if ( msgBuffer[0] == CMD_PROGRAM_FLASH_ISP )
+ {
+ // erase only main section (bootloader protection)
+ if (eraseAddress < APP_END )
+ {
+ boot_page_erase(eraseAddress); // Perform page erase
+ boot_spm_busy_wait(); // Wait until the memory is erased.
+ eraseAddress += SPM_PAGESIZE; // point to next page to be erase
+ }
+
+ /* Write FLASH */
+ do {
+ lowByte = *p++;
+ highByte = *p++;
+
+ data = (highByte << 8) | lowByte;
+ boot_page_fill(address,data);
+
+ address = address + 2; // Select next word in memory
+ size -= 2; // Reduce number of bytes to write by two
+ } while (size); // Loop until all bytes written
+
+ boot_page_write(tempaddress);
+ boot_spm_busy_wait();
+ boot_rww_enable(); // Re-enable the RWW section
+ }
+ else
+ {
+ //* issue 543, this should work, It has not been tested.
+ uint16_t ii = address >> 1;
+ /* write EEPROM */
+ while (size) {
+ eeprom_write_byte((uint8_t*)ii, *p++);
+ address+=2; // Select next EEPROM byte
+ ii++;
+ size--;
+ }
+ }
+ msgLength = 2;
+ msgBuffer[1] = STATUS_CMD_OK;
+ }
+ break;
+
+ case CMD_READ_FLASH_ISP:
+ case CMD_READ_EEPROM_ISP:
+ {
+ unsigned int size = ((msgBuffer[1])<<8) | msgBuffer[2];
+ unsigned char *p = msgBuffer+1;
+ msgLength = size+3;
+
+ *p++ = STATUS_CMD_OK;
+ if (msgBuffer[0] == CMD_READ_FLASH_ISP )
+ {
+ unsigned int data;
+
+ // Read FLASH
+ do {
+ //#if defined(RAMPZ)
+ #if (FLASHEND > 0x10000)
+ data = pgm_read_word_far(address);
+ #else
+ data = pgm_read_word_near(address);
+ #endif
+ *p++ = (unsigned char)data; //LSB
+ *p++ = (unsigned char)(data >> 8); //MSB
+ address += 2; // Select next word in memory
+ size -= 2;
+ }while (size);
+ }
+ else
+ {
+ /* Read EEPROM */
+ do {
+ EEARL = address; // Setup EEPROM address
+ EEARH = ((address >> 8));
+ address++; // Select next EEPROM byte
+ EECR |= (1<>8)&0xFF);
+ sendchar(c);
+ checksum ^= c;
+
+ c = msgLength&0x00FF;
+ sendchar(c);
+ checksum ^= c;
+
+ sendchar(TOKEN);
+ checksum ^= TOKEN;
+
+ p = msgBuffer;
+ while ( msgLength )
+ {
+ c = *p++;
+ sendchar(c);
+ checksum ^=c;
+ msgLength--;
+ }
+ sendchar(checksum);
+ seqNum++;
+
+ #ifndef REMOVE_BOOTLOADER_LED
+ //* toggle the LED
+ PROGLED_PORT ^= (1<
+
+
+base address = f000
+avrdude: Device signature = 0x1e9703
+avrdude: safemode: lfuse reads as FF
+avrdude: safemode: hfuse reads as D8
+avrdude: safemode: efuse reads as F5
+avrdude>
+*/
+
+//************************************************************************
+#ifdef ENABLE_MONITOR
+#include
+
+unsigned long gRamIndex;
+unsigned long gFlashIndex;
+unsigned long gEepromIndex;
+
+
+#define true 1
+#define false 0
+
+#include "avr_cpunames.h"
+
+#ifndef _AVR_CPU_NAME_
+ #error cpu name not defined
+#endif
+
+#ifdef _VECTORS_SIZE
+ #define kInterruptVectorCount (_VECTORS_SIZE / 4)
+#else
+ #define kInterruptVectorCount 23
+#endif
+
+
+void PrintDecInt(int theNumber, int digitCnt);
+
+#ifdef _AVR_CPU_NAME_
+ const char gTextMsg_CPU_Name[] PROGMEM = _AVR_CPU_NAME_;
+#else
+ const char gTextMsg_CPU_Name[] PROGMEM = "UNKNOWN";
+#endif
+
+ const char gTextMsg_Explorer[] PROGMEM = "Arduino explorer stk500V2 by MLS";
+ const char gTextMsg_Prompt[] PROGMEM = "Bootloader>";
+ const char gTextMsg_HUH[] PROGMEM = "Huh?";
+ const char gTextMsg_COMPILED_ON[] PROGMEM = "Compiled on = ";
+ const char gTextMsg_CPU_Type[] PROGMEM = "CPU Type = ";
+ const char gTextMsg_AVR_ARCH[] PROGMEM = "__AVR_ARCH__= ";
+ const char gTextMsg_AVR_LIBC[] PROGMEM = "AVR LibC Ver= ";
+ const char gTextMsg_GCC_VERSION[] PROGMEM = "GCC Version = ";
+ const char gTextMsg_CPU_SIGNATURE[] PROGMEM = "CPU ID = ";
+ const char gTextMsg_FUSE_BYTE_LOW[] PROGMEM = "Low fuse = ";
+ const char gTextMsg_FUSE_BYTE_HIGH[] PROGMEM = "High fuse = ";
+ const char gTextMsg_FUSE_BYTE_EXT[] PROGMEM = "Ext fuse = ";
+ const char gTextMsg_FUSE_BYTE_LOCK[] PROGMEM = "Lock fuse = ";
+ const char gTextMsg_GCC_DATE_STR[] PROGMEM = __DATE__;
+ const char gTextMsg_AVR_LIBC_VER_STR[] PROGMEM = __AVR_LIBC_VERSION_STRING__;
+ const char gTextMsg_GCC_VERSION_STR[] PROGMEM = __VERSION__;
+ const char gTextMsg_VECTOR_HEADER[] PROGMEM = "V# ADDR op code instruction addr Interrupt";
+ const char gTextMsg_noVector[] PROGMEM = "no vector";
+ const char gTextMsg_rjmp[] PROGMEM = "rjmp ";
+ const char gTextMsg_jmp[] PROGMEM = "jmp ";
+ const char gTextMsg_WHAT_PORT[] PROGMEM = "What port:";
+ const char gTextMsg_PortNotSupported[] PROGMEM = "Port not supported";
+ const char gTextMsg_MustBeLetter[] PROGMEM = "Must be a letter";
+ const char gTextMsg_SPACE[] PROGMEM = " ";
+ const char gTextMsg_WriteToEEprom[] PROGMEM = "Writting EE";
+ const char gTextMsg_ReadingEEprom[] PROGMEM = "Reading EE";
+ const char gTextMsg_EEPROMerrorCnt[] PROGMEM = "EE err cnt=";
+ const char gTextMsg_PORT[] PROGMEM = "PORT";
+
+
+//************************************************************************
+//* Help messages
+ const char gTextMsg_HELP_MSG_0[] PROGMEM = "0=Zero addr";
+ const char gTextMsg_HELP_MSG_QM[] PROGMEM = "?=CPU stats";
+ const char gTextMsg_HELP_MSG_AT[] PROGMEM = "@=EEPROM test";
+ const char gTextMsg_HELP_MSG_B[] PROGMEM = "B=Blink LED";
+ const char gTextMsg_HELP_MSG_E[] PROGMEM = "E=Dump EEPROM";
+ const char gTextMsg_HELP_MSG_F[] PROGMEM = "F=Dump FLASH";
+ const char gTextMsg_HELP_MSG_H[] PROGMEM = "H=Help";
+ const char gTextMsg_HELP_MSG_L[] PROGMEM = "L=List I/O Ports";
+// const char gTextMsg_HELP_MSG_Q[] PROGMEM = "Q=Quit & jump to user pgm";
+ const char gTextMsg_HELP_MSG_Q[] PROGMEM = "Q=Quit";
+ const char gTextMsg_HELP_MSG_R[] PROGMEM = "R=Dump RAM";
+ const char gTextMsg_HELP_MSG_V[] PROGMEM = "V=show interrupt Vectors";
+ const char gTextMsg_HELP_MSG_Y[] PROGMEM = "Y=Port blink";
+
+ const char gTextMsg_END[] PROGMEM = "*";
+
+
+//************************************************************************
+void PrintFromPROGMEM(const void *dataPtr, unsigned char offset)
+{
+char theChar;
+
+ dataPtr += offset;
+
+ do {
+ #if (FLASHEND > 0x10000)
+ theChar = pgm_read_byte_far((uint16_t)dataPtr++);
+ #else
+ theChar = pgm_read_byte_near((uint16_t)dataPtr++);
+ #endif
+ if (theChar != 0)
+ {
+ sendchar(theChar);
+ }
+ } while (theChar != 0);
+}
+
+//************************************************************************
+void PrintNewLine(void)
+{
+ sendchar(0x0d);
+ sendchar(0x0a);
+}
+
+
+//************************************************************************
+void PrintFromPROGMEMln(const void *dataPtr, unsigned char offset)
+{
+ PrintFromPROGMEM(dataPtr, offset);
+
+ PrintNewLine();
+}
+
+
+//************************************************************************
+void PrintString(char *textString)
+{
+char theChar;
+int ii;
+
+ theChar = 1;
+ ii = 0;
+ while (theChar != 0)
+ {
+ theChar = textString[ii];
+ if (theChar != 0)
+ {
+ sendchar(theChar);
+ }
+ ii++;
+ }
+}
+
+//************************************************************************
+void PrintHexByte(unsigned char theByte)
+{
+char theChar;
+
+ theChar = 0x30 + ((theByte >> 4) & 0x0f);
+ if (theChar > 0x39)
+ {
+ theChar += 7;
+ }
+ sendchar(theChar );
+
+ theChar = 0x30 + (theByte & 0x0f);
+ if (theChar > 0x39)
+ {
+ theChar += 7;
+ }
+ sendchar(theChar );
+}
+
+//************************************************************************
+void PrintDecInt(int theNumber, int digitCnt)
+{
+int theChar;
+int myNumber;
+
+ myNumber = theNumber;
+
+ if ((myNumber > 100) || (digitCnt >= 3))
+ {
+ theChar = 0x30 + myNumber / 100;
+ sendchar(theChar );
+ }
+
+ if ((myNumber > 10) || (digitCnt >= 2))
+ {
+ theChar = 0x30 + ((myNumber % 100) / 10 );
+ sendchar(theChar );
+ }
+ theChar = 0x30 + (myNumber % 10);
+ sendchar(theChar );
+}
+
+
+
+
+//************************************************************************
+static void PrintCPUstats(void)
+{
+unsigned char fuseByte;
+
+ PrintFromPROGMEMln(gTextMsg_Explorer, 0);
+
+ PrintFromPROGMEM(gTextMsg_COMPILED_ON, 0);
+ PrintFromPROGMEMln(gTextMsg_GCC_DATE_STR, 0);
+
+ PrintFromPROGMEM(gTextMsg_CPU_Type, 0);
+ PrintFromPROGMEMln(gTextMsg_CPU_Name, 0);
+
+ PrintFromPROGMEM(gTextMsg_AVR_ARCH, 0);
+ PrintDecInt(__AVR_ARCH__, 1);
+ PrintNewLine();
+
+ PrintFromPROGMEM(gTextMsg_GCC_VERSION, 0);
+ PrintFromPROGMEMln(gTextMsg_GCC_VERSION_STR, 0);
+
+ //* these can be found in avr/version.h
+ PrintFromPROGMEM(gTextMsg_AVR_LIBC, 0);
+ PrintFromPROGMEMln(gTextMsg_AVR_LIBC_VER_STR, 0);
+
+#if defined(SIGNATURE_0)
+ PrintFromPROGMEM(gTextMsg_CPU_SIGNATURE, 0);
+ //* these can be found in avr/iomxxx.h
+ PrintHexByte(SIGNATURE_0);
+ PrintHexByte(SIGNATURE_1);
+ PrintHexByte(SIGNATURE_2);
+ PrintNewLine();
+#endif
+
+
+#if defined(GET_LOW_FUSE_BITS)
+ //* fuse settings
+ PrintFromPROGMEM(gTextMsg_FUSE_BYTE_LOW, 0);
+ fuseByte = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
+ PrintHexByte(fuseByte);
+ PrintNewLine();
+
+ PrintFromPROGMEM(gTextMsg_FUSE_BYTE_HIGH, 0);
+ fuseByte = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
+ PrintHexByte(fuseByte);
+ PrintNewLine();
+
+ PrintFromPROGMEM(gTextMsg_FUSE_BYTE_EXT, 0);
+ fuseByte = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
+ PrintHexByte(fuseByte);
+ PrintNewLine();
+
+ PrintFromPROGMEM(gTextMsg_FUSE_BYTE_LOCK, 0);
+ fuseByte = boot_lock_fuse_bits_get(GET_LOCK_BITS);
+ PrintHexByte(fuseByte);
+ PrintNewLine();
+
+#endif
+
+}
+
+
+//************************************************************************
+static void BlinkLED(void)
+{
+ PROGLED_DDR |= (1< 0)
+ {
+ if (myAddressPointer > 0x10000)
+ {
+ PrintHexByte((myAddressPointer >> 16) & 0x00ff);
+ }
+ PrintHexByte((myAddressPointer >> 8) & 0x00ff);
+ PrintHexByte(myAddressPointer & 0x00ff);
+ sendchar(0x20);
+ sendchar('-');
+ sendchar(0x20);
+
+ asciiDump[0] = 0;
+ for (ii=0; ii<16; ii++)
+ {
+ switch(dumpWhat)
+ {
+ case kDUMP_FLASH:
+ #if (FLASHEND > 0x10000)
+ theValue = pgm_read_byte_far(myAddressPointer);
+ #else
+ theValue = pgm_read_byte_near(myAddressPointer);
+ #endif
+ break;
+
+ case kDUMP_EEPROM:
+ theValue = eeprom_read_byte((uint8_t *)(uint16_t)myAddressPointer);
+ break;
+
+ case kDUMP_RAM:
+ theValue = ramPtr[myAddressPointer];
+ break;
+
+ }
+ PrintHexByte(theValue);
+ sendchar(0x20);
+ if ((theValue >= 0x20) && (theValue < 0x7f))
+ {
+ asciiDump[ii % 16] = theValue;
+ }
+ else
+ {
+ asciiDump[ii % 16] = '.';
+ }
+
+ myAddressPointer++;
+ }
+ asciiDump[16] = 0;
+ PrintString(asciiDump);
+ PrintNewLine();
+
+ numRows--;
+ }
+}
+
+
+
+//************************************************************************
+//* returns amount of extended memory
+static void EEPROMtest(void)
+{
+int ii;
+char theChar;
+char theEEPROMchar;
+int errorCount;
+
+ PrintFromPROGMEMln(gTextMsg_WriteToEEprom, 0);
+ PrintNewLine();
+ ii = 0;
+#if (FLASHEND > 0x10000)
+ while (((theChar = pgm_read_byte_far(((uint16_t)gTextMsg_Explorer) + ii)) != '*') && (ii < 512))
+#else
+ while (((theChar = pgm_read_byte_near(((uint16_t)gTextMsg_Explorer) + ii)) != '*') && (ii < 512))
+#endif
+ {
+ eeprom_write_byte((uint8_t *)ii, theChar);
+ if (theChar == 0)
+ {
+ PrintFromPROGMEM(gTextMsg_SPACE, 0);
+ }
+ else
+ {
+ sendchar(theChar);
+ }
+ ii++;
+ }
+
+ //* no go back through and test
+ PrintNewLine();
+ PrintNewLine();
+ PrintFromPROGMEMln(gTextMsg_ReadingEEprom, 0);
+ PrintNewLine();
+ errorCount = 0;
+ ii = 0;
+#if (FLASHEND > 0x10000)
+ while (((theChar = pgm_read_byte_far((uint16_t)gTextMsg_Explorer + ii)) != '*') && (ii < 512))
+#else
+ while (((theChar = pgm_read_byte_near((uint16_t)gTextMsg_Explorer + ii)) != '*') && (ii < 512))
+#endif
+ {
+ theEEPROMchar = eeprom_read_byte((uint8_t *)ii);
+ if (theEEPROMchar == 0)
+ {
+ PrintFromPROGMEM(gTextMsg_SPACE, 0);
+ }
+ else
+ {
+ sendchar(theEEPROMchar);
+ }
+ if (theEEPROMchar != theChar)
+ {
+ errorCount++;
+ }
+ ii++;
+ }
+ PrintNewLine();
+ PrintNewLine();
+ PrintFromPROGMEM(gTextMsg_EEPROMerrorCnt, 0);
+ PrintDecInt(errorCount, 1);
+ PrintNewLine();
+ PrintNewLine();
+
+ gEepromIndex = 0; //* set index back to zero for next eeprom dump
+
+}
+
+
+
+#if (FLASHEND > 0x08000)
+//* this includes the interrupt names for the monitor portion. There is no longer enough
+//* memory to include this
+// #include "avrinterruptnames.h"
+// #ifndef _INTERRUPT_NAMES_DEFINED_
+// #warning Interrupt vectors not defined
+// #endif
+#endif
+
+//************************************************************************
+static void VectorDisplay(void)
+{
+unsigned long byte1;
+unsigned long byte2;
+unsigned long byte3;
+unsigned long byte4;
+unsigned long word1;
+unsigned long word2;
+int vectorIndex;
+unsigned long myMemoryPtr;
+unsigned long wordMemoryAddress;
+unsigned long realitiveAddr;
+unsigned long myFullAddress;
+unsigned long absoluteAddr;
+#if defined(_INTERRUPT_NAMES_DEFINED_)
+ long stringPointer;
+#endif
+
+ myMemoryPtr = 0;
+ vectorIndex = 0;
+ PrintFromPROGMEMln(gTextMsg_CPU_Name, 0);
+ PrintFromPROGMEMln(gTextMsg_VECTOR_HEADER, 0);
+ // V# ADDR op code
+ // 1 - 0000 = C3 BB 00 00 rjmp 03BB >000776 RESET
+ while (vectorIndex < kInterruptVectorCount)
+ {
+ wordMemoryAddress = myMemoryPtr / 2;
+ // 01 - 0000 = 12 34
+ PrintDecInt(vectorIndex + 1, 2);
+ sendchar(0x20);
+ sendchar('-');
+ sendchar(0x20);
+ PrintHexByte((wordMemoryAddress >> 8) & 0x00ff);
+ PrintHexByte((wordMemoryAddress) & 0x00ff);
+ sendchar(0x20);
+ sendchar('=');
+ sendchar(0x20);
+
+
+ //* the AVR is LITTLE ENDIAN, swap the byte order
+ #if (FLASHEND > 0x10000)
+ byte1 = pgm_read_byte_far(myMemoryPtr++);
+ byte2 = pgm_read_byte_far(myMemoryPtr++);
+ byte3 = pgm_read_byte_far(myMemoryPtr++);
+ byte4 = pgm_read_byte_far(myMemoryPtr++);
+ #else
+ byte1 = pgm_read_byte_near(myMemoryPtr++);
+ byte2 = pgm_read_byte_near(myMemoryPtr++);
+ byte3 = pgm_read_byte_near(myMemoryPtr++);
+ byte4 = pgm_read_byte_near(myMemoryPtr++);
+ #endif
+ word1 = (byte2 << 8) + byte1;
+ word2 = (byte4 << 8) + byte3;
+
+
+ PrintHexByte(byte2);
+ sendchar(0x20);
+ PrintHexByte(byte1);
+ sendchar(0x20);
+ PrintHexByte(byte4);
+ sendchar(0x20);
+ PrintHexByte(byte3);
+ sendchar(0x20);
+
+ if (word1 == 0xffff)
+ {
+ PrintFromPROGMEM(gTextMsg_noVector, 0);
+ }
+ else if ((word1 & 0xc000) == 0xc000)
+ {
+ //* rjmp instruction
+ realitiveAddr = word1 & 0x3FFF;
+ absoluteAddr = wordMemoryAddress + realitiveAddr; //* add the offset to the current address
+ absoluteAddr = absoluteAddr << 1; //* multiply by 2 for byte address
+
+ PrintFromPROGMEM(gTextMsg_rjmp, 0);
+ PrintHexByte((realitiveAddr >> 8) & 0x00ff);
+ PrintHexByte((realitiveAddr) & 0x00ff);
+ sendchar(0x20);
+ sendchar('>');
+ PrintHexByte((absoluteAddr >> 16) & 0x00ff);
+ PrintHexByte((absoluteAddr >> 8) & 0x00ff);
+ PrintHexByte((absoluteAddr) & 0x00ff);
+
+ }
+ else if ((word1 & 0xfE0E) == 0x940c)
+ {
+ //* jmp instruction, this is REALLY complicated, refer to the instruction manual (JMP)
+ myFullAddress = ((byte1 & 0x01) << 16) +
+ ((byte1 & 0xf0) << 17) +
+ ((byte2 & 0x01) << 21) +
+ word2;
+
+ absoluteAddr = myFullAddress << 1;
+
+ PrintFromPROGMEM(gTextMsg_jmp, 0);
+ PrintHexByte((myFullAddress >> 16) & 0x00ff);
+ PrintHexByte((myFullAddress >> 8) & 0x00ff);
+ PrintHexByte((myFullAddress) & 0x00ff);
+ sendchar(0x20);
+ sendchar('>');
+ PrintHexByte((absoluteAddr >> 16) & 0x00ff);
+ PrintHexByte((absoluteAddr >> 8) & 0x00ff);
+ PrintHexByte((absoluteAddr) & 0x00ff);
+ }
+
+ #if defined(_INTERRUPT_NAMES_DEFINED_)
+ sendchar(0x20);
+ #if (FLASHEND > 0x10000)
+ stringPointer = pgm_read_word_far(&(gInterruptNameTable[vectorIndex]));
+ #else
+ stringPointer = pgm_read_word_near(&(gInterruptNameTable[vectorIndex]));
+ #endif
+ PrintFromPROGMEM((char *)stringPointer, 0);
+ #endif
+ PrintNewLine();
+
+ vectorIndex++;
+ }
+}
+
+//************************************************************************
+static void PrintAvailablePort(char thePortLetter)
+{
+ PrintFromPROGMEM(gTextMsg_PORT, 0);
+ sendchar(thePortLetter);
+ PrintNewLine();
+}
+
+//************************************************************************
+static void ListAvailablePorts(void)
+{
+
+#ifdef DDRA
+ PrintAvailablePort('A');
+#endif
+
+#ifdef DDRB
+ PrintAvailablePort('B');
+#endif
+
+#ifdef DDRC
+ PrintAvailablePort('C');
+#endif
+
+#ifdef DDRD
+ PrintAvailablePort('D');
+#endif
+
+#ifdef DDRE
+ PrintAvailablePort('E');
+#endif
+
+#ifdef DDRF
+ PrintAvailablePort('F');
+#endif
+
+#ifdef DDRG
+ PrintAvailablePort('G');
+#endif
+
+#ifdef DDRH
+ PrintAvailablePort('H');
+#endif
+
+#ifdef DDRI
+ PrintAvailablePort('I');
+#endif
+
+#ifdef DDRJ
+ PrintAvailablePort('J');
+#endif
+
+#ifdef DDRK
+ PrintAvailablePort('K');
+#endif
+
+#ifdef DDRL
+ PrintAvailablePort('L');
+#endif
+
+}
+
+//************************************************************************
+static void AVR_PortOutput(void)
+{
+char portLetter;
+char getCharFlag;
+
+ PrintFromPROGMEM(gTextMsg_WHAT_PORT, 0);
+
+ portLetter = recchar();
+ portLetter = portLetter & 0x5f;
+ sendchar(portLetter);
+ PrintNewLine();
+
+ if ((portLetter >= 'A') && (portLetter <= 'Z'))
+ {
+ getCharFlag = true;
+ switch(portLetter)
+ {
+ #ifdef DDRA
+ case 'A':
+ DDRA = 0xff;
+ while (!Serial_Available())
+ {
+ PORTA ^= 0xff;
+ delay_ms(200);
+ }
+ PORTA = 0;
+ break;
+ #endif
+
+ #ifdef DDRB
+ case 'B':
+ DDRB = 0xff;
+ while (!Serial_Available())
+ {
+ PORTB ^= 0xff;
+ delay_ms(200);
+ }
+ PORTB = 0;
+ break;
+ #endif
+
+ #ifdef DDRC
+ case 'C':
+ DDRC = 0xff;
+ while (!Serial_Available())
+ {
+ PORTC ^= 0xff;
+ delay_ms(200);
+ }
+ PORTC = 0;
+ break;
+ #endif
+
+ #ifdef DDRD
+ case 'D':
+ DDRD = 0xff;
+ while (!Serial_Available())
+ {
+ PORTD ^= 0xff;
+ delay_ms(200);
+ }
+ PORTD = 0;
+ break;
+ #endif
+
+ #ifdef DDRE
+ case 'E':
+ DDRE = 0xff;
+ while (!Serial_Available())
+ {
+ PORTE ^= 0xff;
+ delay_ms(200);
+ }
+ PORTE = 0;
+ break;
+ #endif
+
+ #ifdef DDRF
+ case 'F':
+ DDRF = 0xff;
+ while (!Serial_Available())
+ {
+ PORTF ^= 0xff;
+ delay_ms(200);
+ }
+ PORTF = 0;
+ break;
+ #endif
+
+ #ifdef DDRG
+ case 'G':
+ DDRG = 0xff;
+ while (!Serial_Available())
+ {
+ PORTG ^= 0xff;
+ delay_ms(200);
+ }
+ PORTG = 0;
+ break;
+ #endif
+
+ #ifdef DDRH
+ case 'H':
+ DDRH = 0xff;
+ while (!Serial_Available())
+ {
+ PORTH ^= 0xff;
+ delay_ms(200);
+ }
+ PORTH = 0;
+ break;
+ #endif
+
+ #ifdef DDRI
+ case 'I':
+ DDRI = 0xff;
+ while (!Serial_Available())
+ {
+ PORTI ^= 0xff;
+ delay_ms(200);
+ }
+ PORTI = 0;
+ break;
+ #endif
+
+ #ifdef DDRJ
+ case 'J':
+ DDRJ = 0xff;
+ while (!Serial_Available())
+ {
+ PORTJ ^= 0xff;
+ delay_ms(200);
+ }
+ PORTJ = 0;
+ break;
+ #endif
+
+ #ifdef DDRK
+ case 'K':
+ DDRK = 0xff;
+ while (!Serial_Available())
+ {
+ PORTK ^= 0xff;
+ delay_ms(200);
+ }
+ PORTK = 0;
+ break;
+ #endif
+
+ #ifdef DDRL
+ case 'L':
+ DDRL = 0xff;
+ while (!Serial_Available())
+ {
+ PORTL ^= 0xff;
+ delay_ms(200);
+ }
+ PORTL = 0;
+ break;
+ #endif
+
+ default:
+ PrintFromPROGMEMln(gTextMsg_PortNotSupported, 0);
+ getCharFlag = false;
+ break;
+ }
+ if (getCharFlag)
+ {
+ recchar();
+ }
+ }
+ else
+ {
+ PrintFromPROGMEMln(gTextMsg_MustBeLetter, 0);
+ }
+}
+
+
+//*******************************************************************
+static void PrintHelp(void)
+{
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_0, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_QM, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_AT, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_B, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_E, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_F, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_H, 0);
+
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_L, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_Q, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_R, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_V, 0);
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_Y, 0);
+}
+
+//************************************************************************
+static void RunMonitor(void)
+{
+char keepGoing;
+unsigned char theChar;
+int ii, jj;
+
+ for (ii=0; ii<5; ii++)
+ {
+ for (jj=0; jj<25; jj++)
+ {
+ sendchar('!');
+ }
+ PrintNewLine();
+ }
+
+ gRamIndex = 0;
+ gFlashIndex = 0;
+ gEepromIndex = 0;
+
+ PrintFromPROGMEMln(gTextMsg_Explorer, 0);
+
+ keepGoing = 1;
+ while (keepGoing)
+ {
+ PrintFromPROGMEM(gTextMsg_Prompt, 0);
+ theChar = recchar();
+ if (theChar >= 0x60)
+ {
+ theChar = theChar & 0x5F;
+ }
+
+ if (theChar >= 0x20)
+ {
+ sendchar(theChar);
+ sendchar(0x20);
+ }
+
+ switch(theChar)
+ {
+ case '0':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_0, 2);
+ gFlashIndex = 0;
+ gRamIndex = 0;
+ gEepromIndex = 0;
+ break;
+
+ case '?':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_QM, 2);
+ PrintCPUstats();
+ break;
+
+ case '@':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_AT, 2);
+ EEPROMtest();
+ break;
+
+ case 'B':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_B, 2);
+ BlinkLED();
+ break;
+
+ case 'E':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_E, 2);
+ DumpHex(kDUMP_EEPROM, gEepromIndex, 16);
+ gEepromIndex += 256;
+ if (gEepromIndex > E2END)
+ {
+ gEepromIndex = 0;
+ }
+ break;
+
+ case 'F':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_F, 2);
+ DumpHex(kDUMP_FLASH, gFlashIndex, 16);
+ gFlashIndex += 256;
+ break;
+
+ case 'H':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_H, 2);
+ PrintHelp();
+ break;
+
+ case 'L':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_L, 2);
+ ListAvailablePorts();
+ break;
+
+ case 'Q':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_Q, 2);
+ keepGoing = false;
+ break;
+
+ case 'R':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_R, 2);
+ DumpHex(kDUMP_RAM, gRamIndex, 16);
+ gRamIndex += 256;
+ break;
+
+ case 'V':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_V, 2);
+ VectorDisplay();
+ break;
+
+ case 'Y':
+ PrintFromPROGMEMln(gTextMsg_HELP_MSG_Y, 2);
+ AVR_PortOutput();
+ break;
+
+ default:
+ PrintFromPROGMEMln(gTextMsg_HUH, 0);
+ break;
+ }
+ }
+}
+
+#endif
+
diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp
index f3f3499b4..704953283 100644
--- a/radio/src/targets/simu/simpgmspace.cpp
+++ b/radio/src/targets/simu/simpgmspace.cpp
@@ -795,10 +795,12 @@ char *findTrueFileName(const char *path)
strcat(result, res->d_name);
TRACE("\tfound: %s", res->d_name);
fileMap.insert(filemap_t:: value_type(path, result));
+ simu::closedir(dir);
return result;
}
}
}
+ simu::closedir(dir);
}
#endif
}
@@ -840,10 +842,10 @@ FRESULT f_open (FIL * fil, const TCHAR *name, BYTE flag)
fil->fsize = tmp.st_size;
fil->fptr = 0;
}
- fil->fs = (FATFS*)fopen(realPath, (flag & FA_WRITE) ? "wb+" : "rb+");
+ fil->fs = (FATFS*)fopen(realPath, (flag & FA_WRITE) ? ((flag & FA_CREATE_ALWAYS) ? "wb+" : "ab+") : "rb+");
fil->fptr = 0;
if (fil->fs) {
- TRACE("f_open(%s) = %p", path, (FILE*)fil->fs);
+ TRACE("f_open(%s, %x) = %p", path, flag, (FILE*)fil->fs);
return FR_OK;
}
TRACE("f_open(%s) = error %d (%s)", path, errno, strerror(errno));
@@ -877,6 +879,19 @@ FRESULT f_lseek (FIL* fil, DWORD offset)
return FR_OK;
}
+UINT f_size(FIL* fil)
+{
+ if (fil && fil->fs) {
+ long curr = ftell((FILE*)fil->fs);
+ fseek((FILE*)fil->fs, 0, SEEK_END);
+ long size = ftell((FILE*)fil->fs);
+ fseek((FILE*)fil->fs, curr, SEEK_SET);
+ TRACE("f_size(%p) %u", fil->fs, size);
+ return size;
+ }
+ return 0;
+}
+
FRESULT f_close (FIL * fil)
{
if (fil && fil->fs) {
diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp
index 7fdad03e4..eeb9513a3 100644
--- a/radio/src/telemetry/telemetry.cpp
+++ b/radio/src/telemetry/telemetry.cpp
@@ -366,10 +366,7 @@ void TelemetryItem::eval(const TelemetrySensor & sensor)
result += dist*dist;
if (altItem) {
- dist = abs(altItem->value);
- uint8_t prec = g_model.telemetrySensors[sensor.dist.alt-1].prec;
- if (prec > 0)
- dist /= (prec==2 ? 100 : 10);
+ dist = abs(altItem->value) / g_model.telemetrySensors[sensor.dist.alt-1].getPrecDivisor();
result += dist*dist;
}
@@ -545,49 +542,56 @@ void TelemetrySensor::init(uint16_t id)
init(label);
}
-bool TelemetrySensor::isAvailable()
+bool TelemetrySensor::isAvailable() const
{
return ZLEN(label) > 0;
}
+PACK(typedef struct {
+ uint8_t unitFrom;
+ uint8_t unitTo;
+ int16_t multiplier;
+ int16_t divisor;
+}) UnitConversionRule;
+
+const UnitConversionRule unitConversionTable[] = {
+ /* unitFrom unitTo multiplier divisor */
+ { UNIT_METERS, UNIT_FEET, 105, 32},
+ { UNIT_METERS_PER_SECOND, UNIT_FEET_PER_SECOND, 105, 32},
+
+ { UNIT_KTS, UNIT_KMH, 1852, 1000}, // 1 knot = 1.85200 kilometers per hour
+ { UNIT_KTS, UNIT_MPH, 1151, 1000}, // 1 knot = 1.15077945 miles per hour
+ { UNIT_KTS, UNIT_METERS_PER_SECOND, 1000, 1944}, // 1 knot = 0.514444444 meters / second (divide with 1.94384449)
+ { UNIT_KTS, UNIT_FEET_PER_SECOND, 1688, 1000}, // 1 knot = 1.68780986 feet per second
+
+ { UNIT_KMH, UNIT_KTS, 1000, 1852}, // 1 km/h = 0.539956803 knots (divide with 1.85200)
+ { UNIT_KMH, UNIT_MPH, 1000, 1609}, // 1 km/h = 0.621371192 miles per hour (divide with 1.60934400)
+ { UNIT_KMH, UNIT_METERS_PER_SECOND, 10, 36}, // 1 km/h = 0.277777778 meters / second (divide with 3.6)
+ { UNIT_KMH, UNIT_FEET_PER_SECOND, 911, 1000}, // 1 km/h = 0.911344415 feet per second
+
+ { UNIT_MILLILITERS, UNIT_FLOZ, 100, 2957},
+ { 0, 0, 0, 0} // termination
+};
+
int32_t convertTelemetryValue(int32_t value, uint8_t unit, uint8_t prec, uint8_t destUnit, uint8_t destPrec)
{
for (int i=prec; idivisor) {
+ if (p->unitFrom == unit && p->unitTo == destUnit) {
+ value = (value * (int32_t)p->multiplier) / (int32_t)p->divisor;
+ break;
+ }
+ ++p;
}
}
@@ -622,7 +626,7 @@ int32_t TelemetrySensor::getValue(int32_t value, uint8_t unit, uint8_t prec) con
return value;
}
-bool TelemetrySensor::isConfigurable()
+bool TelemetrySensor::isConfigurable() const
{
if (type == TELEM_TYPE_CALCULATED) {
if (formula >= TELEM_FORMULA_CELL) {
@@ -637,7 +641,7 @@ bool TelemetrySensor::isConfigurable()
return true;
}
-bool TelemetrySensor::isPrecConfigurable()
+bool TelemetrySensor::isPrecConfigurable() const
{
if (isConfigurable()) {
return true;
@@ -649,3 +653,21 @@ bool TelemetrySensor::isPrecConfigurable()
return false;
}
}
+
+int32_t TelemetrySensor::getPrecMultiplier() const
+{
+ /*
+ Important: the return type must be signed, otherwise
+ mathematic operations with a negative telemetry value won't work
+ */
+ if (prec == 2) return 1;
+ if (prec == 1) return 10;
+ return 100;
+}
+
+int32_t TelemetrySensor::getPrecDivisor() const
+{
+ if (prec == 2) return 100;
+ if (prec == 1) return 10;
+ return 1;
+}
diff --git a/radio/src/tests/lua.cpp b/radio/src/tests/lua.cpp
index f1f89ab40..906a9acf0 100644
--- a/radio/src/tests/lua.cpp
+++ b/radio/src/tests/lua.cpp
@@ -42,10 +42,6 @@
#define SWAP_DEFINED
#include "opentx.h"
-#include
-#include
-#include
-
extern const char * zchar2string(const char * zstring, int size);
#define EXPECT_ZSTREQ(c_string, z_string) EXPECT_STREQ(c_string, zchar2string(z_string, sizeof(z_string)))
extern void luaInit();
diff --git a/radio/src/thirdparty/FatFs/ff.h b/radio/src/thirdparty/FatFs/ff.h
index 88a0fbaa1..1f50e4867 100644
--- a/radio/src/thirdparty/FatFs/ff.h
+++ b/radio/src/thirdparty/FatFs/ff.h
@@ -238,7 +238,11 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
#define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
-#define f_size(fp) ((fp)->fsize)
+#if !defined(SIMU)
+ #define f_size(fp) ((fp)->fsize)
+#else
+ UINT f_size(FIL* fil);
+#endif
#ifndef EOF
#define EOF (-1)
diff --git a/radio/src/thirdparty/Lua/src/liolib.c b/radio/src/thirdparty/Lua/src/liolib.c
index 3946e7e6d..d5476d298 100644
--- a/radio/src/thirdparty/Lua/src/liolib.c
+++ b/radio/src/thirdparty/Lua/src/liolib.c
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#define liolib_c
@@ -183,14 +184,10 @@ static LStream *newprefile (lua_State *L) {
#if !defined(USE_FATFS)
static int aux_close (lua_State *L) {
-#if !defined(USE_FATFS)
LStream *p = tolstream(L);
lua_CFunction cf = p->closef;
p->closef = NULL; /* mark stream as closed */
return (*cf)(L); /* close it */
-#else
- return 0;
-#endif
}
#endif
@@ -249,14 +246,14 @@ static int io_open (lua_State *L) {
const char *md = luaL_optstring(L, 2, "r");
LStream *p = newfile(L);
#if defined(USE_FATFS)
- BYTE mode;
- if (strchr(md, 'w') || strchr(md, 'a'))
- mode = FA_WRITE;
- else
- mode = FA_READ;
+ BYTE mode = FA_READ;
+ if (*md == 'w')
+ mode = FA_WRITE | FA_CREATE_ALWAYS; // always create file and truncate it
+ else if (*md == 'a')
+ mode = FA_WRITE | FA_OPEN_ALWAYS; // always open file (create it if necessary)
FRESULT result = f_open(&p->f, filename, mode);
- if (result == FR_OK && strchr(md, 'a'))
- result = f_lseek(&p->f, f_size(&p->f));
+ if (result == FR_OK && *md == 'a')
+ result = f_lseek(&p->f, f_size(&p->f)); // seek to the end of the file
return result == FR_OK ? 1 : 0;
#else
const char *mode = md; /* to traverse/check mode */
@@ -559,8 +556,9 @@ static int g_write (lua_State *L, FILE *f, int arg) {
for (; nargs--; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) {
/* optimization: could be done exactly as for strings */
- status = status &&
- f_printf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ char s[LUAI_MAXNUMBER2STR];
+ sprintf(s, LUA_NUMBER_FMT, lua_tonumber(L, arg));
+ status = status && f_puts(s, f) > 0;
}
else {
size_t l;
diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt
index bb1a20ff2..9aeeb0dab 100644
--- a/radio/src/translations/cz.h.txt
+++ b/radio/src/translations/cz.h.txt
@@ -391,7 +391,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
+ #define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt
index b928e15c4..06e6adfd0 100644
--- a/radio/src/translations/en.h.txt
+++ b/radio/src/translations/en.h.txt
@@ -395,7 +395,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
+ #define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt
index e187fc233..53137e75b 100644
--- a/radio/src/translations/es.h.txt
+++ b/radio/src/translations/es.h.txt
@@ -389,7 +389,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
+ #define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt
index b4029f9a8..5cc4de5ed 100644
--- a/radio/src/translations/fi.h.txt
+++ b/radio/src/translations/fi.h.txt
@@ -389,7 +389,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
+ #define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt
index b6216fe9a..5d1e28580 100644
--- a/radio/src/translations/fr.h.txt
+++ b/radio/src/translations/fr.h.txt
@@ -393,7 +393,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
+ #define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt
index 3a2c9585a..205aab898 100644
--- a/radio/src/translations/it.h.txt
+++ b/radio/src/translations/it.h.txt
@@ -396,7 +396,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
+ #define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
@@ -849,10 +849,10 @@
#define TR_NO_MODELS_ON_SD "No Model. su SD"
#define TR_NO_BITMAPS_ON_SD "No Immag. su SD"
#define TR_NO_SCRIPTS_ON_SD "No Scripts su SD"
-#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error"
-#define TR_SCRIPT_PANIC "Script panic"
-#define TR_SCRIPT_KILLED "Script killed"
-#define TR_SCRIPT_ERROR "Unknown error"
+#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error"
+#define TR_SCRIPT_PANIC "Script panic"
+#define TR_SCRIPT_KILLED "Script killed"
+#define TR_SCRIPT_ERROR "Unknown error"
#define TR_PLAY_FILE "Suona"
#define TR_DELETE_FILE "Elimina"
#define TR_COPY_FILE "Copia"
@@ -1115,7 +1115,7 @@
#define ZSTR_A4 "A4"
#define ZSTR_BATT "RxBt"
#define ZSTR_ALT "Alt"
-#define ZSTR_TEMP1 "Tmp1"
+#define ZSTR_TEMP1 "Tmp1"
#define ZSTR_TEMP2 "Tmp2"
#define ZSTR_RPM "RPM"
#define ZSTR_FUEL "Fuel"
diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt
index 1e62a463b..4fab82065 100644
--- a/radio/src/translations/pl.h.txt
+++ b/radio/src/translations/pl.h.txt
@@ -397,7 +397,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
+ #define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt
index 580c1a7cf..5d00d28ee 100644
--- a/radio/src/translations/pt.h.txt
+++ b/radio/src/translations/pt.h.txt
@@ -389,7 +389,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
+ #define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
@@ -801,10 +801,10 @@
#define TR_NO_MODELS_ON_SD "Sem Modelo no SD"
#define TR_NO_BITMAPS_ON_SD "No Bitmaps on SD"
#define TR_NO_SCRIPTS_ON_SD "No Scripts on SD"
-#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error"
-#define TR_SCRIPT_PANIC "Script panic"
-#define TR_SCRIPT_KILLED "Script killed"
-#define TR_SCRIPT_ERROR "Unknown error"
+#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error"
+#define TR_SCRIPT_PANIC "Script panic"
+#define TR_SCRIPT_KILLED "Script killed"
+#define TR_SCRIPT_ERROR "Unknown error"
#define TR_PLAY_FILE "Play"
#define TR_DELETE_FILE "Apagar"
#define TR_COPY_FILE "Copiar"
@@ -902,10 +902,10 @@
#define TR_SMOOTH "Smooth"
#define TR_COPY_STICKS_TO_OFS "Copy Sticks To Offset"
#define TR_COPY_TRIMS_TO_OFS "Copy trims to subtrim"
-#define TR_INCDEC "Inc/Decrement"
-#define TR_GLOBALVAR "Global Var"
-#define TR_MIXSOURCE "Mixer Source"
-#define TR_CONSTANT "Constant"
+#define TR_INCDEC "Inc/Decrement"
+#define TR_GLOBALVAR "Global Var"
+#define TR_MIXSOURCE "Mixer Source"
+#define TR_CONSTANT "Constant"
#define TR_PERSISTENT_MAH INDENT "Store mAh"
#define TR_PREFLIGHT "Preflight Checks"
#define TR_CHECKLIST INDENT "Display Checklist"
@@ -1041,7 +1041,7 @@
#define TR_DISCOVER_SENSORS INDENT "Discover new sensors"
#define TR_STOP_DISCOVER_SENSORS INDENT "Stop discovery"
#define TR_DELETE_ALL_SENSORS INDENT "Delete all sensors"
-#define TR_CONFIRMDELETE "Really delete all?"
+#define TR_CONFIRMDELETE "Really delete all?"
#define TR_MENU_INPUTS "\314Inputs"
#define TR_MENU_LUA "\322Lua scripts"
@@ -1067,7 +1067,7 @@
#define ZSTR_A4 "A4"
#define ZSTR_BATT "RxBt"
#define ZSTR_ALT "Alt"
-#define ZSTR_TEMP1 "Tmp1"
+#define ZSTR_TEMP1 "Tmp1"
#define ZSTR_TEMP2 "Tmp2"
#define ZSTR_RPM "RPM"
#define ZSTR_FUEL "Fuel"
diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt
index a9f81138b..b09c9f530 100644
--- a/radio/src/translations/se.h.txt
+++ b/radio/src/translations/se.h.txt
@@ -389,7 +389,7 @@
#define SPEED_UNIT SPEED_UNIT_METR
#endif
#define LEN_VTELEMUNIT "\003"
- #define TR_VTELEMUNIT "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
+ #define TR_VTELEMUNIT "V\0 ""A\0 ""m/s""-\0 " SPEED_UNIT LENGTH_UNIT "@\0 ""%\0 ""mA\0""mAh""W\0 "
#endif
#define STR_V (STR_VTELEMUNIT+1)
@@ -801,10 +801,10 @@
#define TR_NO_MODELS_ON_SD "Ingen modell i SD"
#define TR_NO_BITMAPS_ON_SD "Ikoner saknas på SD"
#define TR_NO_SCRIPTS_ON_SD "Programkod saknas på SD"
-#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error"
-#define TR_SCRIPT_PANIC "Script panic"
-#define TR_SCRIPT_KILLED "Script killed"
-#define TR_SCRIPT_ERROR "Unknown error"
+#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error"
+#define TR_SCRIPT_PANIC "Script panic"
+#define TR_SCRIPT_KILLED "Script killed"
+#define TR_SCRIPT_ERROR "Unknown error"
#define TR_PLAY_FILE "Spela"
#define TR_DELETE_FILE "Radera"
#define TR_COPY_FILE "Kopia"
@@ -902,10 +902,10 @@
#define TR_SMOOTH "Mjuk"
#define TR_COPY_STICKS_TO_OFS "Spara spakar som offset"
#define TR_COPY_TRIMS_TO_OFS "Spara trimmar som offset"
-#define TR_INCDEC "Inc/Decrement"
-#define TR_GLOBALVAR "Global Var"
-#define TR_MIXSOURCE "Mixer Source"
-#define TR_CONSTANT "Constant"
+#define TR_INCDEC "Inc/Decrement"
+#define TR_GLOBALVAR "Global Var"
+#define TR_MIXSOURCE "Mixer Source"
+#define TR_CONSTANT "Constant"
#define TR_PERSISTENT_MAH INDENT "Lagra mAh"
#define TR_PREFLIGHT "Startkontroller"
#define TR_CHECKLIST TR(INDENT "Checklista", INDENT "Visa Checklista")
@@ -1041,7 +1041,7 @@
#define TR_DISCOVER_SENSORS INDENT "Discover new sensors"
#define TR_STOP_DISCOVER_SENSORS INDENT "Stop discovery"
#define TR_DELETE_ALL_SENSORS INDENT "Delete all sensors"
-#define TR_CONFIRMDELETE "Really delete all?"
+#define TR_CONFIRMDELETE "Really delete all?"
#define TR_MENU_INPUTS "\314Inputs"
#define TR_MENU_LUA "\322Lua scripts"
@@ -1067,7 +1067,7 @@
#define ZSTR_A4 "A4"
#define ZSTR_BATT "RxBt"
#define ZSTR_ALT "Alt"
-#define ZSTR_TEMP1 "Tmp1"
+#define ZSTR_TEMP1 "Tmp1"
#define ZSTR_TEMP2 "Tmp2"
#define ZSTR_RPM "RPM"
#define ZSTR_FUEL "Fuel"
diff --git a/radio/src/vario.cpp b/radio/src/vario.cpp
index 4d5d362e4..c410b2a5a 100644
--- a/radio/src/vario.cpp
+++ b/radio/src/vario.cpp
@@ -47,10 +47,10 @@ void varioWakeup()
int verticalSpeed = 0;
if (g_model.frsky.varioSource) {
- TelemetryItem & varioItem = telemetryItems[g_model.frsky.varioSource-1];
- verticalSpeed = varioItem.value;
- TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.varioSource-1];
- if (sensor.prec != 2) verticalSpeed *= sensor.prec == 0 ? 100 : 10;
+ uint8_t item = g_model.frsky.varioSource-1;
+ if (item < MAX_SENSORS) {
+ verticalSpeed = telemetryItems[item].value * g_model.telemetrySensors[item].getPrecMultiplier();
+ }
}
int varioCenterMin = (int)g_model.frsky.varioCenterMin * 10 - 50;
diff --git a/radio/util/sport-parse.py b/radio/util/sport-parse.py
index 1a455587a..58c041de5 100755
--- a/radio/util/sport-parse.py
+++ b/radio/util/sport-parse.py
@@ -51,12 +51,17 @@ def ParseSWR(packet, dataId, prim, appId, data, crc):
print "packet: %s (%4d)" % (dump(packet), lineNumber) ,
print " SWR: %d" % (data & 0xFF)
+def ParseAirSpeed(packet, dataId, prim, appId, data, crc):
+ print "packet: %s (%4d)" % (dump(packet), lineNumber) ,
+ print " Aspd: %.1f km/h" % (data/10.0)
+
appIdParsers = (
(0x0300, 0x030f, ParseFlVSS),
(0xf101, 0xf101, ParseRSSI),
(0xf102, 0xf103, ParseAdc),
(0xf104, 0xf104, ParseBatt),
(0xf105, 0xf105, ParseSWR),
+ (0x0a00, 0x0a0f, ParseAirSpeed),
)
def dump(data, maxLen = None):