[Simulator] Asynchronous SimulatorInterface & a few new features. (#4738)
* [Simulator] Create RadioKeyWidget class for UI buttons & refactor ButtonsWidget; Refactor SimulatedUIWidget (and subtypes) to use new RadioKeyWidgets/ButtonsWidget; Centralize help text for key mappings and get creative with some icons; Simplify some radio UI setups with rectangular buttons.
* [Simulator] Convert all simulator data I/O to signals/slots mechanism:
* SimulatorInterface/OpenTxSimulator:
- Now inherits from QObject to allow signal/slot interface;
- Allows data exchange on a per-item basis (eg. each I/O value is treated separately instead of sending whole arrays or structs of data);
- Checks for data changes and only emits signals when change is detected (GUI can now assume only new values are being sent);
- Manages its own 10ms timer (doesn't rely on GUI to do that);
- Sends "heartbeat" signals @ 1Hz for status monitoring;
* Simulator GUI:
- All data is exchanged between GUI elements as well as SimulatorInterface via signals/slots using standardized methods;
- Data is sent immediately, and only, when actually changed (eg. a control is moved) instead of in bulk at specific time intervals;
- Similarly, an asynchronous method is used for reading incoming data, w/out timers or loops;
- Improve VirtualJoystickWidget to be more encapsulated and configurable;
- Pause telemetry simulator if window is hidden;
* [Simulator] Move SimulatorInterface instance to separate thread, ensure safe asynchronous operations & proper timer interactions; Protect/remove some functions, & reorganize the order (cosmetics).
* [Simulator] Traces are now delivered to OpenTxSimulator and one or more QIODevice(s) can be added as recipient(s); Add SimulatorInterface::getCapability() for compile-time settings; Remove reversed POT1/SLIDER1 mixer exception (Taranis) requirement for SIMU; Fix plus/minus key delay on wheel event w/out encoder.
* [Simulator] Add current knob/slider/trim input value in tool-tips (KnobWidget and SliderWidget).
* [Simulator] Fix trims widget internal value not properly updating, and remove trim influence on virtual joystick X/Y value display (closes #4671).
* [SimulatorInterface] Add handling of transmitter input voltage, including a rough conversion of volts to ADC value for different boards, and default battery volts lookup function; Clear analogs array before starting.
* [Simulator] Add SimulatorInterface::init() method to separate pre-startup tasks; Report actual trim range, not just extended on/off; Change how radio widget states are restored; VirtualJoystickWidget: Connect trim changes directly from simulator, connect joystick events directly, report stick mode directly instead of setting values/constraints externally.
* [Simulator] Calculate default Tx V input based on configured range in radio settings (or warning V+2 for radios which don't support a range).
* [Simulator] Add functional aux. trims for Horus (closes #4699).
* [Companion] Remove problematic QMessageLogContext from AppDebugMessageHandler::messageOutput().
* [Simulator] Prevent trim change via slider if disabled for flight mode (closes #4600).
* [OpenTxSimulator] Fixes for Qt < 5.4.
* [OpenTxSimulator] Fix slot name.
This commit is contained in:
committed by
Bertrand Songis
parent
36bb951314
commit
57dc0159d6
@@ -34,96 +34,141 @@
|
||||
#include <QLibrary>
|
||||
#include <QMap>
|
||||
|
||||
struct TxInputs
|
||||
{
|
||||
int sticks[CPN_MAX_STICKS]; /* lh lv rv rh */
|
||||
int pots[CPN_MAX_POTS];
|
||||
int switches[CPN_MAX_SWITCHES];
|
||||
bool keys[CPN_MAX_KEYS];
|
||||
bool rotenc;
|
||||
bool trims[CPN_MAX_TRIM_SW];
|
||||
};
|
||||
#define SIMULATOR_INTERFACE_HEARTBEAT_PERIOD 1000 // ms
|
||||
|
||||
class TxOutputs
|
||||
class SimulatorInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TxOutputs() { memset(this, 0, sizeof(TxOutputs)); }
|
||||
int chans[CPN_MAX_CHNOUT];
|
||||
bool vsw[CPN_MAX_LOGICAL_SWITCHES];
|
||||
int gvars[CPN_MAX_FLIGHT_MODES][CPN_MAX_GVARS];
|
||||
unsigned int beep;
|
||||
// uint8_t phase;
|
||||
};
|
||||
|
||||
struct Trims
|
||||
{
|
||||
int values[CPN_MAX_TRIMS]; /* lh lv rv rh t5 t6 */
|
||||
bool extended;
|
||||
};
|
||||
enum InputSourceType {
|
||||
INPUT_SRC_NONE = 0,
|
||||
INPUT_SRC_ANALOG, // any analog source, index into g_anas[]
|
||||
INPUT_SRC_STICK, // Board::StickAxes, g_anas[index]
|
||||
INPUT_SRC_KNOB, // g_anas[index + StickAxes]
|
||||
INPUT_SRC_SLIDER, // g_anas[index + StickAxes + num_pots]
|
||||
INPUT_SRC_TXVIN, // g_anas[Analogs::TX_VOLTAGE]
|
||||
INPUT_SRC_SWITCH, // Named 2/3-pos switches
|
||||
INPUT_SRC_TRIM_SW, // Board::TrimSwitches
|
||||
INPUT_SRC_TRIM, // Board::TrimAxes
|
||||
INPUT_SRC_KEY, // UI key/pushbutton
|
||||
INPUT_SRC_ROTENC, // Rotary encoder (TODO)
|
||||
INPUT_SRC_TRAINER, // Virtual trainer input
|
||||
INPUT_SRC_ENUM_COUNT
|
||||
};
|
||||
|
||||
class SimulatorInterface
|
||||
{
|
||||
public:
|
||||
enum OutputSourceType {
|
||||
OUTPUT_SRC_NONE = 0,
|
||||
OUTPUT_SRC_CHAN_OUT,
|
||||
OUTPUT_SRC_CHAN_MIX,
|
||||
OUTPUT_SRC_TRIM_VALUE,
|
||||
OUTPUT_SRC_TRIM_RANGE,
|
||||
OUTPUT_SRC_VIRTUAL_SW,
|
||||
OUTPUT_SRC_PHASE,
|
||||
OUTPUT_SRC_GVAR,
|
||||
OUTPUT_SRC_ENUM_COUNT
|
||||
};
|
||||
|
||||
// only for data not available from Boards or Firmware, eg. compile-time options
|
||||
enum Capability {
|
||||
CAP_LUA, // LUA
|
||||
CAP_ROTARY_ENC, // ROTARY_ENCODERS
|
||||
CAP_ROTARY_ENC_NAV, // ROTARY_ENCODER_NAVIGATION
|
||||
CAP_TELEM_FRSKY_SPORT, // TELEMETRY_FRSKY_SPORT
|
||||
CAP_ENUM_COUNT
|
||||
};
|
||||
|
||||
// This allows automatic en/decoding of flight mode + gvar value to/from any int32
|
||||
struct gVarMode_t {
|
||||
int16_t value;
|
||||
uint8_t mode;
|
||||
|
||||
gVarMode_t(int i = 0) {
|
||||
set(i);
|
||||
}
|
||||
void set(int i) {
|
||||
mode = (i >> 16) & 0xFF;
|
||||
value = (i & 0xFFFF);
|
||||
}
|
||||
operator int() {
|
||||
return ((mode << 16) | (value & 0xFFFF));
|
||||
}
|
||||
gVarMode_t & operator =(const int i) {
|
||||
set(i);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct TxOutputs {
|
||||
TxOutputs() { clear(); }
|
||||
void clear() { memset(this, 0, sizeof(TxOutputs)); }
|
||||
|
||||
int16_t chans[CPN_MAX_CHNOUT]; // final channel outputs
|
||||
int16_t ex_chans[CPN_MAX_CHNOUT]; // raw mix outputs
|
||||
int16_t gvars[CPN_MAX_FLIGHT_MODES][CPN_MAX_GVARS];
|
||||
int trims[CPN_MAX_TRIMS]; // Board::TrimAxes enum
|
||||
bool vsw[CPN_MAX_LOGICAL_SWITCHES]; // virtual/logic switches
|
||||
int8_t phase;
|
||||
qint16 trimRange; // TRIM_MAX or TRIM_EXTENDED_MAX
|
||||
// bool beep;
|
||||
};
|
||||
|
||||
virtual ~SimulatorInterface() {}
|
||||
|
||||
virtual void setSdPath(const QString & sdPath = "", const QString & settingsPath = "") { }
|
||||
|
||||
virtual void setVolumeGain(int value) { }
|
||||
|
||||
virtual void start(QByteArray & eeprom, bool tests=true) = 0;
|
||||
|
||||
virtual void start(const char * filename, bool tests=true) = 0;
|
||||
|
||||
virtual void stop() = 0;
|
||||
|
||||
virtual void readEepromData(QByteArray & dest) = 0;
|
||||
|
||||
virtual bool timer10ms() = 0;
|
||||
|
||||
virtual QString name() = 0;
|
||||
virtual bool isRunning() = 0;
|
||||
virtual void readRadioData(QByteArray & dest) = 0;
|
||||
virtual uint8_t * getLcd() = 0;
|
||||
|
||||
virtual bool lcdChanged(bool &lightEnable) = 0;
|
||||
|
||||
virtual void setValues(TxInputs &inputs) = 0;
|
||||
|
||||
virtual void getValues(TxOutputs &outputs) = 0;
|
||||
|
||||
virtual void setTrim(unsigned int idx, int value) = 0;
|
||||
|
||||
virtual void getTrims(Trims &trims) = 0;
|
||||
|
||||
virtual unsigned int getPhase() = 0;
|
||||
|
||||
virtual const char * getPhaseName(unsigned int phase) = 0;
|
||||
|
||||
virtual void wheelEvent(int steps) { }
|
||||
|
||||
virtual const char * getError() = 0;
|
||||
|
||||
virtual void sendTelemetry(uint8_t * data, unsigned int len) = 0;
|
||||
|
||||
virtual uint8_t getSensorInstance(uint16_t id, uint8_t defaultValue = 0) = 0;
|
||||
|
||||
virtual uint16_t getSensorRatio(uint16_t id) = 0;
|
||||
virtual const int getCapability(Capability cap) = 0;
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void init() = 0;
|
||||
virtual void start(const char * filename = NULL, bool tests = true) = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void setSdPath(const QString & sdPath = "", const QString & settingsPath = "") = 0;
|
||||
virtual void setVolumeGain(const int value) = 0;
|
||||
virtual void setRadioData(const QByteArray & data) = 0;
|
||||
virtual void setAnalogValue(uint8_t index, int16_t value) = 0;
|
||||
virtual void setKey(uint8_t key, bool state) = 0;
|
||||
virtual void setSwitch(uint8_t swtch, int8_t state) = 0;
|
||||
virtual void setTrim(unsigned int idx, int value) = 0;
|
||||
virtual void setTrimSwitch(uint8_t trim, bool state) = 0;
|
||||
virtual void setTrainerInput(unsigned int inputNumber, int16_t value) = 0;
|
||||
|
||||
virtual void installTraceHook(void (*callback)(const char *)) = 0;
|
||||
|
||||
virtual void setInputValue(int type, uint8_t index, int16_t value) = 0;
|
||||
virtual void rotaryEncoderEvent(int steps) = 0;
|
||||
virtual void setTrainerTimeout(uint16_t ms) = 0;
|
||||
virtual void sendTelemetry(uint8_t * data, unsigned int len) = 0;
|
||||
virtual void setLuaStateReloadPermanentScripts() = 0;
|
||||
virtual void addTracebackDevice(QIODevice * device) = 0;
|
||||
virtual void removeTracebackDevice(QIODevice * device) = 0;
|
||||
|
||||
signals:
|
||||
|
||||
void started();
|
||||
void stopped();
|
||||
void heartbeat(qint32 loops, qint64 timestamp);
|
||||
void runtimeError(const QString & error);
|
||||
void lcdChange(bool backlightEnable);
|
||||
void phaseChanged(qint8 phase, const QString & name);
|
||||
void channelOutValueChange(quint8 index, qint32 value);
|
||||
void channelMixValueChange(quint8 index, qint32 value);
|
||||
void virtualSwValueChange(quint8 index, qint32 value);
|
||||
void trimValueChange(quint8 index, qint32 value);
|
||||
void trimRangeChange(quint8 index, qint32 min, qint16 max);
|
||||
void gVarValueChange(quint8 index, qint32 value);
|
||||
void outputValueChange(int type, quint8 index, qint32 value);
|
||||
};
|
||||
|
||||
class SimulatorFactory {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~SimulatorFactory() { }
|
||||
|
||||
virtual QString name() = 0;
|
||||
|
||||
virtual Board::Type type() = 0;
|
||||
|
||||
virtual SimulatorInterface *create() = 0;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user