1
0
Fork 0
mirror of https://github.com/EdgeTX/edgetx.git synced 2025-07-21 23:35:12 +03:00

[simulation] Fix some potential crashes & 26 memory leaks, improve LCD redraws. (#4634)

* [simulation] Hardening: Fix some potential crashes & 26 memory leaks, improve LCD performance.
  * [simpgmspace] Init trims; Make sure `REa` is really defined (to match board files).
  * [simpgmspace][opentxsimulator] Verify current running state before start/stop; Move rotary enc. init.
  * [simpgmspace][LcdWidget] Improve performance by moving LCD content change check to lcdRefresh() & limiting LcdWidget refresh time to 60 fps max.
  * [simueeprom] Ensure thread could be started, set default running state to false.
  * [simufatfs] Fix paths report trace.
  * [eepromimportexport] Fix memory leaks resulting from import debugging scheme being used.
  * [customdebug] Introduce new scheme for custom debug output in compliance with Qt recommendations (see docs for QLoggingCategory).
  * [opentxeeprom] Fix extra conversion table cache elements being created and also not properly deleted (and hence leaking).
  * [opentxinterface] Unregister EEpromInterfaces in unregisterOpenTxFirmwares();
  * [storage] Unregister storage factories on exit (fixes leak); create virtual StorageFormat/StorageFactory destructors (prevents warnings).
  * [helpers] GVarGroup now emits own signal, no need to pass ModelPanel pointer (removes dependency on modeledit.h)
  * [DebugOutput] Clear simulator trace hook before exiting (prevent possible issues); Fix leak and possible bad QString allocations when reading from buffer; Fix leak with combo box event filter.
  * [TelemetrySimulator] Fix leak by deleting LogPlaybackController object on exit; Only set up data fields once; convert timers to static.
  * [build] Consolidate all Companion/Simulator shared items in `common` library to reduce build time/etc (node & edge still remain awkward).

* [simulatorwidget] Delete removed spacer object (previously-forgotten "26th" leak).

* [DebugOutput] Fix stray trailing characters issue with new text buffer allocation (from previous commit); Increase maximum buffer sizes to better accommodate slower systems.

* Cosmetics.
This commit is contained in:
Max Paperno 2017-03-21 02:43:40 -04:00 committed by Bertrand Songis
parent 52e65179a8
commit 4aa0c1bbe4
28 changed files with 290 additions and 210 deletions

View file

@ -124,7 +124,9 @@ add_subdirectory(thirdparty/qxtcommandoptions)
set(common_SRCS set(common_SRCS
appdebugmessagehandler.cpp appdebugmessagehandler.cpp
boards.cpp boards.cpp
customdebug.cpp
eeprominterface.cpp eeprominterface.cpp
helpers.cpp
radiodata.cpp radiodata.cpp
firmwares/er9x/er9xeeprom.cpp firmwares/er9x/er9xeeprom.cpp
firmwares/er9x/er9xinterface.cpp firmwares/er9x/er9xinterface.cpp
@ -132,21 +134,25 @@ set(common_SRCS
firmwares/ersky9x/ersky9xinterface.cpp firmwares/ersky9x/ersky9xinterface.cpp
firmwares/opentx/opentxeeprom.cpp firmwares/opentx/opentxeeprom.cpp
firmwares/opentx/opentxinterface.cpp firmwares/opentx/opentxinterface.cpp
modeledit/node.cpp # used in simulator
modeledit/edge.cpp # used by node
) )
set(common_MOC_HDRS set(common_MOC_HDRS
appdebugmessagehandler.h appdebugmessagehandler.h
helpers.h
modeledit/node.h
) )
qt5_wrap_cpp(common_SRCS ${common_MOC_HDRS}) qt5_wrap_cpp(common_SRCS ${common_MOC_HDRS})
add_library(common ${common_SRCS}) add_library(common ${common_SRCS})
qt5_use_modules(common Core Xml Widgets) qt5_use_modules(common Core Xml Widgets)
target_link_libraries(common simulation)
############# Companion ############### ############# Companion ###############
set(companion_SRCS set(companion_SRCS
helpers.cpp
helpers_html.cpp helpers_html.cpp
mdichild.cpp mdichild.cpp
modelslist.cpp modelslist.cpp
@ -206,7 +212,6 @@ set(companion_MOC_HDRS
mdichild.h mdichild.h
mainwindow.h mainwindow.h
radionotfound.h radionotfound.h
helpers.h
wizarddialog.h wizarddialog.h
modelprinter.h modelprinter.h
multimodelprinter.h multimodelprinter.h
@ -259,9 +264,9 @@ qt5_wrap_ui(companion_SRCS ${companion_UIS})
qt5_wrap_cpp(companion_SRCS ${companion_MOC_HDRS}) qt5_wrap_cpp(companion_SRCS ${companion_MOC_HDRS})
qt5_add_translation(companion_QM ${companion_TS}) qt5_add_translation(companion_QM ${companion_TS})
qt5_add_resources(companion_RCC ${companion_RESOURCES}) qt5_add_resources(companion_RCC ${companion_RESOURCES})
add_custom_target(gen_qrc DEPENDS ${companion_RCC}) add_custom_target(gen_qrc DEPENDS ${companion_RCC} ${companion_QM})
add_executable(${COMPANION_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${companion_SRCS} ${companion_RCC} ${companion_QM}) add_executable(${COMPANION_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${companion_SRCS} ${companion_RCC})
add_dependencies(${COMPANION_NAME} gen_qrc) add_dependencies(${COMPANION_NAME} gen_qrc)
qt5_use_modules(${COMPANION_NAME} Core Widgets Network) qt5_use_modules(${COMPANION_NAME} Core Widgets Network)
@ -272,19 +277,7 @@ PrintTargetReport("${COMPANION_NAME}")
############# Standalone simulator ############### ############# Standalone simulator ###############
set(simu_SRCS set(simu_SRCS simulator.cpp )
modeledit/node.cpp
modeledit/edge.cpp
helpers.cpp
simulator.cpp
)
set(simu_MOC_HDRS
modeledit/node.h
helpers.h
)
qt5_wrap_cpp(simu_SRCS ${simu_MOC_HDRS} )
if(WIN32) if(WIN32)
list(APPEND simu_SRCS icon.rc) list(APPEND simu_SRCS icon.rc)
@ -293,7 +286,7 @@ endif()
add_executable(${SIMULATOR_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${simu_SRCS} ${companion_RCC}) add_executable(${SIMULATOR_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${simu_SRCS} ${companion_RCC})
add_dependencies(${SIMULATOR_NAME} gen_qrc) add_dependencies(${SIMULATOR_NAME} gen_qrc)
target_link_libraries(${SIMULATOR_NAME} PRIVATE simulation common shared storage qxtcommandoptions ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${WIN_LINK_LIBRARIES}) target_link_libraries(${SIMULATOR_NAME} PRIVATE simulation common storage qxtcommandoptions ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${WIN_LINK_LIBRARIES})
############# Translations #################### ############# Translations ####################

View file

@ -28,6 +28,7 @@
#endif #endif
#include "appdebugmessagehandler.h" #include "appdebugmessagehandler.h"
#include "customdebug.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "version.h" #include "version.h"
#include "appdata.h" #include "appdata.h"
@ -65,6 +66,8 @@ int main(int argc, char *argv[])
if (AppDebugMessageHandler::instance()) if (AppDebugMessageHandler::instance())
AppDebugMessageHandler::instance()->installAppMessageHandler(); AppDebugMessageHandler::instance()->installAppMessageHandler();
CustomDebug::setFilterRules();
g.init(); g.init();
QStringList strl = QApplication::arguments(); QStringList strl = QApplication::arguments();
@ -134,7 +137,7 @@ int main(int argc, char *argv[])
unregisterSimulators(); unregisterSimulators();
unregisterOpenTxFirmwares(); unregisterOpenTxFirmwares();
unregisterEEpromInterfaces(); unregisterStorageFactories();
#if defined(JOYSTICKS) || defined(SIMU_AUDIO) #if defined(JOYSTICKS) || defined(SIMU_AUDIO)
SDL_Quit(); SDL_Quit();

View file

@ -0,0 +1,36 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "customdebug.h"
Q_LOGGING_CATEGORY(eepromImport, "eeprom.import")
void CustomDebug::setFilterRules()
{
QString rules;
rules.append("eeprom.import=");
#if defined(DEBUG_STORAGE_IMPORT)
rules.append("true");
#else
rules.append("false");
#endif
QLoggingCategory::setFilterRules(rules);
}

View file

@ -21,15 +21,15 @@
#ifndef _CUSTOMDEBUG_H_ #ifndef _CUSTOMDEBUG_H_
#define _CUSTOMDEBUG_H_ #define _CUSTOMDEBUG_H_
#include <QDebug> #include <QLoggingCategory>
// Controls the generation of debug output for EEPROM import // Controls the generation of debug output for EEPROM import
#if defined(DEBUG_STORAGE_IMPORT) Q_DECLARE_LOGGING_CATEGORY(eepromImport)
inline QDebug eepromImportDebug() { return QDebug(QtDebugMsg); }
#else
#undef eepromImportDebug
inline QNoDebug eepromImportDebug() { return QNoDebug(); }
#endif
class CustomDebug
{
public:
static void setFilterRules();
};
#endif // _CUSTOMDEBUG_H_ #endif // _CUSTOMDEBUG_H_

View file

@ -181,7 +181,7 @@ class BaseUnsignedField: public DataField {
if (input[i]) if (input[i])
field |= ((container)1<<i); field |= ((container)1<<i);
} }
eepromImportDebug() << QString("\timported %1<%2>: 0x%3(%4)").arg(name).arg(N).arg(field, 0, 16).arg(field); qCDebug(eepromImport) << QString("\timported %1<%2>: 0x%3(%4)").arg(name).arg(N).arg(field, 0, 16).arg(field);
} }
virtual unsigned int size() virtual unsigned int size()
@ -238,7 +238,7 @@ class BoolField: public DataField {
virtual void ImportBits(const QBitArray & input) virtual void ImportBits(const QBitArray & input)
{ {
field = input[0] ? true : false; field = input[0] ? true : false;
eepromImportDebug() << QString("\timported %1<%2>: 0x%3(%4)").arg(name).arg(N).arg(field, 0, 16).arg(field); qCDebug(eepromImport) << QString("\timported %1<%2>: 0x%3(%4)").arg(name).arg(N).arg(field, 0, 16).arg(field);
} }
virtual unsigned int size() virtual unsigned int size()
@ -308,7 +308,7 @@ class SignedField: public DataField {
} }
field = (int)value; field = (int)value;
eepromImportDebug() << QString("\timported %1<%2>: 0x%3(%4)").arg(name).arg(N).arg(field, 0, 16).arg(field); qCDebug(eepromImport) << QString("\timported %1<%2>: 0x%3(%4)").arg(name).arg(N).arg(field, 0, 16).arg(field);
} }
virtual unsigned int size() virtual unsigned int size()
@ -369,7 +369,7 @@ class CharField: public DataField {
} }
field[i] = idx; field[i] = idx;
} }
eepromImportDebug() << QString("\timported %1<%2>: '%3'").arg(name).arg(N).arg(field); qCDebug(eepromImport) << QString("\timported %1<%2>: '%3'").arg(name).arg(N).arg(field);
} }
virtual unsigned int size() virtual unsigned int size()
@ -427,7 +427,7 @@ class ZCharField: public DataField {
else else
break; break;
} }
eepromImportDebug() << QString("\timported %1<%2>: '%3'").arg(name).arg(N).arg(field); qCDebug(eepromImport) << QString("\timported %1<%2>: '%3'").arg(name).arg(N).arg(field);
} }
virtual unsigned int size() virtual unsigned int size()
@ -453,7 +453,7 @@ class StructField: public DataField {
} }
inline void Append(DataField * field) { inline void Append(DataField * field) {
//eepromImportDebug() << QString("StructField(%1) appending field: %2").arg(name).arg(field->getName()); //qCDebug(eepromImport) << QString("StructField(%1) appending field: %2").arg(name).arg(field->getName());
fields.append(field); fields.append(field);
} }
@ -471,7 +471,7 @@ class StructField: public DataField {
virtual void ImportBits(const QBitArray & input) virtual void ImportBits(const QBitArray & input)
{ {
eepromImportDebug() << QString("\timporting %1[%2]:").arg(name).arg(fields.size()); qCDebug(eepromImport) << QString("\timporting %1[%2]:").arg(name).arg(fields.size());
int offset = 0; int offset = 0;
foreach(DataField *field, fields) { foreach(DataField *field, fields) {
unsigned int size = field->size(); unsigned int size = field->size();
@ -526,7 +526,7 @@ class TransformedField: public DataField {
virtual void ImportBits(const QBitArray & input) virtual void ImportBits(const QBitArray & input)
{ {
eepromImportDebug() << QString("\timporting TransformedField %1:").arg(field.getName()); qCDebug(eepromImport) << QString("\timporting TransformedField %1:").arg(field.getName());
field.ImportBits(input); field.ImportBits(input);
afterImport(); afterImport();
} }
@ -564,7 +564,7 @@ class ConversionTable {
after = 0; after = 0;
for (std::list<ConversionTuple>::iterator it=exportTable.begin(); it!=exportTable.end(); it++) { for (std::list<ConversionTuple>::iterator it=exportTable.begin(); it!=exportTable.end(); it++) {
ConversionTuple tuple = *it; ConversionTuple & tuple = *it;
if (before == tuple.a) { if (before == tuple.a) {
after = tuple.b; after = tuple.b;
return true; return true;
@ -579,7 +579,7 @@ class ConversionTable {
after = 0; after = 0;
for (std::list<ConversionTuple>::iterator it=importTable.begin(); it!=importTable.end(); it++) { for (std::list<ConversionTuple>::iterator it=importTable.begin(); it!=importTable.end(); it++) {
ConversionTuple tuple = *it; ConversionTuple & tuple = *it;
if (before == tuple.b) { if (before == tuple.b) {
after = tuple.a; after = tuple.a;
return true; return true;
@ -756,7 +756,7 @@ class ConversionField: public TransformedField {
if (scale) { if (scale) {
field *= scale; field *= scale;
} }
eepromImportDebug() << QString("\timported ConversionField<%1>:").arg(internalField.getName()) << QString(" before: %1, after: %2").arg(_field).arg(field); qCDebug(eepromImport) << QString("\timported ConversionField<%1>:").arg(internalField.getName()) << QString(" before: %1, after: %2").arg(_field).arg(field);
} }
protected: protected:

View file

@ -160,6 +160,7 @@ class SwitchesConversionTable: public ConversionTable {
} }
} }
protected: protected:
void addConversion(const RawSwitch & sw, const int b) void addConversion(const RawSwitch & sw, const int b)
@ -199,7 +200,7 @@ class SwitchesConversionTable: public ConversionTable {
static SwitchesConversionTable * getInstance(Board::Type board, unsigned int version, unsigned long flags=0) static SwitchesConversionTable * getInstance(Board::Type board, unsigned int version, unsigned long flags=0)
{ {
for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) { for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) {
Cache element = *it; Cache & element = *it;
if (element.board == board && element.version == version && element.flags == flags) if (element.board == board && element.version == version && element.flags == flags)
return element.table; return element.table;
} }
@ -211,8 +212,9 @@ class SwitchesConversionTable: public ConversionTable {
static void Cleanup() static void Cleanup()
{ {
for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) { for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) {
Cache element = *it; Cache & element = *it;
delete element.table; if (element.table)
delete element.table;
} }
internalCache.clear(); internalCache.clear();
} }
@ -386,7 +388,7 @@ class SourcesConversionTable: public ConversionTable {
static SourcesConversionTable * getInstance(Board::Type board, unsigned int version, unsigned int variant, unsigned long flags=0) static SourcesConversionTable * getInstance(Board::Type board, unsigned int version, unsigned int variant, unsigned long flags=0)
{ {
for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) { for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) {
Cache element = *it; Cache & element = *it;
if (element.board == board && element.version == version && element.variant == variant && element.flags == flags) if (element.board == board && element.version == version && element.variant == variant && element.flags == flags)
return element.table; return element.table;
} }
@ -398,8 +400,9 @@ class SourcesConversionTable: public ConversionTable {
static void Cleanup() static void Cleanup()
{ {
for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) { for (std::list<Cache>::iterator it=internalCache.begin(); it!=internalCache.end(); it++) {
Cache element = *it; Cache & element = *it;
delete element.table; if (element.table)
delete element.table;
} }
internalCache.clear(); internalCache.clear();
} }
@ -439,7 +442,7 @@ class SwitchField: public ConversionField< SignedField<N> > {
{ {
ConversionField< SignedField<N> >::afterImport(); ConversionField< SignedField<N> >::afterImport();
sw = RawSwitch(_switch); sw = RawSwitch(_switch);
eepromImportDebug() << QString("imported %1: %2").arg(ConversionField< SignedField<N> >::internalField.getName()).arg(sw.toString(board)); qCDebug(eepromImport) << QString("imported %1: %2").arg(ConversionField< SignedField<N> >::internalField.getName()).arg(sw.toString(board));
} }
protected: protected:
@ -565,7 +568,7 @@ class TelemetrySourceField: public ConversionField< UnsignedField<N> > {
{ {
ConversionField< UnsignedField<N> >::afterImport(); ConversionField< UnsignedField<N> >::afterImport();
source = (_source == 0 ? RawSource(0) : RawSource(SOURCE_TYPE_TELEMETRY, _source-1)); source = (_source == 0 ? RawSource(0) : RawSource(SOURCE_TYPE_TELEMETRY, _source-1));
eepromImportDebug() << QString("imported %1: %2").arg(ConversionField< UnsignedField<N> >::internalField.getName()).arg(source.toString()); qCDebug(eepromImport) << QString("imported %1: %2").arg(ConversionField< UnsignedField<N> >::internalField.getName()).arg(source.toString());
} }
protected: protected:
@ -601,7 +604,7 @@ class SourceField: public ConversionField< UnsignedField<N> > {
{ {
ConversionField< UnsignedField<N> >::afterImport(); ConversionField< UnsignedField<N> >::afterImport();
source = RawSource(_source); source = RawSource(_source);
eepromImportDebug() << QString("imported %1: %2").arg(ConversionField< UnsignedField<N> >::internalField.getName()).arg(source.toString()); qCDebug(eepromImport) << QString("imported %1: %2").arg(ConversionField< UnsignedField<N> >::internalField.getName()).arg(source.toString());
} }
protected: protected:
@ -760,7 +763,7 @@ class CurveReferenceField: public TransformedField {
{ {
curve.type = (CurveReference::CurveRefType)_curve_type; curve.type = (CurveReference::CurveRefType)_curve_type;
curve.value = smallGvarToC9x(_curve_value); curve.value = smallGvarToC9x(_curve_value);
eepromImportDebug() << QString("imported CurveReference(%1)").arg(curve.toString()); qCDebug(eepromImport) << QString("imported CurveReference(%1)").arg(curve.toString());
} }
protected: protected:
@ -942,7 +945,7 @@ class FlightModeField: public TransformedField {
} }
} }
} }
eepromImportDebug() << QString("imported %1: '%2'").arg(internalField.getName()).arg(phase.name); qCDebug(eepromImport) << QString("imported %1: '%2'").arg(internalField.getName()).arg(phase.name);
} }
protected: protected:
@ -1231,7 +1234,7 @@ class MixField: public TransformedField {
} }
if (mix.carryTrim < 0) mix.carryTrim = 0; if (mix.carryTrim < 0) mix.carryTrim = 0;
} }
eepromImportDebug() << QString("imported %1: ch %2, name '%3'").arg(internalField.getName()).arg(mix.destCh).arg(mix.name); qCDebug(eepromImport) << QString("imported %1: ch %2, name '%3'").arg(internalField.getName()).arg(mix.destCh).arg(mix.name);
} }
protected: protected:
@ -1412,7 +1415,7 @@ class InputField: public TransformedField {
else else
expo.curve = CurveReference(CurveReference::CURVE_REF_FUNC, _curveParam); expo.curve = CurveReference(CurveReference::CURVE_REF_FUNC, _curveParam);
} }
eepromImportDebug() << QString("imported %1: ch %2 name '%3'").arg(internalField.getName()).arg(expo.chn).arg(expo.name); qCDebug(eepromImport) << QString("imported %1: ch %2 name '%3'").arg(internalField.getName()).arg(expo.chn).arg(expo.name);
} }
protected: protected:
@ -1626,7 +1629,7 @@ class CurvesField: public TransformedField {
for (int j=0; j<curve->count; j++) for (int j=0; j<curve->count; j++)
curve->points[j].x = -100 + (200*i) / (curve->count-1); curve->points[j].x = -100 + (200*i) / (curve->count-1);
} }
eepromImportDebug() << QString("imported curve: %3 points").arg(curve->count); qCDebug(eepromImport) << QString("imported curve: %3 points").arg(curve->count);
} }
} }
@ -1955,7 +1958,7 @@ class LogicalSwitchField: public TransformedField {
} }
} }
} }
eepromImportDebug() << QString("imported %1: %2").arg(internalField.getName()).arg(csw.funcToString()); qCDebug(eepromImport) << QString("imported %1: %2").arg(internalField.getName()).arg(csw.funcToString());
} }
protected: protected:
@ -2115,7 +2118,7 @@ class SwitchesWarningField: public TransformedField {
else { else {
sw = _sw; sw = _sw;
} }
eepromImportDebug() << QString("imported %1").arg(internalField.getName()); qCDebug(eepromImport) << QString("imported %1").arg(internalField.getName());
} }
protected: protected:
@ -2350,7 +2353,7 @@ class ArmCustomFunctionField: public TransformedField {
else { else {
fn.param = value; fn.param = value;
} }
eepromImportDebug() << QString("imported %1").arg(internalField.getName()); qCDebug(eepromImport) << QString("imported %1").arg(internalField.getName());
} }
protected: protected:
@ -2539,7 +2542,7 @@ class AvrCustomFunctionField: public TransformedField {
else if (version >= 213) else if (version >= 213)
fn.repeatParam = _active * 10; fn.repeatParam = _active * 10;
} }
eepromImportDebug() << QString("imported %1").arg(internalField.getName()); qCDebug(eepromImport) << QString("imported %1").arg(internalField.getName());
} }
protected: protected:
@ -2634,7 +2637,7 @@ class FrskyScreenField: public DataField {
virtual void ImportBits(const QBitArray & input) virtual void ImportBits(const QBitArray & input)
{ {
eepromImportDebug() << QString("importing %1: type: %2").arg(name).arg(screen.type); qCDebug(eepromImport) << QString("importing %1: type: %2").arg(name).arg(screen.type);
// NOTA: screen.type should have been imported first! // NOTA: screen.type should have been imported first!
if (IS_ARM(board) && version >= 217) { if (IS_ARM(board) && version >= 217) {
@ -3007,7 +3010,7 @@ class SensorField: public TransformedField {
sensor.unit++; sensor.unit++;
} }
eepromImportDebug() << QString("imported %1").arg(internalField.getName()); qCDebug(eepromImport) << QString("imported %1").arg(internalField.getName());
} }
protected: protected:
@ -3041,7 +3044,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
{ {
sprintf(name, "Model %s", modelData.name); sprintf(name, "Model %s", modelData.name);
eepromImportDebug() << QString("OpenTxModelData::OpenTxModelData(name: %1, board: %2, ver: %3, var: %4)").arg(name).arg(board).arg(version).arg(variant); qCDebug(eepromImport) << QString("OpenTxModelData::OpenTxModelData(name: %1, board: %2, ver: %3, var: %4)").arg(name).arg(board).arg(version).arg(variant);
if (IS_HORUS(board)) if (IS_HORUS(board))
internalField.Append(new ZCharField<15>(this, modelData.name, "Model name")); internalField.Append(new ZCharField<15>(this, modelData.name, "Model name"));
@ -3452,7 +3455,7 @@ void OpenTxModelData::beforeExport()
void OpenTxModelData::afterImport() void OpenTxModelData::afterImport()
{ {
eepromImportDebug() << QString("OpenTxModelData::afterImport()") << modelData.name; qCDebug(eepromImport) << QString("OpenTxModelData::afterImport()") << modelData.name;
if (IS_TARANIS(board) && version < 216) { if (IS_TARANIS(board) && version < 216) {
for (unsigned int i=0; i<CPN_MAX_STICKS; i++) { for (unsigned int i=0; i<CPN_MAX_STICKS; i++) {
@ -3520,7 +3523,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type
version(version), version(version),
inputsCount(CPN_MAX_STICKS+MAX_POTS(board, version)+MAX_SLIDERS(board)+MAX_MOUSE_ANALOGS(board)) inputsCount(CPN_MAX_STICKS+MAX_POTS(board, version)+MAX_SLIDERS(board)+MAX_MOUSE_ANALOGS(board))
{ {
eepromImportDebug() << QString("OpenTxGeneralData::OpenTxGeneralData(board: %1, version:%2, variant:%3)").arg(board).arg(version).arg(variant); qCDebug(eepromImport) << QString("OpenTxGeneralData::OpenTxGeneralData(board: %1, version:%2, variant:%3)").arg(board).arg(version).arg(variant);
generalData.version = version; generalData.version = version;
generalData.variant = variant; generalData.variant = variant;

View file

@ -1514,6 +1514,7 @@ void unregisterOpenTxFirmwares()
foreach (Firmware * f, firmwares) { foreach (Firmware * f, firmwares) {
delete f; delete f;
} }
unregisterEEpromInterfaces();
} }
template <class T, class M> template <class T, class M>

View file

@ -31,10 +31,12 @@
#include "appdata.h" #include "appdata.h"
#include "helpers.h" #include "helpers.h"
#include "modeledit/modeledit.h"
#include "simulatormainwindow.h" #include "simulatormainwindow.h"
#include "storage/sdcard.h" #include "storage/sdcard.h"
#include <QLabel>
#include <QMessageBox>
Stopwatch gStopwatch("global"); Stopwatch gStopwatch("global");
const QColor colors[CPN_MAX_CURVES] = { const QColor colors[CPN_MAX_CURVES] = {
@ -126,7 +128,11 @@ void populatePhasesCB(QComboBox *b, int value)
b->setCurrentIndex(value + getCurrentFirmware()->getCapability(FlightModes)); b->setCurrentIndex(value + getCurrentFirmware()->getCapability(FlightModes));
} }
GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step, bool allowGvars, ModelPanel * panel): /*
* GVarGroup
*/
GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step, bool allowGvars):
QObject(), QObject(),
weightGV(weightGV), weightGV(weightGV),
weightSB(weightSB), weightSB(weightSB),
@ -135,8 +141,7 @@ GVarGroup::GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBo
weightCB(weightCB), weightCB(weightCB),
weight(weight), weight(weight),
step(step), step(step),
lock(true), lock(true)
panel(panel)
{ {
if (allowGvars && getCurrentFirmware()->getCapability(Gvars)) { if (allowGvars && getCurrentFirmware()->getCapability(Gvars)) {
populateGVCB(*weightCB, weight, model); populateGVCB(*weightCB, weight, model);
@ -200,12 +205,15 @@ void GVarGroup::valuesChanged()
weight = sb->value(); weight = sb->value();
else else
weight = round(dsb->value()/step); weight = round(dsb->value()/step);
if (panel)
emit panel->modified();
emit valueChanged();
} }
} }
/*
* CurveGroup
*/
CurveGroup::CurveGroup(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QComboBox * curveValueCB, QSpinBox * curveValueSB, CurveReference & curve, const ModelData & model, unsigned int flags): CurveGroup::CurveGroup(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QComboBox * curveValueCB, QSpinBox * curveValueSB, CurveReference & curve, const ModelData & model, unsigned int flags):
QObject(), QObject(),
curveTypeCB(curveTypeCB), curveTypeCB(curveTypeCB),
@ -364,6 +372,10 @@ void CurveGroup::valuesChanged()
} }
} }
/*
* Helpers
*/
void populateGvarUseCB(QComboBox *b, unsigned int phase) void populateGvarUseCB(QComboBox *b, unsigned int phase)
{ {
b->addItem(QObject::tr("Own value")); b->addItem(QObject::tr("Own value"));

View file

@ -22,7 +22,6 @@
#define _HELPERS_H_ #define _HELPERS_H_
#include "eeprominterface.h" #include "eeprominterface.h"
#include "modeledit/modeledit.h"
#include <QCheckBox> #include <QCheckBox>
#include <QSpinBox> #include <QSpinBox>
#include <QTableWidget> #include <QTableWidget>
@ -69,7 +68,10 @@ class GVarGroup: public QObject {
Q_OBJECT Q_OBJECT
public: public:
GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step=1.0, bool allowGVars=true, ModelPanel * panel=NULL); GVarGroup(QCheckBox * weightGV, QAbstractSpinBox * weightSB, QComboBox * weightCB, int & weight, const ModelData & model, const int deflt, const int mini, const int maxi, const double step=1.0, bool allowGVars=true);
signals:
void valueChanged();
protected slots: protected slots:
void gvarCBChanged(int); void gvarCBChanged(int);
@ -84,7 +86,6 @@ class GVarGroup: public QObject {
int & weight; int & weight;
double step; double step;
bool lock; bool lock;
ModelPanel * panel;
}; };
#define HIDE_DIFF 0x01 #define HIDE_DIFF 0x01
@ -157,26 +158,6 @@ QString getFrSkySrc(int index);
void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx); void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx);
template <class T>
QVector<T> findWidgets(QObject * object, const QString & name)
{
QVector<T> result;
QRegExp rx(name.arg("([0-9]+)"));
QList<T> children = object->findChildren<T>();
foreach(T child, children) {
int pos = rx.indexIn(child->objectName());
if (pos >= 0) {
QStringList list = rx.capturedTexts();
int index = list[1].toInt();
if (result.size() <= index) {
result.resize(index+1);
}
result[index] = child;
}
}
return result;
}
// Format a pixmap to fit on the current firmware // Format a pixmap to fit on the current firmware
QPixmap makePixMap(const QImage & image); QPixmap makePixMap(const QImage & image);
@ -249,13 +230,13 @@ public:
void resizeColumnsToContents(); void resizeColumnsToContents();
void setColumnWidth(int col, int width); void setColumnWidth(int col, int width);
void pushRowsUp(int row); void pushRowsUp(int row);
private: private:
#if defined(TABLE_LAYOUT) #if defined(TABLE_LAYOUT)
QTableWidget * tableWidget; QTableWidget * tableWidget;
#else #else
QGridLayout * gridWidget; QGridLayout * gridWidget;
#endif #endif
}; };

View file

@ -21,6 +21,10 @@
#ifndef _MACROS_H_ #ifndef _MACROS_H_
#define _MACROS_H_ #define _MACROS_H_
#define DIM(arr) (sizeof((arr))/sizeof((arr)[0])) #include <iterator>
#endif // _MACROS_H_ // #define DIM(arr) (sizeof((arr))/sizeof((arr)[0]))
// new way for c++11
#define DIM(arr__) ((size_t)(std::end((arr__)) - std::begin((arr__))))
#endif // _MACROS_H_

View file

@ -23,8 +23,8 @@ set(modeledit_SRCS
customfunctions.cpp customfunctions.cpp
# templates.cpp # templates.cpp
mixerslistwidget.cpp mixerslistwidget.cpp
node.cpp # node.cpp ## node and edge are built in common lib because also used by simulator
edge.cpp # edge.cpp ## commenting them here avoids a "duplicate target" warning eg. from ninja
) )
set(modeledit_HDRS set(modeledit_HDRS
@ -36,7 +36,7 @@ set(modeledit_HDRS
customfunctions.h customfunctions.h
# templates.h # templates.h
mixerslistwidget.h mixerslistwidget.h
node.h # node.h
) )
set(modeledit_UIS set(modeledit_UIS
@ -53,7 +53,7 @@ foreach(name ${modeledit_NAMES})
set(modeledit_HDRS ${modeledit_HDRS} ${name}.h) set(modeledit_HDRS ${modeledit_HDRS} ${name}.h)
set(modeledit_UIS ${modeledit_UIS} ${name}.ui) set(modeledit_UIS ${modeledit_UIS} ${name}.ui)
endforeach() endforeach()
qt5_wrap_ui(modeledit_SRCS ${modeledit_UIS}) qt5_wrap_ui(modeledit_SRCS ${modeledit_UIS})
qt5_wrap_cpp(modeledit_SRCS ${modeledit_HDRS}) qt5_wrap_cpp(modeledit_SRCS ${modeledit_HDRS})

View file

@ -64,7 +64,8 @@ LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row
horizontalLayout->addWidget(cb); horizontalLayout->addWidget(cb);
horizontalLayout->addWidget(spinbox); horizontalLayout->addWidget(spinbox);
tableLayout->addLayout(row, col, horizontalLayout); tableLayout->addLayout(row, col, horizontalLayout);
gvarGroup = new GVarGroup(gv, spinbox, cb, value, model, deflt, min, max, displayStep, allowGVars, panel); gvarGroup = new GVarGroup(gv, spinbox, cb, value, model, deflt, min, max, displayStep, allowGVars);
QObject::connect(gvarGroup, &GVarGroup::valueChanged, panel, &ModelPanel::modified);
} }
LimitsGroup::~LimitsGroup() LimitsGroup::~LimitsGroup()
@ -227,7 +228,7 @@ void Channels::refreshExtendedLimits()
group->updateMinMax(10*channelMax); group->updateMinMax(10*channelMax);
} }
emit modified(); emit modified();
} }
void Channels::invEdited() void Channels::invEdited()

View file

@ -71,7 +71,7 @@ DebugOutput::DebugOutput(QWidget * parent, SimulatorInterface *simulator):
ui->filterText->addItem(fltr, "no_delete"); ui->filterText->addItem(fltr, "no_delete");
ui->filterText->setValidator(new DebugOutputFilterValidator(ui->filterText)); ui->filterText->setValidator(new DebugOutputFilterValidator(ui->filterText));
ui->filterText->installEventFilter(new DeleteComboBoxItemEventFilter()); ui->filterText->installEventFilter(new DeleteComboBoxItemEventFilter(this));
ui->actionShowFilterHelp->setIcon(SimulatorIcon("info")); ui->actionShowFilterHelp->setIcon(SimulatorIcon("info"));
ui->actionWordWrap->setIcon(SimulatorIcon("word_wrap")); ui->actionWordWrap->setIcon(SimulatorIcon("word_wrap"));
@ -115,6 +115,7 @@ DebugOutput::DebugOutput(QWidget * parent, SimulatorInterface *simulator):
DebugOutput::~DebugOutput() DebugOutput::~DebugOutput()
{ {
m_simulator->installTraceHook(NULL);
saveState(); saveState();
if (AppDebugMessageHandler::instance()) if (AppDebugMessageHandler::instance())
@ -173,15 +174,18 @@ void DebugOutput::restoreState()
void DebugOutput::processBytesReceived() void DebugOutput::processBytesReceived()
{ {
static char buf[512];
const QTextCursor savedCursor(ui->console->textCursor()); const QTextCursor savedCursor(ui->console->textCursor());
const int sbValue = ui->console->verticalScrollBar()->value(); const int sbValue = ui->console->verticalScrollBar()->value();
const bool sbAtBottom = (sbValue == ui->console->verticalScrollBar()->maximum()); const bool sbAtBottom = (sbValue == ui->console->verticalScrollBar()->maximum());
qint64 len; qint64 len;
QString text;
while ((len = m_dataBufferDevice->bytesAvailable()) > 0) { while (m_dataBufferDevice && m_dataBufferDevice->bytesAvailable() > 0) {
QString text(m_dataBufferDevice->read(qMin(len, qint64(512)))); len = m_dataBufferDevice->read(buf, sizeof(buf));
if (text.isEmpty()) if (len <= 0)
break; break;
text = QString::fromLocal8Bit(buf, len);
ui->console->moveCursor(QTextCursor::End); ui->console->moveCursor(QTextCursor::End);
ui->console->textCursor().insertText(text); ui->console->textCursor().insertText(text);
if (sbAtBottom) { if (sbAtBottom) {

View file

@ -29,14 +29,15 @@
#include <QValidator> #include <QValidator>
#include <QWidget> #include <QWidget>
// NOTE : The buffer sizes need to be large enough to handle the flood of data when X12/X10 simulator starts up (almost 40K!). // NOTE : The buffer sizes need to be large enough to handle the flood of data when X12/X10 simulator starts up with TRACE_SIMPGMSPACE=1 (> 40K!).
// These are maximum sizes, not necessarily allocated sizes.
#ifndef DEBUG_OUTPUT_WIDGET_OUT_BUFF_SIZE #ifndef DEBUG_OUTPUT_WIDGET_OUT_BUFF_SIZE
// This buffer holds received and processed data until it can be printed to our console. // This buffer holds received and processed data until it can be printed to our console.
#define DEBUG_OUTPUT_WIDGET_OUT_BUFF_SIZE (40 * 1024) // [bytes] #define DEBUG_OUTPUT_WIDGET_OUT_BUFF_SIZE (50 * 1024) // [bytes]
#endif #endif
#ifndef DEBUG_OUTPUT_WIDGET_INP_BUFF_SIZE #ifndef DEBUG_OUTPUT_WIDGET_INP_BUFF_SIZE
// This buffer is active if line filter is enabled and holds received data until it can be filtered and placed in output buffer. // This buffer is active if line filter is enabled and holds received data until it can be filtered and placed in output buffer.
#define DEBUG_OUTPUT_WIDGET_INP_BUFF_SIZE (30 * 1024) // [bytes] #define DEBUG_OUTPUT_WIDGET_INP_BUFF_SIZE (50 * 1024) // [bytes]
#endif #endif
namespace Ui { namespace Ui {
@ -101,6 +102,8 @@ class DebugOutputFilterValidator : public QValidator
class DeleteComboBoxItemEventFilter : public QObject class DeleteComboBoxItemEventFilter : public QObject
{ {
Q_OBJECT Q_OBJECT
public:
DeleteComboBoxItemEventFilter(QObject *parent = Q_NULLPTR) : QObject(parent) { }
protected: protected:
bool eventFilter(QObject *obj, QEvent *event); bool eventFilter(QObject *obj, QEvent *event);
}; };

View file

@ -33,6 +33,8 @@
#endif #endif
#include <QDebug> #include <QDebug>
#include <QLabel>
#include <QMessageBox>
extern AppData g; // ensure what "g" means extern AppData g; // ensure what "g" means

View file

@ -38,6 +38,7 @@
#endif #endif
#include <QFile> #include <QFile>
#include <QMessageBox>
#include <iostream> #include <iostream>
SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface *simulator, quint8 flags): SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface *simulator, quint8 flags):
@ -99,6 +100,7 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface *simulator
keymapHelp.append(item); keymapHelp.append(item);
ui->radioUiWidget->layout()->removeItem(ui->radioUiTempSpacer); ui->radioUiWidget->layout()->removeItem(ui->radioUiTempSpacer);
delete ui->radioUiTempSpacer;
ui->radioUiWidget->layout()->addWidget(radioUiWidget); ui->radioUiWidget->layout()->addWidget(radioUiWidget);
radioUiWidget->setFocusPolicy(Qt::WheelFocus); radioUiWidget->setFocusPolicy(Qt::WheelFocus);
radioUiWidget->setFocus(); radioUiWidget->setFocus();

View file

@ -26,6 +26,7 @@
#include "radiodata.h" #include "radiodata.h"
#include "simulator.h" #include "simulator.h"
#include <QTimer>
#include <QWidget> #include <QWidget>
#include <QVector> #include <QVector>

View file

@ -31,12 +31,12 @@ TelemetrySimulator::TelemetrySimulator(QWidget * parent, SimulatorInterface * si
{ {
ui->setupUi(this); ui->setupUi(this);
timer = new QTimer(this); setupDataFields();
timer->setInterval(10);
connect(timer, SIGNAL(timeout()), this, SLOT(onTimerEvent()));
logTimer = new QTimer(this); timer.setInterval(10);
connect(logTimer, SIGNAL(timeout()), this, SLOT(onLogTimerEvent())); connect(&timer, &QTimer::timeout, this, &TelemetrySimulator::generateTelemetryFrame);
connect(&logTimer, &QTimer::timeout, this, &TelemetrySimulator::onLogTimerEvent);
connect(ui->Simulate, SIGNAL(toggled(bool)), this, SLOT(onSimulateToggled(bool))); connect(ui->Simulate, SIGNAL(toggled(bool)), this, SLOT(onSimulateToggled(bool)));
connect(ui->loadLogFile, SIGNAL(released()), this, SLOT(onLoadLogFile())); connect(ui->loadLogFile, SIGNAL(released()), this, SLOT(onLoadLogFile()));
@ -64,33 +64,27 @@ TelemetrySimulator::TelemetrySimulator(QWidget * parent, SimulatorInterface * si
TelemetrySimulator::~TelemetrySimulator() TelemetrySimulator::~TelemetrySimulator()
{ {
timer->stop(); timer.stop();
logTimer->stop(); logTimer.stop();
delete logPlayback;
delete ui; delete ui;
} }
void TelemetrySimulator::onSimulateToggled(bool isChecked) void TelemetrySimulator::onSimulateToggled(bool isChecked)
{ {
if (isChecked) { if (isChecked) {
timer->start(); timer.start();
} }
else { else {
timer->stop(); timer.stop();
} }
} }
void TelemetrySimulator::onLogTimerEvent() void TelemetrySimulator::onLogTimerEvent()
{ {
logPlayback->stepForward(false); logPlayback->stepForward(false);
} }
void TelemetrySimulator::onTimerEvent()
{
generateTelemetryFrame();
}
void TelemetrySimulator::onLoadLogFile() void TelemetrySimulator::onLoadLogFile()
{ {
onStop(); // in case we are in playback mode onStop(); // in case we are in playback mode
@ -100,7 +94,7 @@ void TelemetrySimulator::onLoadLogFile()
void TelemetrySimulator::onPlay() void TelemetrySimulator::onPlay()
{ {
if (logPlayback->isReady()) { if (logPlayback->isReady()) {
logTimer->start(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]); logTimer.start(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]);
logPlayback->play(); logPlayback->play();
} }
} }
@ -108,7 +102,7 @@ void TelemetrySimulator::onPlay()
void TelemetrySimulator::onRewind() void TelemetrySimulator::onRewind()
{ {
if (logPlayback->isReady()) { if (logPlayback->isReady()) {
logTimer->stop(); logTimer.stop();
logPlayback->rewind(); logPlayback->rewind();
} }
} }
@ -116,7 +110,7 @@ void TelemetrySimulator::onRewind()
void TelemetrySimulator::onStepForward() void TelemetrySimulator::onStepForward()
{ {
if (logPlayback->isReady()) { if (logPlayback->isReady()) {
logTimer->stop(); logTimer.stop();
logPlayback->stepForward(true); logPlayback->stepForward(true);
} }
} }
@ -124,7 +118,7 @@ void TelemetrySimulator::onStepForward()
void TelemetrySimulator::onStepBack() void TelemetrySimulator::onStepBack()
{ {
if (logPlayback->isReady()) { if (logPlayback->isReady()) {
logTimer->stop(); logTimer.stop();
logPlayback->stepBack(); logPlayback->stepBack();
} }
} }
@ -132,7 +126,7 @@ void TelemetrySimulator::onStepBack()
void TelemetrySimulator::onStop() void TelemetrySimulator::onStop()
{ {
if (logPlayback->isReady()) { if (logPlayback->isReady()) {
logTimer->stop(); logTimer.stop();
logPlayback->stop(); logPlayback->stop();
} }
} }
@ -147,21 +141,21 @@ void TelemetrySimulator::onPositionIndicatorChanged(int value)
void TelemetrySimulator::onReplayRateChanged(int value) void TelemetrySimulator::onReplayRateChanged(int value)
{ {
if (logTimer->isActive()) { if (logTimer.isActive()) {
logTimer->setInterval(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]); logTimer.setInterval(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]);
} }
} }
void TelemetrySimulator::closeEvent(QCloseEvent *event) void TelemetrySimulator::closeEvent(QCloseEvent *event)
{ {
timer->stop(); timer.stop();
logTimer->stop(); logTimer.stop();
event->accept(); event->accept();
} }
#define SET_INSTANCE(control, id, def) ui->control->setText(QString::number(simulator->getSensorInstance(id, ((def) & 0x1F) + 1))) #define SET_INSTANCE(control, id, def) ui->control->setText(QString::number(simulator->getSensorInstance(id, ((def) & 0x1F) + 1)))
void TelemetrySimulator::showEvent(QShowEvent *event) void TelemetrySimulator::setupDataFields()
{ {
SET_INSTANCE(rxbt_inst, BATT_ID, 0); SET_INSTANCE(rxbt_inst, BATT_ID, 0);
SET_INSTANCE(rssi_inst, RSSI_ID, 24); SET_INSTANCE(rssi_inst, RSSI_ID, 24);
@ -410,7 +404,7 @@ void TelemetrySimulator::generateTelemetryFrame()
if (ok && (buffer[2] || buffer[3])) if (ok && (buffer[2] || buffer[3]))
simulator->sendTelemetry(buffer, FRSKY_SPORT_PACKET_SIZE); simulator->sendTelemetry(buffer, FRSKY_SPORT_PACKET_SIZE);
else else
onTimerEvent(); generateTelemetryFrame();
} }
uint32_t TelemetrySimulator::FlvssEmulator::encodeCellPair(uint8_t cellNum, uint8_t firstCellNo, double cell1, double cell2) uint32_t TelemetrySimulator::FlvssEmulator::encodeCellPair(uint8_t cellNum, uint8_t firstCellNo, double cell1, double cell2)

View file

@ -49,9 +49,9 @@ class TelemetrySimulator : public QWidget
protected slots: protected slots:
virtual void closeEvent(QCloseEvent *event); virtual void closeEvent(QCloseEvent *event);
virtual void showEvent(QShowEvent *event); void setupDataFields();
void onSimulateToggled(bool isChecked); void onSimulateToggled(bool isChecked);
void onTimerEvent(); void generateTelemetryFrame();
void onLogTimerEvent(); void onLogTimerEvent();
void onLoadLogFile(); void onLoadLogFile();
void onPlay(); void onPlay();
@ -65,10 +65,9 @@ class TelemetrySimulator : public QWidget
protected: protected:
Ui::TelemetrySimulator * ui; Ui::TelemetrySimulator * ui;
QTimer * timer; QTimer timer;
QTimer * logTimer; QTimer logTimer;
SimulatorInterface *simulator; SimulatorInterface *simulator;
void generateTelemetryFrame();
// protected classes follow // protected classes follow

View file

@ -26,10 +26,15 @@
#include <QPainter> #include <QPainter>
#include <QClipboard> #include <QClipboard>
#include <QDir> #include <QDir>
#include <QElapsedTimer>
#include <QMutex>
#include <QMutexLocker>
#include "appdata.h" #include "appdata.h"
#include "appdebugmessagehandler.h" #include "appdebugmessagehandler.h"
#define LCD_WIDGET_REFRESH_PERIOD 16 // [ms] 16 = 62.5fps
class LcdWidget : public QWidget class LcdWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
@ -39,7 +44,7 @@ class LcdWidget : public QWidget
LcdWidget(QWidget * parent = 0): LcdWidget(QWidget * parent = 0):
QWidget(parent), QWidget(parent),
lcdBuf(NULL), lcdBuf(NULL),
previousBuf(NULL), localBuf(NULL),
lightEnable(false), lightEnable(false),
bgDefaultColor(QColor(198, 208, 199)) bgDefaultColor(QColor(198, 208, 199))
{ {
@ -47,8 +52,8 @@ class LcdWidget : public QWidget
~LcdWidget() ~LcdWidget()
{ {
if (previousBuf) { if (localBuf) {
free(previousBuf); free(localBuf);
} }
} }
@ -62,8 +67,9 @@ class LcdWidget : public QWidget
lcdSize = (width * height) * ((depth+7) / 8); lcdSize = (width * height) * ((depth+7) / 8);
else else
lcdSize = (width * ((height+7)/8)) * depth; lcdSize = (width * ((height+7)/8)) * depth;
previousBuf = (unsigned char *)malloc(lcdSize);
memset(previousBuf, 0, lcdSize); localBuf = (unsigned char *)malloc(lcdSize);
memset(localBuf, 0, lcdSize);
} }
void setBgDefaultColor(const QColor & color) void setBgDefaultColor(const QColor & color)
@ -102,10 +108,12 @@ class LcdWidget : public QWidget
void onLcdChanged(bool light) void onLcdChanged(bool light)
{ {
if (light != lightEnable || memcmp(previousBuf, lcdBuf, lcdSize)) { QMutexLocker locker(&lcdMtx);
lightEnable = light; lightEnable = light;
memcpy(previousBuf, lcdBuf, lcdSize); memcpy(localBuf, lcdBuf, lcdSize);
if (!redrawTimer.isValid() || redrawTimer.hasExpired(LCD_WIDGET_REFRESH_PERIOD)) {
update(); update();
redrawTimer.start();
} }
} }
@ -117,24 +125,26 @@ class LcdWidget : public QWidget
int lcdSize; int lcdSize;
unsigned char *lcdBuf; unsigned char *lcdBuf;
unsigned char *previousBuf; unsigned char *localBuf;
bool lightEnable; bool lightEnable;
QColor bgColor; QColor bgColor;
QColor bgDefaultColor; QColor bgDefaultColor;
QMutex lcdMtx;
QElapsedTimer redrawTimer;
inline void doPaint(QPainter & p) inline void doPaint(QPainter & p)
{ {
QRgb rgb; QRgb rgb;
uint16_t z; uint16_t z;
if (!lcdBuf) if (!localBuf)
return; return;
if (lcdDepth == 16) { if (lcdDepth == 16) {
for (int x = 0; x < lcdWidth; x++) { for (int x = 0; x < lcdWidth; x++) {
for (int y = 0; y < lcdHeight; y++) { for (int y = 0; y < lcdHeight; y++) {
z = ((uint16_t *)lcdBuf)[y * lcdWidth + x]; z = ((uint16_t *)localBuf)[y * lcdWidth + x];
rgb = qRgb(255 * ((z & 0xF800) >> 11) / 0x1F, rgb = qRgb(255 * ((z & 0xF800) >> 11) / 0x1F,
255 * ((z & 0x07E0) >> 5) / 0x3F, 255 * ((z & 0x07E0) >> 5) / 0x3F,
255 * (z & 0x001F) / 0x1F); 255 * (z & 0x001F) / 0x1F);
@ -147,7 +157,7 @@ class LcdWidget : public QWidget
if (lcdDepth == 12) { if (lcdDepth == 12) {
for (int x = 0; x < lcdWidth; x++) { for (int x = 0; x < lcdWidth; x++) {
for (int y = 0; y < lcdHeight; y++) { for (int y = 0; y < lcdHeight; y++) {
z = ((uint16_t *)lcdBuf)[y * lcdWidth + x]; z = ((uint16_t *)localBuf)[y * lcdWidth + x];
rgb = qRgb(255 * ((z & 0xF00) >> 8) / 0x0F, rgb = qRgb(255 * ((z & 0xF00) >> 8) / 0x0F,
255 * ((z & 0x0F0) >> 4) / 0x0F, 255 * ((z & 0x0F0) >> 4) / 0x0F,
255 * (z & 0x00F) / 0x0F); 255 * (z & 0x00F) / 0x0F);
@ -181,12 +191,12 @@ class LcdWidget : public QWidget
mask = (1 << (y % 8)); mask = (1 << (y % 8));
for (int x = 0; x < lcdWidth; x++, idx++) { for (int x = 0; x < lcdWidth; x++, idx++) {
if (lcdDepth == 1) { if (lcdDepth == 1) {
if (lcdBuf[idx] & mask) if (localBuf[idx] & mask)
p.drawRect(2 * x, 2 * y, 1, 1); p.drawRect(2 * x, 2 * y, 1, 1);
continue; continue;
} }
// lcdDepth == 4 // lcdDepth == 4
z = (y & 1) ? (lcdBuf[idx] >> 4) : (lcdBuf[idx] & 0x0F); z = (y & 1) ? (localBuf[idx] >> 4) : (localBuf[idx] & 0x0F);
if (!z) if (!z)
continue; continue;
if (z != previousDepth) { if (z != previousDepth) {

View file

@ -34,6 +34,7 @@
#include "appdata.h" #include "appdata.h"
#include "appdebugmessagehandler.h" #include "appdebugmessagehandler.h"
#include "constants.h" #include "constants.h"
#include "customdebug.h"
#include "eeprominterface.h" #include "eeprominterface.h"
#include "simulator.h" #include "simulator.h"
#include "simulatormainwindow.h" #include "simulatormainwindow.h"
@ -95,6 +96,8 @@ int main(int argc, char *argv[])
if (AppDebugMessageHandler::instance()) if (AppDebugMessageHandler::instance())
AppDebugMessageHandler::instance()->installAppMessageHandler(); AppDebugMessageHandler::instance()->installAppMessageHandler();
CustomDebug::setFilterRules();
g.init(); g.init();
QTranslator companionTranslator; QTranslator companionTranslator;
@ -257,6 +260,7 @@ int finish(int exitCode)
qDebug() << "SIMULATOR EXIT" << exitCode; qDebug() << "SIMULATOR EXIT" << exitCode;
unregisterSimulators(); unregisterSimulators();
unregisterOpenTxFirmwares(); unregisterOpenTxFirmwares();
unregisterStorageFactories();
#if defined(JOYSTICKS) || defined(SIMU_AUDIO) #if defined(JOYSTICKS) || defined(SIMU_AUDIO)
SDL_Quit(); SDL_Quit();

View file

@ -24,6 +24,8 @@
#include "helpers.h" #include "helpers.h"
#include "storage.h" #include "storage.h"
#include <QFile>
#define FW_MARK "FW" #define FW_MARK "FW"
#define VERS_MARK "VERS" #define VERS_MARK "VERS"
#define DATE_MARK "DATE" #define DATE_MARK "DATE"

View file

@ -64,6 +64,12 @@ void registerStorageFactories()
registerStorageFactory(new SdcardStorageFactory()); registerStorageFactory(new SdcardStorageFactory());
} }
void unregisterStorageFactories()
{
foreach (StorageFactory * factory, registeredStorageFactories)
delete factory;
}
bool Storage::load(RadioData & radioData) bool Storage::load(RadioData & radioData)
{ {
QFile file(filename); QFile file(filename);
@ -71,30 +77,37 @@ bool Storage::load(RadioData & radioData)
setError(QObject::tr("Unable to find file %1!").arg(filename)); setError(QObject::tr("Unable to find file %1!").arg(filename));
return false; return false;
} }
bool ret = false;
foreach(StorageFactory * factory, registeredStorageFactories) { foreach(StorageFactory * factory, registeredStorageFactories) {
StorageFormat * format = factory->instance(filename); StorageFormat * format = factory->instance(filename);
if (format->load(radioData)) { if (format->load(radioData)) {
board = format->getBoard(); board = format->getBoard();
setWarning(format->warning()); setWarning(format->warning());
return true; ret = true;
break;
} }
else { else {
setError(format->error()); setError(format->error());
} }
delete format;
} }
return false; return ret;
} }
bool Storage::write(const RadioData & radioData) bool Storage::write(const RadioData & radioData)
{ {
bool ret = false;
foreach(StorageFactory * factory, registeredStorageFactories) { foreach(StorageFactory * factory, registeredStorageFactories) {
if (factory->probe(filename)) { if (factory->probe(filename)) {
return factory->instance(filename)->write(radioData); StorageFormat * format = factory->instance(filename);
ret = format->write(radioData);
delete format;
break;
} }
} }
return false; return ret;
} }
bool convertEEprom(const QString & sourceEEprom, const QString & destinationEEprom, const QString & firmwareFilename) bool convertEEprom(const QString & sourceEEprom, const QString & destinationEEprom, const QString & firmwareFilename)
@ -102,26 +115,26 @@ bool convertEEprom(const QString & sourceEEprom, const QString & destinationEEpr
FirmwareInterface firmware(firmwareFilename); FirmwareInterface firmware(firmwareFilename);
if (!firmware.isValid()) if (!firmware.isValid())
return false; return false;
uint8_t version = firmware.getEEpromVersion(); uint8_t version = firmware.getEEpromVersion();
unsigned int variant = firmware.getEEpromVariant(); unsigned int variant = firmware.getEEpromVariant();
QSharedPointer<RadioData> radioData = QSharedPointer<RadioData>(new RadioData()); QSharedPointer<RadioData> radioData = QSharedPointer<RadioData>(new RadioData());
Storage storage(sourceEEprom); Storage storage(sourceEEprom);
if (!storage.load(*radioData)) if (!storage.load(*radioData))
return false; return false;
QByteArray eeprom(EESIZE_MAX, 0); QByteArray eeprom(EESIZE_MAX, 0);
int size = getCurrentEEpromInterface()->save((uint8_t *)eeprom.data(), *radioData, version, variant); int size = getCurrentEEpromInterface()->save((uint8_t *)eeprom.data(), *radioData, version, variant);
if (size == 0) { if (size == 0) {
return false; return false;
} }
QFile destinationFile(destinationEEprom); QFile destinationFile(destinationEEprom);
if (!destinationFile.open(QIODevice::WriteOnly)) { if (!destinationFile.open(QIODevice::WriteOnly)) {
return false; return false;
} }
int result = destinationFile.write(eeprom.constData(), size); int result = destinationFile.write(eeprom.constData(), size);
destinationFile.close(); destinationFile.close();
return (result == size); return (result == size);
@ -131,7 +144,7 @@ bool convertEEprom(const QString & sourceEEprom, const QString & destinationEEpr
unsigned long LoadBackup(RadioData & radioData, uint8_t * eeprom, int size, int index) unsigned long LoadBackup(RadioData & radioData, uint8_t * eeprom, int size, int index)
{ {
std::bitset<NUM_ERRORS> errors; std::bitset<NUM_ERRORS> errors;
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) { foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadBackup(radioData, eeprom, size, index)); std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadBackup(radioData, eeprom, size, index));
if (result.test(ALL_OK)) { if (result.test(ALL_OK)) {
@ -141,7 +154,7 @@ unsigned long LoadBackup(RadioData & radioData, uint8_t * eeprom, int size, int
errors |= result; errors |= result;
} }
} }
if (errors.none()) { if (errors.none()) {
errors.set(UNKNOWN_ERROR); errors.set(UNKNOWN_ERROR);
} }
@ -152,7 +165,7 @@ unsigned long LoadBackup(RadioData & radioData, uint8_t * eeprom, int size, int
unsigned long LoadEepromXml(RadioData & radioData, QDomDocument & doc) unsigned long LoadEepromXml(RadioData & radioData, QDomDocument & doc)
{ {
std::bitset<NUM_ERRORS> errors; std::bitset<NUM_ERRORS> errors;
foreach(EEPROMInterface *eepromInterface, eepromInterfaces) { foreach(EEPROMInterface *eepromInterface, eepromInterfaces) {
std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadxml(radioData, doc)); std::bitset<NUM_ERRORS> result((unsigned long long)eepromInterface->loadxml(radioData, doc));
if (result.test(ALL_OK)) { if (result.test(ALL_OK)) {
@ -162,7 +175,7 @@ unsigned long LoadEepromXml(RadioData & radioData, QDomDocument & doc)
errors |= result; errors |= result;
} }
} }
if (errors.none()) { if (errors.none()) {
errors.set(UNKNOWN_ERROR); errors.set(UNKNOWN_ERROR);
} }

View file

@ -48,14 +48,14 @@ class StorageFormat
board(Board::BOARD_UNKNOWN) board(Board::BOARD_UNKNOWN)
{ {
} }
virtual ~StorageFormat() {}
virtual bool load(RadioData & radioData) = 0; virtual bool load(RadioData & radioData) = 0;
virtual bool write(const RadioData & radioData) = 0; virtual bool write(const RadioData & radioData) = 0;
QString error() { QString error() {
return _error; return _error;
} }
QString warning() { QString warning() {
return _warning; return _warning;
} }
@ -84,13 +84,13 @@ class StorageFormat
qDebug() << qPrintable(QString("[%1] error: %2").arg(name()).arg(error)); qDebug() << qPrintable(QString("[%1] error: %2").arg(name()).arg(error));
_error = error; _error = error;
} }
void setWarning(const QString & warning) void setWarning(const QString & warning)
{ {
qDebug() << qPrintable(QString("[%1] warning: %2").arg(name()).arg(warning)); qDebug() << qPrintable(QString("[%1] warning: %2").arg(name()).arg(warning));
_warning = warning; _warning = warning;
} }
QString filename; QString filename;
uint8_t version; uint8_t version;
QString _error; QString _error;
@ -104,6 +104,7 @@ class StorageFactory
StorageFactory() StorageFactory()
{ {
} }
virtual ~StorageFactory() {}
virtual QString name() = 0; virtual QString name() = 0;
virtual bool probe(const QString & filename) = 0; virtual bool probe(const QString & filename) = 0;
virtual StorageFormat * instance(const QString & filename) = 0; virtual StorageFormat * instance(const QString & filename) = 0;
@ -118,22 +119,22 @@ class DefaultStorageFactory : public StorageFactory
_name(name) _name(name)
{ {
} }
virtual QString name() virtual QString name()
{ {
return _name; return _name;
} }
virtual bool probe(const QString & filename) virtual bool probe(const QString & filename)
{ {
return filename.toLower().endsWith("." + _name); return filename.toLower().endsWith("." + _name);
} }
virtual StorageFormat * instance(const QString & filename) virtual StorageFormat * instance(const QString & filename)
{ {
return new T(filename); return new T(filename);
} }
QString _name; QString _name;
}; };
@ -144,24 +145,25 @@ class Storage : public StorageFormat
StorageFormat(filename) StorageFormat(filename)
{ {
} }
virtual QString name() { return "storage"; }; virtual QString name() { return "storage"; }
void setError(const QString & error) void setError(const QString & error)
{ {
_error = error; _error = error;
} }
void setWarning(const QString & warning) void setWarning(const QString & warning)
{ {
_warning = warning; _warning = warning;
} }
virtual bool load(RadioData & radioData); virtual bool load(RadioData & radioData);
virtual bool write(const RadioData & radioData); virtual bool write(const RadioData & radioData);
}; };
void registerStorageFactories(); void registerStorageFactories();
void unregisterStorageFactories();
#if 0 #if 0
unsigned long LoadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index); unsigned long LoadBackup(RadioData &radioData, uint8_t *eeprom, int esize, int index);

View file

@ -40,19 +40,6 @@ uint8_t getStickMode()
return limit<uint8_t>(0, g_eeGeneral.stickMode, 3); return limit<uint8_t>(0, g_eeGeneral.stickMode, 3);
} }
#if defined(PCBTARANIS)
void resetTrims()
{
TRIMS_GPIO_REG_RVD |= TRIMS_GPIO_PIN_RVD;
TRIMS_GPIO_REG_RVU |= TRIMS_GPIO_PIN_RVU;
TRIMS_GPIO_REG_RHL |= TRIMS_GPIO_PIN_RHL;
TRIMS_GPIO_REG_RHR |= TRIMS_GPIO_PIN_RHR;
TRIMS_GPIO_REG_LVD |= TRIMS_GPIO_PIN_LVD;
TRIMS_GPIO_REG_LVU |= TRIMS_GPIO_PIN_LVU;
TRIMS_GPIO_REG_LHL |= TRIMS_GPIO_PIN_LHL;
TRIMS_GPIO_REG_LHR |= TRIMS_GPIO_PIN_LHR;
}
#endif
OpenTxSimulator::OpenTxSimulator() OpenTxSimulator::OpenTxSimulator()
{ {
@ -96,11 +83,8 @@ void OpenTxSimulator::start(QByteArray & ee, bool tests)
void OpenTxSimulator::start(const char * filename, bool tests) void OpenTxSimulator::start(const char * filename, bool tests)
{ {
#if defined(ROTARY_ENCODER_NAVIGATION) if (main_thread_running)
for (uint8_t i=0; i<DIM(rotencValue); i++) { return;
rotencValue[i] = 0;
}
#endif
StartEepromThread(filename); StartEepromThread(filename);
StartAudioThread(volumeGain); StartAudioThread(volumeGain);
@ -109,6 +93,9 @@ void OpenTxSimulator::start(const char * filename, bool tests)
void OpenTxSimulator::stop() void OpenTxSimulator::stop()
{ {
if (!main_thread_running)
return;
StopSimu(); StopSimu();
#if defined(CPUARM) #if defined(CPUARM)
StopAudioThread(); StopAudioThread();

View file

@ -23,7 +23,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <string> #include <string>
#if !defined _MSC_VER || defined __GNUC__ #if !defined (_MSC_VER) || defined (__GNUC__)
#include <chrono> #include <chrono>
#include <sys/time.h> #include <sys/time.h>
#endif #endif
@ -135,6 +135,13 @@ void simuInit()
simuSetSwitch(i, 0); simuSetSwitch(i, 0);
simuSetKey(i, false); // a little dirty, but setting keys that don't exist is perfectly OK here simuSetKey(i, false); // a little dirty, but setting keys that don't exist is perfectly OK here
} }
for (int i=0; i<(NUM_STICKS+NUM_AUX_TRIMS)*2; i++)
simuSetTrim(i, false);
#if defined(ROTARY_ENCODER_NAVIGATION)
for (uint8_t i=0; i<DIM(rotencValue); i++)
rotencValue[i] = 0;
#endif
} }
#define NEG_CASE(sw_or_key, pin, mask) \ #define NEG_CASE(sw_or_key, pin, mask) \
@ -216,9 +223,9 @@ void simuSetKey(uint8_t key, bool state)
KEY_CASE(KEY_UP, KEYS_GPIO_REG_UP, KEYS_GPIO_PIN_UP) KEY_CASE(KEY_UP, KEYS_GPIO_REG_UP, KEYS_GPIO_PIN_UP)
KEY_CASE(KEY_DOWN, KEYS_GPIO_REG_DOWN, KEYS_GPIO_PIN_DOWN) KEY_CASE(KEY_DOWN, KEYS_GPIO_REG_DOWN, KEYS_GPIO_PIN_DOWN)
#endif #endif
#if defined(PCBSKY9X) && !defined(REVX) && !defined(AR9X) #if defined(PCBSKY9X) && !defined(REVX) && !defined(AR9X) && defined(ROTARY_ENCODERS)
KEY_CASE(BTN_REa, PIOB->PIO_PDSR, 0x40) KEY_CASE(BTN_REa, PIOB->PIO_PDSR, 0x40)
#elif defined(PCBGRUVIN9X) || defined(PCBMEGA2560) #elif (defined(PCBGRUVIN9X) || defined(PCBMEGA2560)) && (defined(ROTARY_ENCODERS) || defined(ROTARY_ENCODER_NAVIGATION))
KEY_CASE(BTN_REa, pind, 0x20) KEY_CASE(BTN_REa, pind, 0x20)
#elif defined(PCB9X) && defined(ROTARY_ENCODER_NAVIGATION) #elif defined(PCB9X) && defined(ROTARY_ENCODER_NAVIGATION)
KEY_CASE(BTN_REa, RotEncoder, 0x20) KEY_CASE(BTN_REa, RotEncoder, 0x20)
@ -337,6 +344,9 @@ void simuSetSwitch(uint8_t swtch, int8_t state)
void StartSimu(bool tests, const char * sdPath, const char * settingsPath) void StartSimu(bool tests, const char * sdPath, const char * settingsPath)
{ {
if (main_thread_running)
return;
s_current_protocol[0] = 255; s_current_protocol[0] = 255;
menuLevel = 0; menuLevel = 0;
@ -380,6 +390,9 @@ void StartSimu(bool tests, const char * sdPath, const char * settingsPath)
void StopSimu() void StopSimu()
{ {
if (!main_thread_running)
return;
main_thread_running = 0; main_thread_running = 0;
#if defined(CPUARM) #if defined(CPUARM)
@ -525,6 +538,7 @@ void StartAudioThread(int volumeGain)
simuAudio.leftoverLen = 0; simuAudio.leftoverLen = 0;
simuAudio.threadRunning = true; simuAudio.threadRunning = true;
simuAudio.volumeGain = volumeGain; simuAudio.volumeGain = volumeGain;
TRACE_SIMPGMSPACE("StartAudioThread(%d)", volumeGain);
setScaledVolume(VOLUME_LEVEL_DEF); setScaledVolume(VOLUME_LEVEL_DEF);
pthread_attr_t attr; pthread_attr_t attr;
@ -569,12 +583,17 @@ void lcdOff()
void lcdRefresh() void lcdRefresh()
{ {
static bool lightEnabled = (bool)isBacklightEnabled();
#if defined(PCBFLAMENCO) #if defined(PCBFLAMENCO)
TW8823_SendScreen(); TW8823_SendScreen();
#endif #endif
memcpy(simuLcdBuf, displayBuf, sizeof(simuLcdBuf)); if ((bool(isBacklightEnabled()) != lightEnabled) || memcmp(simuLcdBuf, displayBuf, DISPLAY_BUFFER_SIZE)) {
simuLcdRefresh = true; memcpy(simuLcdBuf, displayBuf, DISPLAY_BUFFER_SIZE);
lightEnabled = (bool)isBacklightEnabled();
simuLcdRefresh = true;
}
} }
void telemetryPortInit(uint8_t baudrate) void telemetryPortInit(uint8_t baudrate)

View file

@ -28,7 +28,7 @@ uint8_t * eeprom_buffer_data;
volatile int32_t eeprom_buffer_size; volatile int32_t eeprom_buffer_size;
bool eeprom_read_operation; bool eeprom_read_operation;
bool eeprom_thread_running = true; bool eeprom_thread_running = false;
#if defined(EEPROM_SIZE) #if defined(EEPROM_SIZE)
uint8_t eeprom[EEPROM_SIZE]; uint8_t eeprom[EEPROM_SIZE];
@ -41,7 +41,7 @@ sem_t * eeprom_write_sem;
void eepromReadBlock (uint8_t * buffer, size_t address, size_t size) void eepromReadBlock (uint8_t * buffer, size_t address, size_t size)
{ {
assert(size); assert(size);
if (fp) { if (fp) {
// TRACE("EEPROM read (pos=%d, size=%d)", pointer_eeprom, size); // TRACE("EEPROM read (pos=%d, size=%d)", pointer_eeprom, size);
if (fseek(fp, address, SEEK_SET) < 0) if (fseek(fp, address, SEEK_SET) < 0)
@ -154,6 +154,7 @@ void StartEepromThread(const char * filename)
if (!fp) if (!fp)
perror("error in fopen"); perror("error in fopen");
} }
#ifdef __APPLE__ #ifdef __APPLE__
eeprom_write_sem = sem_open("eepromsem", O_CREAT, S_IRUSR | S_IWUSR, 0); eeprom_write_sem = sem_open("eepromsem", O_CREAT, S_IRUSR | S_IWUSR, 0);
#else #else
@ -161,8 +162,10 @@ void StartEepromThread(const char * filename)
sem_init(eeprom_write_sem, 0, 0); sem_init(eeprom_write_sem, 0, 0);
#endif #endif
eeprom_thread_running = true; if (!pthread_create(&eeprom_thread_pid, NULL, &eeprom_thread_function, NULL))
pthread_create(&eeprom_thread_pid, NULL, &eeprom_thread_function, NULL); eeprom_thread_running = true;
else
perror("Could not create eeprom thread.");
} }
void StopEepromThread() void StopEepromThread()
@ -178,5 +181,6 @@ void StopEepromThread()
free(eeprom_write_sem); free(eeprom_write_sem);
#endif #endif
if (fp) fclose(fp); if (fp)
fclose(fp);
} }

View file

@ -97,8 +97,8 @@ void simuFatfsSetPaths(const char * sdPath, const char * settingsPath)
if (settingsPath) { if (settingsPath) {
simuSettingsDirectory = removeTrailingPathDelimiter(fixPathDelimiters(settingsPath)); simuSettingsDirectory = removeTrailingPathDelimiter(fixPathDelimiters(settingsPath));
} }
TRACE_SIMPGMSPACE("simuFatfsSetPaths(): simuSdDirectory: \"\"", simuSdDirectory.c_str()); TRACE_SIMPGMSPACE("simuFatfsSetPaths(): simuSdDirectory: \"%s\"", simuSdDirectory.c_str());
TRACE_SIMPGMSPACE("simuFatfsSetPaths(): simuSettingsDirectory: \"\"", simuSettingsDirectory.c_str()); TRACE_SIMPGMSPACE("simuFatfsSetPaths(): simuSettingsDirectory: \"%s\"", simuSettingsDirectory.c_str());
} }
bool startsWith(const char *path, const char * start) bool startsWith(const char *path, const char * start)