Merge pull request #3142 from opentx/dsbeach/next-issue2919-telemetry-sensors-simulator

Ported simulator enhancements to next
This commit is contained in:
Bertrand Songis
2015-12-13 18:43:07 +01:00
12 changed files with 3364 additions and 962 deletions
@@ -54,6 +54,10 @@ class Er9xSimulator : public SimulatorInterface {
virtual void sendTelemetry(uint8_t * data, unsigned int len) {};
virtual uint8_t getSensorInstance(uint16_t id) { return 0; };
virtual uint16_t getSensorRatio(uint16_t id) { return 0; };
virtual void setTrainerInput(unsigned int inputNumber, int16_t value) {};
protected:
@@ -54,6 +54,10 @@ class Ersky9xSimulator : public SimulatorInterface {
virtual void sendTelemetry(uint8_t * data, unsigned int len) {};
virtual uint8_t getSensorInstance(uint16_t id) { return 0; };
virtual uint16_t getSensorRatio(uint16_t id) { return 0; };
virtual void setTrainerInput(unsigned int inputNumber, int16_t value) {};
protected:
@@ -607,6 +607,36 @@ void OpenTxSimulator::sendTelemetry(::uint8_t * data, unsigned int len)
#endif
}
uint8_t OpenTxSimulator::getSensorInstance(uint16_t id)
{
#if defined(FRSKY_SPORT)
for (int i = 0; i<MAX_SENSORS; i++) {
if (isTelemetryFieldAvailable(i)) {
TelemetrySensor * sensor = &g_model.telemetrySensors[i];
if (sensor->id == id) {
return sensor->instance;
}
}
}
#endif
return 0;
}
uint16_t OpenTxSimulator::getSensorRatio(uint16_t id)
{
#if defined(FRSKY_SPORT)
for (int i = 0; i<MAX_SENSORS; i++) {
if (isTelemetryFieldAvailable(i)) {
TelemetrySensor * sensor = &g_model.telemetrySensors[i];
if (sensor->id == id) {
return sensor->custom.ratio;
}
}
}
#endif
return 0;
}
void OpenTxSimulator::setTrainerInput(unsigned int inputNumber, ::int16_t value)
{
#define SETTRAINER_IMPORT
@@ -130,6 +130,10 @@ class DLLEXPORT OpenTxSimulator : public SimulatorInterface {
virtual void sendTelemetry(uint8_t * data, unsigned int len);
virtual uint8_t getSensorInstance(uint16_t id);
virtual uint16_t getSensorRatio(uint16_t id);
virtual void setTrainerInput(unsigned int inputNumber, int16_t value);
virtual void installTraceHook(void (*callback)(const char *));
+353 -346
View File
@@ -16,13 +16,13 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<property name="minimumSize">
<size>
<width>960</width>
<height>850</height>
</size>
</property>
<property name="minimumSize">
<property name="maximumSize">
<size>
<width>960</width>
<height>850</height>
@@ -36,345 +36,13 @@
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>5</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="1" column="0" colspan="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>700</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="simu">
<attribute name="title">
<string>Horus Simulator</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<property name="topMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<property name="horizontalSpacing">
<number>0</number>
</property>
<item row="0" column="1">
<layout class="QGridLayout" name="gridLayout_3">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0" rowspan="3">
<widget class="ButtonsWidget" name="leftbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>147</width>
<height>292</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>147</width>
<height>292</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/left.png);</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QWidget" name="top" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>9</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>9</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/top.png)</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="LcdWidget" name="lcd" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>272</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>272</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
</font>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QWidget" name="bottom" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>11</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>11</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
<kerning>false</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/bottom.png)</string>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="3">
<widget class="ButtonsWidget" name="led" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>24</width>
<height>292</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>24</width>
<height>292</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/led.png)</string>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="3">
<widget class="ButtonsWidget" name="borderRight" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>27</width>
<height>292</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>27</width>
<height>292</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/border-right.png)</string>
</property>
</widget>
</item>
<item row="0" column="4" rowspan="3">
<widget class="ButtonsWidget" name="rightbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>147</width>
<height>292</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>147</width>
<height>292</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/right.png)</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>292</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>292</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="outputs">
<attribute name="title">
<string>O&amp;utputs</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<layout class="QGridLayout" name="logicalSwitchesLayout"/>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="channelsLayout"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="outputs2">
<attribute name="title">
<string>Ou&amp;tputs2</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QGridLayout" name="logicalSwitchesLayout2"/>
</item>
<item>
<layout class="QGridLayout" name="channelsLayout2"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="misc">
<attribute name="title">
<string>&amp;Gvars</string>
</attribute>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>691</width>
<height>231</height>
</rect>
</property>
<layout class="QGridLayout" name="gvarsLayout"/>
</widget>
</widget>
</widget>
</item>
<item row="0" column="0">
<item row="1" column="0">
<widget class="QFrame" name="controlFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -404,16 +72,7 @@
<number>2</number>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>5</number>
</property>
<property name="spacing">
@@ -1779,6 +1438,354 @@ QPushButton:checked {
</layout>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="teleSim">
<property name="text">
<string>PF4 - Telemetry Simulator</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="trainerSim">
<property name="text">
<string>PF5 - Trainer Simulator</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="debugConsole">
<property name="text">
<string>PF6 - Debug Console Window</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="simu">
<attribute name="title">
<string>Horus Simulator</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<property name="topMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<property name="horizontalSpacing">
<number>0</number>
</property>
<item row="0" column="1">
<layout class="QGridLayout" name="gridLayout_3">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0" rowspan="3">
<widget class="ButtonsWidget" name="leftbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>147</width>
<height>292</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>147</width>
<height>292</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/left.png);</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QWidget" name="top" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>9</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>9</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/top.png)</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="LcdWidget" name="lcd" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>272</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>272</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
</font>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QWidget" name="bottom" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>11</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>480</width>
<height>11</height>
</size>
</property>
<property name="font">
<font>
<pointsize>5</pointsize>
<kerning>false</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/bottom.png)</string>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="3">
<widget class="ButtonsWidget" name="led" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>24</width>
<height>292</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>24</width>
<height>292</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/led.png)</string>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="3">
<widget class="ButtonsWidget" name="borderRight" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>27</width>
<height>292</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>27</width>
<height>292</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/border-right.png)</string>
</property>
</widget>
</item>
<item row="0" column="4" rowspan="3">
<widget class="ButtonsWidget" name="rightbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>147</width>
<height>292</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>147</width>
<height>292</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Horus/right.png)</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>292</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>292</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="outputs">
<attribute name="title">
<string>O&amp;utputs</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<layout class="QGridLayout" name="logicalSwitchesLayout"/>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="channelsLayout"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="outputs2">
<attribute name="title">
<string>Ou&amp;tputs2</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QGridLayout" name="logicalSwitchesLayout2"/>
</item>
<item>
<layout class="QGridLayout" name="channelsLayout2"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="misc">
<attribute name="title">
<string>&amp;Gvars</string>
</attribute>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>691</width>
<height>231</height>
</rect>
</property>
<layout class="QGridLayout" name="gvarsLayout"/>
</widget>
</widget>
</widget>
</item>
<item row="2" column="0" colspan="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>700</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
@@ -30,251 +30,13 @@
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>5</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="1" column="0" colspan="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>570</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="simu">
<attribute name="title">
<string>Taranis Simulator</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="1">
<layout class="QGridLayout" name="gridLayout_3" columnminimumwidth="120,424,120">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0" rowspan="3">
<widget class="ButtonsWidget" name="leftbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>208</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Taranis/x9l0.png);</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QWidget" name="top" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>424</width>
<height>38</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Taranis/x9t0.png)</string>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="3">
<widget class="ButtonsWidget" name="rightbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>208</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Taranis/x9r0.png)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LcdWidget" name="lcd" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>424</width>
<height>128</height>
</size>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QWidget" name="bottom" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>424</width>
<height>42</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Taranis/x9b0.png)</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>438</width>
<height>6</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="outputs">
<attribute name="title">
<string>Outputs</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<layout class="QGridLayout" name="logicalSwitchesLayout"/>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="channelsLayout"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="outputs2">
<attribute name="title">
<string>Outputs2</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QGridLayout" name="logicalSwitchesLayout2"/>
</item>
<item>
<layout class="QGridLayout" name="channelsLayout2"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="misc">
<attribute name="title">
<string>Gvars</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<layout class="QGridLayout" name="gvarsLayout"/>
</item>
</layout>
</widget>
</widget>
</item>
<item row="0" column="0">
<item row="1" column="0">
<widget class="QFrame" name="controlFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -1740,6 +1502,260 @@ QPushButton:checked {
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>570</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="simu">
<attribute name="title">
<string>Taranis Simulator</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="1">
<layout class="QGridLayout" name="gridLayout_3" columnminimumwidth="120,424,120">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0" rowspan="3">
<widget class="ButtonsWidget" name="leftbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>208</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Taranis/x9l0.png);</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QWidget" name="top" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>424</width>
<height>38</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Taranis/x9t0.png)</string>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="3">
<widget class="ButtonsWidget" name="rightbuttons" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>208</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Taranis/x9r0.png)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LcdWidget" name="lcd" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>424</width>
<height>128</height>
</size>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QWidget" name="bottom" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>424</width>
<height>42</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:url(:/images/simulator/Taranis/x9b0.png)</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>438</width>
<height>6</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="outputs">
<attribute name="title">
<string>Outputs</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<layout class="QGridLayout" name="logicalSwitchesLayout"/>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="channelsLayout"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="outputs2">
<attribute name="title">
<string>Outputs2</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QGridLayout" name="logicalSwitchesLayout2"/>
</item>
<item>
<layout class="QGridLayout" name="channelsLayout2"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="misc">
<attribute name="title">
<string>Gvars</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<layout class="QGridLayout" name="gvarsLayout"/>
</item>
</layout>
</widget>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="teleSim">
<property name="text">
<string>PF4 - Telemetry Simulator</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="trainerSim">
<property name="text">
<string>PF5 - Trainer Simulator</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="debugConsole">
<property name="text">
<string>PF6 - Debug Console Output</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
@@ -70,6 +70,9 @@ SimulatorDialogHorus::SimulatorDialogHorus(QWidget * parent, SimulatorInterface
connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
connect(ui->teleSim, SIGNAL(released()), this, SLOT(openTelemetrySimulator()));
connect(ui->trainerSim, SIGNAL(released()), this, SLOT(openTrainerSimulator()));
connect(ui->debugConsole, SIGNAL(released()), this, SLOT(openDebugOutput()));
}
SimulatorDialogHorus::~SimulatorDialogHorus()
@@ -77,6 +77,9 @@ SimulatorDialogTaranis::SimulatorDialogTaranis(QWidget * parent, SimulatorInterf
connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
connect(ui->teleSim, SIGNAL(released()), this, SLOT(openTelemetrySimulator()));
connect(ui->trainerSim, SIGNAL(released()), this, SLOT(openTrainerSimulator()));
connect(ui->debugConsole, SIGNAL(released()), this, SLOT(openDebugOutput()));
}
SimulatorDialogTaranis::~SimulatorDialogTaranis()
@@ -99,6 +99,10 @@ class SimulatorInterface
virtual void sendTelemetry(uint8_t * data, unsigned int len) = 0;
virtual uint8_t getSensorInstance(uint16_t id) = 0;
virtual uint16_t getSensorRatio(uint16_t id) = 0;
virtual void setTrainerInput(unsigned int inputNumber, int16_t value) = 0;
virtual void installTraceHook(void (*callback)(const char *)) = 0;
+796 -58
View File
@@ -11,30 +11,174 @@ TelemetrySimulator::TelemetrySimulator(QWidget * parent, SimulatorInterface * si
{
ui->setupUi(this);
QPoint dialogCenter = mapToGlobal(rect().center());
QPoint parentWindowCenter = parent->window()->mapToGlobal(
parent->window()->rect().center());
move(parentWindowCenter - dialogCenter);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(onTimerEvent()));
timer->start(100);
logTimer = new QTimer(this);
connect(logTimer, SIGNAL(timeout()), this, SLOT(onLogTimerEvent()));
connect(ui->Simulate, SIGNAL(clicked(bool)), this, SLOT(onSimulateToggled(bool)));
connect(ui->loadLogFile, SIGNAL(released()), this, SLOT(onLoadLogFile()));
connect(ui->play, SIGNAL(released()), this, SLOT(onPlay()));
connect(ui->rewind, SIGNAL(clicked()), this, SLOT(onRewind()));
connect(ui->stepForward, SIGNAL(clicked()), this, SLOT(onStepForward()));
connect(ui->stepBack, SIGNAL(clicked()), this, SLOT(onStepBack()));
connect(ui->stop, SIGNAL(clicked()), this, SLOT(onStop()));
connect(ui->positionIndicator, SIGNAL(valueChanged(int)), this, SLOT(onPositionIndicatorChanged(int)));
connect(ui->replayRate, SIGNAL(valueChanged(int)), this, SLOT(onReplayRateChanged(int)));
ui->A1->setSpecialValueText(" ");
ui->A2->setSpecialValueText(" ");
ui->A3->setSpecialValueText(" ");
ui->A4->setSpecialValueText(" ");
ui->rpm->setSpecialValueText(" ");
ui->fuel->setSpecialValueText(" ");
ui->rxbt_ratio->setEnabled(false);
ui->A1_ratio->setEnabled(false);
ui->A2_ratio->setEnabled(false);
logPlayback = new LogPlaybackController(ui);
}
TelemetrySimulator::~TelemetrySimulator()
{
timer->stop();
logTimer->stop();
delete ui;
}
void TelemetrySimulator::onSimulateToggled(bool isChecked)
{
if (isChecked) {
timer->start(10);
}
else {
timer->stop();
}
}
void TelemetrySimulator::onLogTimerEvent()
{
logPlayback->stepForward(false);
}
void TelemetrySimulator::onTimerEvent()
{
if (ui->Simulate->isChecked()) {
generateTelemetryFrame();
generateTelemetryFrame();
}
void TelemetrySimulator::onLoadLogFile()
{
onStop(); // in case we are in playback mode
logPlayback->loadLogFile();
}
void TelemetrySimulator::onPlay()
{
if (logPlayback->isReady()) {
logTimer->start(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]);
logPlayback->play();
}
}
void TelemetrySimulator::onRewind()
{
if (logPlayback->isReady()) {
logTimer->stop();
logPlayback->rewind();
}
}
void TelemetrySimulator::onStepForward()
{
if (logPlayback->isReady()) {
logTimer->stop();
logPlayback->stepForward(true);
}
}
void TelemetrySimulator::onStepBack()
{
if (logPlayback->isReady()) {
logTimer->stop();
logPlayback->stepBack();
}
}
void TelemetrySimulator::onStop()
{
if (logPlayback->isReady()) {
logTimer->stop();
logPlayback->stop();
}
}
void TelemetrySimulator::onPositionIndicatorChanged(int value)
{
if (logPlayback->isReady()) {
logPlayback->updatePositionLabel(value);
logPlayback->setUiDataValues();
}
}
void TelemetrySimulator::onReplayRateChanged(int value)
{
if (logTimer->isActive()) {
logTimer->setInterval(logPlayback->logFrequency * 1000 / SPEEDS[ui->replayRate->value()]);
}
}
void TelemetrySimulator::closeEvent(QCloseEvent *event)
{
ui->Simulate->setChecked(false);
timer->stop();
logTimer->stop();
event->accept();
}
void TelemetrySimulator::showEvent(QShowEvent *event)
{
ui->rxbt_inst->setText(QString::number(simulator->getSensorInstance(BATT_ID)));
ui->rxbt_ratio->setValue(simulator->getSensorRatio(BATT_ID) / 10.0);
ui->rssi_inst->setText(QString::number(simulator->getSensorInstance(RSSI_ID)));
ui->swr_inst->setText(QString::number(simulator->getSensorInstance(SWR_ID)));
ui->a1_inst->setText(QString::number(simulator->getSensorInstance(ADC1_ID)));
ui->A1_ratio->setValue(simulator->getSensorRatio(ADC1_ID) / 10.0);
ui->a2_inst->setText(QString::number(simulator->getSensorInstance(ADC2_ID)));
ui->A2_ratio->setValue(simulator->getSensorRatio(ADC2_ID) / 10.0);
ui->a3_inst->setText(QString::number(simulator->getSensorInstance(A3_FIRST_ID)));
ui->a4_inst->setText(QString::number(simulator->getSensorInstance(A4_FIRST_ID)));
ui->t1_inst->setText(QString::number(simulator->getSensorInstance(T1_FIRST_ID)));
ui->t2_inst->setText(QString::number(simulator->getSensorInstance(T2_FIRST_ID)));
ui->rpm_inst->setText(QString::number(simulator->getSensorInstance(RPM_FIRST_ID)));
ui->fuel_inst->setText(QString::number(simulator->getSensorInstance(FUEL_FIRST_ID)));
ui->aspd_inst->setText(QString::number(simulator->getSensorInstance(AIR_SPEED_FIRST_ID)));
ui->vvspd_inst->setText(QString::number(simulator->getSensorInstance(VARIO_FIRST_ID)));
ui->valt_inst->setText(QString::number(simulator->getSensorInstance(ALT_FIRST_ID)));
ui->fasv_inst->setText(QString::number(simulator->getSensorInstance(VFAS_FIRST_ID)));
ui->fasc_inst->setText(QString::number(simulator->getSensorInstance(CURR_FIRST_ID)));
ui->cells_inst->setText(QString::number(simulator->getSensorInstance(CELLS_FIRST_ID)));
ui->gpsa_inst->setText(QString::number(simulator->getSensorInstance(GPS_ALT_FIRST_ID)));
ui->gpss_inst->setText(QString::number(simulator->getSensorInstance(GPS_SPEED_FIRST_ID)));
ui->gpsc_inst->setText(QString::number(simulator->getSensorInstance(GPS_COURS_FIRST_ID)));
ui->gpst_inst->setText(QString::number(simulator->getSensorInstance(GPS_TIME_DATE_FIRST_ID)));
ui->gpsll_inst->setText(QString::number(simulator->getSensorInstance(GPS_LONG_LATI_FIRST_ID)));
ui->accx_inst->setText(QString::number(simulator->getSensorInstance(ACCX_FIRST_ID)));
ui->accy_inst->setText(QString::number(simulator->getSensorInstance(ACCY_FIRST_ID)));
ui->accz_inst->setText(QString::number(simulator->getSensorInstance(ACCZ_FIRST_ID)));
ui->Simulate->setChecked(true);
onSimulateToggled(true); // not sure why this doesn't fire automatically
}
void setSportPacketCrc(uint8_t * packet)
{
short crc = 0;
@@ -63,133 +207,164 @@ void TelemetrySimulator::generateTelemetryFrame()
static int item = 0;
bool ok = true;
uint8_t buffer[FRSKY_SPORT_PACKET_SIZE];
static FlvssEmulator *flvss = new FlvssEmulator();
static GPSEmulator *gps = new GPSEmulator();
memset(buffer, 0, sizeof(buffer));
switch(item++) {
switch (item++) {
case 0:
if (ui->Rssi->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, RSSI_ID, LIMIT<uint32_t>(0, ui->Rssi->text().toInt(&ok, 0), 0xFF));
break;
#if defined(XJT_VERSION_ID)
generateSportPacket(buffer, 1, DATA_FRAME, XJT_VERSION_ID, 11);
#endif
break;
case 1:
#if defined(XJT_VERSION_ID)
generateSportPacket(buffer, INSTANCE, DATA_FRAME, XJT_VERSION_ID, 11);
#endif
if (ui->rxbt->text().length()) {
generateSportPacket(buffer, ui->rxbt_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, BATT_ID, LIMIT<uint32_t>(0, ui->rxbt->value() * 255.0 / ui->rxbt_ratio->value(), 0xFFFFFFFF));
}
break;
case 2:
if (ui->Swr->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, SWR_ID, LIMIT<uint32_t>(0, ui->Swr->text().toInt(&ok, 0), 0xFFFF));
if (ui->Rssi->text().length())
generateSportPacket(buffer, ui->rssi_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, RSSI_ID, LIMIT<uint32_t>(0, ui->Rssi->text().toInt(&ok, 0), 0xFF));
break;
case 3:
if (ui->A1->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, ADC1_ID, LIMIT<uint32_t>(0, ui->A1->text().toInt(&ok, 0), 0xFF));
if (ui->Swr->text().length())
generateSportPacket(buffer, ui->swr_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, SWR_ID, LIMIT<uint32_t>(0, ui->Swr->text().toInt(&ok, 0), 0xFFFF));
break;
case 4:
if (ui->A2->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, ADC2_ID, LIMIT<uint32_t>(0, ui->A2->text().toInt(&ok, 0), 0xFF));
if (ui->A1->value() > 0)
generateSportPacket(buffer, ui->a1_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ADC1_ID, LIMIT<uint32_t>(0, ui->A1->value() * 255.0 / ui->A1_ratio->value(), 0xFF));
break;
case 5:
if (ui->A3->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, A3_FIRST_ID, LIMIT<uint32_t>(0, ui->A3->text().toInt(&ok, 0), 0xFFFFFFFF));
if (ui->A2->value() > 0)
generateSportPacket(buffer, ui->a2_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ADC2_ID, LIMIT<uint32_t>(0, ui->A2->value() * 255.0 / ui->A2_ratio->value(), 0xFF));
break;
case 6:
if (ui->A4->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, A4_FIRST_ID, LIMIT<uint32_t>(0, ui->A4->text().toInt(&ok, 0), 0xFFFFFFFF));
if (ui->A3->value() > 0)
generateSportPacket(buffer, ui->a3_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, A3_FIRST_ID, LIMIT<uint32_t>(0, ui->A3->value() * 100.0, 0xFFFFFFFF));
break;
case 7:
if (ui->T1->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, T1_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T1->text().toInt(&ok, 0), 0x7FFFFFFF));
if (ui->A4->value() > 0)
generateSportPacket(buffer, ui->a4_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, A4_FIRST_ID, LIMIT<uint32_t>(0, ui->A4->value() * 100.0, 0xFFFFFFFF));
break;
case 8:
if (ui->T2->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, T2_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T2->text().toInt(&ok, 0), 0x7FFFFFFF));
if (ui->T1->value() != 0)
generateSportPacket(buffer, ui->t1_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, T1_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T1->value(), 0x7FFFFFFF));
break;
case 9:
if (ui->rpm->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, RPM_FIRST_ID, LIMIT<uint32_t>(0, ui->rpm->text().toInt(&ok, 0), 0xFFFF));
if (ui->T2->value() != 0)
generateSportPacket(buffer, ui->t2_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, T2_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->T2->value(), 0x7FFFFFFF));
break;
case 10:
if (ui->fuel->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, FUEL_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel->text().toInt(&ok, 0), 0xFFFF));
if (ui->rpm->value() > 0)
generateSportPacket(buffer, ui->rpm_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, RPM_FIRST_ID, LIMIT<uint32_t>(0, ui->rpm->value(), 0xFFFF));
break;
case 11:
if (ui->aspeed->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, AIR_SPEED_FIRST_ID, LIMIT<uint32_t>(0, ui->aspeed->text().toInt(&ok, 0), 0xFFFFFFFF));
if (ui->fuel->value() > 0)
generateSportPacket(buffer, ui->fuel_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, FUEL_FIRST_ID, LIMIT<uint32_t>(0, ui->fuel->value(), 0xFFFF));
break;
case 12:
if (ui->vspeed->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, VARIO_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->vspeed->text().toInt(&ok, 0), 0x7FFFFFFF));
if (ui->vspeed->value() != 0)
generateSportPacket(buffer, ui->vvspd_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, VARIO_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->vspeed->value() * 100.0, 0x7FFFFFFF));
break;
case 13:
if (ui->valt->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, ALT_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->valt->text().toInt(&ok, 0), 0x7FFFFFFF));
if (ui->valt->value() != 0)
generateSportPacket(buffer, ui->valt_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ALT_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->valt->value() * 100.0, 0x7FFFFFFF));
break;
case 14:
if (ui->accx->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, ACCX_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accx->text().toInt(&ok, 0), 0x7FFFFFFF));
if (ui->vfas->value() != 0)
generateSportPacket(buffer, ui->fasv_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, VFAS_FIRST_ID, LIMIT<uint32_t>(0, ui->vfas->value() * 100.0, 0xFFFFFFFF));
break;
case 15:
if (ui->accy->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, ACCY_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accy->text().toInt(&ok, 0), 0x7FFFFFFF));
if (ui->curr->value() != 0)
generateSportPacket(buffer, ui->fasc_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, CURR_FIRST_ID, LIMIT<uint32_t>(0, ui->curr->value() * 10.0, 0xFFFFFFFF));
break;
case 16:
if (ui->accz->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, ACCZ_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accz->text().toInt(&ok, 0), 0x7FFFFFFF));
double cellValues[FlvssEmulator::MAXCELLS];
if (ui->cell1->value() > 0.009) { // ??? cell1 returning non-zero value when spin box is zero!
cellValues[0] = ui->cell1->value();
cellValues[1] = ui->cell2->value();
cellValues[2] = ui->cell3->value();
cellValues[3] = ui->cell4->value();
cellValues[4] = ui->cell5->value();
cellValues[5] = ui->cell6->value();
generateSportPacket(buffer, ui->cells_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, CELLS_FIRST_ID, flvss->setAllCells_GetNextPair(cellValues));
}
else {
cellValues[0] = 0;
flvss->setAllCells_GetNextPair(cellValues);
}
break;
case 17:
if (ui->vfas->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, VFAS_FIRST_ID, LIMIT<uint32_t>(0, ui->vfas->text().toInt(&ok, 0), 0xFFFFFFFF));
if (ui->aspeed->value() > 0)
generateSportPacket(buffer, ui->aspd_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, AIR_SPEED_FIRST_ID, LIMIT<uint32_t>(0, ui->aspeed->value() * 10.0, 0xFFFFFFFF));
break;
case 18:
if (ui->curr->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, CURR_FIRST_ID, LIMIT<uint32_t>(0, ui->curr->text().toInt(&ok, 0), 0xFFFFFFFF));
if (ui->gps_alt->value() != 0) {
gps->setGPSAltitude(ui->gps_alt->value());
generateSportPacket(buffer, ui->gpsa_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_ALT_FIRST_ID, gps->getNextPacketData(GPS_ALT_FIRST_ID));
}
break;
case 19:
if (ui->cells->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, CELLS_FIRST_ID, LIMIT<uint32_t>(0, ui->cells->text().toInt(&ok, 0), 0xFFFFFFFF));
if (ui->gps_speed->value() > 0) {
gps->setGPSSpeedKMH(ui->gps_speed->value());
generateSportPacket(buffer, ui->gpss_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_SPEED_FIRST_ID, gps->getNextPacketData(GPS_SPEED_FIRST_ID));
}
break;
case 20:
if (ui->gps_alt->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, GPS_ALT_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->gps_alt->text().toInt(&ok, 0), 0x7FFFFFFF));
if (ui->gps_course->value() != 0) {
gps->setGPSCourse(ui->gps_course->value());
generateSportPacket(buffer, ui->gpsc_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_COURS_FIRST_ID, gps->getNextPacketData(GPS_COURS_FIRST_ID));
}
break;
case 21:
if (ui->gps_speed->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, GPS_SPEED_FIRST_ID, LIMIT<uint32_t>(0, ui->gps_speed->text().toInt(&ok, 0), 0xFFFFFFFF));
if (ui->gps_time->text().length()) {
gps->setGPSDateTime(ui->gps_time->text());
generateSportPacket(buffer, ui->gpst_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_TIME_DATE_FIRST_ID, gps->getNextPacketData(GPS_TIME_DATE_FIRST_ID));
}
break;
case 22:
if (ui->gps_course->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, GPS_COURS_FIRST_ID, LIMIT<uint32_t>(0, ui->gps_course->text().toInt(&ok, 0), 0xFFFFFFFF));
if (ui->gps_latlon->text().length()) {
gps->setGPSLatLon(ui->gps_latlon->text());
generateSportPacket(buffer, ui->gpsll_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, GPS_LONG_LATI_FIRST_ID, gps->getNextPacketData(GPS_LONG_LATI_FIRST_ID));
}
break;
case 23:
if (ui->gps_time->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, GPS_TIME_DATE_FIRST_ID, LIMIT<uint32_t>(0, ui->gps_time->text().toInt(&ok, 0), 0xFFFFFFFF));
break;
if (ui->accx->value() != 0)
generateSportPacket(buffer, ui->accx_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ACCX_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accx->value() * 100.0, 0x7FFFFFFF));
break;
case 24:
if (ui->gps_latlon->text().length())
generateSportPacket(buffer, INSTANCE, DATA_FRAME, GPS_LONG_LATI_FIRST_ID, LIMIT<uint32_t>(0, ui->gps_latlon->text().toInt(&ok, 0), 0xFFFFFFFF));
if (ui->accy->value() != 0)
generateSportPacket(buffer, ui->accy_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ACCY_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accy->value() * 100.0, 0x7FFFFFFF));
break;
case 25:
if (ui->accz->value() != 0)
generateSportPacket(buffer, ui->accz_inst->text().toInt(&ok, 0) - 1, DATA_FRAME, ACCZ_FIRST_ID, LIMIT<int32_t>(-0x7FFFFFFF, ui->accz->value() * 100.0, 0x7FFFFFFF));
break;
default:
@@ -202,3 +377,566 @@ void TelemetrySimulator::generateTelemetryFrame()
else
onTimerEvent();
}
uint32_t TelemetrySimulator::FlvssEmulator::encodeCellPair(uint8_t cellNum, uint8_t firstCellNo, double cell1, double cell2)
{
uint16_t cell1Data = cell1 * 500.0;
uint16_t cell2Data = cell2 * 500.0;
uint32_t cellData = 0;
cellData = cell2Data & 0x0FFF;
cellData <<= 12;
cellData |= cell1Data & 0x0FFF;
cellData <<= 4;
cellData |= cellNum & 0x0F;
cellData <<= 4;
cellData |= firstCellNo & 0x0F;
return cellData;
}
void TelemetrySimulator::FlvssEmulator::encodeAllCells()
{
cellData1 = encodeCellPair(numCells, 0, cellFloats[0], cellFloats[1]);
if (numCells > 2) cellData2 = encodeCellPair(numCells, 2, cellFloats[2], cellFloats[3]); else cellData2 = 0;
if (numCells > 4) cellData3 = encodeCellPair(numCells, 4, cellFloats[4], cellFloats[5]); else cellData3 = 0;
}
void TelemetrySimulator::FlvssEmulator::splitIntoCells(double totalVolts)
{
numCells = qFloor((totalVolts / 3.7) + .5);
double avgVolts = totalVolts / numCells;
double remainder = (totalVolts - (avgVolts * numCells));
for (uint32_t i = 0; (i < numCells) && ( i < MAXCELLS); i++) {
cellFloats[i] = avgVolts;
}
for (uint32_t i = numCells; i < MAXCELLS; i++) {
cellFloats[i] = 0;
}
cellFloats[0] += remainder;
numCells = numCells > MAXCELLS ? MAXCELLS : numCells; // force into valid cell count in case of input out of range
}
uint32_t TelemetrySimulator::FlvssEmulator::setAllCells_GetNextPair(double cellValues[6])
{
numCells = 0;
for (uint32_t i = 0; i < MAXCELLS; i++) {
if ((i == 0) && (cellValues[0] > 4.2)) {
splitIntoCells(cellValues[0]);
break;
}
if (cellValues[i] > 0) {
cellFloats[i] = cellValues[i];
numCells++;
}
else {
// zero marks the last cell
for (uint32_t x = i; x < MAXCELLS; x++) {
cellFloats[x] = 0;
}
break;
}
}
// encode the double values into telemetry format
encodeAllCells();
// return the value for the current pair
uint32_t cellData = 0;
if (nextCellNum >= numCells) {
nextCellNum = 0;
}
switch (nextCellNum) {
case 0:
cellData = cellData1;
break;
case 2:
cellData = cellData2;
break;
case 4:
cellData = cellData3;
break;
}
nextCellNum += 2;
return cellData;
}
TelemetrySimulator::GPSEmulator::GPSEmulator()
{
lat = 0;
lon = 0;
dt = QDateTime::currentDateTime();
sendLat = true;
sendDate = true;
}
uint32_t TelemetrySimulator::GPSEmulator::encodeLatLon(double latLon, bool isLat)
{
uint32_t data = (uint32_t)((latLon < 0 ? -latLon : latLon) * 60 * 10000) & 0x3FFFFFFF;
if (isLat == false) {
data |= 0x80000000;
}
if (latLon < 0) {
data |= 0x40000000;
}
return data;
}
uint32_t TelemetrySimulator::GPSEmulator::encodeDateTime(uint8_t yearOrHour, uint8_t monthOrMinute, uint8_t dayOrSecond, bool isDate)
{
uint32_t data = yearOrHour;
data <<= 8;
data |= monthOrMinute;
data <<= 8;
data |= dayOrSecond;
data <<= 8;
if (isDate == true) {
data |= 0xFF;
}
return data;
}
uint32_t TelemetrySimulator::GPSEmulator::getNextPacketData(uint32_t packetType)
{
switch (packetType) {
case GPS_LONG_LATI_FIRST_ID:
sendLat = !sendLat;
return sendLat ? encodeLatLon(lat, TRUE) : encodeLatLon(lon, FALSE);
break;
case GPS_TIME_DATE_FIRST_ID:
sendDate = !sendDate;
return sendDate ? encodeDateTime(dt.date().year() - 2000, dt.date().month(), dt.date().day(), true) : encodeDateTime(dt.time().hour(), dt.time().minute(), dt.time().second(), false);
break;
case GPS_ALT_FIRST_ID:
return (uint32_t) (altitude * 100);
break;
case GPS_SPEED_FIRST_ID:
return speedKNTS * 1000;
break;
case GPS_COURS_FIRST_ID:
return course * 100;
break;
}
return 0;
}
void TelemetrySimulator::GPSEmulator::setGPSDateTime(QString dateTime)
{
dt = QDateTime::currentDateTime().toTimeSpec(Qt::UTC); // default to current systemtime
if (!dateTime.startsWith('*')) {
QString format("dd-MM-yyyy hh:mm:ss");
dt = QDateTime::fromString(dateTime, format);
}
}
void TelemetrySimulator::GPSEmulator::setGPSLatLon(QString latLon)
{
QStringList coords = latLon.split(",");
lat = 0.0;
lon = 0.0;
if (coords.length() > 1)
{
lat = coords[0].toDouble();
lon = coords[1].toDouble();
}
}
void TelemetrySimulator::GPSEmulator::setGPSCourse(double course)
{
this->course = course;
}
void TelemetrySimulator::GPSEmulator::setGPSSpeedKMH(double speedKMH)
{
this->speedKNTS = speedKMH * 0.539957;
}
void TelemetrySimulator::GPSEmulator::setGPSAltitude(double altitude)
{
this->altitude = altitude;
}
TelemetrySimulator::LogPlaybackController::LogPlaybackController(Ui::TelemetrySimulator * ui)
{
TelemetrySimulator::LogPlaybackController::ui = ui;
stepping = false;
// initialize the map - TODO: how should this be localized?
colToFuncMap.clear();
colToFuncMap.insert("RxBt(V)", RXBT_V);
colToFuncMap.insert("RSSI(dB)", RSSI);
colToFuncMap.insert("SWR", SWR);
colToFuncMap.insert("A1", A1);
colToFuncMap.insert("A1(V)", A1);
colToFuncMap.insert("A2", A2);
colToFuncMap.insert("A2(V)", A2);
colToFuncMap.insert("A3", A3);
colToFuncMap.insert("A3(V)", A3);
colToFuncMap.insert("A4", A4);
colToFuncMap.insert("A4(V)", A4);
colToFuncMap.insert("Tmp1(@C)", T1_DEGC);
colToFuncMap.insert("Tmp1(@F)", T1_DEGF);
colToFuncMap.insert("Tmp2(@C)", T2_DEGC);
colToFuncMap.insert("Tmp2(@F)", T2_DEGF);
colToFuncMap.insert("RPM(rpm)", RPM);
colToFuncMap.insert("Fuel(%)", FUEL);
colToFuncMap.insert("VSpd(m/s)", VSPD_MS);
colToFuncMap.insert("VSpd(f/s)", VSPD_FS);
colToFuncMap.insert("Alt(ft)", ALT_FEET);
colToFuncMap.insert("Alt(m)", ALT_METERS);
colToFuncMap.insert("VFAS(V)", FASV);
colToFuncMap.insert("Curr(A)", FASC);
colToFuncMap.insert("Cels(gRe)", CELS_GRE);
colToFuncMap.insert("ASpd(kmh)", ASPD_KMH);
colToFuncMap.insert("ASpd(mph)", ASPD_MPH);
colToFuncMap.insert("GAlt(ft)", GALT_FEET);
colToFuncMap.insert("GAlt(m)", GALT_METERS);
colToFuncMap.insert("GSpd(kts)", GSPD_KNTS);
colToFuncMap.insert("GSpd(kmh)", GSPD_KMH);
colToFuncMap.insert("GSpd(mph)", GSPD_MPH);
colToFuncMap.insert("Hdg(@)", GHDG_DEG);
colToFuncMap.insert("Date", GDATE);
colToFuncMap.insert("GPS", G_LATLON);
colToFuncMap.insert("AccX(g)", ACCX);
colToFuncMap.insert("AccY(g)", ACCY);
colToFuncMap.insert("AccZ(g)", ACCZ);
// ACCX Y and Z
}
QDateTime TelemetrySimulator::LogPlaybackController::parseTransmittterTimestamp(QString row)
{
QStringList rowParts = row.simplified().split(',');
if (rowParts.size() < 2) {
return QDateTime();
}
QString datePart = rowParts[0];
QString timePart = rowParts[1];
QDateTime result;
QString format("yyyy-MM-dd hh:mm:ss.zzz"); // assume this format
// hour can be 'missing'
if (timePart.count(":") < 2) {
timePart = "00:" + timePart;
}
if (datePart.contains("/")) { // happens when csv is edited by Excel
format = "M/d/yyyy hh:mm:ss.z";
}
return QDateTime::fromString(datePart + " " + timePart, format);
}
void TelemetrySimulator::LogPlaybackController::calcLogFrequency()
{
// examine up to 20 rows to determine log frequency in seconds
logFrequency = 25.5; // default value
QDateTime lastTime;
for (int i = 1; (i < 20) && (i < csvRecords.count()); i++)
{
QDateTime logTime = parseTransmittterTimestamp(csvRecords[i]);
// ugh - no timespan in this Qt version
double timeDiff = (logTime.toMSecsSinceEpoch() - lastTime.toMSecsSinceEpoch()) / 1000.0;
if ((timeDiff > 0) && (timeDiff < logFrequency)) {
logFrequency = timeDiff;
}
lastTime = logTime;
}
}
bool TelemetrySimulator::LogPlaybackController::isReady()
{
return csvRecords.count() > 1;
}
void TelemetrySimulator::LogPlaybackController::loadLogFile()
{
// reset the playback ui
ui->play->setEnabled(false);
ui->rewind->setEnabled(false);
ui->stepBack->setEnabled(false);
ui->stepForward->setEnabled(false);
ui->stop->setEnabled(false);
ui->positionIndicator->setEnabled(false);
ui->replayRate->setEnabled(false);
ui->positionLabel->setText("Row #\nTimestamp");
// clear existing data
csvRecords.clear();
QString logFileNameAndPath = QFileDialog::getOpenFileName(NULL, tr("Log File"), ".", tr("LOG Files (*.csv)"));
QFileInfo fileInfo(logFileNameAndPath);
QFile file(logFileNameAndPath);
if (!file.open(QIODevice::ReadOnly)) {
ui->logFileLabel->setText(tr("ERROR - invalid file"));
return;
}
while (!file.atEnd()) {
QByteArray line = file.readLine();
csvRecords.append(line.simplified());
}
if (csvRecords.count() > 1) {
columnNames.clear();
QStringList keys = csvRecords[0].split(',');
// override the first two column names
keys[0] = "LogDate";
keys[1] = "LogTime";
Q_FOREACH(QString key, keys) {
columnNames.append(key.simplified());
}
ui->play->setEnabled(true);
ui->rewind->setEnabled(true);
ui->stepBack->setEnabled(true);
ui->stepForward->setEnabled(true);
ui->stop->setEnabled(true);
ui->positionIndicator->setEnabled(true);
ui->replayRate->setEnabled(true);
supportedCols.clear();
recordIndex = 1;
calcLogFrequency();
}
ui->logFileLabel->setText(QFileInfo(logFileNameAndPath).fileName());
// iterate through all known mappings and add those that are used
QMapIterator<QString, CONVERT_TYPE> it(colToFuncMap);
while (it.hasNext()) {
it.next();
addColumnHash(it.key(), it.value());
}
rewind();
return;
}
void TelemetrySimulator::LogPlaybackController::addColumnHash(QString key, CONVERT_TYPE functionIndex)
{
DATA_TO_FUNC_XREF dfx;
if (columnNames.contains(key)) {
dfx.functionIndex = functionIndex;
dfx.dataIndex = columnNames.indexOf(key);
supportedCols.append(dfx);
}
}
void TelemetrySimulator::LogPlaybackController::play()
{
}
void TelemetrySimulator::LogPlaybackController::stop()
{
}
void TelemetrySimulator::LogPlaybackController::rewind()
{
stepping = true;
recordIndex = 1;
ui->stop->setChecked(true);
updatePositionLabel(-1);
setUiDataValues();
stepping = false;
}
void TelemetrySimulator::LogPlaybackController::stepForward(bool focusOnStop)
{
stepping = true;
if (recordIndex < (csvRecords.count() - 1)) {
recordIndex++;
if (focusOnStop) {
ui->stop->setChecked(true);
}
updatePositionLabel(-1);
setUiDataValues();
}
else {
rewind(); // always loop at the end
}
stepping = false;
}
void TelemetrySimulator::LogPlaybackController::stepBack()
{
stepping = true;
if (recordIndex > 1) {
recordIndex--;
ui->stop->setChecked(true);
updatePositionLabel(-1);
setUiDataValues();
}
stepping = false;
}
double TelemetrySimulator::LogPlaybackController::convertFeetToMeters(QString input)
{
double meters100 = input.toDouble() * 0.3048;
return qFloor(meters100 + .005);
}
QString TelemetrySimulator::LogPlaybackController::convertGPSDate(QString input)
{
QStringList dateTime = input.simplified().split(' ');
if (dateTime.size() < 2) {
return ""; // invalid format
}
QStringList dateParts = dateTime[0].split('-'); // input as yy-mm-dd
if (dateParts.size() < 3) {
return ""; // invalid format
}
// output is dd-MM-yyyy hh:mm:ss
QString localDateString = dateParts[2] + "-" + dateParts[1] + "-20" + dateParts[0] + " " + dateTime[1];
QString format("dd-MM-yyyy hh:mm:ss");
QDateTime utcDate = QDateTime::fromString(localDateString, format).toTimeSpec(Qt::UTC);
return utcDate.toString(format);
}
double TelemetrySimulator::LogPlaybackController::convertDegMin(QString input)
{
double fInput = input.mid(0, input.length() - 1).toDouble();
double degrees = qFloor(fInput / 100.0);
double minutes = fInput - (degrees * 100);
int32_t sign = ((input.endsWith('E')) || (input.endsWith('N'))) ? 1 : -1;
return (degrees + (minutes / 60)) * sign;
}
QString TelemetrySimulator::LogPlaybackController::convertGPS(QString input)
{
// input format is DDmm.mmmmH DDDmm.mmmmH (longitude latitude - degrees (2 places) minutes (2 places) decimal minutes (4 places))
QStringList lonLat = input.simplified().split(' ');
if (lonLat.count() < 2) {
return ""; // invalid format
}
double lon = convertDegMin(lonLat[0]);
double lat = convertDegMin(lonLat[1]);
return QString::number(lat) + ", " + QString::number(lon);
}
void TelemetrySimulator::LogPlaybackController::updatePositionLabel(int32_t percentage)
{
if ((percentage > 0) && (!stepping)) {
recordIndex = qFloor((double)csvRecords.count() / 100.0 * percentage);
if (recordIndex == 0) {
recordIndex = 1; // record 0 is column labels
}
}
// format the transmitter date info
QDateTime transmitterTimestamp = parseTransmittterTimestamp(csvRecords[recordIndex]);
QString format("yyyy-MM-dd hh:mm:ss.z");
ui->positionLabel->setText("Row " + QString::number(recordIndex) + " of " + QString::number(csvRecords.count() - 1)
+ "\n" + transmitterTimestamp.toString(format));
if (percentage < 0) { // did we step past a threshold?
uint32_t posPercent = (recordIndex / (double)(csvRecords.count() - 1)) * 100;
ui->positionIndicator->setValue(posPercent);
}
}
double TelemetrySimulator::LogPlaybackController::convertFahrenheitToCelsius(QString input)
{
return (input.toDouble() - 32.0) * 0.5556;
}
void TelemetrySimulator::LogPlaybackController::setUiDataValues()
{
QStringList columnData = csvRecords[recordIndex].split(',');
Q_FOREACH(DATA_TO_FUNC_XREF info, supportedCols) {
if (info.dataIndex < columnData.size()) {
switch (info.functionIndex) {
case RXBT_V:
ui->rxbt->setValue(columnData[info.dataIndex].toDouble());
break;
case RSSI:
ui->Rssi->setValue(columnData[info.dataIndex].toDouble());
break;
case SWR:
ui->Swr->setValue(columnData[info.dataIndex].toDouble());
break;
case A1:
ui->A1->setValue(columnData[info.dataIndex].toDouble());
break;
case A2:
ui->A2->setValue(columnData[info.dataIndex].toDouble());
break;
case A3:
ui->A3->setValue(columnData[info.dataIndex].toDouble());
break;
case A4:
ui->A4->setValue(columnData[info.dataIndex].toDouble());
break;
case T1_DEGC:
ui->T1->setValue(columnData[info.dataIndex].toDouble());
break;
case T2_DEGC:
ui->T2->setValue(columnData[info.dataIndex].toDouble());
break;
case T1_DEGF:
ui->T1->setValue(convertFahrenheitToCelsius(columnData[info.dataIndex]));
break;
case T2_DEGF:
ui->T2->setValue(convertFahrenheitToCelsius(columnData[info.dataIndex]));
break;
case RPM:
ui->rpm->setValue(columnData[info.dataIndex].toDouble());
break;
case FUEL:
ui->fuel->setValue(columnData[info.dataIndex].toDouble());
break;
case VSPD_MS:
ui->vspeed->setValue(columnData[info.dataIndex].toDouble());
break;
case VSPD_FS:
ui->vspeed->setValue(columnData[info.dataIndex].toDouble() * 0.3048);
break;
case ALT_FEET:
ui->valt->setValue(convertFeetToMeters(columnData[info.dataIndex]));
break;
case ALT_METERS:
ui->valt->setValue(columnData[info.dataIndex].toDouble());
break;
case FASV:
ui->vfas->setValue(columnData[info.dataIndex].toDouble());
break;
case FASC:
ui->curr->setValue(columnData[info.dataIndex].toDouble());
break;
case CELS_GRE:
ui->cell1->setValue(columnData[info.dataIndex].toDouble());
break;
case ASPD_KMH:
ui->aspeed->setValue(columnData[info.dataIndex].toDouble());
break;
case ASPD_MPH:
ui->aspeed->setValue(columnData[info.dataIndex].toDouble() * 1.60934);
break;
case GALT_FEET:
ui->gps_alt->setValue(convertFeetToMeters(columnData[info.dataIndex]));
break;
case GALT_METERS:
ui->gps_alt->setValue(columnData[info.dataIndex].toDouble());
break;
case GSPD_KNTS:
ui->gps_speed->setValue(columnData[info.dataIndex].toDouble() * 1.852);
break;
case GSPD_KMH:
ui->gps_speed->setValue(columnData[info.dataIndex].toDouble());
break;
case GSPD_MPH:
ui->gps_speed->setValue(columnData[info.dataIndex].toDouble() * 1.60934);
break;
case GHDG_DEG:
ui->gps_course->setValue(columnData[info.dataIndex].toDouble());
break;
case GDATE:
ui->gps_time->setText(convertGPSDate(columnData[info.dataIndex]));
break;
case G_LATLON:
ui->gps_latlon->setText(convertGPS(columnData[info.dataIndex]));
break;
case ACCX:
ui->accx->setValue(columnData[info.dataIndex].toDouble());
break;
case ACCY:
ui->accy->setValue(columnData[info.dataIndex].toDouble());
break;
case ACCZ:
ui->accz->setValue(columnData[info.dataIndex].toDouble());
break;
}
}
else {
// file is corrupt - shut down with open logs, or log format changed mid-day
}
}
}
+137 -5
View File
@@ -1,13 +1,16 @@
#ifndef telemetrysimu_h
#define telemetrysimu_h
#include <QCloseEvent>
#include <QDialog>
#include <QTimer>
#include <QDateTime>
#include <QtCore/qmath.h>
#include <QFileDialog>
#include "simulatorinterface.h"
#define INSTANCE (ui->Instance->text().toInt(&ok,0) -1)
static double const SPEEDS[] = { 0.2, 0.4, 0.6, 0.8, 1, 2, 3, 4, 5 };
namespace Ui {
class TelemetrySimulator;
@@ -22,19 +25,148 @@ class TelemetrySimulator : public QDialog
explicit TelemetrySimulator(QWidget * parent, SimulatorInterface * simulator);
virtual ~TelemetrySimulator();
protected:
virtual void closeEvent(QCloseEvent *event);
virtual void showEvent(QShowEvent *event);
private:
class LogPlaybackController
{
public:
LogPlaybackController(Ui::TelemetrySimulator * ui);
bool isReady();
void loadLogFile();
void play();
void stop();
void rewind();
void stepForward(bool focusOnStop);
void stepBack();
void updatePositionLabel(int32_t percentage);
void setUiDataValues();
double logFrequency; // in seconds
private:
enum CONVERT_TYPE {
RXBT_V,
RSSI,
SWR,
A1,
A2,
A3,
A4,
T1_DEGC,
T1_DEGF,
T2_DEGC,
T2_DEGF,
RPM,
FUEL,
VSPD_MS,
VSPD_FS,
ALT_FEET,
ALT_METERS,
FASV,
FASC,
CELS_GRE,
ASPD_KMH,
ASPD_MPH,
GALT_FEET,
GALT_METERS,
GSPD_KNTS,
GSPD_KMH,
GSPD_MPH,
GHDG_DEG,
GDATE,
G_LATLON,
ACCX,
ACCY,
ACCZ,
};
QMap<QString, CONVERT_TYPE> colToFuncMap; // contains all 'known' column headings and how they are to be processed
Ui::TelemetrySimulator * ui;
struct DATA_TO_FUNC_XREF {
CONVERT_TYPE functionIndex;
int32_t dataIndex;
};
QStringList csvRecords; // contents of the log file (one string per line);
QStringList columnNames;
QList<DATA_TO_FUNC_XREF> supportedCols;
int32_t recordIndex;
double convertFeetToMeters(QString input);
double convertFahrenheitToCelsius(QString input);
QString convertGPSDate(QString input);
QString convertGPS(QString input);
void addColumnHash(QString key, CONVERT_TYPE functionIndex);
double convertDegMin(QString input);
bool stepping;
QDateTime parseTransmittterTimestamp(QString row);
void calcLogFrequency();
int32_t replayRate;
};
private:
Ui::TelemetrySimulator * ui;
QTimer * timer;
QTimer * logTimer;
SimulatorInterface *simulator;
void generateTelemetryFrame();
TelemetrySimulator::LogPlaybackController *logPlayback;
private slots:
void onSimulateToggled(bool isChecked);
void onTimerEvent();
void onLogTimerEvent();
void onLoadLogFile();
void onPlay();
void onRewind();
void onStepForward();
void onStepBack();
void onStop();
void onPositionIndicatorChanged(int value);
void onReplayRateChanged(int value);
private: // private classes follow
class FlvssEmulator
{
public:
uint32_t setAllCells_GetNextPair(double cellValues[6]);
static const uint32_t MAXCELLS = 6;
private:
void encodeAllCells();
void splitIntoCells(double totalVolts);
static uint32_t encodeCellPair(uint8_t cellNum, uint8_t firstCellNo, double cell1, double cell2);
double cellFloats[6];
uint32_t nextCellNum;
uint32_t numCells;
uint32_t cellData1;
uint32_t cellData2;
uint32_t cellData3;
uint32_t cellDataTime;
double cell[MAXCELLS];
};
class GPSEmulator
{
public:
GPSEmulator();
uint32_t getNextPacketData(uint32_t packetType);
void setGPSDateTime(QString dateTime);
void setGPSLatLon(QString latLon);
void setGPSCourse(double course);
void setGPSSpeedKMH(double speed);
void setGPSAltitude(double altitude);
private:
QDateTime dt;
bool sendLat;
bool sendDate;
double lat;
double lon;
double course;
double speedKNTS;
double altitude; // in meters
uint32_t nextDataIndex;
uint32_t encodeLatLon(double latLon, bool isLat);
uint32_t encodeDateTime(uint8_t yearOrHour, uint8_t monthOrMinute, uint8_t dayOrSecond, bool isDate);
};
};
File diff suppressed because it is too large Load Diff