1
0
Fork 0
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:
Damjan Adamic 2016-11-16 13:05:57 +01:00 committed by Bertrand Songis
parent fb27acf286
commit 60524f77f0
61 changed files with 5614 additions and 1104 deletions

View file

@ -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)

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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()

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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"
}

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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"
}

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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)

View file

@ -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"
}

View file

@ -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

View file

@ -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

View file

@ -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):

View file

@ -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"

View file

@ -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

View file

@ -3,7 +3,7 @@
#include <QtCore>
#include <QtGui>
#include "qcustomplot/qcustomplot.h"
#include "qcustomplot.h"
#define INVALID_MIN 999999
#define INVALID_MAX -999999

View file

@ -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>

View file

@ -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);

View file

@ -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) {

View file

@ -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;

View file

@ -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;

View 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)

View file

@ -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;
}

View file

@ -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);

View file

@ -21,7 +21,7 @@
#include <assert.h>
#include <algorithm>
#include "eeprominterface.h"
#include "file.h"
#include "rlefile.h"
RleFile::RleFile():
eeprom(NULL),

View file

@ -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"

View 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;
}

View 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

View 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;
}

View 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

View file

@ -0,0 +1 @@
add_definitions(-DFOO)

4920
companion/src/thirdparty/miniz/miniz.c vendored Normal file

File diff suppressed because it is too large Load diff