mirror of
https://github.com/EdgeTX/edgetx.git
synced 2025-07-23 16:25:12 +03:00
Merge remote-tracking branch 'origin/next' into Horus
# Conflicts: # companion/src/CMakeLists.txt # companion/src/firmwares/opentx/opentxinterface.cpp # companion/src/firmwares/opentx/simulator/CMakeLists.txt # companion/src/firmwares/opentx/stamp-opentx.h.in # radio/src/Makefile # radio/src/cli.cpp # radio/src/gui/Taranis/helpers.cpp # radio/src/gui/Taranis/lcd.cpp # radio/src/gui/Taranis/menu_model_setup.cpp # radio/src/gui/Taranis/view_main.cpp # radio/src/lua_api.cpp # radio/src/main_avr.cpp # radio/src/myeeprom.h # radio/src/opentx.cpp # radio/src/pulses/pxx_arm.cpp # radio/src/storage/eeprom_conversions.cpp # radio/src/targets/Horus/adc_driver.cpp # radio/src/targets/Horus/board_horus.cpp # radio/src/targets/Horus/board_horus.h # radio/src/targets/Horus/diskio.cpp # radio/src/targets/Horus/hal.h # radio/src/targets/Horus/haptic_driver.cpp # radio/src/targets/Horus/i2c_driver.cpp # radio/src/targets/Horus/keys_driver.cpp # radio/src/targets/Horus/lcd_driver.cpp # radio/src/targets/Horus/led_driver.cpp # radio/src/targets/Horus/pulses_driver.cpp # radio/src/targets/Horus/pwr_driver.c # radio/src/targets/Horus/sdio_sd.c # radio/src/targets/Horus/sdio_sd.h # radio/src/targets/Horus/serial2_driver.cpp # radio/src/targets/Horus/telemetry_driver.cpp # radio/src/targets/Horus/usb_conf.h # radio/src/targets/Horus/usbd_desc.c # radio/src/targets/Horus/usbd_storage_msd.cpp
This commit is contained in:
commit
de733579d5
85 changed files with 7038 additions and 3664 deletions
|
@ -26,7 +26,6 @@ Chris Guy
|
||||||
Adrien Gravouille
|
Adrien Gravouille
|
||||||
Thomas Black
|
Thomas Black
|
||||||
Marc Lucht
|
Marc Lucht
|
||||||
Michel Baily
|
|
||||||
Zdenek Trojanek
|
Zdenek Trojanek
|
||||||
Martin Hotar
|
Martin Hotar
|
||||||
Stefan Grundevik
|
Stefan Grundevik
|
||||||
|
@ -113,7 +112,6 @@ Erhard Werner
|
||||||
Stig Jøran Moen
|
Stig Jøran Moen
|
||||||
Keith Hertzog
|
Keith Hertzog
|
||||||
Christophe Dauvergne
|
Christophe Dauvergne
|
||||||
Michel Baily
|
|
||||||
Tauno Rautakorpi
|
Tauno Rautakorpi
|
||||||
Sven Assmus
|
Sven Assmus
|
||||||
Paul Dittman
|
Paul Dittman
|
||||||
|
@ -417,7 +415,6 @@ Andrea Montefusco
|
||||||
Paul Luby
|
Paul Luby
|
||||||
Donald L Webster
|
Donald L Webster
|
||||||
Kenneth Frehafer
|
Kenneth Frehafer
|
||||||
Peter McHenry
|
|
||||||
Matthias Hase
|
Matthias Hase
|
||||||
Markus Wolf
|
Markus Wolf
|
||||||
Andrew Fazio
|
Andrew Fazio
|
||||||
|
@ -588,7 +585,6 @@ Dietmar Drees
|
||||||
Jürgen Monden
|
Jürgen Monden
|
||||||
David Morgan
|
David Morgan
|
||||||
Andrew Fernie
|
Andrew Fernie
|
||||||
Michel Baily
|
|
||||||
Donald Burke
|
Donald Burke
|
||||||
Ronald Donker
|
Ronald Donker
|
||||||
Fredie Singh
|
Fredie Singh
|
||||||
|
@ -837,3 +833,20 @@ Jay Warren
|
||||||
Marian Matej
|
Marian Matej
|
||||||
Alastair Smith
|
Alastair Smith
|
||||||
Timothy Senecal
|
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
|
||||||
|
|
|
@ -1,4 +1,14 @@
|
||||||
<h2>Version 2.1.4 / <set date></h2>
|
<h2>Version 2.1.6 / 2015-11-11</h2>
|
||||||
|
[Taranis]
|
||||||
|
<ul>
|
||||||
|
<li>Telemetry custom screen changes didn't emit modified signal (<a href=https://github.com/opentx/opentx/issues/3029>#3029</a>)</li>
|
||||||
|
<li>Hide D8/LR12 when eu firmware option is selected</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Version 2.1.5 / 2015-11-05</h2>
|
||||||
|
|
||||||
|
Notice: version 2.1.4 was skipped by the OpenTX team to avoid confusion with FrSky's release of OpenTX 2.1.4
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Fixed: changing any setting on the telemetry panel does not set the file as being modified (<a href=https://github.com/opentx/opentx/issues/2875>#2875</a>)</li>
|
<li>Fixed: changing any setting on the telemetry panel does not set the file as being modified (<a href=https://github.com/opentx/opentx/issues/2875>#2875</a>)</li>
|
||||||
|
@ -11,10 +21,17 @@
|
||||||
<li>Fixed wrong import of Logical switches from OpenTX 2.0.x version (<a href=https://github.com/opentx/opentx/issues/2942>#2942</a>)</li>
|
<li>Fixed wrong import of Logical switches from OpenTX 2.0.x version (<a href=https://github.com/opentx/opentx/issues/2942>#2942</a>)</li>
|
||||||
<li>Fixed a problem with updates path on Windows (<a href=https://github.com/opentx/opentx/issues/2876>#2876</a>)</li>
|
<li>Fixed a problem with updates path on Windows (<a href=https://github.com/opentx/opentx/issues/2876>#2876</a>)</li>
|
||||||
<li>Edge representation unified (changed from "no release" to "instant") (<a href=https://github.com/opentx/opentx/issues/2837>#2837</a>)</li>
|
<li>Edge representation unified (changed from "no release" to "instant") (<a href=https://github.com/opentx/opentx/issues/2837>#2837</a>)</li>
|
||||||
|
<li>Added channel names on failsafe sliders (<a href=https://github.com/opentx/opentx/issues/3021>#3021</a>)</li>
|
||||||
|
<li>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 (<a href=https://github.com/opentx/opentx/issues/2975>#2975</a>)</li>
|
||||||
|
<li>Various texts and translations corrections</li>
|
||||||
|
<li>Various small bug-fixes: <a href=https://github.com/opentx/opentx/issues/2994>#2994</a>,
|
||||||
|
<a href=https://github.com/opentx/opentx/issues/3016>#3016</a>,
|
||||||
|
<a href=https://github.com/opentx/opentx/issues/3012>#3012</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2>Version 2.1.3 / 2015-09-09</h2>
|
<h2>Version 2.1.3 / 2015-09-09</h2>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -103,6 +103,11 @@ ELSE( )
|
||||||
LINK_DIRECTORIES( /usr/local/lib )
|
LINK_DIRECTORIES( /usr/local/lib )
|
||||||
ENDIF( )
|
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(RADIO_SRC_DIRECTORY ${PROJECT_SOURCE_DIR}/../../radio/src)
|
||||||
set(SIMU_SRC_DIRECTORY ${PROJECT_SOURCE_DIR}/simulation)
|
set(SIMU_SRC_DIRECTORY ${PROJECT_SOURCE_DIR}/simulation)
|
||||||
set(COMPANION_SRC_DIRECTORY ${PROJECT_SOURCE_DIR})
|
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}/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}/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}/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)
|
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_NAME "companion${C9X_NAME_SUFFIX}")
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Models and settings editor for the OpenTx open source firmware")
|
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Models and settings editor for the OpenTx open source firmware")
|
||||||
string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_PACKAGE_NAME_LOWERCASE)
|
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")
|
find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
|
||||||
if(DPKG_PROGRAM)
|
if(DPKG_PROGRAM)
|
||||||
SET(CPACK_GENERATOR "DEB")
|
SET(CPACK_GENERATOR "DEB")
|
||||||
|
|
|
@ -627,7 +627,7 @@ Mode 4:
|
||||||
<item row="10" column="2" colspan="2">
|
<item row="10" column="2" colspan="2">
|
||||||
<widget class="QPushButton" name="sdPathButton">
|
<widget class="QPushButton" name="sdPathButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open Folder</string>
|
<string>Select Folder</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -637,7 +637,7 @@ Mode 4:
|
||||||
<string>The profile specific folder, if set, will override general Backup folder</string>
|
<string>The profile specific folder, if set, will override general Backup folder</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open Folder</string>
|
<string>Select Folder</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -854,7 +854,7 @@ Mode 4:
|
||||||
<item row="12" column="2" colspan="2">
|
<item row="12" column="2" colspan="2">
|
||||||
<widget class="QPushButton" name="backupPathButton">
|
<widget class="QPushButton" name="backupPathButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open Folder</string>
|
<string>Select Folder</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -874,14 +874,14 @@ Mode 4:
|
||||||
<item row="0" column="2" colspan="2">
|
<item row="0" column="2" colspan="2">
|
||||||
<widget class="QPushButton" name="ge_pathButton">
|
<widget class="QPushButton" name="ge_pathButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Find Executable</string>
|
<string>Select Executable</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="16" column="2" colspan="2">
|
<item row="16" column="2" colspan="2">
|
||||||
<widget class="QPushButton" name="libraryPathButton">
|
<widget class="QPushButton" name="libraryPathButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open Folder</string>
|
<string>Select Folder</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -1001,7 +1001,7 @@ Mode 4:
|
||||||
<item row="0" column="3">
|
<item row="0" column="3">
|
||||||
<widget class="QPushButton" name="snapshotPathButton">
|
<widget class="QPushButton" name="snapshotPathButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open Folder</string>
|
<string>Select Folder</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="flat">
|
<property name="flat">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
|
|
|
@ -156,7 +156,8 @@ int main(int argc, char *argv[])
|
||||||
delete splash;
|
delete splash;
|
||||||
delete mainWin;
|
delete mainWin;
|
||||||
|
|
||||||
unregisterFirmwares();
|
unregisterSimulators();
|
||||||
|
unregisterOpenTxFirmwares();
|
||||||
unregisterEEpromInterfaces();
|
unregisterEEpromInterfaces();
|
||||||
|
|
||||||
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
|
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
|
||||||
|
|
|
@ -783,7 +783,7 @@ QString CustomFunctionData::funcToString() const
|
||||||
else if (func == FuncPlayScript)
|
else if (func == FuncPlayScript)
|
||||||
return QObject::tr("Play Script");
|
return QObject::tr("Play Script");
|
||||||
else if (func == FuncLogs)
|
else if (func == FuncLogs)
|
||||||
return QObject::tr("Start Logs");
|
return QObject::tr("SD Logs");
|
||||||
else if (func == FuncVolume)
|
else if (func == FuncVolume)
|
||||||
return QObject::tr("Volume");
|
return QObject::tr("Volume");
|
||||||
else if (func == FuncBacklight)
|
else if (func == FuncBacklight)
|
||||||
|
@ -1628,13 +1628,6 @@ QList<Firmware *> firmwares;
|
||||||
Firmware * default_firmware_variant;
|
Firmware * default_firmware_variant;
|
||||||
Firmware * current_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)
|
void ShowEepromErrors(QWidget *parent, const QString &title, const QString &mainMessage, unsigned long errorsFound)
|
||||||
{
|
{
|
||||||
std::bitset<NUM_ERRORS> errors((unsigned long long)errorsFound);
|
std::bitset<NUM_ERRORS> errors((unsigned long long)errorsFound);
|
||||||
|
|
|
@ -755,6 +755,22 @@ enum TelemetryCurrentSources {
|
||||||
TELEMETRY_CURRENT_SOURCE_FAS
|
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 {
|
class FrSkyData {
|
||||||
public:
|
public:
|
||||||
FrSkyData() { clear(); }
|
FrSkyData() { clear(); }
|
||||||
|
@ -1284,7 +1300,6 @@ enum Capability {
|
||||||
HasExpoNames,
|
HasExpoNames,
|
||||||
HasNoExpo,
|
HasNoExpo,
|
||||||
HasMixerNames,
|
HasMixerNames,
|
||||||
HasChNames,
|
|
||||||
HasCvNames,
|
HasCvNames,
|
||||||
HasPxxCountry,
|
HasPxxCountry,
|
||||||
HasPPMStart,
|
HasPPMStart,
|
||||||
|
@ -1376,8 +1391,6 @@ class EEPROMInterface
|
||||||
|
|
||||||
virtual int getSize(const GeneralSettings &) = 0;
|
virtual int getSize(const GeneralSettings &) = 0;
|
||||||
|
|
||||||
virtual int isAvailable(PulsesProtocol proto, int port=0) = 0;
|
|
||||||
|
|
||||||
virtual const int getEEpromSize() = 0;
|
virtual const int getEEpromSize() = 0;
|
||||||
|
|
||||||
virtual const int getMaxModels() = 0;
|
virtual const int getMaxModels() = 0;
|
||||||
|
@ -1489,7 +1502,7 @@ inline void applyStickModeToModel(ModelData &model, unsigned int mode)
|
||||||
void registerEEpromInterfaces();
|
void registerEEpromInterfaces();
|
||||||
void unregisterEEpromInterfaces();
|
void unregisterEEpromInterfaces();
|
||||||
void registerOpenTxFirmwares();
|
void registerOpenTxFirmwares();
|
||||||
void unregisterFirmwares();
|
void unregisterOpenTxFirmwares();
|
||||||
|
|
||||||
enum EepromLoadErrors {
|
enum EepromLoadErrors {
|
||||||
NO_ERROR,
|
NO_ERROR,
|
||||||
|
@ -1613,6 +1626,8 @@ class Firmware {
|
||||||
|
|
||||||
virtual bool isTelemetrySourceAvailable(int source) = 0;
|
virtual bool isTelemetrySourceAvailable(int source) = 0;
|
||||||
|
|
||||||
|
virtual int isAvailable(PulsesProtocol proto, int port=0) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QList<const char *> languages;
|
QList<const char *> languages;
|
||||||
QList<const char *> ttslanguages;
|
QList<const char *> ttslanguages;
|
||||||
|
|
|
@ -121,20 +121,16 @@ PACK(struct EepromFileHeader
|
||||||
|
|
||||||
bool RleFile::searchFat()
|
bool RleFile::searchFat()
|
||||||
{
|
{
|
||||||
int bestFatIndex = -1;
|
eepromFatHeader = NULL;
|
||||||
|
uint32_t bestFatIndex = 0;
|
||||||
for (int i=0; i<EEPROM_ZONE_SIZE/EEPROM_FAT_SIZE; i++) {
|
for (int i=0; i<EEPROM_ZONE_SIZE/EEPROM_FAT_SIZE; i++) {
|
||||||
EepromHeader * header = (EepromHeader *)(eeprom+i*EEPROM_FAT_SIZE);
|
EepromHeader * header = (EepromHeader *)(eeprom+i*EEPROM_FAT_SIZE);
|
||||||
if (header->mark == EEPROM_MARK && (int)header->index >= bestFatIndex) {
|
if (header->mark == EEPROM_MARK && (int)header->index >= bestFatIndex) {
|
||||||
bestFatIndex = i;
|
eepromFatHeader = header;
|
||||||
|
bestFatIndex = header->index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bestFatIndex >= 0) {
|
return (eepromFatHeader != NULL);
|
||||||
eepromFatHeader = (EepromHeader *)(eeprom+bestFatIndex*EEPROM_FAT_SIZE);;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RleFile::EeFsOpen(uint8_t *eeprom, int size, BoardEnum board)
|
bool RleFile::EeFsOpen(uint8_t *eeprom, int size, BoardEnum board)
|
||||||
|
|
|
@ -392,8 +392,8 @@ template <int N>
|
||||||
class SwitchField: public ConversionField< SignedField<N> > {
|
class SwitchField: public ConversionField< SignedField<N> > {
|
||||||
public:
|
public:
|
||||||
SwitchField(RawSwitch & sw, BoardEnum board, unsigned int version, unsigned long flags=0):
|
SwitchField(RawSwitch & sw, BoardEnum board, unsigned int version, unsigned long flags=0):
|
||||||
ConversionField< SignedField<N> >(_switch, SwitchesConversionTable::getInstance(board, version, flags), "Switch",
|
ConversionField< SignedField<N> >(_switch, SwitchesConversionTable::getInstance(board, version, flags), QObject::tr("Switch").toAscii(),
|
||||||
"Switch "+ sw.toString()+" cannot be exported on this board!"),
|
QObject::tr("Switch ").toAscii()+ sw.toString()+ QObject::tr(" cannot be exported on this board!").toAscii()),
|
||||||
sw(sw),
|
sw(sw),
|
||||||
_switch(0)
|
_switch(0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -586,8 +586,6 @@ int OpenTxFirmware::getCapability(const Capability capability)
|
||||||
return (IS_TARANIS(board) ? 10 : 6);
|
return (IS_TARANIS(board) ? 10 : 6);
|
||||||
case GvarsName:
|
case GvarsName:
|
||||||
return (IS_9X(board) ? 0 : 6);
|
return (IS_9X(board) ? 0 : 6);
|
||||||
case HasChNames:
|
|
||||||
return (IS_TARANIS(board) ? 1 : 0);
|
|
||||||
case GvarsInCS:
|
case GvarsInCS:
|
||||||
case HasFAIMode:
|
case HasFAIMode:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -807,7 +805,7 @@ int OpenTxFirmware::getCapability(const Capability capability)
|
||||||
case MixersMonitor:
|
case MixersMonitor:
|
||||||
return id.contains("mixersmon") ? 1 : 0;
|
return id.contains("mixersmon") ? 1 : 0;
|
||||||
case HasBatMeterRange:
|
case HasBatMeterRange:
|
||||||
return (IS_TARANIS(board) ? true : false);
|
return (IS_TARANIS(board) ? true : id.contains("battgraph"));
|
||||||
case DangerousFunctions:
|
case DangerousFunctions:
|
||||||
return id.contains("danger") ? 1 : 0;
|
return id.contains("danger") ? 1 : 0;
|
||||||
default:
|
default:
|
||||||
|
@ -826,7 +824,7 @@ bool OpenTxFirmware::isTelemetrySourceAvailable(int source)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpenTxEepromInterface::isAvailable(PulsesProtocol proto, int port)
|
int OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
|
||||||
{
|
{
|
||||||
if (IS_TARANIS(board)) {
|
if (IS_TARANIS(board)) {
|
||||||
switch (port) {
|
switch (port) {
|
||||||
|
@ -834,9 +832,12 @@ int OpenTxEepromInterface::isAvailable(PulsesProtocol proto, int port)
|
||||||
switch (proto) {
|
switch (proto) {
|
||||||
case PULSES_OFF:
|
case PULSES_OFF:
|
||||||
case PULSES_PXX_XJT_X16:
|
case PULSES_PXX_XJT_X16:
|
||||||
|
return 1;
|
||||||
case PULSES_PXX_XJT_D8:
|
case PULSES_PXX_XJT_D8:
|
||||||
case PULSES_PXX_XJT_LR12:
|
case PULSES_PXX_XJT_LR12:
|
||||||
return 1;
|
return id.contains("eu") ? 0 : 1;
|
||||||
|
case PULSES_PPM:
|
||||||
|
return id.contains("internalppm") ? 1 : 0;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -903,7 +904,7 @@ int OpenTxEepromInterface::isAvailable(PulsesProtocol proto, int port)
|
||||||
case PULSES_DSMX:
|
case PULSES_DSMX:
|
||||||
case PULSES_LP45:
|
case PULSES_LP45:
|
||||||
case PULSES_DSM2:
|
case PULSES_DSM2:
|
||||||
case PULSES_PXX_DJT:
|
// case PULSES_PXX_DJT: // Unavailable for now
|
||||||
case PULSES_PPM16:
|
case PULSES_PPM16:
|
||||||
case PULSES_PPMSIM:
|
case PULSES_PPMSIM:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1452,3 +1453,9 @@ void registerOpenTxFirmwares()
|
||||||
current_firmware_variant = default_firmware_variant;
|
current_firmware_variant = default_firmware_variant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unregisterOpenTxFirmwares()
|
||||||
|
{
|
||||||
|
foreach (Firmware * f, firmwares) {
|
||||||
|
delete f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -45,8 +45,6 @@ class OpenTxEepromInterface : public EEPROMInterface
|
||||||
|
|
||||||
virtual int getSize(const GeneralSettings &);
|
virtual int getSize(const GeneralSettings &);
|
||||||
|
|
||||||
virtual int isAvailable(PulsesProtocol proto, int port=0);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
const char * getName();
|
const char * getName();
|
||||||
|
@ -123,6 +121,8 @@ class OpenTxFirmware: public Firmware {
|
||||||
|
|
||||||
virtual bool isTelemetrySourceAvailable(int source);
|
virtual bool isTelemetrySourceAvailable(int source);
|
||||||
|
|
||||||
|
virtual int isAvailable(PulsesProtocol proto, int port=0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
QString getFirmwareBaseUrl();
|
QString getFirmwareBaseUrl();
|
||||||
|
@ -130,5 +130,6 @@ class OpenTxFirmware: public Firmware {
|
||||||
};
|
};
|
||||||
|
|
||||||
void registerOpenTxFirmwares();
|
void registerOpenTxFirmwares();
|
||||||
|
void unregisterOpenTxFirmwares();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,9 +31,9 @@ add_custom_target(commondeps
|
||||||
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${RADIO_SRC_DIRECTORY}/stamp-opentx.h)
|
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${RADIO_SRC_DIRECTORY}/stamp-opentx.h)
|
||||||
|
|
||||||
add_custom_target(lua_exports
|
add_custom_target(lua_exports
|
||||||
COMMAND make PCB=TARANIS lua_exports_taranis.inc
|
COMMAND make PCB=TARANIS lua/lua_exports_taranis.inc
|
||||||
COMMAND make PCB=FLAMENCO lua_exports_flamenco.inc
|
COMMAND make PCB=FLAMENCO lua/lua_exports_flamenco.inc
|
||||||
COMMAND make PCB=HORUS lua_exports_horus.inc
|
COMMAND make PCB=HORUS lua/lua_exports_horus.inc
|
||||||
DEPENDS ${RADIO_SRC_DIRECTORY}/myeeprom.h
|
DEPENDS ${RADIO_SRC_DIRECTORY}/myeeprom.h
|
||||||
WORKING_DIRECTORY ${RADIO_SRC_DIRECTORY}
|
WORKING_DIRECTORY ${RADIO_SRC_DIRECTORY}
|
||||||
)
|
)
|
||||||
|
|
|
@ -387,7 +387,10 @@ namespace NAMESPACE {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LUA)
|
#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/lapi.c"
|
||||||
#include "radio/src/thirdparty/Lua/src/lcode.c"
|
#include "radio/src/thirdparty/Lua/src/lcode.c"
|
||||||
#include "radio/src/thirdparty/Lua/src/lctype.c"
|
#include "radio/src/thirdparty/Lua/src/lctype.c"
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
// Automatically generated file (CMake) - do not edit
|
|
||||||
#define DATE_STR "@DATE@"
|
|
||||||
#define TIME_STR "@TIME@"
|
|
||||||
#define VERS_STR "@VERSION@"
|
|
|
@ -137,6 +137,9 @@ ModulePanel::ModulePanel(QWidget *parent, ModelData & model, ModuleData & module
|
||||||
QString label;
|
QString label;
|
||||||
if (moduleIdx < 0) {
|
if (moduleIdx < 0) {
|
||||||
label = tr("Trainer Port");
|
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);
|
ui->trainerMode->setCurrentIndex(model.trainerMode);
|
||||||
if (!IS_TARANIS(firmware->getBoard())) {
|
if (!IS_TARANIS(firmware->getBoard())) {
|
||||||
ui->label_trainerMode->hide();
|
ui->label_trainerMode->hide();
|
||||||
|
@ -168,7 +171,7 @@ ModulePanel::ModulePanel(QWidget *parent, ModelData & model, ModuleData & module
|
||||||
|
|
||||||
// The protocols available on this board
|
// The protocols available on this board
|
||||||
for (int i=0; i<PULSES_PROTOCOL_LAST; i++) {
|
for (int i=0; i<PULSES_PROTOCOL_LAST; i++) {
|
||||||
if (GetEepromInterface()->isAvailable((PulsesProtocol)i, moduleIdx)) {
|
if (firmware->isAvailable((PulsesProtocol)i, moduleIdx)) {
|
||||||
ui->protocol->addItem(ModelPrinter::printModuleProtocol(i), (QVariant)i);
|
ui->protocol->addItem(ModelPrinter::printModuleProtocol(i), (QVariant)i);
|
||||||
if (i == module.protocol) ui->protocol->setCurrentIndex(ui->protocol->count()-1);
|
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);
|
spinbox->setDecimals(1);
|
||||||
label->setProperty("index", i);
|
label->setProperty("index", i);
|
||||||
spinbox->setProperty("index", i);
|
spinbox->setProperty("index", i);
|
||||||
failsafeSpins << spinbox;
|
|
||||||
ui->failsafesLayout->addWidget(label, 3*(i/8), i%8, Qt::AlignHCenter);
|
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(combo, 1+3*(i/8), i%8, Qt::AlignHCenter);
|
||||||
ui->failsafesLayout->addWidget(spinbox, 2+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].combo = combo;
|
||||||
failsafeGroups[i].spinbox = spinbox;
|
failsafeGroups[i].spinbox = spinbox;
|
||||||
|
failsafeGroups[i].label = label;
|
||||||
updateFailsafe(i);
|
updateFailsafe(i);
|
||||||
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onFailsafeComboIndexChanged(int)));
|
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(onFailsafeComboIndexChanged(int)));
|
||||||
connect(spinbox, SIGNAL(valueChanged(double)), this, SLOT(onFailsafeSpinChanged(double)));
|
connect(spinbox, SIGNAL(valueChanged(double)), this, SLOT(onFailsafeSpinChanged(double)));
|
||||||
|
@ -234,7 +237,8 @@ void ModulePanel::update()
|
||||||
case PULSES_PXX_XJT_LR12:
|
case PULSES_PXX_XJT_LR12:
|
||||||
case PULSES_PXX_DJT:
|
case PULSES_PXX_DJT:
|
||||||
mask |= MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
|
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;
|
break;
|
||||||
case PULSES_LP45:
|
case PULSES_LP45:
|
||||||
case PULSES_DSM2:
|
case PULSES_DSM2:
|
||||||
|
@ -255,15 +259,8 @@ void ModulePanel::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IS_TARANIS(firmware->getBoard())) {
|
else if (IS_TARANIS(firmware->getBoard())) {
|
||||||
switch(model->trainerMode) {
|
if (model->trainerMode == TRAINER_SLAVE_JACK) {
|
||||||
case TRAINER_MASTER_JACK:
|
|
||||||
break;
|
|
||||||
case TRAINER_SLAVE_JACK:
|
|
||||||
mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
|
mask |= MASK_PPM_FIELDS | MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mask |= MASK_CHANNELS_RANGE | MASK_CHANNELS_COUNT;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (model->trainerMode != TRAINER_MASTER_JACK) {
|
else if (model->trainerMode != TRAINER_MASTER_JACK) {
|
||||||
|
@ -306,6 +303,17 @@ void ModulePanel::update()
|
||||||
ui->failsafeMode->setVisible(mask & MASK_FAILSAFES);
|
ui->failsafeMode->setVisible(mask & MASK_FAILSAFES);
|
||||||
ui->failsafeMode->setCurrentIndex(module.failsafeMode);
|
ui->failsafeMode->setCurrentIndex(module.failsafeMode);
|
||||||
ui->failsafesFrame->setEnabled(module.failsafeMode == FAILSAFE_CUSTOM);
|
ui->failsafesFrame->setEnabled(module.failsafeMode == FAILSAFE_CUSTOM);
|
||||||
|
if (firmware->getCapability(ChannelsName) > 0) {
|
||||||
|
for(int i=0; i<maxChannels;i++) {
|
||||||
|
QString name = QString(model->limitData[i+module.channelsStart].name).trimmed();
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
failsafeGroups[i].label->setText(name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
failsafeGroups[i].label->setText(QString::number(i+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mask = 0;
|
mask = 0;
|
||||||
|
@ -313,6 +321,11 @@ void ModulePanel::update()
|
||||||
|
|
||||||
ui->failsafesLayoutLabel->setVisible(mask & MASK_FAILSAFES);
|
ui->failsafesLayoutLabel->setVisible(mask & MASK_FAILSAFES);
|
||||||
ui->failsafesFrame->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)
|
void ModulePanel::on_trainerMode_currentIndexChanged(int index)
|
||||||
|
@ -656,6 +669,7 @@ SetupPanel::SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & gen
|
||||||
if (firmware->getCapability(ModelTrainerEnable)) {
|
if (firmware->getCapability(ModelTrainerEnable)) {
|
||||||
modules[C9X_NUM_MODULES] = new ModulePanel(this, model, model.moduleData[C9X_NUM_MODULES], generalSettings, firmware, -1);
|
modules[C9X_NUM_MODULES] = new ModulePanel(this, model, model.moduleData[C9X_NUM_MODULES], generalSettings, firmware, -1);
|
||||||
ui->modulesLayout->addWidget(modules[C9X_NUM_MODULES]);
|
ui->modulesLayout->addWidget(modules[C9X_NUM_MODULES]);
|
||||||
|
connect(modules[C9X_NUM_MODULES], SIGNAL(modified()), this, SLOT(onChildModified()));
|
||||||
}
|
}
|
||||||
|
|
||||||
disableMouseScrolling();
|
disableMouseScrolling();
|
||||||
|
|
|
@ -45,6 +45,7 @@ class ModulePanel : public ModelPanel
|
||||||
struct ChannelFailsafeWidgetsGroup {
|
struct ChannelFailsafeWidgetsGroup {
|
||||||
QComboBox * combo;
|
QComboBox * combo;
|
||||||
QDoubleSpinBox * spinbox;
|
QDoubleSpinBox * spinbox;
|
||||||
|
QLabel * label;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -75,7 +76,6 @@ class ModulePanel : public ModelPanel
|
||||||
ModuleData & module;
|
ModuleData & module;
|
||||||
int moduleIdx;
|
int moduleIdx;
|
||||||
Ui::Module *ui;
|
Ui::Module *ui;
|
||||||
QVector<QDoubleSpinBox *> failsafeSpins;
|
|
||||||
ChannelFailsafeWidgetsGroup failsafeGroups[maxChannels];
|
ChannelFailsafeWidgetsGroup failsafeGroups[maxChannels];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -67,12 +67,12 @@
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_69" rowstretch="0,0,0,0,0,0,0,0,0" columnstretch="0,0,0,0,0,0,0">
|
<layout class="QGridLayout" name="gridLayout_69" rowstretch="0,0,0,0,0,0,0,0,0" columnstretch="0,0,0,0,0,0,0">
|
||||||
<property name="verticalSpacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="margin">
|
<property name="margin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="verticalSpacing">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
<item row="2" column="3" alignment="Qt::AlignLeft">
|
<item row="2" column="3" alignment="Qt::AlignLeft">
|
||||||
<widget class="QSpinBox" name="channelsStart">
|
<widget class="QSpinBox" name="channelsStart">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
|
@ -353,7 +353,7 @@
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1</number>
|
<number>4</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>16</number>
|
<number>16</number>
|
||||||
|
|
|
@ -745,6 +745,7 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
|
||||||
TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware);
|
TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware);
|
||||||
ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i+1));
|
ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i+1));
|
||||||
telemetryCustomScreens[i] = tab;
|
telemetryCustomScreens[i] = tab;
|
||||||
|
connect(tab, SIGNAL(modified()), this, SLOT(onModified()));
|
||||||
}
|
}
|
||||||
|
|
||||||
disableMouseScrolling();
|
disableMouseScrolling();
|
||||||
|
|
|
@ -57,7 +57,7 @@ QString ModelPrinter::printChannelName(int idx)
|
||||||
QString ModelPrinter::printOutputName(int idx)
|
QString ModelPrinter::printOutputName(int idx)
|
||||||
{
|
{
|
||||||
QString name = QString(model.limitData[idx].name).trimmed();
|
QString name = QString(model.limitData[idx].name).trimmed();
|
||||||
if (firmware->getCapability(HasChNames) && !name.isEmpty()) {
|
if (firmware->getCapability(ChannelsName) > 0 && !name.isEmpty()) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -313,7 +313,7 @@ QString ModelPrinter::printInputLine(const ExpoData & input)
|
||||||
QString ModelPrinter::printMixerName(int curDest)
|
QString ModelPrinter::printMixerName(int curDest)
|
||||||
{
|
{
|
||||||
QString str = printChannelName(curDest-1) + " ";
|
QString str = printChannelName(curDest-1) + " ";
|
||||||
if (firmware->getCapability(HasChNames)) {
|
if (firmware->getCapability(ChannelsName) > 0) {
|
||||||
QString name = model.limitData[curDest-1].name;
|
QString name = model.limitData[curDest-1].name;
|
||||||
if (!name.isEmpty()) {
|
if (!name.isEmpty()) {
|
||||||
name = QString("(") + name + QString(")");
|
name = QString("(") + name + QString(")");
|
||||||
|
|
|
@ -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
|
#endif
|
||||||
|
|
|
@ -49,4 +49,6 @@ struct mount_entry
|
||||||
|
|
||||||
struct mount_entry *read_file_system_list (bool need_fs_type);
|
struct mount_entry *read_file_system_list (bool need_fs_type);
|
||||||
|
|
||||||
|
void free_file_system_list(struct mount_entry * mount_list);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -270,7 +270,7 @@ QString MultiModelPrinter::printLimits()
|
||||||
columns.append("<table border='0' cellspacing='0' cellpadding='1' width='100%'>" \
|
columns.append("<table border='0' cellspacing='0' cellpadding='1' width='100%'>" \
|
||||||
"<tr>" \
|
"<tr>" \
|
||||||
" <td><b>" + tr("Channel") + "</b></td>" \
|
" <td><b>" + tr("Channel") + "</b></td>" \
|
||||||
" <td><b>" + (firmware->getCapability(HasChNames) ? tr("Name") : "") + "</b></td>" \
|
" <td><b>" + (firmware->getCapability(ChannelsName) > 0 ? tr("Name") : "") + "</b></td>" \
|
||||||
" <td><b>" + tr("Offset") + "</b></td>" \
|
" <td><b>" + tr("Offset") + "</b></td>" \
|
||||||
" <td><b>" + tr("Min") + "</b></td>" \
|
" <td><b>" + tr("Min") + "</b></td>" \
|
||||||
" <td><b>" + tr("Max") + "</b></td>" \
|
" <td><b>" + tr("Max") + "</b></td>" \
|
||||||
|
|
|
@ -411,7 +411,8 @@ QString findMassstoragePath(const QString &filename)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
struct mount_entry *entry;
|
struct mount_entry *entry;
|
||||||
entry = read_file_system_list(true);
|
struct mount_entry *firstEntry;
|
||||||
|
firstEntry = entry = read_file_system_list(true);
|
||||||
while (entry != NULL) {
|
while (entry != NULL) {
|
||||||
if (!drives.contains(entry->me_devname)) {
|
if (!drives.contains(entry->me_devname)) {
|
||||||
drives.append(entry->me_devname);
|
drives.append(entry->me_devname);
|
||||||
|
@ -426,11 +427,13 @@ QString findMassstoragePath(const QString &filename)
|
||||||
#else
|
#else
|
||||||
if (QFile::exists(eepromfile)) {
|
if (QFile::exists(eepromfile)) {
|
||||||
#endif
|
#endif
|
||||||
|
free_file_system_list(firstEntry);
|
||||||
return eepromfile;
|
return eepromfile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entry = entry->me_next;
|
entry = entry->me_next;
|
||||||
}
|
}
|
||||||
|
free_file_system_list(firstEntry);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#if defined WIN32 || !defined __GNUC__
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
QMap<QString, SimulatorFactory *> registered_simulators;
|
QMap<QString, SimulatorFactory *> registered_simulators;
|
||||||
|
|
||||||
|
@ -47,10 +50,15 @@ void registerSimulators()
|
||||||
simulatorsFound = true;
|
simulatorsFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__APPLE__) || !( (!defined __GNUC__) || (defined __CYGWIN__) )
|
|
||||||
if (!simulatorsFound) {
|
if (!simulatorsFound) {
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
dir = QLibraryInfo::location(QLibraryInfo::PrefixPath) + "/Resources";
|
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
|
#else
|
||||||
dir = SIMULATOR_LIB_SEARCH_PATH;
|
dir = SIMULATOR_LIB_SEARCH_PATH;
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,7 +67,6 @@ void registerSimulators()
|
||||||
simulatorsFound = true;
|
simulatorsFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SimulatorFactory *getSimulatorFactory(const QString &name)
|
SimulatorFactory *getSimulatorFactory(const QString &name)
|
||||||
|
@ -81,3 +88,9 @@ SimulatorFactory *getSimulatorFactory(const QString &name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unregisterSimulators()
|
||||||
|
{
|
||||||
|
foreach(SimulatorFactory *factory, registered_simulators) {
|
||||||
|
delete factory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -118,6 +118,7 @@ class SimulatorFactory {
|
||||||
};
|
};
|
||||||
|
|
||||||
void registerSimulators();
|
void registerSimulators();
|
||||||
|
void unregisterSimulators();
|
||||||
SimulatorFactory *getSimulatorFactory(const QString &name);
|
SimulatorFactory *getSimulatorFactory(const QString &name);
|
||||||
extern QMap<QString, SimulatorFactory *> registered_simulators;
|
extern QMap<QString, SimulatorFactory *> registered_simulators;
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
delete dialog;
|
delete dialog;
|
||||||
|
|
||||||
|
unregisterSimulators();
|
||||||
|
unregisterOpenTxFirmwares();
|
||||||
|
|
||||||
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
|
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -36,7 +36,7 @@ $Descr A4 11693 8268
|
||||||
encoding utf-8
|
encoding utf-8
|
||||||
Sheet 1 1
|
Sheet 1 1
|
||||||
Title "OpenTX board based on Arduino MEGA2560"
|
Title "OpenTX board based on Arduino MEGA2560"
|
||||||
Date "18 jun 2015"
|
Date "21 oct 2015"
|
||||||
Rev "0"
|
Rev "0"
|
||||||
Comp "Copyright 2015 F. Aguerre"
|
Comp "Copyright 2015 F. Aguerre"
|
||||||
Comment1 ""
|
Comment1 ""
|
||||||
|
@ -1057,13 +1057,13 @@ Text Label 5650 5850 2 42 ~ 0
|
||||||
SW_Trn
|
SW_Trn
|
||||||
Text GLabel 4850 5850 2 42 Input ~ 0
|
Text GLabel 4850 5850 2 42 Input ~ 0
|
||||||
port L 7 (1)
|
port L 7 (1)
|
||||||
Text GLabel 4850 6250 2 42 Output ~ 0
|
Text GLabel 4850 6250 2 42 Input ~ 0
|
||||||
port B 3 (1)
|
port B 3 (1)
|
||||||
Text Label 5650 6250 2 42 ~ 0
|
Text Label 5650 6250 2 42 ~ 0
|
||||||
SD_MISO
|
SD_MISO
|
||||||
Text Label 6600 6250 2 42 ~ 0
|
Text Label 6600 6250 2 42 ~ 0
|
||||||
SD_MOSI
|
SD_MOSI
|
||||||
Text GLabel 5800 6250 2 42 Input ~ 0
|
Text GLabel 5800 6250 2 42 Output ~ 0
|
||||||
port B 2 (1)
|
port B 2 (1)
|
||||||
Text GLabel 5800 6350 2 42 Input ~ 0
|
Text GLabel 5800 6350 2 42 Input ~ 0
|
||||||
port B 0 (1)
|
port B 0 (1)
|
||||||
|
@ -1278,7 +1278,7 @@ PPM_OUT
|
||||||
Text GLabel 2100 4600 1 42 Output ~ 0
|
Text GLabel 2100 4600 1 42 Output ~ 0
|
||||||
port B 6 (0)
|
port B 6 (0)
|
||||||
Text GLabel 2000 4600 1 42 Input ~ 0
|
Text GLabel 2000 4600 1 42 Input ~ 0
|
||||||
port B 7 (0)
|
port E 7 (0)
|
||||||
Text Label 5650 4850 2 42 ~ 0
|
Text Label 5650 4850 2 42 ~ 0
|
||||||
LCD_DATA0
|
LCD_DATA0
|
||||||
Text GLabel 4850 4850 2 42 Output ~ 0
|
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
|
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
|
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
|
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
|
EndData
|
||||||
$EndBitmap
|
$EndBitmap
|
||||||
$Comp
|
$Comp
|
||||||
|
@ -41427,7 +41427,7 @@ Wire Wire Line
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
2100 4750 2100 4600
|
2100 4750 2100 4600
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
2000 4750 2000 4600
|
2000 4600 2000 5550
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
4700 4850 4850 4850
|
4700 4850 4850 4850
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
|
@ -41863,4 +41863,8 @@ Wire Wire Line
|
||||||
5300 7500 5300 7600
|
5300 7500 5300 7600
|
||||||
Wire Wire Line
|
Wire Wire Line
|
||||||
4800 7500 5300 7500
|
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
|
$EndSCHEMATC
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,4 +1,14 @@
|
||||||
<h2>Version 2.1.4 / <set date></h2>
|
<h2>Version 2.1.6 / 2015-11-11</h2>
|
||||||
|
[Taranis]
|
||||||
|
<ul>
|
||||||
|
<li>Fix for some X9E units which could not shutdown properly</li>
|
||||||
|
<li>Fixed a bug with negative altitudes in the Top bar (<a href=https://github.com/opentx/opentx/issues/3047>#3047</a>)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Version 2.1.5 / 2015-11-05</h2>
|
||||||
|
|
||||||
|
Notice: version 2.1.4 was skipped by the OpenTX team to avoid confusion with FrSky's release of OpenTX 2.1.4
|
||||||
|
|
||||||
[Taranis]
|
[Taranis]
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -10,6 +20,11 @@
|
||||||
<li>Trainer mode fixes for X9E (<a href=https://github.com/opentx/opentx/issues/2913>#2913</a>)</li>
|
<li>Trainer mode fixes for X9E (<a href=https://github.com/opentx/opentx/issues/2913>#2913</a>)</li>
|
||||||
<li>Fixed a bug that caused no servo movement when certain firmware option combinations were used (<a href=https://github.com/opentx/opentx/issues/2945>#2945</a>)</li>
|
<li>Fixed a bug that caused no servo movement when certain firmware option combinations were used (<a href=https://github.com/opentx/opentx/issues/2945>#2945</a>)</li>
|
||||||
<li>Fixed missing arrows on RS, LS2, RS2 pot warnings on X9E (<a href=https://github.com/opentx/opentx/issues/2961>#2961</a>)</li>
|
<li>Fixed missing arrows on RS, LS2, RS2 pot warnings on X9E (<a href=https://github.com/opentx/opentx/issues/2961>#2961</a>)</li>
|
||||||
|
<li>Fixed erroneous haptic feedback when using high powered UHF RF modules (<a href=https://github.com/opentx/opentx/issues/2722>#2722</a>)</li>
|
||||||
|
<li>The trainer icon will be shown only if valid PPM is received</li>
|
||||||
|
<li>Several Lua io library fixes (<a href=https://github.com/opentx/opentx/issues/3001>#3001</a>, <a href=https://github.com/opentx/opentx/issues/3003>#3003</a>)</li>
|
||||||
|
<li>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 (<a href=https://github.com/opentx/opentx/issues/2975>#2975</a>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
[ARM boards]
|
[ARM boards]
|
||||||
|
@ -24,6 +39,8 @@
|
||||||
[Sky9x / 9XR-PRO / AR9X]
|
[Sky9x / 9XR-PRO / AR9X]
|
||||||
<ul>
|
<ul>
|
||||||
<li>Fixed navigation problem in Telemetry setup (<a href=https://github.com/opentx/opentx/issues/2951>#2951</a>)</li>
|
<li>Fixed navigation problem in Telemetry setup (<a href=https://github.com/opentx/opentx/issues/2951>#2951</a>)</li>
|
||||||
|
<li>Fixed: Model Restore broken (<a href=https://github.com/opentx/opentx/issues/2797>#2797</a>)</li>
|
||||||
|
<li>Fixed battery indicator graphics (<a href=https://github.com/opentx/opentx/issues/2989>#2989</a>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
[AVR boards]
|
[AVR boards]
|
||||||
|
@ -31,6 +48,11 @@
|
||||||
<li>Mavlink build option was not working (<a href=https://github.com/opentx/opentx/issues/2950>#2950</a>)</li>
|
<li>Mavlink build option was not working (<a href=https://github.com/opentx/opentx/issues/2950>#2950</a>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
[Mega2560]
|
||||||
|
<ul>
|
||||||
|
<li>Fixed : mixer update rate was too slow (<a href=https://github.com/opentx/opentx/issues/2750>#2750</a>)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2>Version 2.1.3 / 2015-09-09</h2>
|
<h2>Version 2.1.3 / 2015-09-09</h2>
|
||||||
|
|
|
@ -379,6 +379,10 @@ WATCHDOG_TEST = NO
|
||||||
# Values = NO, YES
|
# Values = NO, YES
|
||||||
WARNINGS_AS_ERRORS = NO
|
WARNINGS_AS_ERRORS = NO
|
||||||
|
|
||||||
|
# Enable saving of Lua byte-code of all loaded scripts
|
||||||
|
# Values = NO, YES
|
||||||
|
LUA_COMPILER = NO
|
||||||
|
|
||||||
#------- END BUILD OPTIONS ---------------------------
|
#------- END BUILD OPTIONS ---------------------------
|
||||||
|
|
||||||
# Define programs and commands.
|
# Define programs and commands.
|
||||||
|
@ -1029,12 +1033,12 @@ ifeq ($(PCB), TARANIS)
|
||||||
endif
|
endif
|
||||||
CPPDEFS += -DLUA
|
CPPDEFS += -DLUA
|
||||||
INCDIRS += $(LUADIR)
|
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 \
|
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)/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
|
$(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)
|
SRC += $(LUASRC)
|
||||||
LUADEP = lua_exports_taranis.inc
|
LUADEP = lua/lua_exports_taranis.inc
|
||||||
ifeq ($(USE_BIN_ALLOCATOR), YES)
|
ifeq ($(USE_BIN_ALLOCATOR), YES)
|
||||||
CPPDEFS += -DUSE_BIN_ALLOCATOR
|
CPPDEFS += -DUSE_BIN_ALLOCATOR
|
||||||
CPPSRC += bin_allocator.cpp
|
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)/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
|
$(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)
|
SRC += $(LUASRC)
|
||||||
LUADEP = lua_exports_flamenco.inc
|
LUADEP = lua/lua_exports_flamenco.inc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
EXTRABOARDSRC += $(FATFSDIR)/ff.c $(FATFSDIR)/fattime.c $(FATFSDIR)/option/ccsbcs.c targets/Flamenco/diskio.cpp
|
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)/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
|
$(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)
|
SRC += $(LUASRC)
|
||||||
LUADEP = lua_exports_horus.inc
|
LUADEP = lua/lua_exports_horus.inc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
EXTRABOARDSRC += $(FATFSDIR)/ff.c $(FATFSDIR)/fattime.c $(FATFSDIR)/option/ccsbcs.c targets/Horus/diskio.cpp
|
EXTRABOARDSRC += $(FATFSDIR)/ff.c $(FATFSDIR)/fattime.c $(FATFSDIR)/option/ccsbcs.c targets/Horus/diskio.cpp
|
||||||
|
@ -1667,6 +1671,10 @@ ifeq ($(IRPROTOS), YES)
|
||||||
CPPDEFS += -DIRPROTOS
|
CPPDEFS += -DIRPROTOS
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(LUA_COMPILER), YES)
|
||||||
|
CPPDEFS += -DLUA_COMPILER
|
||||||
|
endif
|
||||||
|
|
||||||
#---------------- Compiler Options C++ ----------------
|
#---------------- Compiler Options C++ ----------------
|
||||||
# -g*: generate debugging information
|
# -g*: generate debugging information
|
||||||
# -O*: optimization level
|
# -O*: optimization level
|
||||||
|
@ -1924,25 +1932,25 @@ else
|
||||||
PARSER = gcc -E -x c++
|
PARSER = gcc -E -x c++
|
||||||
endif
|
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"
|
@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
|
@$(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"
|
@echo "Parsing and generating C Lua exports in lua/lua_exports_taranis.inc"
|
||||||
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_taranis.txt lua_exports_taranis.inc lua_fields_taranis.txt
|
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_taranis.txt lua/lua_exports_taranis.inc lua_fields_taranis.txt
|
||||||
@rm lua_exports_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"
|
@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
|
@$(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"
|
@echo "Parsing and generating C Lua exports in lua/lua_exports_horus.inc"
|
||||||
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_horus.txt lua_exports_horus.inc lua_fields_horus.txt
|
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_horus.txt lua/lua_exports_horus.inc lua_fields_horus.txt
|
||||||
@rm lua_exports_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"
|
@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
|
@$(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"
|
@echo "Parsing and generating C Lua exports in lua/lua_exports_flamenco.inc"
|
||||||
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_flamenco.txt lua_exports_flamenco.inc lua_fields_flamenco.txt
|
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_flamenco.txt lua/lua_exports_flamenco.inc lua_fields_flamenco.txt
|
||||||
@rm lua_exports_flamenco.txt
|
@rm lua_exports_flamenco.txt
|
||||||
|
|
||||||
# Eye candy.
|
# Eye candy.
|
||||||
|
@ -2101,7 +2109,7 @@ clean_list :
|
||||||
$(REMOVE) bitmaps/*.lbm
|
$(REMOVE) bitmaps/*.lbm
|
||||||
$(REMOVE) bitmaps/*/*.lbm
|
$(REMOVE) bitmaps/*/*.lbm
|
||||||
$(REMOVE) fonts/*/*.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
|
$(MAKE) -C targets/Taranis/bootloader clean
|
||||||
|
|
||||||
#### Install
|
#### Install
|
||||||
|
|
|
@ -367,8 +367,10 @@ void evalFunctions()
|
||||||
}
|
}
|
||||||
#if defined(CPUARM)
|
#if defined(CPUARM)
|
||||||
if (CFN_PARAM(cfn)>=FUNC_RESET_PARAM_FIRST_TELEM) {
|
if (CFN_PARAM(cfn)>=FUNC_RESET_PARAM_FIRST_TELEM) {
|
||||||
TelemetryItem * telemetryItem = & telemetryItems[CFN_PARAM(cfn)-FUNC_RESET_PARAM_FIRST_TELEM];
|
uint8_t item = CFN_PARAM(cfn)-FUNC_RESET_PARAM_FIRST_TELEM;
|
||||||
telemetryItem->clear();
|
if (item < MAX_SENSORS) {
|
||||||
|
telemetryItems[item].clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -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)
|
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];
|
TelemetryItem & telemetryItem = telemetryItems[channel];
|
||||||
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[channel];
|
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[channel];
|
||||||
if (telemetrySensor.unit == UNIT_DATETIME) {
|
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:
|
case TELEM_TX_VOLTAGE-1:
|
||||||
lcd_outdezAtt(x, y, val, (att|PREC1) & (~NO_UNIT));
|
lcd_outdezAtt(x, y, val, (att|PREC1) & (~NO_UNIT));
|
||||||
if (!(att & NO_UNIT))
|
if (!(att & NO_UNIT))
|
||||||
lcd_putc(lcdLastPos/*+1*/, y, 'v');
|
lcd_putc(lcdLastPos/*+1*/, y, 'V');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,6 +262,13 @@ void lcdInit();
|
||||||
|
|
||||||
void lcdRefresh();
|
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)
|
#if defined(BOOT)
|
||||||
#define BLINK_ON_PHASE (0)
|
#define BLINK_ON_PHASE (0)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -185,7 +185,11 @@ void menuModelLogicalSwitchOne(uint8_t event)
|
||||||
else {
|
else {
|
||||||
#if defined(FRSKY)
|
#if defined(FRSKY)
|
||||||
if (v1_val >= MIXSRC_FIRST_TELEM) {
|
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);
|
putsTelemetryChannelValue(CSWONE_2ND_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), attr|LEFT);
|
||||||
|
#endif
|
||||||
v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1);
|
v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1);
|
||||||
if (cs->func == LS_FUNC_DIFFEGREATER)
|
if (cs->func == LS_FUNC_DIFFEGREATER)
|
||||||
v2_min = -v2_max;
|
v2_min = -v2_max;
|
||||||
|
@ -295,7 +299,11 @@ void menuModelLogicalSwitches(uint8_t event)
|
||||||
uint8_t v1 = cs->v1;
|
uint8_t v1 = cs->v1;
|
||||||
putsMixerSource(CSW_2ND_COLUMN, y, v1, 0);
|
putsMixerSource(CSW_2ND_COLUMN, y, v1, 0);
|
||||||
if (v1 >= MIXSRC_FIRST_TELEM) {
|
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);
|
putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1 - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT);
|
lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT);
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
#define RBOX_CENTERX (3*LCD_W/4 - 10)
|
#define RBOX_CENTERX (3*LCD_W/4 - 10)
|
||||||
#define MODELNAME_X (2*FW-2)
|
#define MODELNAME_X (2*FW-2)
|
||||||
#define MODELNAME_Y (0)
|
#define MODELNAME_Y (0)
|
||||||
#define PHASE_X (6*FW)
|
#define PHASE_X (6*FW-1)
|
||||||
#define PHASE_Y (2*FH)
|
#define PHASE_Y (2*FH)
|
||||||
#define PHASE_FLAGS 0
|
#define PHASE_FLAGS 0
|
||||||
#define VBATT_X (6*FW)
|
#define VBATT_X (6*FW)
|
||||||
|
@ -206,13 +206,13 @@ void displayBattVoltage()
|
||||||
{
|
{
|
||||||
#if defined(BATTGRAPH)
|
#if defined(BATTGRAPH)
|
||||||
putsVBat(VBATT_X-8, VBATT_Y+1, 0);
|
putsVBat(VBATT_X-8, VBATT_Y+1, 0);
|
||||||
drawFilledRect(VBATT_X-25, VBATT_Y+9, 22, 5);
|
drawFilledRect(VBATT_X-25, VBATT_Y+9, 21, 5);
|
||||||
lcd_vline(VBATT_X-3, VBATT_Y+10, 3);
|
lcd_vline(VBATT_X-4, VBATT_Y+10, 3);
|
||||||
uint8_t count = GET_TXBATT_BARS();
|
uint8_t count = GET_TXBATT_BARS();
|
||||||
for (uint8_t i=0; i<count; i+=2)
|
for (uint8_t i=0; i<count; i+=2)
|
||||||
lcd_vline(VBATT_X-24+i, VBATT_Y+10, 3);
|
lcd_vline(VBATT_X-24+i, VBATT_Y+10, 3);
|
||||||
if (!IS_TXBATT_WARNING() || BLINK_ON_PHASE)
|
if (!IS_TXBATT_WARNING() || BLINK_ON_PHASE)
|
||||||
drawFilledRect(VBATT_X-26, VBATT_Y, 25, 15);
|
drawFilledRect(VBATT_X-26, VBATT_Y, 24, 15);
|
||||||
#else
|
#else
|
||||||
LcdFlags att = (IS_TXBATT_WARNING() ? BLINK|INVERS : 0) | BIGSIZE;
|
LcdFlags att = (IS_TXBATT_WARNING() ? BLINK|INVERS : 0) | BIGSIZE;
|
||||||
putsVBat(VBATT_X-1, VBATT_Y, att|NO_UNIT);
|
putsVBat(VBATT_X-1, VBATT_Y, att|NO_UNIT);
|
||||||
|
|
|
@ -779,6 +779,12 @@ void putsSwitches(coord_t x, coord_t y, int32_t idx, LcdFlags att)
|
||||||
else if (idx == SWSRC_TELEMETRY_STREAMING) {
|
else if (idx == SWSRC_TELEMETRY_STREAMING) {
|
||||||
lcdDrawText(x, y, "Tele", att);
|
lcdDrawText(x, y, "Tele", att);
|
||||||
}
|
}
|
||||||
|
else if (idx <= SWSRC_LAST_FLIGHT_MODE) {
|
||||||
|
putsStrIdx(x, y, STR_FP, idx-SWSRC_FIRST_FLIGHT_MODE, att);
|
||||||
|
}
|
||||||
|
else if (idx == SWSRC_TELEMETRY_STREAMING) {
|
||||||
|
lcdDrawText(x, y, "Tele", att);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
lcdDrawTextWithLen(x, y, g_model.telemetrySensors[idx-SWSRC_FIRST_SENSOR].label, TELEM_LABEL_LEN, ZCHAR|att);
|
lcdDrawTextWithLen(x, y, g_model.telemetrySensors[idx-SWSRC_FIRST_SENSOR].label, TELEM_LABEL_LEN, ZCHAR|att);
|
||||||
}
|
}
|
||||||
|
@ -958,6 +964,7 @@ void displayGpsCoords(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFl
|
||||||
|
|
||||||
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, int32_t value, LcdFlags att)
|
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, int32_t value, LcdFlags att)
|
||||||
{
|
{
|
||||||
|
if (channel >= MAX_SENSORS) return; //Lua luaLcdDrawChannel() can call us with a bad value
|
||||||
TelemetryItem & telemetryItem = telemetryItems[channel];
|
TelemetryItem & telemetryItem = telemetryItems[channel];
|
||||||
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[channel];
|
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[channel];
|
||||||
if (telemetrySensor.unit == UNIT_DATETIME) {
|
if (telemetrySensor.unit == UNIT_DATETIME) {
|
||||||
|
|
|
@ -120,8 +120,10 @@ void menuModelFlightModesAll(uint8_t event)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ITEM_FLIGHT_MODES_SWITCH:
|
case ITEM_FLIGHT_MODES_SWITCH:
|
||||||
|
if (k>0) {
|
||||||
putsSwitches((5+LEN_FLIGHT_MODE_NAME)*FW+FW/2, y, p->swtch, attr);
|
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 (active) CHECK_INCDEC_MODELSWITCH(event, p->swtch, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, isSwitchAvailableInMixes);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ITEM_FLIGHT_MODES_TRIM_RUD:
|
case ITEM_FLIGHT_MODES_TRIM_RUD:
|
||||||
|
|
|
@ -645,17 +645,14 @@ void menuModelSetup(uint8_t event)
|
||||||
if (checkIncDec_Ret) {
|
if (checkIncDec_Ret) {
|
||||||
g_model.moduleData[INTERNAL_MODULE].rfProtocol = 0;
|
g_model.moduleData[INTERNAL_MODULE].rfProtocol = 0;
|
||||||
g_model.moduleData[INTERNAL_MODULE].channelsStart = 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;
|
g_model.moduleData[INTERNAL_MODULE].channelsCount = 0;
|
||||||
else
|
|
||||||
g_model.moduleData[INTERNAL_MODULE].channelsCount = MAX_INTERNAL_MODULE_CHANNELS();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[INTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST);
|
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[INTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST);
|
||||||
if (checkIncDec_Ret) {
|
if (checkIncDec_Ret) {
|
||||||
g_model.moduleData[INTERNAL_MODULE].channelsStart = 0;
|
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) {
|
if (attr) {
|
||||||
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].rfProtocol, RF_PROTO_OFF, RF_PROTO_LAST);
|
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].rfProtocol, RF_PROTO_OFF, RF_PROTO_LAST);
|
||||||
if (checkIncDec_Ret) {
|
if (checkIncDec_Ret) {
|
||||||
|
g_model.moduleData[0].type = MODULE_TYPE_XJT;
|
||||||
g_model.moduleData[0].channelsStart = 0;
|
g_model.moduleData[0].channelsStart = 0;
|
||||||
g_model.moduleData[0].channelsCount = 0;
|
g_model.moduleData[0].channelsCount = 0;
|
||||||
}
|
}
|
||||||
|
@ -695,10 +693,8 @@ void menuModelSetup(uint8_t event)
|
||||||
if (checkIncDec_Ret) {
|
if (checkIncDec_Ret) {
|
||||||
g_model.moduleData[EXTERNAL_MODULE].rfProtocol = 0;
|
g_model.moduleData[EXTERNAL_MODULE].rfProtocol = 0;
|
||||||
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 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;
|
g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0;
|
||||||
else
|
|
||||||
g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_EXTERNAL_MODULE_CHANNELS();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
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);
|
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST);
|
||||||
if (checkIncDec_Ret) {
|
if (checkIncDec_Ret) {
|
||||||
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
|
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 {
|
else {
|
||||||
horzpos_t l_posHorz = m_posHorz;
|
horzpos_t l_posHorz = m_posHorz;
|
||||||
coord_t xOffsetBind = MODEL_SETUP_BIND_OFS;
|
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;
|
xOffsetBind = 0;
|
||||||
lcd_putsLeft(y, INDENT "Receiver");
|
lcd_putsLeft(y, INDENT "Receiver");
|
||||||
if (attr) l_posHorz += 1;
|
if (attr) l_posHorz += 1;
|
||||||
|
@ -871,14 +867,16 @@ void menuModelFailsafe(uint8_t event)
|
||||||
static bool longNames = false;
|
static bool longNames = false;
|
||||||
bool newLongNames = false;
|
bool newLongNames = false;
|
||||||
uint8_t ch = 0;
|
uint8_t ch = 0;
|
||||||
|
uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart;
|
||||||
|
|
||||||
if (event == EVT_KEY_LONG(KEY_ENTER)) {
|
if (event == EVT_KEY_LONG(KEY_ENTER)) {
|
||||||
killEvents(event);
|
killEvents(event);
|
||||||
event = 0;
|
event = 0;
|
||||||
if (s_editMode) {
|
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);
|
storageDirty(EE_MODEL);
|
||||||
AUDIO_WARNING1();
|
AUDIO_WARNING1();
|
||||||
|
s_editMode = 0;
|
||||||
SEND_FAILSAFE_NOW(g_moduleIdx);
|
SEND_FAILSAFE_NOW(g_moduleIdx);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -888,14 +886,14 @@ void menuModelFailsafe(uint8_t event)
|
||||||
else if (failsafe == FAILSAFE_CHANNEL_HOLD)
|
else if (failsafe == FAILSAFE_CHANNEL_HOLD)
|
||||||
failsafe = FAILSAFE_CHANNEL_NOPULSE;
|
failsafe = FAILSAFE_CHANNEL_NOPULSE;
|
||||||
else
|
else
|
||||||
failsafe = channelOutputs[m_posVert];
|
failsafe = 0;
|
||||||
storageDirty(EE_MODEL);
|
storageDirty(EE_MODEL);
|
||||||
AUDIO_WARNING1();
|
AUDIO_WARNING1();
|
||||||
SEND_FAILSAFE_NOW(g_moduleIdx);
|
SEND_FAILSAFE_NOW(g_moduleIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SIMPLE_SUBMENU_NOTITLE(NUM_CHNOUT);
|
SIMPLE_SUBMENU_NOTITLE(NUM_CHANNELS(g_moduleIdx));
|
||||||
|
|
||||||
SET_SCROLLBAR_X(0);
|
SET_SCROLLBAR_X(0);
|
||||||
|
|
||||||
|
@ -904,10 +902,6 @@ void menuModelFailsafe(uint8_t event)
|
||||||
// Column separator
|
// Column separator
|
||||||
lcd_vline(LCD_W/2, FH, LCD_H-FH);
|
lcd_vline(LCD_W/2, FH, LCD_H-FH);
|
||||||
|
|
||||||
if (m_posVert >= 16) {
|
|
||||||
ch = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
lcd_putsCenter(0*FH, FAILSAFESET);
|
lcd_putsCenter(0*FH, FAILSAFESET);
|
||||||
lcd_invert_line(0);
|
lcd_invert_line(0);
|
||||||
|
|
||||||
|
@ -919,24 +913,25 @@ void menuModelFailsafe(uint8_t event)
|
||||||
// Channels
|
// Channels
|
||||||
for (uint8_t line=0; line<8; line++) {
|
for (uint8_t line=0; line<8; line++) {
|
||||||
coord_t y = 9+line*7;
|
coord_t y = 9+line*7;
|
||||||
int32_t channelValue = channelOutputs[ch];
|
int32_t channelValue = channelOutputs[ch+channelStart];
|
||||||
int32_t failsafeValue = 0;
|
int32_t failsafeValue = 0;
|
||||||
bool failsafeEditable = false;
|
bool failsafeEditable = false;
|
||||||
uint8_t ofs = (col ? 0 : 1);
|
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];
|
failsafeValue = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line];
|
||||||
failsafeEditable = true;
|
failsafeEditable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (failsafeEditable) {
|
||||||
// Channel name if present, number if not
|
// Channel name if present, number if not
|
||||||
uint8_t lenLabel = ZLEN(g_model.limitData[ch].name);
|
uint8_t lenLabel = ZLEN(g_model.limitData[ch+channelStart].name);
|
||||||
if (lenLabel > 4) {
|
if (lenLabel > 4) {
|
||||||
newLongNames = longNames = true;
|
newLongNames = longNames = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lenLabel > 0)
|
if (lenLabel > 0)
|
||||||
lcdDrawTextWithLen(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE);
|
lcdDrawTextWithLen(x+1-ofs, y, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR | SMLSIZE);
|
||||||
else
|
else
|
||||||
putsChn(x+1-ofs, y, ch+1, SMLSIZE);
|
putsChn(x+1-ofs, y, ch+1, SMLSIZE);
|
||||||
|
|
||||||
|
@ -945,7 +940,7 @@ void menuModelFailsafe(uint8_t event)
|
||||||
if (m_posVert == ch) {
|
if (m_posVert == ch) {
|
||||||
flags |= INVERS;
|
flags |= INVERS;
|
||||||
if (s_editMode) {
|
if (s_editMode) {
|
||||||
if (!failsafeEditable || failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
|
if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
|
||||||
s_editMode = 0;
|
s_editMode = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -989,7 +984,7 @@ void menuModelFailsafe(uint8_t event)
|
||||||
lcdDrawHorizontalLine(xChannel, y+2, lenChannel, DOTTED, 0);
|
lcdDrawHorizontalLine(xChannel, y+2, lenChannel, DOTTED, 0);
|
||||||
lcd_hline(xFailsafe, y+3, lenFailsafe);
|
lcd_hline(xFailsafe, y+3, lenFailsafe);
|
||||||
lcd_hline(xFailsafe, y+4, lenFailsafe);
|
lcd_hline(xFailsafe, y+4, lenFailsafe);
|
||||||
|
}
|
||||||
ch++;
|
ch++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,12 +164,8 @@ enum SensorFields {
|
||||||
|
|
||||||
bool isSensorUnit(int sensor, uint8_t unit)
|
bool isSensorUnit(int sensor, uint8_t unit)
|
||||||
{
|
{
|
||||||
if (sensor == 0)
|
if (sensor <= 0 || sensor > MAX_SENSORS ) return true;
|
||||||
return true;
|
return g_model.telemetrySensors[--sensor].unit == unit;
|
||||||
|
|
||||||
sensor -= 1;
|
|
||||||
|
|
||||||
return g_model.telemetrySensors[sensor].unit == unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCellsSensor(int sensor)
|
bool isCellsSensor(int sensor)
|
||||||
|
@ -184,7 +180,7 @@ bool isGPSSensor(int sensor)
|
||||||
|
|
||||||
bool isAltSensor(int sensor)
|
bool isAltSensor(int sensor)
|
||||||
{
|
{
|
||||||
return isSensorUnit(sensor, UNIT_DIST);
|
return isSensorUnit(sensor, UNIT_DIST) || isSensorUnit(sensor, UNIT_FEET);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isVoltsSensor(int sensor)
|
bool isVoltsSensor(int sensor)
|
||||||
|
|
|
@ -236,22 +236,26 @@ void displayTopBar()
|
||||||
/* Rx voltage */
|
/* Rx voltage */
|
||||||
altitude_icon_x = batt_icon_x+7*FW+3;
|
altitude_icon_x = batt_icon_x+7*FW+3;
|
||||||
if (g_model.frsky.voltsSource) {
|
if (g_model.frsky.voltsSource) {
|
||||||
TelemetryItem & voltsItem = telemetryItems[g_model.frsky.voltsSource-1];
|
uint8_t item = g_model.frsky.voltsSource-1;
|
||||||
|
if (item < MAX_SENSORS) {
|
||||||
|
TelemetryItem & voltsItem = telemetryItems[item];
|
||||||
if (voltsItem.isAvailable()) {
|
if (voltsItem.isAvailable()) {
|
||||||
putsTelemetryChannelValue(batt_icon_x+7*FW+2, BAR_Y+1, g_model.frsky.voltsSource-1, voltsItem.value, LEFT);
|
putsTelemetryChannelValue(batt_icon_x+7*FW+2, BAR_Y+1, item, voltsItem.value, LEFT);
|
||||||
altitude_icon_x = lcdLastPos+1;
|
altitude_icon_x = lcdLastPos+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Altitude */
|
/* Altitude */
|
||||||
if (g_model.frsky.altitudeSource) {
|
if (g_model.frsky.altitudeSource) {
|
||||||
TelemetryItem & altitudeItem = telemetryItems[g_model.frsky.altitudeSource-1];
|
uint8_t item = g_model.frsky.altitudeSource-1;
|
||||||
|
if (item < MAX_SENSORS) {
|
||||||
|
TelemetryItem & altitudeItem = telemetryItems[item];
|
||||||
if (altitudeItem.isAvailable()) {
|
if (altitudeItem.isAvailable()) {
|
||||||
LCD_ICON(altitude_icon_x, BAR_Y, ICON_ALTITUDE);
|
LCD_ICON(altitude_icon_x, BAR_Y, ICON_ALTITUDE);
|
||||||
int32_t value = altitudeItem.value;
|
int32_t value = altitudeItem.value / g_model.telemetrySensors[item].getPrecDivisor();
|
||||||
TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1];
|
putsValueWithUnit(altitude_icon_x+2*FW-1, BAR_Y+1, value, g_model.telemetrySensors[item].unit, LEFT);
|
||||||
if (sensor.prec) value /= sensor.prec == 2 ? 100 : 10;
|
}
|
||||||
putsValueWithUnit(altitude_icon_x+2*FW-1, BAR_Y+1, value, UNIT_METERS, LEFT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,12 +275,13 @@ void displayTopBar()
|
||||||
if (TRAINER_CONNECTED()) {
|
if (TRAINER_CONNECTED()) {
|
||||||
if (SLAVE_MODE()) {
|
if (SLAVE_MODE()) {
|
||||||
LCD_NOTIF_ICON(x, ICON_TRAINEE);
|
LCD_NOTIF_ICON(x, ICON_TRAINEE);
|
||||||
}
|
|
||||||
else {
|
|
||||||
LCD_NOTIF_ICON(x, ICON_TRAINER);
|
|
||||||
}
|
|
||||||
x -= 12;
|
x -= 12;
|
||||||
}
|
}
|
||||||
|
else if (IS_TRAINER_INPUT_VALID()) {
|
||||||
|
LCD_NOTIF_ICON(x, ICON_TRAINER);
|
||||||
|
x -= 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isFunctionActive(FUNCTION_LOGS)) {
|
if (isFunctionActive(FUNCTION_LOGS)) {
|
||||||
LCD_NOTIF_ICON(x, ICON_LOGS);
|
LCD_NOTIF_ICON(x, ICON_LOGS);
|
||||||
|
|
1
radio/src/lua/.gitignore
vendored
Normal file
1
radio/src/lua/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/lua_exports_*.inc
|
749
radio/src/lua/api_general.cpp
Normal file
749
radio/src/lua/api_general.cpp
Normal file
|
@ -0,0 +1,749 @@
|
||||||
|
/*
|
||||||
|
* Authors (alphabetical order)
|
||||||
|
* - Andre Bernet <bernet.andre@gmail.com>
|
||||||
|
* - Andreas Weitl
|
||||||
|
* - Bertrand Songis <bsongis@gmail.com>
|
||||||
|
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||||
|
* - Cameron Weeks <th9xer@gmail.com>
|
||||||
|
* - Erez Raviv
|
||||||
|
* - Gabriel Birkus
|
||||||
|
* - Jean-Pierre Parisy
|
||||||
|
* - Karl Szmutny
|
||||||
|
* - Michael Blandford
|
||||||
|
* - Michal Hlavinka
|
||||||
|
* - Pat Mackenzie
|
||||||
|
* - Philip Moss
|
||||||
|
* - Rob Thomson
|
||||||
|
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||||
|
* - 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 <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#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<DIM(luaSingleFields); ++n) {
|
||||||
|
if (!strcmp(name, luaSingleFields[n].name)) {
|
||||||
|
field.id = luaSingleFields[n].id;
|
||||||
|
if (flags & FIND_FIELD_DESC) {
|
||||||
|
strncpy(field.desc, luaSingleFields[n].desc, sizeof(field.desc)-1);
|
||||||
|
field.desc[sizeof(field.desc)-1] = '\0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
field.desc[0] = '\0';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// search in multiples
|
||||||
|
unsigned int len = strlen(name);
|
||||||
|
for (unsigned int n=0; n<DIM(luaMultipleFields); ++n) {
|
||||||
|
const char * fieldName = luaMultipleFields[n].name;
|
||||||
|
unsigned int fieldLen = strlen(fieldName);
|
||||||
|
if (!strncmp(name, fieldName, fieldLen)) {
|
||||||
|
unsigned int index;
|
||||||
|
if (len == fieldLen+1 && isdigit(name[fieldLen])) {
|
||||||
|
index = name[fieldLen] - '1';
|
||||||
|
}
|
||||||
|
else if (len == fieldLen+2 && isdigit(name[fieldLen]) && isdigit(name[fieldLen+1])) {
|
||||||
|
index = 10 * (name[fieldLen] - '0') + (name[fieldLen+1] - '1');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (index < luaMultipleFields[n].count) {
|
||||||
|
field.id = luaMultipleFields[n].id + index;
|
||||||
|
if (flags & FIND_FIELD_DESC) {
|
||||||
|
snprintf(field.desc, sizeof(field.desc)-1, luaMultipleFields[n].desc, index+1);
|
||||||
|
field.desc[sizeof(field.desc)-1] = '\0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
field.desc[0] = '\0';
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// search in telemetry
|
||||||
|
field.desc[0] = '\0';
|
||||||
|
for (int i=0; i<MAX_SENSORS; i++) {
|
||||||
|
if (isTelemetryFieldAvailable(i)) {
|
||||||
|
char sensorName[TELEM_LABEL_LEN+1];
|
||||||
|
int len = zchar2str(sensorName, g_model.telemetrySensors[i].label, TELEM_LABEL_LEN);
|
||||||
|
if (!strncmp(sensorName, name, len)) {
|
||||||
|
if (name[len] == '\0') {
|
||||||
|
field.id = MIXSRC_FIRST_TELEM + 3*i;
|
||||||
|
field.desc[0] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (name[len] == '-' && name[len+1] == '\0') {
|
||||||
|
field.id = MIXSRC_FIRST_TELEM + 3*i + 1;
|
||||||
|
field.desc[0] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (name[len] == '+' && name[len+1] == '\0') {
|
||||||
|
field.id = MIXSRC_FIRST_TELEM + 3*i + 2;
|
||||||
|
field.desc[0] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // not found
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function getFieldInfo(name)
|
||||||
|
|
||||||
|
Returns detailed information about field (source)
|
||||||
|
|
||||||
|
@param name (string) name of the field
|
||||||
|
|
||||||
|
@retval table information about requested field, table elements:
|
||||||
|
* `id` (number) field identifier
|
||||||
|
* `name` (string) field name
|
||||||
|
* `desc` (string) field description
|
||||||
|
|
||||||
|
@retval nil the requested field was not found
|
||||||
|
|
||||||
|
@status current Introduced in 2.0.8
|
||||||
|
*/
|
||||||
|
static int luaGetFieldInfo(lua_State *L)
|
||||||
|
{
|
||||||
|
const char * what = luaL_checkstring(L, 1);
|
||||||
|
LuaField field;
|
||||||
|
bool found = luaFindFieldByName(what, field, FIND_FIELD_DESC);
|
||||||
|
if (found) {
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushtableinteger(L, "id", field.id);
|
||||||
|
lua_pushtablestring(L, "name", what);
|
||||||
|
lua_pushtablestring(L, "desc", field.desc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function getValue(source)
|
||||||
|
|
||||||
|
Returns the value of a source.
|
||||||
|
|
||||||
|
The list of valid sources is available:
|
||||||
|
* for OpenTX 2.0.x at http://downloads-20.open-tx.org/firmware/lua_fields.txt
|
||||||
|
* for OpenTX 2.1.x at http://downloads-21.open-tx.org/firmware/lua_fields.txt
|
||||||
|
|
||||||
|
In OpenTX 2.1.x the telemetry sources no longer have a predefined name.
|
||||||
|
To get a telemetry value simply use its sensor name. For example:
|
||||||
|
* Altitude sensor has a name "Alt"
|
||||||
|
* to get the current altitude use the source "Alt"
|
||||||
|
* to get the minimum altitude use the source "Alt-", to get the maximum use "Alt+"
|
||||||
|
|
||||||
|
@param source can be an identifier (number) (which was obtained by the getFieldInfo())
|
||||||
|
or a name (string) of the source.
|
||||||
|
|
||||||
|
@retval value current source value (number). Zero is returned for:
|
||||||
|
* non-existing sources
|
||||||
|
* for all telemetry source when the telemetry stream is not received
|
||||||
|
|
||||||
|
@retval table GPS position is returned in a table:
|
||||||
|
* `lat` latitude, positive is North (number)
|
||||||
|
* `lon` longitude, positive is East (number)
|
||||||
|
|
||||||
|
@retval table GPS date/time is returned in a table, format is the same
|
||||||
|
as is returned from getDateTime()
|
||||||
|
|
||||||
|
@retval table Cells are returned in a table
|
||||||
|
(except where no cells were detected in which
|
||||||
|
case the returned value is 0):
|
||||||
|
* table has one item for each detected cell
|
||||||
|
* each item name is the cell number (1 to number of cells)
|
||||||
|
* each item value is the current cell voltage
|
||||||
|
|
||||||
|
@status current Introduced in 2.0.0, changed in 2.1.0
|
||||||
|
|
||||||
|
@notice Getting a value by its numerical identifier is faster then by its name.
|
||||||
|
*/
|
||||||
|
static int luaGetValue(lua_State *L)
|
||||||
|
{
|
||||||
|
int src = 0;
|
||||||
|
if (lua_isnumber(L, 1)) {
|
||||||
|
src = luaL_checkinteger(L, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// convert from field name to its id
|
||||||
|
const char *name = luaL_checkstring(L, 1);
|
||||||
|
LuaField field;
|
||||||
|
bool found = luaFindFieldByName(name, field);
|
||||||
|
if (found) {
|
||||||
|
src = field.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
luaGetValueAndPush(src);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function playFile(name)
|
||||||
|
|
||||||
|
Plays a file from the SD card
|
||||||
|
|
||||||
|
@param path (string) full path to wav file (i.e. “/SOUNDS/en/system/tada.wav”)
|
||||||
|
Introduced in 2.1.0: If you use a relative path, the current language is appended
|
||||||
|
to the path (example for English language: `/SOUNDS/en` is appended)
|
||||||
|
|
||||||
|
@status current Introduced in 2.0.0, changed in 2.1.0
|
||||||
|
*/
|
||||||
|
static int luaPlayFile(lua_State *L)
|
||||||
|
{
|
||||||
|
const char * filename = luaL_checkstring(L, 1);
|
||||||
|
if (filename[0] != '/') {
|
||||||
|
// relative sound file path - use current language dir for absolute path
|
||||||
|
char file[AUDIO_FILENAME_MAXLEN+1];
|
||||||
|
char * str = getAudioPath(file);
|
||||||
|
strncpy(str, filename, AUDIO_FILENAME_MAXLEN - (str-file));
|
||||||
|
file[AUDIO_FILENAME_MAXLEN] = 0;
|
||||||
|
PLAY_FILE(file, 0, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PLAY_FILE(filename, 0, 0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function playNumber(value, unit [, attributes])
|
||||||
|
|
||||||
|
Plays a numerical value (text to speech)
|
||||||
|
|
||||||
|
@param value (number) number to play. Value is interpreted as integer.
|
||||||
|
|
||||||
|
@param unit (number) unit identifier (see table todo)
|
||||||
|
|
||||||
|
@param attributes (unsigned number) possible values:
|
||||||
|
* `0 or not present` plays integral part of the number (for a number 123 it plays 123)
|
||||||
|
* `PREC1` plays a number with one decimal place (for a number 123 it plays 12.3)
|
||||||
|
* `PREC2` plays a number with two decimal places (for a number 123 it plays 1.23)
|
||||||
|
|
||||||
|
@status current Introduced in 2.0.0
|
||||||
|
*/
|
||||||
|
static int luaPlayNumber(lua_State *L)
|
||||||
|
{
|
||||||
|
int number = luaL_checkinteger(L, 1);
|
||||||
|
int unit = luaL_checkinteger(L, 2);
|
||||||
|
unsigned int att = luaL_optunsigned(L, 3, 0);
|
||||||
|
playNumber(number, unit, att, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function playDuration(duration [, hourFormat])
|
||||||
|
|
||||||
|
Plays a time value (text to speech)
|
||||||
|
|
||||||
|
@param duration (number) number of seconds to play. Only integral part is used.
|
||||||
|
|
||||||
|
@param hourFormat (number):
|
||||||
|
* `0 or not present` play format: minutes and seconds.
|
||||||
|
* `!= 0` play format: hours, minutes and seconds.
|
||||||
|
|
||||||
|
@status current Introduced in 2.1.0
|
||||||
|
*/
|
||||||
|
static int luaPlayDuration(lua_State *L)
|
||||||
|
{
|
||||||
|
int duration = luaL_checkinteger(L, 1);
|
||||||
|
bool playTime = (luaL_checkinteger(L, 2) != 0);
|
||||||
|
playDuration(duration, playTime ? PLAY_TIME : 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function playTone(frequency, duration, pause [, flags [, freqIncr]])
|
||||||
|
|
||||||
|
Plays a tone
|
||||||
|
|
||||||
|
@param frequency (number) tone frequency in Hz
|
||||||
|
|
||||||
|
@param duration (number) length of the tone in (TODO units)
|
||||||
|
|
||||||
|
@param pause (number) length of the pause in (TODO units)
|
||||||
|
|
||||||
|
@param flags (number):
|
||||||
|
* `0 or not present` play with normal priority.
|
||||||
|
* `PLAY_BACKGROUND` play in background (built in vario function used this context)
|
||||||
|
* `PLAY_NOW` play immediately
|
||||||
|
|
||||||
|
@param freqIncr (number) positive number increases the tone pitch (frequency with time),
|
||||||
|
negative number decreases it. Bigger number has more effect
|
||||||
|
|
||||||
|
@notice Minimum played frequency is 150Hz even if a lower value is specified.
|
||||||
|
|
||||||
|
@status current Introduced in 2.1.0
|
||||||
|
*/
|
||||||
|
static int luaPlayTone(lua_State *L)
|
||||||
|
{
|
||||||
|
int frequency = luaL_checkinteger(L, 1);
|
||||||
|
int length = luaL_checkinteger(L, 2);
|
||||||
|
int pause = luaL_checkinteger(L, 3);
|
||||||
|
int flags = luaL_optinteger(L, 4, 0);
|
||||||
|
int freqIncr = luaL_optinteger(L, 5, 0);
|
||||||
|
audioQueue.playTone(frequency, length, pause, flags, freqIncr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function killEvents(eventMask)
|
||||||
|
|
||||||
|
Cancels the key press propagation to the normal user interface algorithm.
|
||||||
|
|
||||||
|
@param eventMask (number) events to be suppressed
|
||||||
|
|
||||||
|
@status current Introduced in 2.0.0
|
||||||
|
|
||||||
|
@notice This function has currently no effect in OpenTX 2.1.x series
|
||||||
|
|
||||||
|
TODO table of events/masks
|
||||||
|
*/
|
||||||
|
static int luaKillEvents(lua_State *L)
|
||||||
|
{
|
||||||
|
int event = luaL_checkinteger(L, 1);
|
||||||
|
killEvents(event);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function GREY()
|
||||||
|
|
||||||
|
Returns gray value which can be used in lcd functions
|
||||||
|
|
||||||
|
@retval (number) a value that represents amount of *greyness* (from 0 to 15)
|
||||||
|
|
||||||
|
*/
|
||||||
|
static int luaGrey(lua_State *L)
|
||||||
|
{
|
||||||
|
int index = luaL_checkinteger(L, 1);
|
||||||
|
lua_pushunsigned(L, GREY(index));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function getGeneralSettings()
|
||||||
|
|
||||||
|
Returns (some of) the general radio settings
|
||||||
|
|
||||||
|
@retval table with elements:
|
||||||
|
* `battMin` radio battery range - minimum value
|
||||||
|
* `battMax` radio battery range - maximum value
|
||||||
|
* `imperial` set to a value different from 0 if the radio is set to the
|
||||||
|
IMPERIAL units
|
||||||
|
|
||||||
|
@status current Introduced in 2.0.6, `imperial` added in TODO
|
||||||
|
|
||||||
|
*/
|
||||||
|
static int luaGetGeneralSettings(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushtablenumber(L, "battMin", double(90+g_eeGeneral.vBatMin)/10);
|
||||||
|
lua_pushtablenumber(L, "battMax", double(120+g_eeGeneral.vBatMax)/10);
|
||||||
|
lua_pushtableinteger(L, "imperial", g_eeGeneral.imperial);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function popupInput(title, event, input, min, max)
|
||||||
|
|
||||||
|
Raises a popup on screen that allows uses input
|
||||||
|
|
||||||
|
@param title (string) text to display
|
||||||
|
|
||||||
|
@param event (number) the event variable that is passed in from the
|
||||||
|
Run function (key pressed)
|
||||||
|
|
||||||
|
@param input (number) value that can be adjusted by the +/- keys
|
||||||
|
|
||||||
|
@param min (number) min value that input can reach (by pressing the - key)
|
||||||
|
|
||||||
|
@param max (number) max value that input can reach
|
||||||
|
|
||||||
|
@retval number result of the input adjustment
|
||||||
|
|
||||||
|
@retval "OK" user pushed ENT key
|
||||||
|
|
||||||
|
@retval "CANCEL" user pushed EXIT key
|
||||||
|
|
||||||
|
@notice Use only from stand-alone and telemetry scripts.
|
||||||
|
|
||||||
|
@status current Introduced in 2.0.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function defaultStick(channel)
|
||||||
|
|
||||||
|
Get stick that is assigned to a channel. See Default Channel Order in General Settings.
|
||||||
|
|
||||||
|
@param channel (number) channel number (0 means CH1)
|
||||||
|
|
||||||
|
@retval number Stick assigned to this channel (from 0 to 3)
|
||||||
|
|
||||||
|
@status current Introduced in 2.0.0
|
||||||
|
*/
|
||||||
|
static int luaDefaultStick(lua_State *L)
|
||||||
|
{
|
||||||
|
uint8_t channel = luaL_checkinteger(L, 1);
|
||||||
|
lua_pushinteger(L, channel_order(channel+1)-1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*luadoc
|
||||||
|
@function defaultChannel(stick)
|
||||||
|
|
||||||
|
Get channel assigned to stick. See Default Channel Order in General Settings
|
||||||
|
|
||||||
|
@param stick (number) stick number (from 0 to 3)
|
||||||
|
|
||||||
|
@retval number channel assigned to this stick (from 0 to 3)
|
||||||
|
|
||||||
|
@retval nil stick not found
|
||||||
|
|
||||||
|
@status current Introduced in 2.0.0
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const luaL_Reg opentxLib[] = {
|
||||||
|
{ "getTime", luaGetTime },
|
||||||
|
{ "getDateTime", luaGetDateTime },
|
||||||
|
{ "getVersion", luaGetVersion },
|
||||||
|
{ "getGeneralSettings", luaGetGeneralSettings },
|
||||||
|
{ "getValue", luaGetValue },
|
||||||
|
{ "getFieldInfo", luaGetFieldInfo },
|
||||||
|
{ "playFile", luaPlayFile },
|
||||||
|
{ "playNumber", luaPlayNumber },
|
||||||
|
{ "playDuration", luaPlayDuration },
|
||||||
|
{ "playTone", luaPlayTone },
|
||||||
|
{ "popupInput", luaPopupInput },
|
||||||
|
{ "defaultStick", luaDefaultStick },
|
||||||
|
{ "defaultChannel", luaDefaultChannel },
|
||||||
|
{ "killEvents", luaKillEvents },
|
||||||
|
{ "GREY", luaGrey },
|
||||||
|
{ NULL, NULL } /* sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
const luaR_value_entry opentxConstants[] = {
|
||||||
|
{ "FULLSCALE", RESX },
|
||||||
|
{ "XXLSIZE", XXLSIZE },
|
||||||
|
{ "DBLSIZE", DBLSIZE },
|
||||||
|
{ "MIDSIZE", MIDSIZE },
|
||||||
|
{ "SMLSIZE", SMLSIZE },
|
||||||
|
{ "INVERS", INVERS },
|
||||||
|
{ "BOLD", BOLD },
|
||||||
|
{ "BLINK", BLINK },
|
||||||
|
{ "FIXEDWIDTH", FIXEDWIDTH },
|
||||||
|
{ "LEFT", LEFT },
|
||||||
|
{ "PREC1", PREC1 },
|
||||||
|
{ "PREC2", PREC2 },
|
||||||
|
{ "VALUE", 0 },
|
||||||
|
{ "SOURCE", 1 },
|
||||||
|
{ "REPLACE", MLTPX_REP },
|
||||||
|
{ "MIXSRC_FIRST_INPUT", MIXSRC_FIRST_INPUT },
|
||||||
|
{ "MIXSRC_Rud", MIXSRC_Rud },
|
||||||
|
{ "MIXSRC_Ele", MIXSRC_Ele },
|
||||||
|
{ "MIXSRC_Thr", MIXSRC_Thr },
|
||||||
|
{ "MIXSRC_Ail", MIXSRC_Ail },
|
||||||
|
{ "MIXSRC_SA", MIXSRC_SA },
|
||||||
|
{ "MIXSRC_SB", MIXSRC_SB },
|
||||||
|
{ "MIXSRC_SC", MIXSRC_SC },
|
||||||
|
{ "MIXSRC_SD", MIXSRC_SD },
|
||||||
|
{ "MIXSRC_SE", MIXSRC_SE },
|
||||||
|
{ "MIXSRC_SF", MIXSRC_SF },
|
||||||
|
{ "MIXSRC_SG", MIXSRC_SG },
|
||||||
|
{ "MIXSRC_SH", MIXSRC_SH },
|
||||||
|
{ "MIXSRC_CH1", MIXSRC_CH1 },
|
||||||
|
{ "SWSRC_LAST", SWSRC_LAST_LOGICAL_SWITCH },
|
||||||
|
{ "EVT_MENU_BREAK", EVT_KEY_BREAK(KEY_MENU) },
|
||||||
|
{ "EVT_PAGE_BREAK", EVT_KEY_BREAK(KEY_PAGE) },
|
||||||
|
{ "EVT_PAGE_LONG", EVT_KEY_LONG(KEY_PAGE) },
|
||||||
|
{ "EVT_ENTER_BREAK", EVT_KEY_BREAK(KEY_ENTER) },
|
||||||
|
{ "EVT_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) },
|
||||||
|
{ "EVT_EXIT_BREAK", EVT_KEY_BREAK(KEY_EXIT) },
|
||||||
|
{ "EVT_PLUS_BREAK", EVT_KEY_BREAK(KEY_PLUS) },
|
||||||
|
{ "EVT_MINUS_BREAK", EVT_KEY_BREAK(KEY_MINUS) },
|
||||||
|
{ "EVT_PLUS_FIRST", EVT_KEY_FIRST(KEY_PLUS) },
|
||||||
|
{ "EVT_MINUS_FIRST", EVT_KEY_FIRST(KEY_MINUS) },
|
||||||
|
{ "EVT_PLUS_REPT", EVT_KEY_REPT(KEY_PLUS) },
|
||||||
|
{ "EVT_MINUS_REPT", EVT_KEY_REPT(KEY_MINUS) },
|
||||||
|
{ "FILL_WHITE", FILL_WHITE },
|
||||||
|
{ "GREY_DEFAULT", GREY_DEFAULT },
|
||||||
|
{ "SOLID", SOLID },
|
||||||
|
{ "DOTTED", DOTTED },
|
||||||
|
{ "FORCE", FORCE },
|
||||||
|
{ "ERASE", ERASE },
|
||||||
|
{ "ROUND", ROUND },
|
||||||
|
{ "LCD_W", LCD_W },
|
||||||
|
{ "LCD_H", LCD_H },
|
||||||
|
{ "PLAY_NOW", PLAY_NOW },
|
||||||
|
{ "PLAY_BACKGROUND", PLAY_BACKGROUND },
|
||||||
|
{ "TIMEHOUR", TIMEHOUR },
|
||||||
|
{ NULL, 0 } /* sentinel */
|
||||||
|
};
|
352
radio/src/lua/api_lcd.cpp
Normal file
352
radio/src/lua/api_lcd.cpp
Normal file
|
@ -0,0 +1,352 @@
|
||||||
|
/*
|
||||||
|
* Authors (alphabetical order)
|
||||||
|
* - Andre Bernet <bernet.andre@gmail.com>
|
||||||
|
* - Andreas Weitl
|
||||||
|
* - Bertrand Songis <bsongis@gmail.com>
|
||||||
|
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||||
|
* - Cameron Weeks <th9xer@gmail.com>
|
||||||
|
* - Erez Raviv
|
||||||
|
* - Gabriel Birkus
|
||||||
|
* - Jean-Pierre Parisy
|
||||||
|
* - Karl Szmutny
|
||||||
|
* - Michael Blandford
|
||||||
|
* - Michal Hlavinka
|
||||||
|
* - Pat Mackenzie
|
||||||
|
* - Philip Moss
|
||||||
|
* - Rob Thomson
|
||||||
|
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||||
|
* - 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 <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#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<h-1; i++) {
|
||||||
|
lcd_hline(x+1, y+i, len);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(COLORLCD)
|
||||||
|
static int luaLcdDrawScreenTitle(lua_State *L)
|
||||||
|
{
|
||||||
|
if (!luaLcdAllowed) return 0;
|
||||||
|
const char * str = luaL_checkstring(L, 1);
|
||||||
|
int idx = luaL_checkinteger(L, 2);
|
||||||
|
int cnt = luaL_checkinteger(L, 3);
|
||||||
|
|
||||||
|
if (cnt) displayScreenIndex(idx-1, cnt, 0);
|
||||||
|
drawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT);
|
||||||
|
title(str);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int luaLcdDrawCombobox(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);
|
||||||
|
luaL_checktype(L, 4, LUA_TTABLE);
|
||||||
|
int count = luaL_len(L, 4); /* get size of table */
|
||||||
|
int idx = luaL_checkinteger(L, 5);
|
||||||
|
unsigned int flags = luaL_optunsigned(L, 6, 0);
|
||||||
|
if (idx >= 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<count; i++) {
|
||||||
|
lua_rawgeti(L, 4, i+1);
|
||||||
|
const char * item = luaL_checkstring(L, -1);
|
||||||
|
lcdDrawText(x+2, y+2+9*i, item, 0);
|
||||||
|
}
|
||||||
|
drawFilledRect(x+1, y+1+9*idx, w-11, 9);
|
||||||
|
drawFilledRect(x+w-10, y, 10, 11, SOLID, ERASE);
|
||||||
|
lcdDrawRect(x+w-10, y, 10, 11);
|
||||||
|
}
|
||||||
|
else if (flags & INVERS) {
|
||||||
|
drawFilledRect(x, y, w, 11);
|
||||||
|
drawFilledRect(x+w-9, y+1, 8, 9, SOLID, ERASE);
|
||||||
|
lua_rawgeti(L, 4, idx+1);
|
||||||
|
const char * item = luaL_checkstring(L, -1);
|
||||||
|
lcdDrawText(x+2, y+2, item, INVERS);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawFilledRect(x, y, w, 11, SOLID, ERASE);
|
||||||
|
lcdDrawRect(x, y, w, 11);
|
||||||
|
drawFilledRect(x+w-10, y+1, 9, 9, SOLID);
|
||||||
|
lua_rawgeti(L, 4, idx+1);
|
||||||
|
const char * item = luaL_checkstring(L, -1);
|
||||||
|
lcdDrawText(x+2, y+2, item, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lcd_hline(x+w-8, y+3, 6);
|
||||||
|
lcd_hline(x+w-8, y+5, 6);
|
||||||
|
lcd_hline(x+w-8, y+7, 6);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const luaL_Reg lcdLib[] = {
|
||||||
|
{ "lock", luaLcdLock },
|
||||||
|
{ "clear", luaLcdClear },
|
||||||
|
{ "getLastPos", luaLcdGetLastPos },
|
||||||
|
{ "drawPoint", luaLcdDrawPoint },
|
||||||
|
{ "drawLine", luaLcdDrawLine },
|
||||||
|
{ "drawRectangle", luaLcdDrawRectangle },
|
||||||
|
{ "drawFilledRectangle", luaLcdDrawFilledRectangle },
|
||||||
|
{ "drawGauge", luaLcdDrawGauge },
|
||||||
|
{ "drawText", luaLcdDrawText },
|
||||||
|
{ "drawTimer", luaLcdDrawTimer },
|
||||||
|
{ "drawNumber", luaLcdDrawNumber },
|
||||||
|
{ "drawChannel", luaLcdDrawChannel },
|
||||||
|
{ "drawSwitch", luaLcdDrawSwitch },
|
||||||
|
{ "drawSource", luaLcdDrawSource },
|
||||||
|
{ "drawPixmap", luaLcdDrawPixmap },
|
||||||
|
{ "drawScreenTitle", luaLcdDrawScreenTitle },
|
||||||
|
{ "drawCombobox", luaLcdDrawCombobox },
|
||||||
|
{ NULL, NULL } /* sentinel */
|
||||||
|
};
|
864
radio/src/lua/api_model.cpp
Normal file
864
radio/src/lua/api_model.cpp
Normal file
|
@ -0,0 +1,864 @@
|
||||||
|
/*
|
||||||
|
* Authors (alphabetical order)
|
||||||
|
* - Andre Bernet <bernet.andre@gmail.com>
|
||||||
|
* - Andreas Weitl
|
||||||
|
* - Bertrand Songis <bsongis@gmail.com>
|
||||||
|
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||||
|
* - Cameron Weeks <th9xer@gmail.com>
|
||||||
|
* - Erez Raviv
|
||||||
|
* - Gabriel Birkus
|
||||||
|
* - Jean-Pierre Parisy
|
||||||
|
* - Karl Szmutny
|
||||||
|
* - Michael Blandford
|
||||||
|
* - Michal Hlavinka
|
||||||
|
* - Pat Mackenzie
|
||||||
|
* - Philip Moss
|
||||||
|
* - Rob Thomson
|
||||||
|
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||||
|
* - 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 <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#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; i<MAX_INPUTS; i++) {
|
||||||
|
ExpoData * expo = expoAddress(i);
|
||||||
|
if (!expo->srcRaw || 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; i<MAX_INPUTS; i++) {
|
||||||
|
ExpoData * expo = expoAddress(i);
|
||||||
|
if (!expo->srcRaw || 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 (chn<MAX_INPUTS && getExpoMixCount(1)<MAX_EXPOS && idx<=count) {
|
||||||
|
idx = first + idx;
|
||||||
|
s_currCh = chn + 1;
|
||||||
|
insertExpoMix(1, idx);
|
||||||
|
ExpoData * expo = expoAddress(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(expo->name, 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; i<MAX_MIXERS; i++) {
|
||||||
|
MixData * mix = mixAddress(i);
|
||||||
|
if (!mix->srcRaw || 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; i<MAX_MIXERS; i++) {
|
||||||
|
MixData * mix = mixAddress(i);
|
||||||
|
if (!mix->srcRaw || 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 (chn<NUM_CHNOUT && getExpoMixCount(0)<MAX_MIXERS && idx<=count) {
|
||||||
|
idx += first;
|
||||||
|
s_currCh = chn+1;
|
||||||
|
insertExpoMix(0, idx);
|
||||||
|
MixData *mix = mixAddress(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(mix->name, 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; i<curveInfo.points+5; i++) {
|
||||||
|
lua_pushinteger(L, i);
|
||||||
|
lua_pushinteger(L, *point++);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
lua_settable(L, -3);
|
||||||
|
if (curveInfo.type == CURVE_TYPE_CUSTOM) {
|
||||||
|
lua_pushstring(L, "x");
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushinteger(L, 0);
|
||||||
|
lua_pushinteger(L, 0);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
for (int i=0; i<curveInfo.points+3; i++) {
|
||||||
|
lua_pushinteger(L, i+1);
|
||||||
|
lua_pushinteger(L, *point++);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
lua_pushinteger(L, curveInfo.points+4);
|
||||||
|
lua_pushinteger(L, 100);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_pushnil(L);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int luaModelGetCustomFunction(lua_State *L)
|
||||||
|
{
|
||||||
|
unsigned int idx = luaL_checkunsigned(L, 1);
|
||||||
|
if (idx < NUM_CFN) {
|
||||||
|
CustomFunctionData * cfn = &g_model.customFn[idx];
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushtableinteger(L, "switch", CFN_SWITCH(cfn));
|
||||||
|
lua_pushtableinteger(L, "func", CFN_FUNC(cfn));
|
||||||
|
if (CFN_FUNC(cfn) == FUNC_PLAY_TRACK || CFN_FUNC(cfn) == FUNC_BACKGND_MUSIC || CFN_FUNC(cfn) == FUNC_PLAY_SCRIPT) {
|
||||||
|
lua_pushtablenzstring(L, "name", cfn->play.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 */
|
||||||
|
};
|
786
radio/src/lua/interface.cpp
Normal file
786
radio/src/lua/interface.cpp
Normal file
|
@ -0,0 +1,786 @@
|
||||||
|
/*
|
||||||
|
* Authors (alphabetical order)
|
||||||
|
* - Andre Bernet <bernet.andre@gmail.com>
|
||||||
|
* - Andreas Weitl
|
||||||
|
* - Bertrand Songis <bsongis@gmail.com>
|
||||||
|
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||||
|
* - Cameron Weeks <th9xer@gmail.com>
|
||||||
|
* - Erez Raviv
|
||||||
|
* - Gabriel Birkus
|
||||||
|
* - Jean-Pierre Parisy
|
||||||
|
* - Karl Szmutny
|
||||||
|
* - Michael Blandford
|
||||||
|
* - Michal Hlavinka
|
||||||
|
* - Pat Mackenzie
|
||||||
|
* - Philip Moss
|
||||||
|
* - Rob Thomson
|
||||||
|
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||||
|
* - 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 <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "opentx.h"
|
||||||
|
#include "bin_allocator.h"
|
||||||
|
#include "lua/lua_api.h"
|
||||||
|
|
||||||
|
#if defined(LUA_COMPILER) && defined(SIMU)
|
||||||
|
#include <lundump.h>
|
||||||
|
#include <lstate.h>
|
||||||
|
#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.inputsCount<MAX_SCRIPT_INPUTS) {
|
||||||
|
uint8_t field = 0;
|
||||||
|
for (lua_pushnil(L); lua_next(L, -2) && field<5; lua_pop(L, 1), field++) {
|
||||||
|
switch (field) {
|
||||||
|
case 0:
|
||||||
|
luaL_checktype(L, -2, LUA_TNUMBER); // key is number
|
||||||
|
luaL_checktype(L, -1, LUA_TSTRING); // value is string
|
||||||
|
sid.inputs[sid.inputsCount].name = lua_tostring(L, -1);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
luaL_checktype(L, -2, LUA_TNUMBER); // key is number
|
||||||
|
luaL_checktype(L, -1, LUA_TNUMBER); // value is number
|
||||||
|
sid.inputs[sid.inputsCount].type = lua_tointeger(L, -1);
|
||||||
|
if (sid.inputs[sid.inputsCount].type == 0) {
|
||||||
|
sid.inputs[sid.inputsCount].min = -100;
|
||||||
|
sid.inputs[sid.inputsCount].max = 100;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sid.inputs[sid.inputsCount].max = MIXSRC_LAST_TELEM;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
luaL_checktype(L, -2, LUA_TNUMBER); // key is number
|
||||||
|
luaL_checktype(L, -1, LUA_TNUMBER); // value is number
|
||||||
|
sid.inputs[sid.inputsCount].min = lua_tointeger(L, -1);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
luaL_checktype(L, -2, LUA_TNUMBER); // key is number
|
||||||
|
luaL_checktype(L, -1, LUA_TNUMBER); // value is number
|
||||||
|
sid.inputs[sid.inputsCount].max = lua_tointeger(L, -1);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
luaL_checktype(L, -2, LUA_TNUMBER); // key is number
|
||||||
|
luaL_checktype(L, -1, LUA_TNUMBER); // value is number
|
||||||
|
sid.inputs[sid.inputsCount].def = lua_tointeger(L, -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sid.inputsCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int luaGetOutputs(ScriptInputsOutputs & sid)
|
||||||
|
{
|
||||||
|
if (!lua_istable(L, -1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sid.outputsCount = 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_TSTRING); // value is string
|
||||||
|
if (sid.outputsCount<MAX_SCRIPT_OUTPUTS) {
|
||||||
|
sid.outputs[sid.outputsCount++].name = lua_tostring(L, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaDisable()
|
||||||
|
{
|
||||||
|
POPUP_WARNING("Lua disabled!");
|
||||||
|
luaState = INTERPRETER_PANIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaClose()
|
||||||
|
{
|
||||||
|
if (L) {
|
||||||
|
PROTECT_LUA() {
|
||||||
|
lua_close(L); // this should not panic, but we make sure anyway
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we can only disable Lua for the rest of the session
|
||||||
|
luaDisable();
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
|
L = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaRegisterAll()
|
||||||
|
{
|
||||||
|
// Init lua
|
||||||
|
luaL_openlibs(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaInit()
|
||||||
|
{
|
||||||
|
luaClose();
|
||||||
|
if (luaState != INTERPRETER_PANIC) {
|
||||||
|
#if defined(USE_BIN_ALLOCATOR)
|
||||||
|
L = lua_newstate(bin_l_alloc, NULL); //we use our own allocator!
|
||||||
|
#else
|
||||||
|
L = lua_newstate(l_alloc, NULL); //we use Lua default allocator
|
||||||
|
#endif
|
||||||
|
if (L) {
|
||||||
|
// install our panic handler
|
||||||
|
lua_atpanic(L, &custom_lua_atpanic);
|
||||||
|
|
||||||
|
// protect libs and constants registration
|
||||||
|
PROTECT_LUA() {
|
||||||
|
luaRegisterAll();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// if we got panic during registration
|
||||||
|
// we disable Lua for this session
|
||||||
|
luaDisable();
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* log error and return */
|
||||||
|
luaDisable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaFree(ScriptInternalData & sid)
|
||||||
|
{
|
||||||
|
PROTECT_LUA() {
|
||||||
|
if (sid.run) {
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, sid.run);
|
||||||
|
sid.run = 0;
|
||||||
|
}
|
||||||
|
if (sid.background) {
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, sid.background);
|
||||||
|
sid.background = 0;
|
||||||
|
}
|
||||||
|
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
luaDisable();
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(LUA_COMPILER) && defined(SIMU)
|
||||||
|
static int luaDumpWriter(lua_State* L, const void* p, size_t size, void* u)
|
||||||
|
{
|
||||||
|
UNUSED(L);
|
||||||
|
UINT written;
|
||||||
|
FRESULT result = f_write((FIL *)u, p, size, &written);
|
||||||
|
return (result != FR_OK && !written);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void luaCompileAndSave(const char *filename)
|
||||||
|
{
|
||||||
|
FIL D;
|
||||||
|
char bytecodeName[1024];
|
||||||
|
strcpy(bytecodeName, filename);
|
||||||
|
strcat(bytecodeName, "c");
|
||||||
|
|
||||||
|
if (f_stat(bytecodeName, 0) == FR_OK) {
|
||||||
|
return; // compiled file already exists
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f_open(&D, bytecodeName, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) {
|
||||||
|
TRACE("Could not open Lua bytecode output file %s", bytecodeName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROTECT_LUA() {
|
||||||
|
if (luaL_loadfile(L, filename) == 0) {
|
||||||
|
lua_lock(L);
|
||||||
|
luaU_dump(L, getproto(L->top - 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<luaScriptsCount; i++) {
|
||||||
|
ScriptInternalData & sid = scriptInternalData[i];
|
||||||
|
if (sid.reference == SCRIPT_TELEMETRY_FIRST+index) {
|
||||||
|
return sid.state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SCRIPT_NOFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaLoadPermanentScripts()
|
||||||
|
{
|
||||||
|
luaScriptsCount = 0;
|
||||||
|
memset(scriptInternalData, 0, sizeof(scriptInternalData));
|
||||||
|
memset(scriptInputsOutputs, 0, sizeof(scriptInputsOutputs));
|
||||||
|
|
||||||
|
// Load model scripts
|
||||||
|
for (int i=0; i<MAX_SCRIPTS; i++) {
|
||||||
|
if (!luaLoadMixScript(i)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load custom function scripts
|
||||||
|
for (int i=0; i<NUM_CFN; i++) {
|
||||||
|
if (!luaLoadFunctionScript(i)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load custom telemetry scripts
|
||||||
|
for (int i=0; i<MAX_TELEMETRY_SCREENS; i++) {
|
||||||
|
if (!luaLoadTelemetryScript(i)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayLuaError(const char * title)
|
||||||
|
{
|
||||||
|
#if !defined(COLORLCD)
|
||||||
|
displayBox(title);
|
||||||
|
#endif
|
||||||
|
if (lua_warning_info[0]) {
|
||||||
|
char * split = strstr(lua_warning_info, ": ");
|
||||||
|
if (split) {
|
||||||
|
lcdDrawTextWithLen(WARNING_LINE_X, WARNING_LINE_Y+FH+3, lua_warning_info, split-lua_warning_info, SMLSIZE);
|
||||||
|
lcdDrawTextWithLen(WARNING_LINE_X, WARNING_LINE_Y+2*FH+2, split+2, lua_warning_info+LUA_WARNING_INFO_LEN-split, SMLSIZE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lcdDrawTextWithLen(WARNING_LINE_X, WARNING_LINE_Y+FH+3, lua_warning_info, 40, SMLSIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayAcknowledgeLuaError(uint8_t event)
|
||||||
|
{
|
||||||
|
s_warning_result = false;
|
||||||
|
displayLuaError(s_warning);
|
||||||
|
if (event == EVT_KEY_BREAK(KEY_EXIT)) {
|
||||||
|
s_warning = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaError(uint8_t error, bool acknowledge)
|
||||||
|
{
|
||||||
|
const char * errorTitle;
|
||||||
|
|
||||||
|
switch (error) {
|
||||||
|
case SCRIPT_SYNTAX_ERROR:
|
||||||
|
errorTitle = STR_SCRIPT_SYNTAX_ERROR;
|
||||||
|
break;
|
||||||
|
case SCRIPT_KILLED:
|
||||||
|
errorTitle = STR_SCRIPT_KILLED;
|
||||||
|
break;
|
||||||
|
case SCRIPT_PANIC:
|
||||||
|
errorTitle = STR_SCRIPT_PANIC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorTitle = STR_SCRIPT_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * msg = lua_tostring(L, -1);
|
||||||
|
if (msg) {
|
||||||
|
#if defined(SIMU)
|
||||||
|
if (!strncmp(msg, ".", 2)) msg += 1;
|
||||||
|
#endif
|
||||||
|
if (!strncmp(msg, "/SCRIPTS/", 9)) msg += 9;
|
||||||
|
strncpy(lua_warning_info, msg, LUA_WARNING_INFO_LEN);
|
||||||
|
lua_warning_info[LUA_WARNING_INFO_LEN] = '\0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_warning_info[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acknowledge) {
|
||||||
|
s_warning = errorTitle;
|
||||||
|
popupFunc = displayAcknowledgeLuaError;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
displayLuaError(errorTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaExec(const char *filename)
|
||||||
|
{
|
||||||
|
luaInit();
|
||||||
|
if (luaState != INTERPRETER_PANIC) {
|
||||||
|
standaloneScript.state = SCRIPT_NOFILE;
|
||||||
|
int result = luaLoad(filename, standaloneScript);
|
||||||
|
// TODO the same with run ...
|
||||||
|
if (result == SCRIPT_OK) {
|
||||||
|
luaState = INTERPRETER_RUNNING_STANDALONE_SCRIPT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
luaError(result);
|
||||||
|
luaState = INTERPRETER_RELOAD_PERMANENT_SCRIPTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaDoOneRunStandalone(uint8_t evt)
|
||||||
|
{
|
||||||
|
static uint8_t luaDisplayStatistics = false;
|
||||||
|
|
||||||
|
if (standaloneScript.state == SCRIPT_OK && standaloneScript.run) {
|
||||||
|
SET_LUA_INSTRUCTIONS_COUNT(MANUAL_SCRIPTS_MAX_INSTRUCTIONS);
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, standaloneScript.run);
|
||||||
|
lua_pushinteger(L, evt);
|
||||||
|
if (lua_pcall(L, 1, 1, 0) == 0) {
|
||||||
|
if (!lua_isnumber(L, -1)) {
|
||||||
|
if (instructionsPercent > 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; j<sio->inputsCount; 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<luaScriptsCount; i++) {
|
||||||
|
PROTECT_LUA() {
|
||||||
|
scriptWasRun |= luaDoOneRunPermanentScript(evt, i, scriptType);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
luaDisable();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
UNPROTECT_LUA();
|
||||||
|
//todo gc step between scripts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
luaDoGc();
|
||||||
|
return scriptWasRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
int luaGetMemUsed()
|
||||||
|
{
|
||||||
|
return (lua_gc(L, LUA_GCCOUNT, 0) << 10) + lua_gc(L, LUA_GCCOUNTB, 0);
|
||||||
|
}
|
|
@ -34,18 +34,42 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef luaapi_h
|
#ifndef lua_api_h
|
||||||
#define luaapi_h
|
#define lua_api_h
|
||||||
|
|
||||||
|
|
||||||
#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)
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(LUA)
|
#if defined(LUA)
|
||||||
|
|
||||||
|
#if !defined(SIMU)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <lrotable.h>
|
||||||
|
#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 {
|
struct ScriptInput {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
@ -98,11 +122,11 @@
|
||||||
void luaExec(const char * filename);
|
void luaExec(const char * filename);
|
||||||
void luaError(uint8_t error, bool acknowledge=true);
|
void luaError(uint8_t error, bool acknowledge=true);
|
||||||
int luaGetMemUsed();
|
int luaGetMemUsed();
|
||||||
|
void luaGetValueAndPush(int src);
|
||||||
#define luaGetCpuUsed(idx) scriptInternalData[idx].instructions
|
#define luaGetCpuUsed(idx) scriptInternalData[idx].instructions
|
||||||
uint8_t isTelemetryScriptAvailable(uint8_t index);
|
uint8_t isTelemetryScriptAvailable(uint8_t index);
|
||||||
#define LUA_LOAD_MODEL_SCRIPTS() luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
|
#define LUA_LOAD_MODEL_SCRIPTS() luaState |= INTERPRETER_RELOAD_PERMANENT_SCRIPTS
|
||||||
#define LUA_LOAD_MODEL_SCRIPT(idx) 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
|
// Lua PROTECT/UNPROTECT
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
struct our_longjmp {
|
struct our_longjmp {
|
||||||
|
@ -119,10 +143,11 @@
|
||||||
|
|
||||||
extern uint16_t maxLuaInterval;
|
extern uint16_t maxLuaInterval;
|
||||||
extern uint16_t maxLuaDuration;
|
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
|
File diff suppressed because it is too large
Load diff
|
@ -43,6 +43,9 @@ void perMain()
|
||||||
{
|
{
|
||||||
#if defined(SIMU)
|
#if defined(SIMU)
|
||||||
doMixerCalculations();
|
doMixerCalculations();
|
||||||
|
#endif
|
||||||
|
#if defined(LCD_ST7920)
|
||||||
|
uint8_t lcdstate=0;
|
||||||
#endif
|
#endif
|
||||||
uint16_t t0 = getTmr16KHz();
|
uint16_t t0 = getTmr16KHz();
|
||||||
int16_t delta = (nextMixerEndTime - lastMixerDuration) - t0;
|
int16_t delta = (nextMixerEndTime - lastMixerDuration) - t0;
|
||||||
|
@ -129,6 +132,7 @@ void perMain()
|
||||||
const char *warn = s_warning;
|
const char *warn = s_warning;
|
||||||
uint8_t menu = s_menu_count;
|
uint8_t menu = s_menu_count;
|
||||||
|
|
||||||
|
if (IS_LCD_REFRESH_ALLOWED()) { // No need to redraw until lcdRefresh_ST7920(0) below completely refreshes the display.
|
||||||
lcdClear();
|
lcdClear();
|
||||||
if (menuEvent) {
|
if (menuEvent) {
|
||||||
m_posVert = menuEvent == EVT_ENTRY_UP ? g_menuPos[g_menuStackPtr] : 0;
|
m_posVert = menuEvent == EVT_ENTRY_UP ? g_menuPos[g_menuStackPtr] : 0;
|
||||||
|
@ -139,7 +143,6 @@ void perMain()
|
||||||
}
|
}
|
||||||
g_menuStack[g_menuStackPtr]((warn || menu) ? 0 : evt);
|
g_menuStack[g_menuStackPtr]((warn || menu) ? 0 : evt);
|
||||||
|
|
||||||
|
|
||||||
if (warn) DISPLAY_WARNING(evt);
|
if (warn) DISPLAY_WARNING(evt);
|
||||||
#if defined(NAVIGATION_MENUS)
|
#if defined(NAVIGATION_MENUS)
|
||||||
if (menu) {
|
if (menu) {
|
||||||
|
@ -149,12 +152,17 @@ void perMain()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
drawStatusLine();
|
drawStatusLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(LCD_ST7920)
|
||||||
|
lcdstate = lcdRefresh_ST7920(0);
|
||||||
|
#else
|
||||||
lcdRefresh();
|
lcdRefresh();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // defined(GUI)
|
||||||
|
|
||||||
if (SLAVE_MODE()) {
|
if (SLAVE_MODE()) {
|
||||||
JACK_PPM_OUT();
|
JACK_PPM_OUT();
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,7 @@ int16_t applyLimits(uint8_t channel, int32_t value)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int16_t ofs = LIMIT_OFS_RESX(lim);
|
int16_t ofs = LIMIT_OFS_RESX(lim);
|
||||||
int16_t lim_p = LIMIT_MAX_RESX(lim);
|
int16_t lim_p = LIMIT_MAX_RESX(lim);
|
||||||
int16_t lim_n = LIMIT_MIN_RESX(lim);
|
int16_t lim_n = LIMIT_MIN_RESX(lim);
|
||||||
|
@ -1107,7 +1108,7 @@ void evalMixes(uint8_t tick10ms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PCBGRUVIN9X) && defined(DEBUG) && !defined(VOICE)
|
#if defined(CPU2560) && defined(DEBUG) && !defined(VOICE)
|
||||||
PORTH &= ~0x40; // PORTH:6 HIGH->LOW signals end of mixer interrupt
|
PORTH &= ~0x40; // PORTH:6 HIGH->LOW signals end of mixer interrupt
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -560,7 +560,7 @@ enum PotsWarnMode {
|
||||||
TRAINER_MODULE
|
TRAINER_MODULE
|
||||||
};
|
};
|
||||||
enum TrainerMode {
|
enum TrainerMode {
|
||||||
TRAINER_MODE_MASTER,
|
TRAINER_MODE_MASTER_TRAINER_JACK,
|
||||||
TRAINER_MODE_SLAVE,
|
TRAINER_MODE_SLAVE,
|
||||||
TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE,
|
TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE,
|
||||||
TRAINER_MODE_MASTER_CPPM_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(const char *label, uint8_t unit=UNIT_RAW, uint8_t prec=0);
|
||||||
void init(uint16_t id);
|
void init(uint16_t id);
|
||||||
bool isAvailable();
|
bool isAvailable() const;
|
||||||
int32_t getValue(int32_t value, uint8_t unit, uint8_t prec) const;
|
int32_t getValue(int32_t value, uint8_t unit, uint8_t prec) const;
|
||||||
bool isConfigurable();
|
bool isConfigurable() const;
|
||||||
bool isPrecConfigurable();
|
bool isPrecConfigurable() const;
|
||||||
|
int32_t getPrecMultiplier() const;
|
||||||
|
int32_t getPrecDivisor() const;
|
||||||
}) TelemetrySensor;
|
}) TelemetrySensor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2201,11 +2203,7 @@ enum RFProtocols {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(MODULE_D16_EU_ONLY_SUPPORT)
|
#define HAS_RF_PROTOCOL_FAILSAFE(protocol) ((protocol) == RF_PROTO_X16)
|
||||||
#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
|
|
||||||
|
|
||||||
enum DSM2Protocols {
|
enum DSM2Protocols {
|
||||||
DSM2_PROTO_LP45,
|
DSM2_PROTO_LP45,
|
||||||
|
|
|
@ -1173,10 +1173,10 @@ extern const char vers_stamp[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern uint8_t g_vbat100mV;
|
extern uint8_t g_vbat100mV;
|
||||||
#if defined(CPUARM)
|
#if defined(PCBTARANIS)
|
||||||
#define GET_TXBATT_BARS() (min(10, 10 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin)))
|
#define GET_TXBATT_BARS() (limit<int8_t>(0, 10 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin), 10))
|
||||||
#else
|
#else
|
||||||
#define GET_TXBATT_BARS() (limit<uint8_t>(2, 20 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin), 20))
|
#define GET_TXBATT_BARS() (limit<int8_t>(2, 20 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin), 20))
|
||||||
#endif
|
#endif
|
||||||
#define IS_TXBATT_WARNING() (g_vbat100mV <= g_eeGeneral.vBatWarn)
|
#define IS_TXBATT_WARNING() (g_vbat100mV <= g_eeGeneral.vBatWarn)
|
||||||
|
|
||||||
|
@ -1783,7 +1783,7 @@ void varioWakeup();
|
||||||
extern void usbPluggedIn();
|
extern void usbPluggedIn();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "lua_api.h"
|
#include "lua/lua_api.h"
|
||||||
|
|
||||||
#if defined(SDCARD)
|
#if defined(SDCARD)
|
||||||
enum ClipboardType {
|
enum ClipboardType {
|
||||||
|
|
|
@ -231,8 +231,7 @@ void setupPulsesPXX(unsigned int port)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (i < sendUpperChannels) {
|
if (i < sendUpperChannels) {
|
||||||
int channel = 8 + g_model.moduleData[port].channelsStart + i;
|
int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[8+i];
|
||||||
int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[channel];
|
|
||||||
if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
|
if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
|
||||||
pulseValue = 4095;
|
pulseValue = 4095;
|
||||||
}
|
}
|
||||||
|
@ -240,13 +239,12 @@ void setupPulsesPXX(unsigned int port)
|
||||||
pulseValue = 2048;
|
pulseValue = 2048;
|
||||||
}
|
}
|
||||||
else {
|
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);
|
pulseValue = limit(2049, (failsafeValue * 512 / 682) + 3072, 4094);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int channel = g_model.moduleData[port].channelsStart + i;
|
int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[i];
|
||||||
int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[channel];
|
|
||||||
if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
|
if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
|
||||||
pulseValue = 2047;
|
pulseValue = 2047;
|
||||||
}
|
}
|
||||||
|
@ -254,7 +252,7 @@ void setupPulsesPXX(unsigned int port)
|
||||||
pulseValue = 0;
|
pulseValue = 0;
|
||||||
}
|
}
|
||||||
else {
|
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);
|
pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,7 +287,7 @@ void setupPulsesPXX(unsigned int port)
|
||||||
/* CRC16 */
|
/* CRC16 */
|
||||||
putPcmByte(0, port);
|
putPcmByte(0, port);
|
||||||
pulseValue = modulePulsesData[port].pxx.pcmCrc;
|
pulseValue = modulePulsesData[port].pxx.pcmCrc;
|
||||||
putPcmByte(pulseValue>>8, port);
|
putPcmByte(pulseValue >> 8, port);
|
||||||
putPcmByte(pulseValue, port);
|
putPcmByte(pulseValue, port);
|
||||||
|
|
||||||
/* Sync */
|
/* Sync */
|
||||||
|
|
|
@ -60,11 +60,7 @@ const char * sdCheckAndCreateDirectory(const char * path)
|
||||||
|
|
||||||
bool isFileAvailable(const char * path)
|
bool isFileAvailable(const char * path)
|
||||||
{
|
{
|
||||||
FILINFO info;
|
return f_stat(path, 0) == FR_OK;
|
||||||
TCHAR lfn[_MAX_LFN + 1];
|
|
||||||
info.lfname = lfn;
|
|
||||||
info.lfsize = sizeof(lfn);
|
|
||||||
return f_stat(path, &info) == FR_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFileAvailable(const char * filename, const char * directory)
|
bool isFileAvailable(const char * filename, const char * directory)
|
||||||
|
|
|
@ -611,22 +611,25 @@ const pm_char * eeRestoreModel(uint8_t i_fileDst, char *model_name)
|
||||||
eepromEraseBlock(address+EEPROM_BLOCK_SIZE);
|
eepromEraseBlock(address+EEPROM_BLOCK_SIZE);
|
||||||
|
|
||||||
// write header
|
// write header
|
||||||
EepromFileHeader header = { uint16_t(i_fileDst+1), size };
|
EepromFileHeader * header = (EepromFileHeader *)eepromWriteBuffer;
|
||||||
eepromWrite(address, (uint8_t *)&header, sizeof(header));
|
header->fileIndex = i_fileDst+1;
|
||||||
address += sizeof(header);
|
header->size = size;
|
||||||
|
|
||||||
|
int offset = 4;
|
||||||
|
|
||||||
// write model
|
// write model
|
||||||
while (size > 0) {
|
do {
|
||||||
uint16_t blockSize = min<uint16_t>(size, EEPROM_BUFFER_SIZE);
|
uint16_t blockSize = min<uint16_t>(size, EEPROM_BUFFER_SIZE-offset);
|
||||||
result = f_read(&restoreFile, eepromWriteBuffer, blockSize, &read);
|
result = f_read(&restoreFile, eepromWriteBuffer+offset, blockSize, &read);
|
||||||
if (result != FR_OK || read != blockSize) {
|
if (result != FR_OK || read != blockSize) {
|
||||||
f_close(&g_oLogFile);
|
f_close(&g_oLogFile);
|
||||||
return SDCARD_ERROR(result);
|
return SDCARD_ERROR(result);
|
||||||
}
|
}
|
||||||
eepromWrite(address, eepromWriteBuffer, blockSize);
|
eepromWrite(address, eepromWriteBuffer, blockSize+offset);
|
||||||
size -= blockSize;
|
size -= blockSize;
|
||||||
address += blockSize;
|
address += EEPROM_BUFFER_SIZE;
|
||||||
}
|
offset = 0;
|
||||||
|
} while (size > 0);
|
||||||
|
|
||||||
// write FAT
|
// write FAT
|
||||||
eepromHeader.files[i_fileDst+1].exists = 1;
|
eepromHeader.files[i_fileDst+1].exists = 1;
|
||||||
|
|
|
@ -150,17 +150,65 @@ void lcdSetRefVolt(uint8_t val)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(LCD_ST7920)
|
||||||
|
void lcdRefresh(){
|
||||||
|
lcdRefresh_ST7920(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t lcdRefresh_ST7920(uint8_t full)
|
||||||
|
{
|
||||||
|
#else
|
||||||
void lcdRefresh()
|
void lcdRefresh()
|
||||||
{
|
{
|
||||||
|
#endif
|
||||||
LCD_LOCK();
|
LCD_LOCK();
|
||||||
#if defined(LCD_ST7920)
|
#if defined(LCD_ST7920)
|
||||||
|
static uint8_t state;
|
||||||
|
uint8_t yst,yend;
|
||||||
uint8_t x_addr = 0;
|
uint8_t x_addr = 0;
|
||||||
uint8_t y_addr = 0;
|
uint8_t y_addr = 0;
|
||||||
uint16_t line_offset = 0;
|
uint16_t line_offset = 0;
|
||||||
uint8_t col_offset = 0;
|
uint8_t col_offset = 0;
|
||||||
uint16_t byte_offset = 0;
|
|
||||||
uint8_t bit_count = 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<yend; y++) {
|
||||||
x_addr = 0;
|
x_addr = 0;
|
||||||
//Convert coordinates to weirdly-arranged 128x64 screen (the ST7920 is mapped for 256x32 displays)
|
//Convert coordinates to weirdly-arranged 128x64 screen (the ST7920 is mapped for 256x32 displays)
|
||||||
if (y > 31) {
|
if (y > 31) {
|
||||||
|
@ -180,10 +228,18 @@ void lcdRefresh()
|
||||||
col_offset = 1 << bit_count; //Build a value for a AND operation with the vorrect bitposition
|
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
|
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)
|
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
|
p=displayBuf + 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
|
// 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 left-most position of the byte to the ST7920
|
// the position of the LSB is the right-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);
|
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<<OUT_C_LCD_E);
|
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
|
||||||
_delay_us(8);
|
_delay_us(8);
|
||||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
|
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
|
||||||
|
@ -216,4 +272,8 @@ void lcdRefresh()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LCD_UNLOCK();
|
LCD_UNLOCK();
|
||||||
|
#if defined(LCD_ST7920)
|
||||||
|
return state;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
120
radio/src/targets/Horus/usbd_desc.h~origin_next
Normal file
120
radio/src/targets/Horus/usbd_desc.h~origin_next
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file usbd_desc.h
|
||||||
|
* @author MCD Application Team
|
||||||
|
* @version V1.1.0
|
||||||
|
* @date 19-March-2012
|
||||||
|
* @brief header file for the usbd_desc.c file
|
||||||
|
******************************************************************************
|
||||||
|
* @attention
|
||||||
|
*
|
||||||
|
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||||
|
*
|
||||||
|
* 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****/
|
|
@ -4,6 +4,5 @@ MEGA2560 board
|
||||||
DIY radio wih :
|
DIY radio wih :
|
||||||
- Arduino MEGA2560 or compatible
|
- Arduino MEGA2560 or compatible
|
||||||
- Gruvin9x features (soft-off, SD-Card, RTC, haptic, voice, rotary encoders)
|
- Gruvin9x features (soft-off, SD-Card, RTC, haptic, voice, rotary encoders)
|
||||||
- LCD 128x64 Artronic (ST7565R) or Zolen (ST7565P)
|
- LCD 128x64 8 bits parallel mode
|
||||||
- Aurora9 or T9X gimballs
|
|
||||||
- home made case
|
- home made case
|
|
@ -42,13 +42,17 @@ inline void boardInit()
|
||||||
{
|
{
|
||||||
// Set up I/O port data directions and initial states (unused pin setting : input, pull-up on)
|
// Set up I/O port data directions and initial states (unused pin setting : input, pull-up on)
|
||||||
DDRA = 0b11111111; PORTA = 0b00000000; // LCD data
|
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
|
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
|
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
|
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
|
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
|
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
|
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)
|
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
|
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
|
||||||
|
|
|
@ -111,7 +111,7 @@ void sdPoll10ms(void);
|
||||||
# define INP_L_Trainer 7
|
# define INP_L_Trainer 7
|
||||||
|
|
||||||
// Servitudes driver
|
// 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_PPM 6
|
||||||
# define OUT_B_SIM_CTL 5
|
# define OUT_B_SIM_CTL 5
|
||||||
# define OUT_B_BUZZER 4
|
# define OUT_B_BUZZER 4
|
||||||
|
|
|
@ -66,111 +66,105 @@
|
||||||
#if defined(REVA)
|
#if defined(REVA)
|
||||||
const uint8_t Lcd_lookup[] =
|
const uint8_t Lcd_lookup[] =
|
||||||
{
|
{
|
||||||
0x00,0x01,0x80,0x81,0x40,0x41,0xC0,0xC1,0x20,0x21,0xA0,0xA1,0x60,0x61,0xE0,0xE1,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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
|
0x1E,0x1F,0x9E,0x9F,0x5E,0x5F,0xDE,0xDF,0x3E,0x3F,0xBE,0xBF,0x7E,0x7F,0xFE,0xFF
|
||||||
} ;
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void lcdSendCtl(uint8_t val)
|
void lcdSendCtl(uint8_t val)
|
||||||
{
|
{
|
||||||
register Pio *pioptr ;
|
register Pio *pioptr;
|
||||||
|
|
||||||
#if defined(REVA)
|
#if defined(REVA)
|
||||||
pioptr = PIOC ;
|
pioptr = PIOC;
|
||||||
pioptr->PIO_CODR = LCD_CS1 ; // Select LCD
|
pioptr->PIO_CODR = LCD_CS1; // Select LCD
|
||||||
pioptr->PIO_CODR = LCD_A0 ; // Control
|
pioptr->PIO_CODR = LCD_A0; // Control
|
||||||
pioptr->PIO_CODR = LCD_RnW ; // Write
|
pioptr->PIO_CODR = LCD_RnW; // Write
|
||||||
pioptr->PIO_ODSR = Lcd_lookup[val] ;
|
pioptr->PIO_ODSR = Lcd_lookup[val];
|
||||||
#else
|
#else
|
||||||
pioptr = PIOC ;
|
pioptr = PIOC;
|
||||||
#if !defined(REVX)
|
#if !defined(REVX)
|
||||||
pioptr->PIO_CODR = LCD_CS1 ; // Select LCD
|
pioptr->PIO_CODR = LCD_CS1; // Select LCD
|
||||||
#endif
|
#endif
|
||||||
PIOA->PIO_CODR = LCD_A0 ;
|
PIOA->PIO_CODR = LCD_A0;
|
||||||
#if !defined(REVX)
|
#if !defined(REVX)
|
||||||
pioptr->PIO_CODR = LCD_RnW ; // Write
|
pioptr->PIO_CODR = LCD_RnW; // Write
|
||||||
#endif
|
#endif
|
||||||
pioptr->PIO_ODSR = val ;
|
pioptr->PIO_ODSR = val;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pioptr->PIO_SODR = LCD_E ; // Start E pulse
|
pioptr->PIO_SODR = LCD_E; // Start E pulse
|
||||||
// Need a delay here (250nS)
|
// 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)
|
while ( TC0->TC_CHANNEL[0].TC_CV < 9 ) // Value depends on MCK/2 (used 18MHz)
|
||||||
{
|
{
|
||||||
// Wait
|
// Wait
|
||||||
}
|
}
|
||||||
pioptr->PIO_CODR = LCD_E ; // End E pulse
|
pioptr->PIO_CODR = LCD_E; // End E pulse
|
||||||
#if defined(REVA)
|
#if defined(REVA)
|
||||||
pioptr->PIO_SODR = LCD_A0 ; // Data
|
pioptr->PIO_SODR = LCD_A0; // Data
|
||||||
#else
|
#else
|
||||||
PIOA->PIO_SODR = LCD_A0 ; // Data
|
PIOA->PIO_SODR = LCD_A0; // Data
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(REVX)
|
#if !defined(REVX)
|
||||||
pioptr->PIO_SODR = LCD_CS1 ; // Deselect LCD
|
pioptr->PIO_SODR = LCD_CS1; // Deselect LCD
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcdInit()
|
void lcdInit()
|
||||||
{
|
{
|
||||||
register Pio *pioptr ;
|
register Pio *pioptr;
|
||||||
// /home/thus/txt/datasheets/lcd/KS0713.pdf
|
// /home/thus/txt/datasheets/lcd/KS0713.pdf
|
||||||
// ~/txt/flieger/ST7565RV17.pdf from http://www.glyn.de/content.asp?wdid=132&sid=
|
// ~/txt/flieger/ST7565RV17.pdf from http://www.glyn.de/content.asp?wdid=132&sid=
|
||||||
|
|
||||||
// read the inputs, and lock the LCD lines
|
// read the inputs, and lock the LCD lines
|
||||||
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
|
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
|
||||||
lcdLock = 1 ;
|
lcdLock = 1;
|
||||||
|
|
||||||
#if defined(REVA)
|
#if defined(REVA)
|
||||||
pioptr = PIOC ;
|
pioptr = PIOC;
|
||||||
pioptr->PIO_PER = 0x0C00B0FFL ; // Enable bits 27,26,15,13,12,7-0
|
pioptr->PIO_PER = 0x0C00B0FFL; // Enable bits 27,26,15,13,12,7-0
|
||||||
pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_A0 ;
|
pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_A0;
|
||||||
pioptr->PIO_SODR = LCD_RES | LCD_CS1 ;
|
pioptr->PIO_SODR = LCD_RES | LCD_CS1;
|
||||||
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
|
||||||
pioptr->PIO_OWER = 0x000000FFL ; // Allow write to ls 8 bits in ODSR
|
pioptr->PIO_OWER = 0x000000FFL; // Allow write to ls 8 bits in ODSR
|
||||||
#else
|
#else
|
||||||
configure_pins( LCD_A0, PIN_ENABLE | PIN_LOW | PIN_OUTPUT | PIN_PORTA | PIN_NO_PULLUP ) ;
|
configure_pins( LCD_A0, PIN_ENABLE | PIN_LOW | PIN_OUTPUT | PIN_PORTA | PIN_NO_PULLUP );
|
||||||
pioptr = PIOC ;
|
pioptr = PIOC;
|
||||||
#if defined(REVX)
|
#if defined(REVX)
|
||||||
pioptr->PIO_PER = PIO_PC27 | PIO_PC12 | 0xFF ;
|
pioptr->PIO_PER = PIO_PC27 | PIO_PC12 | 0xFF;
|
||||||
pioptr->PIO_CODR = LCD_E ;
|
pioptr->PIO_CODR = LCD_E;
|
||||||
pioptr->PIO_CODR = LCD_RnW | LCD_CS1 ; // No longer needed, used elsewhere
|
pioptr->PIO_CODR = LCD_RnW | LCD_CS1; // No longer needed, used elsewhere
|
||||||
#else
|
#else
|
||||||
pioptr->PIO_PER = PIO_PC27 | PIO_PC26 | PIO_PC13 | PIO_PC12 | 0xFF ;
|
pioptr->PIO_PER = PIO_PC27 | PIO_PC26 | PIO_PC13 | PIO_PC12 | 0xFF;
|
||||||
pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_CS1 ;
|
pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_CS1;
|
||||||
#endif
|
#endif
|
||||||
pioptr->PIO_SODR = LCD_RES ;
|
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_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
|
pioptr->PIO_OWER = 0x000000FFL; // Allow write to ls 8 bits in ODSR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pioptr->PIO_CODR = LCD_RES ; // Reset LCD
|
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)
|
pioptr->PIO_CODR = LCD_RES; // Reset LCD
|
||||||
while ( TC0->TC_CHANNEL[0].TC_CV < 200 ) // > 10us, Value depends on MCK/2 (used 18MHz)
|
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)
|
||||||
// Wait
|
pioptr->PIO_SODR = LCD_RES; // Remove LCD reset
|
||||||
}
|
while ( TC0->TC_CHANNEL[0].TC_CV < 27000 ) ; // 1500us, Value depends on MCK/2 (used 18MHz)
|
||||||
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
|
|
||||||
}
|
|
||||||
lcdSendCtl(0xe2); //Initialize the internal functions
|
lcdSendCtl(0xe2); //Initialize the internal functions
|
||||||
lcdSendCtl(0xae); //DON = 0: display OFF
|
lcdSendCtl(0xae); //DON = 0: display OFF
|
||||||
lcdSendCtl(0xa1); //ADC = 1: reverse direction(SEG132->SEG1)
|
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(0x25); //Select int resistance ratio R2 R1 R0 =5
|
||||||
lcdSendCtl(0x81); //Set reference voltage Mode
|
lcdSendCtl(0x81); //Set reference voltage Mode
|
||||||
lcdSendCtl(0x22); // 24 SV5 SV4 SV3 SV2 SV1 SV0 = 0x18
|
lcdSendCtl(0x22); // 24 SV5 SV4 SV3 SV2 SV1 SV0 = 0x18
|
||||||
lcdSendCtl(0xAF); //DON = 1: display ON
|
|
||||||
// g_eeGeneral.contrast = 0x22;
|
|
||||||
|
|
||||||
#if defined(REVA)
|
#if defined(REVX)
|
||||||
pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
|
// 200mS delay (only if not wdt reset)
|
||||||
pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
|
if ( ( ( ResetReason & RSTC_SR_RSTTYP ) != (2 << 8) ) && !unexpectedShutdown ) {
|
||||||
pioptr->PIO_ODSR = 0 ; // Drive D0 low
|
for (uint32_t j = 0; j < 100; j += 1 ) {
|
||||||
#else
|
TC0->TC_CHANNEL[0].TC_CCR = 5; // Enable clock and trigger it (may only need trigger)
|
||||||
pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
|
while ( TC0->TC_CHANNEL[0].TC_CV < 36000 ) {
|
||||||
pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
|
// Value depends on MCK/2 (used 18MHz) give 2mS delay
|
||||||
pioptr->PIO_ODSR = 0 ; // Drive D0 low
|
wdt_reset(); // Wait
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#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)
|
void lcdSetRefVolt(uint8_t val)
|
||||||
{
|
{
|
||||||
register Pio *pioptr ;
|
register Pio *pioptr;
|
||||||
pioptr = PIOC ;
|
pioptr = PIOC;
|
||||||
|
|
||||||
// read the inputs, and lock the LCD lines
|
// read the inputs, and lock the LCD lines
|
||||||
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
|
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);
|
lcdSendCtl(0x81);
|
||||||
if ( val == 0 )
|
if ( val == 0 )
|
||||||
{
|
{
|
||||||
val = 0x22 ;
|
val = 0x22;
|
||||||
}
|
}
|
||||||
lcdSendCtl(val);
|
lcdSendCtl(val);
|
||||||
|
|
||||||
#if defined(REVA)
|
#if defined(REVA)
|
||||||
pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
|
pioptr->PIO_ODR = 0x000000FEL; // Set bits 2, 3, 4, 5 input
|
||||||
pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
|
pioptr->PIO_PUER = 0x000000FEL; // Set bits 2, 3, 4, 5 with pullups
|
||||||
#else
|
#else
|
||||||
pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
|
pioptr->PIO_ODR = 0x000000FEL; // Set bits 1, 3, 4, 5 input
|
||||||
pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
|
pioptr->PIO_PUER = 0x000000FEL; // Set bits 1, 3, 4, 5 with pullups
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pioptr->PIO_ODSR = lcdInputs; // Drive D0 low
|
pioptr->PIO_ODSR = 0; // Drive D0 low
|
||||||
lcdLock = 0 ;
|
lcdLock = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcdRefresh()
|
void lcdRefresh()
|
||||||
|
@ -251,7 +258,7 @@ void lcdRefresh()
|
||||||
|
|
||||||
// read the inputs, and lock the LCD lines
|
// read the inputs, and lock the LCD lines
|
||||||
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
|
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
|
||||||
lcdLock = 1 ;
|
lcdLock = 1;
|
||||||
|
|
||||||
pioptr = PIOC;
|
pioptr = PIOC;
|
||||||
#if defined(REVA)
|
#if defined(REVA)
|
||||||
|
@ -264,13 +271,13 @@ void lcdRefresh()
|
||||||
lcdSendCtl(0x10); //column addr 0
|
lcdSendCtl(0x10); //column addr 0
|
||||||
lcdSendCtl(y | 0xB0); //page addr y
|
lcdSendCtl(y | 0xB0); //page addr y
|
||||||
|
|
||||||
#if !defined(REVX)
|
#if !defined(REVX)
|
||||||
pioptr->PIO_CODR = LCD_CS1; // Select LCD
|
pioptr->PIO_CODR = LCD_CS1; // Select LCD
|
||||||
#endif
|
#endif
|
||||||
PIOA->PIO_SODR = LCD_A0; // Data
|
PIOA->PIO_SODR = LCD_A0; // Data
|
||||||
#if !defined(REVX)
|
#if !defined(REVX)
|
||||||
pioptr->PIO_CODR = LCD_RnW; // Write
|
pioptr->PIO_CODR = LCD_RnW; // Write
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(REVA)
|
#if defined(REVA)
|
||||||
x = lookup[*p];
|
x = lookup[*p];
|
||||||
|
@ -278,16 +285,6 @@ void lcdRefresh()
|
||||||
x = *p;
|
x = *p;
|
||||||
#endif
|
#endif
|
||||||
for (z = 0; z < LCD_W; z += 1) {
|
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_ODSR = x;
|
||||||
pioptr->PIO_SODR = ebit; // Start E pulse
|
pioptr->PIO_SODR = ebit; // Start E pulse
|
||||||
// Need a delay here (250nS)
|
// Need a delay here (250nS)
|
||||||
|
@ -297,27 +294,27 @@ void lcdRefresh()
|
||||||
#else
|
#else
|
||||||
x = *p;
|
x = *p;
|
||||||
#endif
|
#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)
|
// while ( TC0->TC_CHANNEL[0].TC_CV < 3 ) // Value depends on MCK/2 (used 6MHz)
|
||||||
// {
|
// {
|
||||||
// // Wait
|
// // Wait
|
||||||
// }
|
// }
|
||||||
pioptr->PIO_CODR = ebit; // End E pulse
|
pioptr->PIO_CODR = ebit; // End E pulse
|
||||||
}
|
}
|
||||||
#if !defined(REVX)
|
#if !defined(REVX)
|
||||||
pioptr->PIO_SODR = LCD_CS1; // Deselect LCD
|
pioptr->PIO_SODR = LCD_CS1; // Deselect LCD
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
pioptr->PIO_ODSR = 0xFF ; // Drive lines high
|
pioptr->PIO_ODSR = 0xFF; // Drive lines high
|
||||||
#if defined(REVA)
|
#if defined(REVA)
|
||||||
pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
|
pioptr->PIO_PUER = 0x000000FEL; // Set bits 2, 3, 4, 5 with pullups
|
||||||
pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
|
pioptr->PIO_ODR = 0x000000FEL; // Set bits 2, 3, 4, 5 input
|
||||||
#else
|
#else
|
||||||
pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
|
pioptr->PIO_PUER = 0x000000FEL; // Set bits 1, 3, 4, 5 with pullups
|
||||||
pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
|
pioptr->PIO_ODR = 0x000000FEL; // Set bits 1, 3, 4, 5 input
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pioptr->PIO_ODSR = lcdInputs; // Drive D0 low
|
pioptr->PIO_ODSR = 0xFE; // Drive D0 low
|
||||||
lcdLock = 0;
|
lcdLock = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_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);
|
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();
|
pwrInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
keysInit();
|
keysInit();
|
||||||
adcInit();
|
adcInit();
|
||||||
delaysInit();
|
delaysInit();
|
||||||
|
@ -179,6 +183,7 @@ void boardInit()
|
||||||
else {
|
else {
|
||||||
if (pwr_on != 1) {
|
if (pwr_on != 1) {
|
||||||
pwr_on = 1;
|
pwr_on = 1;
|
||||||
|
pwrInit();
|
||||||
backlightInit();
|
backlightInit();
|
||||||
haptic.play(15, 3, PLAY_NOW);
|
haptic.play(15, 3, PLAY_NOW);
|
||||||
}
|
}
|
||||||
|
@ -191,6 +196,7 @@ void boardInit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
pwrInit();
|
||||||
backlightInit();
|
backlightInit();
|
||||||
}
|
}
|
||||||
toplcdInit();
|
toplcdInit();
|
||||||
|
@ -264,7 +270,7 @@ void checkTrainerSettings()
|
||||||
uint8_t requiredTrainerMode = g_model.trainerMode;
|
uint8_t requiredTrainerMode = g_model.trainerMode;
|
||||||
if (requiredTrainerMode != currentTrainerMode) {
|
if (requiredTrainerMode != currentTrainerMode) {
|
||||||
switch (currentTrainerMode) {
|
switch (currentTrainerMode) {
|
||||||
case TRAINER_MODE_MASTER:
|
case TRAINER_MODE_MASTER_TRAINER_JACK:
|
||||||
stop_trainer_capture();
|
stop_trainer_capture();
|
||||||
break;
|
break;
|
||||||
case TRAINER_MODE_SLAVE:
|
case TRAINER_MODE_SLAVE:
|
||||||
|
|
|
@ -143,7 +143,12 @@ void configure_pins( uint32_t pins, uint16_t config );
|
||||||
extern uint16_t sessionTimer;
|
extern uint16_t sessionTimer;
|
||||||
|
|
||||||
#define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE)
|
#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)
|
#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_GPIO_DETECT, TRAINER_GPIO_PIN_DETECT) == Bit_RESET)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -127,12 +127,14 @@ extern "C" void TIM3_IRQHandler()
|
||||||
if ( (TRAINER_TIMER->DIER & TIM_DIER_CC3IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC3IF ) ) {
|
if ( (TRAINER_TIMER->DIER & TIM_DIER_CC3IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC3IF ) ) {
|
||||||
// capture mode on trainer jack
|
// capture mode on trainer jack
|
||||||
capture = TRAINER_TIMER->CCR3 ;
|
capture = TRAINER_TIMER->CCR3 ;
|
||||||
|
if (TRAINER_CONNECTED() && currentTrainerMode == TRAINER_MODE_MASTER_TRAINER_JACK)
|
||||||
doCapture = true;
|
doCapture = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ( TRAINER_TIMER->DIER & TIM_DIER_CC2IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC2IF ) ) {
|
if ( ( TRAINER_TIMER->DIER & TIM_DIER_CC2IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC2IF ) ) {
|
||||||
// capture mode on heartbeat pin (external module)
|
// capture mode on heartbeat pin (external module)
|
||||||
capture = TRAINER_TIMER->CCR2 ;
|
capture = TRAINER_TIMER->CCR2 ;
|
||||||
|
if (currentTrainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)
|
||||||
doCapture = true ;
|
doCapture = true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,8 +249,10 @@ extern "C" void HEARTBEAT_USART_IRQHandler()
|
||||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||||
data = HEARTBEAT_USART->DR;
|
data = HEARTBEAT_USART->DR;
|
||||||
|
|
||||||
if (!(status & USART_FLAG_ERRORS))
|
if (!(status & USART_FLAG_ERRORS)) {
|
||||||
|
if (currentTrainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE)
|
||||||
sbusFifo.push(data);
|
sbusFifo.push(data);
|
||||||
|
}
|
||||||
|
|
||||||
status = HEARTBEAT_USART->SR;
|
status = HEARTBEAT_USART->SR;
|
||||||
}
|
}
|
||||||
|
|
2132
radio/src/targets/mega2560/board_mega2560_stk500v2bootloader.c
Normal file
2132
radio/src/targets/mega2560/board_mega2560_stk500v2bootloader.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -795,10 +795,12 @@ char *findTrueFileName(const char *path)
|
||||||
strcat(result, res->d_name);
|
strcat(result, res->d_name);
|
||||||
TRACE("\tfound: %s", res->d_name);
|
TRACE("\tfound: %s", res->d_name);
|
||||||
fileMap.insert(filemap_t:: value_type(path, result));
|
fileMap.insert(filemap_t:: value_type(path, result));
|
||||||
|
simu::closedir(dir);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
simu::closedir(dir);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -840,10 +842,10 @@ FRESULT f_open (FIL * fil, const TCHAR *name, BYTE flag)
|
||||||
fil->fsize = tmp.st_size;
|
fil->fsize = tmp.st_size;
|
||||||
fil->fptr = 0;
|
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;
|
fil->fptr = 0;
|
||||||
if (fil->fs) {
|
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;
|
return FR_OK;
|
||||||
}
|
}
|
||||||
TRACE("f_open(%s) = error %d (%s)", path, errno, strerror(errno));
|
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;
|
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)
|
FRESULT f_close (FIL * fil)
|
||||||
{
|
{
|
||||||
if (fil && fil->fs) {
|
if (fil && fil->fs) {
|
||||||
|
|
|
@ -366,10 +366,7 @@ void TelemetryItem::eval(const TelemetrySensor & sensor)
|
||||||
result += dist*dist;
|
result += dist*dist;
|
||||||
|
|
||||||
if (altItem) {
|
if (altItem) {
|
||||||
dist = abs(altItem->value);
|
dist = abs(altItem->value) / g_model.telemetrySensors[sensor.dist.alt-1].getPrecDivisor();
|
||||||
uint8_t prec = g_model.telemetrySensors[sensor.dist.alt-1].prec;
|
|
||||||
if (prec > 0)
|
|
||||||
dist /= (prec==2 ? 100 : 10);
|
|
||||||
result += dist*dist;
|
result += dist*dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,49 +542,56 @@ void TelemetrySensor::init(uint16_t id)
|
||||||
init(label);
|
init(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelemetrySensor::isAvailable()
|
bool TelemetrySensor::isAvailable() const
|
||||||
{
|
{
|
||||||
return ZLEN(label) > 0;
|
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)
|
int32_t convertTelemetryValue(int32_t value, uint8_t unit, uint8_t prec, uint8_t destUnit, uint8_t destPrec)
|
||||||
{
|
{
|
||||||
for (int i=prec; i<destPrec; i++)
|
for (int i=prec; i<destPrec; i++)
|
||||||
value *= 10;
|
value *= 10;
|
||||||
|
|
||||||
if (unit == UNIT_METERS || unit == UNIT_METERS_PER_SECOND) {
|
if (unit == UNIT_CELSIUS) {
|
||||||
if (destUnit == UNIT_FEET || destUnit == UNIT_FEET_PER_SECOND) {
|
|
||||||
// m to ft *105/32
|
|
||||||
value = (value * 105) / 32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (unit == UNIT_KTS) {
|
|
||||||
if (destUnit == UNIT_KMH) {
|
|
||||||
// kts to km/h (1 knot = 1.85200 kilometers per hour)
|
|
||||||
value = (value * 1852) / 1000;
|
|
||||||
}
|
|
||||||
else if (destUnit == UNIT_MPH) {
|
|
||||||
// kts to mph (1 knot = 1.15077945 miles per hour)
|
|
||||||
value = (value * 1151) / 1000;
|
|
||||||
}
|
|
||||||
else if (destUnit == UNIT_METERS_PER_SECOND) {
|
|
||||||
// kts to m/s (1 knot = 0.514444444 meters / second)
|
|
||||||
value = (value * 514) / 1000;
|
|
||||||
}
|
|
||||||
else if (destUnit == UNIT_FEET_PER_SECOND) {
|
|
||||||
// kts to f/s (1 knot = 1.68780986 feet per second)
|
|
||||||
value = (value * 1688) / 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (unit == UNIT_CELSIUS) {
|
|
||||||
if (destUnit == UNIT_FAHRENHEIT) {
|
if (destUnit == UNIT_FAHRENHEIT) {
|
||||||
// T(°F) = T(°C)×1,8 + 32
|
// T(°F) = T(°C)×1,8 + 32
|
||||||
value = 32 + (value*18)/10;
|
value = 32 + (value*18) / 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (unit == UNIT_MILLILITERS) {
|
else {
|
||||||
if (destUnit == UNIT_FLOZ) {
|
const UnitConversionRule * p = unitConversionTable;
|
||||||
value = (value * 100) / 2957;
|
while (p->divisor) {
|
||||||
|
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;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelemetrySensor::isConfigurable()
|
bool TelemetrySensor::isConfigurable() const
|
||||||
{
|
{
|
||||||
if (type == TELEM_TYPE_CALCULATED) {
|
if (type == TELEM_TYPE_CALCULATED) {
|
||||||
if (formula >= TELEM_FORMULA_CELL) {
|
if (formula >= TELEM_FORMULA_CELL) {
|
||||||
|
@ -637,7 +641,7 @@ bool TelemetrySensor::isConfigurable()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TelemetrySensor::isPrecConfigurable()
|
bool TelemetrySensor::isPrecConfigurable() const
|
||||||
{
|
{
|
||||||
if (isConfigurable()) {
|
if (isConfigurable()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -649,3 +653,21 @@ bool TelemetrySensor::isPrecConfigurable()
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -42,10 +42,6 @@
|
||||||
#define SWAP_DEFINED
|
#define SWAP_DEFINED
|
||||||
#include "opentx.h"
|
#include "opentx.h"
|
||||||
|
|
||||||
#include <lua.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <lualib.h>
|
|
||||||
|
|
||||||
extern const char * zchar2string(const char * zstring, int size);
|
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)))
|
#define EXPECT_ZSTREQ(c_string, z_string) EXPECT_STREQ(c_string, zchar2string(z_string, sizeof(z_string)))
|
||||||
extern void luaInit();
|
extern void luaInit();
|
||||||
|
|
6
radio/src/thirdparty/FatFs/ff.h
vendored
6
radio/src/thirdparty/FatFs/ff.h
vendored
|
@ -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_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
|
||||||
#define f_error(fp) ((fp)->err)
|
#define f_error(fp) ((fp)->err)
|
||||||
#define f_tell(fp) ((fp)->fptr)
|
#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
|
#ifndef EOF
|
||||||
#define EOF (-1)
|
#define EOF (-1)
|
||||||
|
|
24
radio/src/thirdparty/Lua/src/liolib.c
vendored
24
radio/src/thirdparty/Lua/src/liolib.c
vendored
|
@ -19,6 +19,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define liolib_c
|
#define liolib_c
|
||||||
|
|
||||||
|
@ -183,14 +184,10 @@ static LStream *newprefile (lua_State *L) {
|
||||||
|
|
||||||
#if !defined(USE_FATFS)
|
#if !defined(USE_FATFS)
|
||||||
static int aux_close (lua_State *L) {
|
static int aux_close (lua_State *L) {
|
||||||
#if !defined(USE_FATFS)
|
|
||||||
LStream *p = tolstream(L);
|
LStream *p = tolstream(L);
|
||||||
lua_CFunction cf = p->closef;
|
lua_CFunction cf = p->closef;
|
||||||
p->closef = NULL; /* mark stream as closed */
|
p->closef = NULL; /* mark stream as closed */
|
||||||
return (*cf)(L); /* close it */
|
return (*cf)(L); /* close it */
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -249,14 +246,14 @@ static int io_open (lua_State *L) {
|
||||||
const char *md = luaL_optstring(L, 2, "r");
|
const char *md = luaL_optstring(L, 2, "r");
|
||||||
LStream *p = newfile(L);
|
LStream *p = newfile(L);
|
||||||
#if defined(USE_FATFS)
|
#if defined(USE_FATFS)
|
||||||
BYTE mode;
|
BYTE mode = FA_READ;
|
||||||
if (strchr(md, 'w') || strchr(md, 'a'))
|
if (*md == 'w')
|
||||||
mode = FA_WRITE;
|
mode = FA_WRITE | FA_CREATE_ALWAYS; // always create file and truncate it
|
||||||
else
|
else if (*md == 'a')
|
||||||
mode = FA_READ;
|
mode = FA_WRITE | FA_OPEN_ALWAYS; // always open file (create it if necessary)
|
||||||
FRESULT result = f_open(&p->f, filename, mode);
|
FRESULT result = f_open(&p->f, filename, mode);
|
||||||
if (result == FR_OK && strchr(md, 'a'))
|
if (result == FR_OK && *md == 'a')
|
||||||
result = f_lseek(&p->f, f_size(&p->f));
|
result = f_lseek(&p->f, f_size(&p->f)); // seek to the end of the file
|
||||||
return result == FR_OK ? 1 : 0;
|
return result == FR_OK ? 1 : 0;
|
||||||
#else
|
#else
|
||||||
const char *mode = md; /* to traverse/check mode */
|
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++) {
|
for (; nargs--; arg++) {
|
||||||
if (lua_type(L, arg) == LUA_TNUMBER) {
|
if (lua_type(L, arg) == LUA_TNUMBER) {
|
||||||
/* optimization: could be done exactly as for strings */
|
/* optimization: could be done exactly as for strings */
|
||||||
status = status &&
|
char s[LUAI_MAXNUMBER2STR];
|
||||||
f_printf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
|
sprintf(s, LUA_NUMBER_FMT, lua_tonumber(L, arg));
|
||||||
|
status = status && f_puts(s, f) > 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
size_t l;
|
size_t l;
|
||||||
|
|
|
@ -391,7 +391,7 @@
|
||||||
#define SPEED_UNIT SPEED_UNIT_METR
|
#define SPEED_UNIT SPEED_UNIT_METR
|
||||||
#endif
|
#endif
|
||||||
#define LEN_VTELEMUNIT "\003"
|
#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
|
#endif
|
||||||
|
|
||||||
#define STR_V (STR_VTELEMUNIT+1)
|
#define STR_V (STR_VTELEMUNIT+1)
|
||||||
|
|
|
@ -395,7 +395,7 @@
|
||||||
#define SPEED_UNIT SPEED_UNIT_METR
|
#define SPEED_UNIT SPEED_UNIT_METR
|
||||||
#endif
|
#endif
|
||||||
#define LEN_VTELEMUNIT "\003"
|
#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
|
#endif
|
||||||
|
|
||||||
#define STR_V (STR_VTELEMUNIT+1)
|
#define STR_V (STR_VTELEMUNIT+1)
|
||||||
|
|
|
@ -389,7 +389,7 @@
|
||||||
#define SPEED_UNIT SPEED_UNIT_METR
|
#define SPEED_UNIT SPEED_UNIT_METR
|
||||||
#endif
|
#endif
|
||||||
#define LEN_VTELEMUNIT "\003"
|
#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
|
#endif
|
||||||
|
|
||||||
#define STR_V (STR_VTELEMUNIT+1)
|
#define STR_V (STR_VTELEMUNIT+1)
|
||||||
|
|
|
@ -389,7 +389,7 @@
|
||||||
#define SPEED_UNIT SPEED_UNIT_METR
|
#define SPEED_UNIT SPEED_UNIT_METR
|
||||||
#endif
|
#endif
|
||||||
#define LEN_VTELEMUNIT "\003"
|
#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
|
#endif
|
||||||
|
|
||||||
#define STR_V (STR_VTELEMUNIT+1)
|
#define STR_V (STR_VTELEMUNIT+1)
|
||||||
|
|
|
@ -393,7 +393,7 @@
|
||||||
#define SPEED_UNIT SPEED_UNIT_METR
|
#define SPEED_UNIT SPEED_UNIT_METR
|
||||||
#endif
|
#endif
|
||||||
#define LEN_VTELEMUNIT "\003"
|
#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
|
#endif
|
||||||
|
|
||||||
#define STR_V (STR_VTELEMUNIT+1)
|
#define STR_V (STR_VTELEMUNIT+1)
|
||||||
|
|
|
@ -396,7 +396,7 @@
|
||||||
#define SPEED_UNIT SPEED_UNIT_METR
|
#define SPEED_UNIT SPEED_UNIT_METR
|
||||||
#endif
|
#endif
|
||||||
#define LEN_VTELEMUNIT "\003"
|
#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
|
#endif
|
||||||
|
|
||||||
#define STR_V (STR_VTELEMUNIT+1)
|
#define STR_V (STR_VTELEMUNIT+1)
|
||||||
|
|
|
@ -397,7 +397,7 @@
|
||||||
#define SPEED_UNIT SPEED_UNIT_METR
|
#define SPEED_UNIT SPEED_UNIT_METR
|
||||||
#endif
|
#endif
|
||||||
#define LEN_VTELEMUNIT "\003"
|
#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
|
#endif
|
||||||
|
|
||||||
#define STR_V (STR_VTELEMUNIT+1)
|
#define STR_V (STR_VTELEMUNIT+1)
|
||||||
|
|
|
@ -389,7 +389,7 @@
|
||||||
#define SPEED_UNIT SPEED_UNIT_METR
|
#define SPEED_UNIT SPEED_UNIT_METR
|
||||||
#endif
|
#endif
|
||||||
#define LEN_VTELEMUNIT "\003"
|
#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
|
#endif
|
||||||
|
|
||||||
#define STR_V (STR_VTELEMUNIT+1)
|
#define STR_V (STR_VTELEMUNIT+1)
|
||||||
|
|
|
@ -389,7 +389,7 @@
|
||||||
#define SPEED_UNIT SPEED_UNIT_METR
|
#define SPEED_UNIT SPEED_UNIT_METR
|
||||||
#endif
|
#endif
|
||||||
#define LEN_VTELEMUNIT "\003"
|
#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
|
#endif
|
||||||
|
|
||||||
#define STR_V (STR_VTELEMUNIT+1)
|
#define STR_V (STR_VTELEMUNIT+1)
|
||||||
|
|
|
@ -47,10 +47,10 @@ void varioWakeup()
|
||||||
|
|
||||||
int verticalSpeed = 0;
|
int verticalSpeed = 0;
|
||||||
if (g_model.frsky.varioSource) {
|
if (g_model.frsky.varioSource) {
|
||||||
TelemetryItem & varioItem = telemetryItems[g_model.frsky.varioSource-1];
|
uint8_t item = g_model.frsky.varioSource-1;
|
||||||
verticalSpeed = varioItem.value;
|
if (item < MAX_SENSORS) {
|
||||||
TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.varioSource-1];
|
verticalSpeed = telemetryItems[item].value * g_model.telemetrySensors[item].getPrecMultiplier();
|
||||||
if (sensor.prec != 2) verticalSpeed *= sensor.prec == 0 ? 100 : 10;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int varioCenterMin = (int)g_model.frsky.varioCenterMin * 10 - 50;
|
int varioCenterMin = (int)g_model.frsky.varioCenterMin * 10 - 50;
|
||||||
|
|
|
@ -51,12 +51,17 @@ def ParseSWR(packet, dataId, prim, appId, data, crc):
|
||||||
print "packet: %s (%4d)" % (dump(packet), lineNumber) ,
|
print "packet: %s (%4d)" % (dump(packet), lineNumber) ,
|
||||||
print " SWR: %d" % (data & 0xFF)
|
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 = (
|
appIdParsers = (
|
||||||
(0x0300, 0x030f, ParseFlVSS),
|
(0x0300, 0x030f, ParseFlVSS),
|
||||||
(0xf101, 0xf101, ParseRSSI),
|
(0xf101, 0xf101, ParseRSSI),
|
||||||
(0xf102, 0xf103, ParseAdc),
|
(0xf102, 0xf103, ParseAdc),
|
||||||
(0xf104, 0xf104, ParseBatt),
|
(0xf104, 0xf104, ParseBatt),
|
||||||
(0xf105, 0xf105, ParseSWR),
|
(0xf105, 0xf105, ParseSWR),
|
||||||
|
(0x0a00, 0x0a0f, ParseAirSpeed),
|
||||||
)
|
)
|
||||||
|
|
||||||
def dump(data, maxLen = None):
|
def dump(data, maxLen = None):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue