mirror of
https://github.com/opentx/opentx.git
synced 2025-07-24 16:55:20 +03:00
Projectkk2glider/companion archive support (#4017)
* Files moved to thirdparty directory * Miniz library added * Unused simulators removed: er9x, th9x, ersky9x * Example of opening archive file .eepe2 (File->Open) * File reorganization, bunch of files moved to storage directory * Added StorageSdcard class to handle storage for radios that use SD card to store radio settings and models
This commit is contained in:
parent
fb27acf286
commit
60524f77f0
61 changed files with 5614 additions and 1104 deletions
|
@ -72,15 +72,19 @@ include_directories(
|
|||
${COMPANION_SRC_DIRECTORY}
|
||||
${COMPANION_SRC_DIRECTORY}/shared
|
||||
${SIMU_SRC_DIRECTORY}
|
||||
${COMPANION_SRC_DIRECTORY}/qxtcommandoptions
|
||||
${COMPANION_SRC_DIRECTORY}/thirdparty/qxtcommandoptions
|
||||
${COMPANION_SRC_DIRECTORY}/thirdparty/qcustomplot
|
||||
${COMPANION_SRC_DIRECTORY}/thirdparty/miniz
|
||||
${COMPANION_SRC_DIRECTORY}/storage
|
||||
)
|
||||
|
||||
add_subdirectory(shared)
|
||||
add_subdirectory(modeledit)
|
||||
add_subdirectory(generaledit)
|
||||
add_subdirectory(simulation)
|
||||
add_subdirectory(qcustomplot)
|
||||
add_subdirectory(qxtcommandoptions)
|
||||
add_subdirectory(storage)
|
||||
add_subdirectory(thirdparty/qcustomplot)
|
||||
add_subdirectory(thirdparty/qxtcommandoptions)
|
||||
|
||||
set(common_SRCS
|
||||
eeprominterface.cpp
|
||||
|
@ -97,8 +101,6 @@ set(common_SRCS
|
|||
firmwares/opentx/open9xGruvin9xeeprom.cpp
|
||||
firmwares/opentx/open9xSky9xeeprom.cpp
|
||||
firmwares/opentx/opentxinterface.cpp
|
||||
file.cpp
|
||||
appdata.cpp
|
||||
)
|
||||
|
||||
qt5_wrap_cpp(common_SRCS)
|
||||
|
@ -107,16 +109,10 @@ add_library(common ${common_SRCS})
|
|||
qt5_use_modules(common Core Xml Widgets)
|
||||
|
||||
set(companion_SRCS
|
||||
hexinterface.cpp
|
||||
firmwareinterface.cpp
|
||||
converteeprom.cpp
|
||||
# xmlinterface.cpp
|
||||
# ${PROJECT_BINARY_DIR}/radio.cxx
|
||||
helpers.cpp
|
||||
helpers_html.cpp
|
||||
mdichild.cpp
|
||||
modelslist.cpp
|
||||
mountlist.cpp
|
||||
apppreferencesdialog.cpp
|
||||
fwpreferencesdialog.cpp
|
||||
burnconfigdialog.cpp
|
||||
|
@ -236,7 +232,7 @@ add_executable(${COMPANION_NAME} MACOSX_BUNDLE WIN32 ${companion_SRCS} ${compani
|
|||
|
||||
add_dependencies(${COMPANION_NAME} gen_qrc)
|
||||
qt5_use_modules(${COMPANION_NAME} Core Widgets Network)
|
||||
target_link_libraries(${COMPANION_NAME} PRIVATE generaledit modeledit simulation common qcustomplot shared ${PTHREAD_LIBRARY} ${SDL_LIBRARY})
|
||||
target_link_libraries(${COMPANION_NAME} PRIVATE generaledit modeledit simulation common qcustomplot shared storage ${PTHREAD_LIBRARY} ${SDL_LIBRARY})
|
||||
|
||||
############# Standalone simu ###############
|
||||
|
||||
|
@ -261,7 +257,7 @@ add_executable(${SIMULATOR_NAME} MACOSX_BUNDLE WIN32 ${simu_SRCS} ${companion_RC
|
|||
|
||||
add_dependencies(${SIMULATOR_NAME} gen_qrc)
|
||||
# TODO not the same link command than companion?
|
||||
target_link_libraries(${SIMULATOR_NAME} PRIVATE simulation common qxtcommandoptions ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${OPENTX_SIMULATOR_LIBS})
|
||||
target_link_libraries(${SIMULATOR_NAME} PRIVATE simulation common storage qxtcommandoptions ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${OPENTX_SIMULATOR_LIBS})
|
||||
|
||||
############# Packaging ####################
|
||||
message(STATUS ${CMAKE_BINARY_DIR} ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
#include "converteeprom.h"
|
||||
#include "eeprominterface.h"
|
||||
#include "firmwareinterface.h"
|
||||
#include <QFile>
|
||||
|
||||
bool convertEEprom(const QString &sourceEEprom, const QString &destinationEEprom, const QString &firmwareFilename)
|
||||
{
|
||||
Firmware *currentFirmware = GetCurrentFirmware();
|
||||
FirmwareInterface firmware(firmwareFilename);
|
||||
if (!firmware.isValid())
|
||||
return false;
|
||||
|
||||
unsigned int version = firmware.getEEpromVersion();
|
||||
unsigned int variant = firmware.getEEpromVariant();
|
||||
|
||||
QFile sourceFile(sourceEEprom);
|
||||
int eeprom_size = sourceFile.size();
|
||||
if (!eeprom_size)
|
||||
return false;
|
||||
|
||||
if (!sourceFile.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
|
||||
QByteArray eeprom(eeprom_size, 0);
|
||||
long result = sourceFile.read(eeprom.data(), eeprom_size);
|
||||
sourceFile.close();
|
||||
|
||||
QSharedPointer<RadioData> radioData = QSharedPointer<RadioData>(new RadioData());
|
||||
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(*radioData, (uint8_t *)eeprom.data(), eeprom_size));
|
||||
if (!errors.test(ALL_OK)
|
||||
|| !currentFirmware->saveEEPROM((uint8_t *)eeprom.data(), *radioData, variant, version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile destinationFile(destinationEEprom);
|
||||
if (!destinationFile.open(QIODevice::WriteOnly))
|
||||
return false;
|
||||
|
||||
result = destinationFile.write(eeprom.constData(), eeprom_size);
|
||||
destinationFile.close();
|
||||
if (result != eeprom_size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef CONVERTHEADER_H_
|
||||
#define CONVERTHEADER_H_
|
||||
|
||||
#include <QString>
|
||||
|
||||
bool convertEEprom(const QString &sourceEEprom, const QString &destinationEEprom, const QString &firmware);
|
||||
|
||||
#endif /* CONVERTHEADER_H_ */
|
|
@ -1639,65 +1639,30 @@ void ShowEepromWarnings(QWidget *parent, const QString &title, unsigned long err
|
|||
msgBox.exec();
|
||||
}
|
||||
|
||||
unsigned long LoadEeprom(RadioData &radioData, const uint8_t *eeprom, const int size)
|
||||
QString getBoardName(BoardEnum board)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
|
||||
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->load(radioData, eeprom, size));
|
||||
if (result.test(ALL_OK)) {
|
||||
return result.to_ulong();
|
||||
}
|
||||
else {
|
||||
errors |= result;
|
||||
}
|
||||
switch (board) {
|
||||
case BOARD_STOCK:
|
||||
return "9X";
|
||||
case BOARD_M128:
|
||||
return "9X128";
|
||||
case BOARD_GRUVIN9X:
|
||||
return "Gruvin9x";
|
||||
case BOARD_MEGA2560:
|
||||
return "MEGA2560";
|
||||
case BOARD_TARANIS:
|
||||
return "Taranis";
|
||||
case BOARD_TARANIS_PLUS:
|
||||
return "Taranis Plus";
|
||||
case BOARD_SKY9X:
|
||||
return "Sky9x";
|
||||
case BOARD_9XRPRO:
|
||||
return "9XR-PRO";
|
||||
case BOARD_AR9X:
|
||||
return "AR9X";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
if (errors.none()) {
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
}
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
unsigned long LoadBackup(RadioData & radioData, uint8_t * eeprom, int size, int index)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
|
||||
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadBackup(radioData, eeprom, size, index));
|
||||
if (result.test(ALL_OK)) {
|
||||
return result.to_ulong();
|
||||
}
|
||||
else {
|
||||
errors |= result;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.none()) {
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
}
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
|
||||
unsigned long LoadEepromXml(RadioData & radioData, QDomDocument & doc)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
foreach(EEPROMInterface * eepromInterface, eepromInterfaces) {
|
||||
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadxml(radioData, doc));
|
||||
if (result.test(ALL_OK)) {
|
||||
return result.to_ulong();
|
||||
}
|
||||
else {
|
||||
errors |= result;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.none()) {
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
}
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
const int Firmware::getFlashSize()
|
||||
|
|
|
@ -1554,9 +1554,6 @@ enum EepromLoadErrors {
|
|||
void ShowEepromErrors(QWidget *parent, const QString &title, const QString &mainMessage, unsigned long errorsFound);
|
||||
void ShowEepromWarnings(QWidget *parent, const QString &title, unsigned long errorsFound);
|
||||
|
||||
unsigned long LoadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index);
|
||||
unsigned long LoadEeprom(RadioData &radioData, const uint8_t *eeprom, int size);
|
||||
unsigned long LoadEepromXml(RadioData &radioData, QDomDocument &doc);
|
||||
|
||||
struct Option {
|
||||
const char * name;
|
||||
|
@ -1715,4 +1712,6 @@ inline int divRoundClosest(const int n, const int d)
|
|||
|
||||
SimulatorInterface * GetCurrentFirmwareSimulator();
|
||||
|
||||
extern QList<EEPROMInterface *> eepromInterfaces;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
#include <iostream>
|
||||
#include "er9xinterface.h"
|
||||
#include "er9xeeprom.h"
|
||||
#include "simulator/er9xsimulator.h"
|
||||
#include "file.h"
|
||||
#include "rlefile.h"
|
||||
#include "appdata.h"
|
||||
|
||||
#define FILE_TYP_GENERAL 1
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
set(ER9X_CHECKOUT_DIRECTORY ${PROJECT_BINARY_DIR}/firmwares/er9x)
|
||||
add_custom_command(
|
||||
OUTPUT ${ER9X_CHECKOUT_DIRECTORY}/er9xsimulator.cpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${ER9X_CHECKOUT_DIRECTORY}
|
||||
COMMAND cd ${ER9X_CHECKOUT_DIRECTORY} && svn checkout http://er9x.googlecode.com/svn/trunk/src@790 .
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/firmwares/er9x/er9xsimulator.cpp ${ER9X_CHECKOUT_DIRECTORY}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/firmwares/er9x/er9xsimulator.cpp
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROJECT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_library(er9x-simulator er9xsimulator.cpp)
|
|
@ -1,224 +0,0 @@
|
|||
/*
|
||||
* Author - Bertrand Songis <bsongis@gmail.com>
|
||||
*
|
||||
* Based on 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 "firmwares/er9x/er9xsimulator.h"
|
||||
#include "firmwares/er9x/er9xinterface.h"
|
||||
|
||||
#define SIMU
|
||||
#define SIMU_EXCEPTIONS
|
||||
#define TELEMETRY_FRSKY
|
||||
#define PHASES
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#define NUM_POTS 3
|
||||
#define NUM_SLIDERS 0
|
||||
#define SWSRC_SW1 DSW_SW1
|
||||
|
||||
#include <exception>
|
||||
|
||||
namespace Er9x {
|
||||
|
||||
#include "simpgmspace.h"
|
||||
#include "er9x.cpp"
|
||||
#include "stamp.cpp"
|
||||
#include "menus.cpp"
|
||||
#include "pers.cpp"
|
||||
#include "file.cpp"
|
||||
#include "lcd.cpp"
|
||||
#include "drivers.cpp"
|
||||
#include "simpgmspace.cpp"
|
||||
#include "templates.cpp"
|
||||
#include "frsky.cpp"
|
||||
#include "audio.cpp"
|
||||
|
||||
uint8_t pxxFlag = 0;
|
||||
int16_t g_anas[7];
|
||||
|
||||
#define isBacklightEnabled() (PORTB & (1<<OUT_B_LIGHT))
|
||||
|
||||
uint16_t anaIn(uint8_t chan)
|
||||
{
|
||||
if (chan == 7)
|
||||
return 1500;
|
||||
else
|
||||
return g_anas[chan];
|
||||
}
|
||||
|
||||
bool hasExtendedTrims()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void setTrim(uint8_t idx, int8_t value)
|
||||
{
|
||||
g_model.trim[idx] = value;
|
||||
}
|
||||
|
||||
void getTrims(int16_t values[4])
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
values[i] = g_model.trim[i];
|
||||
}
|
||||
|
||||
#define TRIMS_GPIO_REG_LHL pind
|
||||
#define TRIMS_GPIO_REG_LVD pind
|
||||
#define TRIMS_GPIO_REG_RVU pind
|
||||
#define TRIMS_GPIO_REG_RHL pind
|
||||
#define TRIMS_GPIO_REG_LHR pind
|
||||
#define TRIMS_GPIO_REG_LVU pind
|
||||
#define TRIMS_GPIO_REG_RVD pind
|
||||
#define TRIMS_GPIO_REG_RHR pind
|
||||
#define PIN_TRIM_LH_L (1<<INP_D_TRM_LH_DWN)
|
||||
#define PIN_TRIM_LV_DN (1<<INP_D_TRM_LV_DWN)
|
||||
#define PIN_TRIM_RV_UP (1<<INP_D_TRM_RV_UP)
|
||||
#define PIN_TRIM_RH_L (1<<INP_D_TRM_RH_DWN)
|
||||
#define PIN_TRIM_LH_R (1<<INP_D_TRM_LH_UP)
|
||||
#define PIN_TRIM_LV_UP (1<<INP_D_TRM_LV_UP)
|
||||
#define PIN_TRIM_RV_DN (1<<INP_D_TRM_RV_DWN)
|
||||
#define PIN_TRIM_RH_R (1<<INP_D_TRM_RH_UP)
|
||||
|
||||
#define TRIM_CASE(key, pin, mask) \
|
||||
case key: \
|
||||
if (state) pin |= mask; else pin &= ~mask;\
|
||||
break;
|
||||
|
||||
void simuSetTrim(uint8_t trim, bool state)
|
||||
{
|
||||
switch (trim) {
|
||||
TRIM_CASE(0, TRIMS_GPIO_REG_LHL, PIN_TRIM_LH_L)
|
||||
TRIM_CASE(1, TRIMS_GPIO_REG_LHR, PIN_TRIM_LH_R)
|
||||
TRIM_CASE(2, TRIMS_GPIO_REG_LVD, PIN_TRIM_LV_DN)
|
||||
TRIM_CASE(3, TRIMS_GPIO_REG_LVU, PIN_TRIM_LV_UP)
|
||||
TRIM_CASE(4, TRIMS_GPIO_REG_RVD, PIN_TRIM_RV_DN)
|
||||
TRIM_CASE(5, TRIMS_GPIO_REG_RVU, PIN_TRIM_RV_UP)
|
||||
TRIM_CASE(6, TRIMS_GPIO_REG_RHL, PIN_TRIM_RH_L)
|
||||
TRIM_CASE(7, TRIMS_GPIO_REG_RHR, PIN_TRIM_RH_R)
|
||||
}
|
||||
}
|
||||
|
||||
#define SWITCH_CASE(swtch, pin, mask) \
|
||||
case swtch: \
|
||||
if (state) pin &= ~(mask); else pin |= (mask); \
|
||||
break;
|
||||
#define SWITCH_3_CASE(swtch, pin1, pin2, mask1, mask2) \
|
||||
case swtch: \
|
||||
if (state >= 0) pin1 &= ~(mask1); else pin1 |= (mask1); \
|
||||
if (state <= 0) pin2 &= ~(mask2); else pin2 |= (mask2); \
|
||||
break;
|
||||
|
||||
void simuSetSwitch(uint8_t swtch, int8_t state)
|
||||
{
|
||||
switch (swtch) {
|
||||
SWITCH_CASE(0, pinc, 1<<INP_C_ThrCt)
|
||||
SWITCH_CASE(4, pinc, 1<<INP_C_AileDR)
|
||||
SWITCH_3_CASE(3, ping, pine, (1<<INP_G_ID1), (1<<INP_E_ID2))
|
||||
SWITCH_CASE(1, ping, 1<<INP_G_RuddDR)
|
||||
SWITCH_CASE(2, pine, 1<<INP_E_ElevDR)
|
||||
SWITCH_CASE(5, pine, 1<<INP_E_Gear)
|
||||
SWITCH_CASE(6, pine, 1<<INP_E_Trainer)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define KEY_CASE(key, pin, mask) \
|
||||
case key: \
|
||||
if (state) pin |= mask; else pin &= ~mask;\
|
||||
break;
|
||||
|
||||
void simuSetKey(uint8_t key, bool state)
|
||||
{
|
||||
switch (key) {
|
||||
KEY_CASE(KEY_MENU, pinb, (1<<INP_B_KEY_MEN))
|
||||
KEY_CASE(KEY_EXIT, pinb, (1<<INP_B_KEY_EXT))
|
||||
KEY_CASE(KEY_RIGHT, pinb, (1<<INP_B_KEY_RGT))
|
||||
KEY_CASE(KEY_LEFT, pinb, (1<<INP_B_KEY_LFT))
|
||||
KEY_CASE(KEY_UP, pinb, (1<<INP_B_KEY_UP))
|
||||
KEY_CASE(KEY_DOWN, pinb, (1<<INP_B_KEY_DWN))
|
||||
}
|
||||
}
|
||||
|
||||
#define isBacklightEnabled() (PORTB & (1<<OUT_B_LIGHT))
|
||||
|
||||
}
|
||||
|
||||
using namespace Er9x;
|
||||
|
||||
Er9xSimulator::Er9xSimulator(Er9xInterface * er9xInterface):
|
||||
er9xInterface(er9xInterface)
|
||||
{
|
||||
}
|
||||
|
||||
bool Er9xSimulator::timer10ms()
|
||||
{
|
||||
AUDIO_DRIVER(); // the tone generator
|
||||
AUDIO_HEARTBEAT(); // the queue processing
|
||||
#define TIMER10MS_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
uint8_t * Er9xSimulator::getLcd()
|
||||
{
|
||||
return (::uint8_t *)simuLcdBuf;
|
||||
}
|
||||
|
||||
bool Er9xSimulator::lcdChanged(bool & lightEnable)
|
||||
{
|
||||
#define LCDCHANGED_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
void Er9xSimulator::start(RadioData &radioData, bool tests)
|
||||
{
|
||||
er9xInterface->save(&eeprom[0], radioData);
|
||||
StartMainThread(tests);
|
||||
}
|
||||
|
||||
void Er9xSimulator::stop()
|
||||
{
|
||||
StopMainThread();
|
||||
}
|
||||
|
||||
void Er9xSimulator::getValues(TxOutputs &outputs)
|
||||
{
|
||||
#define GETVALUES_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
outputs.beep = audio.busy();
|
||||
}
|
||||
|
||||
void Er9xSimulator::setValues(TxInputs &inputs)
|
||||
{
|
||||
#define SETVALUES_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
void Er9xSimulator::setTrim(unsigned int idx, int value)
|
||||
{
|
||||
Er9x::setTrim(idx, value);
|
||||
}
|
||||
|
||||
void Er9xSimulator::getTrims(Trims & trims)
|
||||
{
|
||||
trims.extended = false;
|
||||
Er9x::getTrims(trims.values);
|
||||
}
|
||||
|
||||
const char * Er9xSimulator::getError()
|
||||
{
|
||||
#define GETERROR_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Author - Bertrand Songis <bsongis@gmail.com>
|
||||
*
|
||||
* Based on 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef er9x_simulator_h
|
||||
#define er9x_simulator_h
|
||||
|
||||
#include "simulatorinterface.h"
|
||||
|
||||
class RadioData;
|
||||
class Er9xInterface;
|
||||
|
||||
class Er9xSimulator : public SimulatorInterface {
|
||||
|
||||
public:
|
||||
|
||||
Er9xSimulator(Er9xInterface *);
|
||||
|
||||
virtual void start(RadioData & radioData, bool tests);
|
||||
|
||||
virtual void stop();
|
||||
|
||||
virtual bool timer10ms();
|
||||
|
||||
virtual uint8_t * getLcd();
|
||||
|
||||
virtual bool lcdChanged(bool & lightEnable);
|
||||
|
||||
virtual void setValues(TxInputs &inputs);
|
||||
|
||||
virtual void getValues(TxOutputs &outputs);
|
||||
|
||||
virtual void setTrim(unsigned int idx, int value);
|
||||
|
||||
virtual void getTrims(Trims & trims);
|
||||
|
||||
virtual unsigned int getPhase() { return 0; }
|
||||
|
||||
virtual const char * getPhaseName(unsigned int phase) { return 0; }
|
||||
|
||||
virtual const char * getError();
|
||||
|
||||
virtual void sendTelemetry(uint8_t * data, unsigned int len) {};
|
||||
|
||||
virtual uint8_t getSensorInstance(uint16_t id, uint8_t defaultValue = 0) { return 0; };
|
||||
|
||||
virtual uint16_t getSensorRatio(uint16_t id) { return 0; };
|
||||
|
||||
virtual void setTrainerInput(unsigned int inputNumber, int16_t value) {};
|
||||
|
||||
virtual void setLuaStateReloadPermanentScripts() {};
|
||||
|
||||
protected:
|
||||
|
||||
Er9xInterface * er9xInterface;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -17,8 +17,7 @@
|
|||
#include <iostream>
|
||||
#include "ersky9xinterface.h"
|
||||
#include "ersky9xeeprom.h"
|
||||
#include "simulator/ersky9xsimulator.h"
|
||||
#include "file.h"
|
||||
#include "rlefile.h"
|
||||
|
||||
#define FILE_TYP_GENERAL 1
|
||||
#define FILE_TYP_MODEL 2
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
set(ERSKY9X_CHECKOUT_DIRECTORY ${PROJECT_BINARY_DIR}/firmwares/ersky9x)
|
||||
add_custom_command(
|
||||
OUTPUT ${ERSKY9X_CHECKOUT_DIRECTORY}/ersky9xsimulator.cpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${ERSKY9X_CHECKOUT_DIRECTORY}
|
||||
COMMAND cd ${ERSKY9X_CHECKOUT_DIRECTORY} && svn checkout http://ersky9x.googlecode.com/svn/trunk/src@170 .
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/firmwares/ersky9x/ersky9xsimulator.cpp ${ERSKY9X_CHECKOUT_DIRECTORY}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/firmwares/ersky9x/ersky9xsimulator.cpp
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROJECT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_library(ersky9x-simulator ersky9xsimulator.cpp)
|
|
@ -1,247 +0,0 @@
|
|||
/*
|
||||
* Author - Bertrand Songis <bsongis@gmail.com>
|
||||
*
|
||||
* Based on 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 "firmwares/ersky9x/ersky9xsimulator.h"
|
||||
#include "firmwares/ersky9x/ersky9xinterface.h"
|
||||
|
||||
#define SIMU
|
||||
#define SIMU_EXCEPTIONS
|
||||
#define PCBSKY9X
|
||||
#define PCBSKY
|
||||
#define STAMP
|
||||
#define TELEMETRY_FRSKY
|
||||
#define FRSKY_HUB
|
||||
#define WS_HOW_HIGH
|
||||
#define TEMPLATES
|
||||
#define HELI
|
||||
#define HAPTIC
|
||||
#define AUDIO
|
||||
#define REVB
|
||||
|
||||
#define NUM_POTS 3
|
||||
#define NUM_SLIDERS 0
|
||||
#define SWSRC_SW1 DSW_SW1
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#include <exception>
|
||||
|
||||
namespace Ersky9x {
|
||||
|
||||
#include "../ersky9x/timers.h"
|
||||
#include "../ersky9x/ersky9x.cpp"
|
||||
#include "../ersky9x/stamp.cpp"
|
||||
#include "../ersky9x/menus.cpp"
|
||||
#include "../ersky9x/pers.cpp"
|
||||
#include "../ersky9x/file.cpp"
|
||||
#include "../ersky9x/lcd.cpp"
|
||||
#include "../ersky9x/drivers.cpp"
|
||||
#include "../ersky9x/logicio.cpp"
|
||||
#include "../ersky9x/timers.cpp"
|
||||
#include "../ersky9x/simpgmspace.cpp"
|
||||
#include "../ersky9x/templates.cpp"
|
||||
#include "../ersky9x/frsky.cpp"
|
||||
#include "../ersky9x/audio.cpp"
|
||||
#include "../ersky9x/sound.cpp"
|
||||
#include "../ersky9x/diskio.cpp"
|
||||
|
||||
#define isBacklightEnabled() (PWM->PWM_CH_NUM[0].PWM_CDTY != 100)
|
||||
|
||||
//uint8_t pxxFlag = 0;
|
||||
int16_t g_anas[7];
|
||||
|
||||
uint16_t anaIn(uint8_t chan)
|
||||
{
|
||||
if (chan == 7)
|
||||
return 1500;
|
||||
else
|
||||
return g_anas[chan];
|
||||
}
|
||||
|
||||
bool hasExtendedTrims()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void setTrim(uint8_t idx, int8_t value)
|
||||
{
|
||||
g_model.trim[idx] = value;
|
||||
}
|
||||
|
||||
void getTrims(int16_t values[4])
|
||||
{
|
||||
for (int i=0; i<4; i++)
|
||||
values[i] = g_model.trim[i];
|
||||
}
|
||||
|
||||
#define SWITCH_CASE(swtch, pin, mask) \
|
||||
case swtch: \
|
||||
if (state) pin |= (mask); else pin &= ~(mask); \
|
||||
break;
|
||||
#define SWITCH_3_CASE(swtch, pin1, pin2, mask1, mask2) \
|
||||
case swtch: \
|
||||
if (state < 0) pin1 &= ~(mask1); else pin1 |= (mask1); \
|
||||
if (state > 0) pin2 &= ~(mask2); else pin2 |= (mask2); \
|
||||
break;
|
||||
|
||||
void simuSetSwitch(uint8_t swtch, int8_t state)
|
||||
{
|
||||
// printf("swtch=%d state=%d\n", swtch, state); fflush(stdout);
|
||||
switch (swtch) {
|
||||
SWITCH_CASE(0, PIOC->PIO_PDSR, 1<<20)
|
||||
SWITCH_CASE(1, PIOA->PIO_PDSR, 1<<15)
|
||||
SWITCH_CASE(2, PIOC->PIO_PDSR, 1<<31)
|
||||
SWITCH_3_CASE(3, PIOC->PIO_PDSR, PIOC->PIO_PDSR, 0x00004000, 0x00000800)
|
||||
SWITCH_CASE(4, PIOA->PIO_PDSR, 1<<2)
|
||||
SWITCH_CASE(5, PIOC->PIO_PDSR, 1<<16)
|
||||
SWITCH_CASE(6, PIOC->PIO_PDSR, 1<<8)
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define KEYS_GPIO_REG_MENU PIOB->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_EXIT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_UP PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_DOWN PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_RIGHT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_LEFT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_PIN_MENU 0x00000020
|
||||
#define KEYS_GPIO_PIN_EXIT 0x01000000
|
||||
#define KEYS_GPIO_PIN_UP 0x00000002
|
||||
#define KEYS_GPIO_PIN_DOWN 0x00000020
|
||||
#define KEYS_GPIO_PIN_RIGHT 0x00000010
|
||||
#define KEYS_GPIO_PIN_LEFT 0x00000008
|
||||
|
||||
#define KEY_CASE(key, pin, mask) \
|
||||
case key: \
|
||||
if (state) pin &= ~mask; else pin |= mask;\
|
||||
break;
|
||||
|
||||
void simuSetKey(uint8_t key, bool state)
|
||||
{
|
||||
switch (key) {
|
||||
KEY_CASE(KEY_MENU, KEYS_GPIO_REG_MENU, KEYS_GPIO_PIN_MENU)
|
||||
KEY_CASE(KEY_EXIT, KEYS_GPIO_REG_EXIT, KEYS_GPIO_PIN_EXIT)
|
||||
KEY_CASE(KEY_RIGHT, KEYS_GPIO_REG_RIGHT, KEYS_GPIO_PIN_RIGHT)
|
||||
KEY_CASE(KEY_LEFT, KEYS_GPIO_REG_LEFT, KEYS_GPIO_PIN_LEFT)
|
||||
KEY_CASE(KEY_UP, KEYS_GPIO_REG_UP, KEYS_GPIO_PIN_UP)
|
||||
KEY_CASE(KEY_DOWN, KEYS_GPIO_REG_DOWN, KEYS_GPIO_PIN_DOWN)
|
||||
}
|
||||
}
|
||||
|
||||
#define TRIMS_GPIO_REG_LHL PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVD PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVU PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHL PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LHR PIOB->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVU PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVD PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHR PIOC->PIO_PDSR
|
||||
#define PIN_TRIM_LH_L 0x00800000
|
||||
#define PIN_TRIM_LV_DN 0x01000000
|
||||
#define PIN_TRIM_RV_UP 0x00000002
|
||||
#define PIN_TRIM_RH_L 0x00000001
|
||||
#define PIN_TRIM_LH_R 0x00000010
|
||||
#define PIN_TRIM_LV_UP 0x10000000
|
||||
#define PIN_TRIM_RV_DN 0x00000400
|
||||
#define PIN_TRIM_RH_R 0x00000200
|
||||
|
||||
#define TRIM_CASE KEY_CASE
|
||||
|
||||
void simuSetTrim(uint8_t trim, bool state)
|
||||
{
|
||||
switch (trim) {
|
||||
TRIM_CASE(0, TRIMS_GPIO_REG_LHL, PIN_TRIM_LH_L)
|
||||
TRIM_CASE(1, TRIMS_GPIO_REG_LHR, PIN_TRIM_LH_R)
|
||||
TRIM_CASE(2, TRIMS_GPIO_REG_LVD, PIN_TRIM_LV_DN)
|
||||
TRIM_CASE(3, TRIMS_GPIO_REG_LVU, PIN_TRIM_LV_UP)
|
||||
TRIM_CASE(4, TRIMS_GPIO_REG_RVD, PIN_TRIM_RV_DN)
|
||||
TRIM_CASE(5, TRIMS_GPIO_REG_RVU, PIN_TRIM_RV_UP)
|
||||
TRIM_CASE(6, TRIMS_GPIO_REG_RHL, PIN_TRIM_RH_L)
|
||||
TRIM_CASE(7, TRIMS_GPIO_REG_RHR, PIN_TRIM_RH_R)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace Ersky9x;
|
||||
|
||||
Ersky9xSimulator::Ersky9xSimulator(Ersky9xInterface * ersky9xInterface):
|
||||
ersky9xInterface(ersky9xInterface)
|
||||
{
|
||||
}
|
||||
|
||||
bool Ersky9xSimulator::timer10ms()
|
||||
{
|
||||
#define TIMER10MS_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
uint8_t * Ersky9xSimulator::getLcd()
|
||||
{
|
||||
return (::uint8_t *)simuLcdBuf;
|
||||
}
|
||||
|
||||
bool Ersky9xSimulator::lcdChanged(bool & lightEnable)
|
||||
{
|
||||
#define LCDCHANGED_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
void Ersky9xSimulator::start(RadioData &radioData, bool tests)
|
||||
{
|
||||
ersky9xInterface->save(Ersky9x::eeprom, radioData);
|
||||
StartEepromThread(NULL);
|
||||
StartMainThread(tests);
|
||||
}
|
||||
|
||||
void Ersky9xSimulator::stop()
|
||||
{
|
||||
StopMainThread();
|
||||
StopEepromThread();
|
||||
}
|
||||
|
||||
void Ersky9xSimulator::getValues(TxOutputs &outputs)
|
||||
{
|
||||
#define GETVALUES_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
void Ersky9xSimulator::setValues(TxInputs &inputs)
|
||||
{
|
||||
#define SETVALUES_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
void Ersky9xSimulator::setTrim(unsigned int idx, int value)
|
||||
{
|
||||
Ersky9x::setTrim(idx, value);
|
||||
}
|
||||
|
||||
void Ersky9xSimulator::getTrims(Trims & trims)
|
||||
{
|
||||
trims.extended = false;
|
||||
Ersky9x::getTrims(trims.values);
|
||||
}
|
||||
|
||||
const char * Ersky9xSimulator::getError()
|
||||
{
|
||||
#define GETERROR_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Author - Bertrand Songis <bsongis@gmail.com>
|
||||
*
|
||||
* Based on 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ersky9x_simulator_h
|
||||
#define ersky9x_simulator_h
|
||||
|
||||
#include "simulatorinterface.h"
|
||||
|
||||
class RadioData;
|
||||
class Ersky9xInterface;
|
||||
|
||||
class Ersky9xSimulator : public SimulatorInterface {
|
||||
|
||||
public:
|
||||
|
||||
Ersky9xSimulator(Ersky9xInterface *);
|
||||
|
||||
virtual void start(RadioData & radioData, bool tests);
|
||||
|
||||
virtual void stop();
|
||||
|
||||
virtual bool timer10ms();
|
||||
|
||||
virtual uint8_t * getLcd();
|
||||
|
||||
virtual bool lcdChanged(bool & lightEnable);
|
||||
|
||||
virtual void setValues(TxInputs &inputs);
|
||||
|
||||
virtual void getValues(TxOutputs &outputs);
|
||||
|
||||
virtual void setTrim(unsigned int idx, int value);
|
||||
|
||||
virtual void getTrims(Trims & trims);
|
||||
|
||||
virtual unsigned int getPhase() { return 0; }
|
||||
|
||||
virtual const char * getPhaseName(unsigned int phase) { return 0; }
|
||||
|
||||
virtual const char * getError();
|
||||
|
||||
virtual void sendTelemetry(uint8_t * data, unsigned int len) {};
|
||||
|
||||
virtual uint8_t getSensorInstance(uint16_t id, uint8_t defaultValue = 0) { return 0; };
|
||||
|
||||
virtual uint16_t getSensorRatio(uint16_t id) { return 0; };
|
||||
|
||||
virtual void setTrainerInput(unsigned int inputNumber, int16_t value) {};
|
||||
|
||||
virtual void setLuaStateReloadPermanentScripts() {};
|
||||
|
||||
protected:
|
||||
|
||||
Ersky9xInterface * ersky9xInterface;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -17,7 +17,7 @@
|
|||
#include <iostream>
|
||||
#include "gruvin9xinterface.h"
|
||||
#include "gruvin9xeeprom.h"
|
||||
#include "file.h"
|
||||
#include "rlefile.h"
|
||||
#include "appdata.h"
|
||||
|
||||
#define FILE_TYP_GENERAL 1
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "opentxeeprom.h"
|
||||
#include "open9xGruvin9xeeprom.h"
|
||||
#include "open9xSky9xeeprom.h"
|
||||
#include "file.h"
|
||||
#include "rlefile.h"
|
||||
#include "appdata.h"
|
||||
|
||||
#define OPENTX_FIRMWARE_DOWNLOADS "http://downloads-22.open-tx.org/firmware"
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
set(TH9X_CHECKOUT_DIRECTORY ${PROJECT_BINARY_DIR}/firmwares/th9x)
|
||||
add_custom_command(
|
||||
OUTPUT ${TH9X_CHECKOUT_DIRECTORY}/th9xsimulator.cpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${TH9X_CHECKOUT_DIRECTORY}
|
||||
COMMAND cd ${TH9X_CHECKOUT_DIRECTORY} && svn checkout http://th9x.googlecode.com/svn/trunk/src@285 .
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/firmwares/th9x/th9xsimulator.cpp ${TH9X_CHECKOUT_DIRECTORY}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/firmwares/th9x/th9xsimulator.cpp
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROJECT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_library(th9x-simulator th9xsimulator.cpp)
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* Author - Bertrand Songis <bsongis@gmail.com>
|
||||
*
|
||||
* Based on 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 "firmwares/th9x/th9xsimulator.h"
|
||||
#include "firmwares/th9x/th9xinterface.h"
|
||||
|
||||
#define SIM
|
||||
#define SIMU
|
||||
#define SIMU_EXCEPTIONS
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#define NUM_POTS 3
|
||||
#define NUM_SLIDERS 0
|
||||
#define NUM_CSW 12
|
||||
#define SWSRC_SW1 10
|
||||
|
||||
#include <exception>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Th9x {
|
||||
|
||||
#include "simpgmspace.h"
|
||||
#include "th9x.cpp"
|
||||
#include "stamp.cpp"
|
||||
#include "menus.cpp"
|
||||
#include "pers.cpp"
|
||||
#include "file.cpp"
|
||||
#include "lcd.cpp"
|
||||
#include "drivers.cpp"
|
||||
#include "foldedlist.cpp"
|
||||
#include "simpgmspace.cpp"
|
||||
#include "pulses.cpp"
|
||||
|
||||
int16_t g_anas[7];
|
||||
char g_title[80] = "";
|
||||
|
||||
uint16_t anaIn(uint8_t chan)
|
||||
{
|
||||
if (chan == 7)
|
||||
return 750;
|
||||
else
|
||||
return 512 + g_anas[chan];
|
||||
}
|
||||
|
||||
bool hasExtendedTrims()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void setTrim(uint8_t idx, int8_t value)
|
||||
{
|
||||
g_model.trimData[idx].itrim = trimRevertM(value, g_model.trimData[idx].tmode);
|
||||
}
|
||||
|
||||
void getTrims(int16_t values[4])
|
||||
{
|
||||
for (int i=0; i<4; i++) {
|
||||
values[i] = trimVal(i);
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_RESV_mismatch(void)
|
||||
{
|
||||
assert(!"Should never been called. Only needed by VC++ (debug mode)");
|
||||
}
|
||||
|
||||
#define TRIMS_GPIO_REG_LHL pind
|
||||
#define TRIMS_GPIO_REG_LVD pind
|
||||
#define TRIMS_GPIO_REG_RVU pind
|
||||
#define TRIMS_GPIO_REG_RHL pind
|
||||
#define TRIMS_GPIO_REG_LHR pind
|
||||
#define TRIMS_GPIO_REG_LVU pind
|
||||
#define TRIMS_GPIO_REG_RVD pind
|
||||
#define TRIMS_GPIO_REG_RHR pind
|
||||
#define PIN_TRIM_LH_L (1<<INP_D_TRM_LH_DWN)
|
||||
#define PIN_TRIM_LV_DN (1<<INP_D_TRM_LV_DWN)
|
||||
#define PIN_TRIM_RV_UP (1<<INP_D_TRM_RV_UP)
|
||||
#define PIN_TRIM_RH_L (1<<INP_D_TRM_RH_DWN)
|
||||
#define PIN_TRIM_LH_R (1<<INP_D_TRM_LH_UP)
|
||||
#define PIN_TRIM_LV_UP (1<<INP_D_TRM_LV_UP)
|
||||
#define PIN_TRIM_RV_DN (1<<INP_D_TRM_RV_DWN)
|
||||
#define PIN_TRIM_RH_R (1<<INP_D_TRM_RH_UP)
|
||||
|
||||
#define TRIM_CASE(key, pin, mask) \
|
||||
case key: \
|
||||
if (state) pin |= mask; else pin &= ~mask;\
|
||||
break;
|
||||
|
||||
void simuSetTrim(uint8_t trim, bool state)
|
||||
{
|
||||
switch (trim) {
|
||||
TRIM_CASE(0, TRIMS_GPIO_REG_LHL, PIN_TRIM_LH_L)
|
||||
TRIM_CASE(1, TRIMS_GPIO_REG_LHR, PIN_TRIM_LH_R)
|
||||
TRIM_CASE(2, TRIMS_GPIO_REG_LVD, PIN_TRIM_LV_DN)
|
||||
TRIM_CASE(3, TRIMS_GPIO_REG_LVU, PIN_TRIM_LV_UP)
|
||||
TRIM_CASE(4, TRIMS_GPIO_REG_RVD, PIN_TRIM_RV_DN)
|
||||
TRIM_CASE(5, TRIMS_GPIO_REG_RVU, PIN_TRIM_RV_UP)
|
||||
TRIM_CASE(6, TRIMS_GPIO_REG_RHL, PIN_TRIM_RH_L)
|
||||
TRIM_CASE(7, TRIMS_GPIO_REG_RHR, PIN_TRIM_RH_R)
|
||||
}
|
||||
}
|
||||
|
||||
#define SWITCH_CASE(swtch, pin, mask) \
|
||||
case swtch: \
|
||||
if (state) pin &= ~(mask); else pin |= (mask); \
|
||||
break;
|
||||
#define SWITCH_3_CASE(swtch, pin1, pin2, mask1, mask2) \
|
||||
case swtch: \
|
||||
if (state >= 0) pin1 &= ~(mask1); else pin1 |= (mask1); \
|
||||
if (state <= 0) pin2 &= ~(mask2); else pin2 |= (mask2); \
|
||||
break;
|
||||
|
||||
void simuSetSwitch(uint8_t swtch, int8_t state)
|
||||
{
|
||||
switch (swtch) {
|
||||
SWITCH_CASE(0, pine, 1<<INP_E_ThrCt)
|
||||
SWITCH_CASE(4, pine, 1<<INP_E_AileDR)
|
||||
SWITCH_3_CASE(3, ping, pine, (1<<INP_G_ID1), (1<<INP_E_ID2))
|
||||
SWITCH_CASE(1, ping, 1<<INP_G_RuddDR)
|
||||
SWITCH_CASE(2, pine, 1<<INP_E_ElevDR)
|
||||
SWITCH_CASE(5, pine, 1<<INP_E_Gear)
|
||||
SWITCH_CASE(6, pine, 1<<INP_E_Trainer)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define KEY_CASE(key, pin, mask) \
|
||||
case key: \
|
||||
if (state) pin |= mask; else pin &= ~mask;\
|
||||
break;
|
||||
|
||||
void simuSetKey(uint8_t key, bool state)
|
||||
{
|
||||
switch (key) {
|
||||
KEY_CASE(KEY_MENU, pinb, (1<<INP_B_KEY_MEN))
|
||||
KEY_CASE(KEY_EXIT, pinb, (1<<INP_B_KEY_EXT))
|
||||
KEY_CASE(KEY_RIGHT, pinb, (1<<INP_B_KEY_RGT))
|
||||
KEY_CASE(KEY_LEFT, pinb, (1<<INP_B_KEY_LFT))
|
||||
KEY_CASE(KEY_UP, pinb, (1<<INP_B_KEY_UP))
|
||||
KEY_CASE(KEY_DOWN, pinb, (1<<INP_B_KEY_DWN))
|
||||
}
|
||||
}
|
||||
|
||||
#define isBacklightEnabled() (PORTB & (1<<OUT_B_LIGHT))
|
||||
|
||||
}
|
||||
|
||||
using namespace Th9x;
|
||||
|
||||
Th9xSimulator::Th9xSimulator(Th9xInterface * th9xInterface):
|
||||
th9xInterface(th9xInterface)
|
||||
{
|
||||
}
|
||||
|
||||
bool Th9xSimulator::timer10ms()
|
||||
{
|
||||
#define TIMER10MS_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
uint8_t * Th9xSimulator::getLcd()
|
||||
{
|
||||
return (::uint8_t *)simuLcdBuf;
|
||||
}
|
||||
|
||||
bool Th9xSimulator::lcdChanged(bool & lightEnable)
|
||||
{
|
||||
#define LCDCHANGED_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
void Th9xSimulator::start(RadioData &radioData, bool tests)
|
||||
{
|
||||
th9xInterface->save(&eeprom[0], radioData);
|
||||
StartMainThread(tests);
|
||||
}
|
||||
|
||||
void Th9xSimulator::stop()
|
||||
{
|
||||
StopMainThread();
|
||||
}
|
||||
|
||||
void Th9xSimulator::getValues(TxOutputs &outputs)
|
||||
{
|
||||
#define GETVALUES_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
for (int i=0; i<8; i++)
|
||||
outputs.chans[i] *= 2;
|
||||
}
|
||||
|
||||
void Th9xSimulator::setValues(TxInputs &_inputs)
|
||||
{
|
||||
TxInputs inputs = _inputs;
|
||||
for (int i=0; i<4; i++)
|
||||
inputs.sticks[i] /= 2;
|
||||
for (int i=0; i<3; i++)
|
||||
inputs.pots[i] /= 2;
|
||||
#define SETVALUES_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
void Th9xSimulator::setTrim(unsigned int idx, int value)
|
||||
{
|
||||
Th9x::setTrim(idx, value);
|
||||
}
|
||||
|
||||
void Th9xSimulator::getTrims(Trims & trims)
|
||||
{
|
||||
trims.extended = false;
|
||||
Th9x::getTrims(trims.values);
|
||||
}
|
||||
|
||||
const char * Th9xSimulator::getError()
|
||||
{
|
||||
#define GETERROR_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Author - Bertrand Songis <bsongis@gmail.com>
|
||||
*
|
||||
* Based on 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef th9x_simulator_h
|
||||
#define th9x_simulator_h
|
||||
|
||||
#include "simulatorinterface.h"
|
||||
|
||||
class RadioData;
|
||||
class Th9xInterface;
|
||||
|
||||
class Th9xSimulator : public SimulatorInterface {
|
||||
|
||||
public:
|
||||
|
||||
Th9xSimulator(Th9xInterface *);
|
||||
|
||||
virtual void start(RadioData & radioData, bool tests);
|
||||
|
||||
virtual void stop();
|
||||
|
||||
virtual bool timer10ms();
|
||||
|
||||
virtual uint8_t * getLcd();
|
||||
|
||||
virtual bool lcdChanged(bool & lightEnable);
|
||||
|
||||
virtual void setValues(TxInputs &inputs);
|
||||
|
||||
virtual void getValues(TxOutputs &outputs);
|
||||
|
||||
virtual void setTrim(unsigned int idx, int value);
|
||||
|
||||
virtual void getTrims(Trims & trims);
|
||||
|
||||
virtual unsigned int getPhase() { return 0; }
|
||||
|
||||
virtual const char * getError();
|
||||
|
||||
protected:
|
||||
|
||||
Th9xInterface * th9xInterface;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -17,8 +17,7 @@
|
|||
#include <iostream>
|
||||
#include "th9xinterface.h"
|
||||
#include "th9xeeprom.h"
|
||||
#include "simulator/th9xsimulator.h"
|
||||
#include "file.h"
|
||||
#include "rlefile.h"
|
||||
#include "appdata.h"
|
||||
|
||||
#define FILE_TYP_GENERAL 1
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "appdata.h"
|
||||
#include "progressdialog.h"
|
||||
#include "radiointerface.h"
|
||||
#include "converteeprom.h"
|
||||
#include "storage_eeprom.h"
|
||||
#include "splashlibrarydialog.h"
|
||||
|
||||
FlashEEpromDialog::FlashEEpromDialog(QWidget *parent, const QString &filename):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "flashfirmwaredialog.h"
|
||||
#include "ui_flashfirmwaredialog.h"
|
||||
#include "appdata.h"
|
||||
#include "converteeprom.h"
|
||||
#include "storage_eeprom.h"
|
||||
#include "eeprominterface.h"
|
||||
#include "firmwareinterface.h"
|
||||
#include "process_flash.h"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define BIN_FILES_FILTER "BIN files (*.bin);;"
|
||||
#define DFU_FILES_FILTER "DFU files (*.dfu);;"
|
||||
#define EEPE_FILES_FILTER "EEPE EEPROM files (*.eepe);;"
|
||||
#define OTX_FILES_FILTER "OpenTX files (*.otx);;"
|
||||
#define EEPROM_FILES_FILTER "EEPE files (*.eepe *.bin *.hex);;" EEPE_FILES_FILTER BIN_FILES_FILTER HEX_FILES_FILTER
|
||||
#define FLASH_FILES_FILTER "FLASH files (*.bin *.hex *.dfu);;" BIN_FILES_FILTER HEX_FILES_FILTER DFU_FILES_FILTER
|
||||
#define EXTERNAL_EEPROM_FILES_FILTER "EEPROM files (*.bin *.hex);;" BIN_FILES_FILTER HEX_FILES_FILTER
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include "qcustomplot/qcustomplot.h"
|
||||
#include "qcustomplot.h"
|
||||
|
||||
#define INVALID_MIN 999999
|
||||
#define INVALID_MAX -999999
|
||||
|
|
|
@ -315,7 +315,7 @@
|
|||
<customwidget>
|
||||
<class>QCustomPlot</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qcustomplot/qcustomplot.h</header>
|
||||
<header>qcustomplot.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
#include "process_sync.h"
|
||||
#include "radiointerface.h"
|
||||
#include "progressdialog.h"
|
||||
#include "storage_sdcard.h"
|
||||
|
||||
#define OPENTX_COMPANION_DOWNLOADS "http://downloads-22.open-tx.org/companion"
|
||||
#define DONATE_STR "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QUZ48K4SEXDP2"
|
||||
|
@ -576,22 +577,29 @@ void MainWindow::openDocURL()
|
|||
|
||||
void MainWindow::openFile()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Models and Settings file"), g.eepromDir(), tr(EEPROM_FILES_FILTER));
|
||||
if (!fileName.isEmpty()) {
|
||||
g.eepromDir(QFileInfo(fileName).dir().absolutePath());
|
||||
QString fileFilter;
|
||||
if (GetCurrentFirmware()->getBoard() == BOARD_HORUS) {
|
||||
fileFilter = tr(OTX_FILES_FILTER);
|
||||
}
|
||||
else {
|
||||
fileFilter = tr(EEPROM_FILES_FILTER);
|
||||
}
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Models and Settings file"), g.eepromDir(), fileFilter);
|
||||
if (!fileName.isEmpty()) {
|
||||
g.eepromDir(QFileInfo(fileName).dir().absolutePath());
|
||||
|
||||
QMdiSubWindow *existing = findMdiChild(fileName);
|
||||
if (existing) {
|
||||
mdiArea->setActiveSubWindow(existing);
|
||||
return;
|
||||
}
|
||||
|
||||
MdiChild *child = createMdiChild();
|
||||
if (child->loadFile(fileName)) {
|
||||
statusBar()->showMessage(tr("File loaded"), 2000);
|
||||
child->show();
|
||||
}
|
||||
QMdiSubWindow *existing = findMdiChild(fileName);
|
||||
if (existing) {
|
||||
mdiArea->setActiveSubWindow(existing);
|
||||
return;
|
||||
}
|
||||
|
||||
MdiChild *child = createMdiChild();
|
||||
if (child->loadFile(fileName)) {
|
||||
statusBar()->showMessage(tr("File loaded"), 2000);
|
||||
child->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::save()
|
||||
|
@ -764,6 +772,46 @@ void MainWindow::loadBackup()
|
|||
|
||||
void MainWindow::readEeprom()
|
||||
{
|
||||
if(GetCurrentFirmware()->getBoard()== BOARD_HORUS) {
|
||||
// just an example
|
||||
QString path = findMassstoragePath("RADIO");
|
||||
if (path.isEmpty()) {
|
||||
qDebug() << "Horus card not found";
|
||||
return;
|
||||
}
|
||||
|
||||
QString realPath = path.remove(path.size()- 5, 5);
|
||||
|
||||
qDebug() << "Reading files from" << realPath;
|
||||
StorageSdcard storage;
|
||||
storage.read(realPath);
|
||||
|
||||
// display models.txt
|
||||
QString modelList = QString(storage.modelList);
|
||||
qDebug() << "Models: size" << modelList.size() << "contents" << modelList;
|
||||
|
||||
// info about radio.bin
|
||||
qDebug() << "Radio settings:" << storage.radio.size();
|
||||
|
||||
// info about all models
|
||||
QList<QString> models = storage.getModelsFileNames();
|
||||
qDebug() << "We have" << models.size() << "models:";
|
||||
foreach(QString filename, models) {
|
||||
QList<ModelFile>::const_iterator i = storage.getModelIterator(filename);
|
||||
if (i != storage.models.end()) {
|
||||
qDebug() << "\tModel:" << i->filename << "size" << i->data.size();
|
||||
}
|
||||
}
|
||||
|
||||
for (QList<ModelFile>::iterator i = storage.models.begin(); i != storage.models.end(); ++i) {
|
||||
}
|
||||
|
||||
|
||||
// for test immediately save to current dir
|
||||
storage.write("./");
|
||||
|
||||
}
|
||||
else {
|
||||
QString tempFile;
|
||||
|
||||
EEPROMInterface *eepromInterface = GetEepromInterface();
|
||||
|
@ -782,6 +830,7 @@ void MainWindow::readEeprom()
|
|||
child->show();
|
||||
qunlink(tempFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::readFirmwareFromRadio(const QString &filename)
|
||||
|
@ -922,7 +971,7 @@ void MainWindow::updateMenus()
|
|||
bool hasMdiChild = (activeMdiChild() != 0);
|
||||
bool hasSelection = (activeMdiChild() && activeMdiChild()->hasSelection());
|
||||
|
||||
if(GetCurrentFirmware()->getBoard() == BOARD_HORUS) {
|
||||
if(false /*GetCurrentFirmware()->getBoard() == BOARD_HORUS*/) {
|
||||
newAct->setEnabled(false);
|
||||
openAct->setEnabled(false);
|
||||
saveAct->setEnabled(false);
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "appdata.h"
|
||||
#include "wizarddialog.h"
|
||||
#include "flashfirmwaredialog.h"
|
||||
#include "storage_eeprom.h"
|
||||
#include "storage_sdcard.h"
|
||||
#include <QFileInfo>
|
||||
|
||||
#if defined WIN32 || !defined __GNUC__
|
||||
|
@ -334,7 +336,7 @@ bool MdiChild::loadFile(const QString &fileName, bool resetCurrentFile)
|
|||
tr("Error reading file %1:\n%2.")
|
||||
.arg(fileName)
|
||||
.arg(file.errorString()));
|
||||
|
||||
free(eeprom);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -343,6 +345,7 @@ bool MdiChild::loadFile(const QString &fileName, bool resetCurrentFile)
|
|||
std::bitset<NUM_ERRORS> errorsBackup((unsigned long long)LoadBackup(radioData, eeprom, eeprom_size, 0));
|
||||
if (!errorsBackup.test(ALL_OK)) {
|
||||
ShowEepromErrors(this, tr("Error"), tr("Invalid binary EEPROM File %1").arg(fileName), (errorsEeprom | errorsBackup).to_ulong());
|
||||
free(eeprom);
|
||||
return false;
|
||||
}
|
||||
if (errorsBackup.test(HAS_WARNINGS)) {
|
||||
|
@ -358,10 +361,48 @@ bool MdiChild::loadFile(const QString &fileName, bool resetCurrentFile)
|
|||
free(eeprom);
|
||||
return true;
|
||||
}
|
||||
else if (fileType == FILE_TYPE_OTX) { //read zip archive
|
||||
return loadOtxFile(fileName, resetCurrentFile);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MdiChild::loadOtxFile(const QString &fileName, bool resetCurrentFile)
|
||||
{
|
||||
// example of StorageSdcard usage
|
||||
|
||||
StorageSdcard storage;
|
||||
|
||||
storage.read(fileName);
|
||||
|
||||
// display models.txt
|
||||
QString modelList = QString(storage.modelList);
|
||||
qDebug() << "Models: size" << modelList.size() << "contents" << modelList;
|
||||
|
||||
// info about radio.bin
|
||||
qDebug() << "Radio settings:" << storage.radio.size();
|
||||
|
||||
// info about all models
|
||||
QList<QString> models = storage.getModelsFileNames();
|
||||
qDebug() << "We have" << models.size() << "models:";
|
||||
foreach(QString filename, models) {
|
||||
QList<ModelFile>::const_iterator i = storage.getModelIterator(filename);
|
||||
if (i != storage.models.end()) {
|
||||
qDebug() << "\tModel:" << i->filename << "size" << i->data.size();
|
||||
}
|
||||
}
|
||||
|
||||
for (QList<ModelFile>::iterator i = storage.models.begin(); i != storage.models.end(); ++i) {
|
||||
}
|
||||
|
||||
|
||||
// for test immediately save to another file
|
||||
storage.write(fileName + "test.otx");
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool MdiChild::save()
|
||||
{
|
||||
if (isUntitled) {
|
||||
|
|
|
@ -112,6 +112,7 @@ class MdiChild : public QWidget
|
|||
QString strippedName(const QString &fullFileName);
|
||||
void saveSelection();
|
||||
void restoreSelection();
|
||||
bool loadOtxFile(const QString &fileName, bool resetCurrentFile);
|
||||
|
||||
Ui::mdiChild *ui;
|
||||
|
||||
|
|
|
@ -421,6 +421,7 @@ QString findMassstoragePath(const QString &filename)
|
|||
temppath = entry->me_mountdir;
|
||||
eepromfile = temppath;
|
||||
eepromfile.append("/" + filename);
|
||||
qDebug() << "Searching for" << eepromfile;
|
||||
#if !defined __APPLE__
|
||||
QString fstype = entry->me_type;
|
||||
// qDebug() << eepromfile;
|
||||
|
|
26
companion/src/storage/CMakeLists.txt
Normal file
26
companion/src/storage/CMakeLists.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(storage_NAMES
|
||||
storage_eeprom
|
||||
storage_sdcard
|
||||
hexinterface
|
||||
# xmlinterface
|
||||
mountlist
|
||||
rlefile
|
||||
appdata
|
||||
firmwareinterface
|
||||
)
|
||||
|
||||
set(storage_SRCS
|
||||
)
|
||||
|
||||
set(storage_HDRS
|
||||
)
|
||||
|
||||
foreach(name ${storage_NAMES})
|
||||
set(storage_SRCS ${storage_SRCS} ${name}.cpp)
|
||||
set(storage_HDRS ${storage_HDRS} ${name}.h)
|
||||
endforeach()
|
||||
|
||||
add_library(storage ${storage_SRCS})
|
||||
target_link_libraries(storage Qt5::Core Qt5::Gui Qt5::Xml Qt5::Widgets)
|
|
@ -39,6 +39,8 @@ int getFileType(const QString &fullFileName)
|
|||
return FILE_TYPE_EEPE;
|
||||
else if (suffix == "XML")
|
||||
return FILE_TYPE_XML;
|
||||
else if (suffix == "OTX")
|
||||
return FILE_TYPE_OTX;
|
||||
else
|
||||
return 0;
|
||||
}
|
|
@ -35,6 +35,7 @@
|
|||
#define FILE_TYPE_EEPE 3
|
||||
#define FILE_TYPE_EEPM 4
|
||||
#define FILE_TYPE_XML 5
|
||||
#define FILE_TYPE_OTX 6
|
||||
|
||||
int getFileType(const QString &fullFileName);
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include "eeprominterface.h"
|
||||
#include "file.h"
|
||||
#include "rlefile.h"
|
||||
|
||||
RleFile::RleFile():
|
||||
eeprom(NULL),
|
|
@ -15,8 +15,8 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#ifndef file_h
|
||||
#define file_h
|
||||
#ifndef rlefile_h
|
||||
#define rlefile_h
|
||||
|
||||
#include "eeprominterface.h"
|
||||
|
106
companion/src/storage/storage_eeprom.cpp
Normal file
106
companion/src/storage/storage_eeprom.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
#include <QFile>
|
||||
#include "firmwareinterface.h"
|
||||
#include "storage_eeprom.h"
|
||||
|
||||
|
||||
unsigned long LoadEeprom(RadioData &radioData, const uint8_t *eeprom, const int size)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
|
||||
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->load(radioData, eeprom, size));
|
||||
if (result.test(ALL_OK)) {
|
||||
return result.to_ulong();
|
||||
}
|
||||
else {
|
||||
errors |= result;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.none()) {
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
}
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
unsigned long LoadBackup(RadioData & radioData, uint8_t * eeprom, int size, int index)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
|
||||
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadBackup(radioData, eeprom, size, index));
|
||||
if (result.test(ALL_OK)) {
|
||||
return result.to_ulong();
|
||||
}
|
||||
else {
|
||||
errors |= result;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.none()) {
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
}
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
|
||||
unsigned long LoadEepromXml(RadioData & radioData, QDomDocument & doc)
|
||||
{
|
||||
std::bitset<NUM_ERRORS> errors;
|
||||
|
||||
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
|
||||
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadxml(radioData, doc));
|
||||
if (result.test(ALL_OK)) {
|
||||
return result.to_ulong();
|
||||
}
|
||||
else {
|
||||
errors |= result;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.none()) {
|
||||
errors.set(UNKNOWN_ERROR);
|
||||
}
|
||||
return errors.to_ulong();
|
||||
}
|
||||
|
||||
bool convertEEprom(const QString &sourceEEprom, const QString &destinationEEprom, const QString &firmwareFilename)
|
||||
{
|
||||
Firmware *currentFirmware = GetCurrentFirmware();
|
||||
FirmwareInterface firmware(firmwareFilename);
|
||||
if (!firmware.isValid())
|
||||
return false;
|
||||
|
||||
unsigned int version = firmware.getEEpromVersion();
|
||||
unsigned int variant = firmware.getEEpromVariant();
|
||||
|
||||
QFile sourceFile(sourceEEprom);
|
||||
int eeprom_size = sourceFile.size();
|
||||
if (!eeprom_size)
|
||||
return false;
|
||||
|
||||
if (!sourceFile.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
|
||||
QByteArray eeprom(eeprom_size, 0);
|
||||
long result = sourceFile.read(eeprom.data(), eeprom_size);
|
||||
sourceFile.close();
|
||||
|
||||
QSharedPointer<RadioData> radioData = QSharedPointer<RadioData>(new RadioData());
|
||||
std::bitset<NUM_ERRORS> errors((unsigned long long)LoadEeprom(*radioData, (uint8_t *)eeprom.data(), eeprom_size));
|
||||
if (!errors.test(ALL_OK)
|
||||
|| !currentFirmware->saveEEPROM((uint8_t *)eeprom.data(), *radioData, variant, version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile destinationFile(destinationEEprom);
|
||||
if (!destinationFile.open(QIODevice::WriteOnly))
|
||||
return false;
|
||||
|
||||
result = destinationFile.write(eeprom.constData(), eeprom_size);
|
||||
destinationFile.close();
|
||||
if (result != eeprom_size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
29
companion/src/storage/storage_eeprom.h
Normal file
29
companion/src/storage/storage_eeprom.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Author - Bertrand Songis <bsongis@gmail.com>
|
||||
*
|
||||
* Based on 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef storage_eeprom_h
|
||||
#define storage_eeprom_h
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QString>
|
||||
#include "eeprominterface.h"
|
||||
|
||||
unsigned long LoadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index);
|
||||
unsigned long LoadEeprom(RadioData &radioData, const uint8_t *eeprom, int size);
|
||||
unsigned long LoadEepromXml(RadioData &radioData, QDomDocument &doc);
|
||||
bool convertEEprom(const QString &sourceEEprom, const QString &destinationEEprom, const QString &firmware);
|
||||
|
||||
#endif
|
280
companion/src/storage/storage_sdcard.cpp
Normal file
280
companion/src/storage/storage_sdcard.cpp
Normal file
|
@ -0,0 +1,280 @@
|
|||
#include <QFileInfo>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
#include "storage_sdcard.h"
|
||||
|
||||
// defines for miniz
|
||||
#include "miniz.c"
|
||||
|
||||
int readFromArchive(QByteArray & data, mz_zip_archive * zip_archive, unsigned int index)
|
||||
{
|
||||
size_t uncompSize;
|
||||
void * uncompData = mz_zip_reader_extract_to_heap(zip_archive, index, &uncompSize, 0);
|
||||
if (!uncompData) {
|
||||
return -1;
|
||||
}
|
||||
qDebug() << "Extracted file with index" << index << ",size" << uncompSize;
|
||||
data.append((const char *)uncompData, uncompSize);
|
||||
mz_free(uncompData);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int StorageSdcard::read(const QString & path)
|
||||
{
|
||||
return QFileInfo(path).isDir() ? readSdcard(path) : readOtx(path);
|
||||
}
|
||||
|
||||
int StorageSdcard::write(const QString & path)
|
||||
{
|
||||
return QFileInfo(path).isDir() ? writeSdcard(path) : writeOtx(path);
|
||||
}
|
||||
|
||||
int StorageSdcard::readOtx(const QString & path)
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
lastErrorMessage = QObject::tr("Error opening file %1:\n%2.").arg(path).arg(file.errorString());
|
||||
return -1;
|
||||
}
|
||||
QByteArray archiveContents = file.readAll();
|
||||
file.close();
|
||||
qDebug() << "File" << path << "read, size:" << archiveContents.size();
|
||||
|
||||
// open zip file
|
||||
mz_zip_archive zip_archive;
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
if (!mz_zip_reader_init_mem(&zip_archive, archiveContents.data(), archiveContents.size(), 0)) {
|
||||
lastErrorMessage = QObject::tr("Error opening OTX archive %1.").arg(path);
|
||||
qDebug() << lastErrorMessage;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// go trough all files in an archive
|
||||
QRegularExpression regexModel("MODELS/\\w+.bin", QRegularExpression::CaseInsensitiveOption);
|
||||
for (unsigned int i = 0; i < mz_zip_reader_get_num_files(&zip_archive); i++)
|
||||
{
|
||||
mz_zip_archive_file_stat file_stat;
|
||||
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) {
|
||||
lastErrorMessage = QObject::tr("mz_zip_reader_file_stat() failed!");
|
||||
qDebug() << lastErrorMessage;
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
// printf("Filename: \"%s\", Comment: \"%s\", Uncompressed size: %u, Compressed size: %u, Is Dir: %u\n", file_stat.m_filename, file_stat.m_comment, (uint)file_stat.m_uncomp_size, (uint)file_stat.m_comp_size, mz_zip_reader_is_file_a_directory(&zip_archive, i));
|
||||
|
||||
if (mz_zip_reader_is_file_a_directory(&zip_archive, i)) continue;
|
||||
|
||||
QString filename(file_stat.m_filename);
|
||||
if (regexModel.match(filename).hasMatch()) {
|
||||
qDebug() << "found model:" << filename;
|
||||
models.append(ModelFile());
|
||||
ModelFile & newModel = models.last();
|
||||
newModel.filename = QFileInfo(filename).fileName();
|
||||
if (readFromArchive(newModel.data, &zip_archive, i) < 0) {
|
||||
lastErrorMessage = QObject::tr("Can't extract file %1").arg(filename);
|
||||
qDebug() << lastErrorMessage;
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (QString::compare(filename, "RADIO/radio.bin", Qt::CaseInsensitive) == 0) {
|
||||
if (readFromArchive(radio, &zip_archive, i) < 0) {
|
||||
lastErrorMessage = QObject::tr("Can't extract file %1").arg(filename);
|
||||
qDebug() << lastErrorMessage;
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (QString::compare(filename, "RADIO/models.txt", Qt::CaseInsensitive) == 0) {
|
||||
if (readFromArchive(modelList, &zip_archive, i) < 0) {
|
||||
lastErrorMessage = QObject::tr("Can't extract file %1").arg(filename);
|
||||
qDebug() << lastErrorMessage;
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "Unknown file " << filename;
|
||||
}
|
||||
|
||||
}
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StorageSdcard::readFile(QByteArray & data, const QString & path)
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
lastErrorMessage = QObject::tr("Error opening file %1:\n%2.").arg(path).arg(file.errorString());
|
||||
throw StorageSdcardReadFileError();
|
||||
}
|
||||
data = file.readAll();
|
||||
file.close();
|
||||
qDebug() << "File" << path << "read, size:" << data.size();
|
||||
}
|
||||
|
||||
int StorageSdcard::readSdcard(const QString & path)
|
||||
{
|
||||
try {
|
||||
readFile(radio, path + "/RADIO/radio.bin");
|
||||
readFile(modelList, path + "RADIO/models.txt");
|
||||
|
||||
QDir dir(path + "MODELS/");
|
||||
QStringList filters;
|
||||
filters << "*.bin";
|
||||
foreach(QString filename, dir.entryList(filters, QDir::Files)) {
|
||||
qDebug() << "found" << filename;
|
||||
models.append(ModelFile());
|
||||
ModelFile & newModel = models.last();
|
||||
newModel.filename = QFileInfo(filename).fileName();
|
||||
readFile(newModel.data, path + "MODELS/" + filename);
|
||||
}
|
||||
}
|
||||
catch (StorageSdcardReadFileError) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StorageSdcard::writeFile(const QByteArray & data, const QString & path)
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.open(QFile::WriteOnly)) {
|
||||
lastErrorMessage = QObject::tr("Error opening file %1:\n%2.").arg(path).arg(file.errorString());
|
||||
throw StorageSdcardWriteFileError();
|
||||
}
|
||||
file.write(data.data(), data.size());
|
||||
file.close();
|
||||
qDebug() << "File" << path << "written, size:" << data.size();
|
||||
}
|
||||
|
||||
int StorageSdcard::writeSdcard(const QString & path)
|
||||
{
|
||||
try {
|
||||
QDir dir(path);
|
||||
dir.mkdir("RADIO");
|
||||
writeFile(radio, path + "/RADIO/radio.bin");
|
||||
writeFile(modelList, path + "RADIO/models.txt");
|
||||
|
||||
dir.mkdir("MODELS");
|
||||
for (QList<ModelFile>::const_iterator i = models.begin(); i != models.end(); ++i) {
|
||||
qDebug() << "writing" << i->filename;
|
||||
writeFile(i->data, path + "MODELS/" + i->filename);
|
||||
}
|
||||
}
|
||||
catch (StorageSdcardWriteFileError) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MZ_ALLOCATION_SIZE (32*1024)
|
||||
|
||||
int StorageSdcard::writeOtx(const QString & path)
|
||||
{
|
||||
qDebug() << "Saving to archive" << path;
|
||||
mz_zip_archive zip_archive;
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
|
||||
if (!mz_zip_writer_init_heap(&zip_archive, 0, MZ_ALLOCATION_SIZE)) {
|
||||
lastErrorMessage = QObject::tr("Error initializing OTX archive writer");
|
||||
qDebug() << lastErrorMessage;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// add radio.bin
|
||||
if (!mz_zip_writer_add_mem(&zip_archive, "RADIO/radio.bin", radio.data(), radio.size(), MZ_DEFAULT_LEVEL)) {
|
||||
lastErrorMessage = QObject::tr("Error adding %1 to OTX archive").arg("RADIO/radio.bin");
|
||||
qDebug() << lastErrorMessage;
|
||||
mz_zip_writer_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// add models.txt
|
||||
if (!mz_zip_writer_add_mem(&zip_archive, "RADIO/models.txt", modelList.data(), modelList.size(), MZ_DEFAULT_LEVEL)) {
|
||||
lastErrorMessage = QObject::tr("Error adding %1 to OTX archive").arg("RADIO/models.txt");
|
||||
qDebug() << lastErrorMessage;
|
||||
mz_zip_writer_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// add all models
|
||||
for (QList<ModelFile>::iterator i = models.begin(); i != models.end(); ++i) {
|
||||
QString filename = "MODELS/" + i->filename;
|
||||
qDebug() << "\tadding model:" << filename << "size" << i->data.size();
|
||||
if (!mz_zip_writer_add_mem(&zip_archive, filename.toLatin1(), i->data.data(), i->data.size(), MZ_DEFAULT_LEVEL)) {
|
||||
lastErrorMessage = QObject::tr("Error adding %1 to OTX archive").arg(filename);
|
||||
qDebug() << lastErrorMessage;
|
||||
mz_zip_writer_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// finalize archive and get contents
|
||||
char * archiveContents;
|
||||
size_t archiveSize;
|
||||
if (!mz_zip_writer_finalize_heap_archive(&zip_archive, (void **)&archiveContents, &archiveSize)) {
|
||||
lastErrorMessage = QObject::tr("Error creating OTX archive");
|
||||
qDebug() << lastErrorMessage;
|
||||
mz_zip_writer_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
qDebug() << "Archive size" << archiveSize;
|
||||
|
||||
// write contents to file
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
lastErrorMessage = QObject::tr("Error creating OTX file %1:\n%2.").arg(path).arg(file.errorString());
|
||||
qDebug() << lastErrorMessage;
|
||||
mz_zip_writer_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qint64 result = file.write(archiveContents, archiveSize);
|
||||
if(result != (qint64)archiveSize) {
|
||||
lastErrorMessage = QObject::tr("Error writing file %1:\n%2.").arg(path).arg(file.errorString());
|
||||
mz_zip_writer_end(&zip_archive);
|
||||
return -1;
|
||||
}
|
||||
file.close();
|
||||
|
||||
mz_zip_writer_end(&zip_archive);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QByteArray & StorageSdcard::getModelData(const QString & filename) const
|
||||
{
|
||||
for (QList<ModelFile>::const_iterator i = models.begin(); i != models.end(); ++i) {
|
||||
if (filename == i->filename) return i->data;
|
||||
}
|
||||
throw StorageSdcardModelNotFound();
|
||||
}
|
||||
|
||||
|
||||
QList<ModelFile>::iterator StorageSdcard::getModelIterator(const QString & filename)
|
||||
{
|
||||
for (QList<ModelFile>::iterator i = models.begin(); i != models.end(); ++i) {
|
||||
if (filename == i->filename) return i;
|
||||
}
|
||||
return models.end();
|
||||
}
|
||||
|
||||
QList<ModelFile>::const_iterator StorageSdcard::getModelIterator(const QString & filename) const
|
||||
{
|
||||
for (QList<ModelFile>::const_iterator i = models.begin(); i != models.end(); ++i) {
|
||||
if (filename == i->filename) return i;
|
||||
}
|
||||
return models.end();
|
||||
}
|
||||
|
||||
QList<QString> StorageSdcard::getModelsFileNames() const
|
||||
{
|
||||
QList<QString> result;
|
||||
for (QList<ModelFile>::const_iterator i = models.begin(); i != models.end(); ++i) {
|
||||
result.append(i->filename);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
95
companion/src/storage/storage_sdcard.h
Normal file
95
companion/src/storage/storage_sdcard.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Author - Bertrand Songis <bsongis@gmail.com>
|
||||
*
|
||||
* Based on 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef storage_sdcard_h
|
||||
#define storage_sdcard_h
|
||||
|
||||
#include <QList>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QDir>
|
||||
|
||||
/*
|
||||
This class implements a storage model used for radios that
|
||||
store all settings on the SD card (currently only Hours)
|
||||
|
||||
Disk storage format:
|
||||
* uses extension OTX
|
||||
* its a normal ZIP archive containing the same directory
|
||||
structure as the SD card in the radio. Only the relevant
|
||||
directories and files are included.
|
||||
*/
|
||||
|
||||
class StorageSdcardModelNotFound {};
|
||||
class StorageSdcardReadFileError {};
|
||||
class StorageSdcardWriteFileError {};
|
||||
|
||||
// representation of modelXX.bin file
|
||||
struct ModelFile {
|
||||
QString filename; // file name (without path)
|
||||
QByteArray data; // file contents
|
||||
};
|
||||
|
||||
|
||||
class StorageSdcard {
|
||||
public:
|
||||
/*
|
||||
Reads models and radio settings from:
|
||||
* if a file is specified in path, from that file (OTX archive format)
|
||||
* if a path is specified, from that path (where it expects to find files like on the SD card)
|
||||
*/
|
||||
int read(const QString & path);
|
||||
|
||||
/*
|
||||
|Writes models and radio settings to:
|
||||
* if a file is specified in path, to that file (OTX archive format)
|
||||
* if a path is specified, to that path (layout created is like on the SD card)
|
||||
*/
|
||||
int write(const QString & path);
|
||||
|
||||
/*
|
||||
Returns a model data for specified model
|
||||
*/
|
||||
const QByteArray & getModelData(const QString & filename) const;
|
||||
|
||||
/*
|
||||
Returns a model iterator for specified model
|
||||
*/
|
||||
QList<ModelFile>::iterator getModelIterator(const QString & filename);
|
||||
QList<ModelFile>::const_iterator getModelIterator(const QString & filename) const;
|
||||
|
||||
/*
|
||||
Returns a list of all model bin files (their filenames)
|
||||
*/
|
||||
QList<QString> getModelsFileNames() const;
|
||||
|
||||
QString lastErrorMessage;
|
||||
QByteArray radio; // radio settings (radio.bin)
|
||||
QByteArray modelList; // model names and categories (models.txt)
|
||||
QList<ModelFile> models; // collection of model data (modelXX.bin)
|
||||
|
||||
private:
|
||||
int readOtx(const QString & path);
|
||||
int readSdcard(const QString & path);
|
||||
int writeOtx(const QString & path);
|
||||
int writeSdcard(const QString & path);
|
||||
|
||||
void readFile(QByteArray & data, const QString & path);
|
||||
void writeFile(const QByteArray & data, const QString & path);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
1
companion/src/thirdparty/miniz/CMakeLists.txt
vendored
Normal file
1
companion/src/thirdparty/miniz/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
add_definitions(-DFOO)
|
4920
companion/src/thirdparty/miniz/miniz.c
vendored
Normal file
4920
companion/src/thirdparty/miniz/miniz.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue