1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-19 14:25:11 +03:00

Telemetry refactoring - Fixes #1634

This commit is contained in:
bsongis 2014-11-08 12:06:42 +01:00
parent 7d8ca6931b
commit 88d9691d16
105 changed files with 5789 additions and 3449 deletions

View file

@ -97,6 +97,7 @@ add_custom_command(
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${PROJECT_SOURCE_DIR}/../..
${PROJECT_SOURCE_DIR}/shared
${SIMU_SRC_DIRECTORY}
${RADIO_SRC_DIRECTORY}
${RADIO_SRC_DIRECTORY}/fonts/std
@ -104,6 +105,7 @@ include_directories(
${XSD_INCLUDE_DIR}
)
add_subdirectory(shared)
add_subdirectory(modeledit)
add_subdirectory(generaledit)
add_subdirectory(simulation)
@ -167,8 +169,6 @@ set(companion_SRCS
qcustomplot.cpp
wizarddata.cpp
wizarddialog.cpp
foldersync.cpp
hexspinbox.cpp
)
set(companion_MOC_HDRS
@ -191,10 +191,8 @@ set(companion_MOC_HDRS
mainwindow.h
radionotfound.h
qcustomplot.h
qautocombobox.h
helpers.h
wizarddialog.h
hexspinbox.h
)
set(companion_UIS
@ -284,7 +282,7 @@ ELSE( )
ADD_EXECUTABLE( ${PROJECT_NAME} WIN32 ${companion_SRCS} ${companion_QM} )
ENDIF( )
TARGET_LINK_LIBRARIES( ${PROJECT_NAME} generaledit modeledit simulation common ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} ${XERCESC_LIBRARY} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${PHONON_LIBS} )
TARGET_LINK_LIBRARIES( ${PROJECT_NAME} generaledit modeledit simulation common shared ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} ${XERCESC_LIBRARY} ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${PHONON_LIBS} )
############# Standalone simu ###############

View file

@ -92,6 +92,74 @@ QString getGVarString(int16_t val, bool sign)
}
}
void SensorData::updateUnit()
{
if (type == TYPE_CALCULATED) {
if (formula == FORMULA_CONSUMPTION)
unit = UNIT_MAH;
}
}
QString SensorData::unitString() const
{
switch (unit) {
case UNIT_VOLTS:
return QObject::tr("V");
case UNIT_AMPS:
return QObject::tr("A");
case UNIT_MILLIAMPS:
return QObject::tr("mA");
case UNIT_KTS:
return QObject::tr("kts");
case UNIT_METERS_PER_SECOND:
return QObject::tr("m/s");
case UNIT_KMH:
return QObject::tr("km/h");
case UNIT_MPH:
return QObject::tr("mph");
case UNIT_METERS:
return QObject::tr("m");
case UNIT_FEET:
return QObject::tr("f");
case UNIT_CELSIUS:
return QObject::tr("°C");
case UNIT_FAHRENHEIT:
return QObject::tr("%F");
case UNIT_PERCENT:
return QObject::tr("%");
case UNIT_MAH:
return QObject::tr("mAh");
case UNIT_WATTS:
return QObject::tr("W");
case UNIT_DBM:
return QObject::tr("dB");
case UNIT_RPMS:
return QObject::tr("rpms");
case UNIT_G:
return QObject::tr("g");
case UNIT_DEGREE:
return QObject::tr("°");
case UNIT_HOURS:
return QObject::tr("hours");
case UNIT_MINUTES:
return QObject::tr("minutes");
case UNIT_SECONDS:
return QObject::tr("seconds");
case UNIT_CELLS:
return QObject::tr("V");
default:
return "";
}
}
bool RawSource::isTimeBased() const
{
if (IS_ARM(GetCurrentFirmware()->getBoard()))
return false;
else
return (type==SOURCE_TYPE_TELEMETRY && (index==TELEMETRY_SOURCE_TX_TIME || index==TELEMETRY_SOURCE_TIMER1 || index==TELEMETRY_SOURCE_TIMER2 || index==TELEMETRY_SOURCE_TIMER3));
}
RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSettings & settings, unsigned int flags) const
{
RawSourceRange result;
@ -106,6 +174,21 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting
switch (type) {
case SOURCE_TYPE_TELEMETRY:
if (IS_ARM(board)) {
div_t qr = div(index, 3);
const SensorData & sensor = model->sensorData[qr.quot];
if (sensor.prec == 2)
result.step = 0.01;
else if (sensor.prec == 1)
result.step = 0.1;
else
result.step = 1;
result.min = -30000 * result.step;
result.max = +30000 * result.step;
result.decimals = sensor.prec;
result.unit = sensor.unitString();
}
else {
if (singleprec) {
result.offset = -DBL_MAX;
}
@ -294,6 +377,7 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting
result.min = -result.max;
}
}
}
break;
case SOURCE_TYPE_GVAR:
@ -340,6 +424,10 @@ QString RawSource::toString(const ModelData * model)
QObject::tr("TrmR"), QObject::tr("TrmE"), QObject::tr("TrmT"), QObject::tr("TrmA")
};
static const QString special[] = {
QObject::tr("Batt"), QObject::tr("Time"), QObject::tr("Timer1"), QObject::tr("Timer2"), QObject::tr("Timer3"),
};
static const QString telemetry[] = {
QObject::tr("Batt"), QObject::tr("Time"), QObject::tr("Timer1"), QObject::tr("Timer2"), QObject::tr("Timer3"),
QObject::tr("SWR"), QObject::tr("RSSI Tx"), QObject::tr("RSSI Rx"),
@ -365,6 +453,7 @@ QString RawSource::toString(const ModelData * model)
if (index<0) {
return QObject::tr("----");
}
switch (type) {
case SOURCE_TYPE_VIRTUAL_INPUT:
{
@ -394,8 +483,18 @@ QString RawSource::toString(const ModelData * model)
return QObject::tr("TR%1").arg(index+1);
case SOURCE_TYPE_CH:
return QObject::tr("CH%1").arg(index+1);
case SOURCE_TYPE_SPECIAL:
return CHECK_IN_ARRAY(special, index);
case SOURCE_TYPE_TELEMETRY:
if (IS_ARM(GetEepromInterface()->getBoard())) {
div_t qr = div(index, 3);
QString result = QString(model ? model->sensorData[qr.quot].label : QString("[T%1]").arg(qr.quot+1));
if (qr.rem) result += qr.rem == 1 ? "-" : "+";
return result;
}
else {
return CHECK_IN_ARRAY(telemetry, index);
}
case SOURCE_TYPE_GVAR:
return QObject::tr("GV%1").arg(index+1);
default:
@ -1168,6 +1267,8 @@ void ModelData::clear()
timers[i].clear();
swashRingData.clear();
frsky.clear();
for (int i=0; i<C9X_MAX_SENSORS; i++)
sensorData[i].clear();
}
bool ModelData::isempty()

View file

@ -301,6 +301,7 @@ enum RawSourceType {
SOURCE_TYPE_PPM,
SOURCE_TYPE_CH,
SOURCE_TYPE_GVAR,
SOURCE_TYPE_SPECIAL,
SOURCE_TYPE_TELEMETRY,
MAX_SOURCE_TYPE
};
@ -373,9 +374,7 @@ class RawSource {
return (this->type != other.type) || (this->index != other.index);
}
bool isTimeBased() const {
return (type==SOURCE_TYPE_TELEMETRY && (index==TELEMETRY_SOURCE_TX_TIME || index==TELEMETRY_SOURCE_TIMER1 || index==TELEMETRY_SOURCE_TIMER2 || index==TELEMETRY_SOURCE_TIMER3));
}
bool isTimeBased() const;
RawSourceType type;
int index;
@ -788,9 +787,8 @@ class FrSkyData {
unsigned int usrProto;
int blades;
unsigned int voltsSource;
bool altitudeDisplayed;
unsigned int altitudeSource;
unsigned int currentSource;
unsigned int FrSkyGpsAlt;
FrSkyScreenData screens[4];
FrSkyRSSIAlarm rssiAlarms[2];
unsigned int varioSource;
@ -873,6 +871,103 @@ class ScriptData {
void clear() { memset(this, 0, sizeof(ScriptData)); }
};
#define C9X_MAX_SENSORS 32
class SensorData {
public:
enum
{
TYPE_CUSTOM,
TYPE_CALCULATED
};
enum
{
FORMULA_ADD,
FORMULA_AVERAGE,
FORMULA_MIN,
FORMULA_MAX,
FORMULA_MULTIPLY,
FORMULA_CELL,
FORMULA_CONSUMPTION,
FORMULA_DIST
};
enum {
UNIT_RAW,
UNIT_VOLTS,
UNIT_AMPS,
UNIT_MILLIAMPS,
UNIT_KTS,
UNIT_METERS_PER_SECOND,
UNIT_KMH,
UNIT_MPH,
UNIT_METERS,
UNIT_FEET,
UNIT_CELSIUS,
UNIT_FAHRENHEIT,
UNIT_PERCENT,
UNIT_MAH,
UNIT_WATTS,
UNIT_DBM,
UNIT_RPMS,
UNIT_G,
UNIT_DEGREE,
UNIT_HOURS,
UNIT_MINUTES,
UNIT_SECONDS,
// FrSky format used for these fields, could be another format in the future
UNIT_CELLS,
UNIT_DATETIME,
UNIT_GPS,
UNIT_GPS_LONGITUDE,
UNIT_GPS_LATITUDE,
UNIT_GPS_LONGITUDE_EW,
UNIT_GPS_LATITUDE_NS,
UNIT_DATETIME_YEAR,
UNIT_DATETIME_DAY_MONTH,
UNIT_DATETIME_HOUR_MIN,
UNIT_DATETIME_SEC
};
SensorData() { clear(); }
unsigned int type; // custom / formula
unsigned int id;
unsigned int instance;
unsigned int persistentValue;
unsigned int formula;
char label[4+1];
unsigned int unit;
unsigned int prec;
unsigned int inputFlags;
bool logs;
bool persistent;
// for custom sensors
unsigned int ratio;
unsigned int offset;
// for consumption
unsigned int amps;
// for cell
unsigned int source;
unsigned int index;
// for calculations
unsigned int sources[4];
// for GPS dist
unsigned int gps;
unsigned int alt;
bool isAvailable() const { return type==TYPE_CALCULATED || id!=0 || instance!=0; }
void updateUnit();
QString unitString() const;
void clear() { memset(this, 0, sizeof(SensorData)); }
};
class ModelData {
public:
ModelData();
@ -930,6 +1025,8 @@ class ModelData {
ScriptData scriptData[C9X_MAX_SCRIPTS];
SensorData sensorData[C9X_MAX_SENSORS];
void clear();
bool isempty();
void setDefaultInputs(const GeneralSettings & settings);
@ -1143,7 +1240,6 @@ enum Capability {
TelemetryCustomScreensFieldsPerLine,
TelemetryTimeshift,
TelemetryMaxMultiplier,
HasAltitudeSel,
HasVario,
HasVarioSink,
HasFailsafe,

View file

@ -466,7 +466,6 @@ t_Er9xModelData::operator ModelData ()
c9x.frsky = frsky;
c9x.frsky.usrProto=FrSkyUsrProto;
c9x.frsky.FrSkyGpsAlt=FrSkyGpsAlt;
return c9x;
}

View file

@ -594,7 +594,6 @@ t_Ersky9xModelData_v10::operator ModelData ()
c9x.frsky = frsky;
c9x.frsky.usrProto=FrSkyUsrProto;
c9x.frsky.FrSkyGpsAlt=FrSkyGpsAlt;
return c9x;
}
@ -705,23 +704,10 @@ t_Ersky9xModelData_v11::operator ModelData ()
for (int i=0; i<ERSKY9X_NUM_CSW_V11; i++)
c9x.logicalSw[i] = logicalSw[i];
// for (int i=0; i<ERSKY9X_NUM_CHNOUT_V11; i++)
// c9x.safetySw[i] = safetySw[i];
c9x.frsky = frsky;
c9x.frsky.usrProto=FrSkyUsrProto;
c9x.frsky.FrSkyGpsAlt=FrSkyGpsAlt;
// for (int i=0; i<8; i++) {
// c9x.frskyalarms[i].frskyAlarmLimit=frskyAlarms.alarmData[i].frskyAlarmLimit;
// c9x.frskyalarms[i].frskyAlarmSound=frskyAlarms.alarmData[i].frskyAlarmSound;
// c9x.frskyalarms[i].frskyAlarmType=frskyAlarms.alarmData[i].frskyAlarmType;
// }
// for (int i=0; i<8; i++) {
// c9x.customdisplay[i]=customDisplayIndex[i];
// }
for (int i=0; i<5;i++) {
c9x.flightModeData[0].gvars[i]=gvars[i].gvar;
// c9x.gvsource[i]=gvars[i].gvsource;
}
return c9x;
}

View file

@ -104,6 +104,7 @@ namespace Open9xSky9x {
#include "radio/src/templates.cpp"
#include "radio/src/translations.cpp"
#include "radio/src/fonts.cpp"
#include "radio/src/telemetry/telemetry.cpp"
#include "radio/src/telemetry/frsky.cpp"
#include "radio/src/telemetry/frsky_sport.cpp"
#include "radio/src/telemetry/frsky_d.cpp"

View file

@ -118,6 +118,7 @@ inline int geteepromsize() {
#define SDCARD
#include "radio/src/translations.cpp"
#include "radio/src/fonts.cpp"
#include "radio/src/telemetry/telemetry.cpp"
#include "radio/src/telemetry/frsky.cpp"
#include "radio/src/telemetry/frsky_sport.cpp"
#include "radio/src/telemetry/frsky_d.cpp"

View file

@ -24,6 +24,7 @@
#define MAX_CUSTOM_FUNCTIONS(board, version) (IS_ARM(board) ? (version >= 216 ? 64 : 32) : (IS_DBLEEPROM(board, version) ? 24 : 16))
#define MAX_CURVES(board, version) (IS_ARM(board) ? ((IS_TARANIS(board) && version >= 216) ? 32 : 16) : 8)
#define MAX_GVARS(board, version) ((IS_ARM(board) && version >= 216) ? 9 : 5)
#define MAX_SENSORS(board, version) (IS_TARANIS(board) ? 32 : 16)
#define NUM_PPM_INPUTS(board, version) ((IS_ARM(board) && version >= 216) ? 16 : 8)
#define IS_AFTER_RELEASE_21_MARCH_2013(board, version) (version >= 214 || (!IS_ARM(board) && version >= 213))
@ -268,6 +269,19 @@ class SourcesConversionTable: public ConversionTable {
addConversion(RawSource(SOURCE_TYPE_CH, i), val++);
if (!(flags & FLAG_NOTELEMETRY)) {
if (IS_ARM(board) && version >= 217) {
for (int i=0; i<MAX_GVARS(board, version); i++)
addConversion(RawSource(SOURCE_TYPE_GVAR, i), val++);
addConversion(RawSource(SOURCE_TYPE_SPECIAL, 0), val++); // BATT
addConversion(RawSource(SOURCE_TYPE_SPECIAL, 1), val++); // TIME
val += 5;
addConversion(RawSource(SOURCE_TYPE_SPECIAL, 2), val++); // Timer1
addConversion(RawSource(SOURCE_TYPE_SPECIAL, 3), val++); // Timer2
addConversion(RawSource(SOURCE_TYPE_SPECIAL, 4), val++); // Timer3
for (int i=0; i<C9X_MAX_SENSORS*3; ++i)
addConversion(RawSource(SOURCE_TYPE_TELEMETRY, i), val++);
}
else {
if (afterrelease21March2013) {
if ((board != BOARD_STOCK && (board!=BOARD_M128 || version<215)) || (variant & GVARS_VARIANT)) {
for (int i=0; i<MAX_GVARS(board, version); i++)
@ -298,6 +312,7 @@ class SourcesConversionTable: public ConversionTable {
}
}
}
}
protected:
@ -874,14 +889,14 @@ class MixField: public TransformedField {
internalField.Append(new UnsignedField<1>((unsigned int &)mix.carryTrim));
internalField.Append(new UnsignedField<4>(mix.mixWarn));
internalField.Append(new SignedField<16>(_weight));
internalField.Append(new SourceField<10>(mix.srcRaw, board, version, FLAG_NOTELEMETRY));
internalField.Append(new SignedField<14>(_offset));
internalField.Append(new SwitchField<8>(mix.swtch, board, version));
internalField.Append(new CurveReferenceField(mix.curve, board, version));
internalField.Append(new UnsignedField<8>(mix.delayUp));
internalField.Append(new UnsignedField<8>(mix.delayDown));
internalField.Append(new UnsignedField<8>(mix.speedUp));
internalField.Append(new UnsignedField<8>(mix.speedDown));
internalField.Append(new SourceField<8>(mix.srcRaw, board, version, FLAG_NOTELEMETRY));
internalField.Append(new SignedField<16>(_offset));
internalField.Append(new ZCharField<8>(mix.name));
}
else if (IS_ARM(board) && version >= 217) {
@ -1134,7 +1149,30 @@ class InputField: public TransformedField {
board(board),
version(version)
{
if (IS_TARANIS(board) && version >= 216) {
if (IS_TARANIS(board) && version >= 217) {
internalField.Append(new SourceField<10>(expo.srcRaw, board, version, 0));
internalField.Append(new UnsignedField<14>(expo.scale, "Scale"));
internalField.Append(new UnsignedField<8>(expo.chn, "Channel"));
internalField.Append(new SwitchField<8>(expo.swtch, board, version));
internalField.Append(new UnsignedField<16>(expo.phases));
internalField.Append(new SignedField<8>(_weight, "Weight"));
internalField.Append(new SignedField<6>(expo.carryTrim, "CarryTrim"));
internalField.Append(new UnsignedField<2>(expo.mode, "Mode"));
internalField.Append(new ZCharField<8>(expo.name));
internalField.Append(new SignedField<8>(_offset, "Offset"));
internalField.Append(new CurveReferenceField(expo.curve, board, version));
}
else if (IS_ARM(board) && version >= 216) {
internalField.Append(new UnsignedField<2>(expo.mode, "Mode"));
internalField.Append(new UnsignedField<3>(expo.chn, "Channel"));
internalField.Append(new BoolField<2>(_curveMode));
internalField.Append(new UnsignedField<9>(expo.phases, "Phases"));
internalField.Append(new SwitchField<8>(expo.swtch, board, version));
internalField.Append(new SignedField<8>(_weight, "Weight"));
internalField.Append(new ZCharField<6>(expo.name));
internalField.Append(new SignedField<8>(_curveParam));
}
else if (IS_TARANIS(board) && version >= 216) {
internalField.Append(new SourceField<8>(expo.srcRaw, board, version, 0));
internalField.Append(new UnsignedField<16>(expo.scale, "Scale"));
internalField.Append(new UnsignedField<8>(expo.chn, "Channel"));
@ -1305,11 +1343,11 @@ class LimitField: public StructField {
if (IS_TARANIS(board) && version >= 217) {
Append(new ConversionField< SignedField<11> >(limit.min, exportLimitValue<1000>, importLimitValue<1000>));
Append(new ConversionField< SignedField<11> >(limit.max, exportLimitValue<-1000>, importLimitValue<-1000>));
Append(new SignedField<10>(limit.ppmCenter));
Append(new ConversionField< SignedField<11> >(limit.offset, exportLimitValue<0>, importLimitValue<0>));
Append(new SignedField<11>(limit.ppmCenter));
Append(new BoolField<1>(limit.symetrical));
Append(new BoolField<1>(limit.revert));
Append(new SpareBitsField<2>());
Append(new SpareBitsField<3>());
Append(new SignedField<8>(limit.curve.value));
if (HAS_LARGE_LCD(board)) {
Append(new ZCharField<6>(limit.name));
@ -1591,22 +1629,44 @@ class LogicalSwitchField: public TransformedField {
v2(0),
v3(0)
{
if (IS_ARM(board) && version >= 216) {
if (IS_ARM(board) && version >= 217) {
internalField.Append(new ConversionField< UnsignedField<6> >(csw.func, &functionsConversionTable, "Function"));
internalField.Append(new SignedField<10>(v1));
internalField.Append(new SignedField<16>(v2));
internalField.Append(new SignedField<16>(v3));
}
else if (IS_ARM(board) && version >= 216) {
internalField.Append(new SignedField<8>(v1));
internalField.Append(new SignedField<16>(v2));
internalField.Append(new SignedField<16>(v3));
internalField.Append(new ConversionField< UnsignedField<8> >(csw.func, &functionsConversionTable, "Function"));
}
else if (IS_ARM(board) && version >= 216) {
internalField.Append(new SignedField<8>(v1));
internalField.Append(new SignedField<16>(v2));
internalField.Append(new SignedField<16>(v3));
internalField.Append(new ConversionField< UnsignedField<8> >(csw.func, &functionsConversionTable, "Function"));
}
else if (IS_ARM(board) && version >= 215) {
internalField.Append(new SignedField<16>(v1));
internalField.Append(new SignedField<16>(v2));
internalField.Append(new ConversionField< UnsignedField<8> >(csw.func, &functionsConversionTable, "Function"));
}
else if (IS_ARM(board)) {
internalField.Append(new SignedField<8>(v1));
internalField.Append(new SignedField<8>(v2));
internalField.Append(new ConversionField< UnsignedField<8> >(csw.func, &functionsConversionTable, "Function"));
}
else {
internalField.Append(new SignedField<8>(v1));
internalField.Append(new SignedField<8>(v2));
if (version >= 213)
internalField.Append(new ConversionField< UnsignedField<4> >(csw.func, &functionsConversionTable, "Function"));
else
internalField.Append(new ConversionField< UnsignedField<8> >(csw.func, &functionsConversionTable, "Function"));
}
if (IS_ARM(board)) {
internalField.Append(new ConversionField< UnsignedField<8> >(csw.func, &functionsConversionTable, "Function"));
int scale = (version >= 216 ? 0 : 5);
internalField.Append(new ConversionField< UnsignedField<8> >(csw.delay, 0, scale));
internalField.Append(new ConversionField< UnsignedField<8> >(csw.duration, 0, scale));
@ -1616,12 +1676,8 @@ class LogicalSwitchField: public TransformedField {
}
else {
if (version >= 213) {
internalField.Append(new ConversionField< UnsignedField<4> >(csw.func, &functionsConversionTable, "Function"));
internalField.Append(new ConversionField< UnsignedField<4> >((unsigned int &)csw.andsw, andswitchesConversionTable, "AND switch"));
}
else {
internalField.Append(new ConversionField< UnsignedField<8> >(csw.func, &functionsConversionTable, "Function"));
}
}
}
@ -2286,28 +2342,48 @@ class FrskyScreenField: public DataField {
version(version)
{
for (int i=0; i<4; i++) {
if (IS_ARM(board) && version >= 217) {
if (IS_TARANIS(board))
bars.Append(new TelemetrySourceField<16>(screen.body.bars[i].source, board, version));
else
bars.Append(new TelemetrySourceField<8>(screen.body.bars[i].source, board, version));
bars.Append(new UnsignedField<16>(screen.body.bars[i].barMin));
bars.Append(new UnsignedField<16>(screen.body.bars[i].barMax));
}
else {
bars.Append(new TelemetrySourceField<8>(screen.body.bars[i].source, board, version));
bars.Append(new UnsignedField<8>(screen.body.bars[i].barMin));
bars.Append(new UnsignedField<8>(screen.body.bars[i].barMax));
}
}
int columns = (IS_TARANIS(board) ? 3 : 2);
for (int i=0; i<4; i++) {
for (int j=0; j<columns; j++) {
if (IS_TARANIS(board) && version >= 217)
numbers.Append(new TelemetrySourceField<16>(screen.body.lines[i].source[j], board, version));
else
numbers.Append(new TelemetrySourceField<8>(screen.body.lines[i].source[j], board, version));
}
}
if (!IS_TARANIS(board)) {
for (int i=0; i<4; i++) {
numbers.Append(new SpareBitsField<8>());
}
if (IS_ARM(board))
numbers.Append(new SpareBitsField<12*8>());
else
numbers.Append(new SpareBitsField<4*8>());
}
none.Append(new SpareBitsField<12*8>());
if (version >= 217) {
if (IS_TARANIS(board))
none.Append(new SpareBitsField<24*8>());
else
none.Append(new SpareBitsField<20*8>());
}
if (IS_TARANIS(board) && version >= 217) {
script.Append(new CharField<8>(screen.body.script.filename));
script.Append(new SpareBitsField<32>());
script.Append(new SpareBitsField<16*8>());
}
}
@ -2440,6 +2516,11 @@ class FrskyField: public StructField {
rssiConversionTable[1] = RSSIConversionTable(1);
if (IS_ARM(board)) {
if (version >= 217) {
Append(new UnsignedField<8>(frsky.voltsSource, "Volts Source"));
Append(new UnsignedField<8>(frsky.altitudeSource, "Altitude Source"));
}
else {
for (int i=0; i<((version >= 216) ? 4 : 2); i++) {
Append(new UnsignedField<8>(frsky.channels[i].ratio, "Ratio"));
Append(new SignedField<12>(frsky.channels[i].offset, "Offset"));
@ -2456,13 +2537,14 @@ class FrskyField: public StructField {
Append(new UnsignedField<8>(frsky.usrProto));
if (version >= 216) {
Append(new ConversionField< UnsignedField<7> >(frsky.voltsSource, &telemetryVoltsSourceConversionTable, "Volts Source"));
Append(new BoolField<1>(frsky.altitudeDisplayed));
Append(new SpareBitsField<1>());
}
else {
Append(new ConversionField< UnsignedField<8> >(frsky.voltsSource, &telemetryVoltsSourceConversionTable, "Volts Source"));
}
Append(new ConversionField< SignedField<8> >(frsky.blades, -2));
Append(new ConversionField< UnsignedField<8> >(frsky.currentSource, &telemetryCurrentSourceConversionTable, "Current Source"));
}
if (version >= 217) {
for (int i=0; i<4; i++) {
@ -2491,7 +2573,7 @@ class FrskyField: public StructField {
Append(new ConversionField< UnsignedField<2> >(frsky.rssiAlarms[i].level, &rssiConversionTable[i], "RSSI"));
Append(new ConversionField< SignedField<6> >(frsky.rssiAlarms[i].value, -45+i*3));
}
if (version >= 216) {
if (version == 216) {
Append(new BoolField<1>(frsky.mAhPersistent));
Append(new UnsignedField<15>(frsky.storedMah));
Append(new SignedField<8>(frsky.fasOffset));
@ -2555,6 +2637,80 @@ class MavlinkField: public StructField {
}
};
class SensorField: public TransformedField {
public:
SensorField(SensorData & sensor, BoardEnum board, unsigned int version):
TransformedField(internalField),
internalField("Sensor"),
sensor(sensor),
_param(0)
{
internalField.Append(new UnsignedField<16>(_id, "id/persistentValue"));
internalField.Append(new UnsignedField<8>(_instance, "instance/formula"));
internalField.Append(new ZCharField<4>(sensor.label));
internalField.Append(new UnsignedField<1>(sensor.type, "type"));
internalField.Append(new UnsignedField<5>(sensor.unit, "unit"));
internalField.Append(new UnsignedField<2>(sensor.prec, "prec"));
internalField.Append(new UnsignedField<2>(sensor.inputFlags, "inputFlags"));
internalField.Append(new BoolField<1>(sensor.logs));
internalField.Append(new BoolField<1>(sensor.persistent));
internalField.Append(new SpareBitsField<4>());
internalField.Append(new UnsignedField<32>(_param, "param"));
}
virtual void beforeExport()
{
if (sensor.type == SensorData::TYPE_CUSTOM) {
_id = sensor.id;
_instance = sensor.instance;
_param = (sensor.ratio) + (sensor.offset << 16);
}
else {
_id = sensor.persistentValue;
_instance = sensor.formula;
if (sensor.formula == SensorData::FORMULA_CELL)
_param = (sensor.source) + (sensor.index << 8);
else if (sensor.formula == SensorData::FORMULA_ADD || sensor.formula == SensorData::FORMULA_MULTIPLY || sensor.formula == SensorData::FORMULA_MIN || sensor.formula == SensorData::FORMULA_MAX)
_param = (sensor.sources[0]) + (sensor.sources[1] << 8) + (sensor.sources[2] << 16) + (sensor.sources[3] << 24);
else if (sensor.formula == SensorData::FORMULA_DIST)
_param = (sensor.gps) + (sensor.alt << 8);
else if (sensor.formula == SensorData::FORMULA_CONSUMPTION)
_param = (sensor.amps);
}
}
virtual void afterImport()
{
if (sensor.type == SensorData::TYPE_CUSTOM) {
sensor.id = _id;
sensor.instance = _instance;
}
else {
sensor.persistentValue = _id;
sensor.formula = _instance;
if (sensor.formula == SensorData::FORMULA_CELL)
(sensor.source = _sources[0], sensor.index = _sources[1]);
else if (sensor.formula == SensorData::FORMULA_ADD || sensor.formula == SensorData::FORMULA_MULTIPLY || sensor.formula == SensorData::FORMULA_MIN || sensor.formula == SensorData::FORMULA_MAX)
for (int i=0; i<4; ++i)
sensor.sources[i] = _sources[i];
else if (sensor.formula == SensorData::FORMULA_DIST)
(sensor.gps = _sources[0], sensor.alt = _sources[1]);
else if (sensor.formula == SensorData::FORMULA_CONSUMPTION)
sensor.amps = _sources[0];
}
}
protected:
StructField internalField;
SensorData & sensor;
unsigned int _id;
unsigned int _instance;
union {
unsigned int _param;
uint8_t _sources[4];
};
};
int exportPpmDelay(int delay) { return (delay - 300) / 50; }
int importPpmDelay(int delay) { return 300 + 50 * delay; }
@ -2587,12 +2743,12 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, BoardEnum board, unsigne
for (int i=0; i<MAX_TIMERS(board, version); i++) {
internalField.Append(new SwitchField<8>(modelData.timers[i].mode, board, version, true));
if (IS_ARM(board) && version >= 217) {
internalField.Append(new UnsignedField<24>(modelData.timers[i].val));
internalField.Append(new SignedField<24>(modelData.timers[i].pvalue));
internalField.Append(new UnsignedField<2>(modelData.timers[i].countdownBeep));
internalField.Append(new BoolField<1>(modelData.timers[i].minuteBeep));
internalField.Append(new UnsignedField<2>(modelData.timers[i].persistent));
internalField.Append(new SpareBitsField<3>());
internalField.Append(new UnsignedField<24>(modelData.timers[i].val));
internalField.Append(new SignedField<24>(modelData.timers[i].pvalue));
if (IS_TARANIS(board))
internalField.Append(new ZCharField<8>(modelData.timers[i].name));
else
@ -2637,7 +2793,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, BoardEnum board, unsigne
if (IS_TARANIS(board) || (IS_ARM(board) && version >= 216)) {
internalField.Append(new BoolField<1>(modelData.noGlobalFunctions));
internalField.Append(new SpareBitsField<4>());
internalField.Append(new SpareBitsField<3>());
}
else {
internalField.Append(new ConversionField< SignedField<4> >(modelData.moduleData[0].channelsCount, &channelsConversionTable, "Channels number", ::QObject::tr("OpenTX doesn't allow this number of channels")));
@ -2802,9 +2958,15 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, BoardEnum board, unsigne
}
}
if (IS_ARM(board) && version >= 216) {
if (IS_ARM(board) && version == 216) {
internalField.Append(new SpareBitsField<16>());
}
if (IS_ARM(board) && version >= 217) {
for (int i=0; i<MAX_SENSORS(board, version); ++i) {
internalField.Append(new SensorField(modelData.sensorData[i], board, version));
}
}
}
void OpenTxModelData::beforeExport()

View file

@ -556,7 +556,7 @@ int OpenTxFirmware::getCapability(const Capability capability)
case GvarsFlightModes:
return ((IS_ARM(board) || board==BOARD_GRUVIN9X) ? 1 : 0);
case Mixes:
return (IS_ARM(board) ? 64 : 32);
return (IS_TARANIS(board) ? 64 : (IS_ARM(board) ? 60 : 32));
case OffsetWeight:
return (IS_ARM(board) ? 500 : 245);
case Timers:
@ -575,8 +575,10 @@ int OpenTxFirmware::getCapability(const Capability capability)
case SwitchesPositions:
return (IS_TARANIS(board) ? 22 : 9);
case CustomFunctions:
if (IS_ARM(board))
if (IS_TARANIS(board))
return 64;
else if (IS_ARM(board))
return 60;
else if (board==BOARD_GRUVIN9X||board==BOARD_M128)
return 24;
else

View file

@ -9,6 +9,7 @@
#include "trainer.h"
#include "calibration.h"
#include "../modeledit/customfunctions.h"
#include "verticalscrollarea.h"
GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, FirmwareInterface * firmware) :
QDialog(parent),

View file

@ -3,7 +3,7 @@
#include <QDialog>
#include "eeprominterface.h"
#include "helpers.h"
#include "genericpanel.h"
namespace Ui {
class GeneralEdit;

View file

@ -616,7 +616,25 @@ void populateSourceCB(QComboBox *b, const RawSource & source, const ModelData *
}
}
if (flags & POPULATE_TELEMETRYEXT) {
if (IS_ARM(GetCurrentFirmware()->getBoard())) {
if ((flags & POPULATE_TELEMETRY) || (flags & POPULATE_TELEMETRYEXT)) {
for (int i=0; i<5; ++i) {
item = RawSource(SOURCE_TYPE_SPECIAL, i);
b->addItem(item.toString(model), item.toValue());
if (item == source) b->setCurrentIndex(b->count()-1);
}
for (int i=0; i<C9X_MAX_SENSORS; ++i) {
if (model->sensorData[i].isAvailable()) {
for (int j=0; j<3; ++j) {
item = RawSource(SOURCE_TYPE_TELEMETRY, 3*i+j);
b->addItem(item.toString(model), item.toValue());
if (item == source) b->setCurrentIndex(b->count()-1);
}
}
}
}
}
else if (flags & POPULATE_TELEMETRYEXT) {
for (int i=0; i<TELEMETRY_SOURCE_ACC; i++) {
if (i==TELEMETRY_SOURCE_RSSI_TX && IS_TARANIS(board))
continue;
@ -1001,119 +1019,3 @@ QString generateProcessUniqueTempFileName(const QString & fileName)
sanitizedFileName.remove('/');
return QDir::tempPath() + QString("/%1-").arg(QCoreApplication::applicationPid()) + sanitizedFileName;
}
GenericPanel::GenericPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, FirmwareInterface * firmware):
QWidget(parent),
model(model),
generalSettings(generalSettings),
firmware(firmware),
lock(false)
{
}
GenericPanel::~GenericPanel()
{
}
void GenericPanel::update()
{
}
void GenericPanel::addLabel(QGridLayout * gridLayout, QString text, int col, bool minimize)
{
QLabel *label = new QLabel(this);
label->setFrameShape(QFrame::Panel);
label->setFrameShadow(QFrame::Raised);
label->setMidLineWidth(0);
label->setAlignment(Qt::AlignCenter);
label->setMargin(5);
label->setText(text);
if (!minimize)
label->setMinimumWidth(100);
gridLayout->addWidget(label, 0, col, 1, 1);
}
void GenericPanel::addEmptyLabel(QGridLayout * gridLayout, int col)
{
QLabel *label = new QLabel(this);
label->setText("");
gridLayout->addWidget(label, 0, col, 1, 1);
}
void GenericPanel::addHSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
gridLayout->addItem(spacer, row, col);
}
void GenericPanel::addVSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
gridLayout->addItem(spacer, row, col);
}
void GenericPanel::addDoubleSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding );
gridLayout->addItem(spacer, row, col);
}
bool GenericPanel::eventFilter(QObject *object, QEvent * event)
{
QWidget * widget = qobject_cast<QWidget*>(object);
if (widget) {
if (event->type() == QEvent::Wheel) {
if (widget->focusPolicy() == Qt::WheelFocus) {
event->accept();
return false;
}
else {
event->ignore();
return true;
}
}
else if (event->type() == QEvent::FocusIn) {
widget->setFocusPolicy(Qt::WheelFocus);
}
else if (event->type() == QEvent::FocusOut) {
widget->setFocusPolicy(Qt::StrongFocus);
}
}
return QWidget::eventFilter(object, event);
}
void GenericPanel::disableMouseScrolling()
{
Q_FOREACH(QComboBox * cb, findChildren<QComboBox*>()) {
cb->installEventFilter(this);
cb->setFocusPolicy(Qt::StrongFocus);
}
Q_FOREACH(QAbstractSpinBox * sb, findChildren<QAbstractSpinBox*>()) {
sb->installEventFilter(this);
sb->setFocusPolicy(Qt::StrongFocus);
}
Q_FOREACH(QSlider * slider, findChildren<QSlider*>()) {
slider->installEventFilter(this);
slider->setFocusPolicy(Qt::StrongFocus);
}
}
VerticalScrollArea::VerticalScrollArea(QWidget * parent, GenericPanel * panel):
QScrollArea(parent),
panel(panel),
parent(parent)
{
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setWidget(panel);
panel->installEventFilter(this);
}
bool VerticalScrollArea::eventFilter(QObject *o, QEvent *e)
{
if (o == panel && e->type() == QEvent::Resize) {
setMinimumWidth(panel->minimumSizeHint().width() + verticalScrollBar()->width());
}
return false;
}

View file

@ -153,47 +153,4 @@ int qunlink(const QString & fileName);
QString generateProcessUniqueTempFileName(const QString & fileName);
class GenericPanel : public QWidget
{
Q_OBJECT
friend class QUnsignedAutoComboBox;
public:
GenericPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, FirmwareInterface * firmware);
virtual ~GenericPanel();
signals:
void modified();
public slots:
virtual void update();
protected:
ModelData * model;
GeneralSettings & generalSettings;
FirmwareInterface * firmware;
bool lock;
void addLabel(QGridLayout * gridLayout, QString text, int col, bool mimimize=false);
void addEmptyLabel(QGridLayout * gridLayout, int col);
void addHSpring(QGridLayout *, int col, int row);
void addVSpring(QGridLayout *, int col, int row);
void addDoubleSpring(QGridLayout *, int col, int row);
virtual bool eventFilter(QObject *obj, QEvent *event);
void disableMouseScrolling();
};
class VerticalScrollArea : public QScrollArea
{
public:
VerticalScrollArea(QWidget * parent, GenericPanel * panel);
protected:
virtual bool eventFilter(QObject *o, QEvent *e);
private:
GenericPanel * panel;
QWidget * parent;
};
#endif // HELPERS_H

View file

@ -41,6 +41,7 @@ set(modeledit_UIS
flightmode.ui
telemetry_analog.ui
telemetry_customscreen.ui
telemetry_sensor.ui
)
foreach(name ${modeledit_NAMES})

View file

@ -194,11 +194,9 @@ void Channels::symlimitsEdited()
void Channels::nameEdited()
{
if (!lock) {
lock = true;
QLineEdit *le = qobject_cast<QLineEdit*>(sender());
int index = le->property("index").toInt();
strcpy(model->limitData[index].name, le->text().toAscii());
lock = false;
emit modified();
}
}

View file

@ -2,6 +2,7 @@
#define CURVES_H
#include "modeledit.h"
#include "eeprominterface.h"
#include <QSpinBox>
namespace Ui {

View file

@ -2,6 +2,7 @@
#define CUSTOMFUNCTIONS_H
#include "modeledit.h"
#include "eeprominterface.h"
#include <QLabel>
#include <QCheckBox>
#include <QComboBox>

View file

@ -2,6 +2,7 @@
#define FLIGHTMODES_H
#include "modeledit.h"
#include "eeprominterface.h"
#include <QVector>
#include <QLabel>
#include <QTabWidget>

View file

@ -2,6 +2,7 @@
#define CUSTOMSWITCHES_H
#include "modeledit.h"
#include "eeprominterface.h"
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QTimeEdit>

View file

@ -1,4 +1,5 @@
#include "modeledit.h"
#include "../helpers.h"
#include "ui_modeledit.h"
#include "setup.h"
#include "heli.h"
@ -7,7 +8,7 @@
#include "mixes.h"
#include "channels.h"
#include "curves.h"
#include "../helpers.h"
#include "verticalscrollarea.h"
#include "logicalswitches.h"
#include "customfunctions.h"
#include "telemetry.h"

View file

@ -2,7 +2,9 @@
#define MODELEDIT_H
#include <QDialog>
#include "helpers.h"
#include "genericpanel.h"
class RadioData;
namespace Ui {
class ModelEdit;

View file

@ -34,14 +34,14 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
ui->persistentValue->hide();
}
ui->countdownBeep->setField(&timer.countdownBeep, this);
ui->countdownBeep->setField(timer.countdownBeep, this);
ui->countdownBeep->addItem(tr("Silent"), 0);
ui->countdownBeep->addItem(tr("Beeps"), 1);
if (IS_ARM(board) || IS_2560(board)) {
ui->countdownBeep->addItem(tr("Voice"), 2);
}
ui->persistent->setField(&timer.persistent, this);
ui->persistent->setField(timer.persistent, this);
ui->persistent->addItem(tr("Not persistent"), 0);
ui->persistent->addItem(tr("Persistent (flight)"), 1);
ui->persistent->addItem(tr("Persistent (manual reset)"), 2);

View file

@ -2,6 +2,7 @@
#define SETUP_H
#include "modeledit.h"
#include "eeprominterface.h"
#include <QVector>
#include <QCheckBox>
#include <QSlider>

View file

@ -9,7 +9,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>626</width>
<width>675</width>
<height>33</height>
</rect>
</property>
@ -57,7 +57,7 @@
</widget>
</item>
<item>
<widget class="QUnsignedAutoComboBox" name="countdownBeep"/>
<widget class="AutoComboBox" name="countdownBeep"/>
</item>
<item>
<widget class="QCheckBox" name="minuteBeep">
@ -67,7 +67,7 @@
</widget>
</item>
<item>
<widget class="QUnsignedAutoComboBox" name="persistent"/>
<widget class="AutoComboBox" name="persistent"/>
</item>
<item>
<widget class="QLabel" name="persistentValue">
@ -93,9 +93,9 @@
</widget>
<customwidgets>
<customwidget>
<class>QUnsignedAutoComboBox</class>
<class>AutoComboBox</class>
<extends>QComboBox</extends>
<header>qautocombobox.h</header>
<header>autocombobox.h</header>
</customwidget>
</customwidgets>
<resources/>

View file

@ -2,6 +2,7 @@
#include "ui_telemetry.h"
#include "ui_telemetry_analog.h"
#include "ui_telemetry_customscreen.h"
#include "ui_telemetry_sensor.h"
#include "helpers.h"
#include "appdata.h"
@ -469,6 +470,169 @@ void TelemetryCustomScreen::barMaxChanged(double value)
}
}
TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, ModelData & model, GeneralSettings & generalSettings, FirmwareInterface * firmware):
ModelPanel(parent, model, generalSettings, firmware),
ui(new Ui::TelemetrySensor),
sensor(sensor),
lock(false)
{
ui->setupUi(this);
ui->id->setField(sensor.id);
ui->instance->setField(sensor.instance);
ui->ratio->setField(sensor.ratio);
ui->offset->setField(sensor.offset);
ui->inputFlags->setField(sensor.inputFlags);
ui->logs->setField(sensor.logs);
ui->persistent->setField(sensor.persistent);
ui->gpsSensor->setField(sensor.gps);
ui->altSensor->setField(sensor.alt);
ui->ampsSensor->setField(sensor.amps);
ui->cellsSensor->setField(sensor.source);
ui->source1->setField(sensor.sources[0]);
ui->source2->setField(sensor.sources[1]);
ui->source3->setField(sensor.sources[2]);
ui->source4->setField(sensor.sources[3]);
update();
}
TelemetrySensorPanel::~TelemetrySensorPanel()
{
delete ui;
}
void TelemetrySensorPanel::update()
{
bool precDisplayed = false;
bool gpsFieldsDisplayed = false;
bool cellsFieldsDisplayed = false;
bool consFieldsDisplayed = false;
bool ratioFieldsDisplayed = false;
bool sources12FieldsDisplayed = false;
bool sources34FieldsDisplayed = false;
lock = true;
ui->name->setText(sensor.label);
ui->type->setCurrentIndex(sensor.type);
ui->unit->setCurrentIndex(sensor.unit);
ui->prec->setValue(sensor.prec);
if (sensor.type == SensorData::TYPE_CALCULATED) {
sensor.updateUnit();
ui->idLabel->hide();
ui->id->hide();
ui->instanceLabel->hide();
ui->instance->hide();
ui->formula->show();
ui->formula->setCurrentIndex(sensor.formula);
precDisplayed = (sensor.formula < SensorData::FORMULA_CELL);
gpsFieldsDisplayed = (sensor.formula == SensorData::FORMULA_DIST);
cellsFieldsDisplayed = (sensor.formula == SensorData::FORMULA_CELL);
consFieldsDisplayed = (sensor.formula == SensorData::FORMULA_CONSUMPTION);
sources12FieldsDisplayed = (sensor.formula <= SensorData::FORMULA_MULTIPLY);
sources34FieldsDisplayed = (sensor.formula < SensorData::FORMULA_MULTIPLY);
updateSourcesComboBox(ui->source1);
updateSourcesComboBox(ui->source2);
updateSourcesComboBox(ui->source3);
updateSourcesComboBox(ui->source4);
updateSourcesComboBox(ui->gpsSensor);
updateSourcesComboBox(ui->altSensor);
updateSourcesComboBox(ui->ampsSensor);
}
else {
ui->idLabel->show();
ui->id->show();
ui->instanceLabel->show();
ui->instance->show();
ui->formula->hide();
ratioFieldsDisplayed = (sensor.unit != SensorData::UNIT_GPS && sensor.unit != SensorData::UNIT_DATETIME);
ui->offset->setDecimals(sensor.prec);
precDisplayed = (sensor.unit != SensorData::UNIT_GPS && sensor.unit != SensorData::UNIT_DATETIME);
}
ui->ratioLabel->setVisible(ratioFieldsDisplayed);
ui->ratio->setVisible(ratioFieldsDisplayed);
ui->offsetLabel->setVisible(ratioFieldsDisplayed);
ui->offset->setVisible(ratioFieldsDisplayed);
ui->precLabel->setVisible(precDisplayed);
ui->prec->setVisible(precDisplayed);
ui->unit->setVisible(precDisplayed);
ui->gpsSensorLabel->setVisible(gpsFieldsDisplayed);
ui->gpsSensor->setVisible(gpsFieldsDisplayed);
ui->altSensorLabel->setVisible(gpsFieldsDisplayed);
ui->altSensor->setVisible(gpsFieldsDisplayed);
ui->ampsSensorLabel->setVisible(consFieldsDisplayed);
ui->ampsSensor->setVisible(consFieldsDisplayed);
ui->cellsSensorLabel->setVisible(cellsFieldsDisplayed);
ui->cellsSensor->setVisible(cellsFieldsDisplayed);
ui->cellsIndex->setVisible(cellsFieldsDisplayed);
ui->source1->setVisible(sources12FieldsDisplayed);
ui->source2->setVisible(sources12FieldsDisplayed);
ui->source3->setVisible(sources34FieldsDisplayed);
ui->source4->setVisible(sources34FieldsDisplayed);
lock = false;
}
void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model)
{
cb->clear();
cb->addItem("---", 0);
for (int i=0; i<C9X_MAX_SENSORS; ++i) {
if (model->sensorData[i].isAvailable())
cb->addItem(model->sensorData[i].label, i+1);
}
}
void TelemetrySensorPanel::updateSourcesComboBox(AutoComboBox * cb)
{
populateTelemetrySourcesComboBox(cb, model);
}
void TelemetrySensorPanel::on_name_editingFinished()
{
if (!lock) {
strcpy(sensor.label, ui->name->text().toAscii());
update();
emit modified();
}
}
void TelemetrySensorPanel::on_type_currentIndexChanged(int index)
{
if (!lock) {
sensor.type = index;
update();
emit modified();
}
}
void TelemetrySensorPanel::on_formula_currentIndexChanged(int index)
{
if (!lock) {
sensor.formula = index;
update();
emit modified();
}
}
void TelemetrySensorPanel::on_unit_currentIndexChanged(int index)
{
if (!lock) {
sensor.unit = index;
update();
emit modified();
}
}
void TelemetrySensorPanel::on_prec_editingFinished()
{
if (!lock) {
sensor.prec = ui->prec->value();
update();
emit modified();
}
}
/******************************************************/
TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, FirmwareInterface * firmware):
@ -494,26 +658,31 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
ui->telemetryProtocol->hide();
}
if (IS_ARM(firmware->getBoard())) {
ui->A1GB->hide();
ui->A2GB->hide();
for (int i=0; i<C9X_MAX_SENSORS; ++i) {
TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], model, generalSettings, firmware);
ui->sensorsLayout->addWidget(panel);
sensorPanels[i] = panel;
}
}
else {
ui->sensorsGB->hide();
analogs[0] = new TelemetryAnalog(this, model.frsky.channels[0], model, generalSettings, firmware);
ui->A1Layout->addWidget(analogs[0]);
connect(analogs[0], SIGNAL(modified()), this, SLOT(onAnalogModified()));
analogs[1] = new TelemetryAnalog(this, model.frsky.channels[1], model, generalSettings, firmware);
ui->A2Layout->addWidget(analogs[1]);
connect(analogs[1], SIGNAL(modified()), this, SLOT(onAnalogModified()));
}
if (IS_ARM(firmware->getBoard())) {
analogs[2] = new TelemetryAnalog(this, model.frsky.channels[2], model, generalSettings, firmware);
ui->A3Layout->addWidget(analogs[2]);
connect(analogs[2], SIGNAL(modified()), this, SLOT(onAnalogModified()));
analogs[3] = new TelemetryAnalog(this, model.frsky.channels[3], model, generalSettings, firmware);
ui->A4Layout->addWidget(analogs[3]);
connect(analogs[3], SIGNAL(modified()), this, SLOT(onAnalogModified()));
if (IS_TARANIS(firmware->getBoard())) {
ui->voltsSource->setField(model.frsky.voltsSource);
ui->altitudeSource->setField(model.frsky.altitudeSource);
}
else {
ui->A3GB->hide();
ui->A4GB->hide();
ui->topbarGB->hide();
}
for (int i=0; i<firmware->getCapability(TelemetryCustomScreens); i++) {
@ -522,11 +691,6 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin
telemetryCustomScreens[i] = tab;
}
if (IS_ARM(firmware->getBoard())) {
ui->bladesCount->setMinimum(1);
ui->bladesCount->setMaximum(128);
}
disableMouseScrolling();
setup();
@ -547,6 +711,15 @@ void TelemetryPanel::update()
ui->telemetryProtocol->setEnabled(false);
ui->telemetryProtocol->setCurrentIndex(0);
}
populateTelemetrySourcesComboBox(ui->voltsSource, model);
populateTelemetrySourcesComboBox(ui->altitudeSource, model);
}
if (IS_ARM(firmware->getBoard())) {
for (int i=0; i<C9X_MAX_SENSORS; ++i) {
sensorPanels[i]->update();
}
}
}
@ -569,19 +742,13 @@ void TelemetryPanel::setup()
ui->rssiAlarm2Label->setText(tr("Critical Alarm"));
}
if (!firmware->getCapability(HasAltitudeSel)) {
ui->AltitudeGPS_ChkB->hide();
}
else {
ui->AltitudeGPS_ChkB->setChecked(model->frsky.FrSkyGpsAlt);
}
if (IS_TARANIS(firmware->getBoard())) {
ui->AltitudeToolbar_ChkB->setChecked(model->frsky.altitudeDisplayed);
}
else {
ui->AltitudeToolbar_ChkB->hide();
/*if (IS_ARM(firmware->getBoard())) {
for (int i=0; i<C9X_MAX_SENSORS; ++i) {
TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model->, model, generalSettings, firmware);
ui->sensorsLayout->addWidget(panel);
sensorPanels[i] = panel;
}
}*/
int varioCap = firmware->getCapability(HasVario);
if (!varioCap) {
@ -610,7 +777,7 @@ void TelemetryPanel::setup()
ui->varioLimitCenterMin_DSB->setValue((model->frsky.varioCenterMin/10.0)-0.5);
}
ui->altimetryGB->setVisible(firmware->getCapability(HasAltitudeSel) || firmware->getCapability(HasVario)),
ui->altimetryGB->setVisible(firmware->getCapability(HasVario)),
ui->frskyProtoCB->setDisabled(firmware->getCapability(NoTelemetryProtocol));
if (firmware->getCapability(Telemetry) & TM_HASWSHH) {
@ -621,6 +788,7 @@ void TelemetryPanel::setup()
}
ui->variousGB->hide();
if (!IS_ARM(firmware->getBoard())) {
if (!(firmware->getCapability(HasFasOffset)) && !(firmware_id.contains("fasoffset"))) {
ui->fasOffset_label->hide();
ui->fasOffset_DSB->hide();
@ -648,6 +816,7 @@ void TelemetryPanel::setup()
ui->frskyProtoCB->setCurrentIndex(model->frsky.usrProto);
ui->bladesCount->setValue(model->frsky.blades);
}
populateVoltsSource();
populateCurrentSource();
@ -658,8 +827,8 @@ void TelemetryPanel::setup()
void TelemetryPanel::populateVarioSource()
{
QUnsignedAutoComboBox * cb = ui->varioSourceCB;
cb->setField(&model->frsky.varioSource, this);
AutoComboBox * cb = ui->varioSourceCB;
cb->setField(model->frsky.varioSource, this);
if (!IS_TARANIS(firmware->getBoard())) {
cb->addItem(tr("Alti"), TELEMETRY_VARIO_SOURCE_ALTI);
cb->addItem(tr("Alti+"), TELEMETRY_VARIO_SOURCE_ALTI_PLUS);
@ -674,8 +843,8 @@ void TelemetryPanel::populateVarioSource()
void TelemetryPanel::populateVoltsSource()
{
QUnsignedAutoComboBox * cb = ui->frskyVoltCB;
cb->setField(&model->frsky.voltsSource, this);
AutoComboBox * cb = ui->frskyVoltCB;
cb->setField(model->frsky.voltsSource, this);
cb->addItem(tr("A1"), TELEMETRY_VOLTS_SOURCE_A1);
cb->addItem(tr("A2"), TELEMETRY_VOLTS_SOURCE_A2);
if (IS_ARM(firmware->getBoard())) {
@ -688,8 +857,8 @@ void TelemetryPanel::populateVoltsSource()
void TelemetryPanel::populateCurrentSource()
{
QUnsignedAutoComboBox * cb = ui->frskyCurrentCB;
cb->setField(&model->frsky.currentSource, this);
AutoComboBox * cb = ui->frskyCurrentCB;
cb->setField(model->frsky.currentSource, this);
cb->addItem(tr("---"), TELEMETRY_CURRENT_SOURCE_NONE);
cb->addItem(tr("A1"), TELEMETRY_CURRENT_SOURCE_A1);
cb->addItem(tr("A2"), TELEMETRY_CURRENT_SOURCE_A2);
@ -749,18 +918,6 @@ void TelemetryPanel::on_rssiAlarm2SB_editingFinished()
emit modified();
}
void TelemetryPanel::on_AltitudeGPS_ChkB_toggled(bool checked)
{
model->frsky.FrSkyGpsAlt = checked;
emit modified();
}
void TelemetryPanel::on_AltitudeToolbar_ChkB_toggled(bool checked)
{
model->frsky.altitudeDisplayed = checked;
emit modified();
}
void TelemetryPanel::on_varioLimitMin_DSB_editingFinished()
{
model->frsky.varioMin = round(ui->varioLimitMin_DSB->value()+10);

View file

@ -2,13 +2,17 @@
#define TELEMETRY_H
#include "modeledit.h"
#include "eeprominterface.h"
#include <QGroupBox>
#include <QComboBox>
#include <QDoubleSpinBox>
class AutoComboBox;
namespace Ui {
class TelemetryAnalog;
class TelemetryCustomScreen;
class TelemetrySensor;
class Telemetry;
}
@ -74,6 +78,31 @@ class TelemetryCustomScreen: public ModelPanel
QDoubleSpinBox * maxSB[4];
};
class TelemetrySensorPanel: public ModelPanel
{
Q_OBJECT
public:
TelemetrySensorPanel(QWidget *parent, SensorData & sensor, ModelData & model, GeneralSettings & generalSettings, FirmwareInterface * firmware);
~TelemetrySensorPanel();
void update();
protected slots:
void on_name_editingFinished();
void on_type_currentIndexChanged(int index);
void on_formula_currentIndexChanged(int index);
void on_unit_currentIndexChanged(int index);
void on_prec_editingFinished();
protected:
void updateSourcesComboBox(AutoComboBox * cb);
private:
Ui::TelemetrySensor * ui;
SensorData & sensor;
bool lock;
};
class TelemetryPanel : public ModelPanel
{
Q_OBJECT
@ -88,12 +117,10 @@ class TelemetryPanel : public ModelPanel
void onAnalogModified();
void on_frskyProtoCB_currentIndexChanged(int index);
void on_bladesCount_editingFinished();
void on_AltitudeToolbar_ChkB_toggled(bool checked);
void on_rssiAlarm1CB_currentIndexChanged(int index);
void on_rssiAlarm2CB_currentIndexChanged(int index);
void on_rssiAlarm1SB_editingFinished();
void on_rssiAlarm2SB_editingFinished();
void on_AltitudeGPS_ChkB_toggled(bool checked);
void on_varioLimitMin_DSB_editingFinished();
void on_varioLimitMax_DSB_editingFinished();
void on_varioLimitCenterMin_DSB_editingFinished();
@ -106,6 +133,7 @@ class TelemetryPanel : public ModelPanel
Ui::Telemetry *ui;
TelemetryAnalog * analogs[4];
TelemetryCustomScreen * telemetryCustomScreens[4];
TelemetrySensorPanel * sensorPanels[C9X_MAX_SENSORS];
void setup();
void telBarUpdate();

View file

@ -6,16 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>850</width>
<height>457</height>
<width>861</width>
<height>562</height>
</rect>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,0">
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,0,0,0,0,0,0">
<property name="spacing">
<number>0</number>
<number>4</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
@ -51,8 +51,207 @@
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0">
<widget class="QGroupBox" name="RSSIGB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="rssiLayout" columnstretch="0,0,1">
<property name="margin">
<number>4</number>
</property>
<item row="2" column="0">
<widget class="QLabel" name="rssiAlarm1Label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>Alarm 1</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="rssiAlarm1CB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>----</string>
</property>
</item>
<item>
<property name="text">
<string>Yellow</string>
</property>
</item>
<item>
<property name="text">
<string>Orange</string>
</property>
</item>
<item>
<property name="text">
<string>Red</string>
</property>
</item>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="rssiAlarm1SB">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string/>
</property>
<property name="minimum">
<number>20</number>
</property>
<property name="maximum">
<number>80</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="rssiAlarm2Label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Alarm 2</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="rssiAlarm2CB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>----</string>
</property>
</item>
<item>
<property name="text">
<string>Yellow</string>
</property>
</item>
<item>
<property name="text">
<string>Orange</string>
</property>
</item>
<item>
<property name="text">
<string>Red</string>
</property>
</item>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="rssiAlarm2SB">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string/>
</property>
<property name="minimum">
<number>20</number>
</property>
<property name="maximum">
<number>80</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="rssiLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>RSSI</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="A1GB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -70,17 +269,8 @@
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="A1Layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
<property name="margin">
<number>4</number>
</property>
<item>
<widget class="QLabel" name="label_7">
@ -98,103 +288,14 @@
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="A4GB">
<property name="flat">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="A4Layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label_9">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>A4</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="A3GB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="A3Layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label_8">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>A3</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="A2GB">
<property name="flat">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="A2Layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
<property name="margin">
<number>4</number>
</property>
<item>
<widget class="QLabel" name="label_6">
@ -212,7 +313,7 @@
</layout>
</widget>
</item>
<item row="3" column="1">
<item>
<widget class="QGroupBox" name="altimetryGB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
@ -221,36 +322,12 @@
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout_39">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
<property name="margin">
<number>4</number>
</property>
<property name="spacing">
<number>0</number>
<number>-1</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_40" rowstretch="1,0,0,0" columnstretch="0,0">
<property name="horizontalSpacing">
<number>9</number>
</property>
<item row="1" column="1">
<widget class="QUnsignedAutoComboBox" name="varioSourceCB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QGridLayout" name="gridLayout_66" columnstretch="1,0,0,0">
<item row="0" column="0">
@ -413,13 +490,6 @@
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="varioSource_label">
<property name="text">
<string>Vario source</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="varioLimit_label">
<property name="text">
@ -427,36 +497,29 @@
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<widget class="QCheckBox" name="AltitudeGPS_ChkB">
<item row="1" column="0">
<widget class="QLabel" name="varioSource_label">
<property name="minimumSize">
<size>
<width>95</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Vario source</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="AutoComboBox" name="varioSourceCB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Use GPS as altitude source</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="AltitudeToolbar_ChkB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Display altitude in toolbar</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="font">
@ -471,11 +534,80 @@
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="topbarGB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout_40">
<property name="margin">
<number>4</number>
</property>
<property name="spacing">
<number>-1</number>
</property>
<item row="2" column="0">
<widget class="QLabel" name="altitudeSource_label">
<property name="text">
<string>Altitude source</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="voltsSource_label">
<property name="minimumSize">
<size>
<width>95</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Volts source</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="AutoComboBox" name="voltsSource">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Top Bar</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="AutoComboBox" name="altitudeSource">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="1">
<item>
<widget class="QGroupBox" name="variousGB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
@ -484,17 +616,8 @@
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>9</number>
<property name="margin">
<number>4</number>
</property>
<property name="spacing">
<number>0</number>
@ -508,7 +631,7 @@
<number>0</number>
</property>
<item row="3" column="1">
<widget class="QUnsignedAutoComboBox" name="frskyVoltCB">
<widget class="AutoComboBox" name="frskyVoltCB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -531,7 +654,7 @@
</widget>
</item>
<item row="3" column="3">
<widget class="QUnsignedAutoComboBox" name="frskyCurrentCB">
<widget class="AutoComboBox" name="frskyCurrentCB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -729,24 +852,11 @@
</item>
</layout>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="RSSIGB">
<item>
<widget class="QGroupBox" name="sensorsGB">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -756,178 +866,12 @@
<property name="flat">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<property name="leftMargin">
<number>0</number>
<layout class="QGridLayout" name="sensorsLayout" columnstretch="0">
<property name="margin">
<number>4</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="rssiAlarm1Label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>Alarm 1</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="rssiAlarm1CB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>----</string>
</property>
</item>
<item>
<property name="text">
<string>Yellow</string>
</property>
</item>
<item>
<property name="text">
<string>Orange</string>
</property>
</item>
<item>
<property name="text">
<string>Red</string>
</property>
</item>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="rssiAlarm1SB">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string/>
</property>
<property name="minimum">
<number>20</number>
</property>
<property name="maximum">
<number>80</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="rssiAlarm2Label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Alarm 2</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="rssiAlarm2CB">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>----</string>
</property>
</item>
<item>
<property name="text">
<string>Yellow</string>
</property>
</item>
<item>
<property name="text">
<string>Orange</string>
</property>
</item>
<item>
<property name="text">
<string>Red</string>
</property>
</item>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="rssiAlarm2SB">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string/>
</property>
<property name="minimum">
<number>20</number>
</property>
<property name="maximum">
<number>80</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="rssiLabel">
<widget class="QLabel" name="sensorsLabel">
<property name="font">
<font>
<weight>75</weight>
@ -935,41 +879,13 @@
</font>
</property>
<property name="text">
<string>RSSI</string>
<string>Sensors</string>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QTabWidget" name="customScreens">
<property name="sizePolicy">
@ -1000,9 +916,9 @@
</widget>
<customwidgets>
<customwidget>
<class>QUnsignedAutoComboBox</class>
<class>AutoComboBox</class>
<extends>QComboBox</extends>
<header>qautocombobox.h</header>
<header>autocombobox.h</header>
</customwidget>
</customwidgets>
<resources/>

View file

@ -2,20 +2,12 @@
<ui version="4.0">
<class>TelemetryCustomScreen</class>
<widget class="QWidget" name="TelemetryCustomScreen">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>650</width>
<height>393</height>
</rect>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5" stretch="0,0,1">
<layout class="QHBoxLayout" name="screenScript" stretch="0,0,1">
<item>
<widget class="QLabel" name="screenTypeLabel">
<property name="sizePolicy">
@ -86,13 +78,6 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="screenNums">
<layout class="QGridLayout" name="screenNumsLayout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="screenBars">
<layout class="QGridLayout" name="screenBarsLayout" columnstretch="1,0,1,0">
@ -139,7 +124,10 @@
</layout>
</widget>
</item>
</layout>
<item>
<widget class="QGroupBox" name="screenNums">
<layout class="QGridLayout" name="screenNumsLayout"/>
</widget>
</item>
</layout>
</widget>

View file

@ -0,0 +1,594 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TelemetrySensor</class>
<widget class="QWidget" name="TelemetrySensor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>2790</width>
<height>67</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0,0,0,1,1,1,1,0,0,1,0,1,0,1,1,1,1,1,1,0,1,0,1,0,1,1,0,1">
<property name="leftMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="name">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maxLength">
<number>4</number>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="type">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Custom</string>
</property>
</item>
<item>
<property name="text">
<string>Formula</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="idLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Id</string>
</property>
</widget>
</item>
<item>
<widget class="AutoHexSpinBox" name="id">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="instanceLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Instance</string>
</property>
</widget>
</item>
<item>
<widget class="AutoDoubleSpinBox" name="instance">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>255.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="formula">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Add</string>
</property>
</item>
<item>
<property name="text">
<string>Average</string>
</property>
</item>
<item>
<property name="text">
<string>Min</string>
</property>
</item>
<item>
<property name="text">
<string>Max</string>
</property>
</item>
<item>
<property name="text">
<string>Multiply</string>
</property>
</item>
<item>
<property name="text">
<string>Cell</string>
</property>
</item>
<item>
<property name="text">
<string>Consumption</string>
</property>
</item>
<item>
<property name="text">
<string>Dist</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="cellsSensorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cells Sensor :</string>
</property>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="cellsSensor">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>---</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="cellsIndex">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gpsSensorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>GPS Sensor :</string>
</property>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="gpsSensor">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>---</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="altSensorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Alt. Sensor :</string>
</property>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="altSensor">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>---</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="ampsSensorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Amps Sensor :</string>
</property>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="ampsSensor">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>---</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="source1">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>---</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="source2">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>---</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="source3">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>---</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="source4">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>---</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="unit">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Raw (-)</string>
</property>
</item>
<item>
<property name="text">
<string>Voltage (V)</string>
</property>
</item>
<item>
<property name="text">
<string>Current (A)</string>
</property>
</item>
<item>
<property name="text">
<string>Current (mA)</string>
</property>
</item>
<item>
<property name="text">
<string>Speed (kts)</string>
</property>
</item>
<item>
<property name="text">
<string>Speed (m/s)</string>
</property>
</item>
<item>
<property name="text">
<string>Speed (km/h)</string>
</property>
</item>
<item>
<property name="text">
<string>Speed (miles/h)</string>
</property>
</item>
<item>
<property name="text">
<string>Meters (m)</string>
</property>
</item>
<item>
<property name="text">
<string>Feet (f)</string>
</property>
</item>
<item>
<property name="text">
<string>Temp (°C)</string>
</property>
</item>
<item>
<property name="text">
<string>Temp (°F)</string>
</property>
</item>
<item>
<property name="text">
<string>Percentage (%)</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="precLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Precision</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="prec">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>2.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="ratioLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Range</string>
</property>
</widget>
</item>
<item>
<widget class="AutoDoubleSpinBox" name="ratio">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>3000.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="offsetLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Offset</string>
</property>
</widget>
</item>
<item>
<widget class="AutoDoubleSpinBox" name="offset">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-12.800000000000001</double>
</property>
<property name="maximum">
<double>12.699999999999999</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="AutoComboBox" name="inputFlags">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>---</string>
</property>
</item>
<item>
<property name="text">
<string>Auto Offset</string>
</property>
</item>
<item>
<property name="text">
<string>Filtered</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="AutoCheckBox" name="logs">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Logs</string>
</property>
</widget>
</item>
<item>
<widget class="AutoCheckBox" name="persistent">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Persistent</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AutoDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>autodoublespinbox.h</header>
</customwidget>
<customwidget>
<class>AutoComboBox</class>
<extends>QComboBox</extends>
<header>autocombobox.h</header>
</customwidget>
<customwidget>
<class>AutoCheckBox</class>
<extends>QCheckBox</extends>
<header>autocheckbox.h</header>
</customwidget>
<customwidget>
<class>AutoHexSpinBox</class>
<extends>QSpinBox</extends>
<header>autohexspinbox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,22 @@
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
set(shared_SRCS
foldersync.cpp
genericpanel.cpp
hexspinbox.cpp
verticalscrollarea.cpp
)
set(shared_HDRS
autocheckbox.h
autocombobox.h
autodoublespinbox.h
autohexspinbox.h
genericpanel.h
hexspinbox.h
verticalscrollarea.h
)
qt4_wrap_cpp(shared_SRCS ${shared_HDRS})
add_library(shared ${shared_SRCS})

View file

@ -0,0 +1,54 @@
#ifndef AUTOCHECKBOX_H_
#define AUTOCHECKBOX_H_
#include <QCheckBox>
#include "modeledit/modeledit.h"
class AutoCheckBox: public QCheckBox
{
Q_OBJECT
public:
explicit AutoCheckBox(QWidget *parent = 0):
QCheckBox(parent),
field(NULL),
panel(NULL),
lock(false)
{
connect(this, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)));
}
void setField(bool & field, ModelPanel * panel=NULL)
{
this->field = &field;
this->panel = panel;
updateValue();
}
void updateValue()
{
lock = true;
if (field) {
setChecked((int)*field);
}
lock = false;
}
protected slots:
void onToggled(bool checked)
{
if (field && !lock) {
*field = checked;
if (panel) {
emit panel->modified();
}
}
}
protected:
bool * field;
ModelPanel * panel;
bool lock;
};
#endif /* AUTOCHECKBOX_H_ */

View file

@ -1,15 +1,15 @@
#ifndef QAUTOCOMBOBOX_H_
#define QAUTOCOMBOBOX_H_
#ifndef AUTOCOMBOBOX_H_
#define AUTOCOMBOBOX_H_
#include <QComboBox>
#include "modeledit/modeledit.h"
class QUnsignedAutoComboBox: public QComboBox
class AutoComboBox: public QComboBox
{
Q_OBJECT
public:
explicit QUnsignedAutoComboBox(QWidget *parent = 0):
explicit AutoComboBox(QWidget *parent = 0):
QComboBox(parent),
field(NULL),
panel(NULL),
@ -18,19 +18,32 @@ class QUnsignedAutoComboBox: public QComboBox
connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
}
void clear()
{
lock = true;
QComboBox::clear();
lock = false;
}
void addItem(const QString & item, unsigned int value)
{
lock = true;
QComboBox::addItem(item, value);
if (field && *field==value)
if (field && *field==value) {
setCurrentIndex(count()-1);
}
lock = false;
}
void setField(unsigned int * field, ModelPanel * panel=NULL)
void setField(unsigned int & field, ModelPanel * panel=NULL)
{
this->field = field;
this->field = &field;
this->panel = panel;
for (int i=0; i<count(); ++i) {
setItemData(i, i);
if ((int)field == i)
setCurrentIndex(i);
}
}
protected slots:
@ -50,4 +63,4 @@ class QUnsignedAutoComboBox: public QComboBox
bool lock;
};
#endif /* QAUTOCOMBOBOX_H_ */
#endif /* AUTOCOMBOBOX_H_ */

View file

@ -0,0 +1,78 @@
#ifndef AUTODOUBLESPINBOX_H_
#define AUTODOUBLESPINBOX_H_
#include <QDoubleSpinBox>
#include "modeledit/modeledit.h"
class AutoDoubleSpinBox: public QDoubleSpinBox
{
Q_OBJECT
public:
explicit AutoDoubleSpinBox(QWidget *parent = 0):
QDoubleSpinBox(parent),
field(NULL),
panel(NULL),
lock(false)
{
connect(this, SIGNAL(valueChanged(double)), this, SLOT(onValueChanged(double)));
}
void setField(int & field, ModelPanel * panel=NULL)
{
this->field = &field;
this->panel = panel;
updateValue();
}
void setField(unsigned int & field, ModelPanel * panel=NULL)
{
this->field = (int *)&field;
this->panel = panel;
updateValue();
}
void updateValue()
{
if (field) {
setValue(float(*field)/multiplier());
}
}
void setDecimals(int prec)
{
QDoubleSpinBox::setDecimals(prec);
updateValue();
}
protected:
int multiplier()
{
switch (decimals()) {
case 1:
return 10;
case 2:
return 100;
default:
return 1;
}
}
protected slots:
void onValueChanged(double value)
{
if (field && !lock) {
*field = value * multiplier();
if (panel) {
emit panel->modified();
}
}
}
protected:
int * field;
ModelPanel * panel;
bool lock;
};
#endif /* AUTODOUBLESPINBOX_H_ */

View file

@ -0,0 +1,52 @@
#ifndef AUTOHEXSPINBOX_H_
#define AUTOHEXSPINBOX_H_
#include "hexspinbox.h"
#include "modeledit/modeledit.h"
class AutoHexSpinBox: public HexSpinBox
{
Q_OBJECT
public:
explicit AutoHexSpinBox(QWidget *parent = 0):
HexSpinBox(parent),
field(NULL),
panel(NULL),
lock(false)
{
connect(this, SIGNAL(valueChanged(int)), this, SLOT(onValueChanged(int)));
}
void setField(unsigned int & field, ModelPanel * panel=NULL)
{
this->field = &field;
this->panel = panel;
updateValue();
}
void updateValue()
{
if (field) {
setValue(*field);
}
}
protected slots:
void onValueChanged(int value)
{
if (field && !lock) {
*field = value;
if (panel) {
emit panel->modified();
}
}
}
protected:
unsigned int * field;
ModelPanel * panel;
bool lock;
};
#endif /* AUTOHEXSPINBOX_H_ */

View file

@ -0,0 +1,104 @@
#include "genericpanel.h"
#include <QComboBox>
#include <QEvent>
#include <QLabel>
#include <QGridLayout>
#include <QSpacerItem>
GenericPanel::GenericPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, FirmwareInterface * firmware):
QWidget(parent),
model(model),
generalSettings(generalSettings),
firmware(firmware),
lock(false)
{
}
GenericPanel::~GenericPanel()
{
}
void GenericPanel::update()
{
}
void GenericPanel::addLabel(QGridLayout *gridLayout, const QString &text, int col, bool minimize)
{
QLabel *label = new QLabel(this);
label->setFrameShape(QFrame::Panel);
label->setFrameShadow(QFrame::Raised);
label->setMidLineWidth(0);
label->setAlignment(Qt::AlignCenter);
label->setMargin(5);
label->setText(text);
if (!minimize)
label->setMinimumWidth(100);
gridLayout->addWidget(label, 0, col, 1, 1);
}
void GenericPanel::addEmptyLabel(QGridLayout * gridLayout, int col)
{
QLabel *label = new QLabel(this);
label->setText("");
gridLayout->addWidget(label, 0, col, 1, 1);
}
void GenericPanel::addHSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
gridLayout->addItem(spacer, row, col);
}
void GenericPanel::addVSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
gridLayout->addItem(spacer, row, col);
}
void GenericPanel::addDoubleSpring(QGridLayout * gridLayout, int col, int row)
{
QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding );
gridLayout->addItem(spacer, row, col);
}
bool GenericPanel::eventFilter(QObject *object, QEvent * event)
{
QWidget * widget = qobject_cast<QWidget*>(object);
if (widget) {
if (event->type() == QEvent::Wheel) {
if (widget->focusPolicy() == Qt::WheelFocus) {
event->accept();
return false;
}
else {
event->ignore();
return true;
}
}
else if (event->type() == QEvent::FocusIn) {
widget->setFocusPolicy(Qt::WheelFocus);
}
else if (event->type() == QEvent::FocusOut) {
widget->setFocusPolicy(Qt::StrongFocus);
}
}
return QWidget::eventFilter(object, event);
}
void GenericPanel::disableMouseScrolling()
{
Q_FOREACH(QComboBox * cb, findChildren<QComboBox*>()) {
cb->installEventFilter(this);
cb->setFocusPolicy(Qt::StrongFocus);
}
Q_FOREACH(QAbstractSpinBox * sb, findChildren<QAbstractSpinBox*>()) {
sb->installEventFilter(this);
sb->setFocusPolicy(Qt::StrongFocus);
}
Q_FOREACH(QSlider * slider, findChildren<QSlider*>()) {
slider->installEventFilter(this);
slider->setFocusPolicy(Qt::StrongFocus);
}
}

View file

@ -0,0 +1,45 @@
#ifndef GENERICPANEL_H_
#define GENERICPANEL_H_
#include <QWidget>
class ModelData;
class GeneralSettings;
class FirmwareInterface;
class QGridLayout;
class QString;
class GenericPanel : public QWidget
{
Q_OBJECT
friend class AutoComboBox;
friend class AutoDoubleSpinBox;
friend class AutoCheckBox;
friend class AutoHexSpinBox;
public:
GenericPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, FirmwareInterface * firmware);
virtual ~GenericPanel();
signals:
void modified();
public slots:
virtual void update();
protected:
ModelData * model;
GeneralSettings & generalSettings;
FirmwareInterface * firmware;
bool lock;
void addLabel(QGridLayout * gridLayout, const QString &text, int col, bool mimimize=false);
void addEmptyLabel(QGridLayout * gridLayout, int col);
void addHSpring(QGridLayout *, int col, int row);
void addVSpring(QGridLayout *, int col, int row);
void addDoubleSpring(QGridLayout *, int col, int row);
virtual bool eventFilter(QObject *obj, QEvent *event);
void disableMouseScrolling();
};
#endif

View file

@ -0,0 +1,23 @@
#include "verticalscrollarea.h"
#include "genericpanel.h"
#include <QEvent>
#include <QScrollBar>
VerticalScrollArea::VerticalScrollArea(QWidget * parent, GenericPanel * panel):
QScrollArea(parent),
panel(panel),
parent(parent)
{
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setWidget(panel);
panel->installEventFilter(this);
}
bool VerticalScrollArea::eventFilter(QObject *o, QEvent *e)
{
if (o == panel && e->type() == QEvent::Resize) {
setMinimumWidth(panel->minimumSizeHint().width() + verticalScrollBar()->width());
}
return false;
}

View file

@ -0,0 +1,22 @@
#ifndef VERTICALSCROLLAREA_H_
#define VERTICALSCROLLAREA_H_
#include <QScrollArea>
class GenericPanel;
class VerticalScrollArea : public QScrollArea
{
public:
VerticalScrollArea(QWidget * parent, GenericPanel * panel);
protected:
virtual bool eventFilter(QObject *o, QEvent *e);
private:
GenericPanel * panel;
QWidget * parent;
};
#endif

View file

@ -27,3 +27,4 @@
/lua_exports.cpp
/lua_exports.txt
/lua_fields.txt
/allsimusrc.cpp

View file

@ -642,7 +642,7 @@ ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO))
EEPROMSRC = eeprom_common.cpp eeprom_raw.cpp eeprom_conversions.cpp
LCDSRC = lcd_common.cpp lcd_default.cpp
PULSESSRC = pulses/pulses_arm.cpp pulses/ppm_arm.cpp pulses/pxx_arm.cpp pulses/dsm2_arm.cpp
CPPSRC += tasks_arm.cpp audio_arm.cpp haptic.cpp gui/view_about.cpp gui/view_text.cpp
CPPSRC += tasks_arm.cpp audio_arm.cpp haptic.cpp gui/view_about.cpp gui/view_text.cpp telemetry/telemetry.cpp
CPPSRC += targets/sky9x/telemetry_driver.cpp targets/sky9x/second_serial_driver.cpp targets/sky9x/pwr_driver.cpp targets/sky9x/adc_driver.cpp targets/sky9x/eeprom_driver.cpp targets/sky9x/pulses_driver.cpp targets/sky9x/keys_driver.cpp targets/sky9x/audio_driver.cpp targets/sky9x/buzzer_driver.cpp targets/sky9x/haptic_driver.cpp targets/sky9x/sdcard_driver.cpp targets/sky9x/massstorage.cpp
CPPSRC += loadboot.cpp
ifeq ($(SDCARD), YES)
@ -732,7 +732,7 @@ ifeq ($(PCB), TARANIS)
EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp eeprom_conversions.cpp
LCDSRC = lcd_common.cpp lcd_taranis.cpp
PULSESSRC = pulses/pulses_arm.cpp pulses/ppm_arm.cpp pulses/pxx_arm.cpp
CPPSRC += tasks_arm.cpp audio_arm.cpp sbus.cpp
CPPSRC += tasks_arm.cpp audio_arm.cpp sbus.cpp telemetry/telemetry.cpp
CPPSRC += targets/taranis/pulses_driver.cpp targets/taranis/keys_driver.cpp targets/taranis/adc_driver.cpp targets/taranis/trainer_driver.cpp targets/taranis/audio_driver.cpp targets/taranis/uart3_driver.cpp targets/taranis/telemetry_driver.cpp
CPPSRC += bmp.cpp gui/view_channels.cpp gui/view_about.cpp gui/view_text.cpp loadboot.cpp
SRC += targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Source/Templates/system_stm32f2xx.c
@ -1374,8 +1374,8 @@ FOXLIB=-L/usr/local/lib \
-lFOX-1.6 \
-Wl,-rpath,$(FOXPATH)/src/.libs
simu: $(LUADEP) stamp_header $(BOARDSRC) $(CPPSRC) Makefile simu.cpp targets/simu/simpgmspace.cpp *.h tra lbm eeprom.bin
g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp $(BOARDSRC) $(CPPSRC) $(LUASRC) targets/simu/simpgmspace.cpp -MD -DSIMU -DLUA_USE_APICHECK -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions
simu: $(LUADEP) stamp_header allsimusrc.cpp Makefile simu.cpp targets/simu/simpgmspace.cpp *.h tra lbm eeprom.bin
g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp allsimusrc.cpp $(LUASRC) targets/simu/simpgmspace.cpp -MD -DSIMU -DLUA_USE_APICHECK -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions
eeprom.bin:
dd if=/dev/zero of=$@ bs=1 count=2048
@ -1421,8 +1421,13 @@ allsrc.cpp: Makefile $(BOARDSRC) $(CPPSRC) $(EXTRABOARDSRC)
@rm -f allsrc.cpp
for f in $(BOARDSRC) $(CPPSRC) $(EXTRABOARDSRC) ; do echo "# 1 \"$$f\"" >> allsrc.cpp; cat "$$f" >> allsrc.cpp; done
allsimusrc.cpp: Makefile $(BOARDSRC) $(CPPSRC)
@rm -f allsimusrc.cpp
for f in $(BOARDSRC) $(CPPSRC) ; do echo "# 1 \"$$f\"" >> allsimusrc.cpp; cat "$$f" >> allsimusrc.cpp; done
remallsrc:
$(REMOVE) allsrc.cpp
$(REMOVE) allsimusrc.cpp
# Link: create ELF output file from object files.
ifeq ($(ARCH), AVR)
@ -1468,6 +1473,7 @@ clean_list :
$(REMOVE) *.d
$(REMOVE) *.lst
$(REMOVE) allsrc.cpp
$(REMOVE) allsimusrc.cpp
$(REMOVE) stamp-opentx.h
$(REMOVE) *.lbm
$(REMOVE) bitmaps/*.lbm
@ -1553,6 +1559,6 @@ gtest_main.a : gtest-all.o gtest_main.o
#use all .cpp files from tests/ dir
GTEST_TESTS_SRCS = $(shell find tests/ -type f -name '*.cpp')
gtests: $(BOARDSRC) $(CPPSRC) $(GTEST_TESTS_SRCS) targets/simu/simpgmspace.cpp *.h gtest_main.a
g++ -std=gnu++0x $(CPPFLAGS) $(BOARDSRC) $(CPPSRC) $(LUASRC) $(GTEST_TESTS_SRCS) targets/simu/simpgmspace.cpp -I$(GTEST_DIR) ${INCFLAGS} -I$(GTEST_DIR)/include -o gtests -lpthread -MD -DSIMU -lQtCore -lQtGui gtest_main.a -fexceptions
gtests: allsimusrc.cpp $(GTEST_TESTS_SRCS) targets/simu/simpgmspace.cpp *.h gtest_main.a
g++ -std=gnu++0x $(CPPFLAGS) allsimusrc.cpp $(LUASRC) $(GTEST_TESTS_SRCS) targets/simu/simpgmspace.cpp -I$(GTEST_DIR) ${INCFLAGS} -I$(GTEST_DIR)/include -o gtests -lpthread -MD -DSIMU -lQtCore -lQtGui gtest_main.a -fexceptions

View file

@ -119,6 +119,20 @@ PACK(typedef struct {
uint8_t spare[2];
int8_t curveParam;
}) ExpoData_v215;
PACK(typedef struct {
uint8_t srcRaw;
uint16_t scale;
uint8_t chn;
int8_t swtch;
uint16_t flightModes;
int8_t weight;
int8_t carryTrim:6;
uint8_t mode:2;
char name[LEN_EXPOMIX_NAME];
int8_t offset;
CurveRef curve;
uint8_t spare;
}) ExpoData_v216;
#else
PACK(typedef struct {
uint8_t mode; // 0=end, 1=pos, 2=neg, 3=both
@ -130,6 +144,16 @@ PACK(typedef struct {
char name[LEN_EXPOMIX_NAME];
int8_t curveParam;
}) ExpoData_v215;
PACK(typedef struct {
uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
uint8_t chn:4;
uint8_t curveMode:2;
int8_t swtch;
uint16_t flightModes;
int8_t weight;
char name[LEN_EXPOMIX_NAME];
int8_t curveParam;
}) ExpoData_v216;
#endif
#if defined(PCBTARANIS)
@ -289,6 +313,16 @@ PACK(typedef struct {
int8_t andsw;
}) LogicalSwitchData_v215;
PACK(typedef struct { // Logical Switches data
int8_t v1;
int16_t v2;
int16_t v3;
uint8_t func;
uint8_t delay;
uint8_t duration;
int8_t andsw;
}) LogicalSwitchData_v216;
#if defined(PCBTARANIS)
PACK(typedef struct {
int8_t swtch;
@ -321,6 +355,21 @@ PACK(typedef struct {
}) CustomFunctionData_v215;
#endif
PACK(typedef struct {
uint8_t source;
uint8_t barMin; // minimum for bar display
uint8_t barMax; // ditto for max display (would usually = ratio)
}) FrSkyBarData_v215;
PACK(typedef struct {
uint8_t sources[NUM_LINE_ITEMS];
}) FrSkyLineData_v215;
typedef union {
FrSkyBarData_v215 bars[4];
FrSkyLineData_v215 lines[4];
} FrSkyScreenData_v215;
PACK(typedef struct {
FrSkyChannelData channels[2];
uint8_t usrProto; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon
@ -328,7 +377,7 @@ PACK(typedef struct {
uint8_t blades; // How many blades for RPMs, 0=2 blades, 1=3 blades
uint8_t currentSource;
uint8_t screensType;
FrSkyScreenData screens[3];
FrSkyScreenData_v215 screens[3];
uint8_t varioSource;
int8_t varioCenterMax;
int8_t varioCenterMin;
@ -345,7 +394,7 @@ PACK(typedef struct {
int8_t blades; // How many blades for RPMs, 0=2 blades
uint8_t currentSource;
uint8_t screensType; // 2bits per screen (None/Gauges/Numbers/Script)
FrSkyScreenData screens[3];
FrSkyScreenData_v215 screens[3];
uint8_t varioSource;
int8_t varioCenterMax;
int8_t varioCenterMin;
@ -441,12 +490,12 @@ PACK(typedef struct {
BeepANACenter beepANACenter; // 1<<0->A1.. 1<<6->A7
MixData_v216 mixData[MAX_MIXERS];
LimitData_v216 limitData[NUM_CHNOUT];
ExpoData expoData[MAX_EXPOS];
ExpoData_v216 expoData[MAX_EXPOS];
CURVDATA curves[MAX_CURVES];
int8_t points[NUM_POINTS];
LogicalSwitchData logicalSw[NUM_LOGICAL_SWITCH];
LogicalSwitchData_v216 logicalSw[NUM_LOGICAL_SWITCH];
CustomFunctionData customFn[NUM_CFN];
SwashRingData swashR;
FlightModeData flightModeData[MAX_FLIGHT_MODES];
@ -593,8 +642,8 @@ int ConvertTelemetrySource_215_to_216(int source)
int ConvertTelemetrySource_216_to_217(int source)
{
// TELEM_TIMER3 added
if (source >= TELEM_TIMER3)
source += 1;
// if (source >= TELEM_TIMER3)
// source += 1;
return source;
}
@ -679,7 +728,7 @@ int ConvertSource_216_to_217(int source)
{
// Telemetry conversions
if (source >= MIXSRC_FIRST_TELEM)
source = MIXSRC_FIRST_TELEM + ConvertTelemetrySource_216_to_217(source-MIXSRC_FIRST_TELEM+1) - 1;
source = 0;
return source;
}
@ -819,7 +868,7 @@ void ConvertModel_215_to_216(ModelData &model)
int indexes[NUM_STICKS] = { 0, 0, 0, 0 };
#endif
for (uint8_t i=0; i<32; i++) {
ExpoData * expo = &newModel.expoData[i];
ExpoData_v216 * expo = &newModel.expoData[i];
ExpoData_v215 * oldExpo = &oldModel.expoData[i];
if (oldExpo->mode) {
#if defined(PCBTARANIS)
@ -873,9 +922,9 @@ void ConvertModel_215_to_216(ModelData &model)
for (int i=NUM_STICKS-1; i>=0; i--) {
int idx = indexes[i];
if (idx >= 0) {
ExpoData * expo = expoAddress(idx);
memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
memclear(expo, sizeof(ExpoData));
ExpoData_v216 * expo = &newModel.expoData[idx];
memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData_v216));
memclear(expo, sizeof(ExpoData_v216));
expo->srcRaw = MIXSRC_Rud + i;
expo->chn = i;
expo->weight = 100;
@ -907,7 +956,7 @@ void ConvertModel_215_to_216(ModelData &model)
newModel.points[i] = oldModel.points[i];
}
for (uint8_t i=0; i<32; i++) {
LogicalSwitchData & sw = newModel.logicalSw[i];
LogicalSwitchData_v216 & sw = newModel.logicalSw[i];
sw.func = oldModel.logicalSw[i].func;
if (sw.func >= LS_FUNC_VEQUAL) sw.func += 1;
if (sw.func >= LS_FUNC_RANGE) sw.func += 1;
@ -1097,16 +1146,16 @@ void ConvertModel_215_to_216(ModelData &model)
if (newModel.frsky.screensType & (1<<i)) {
// gauges
for (int j=0; j<4; j++) {
uint8_t & source = newModel.frsky.screens[i].bars[j].source;
source = ConvertTelemetrySource_215_to_216(source);
// uint8_t & source = newModel.frsky.screens[i].bars[j].source;
// source = ConvertTelemetrySource_215_to_216(source);
}
}
else {
// numbers
for (int j=0; j<4; j++) {
for (int k=0; k<NUM_LINE_ITEMS; k++) {
uint8_t & source = newModel.frsky.screens[i].lines[j].sources[k];
source = ConvertTelemetrySource_215_to_216(source);
// uint8_t & source = newModel.frsky.screens[i].lines[j].sources[k];
// source = ConvertTelemetrySource_215_to_216(source);
}
}
}
@ -1205,20 +1254,38 @@ void ConvertModel_216_to_217(ModelData &model)
#endif
}
for (int i=0; i<MAX_EXPOS; i++) {
newModel.expoData[i] = oldModel.expoData[i];
#if defined(PCBTARANIS)
newModel.expoData[i].srcRaw = ConvertSource_216_to_217(oldModel.expoData[i].srcRaw);
newModel.expoData[i].scale = oldModel.expoData[i].scale;
newModel.expoData[i].carryTrim = oldModel.expoData[i].carryTrim;
newModel.expoData[i].curve = oldModel.expoData[i].curve;
newModel.expoData[i].offset = oldModel.expoData[i].offset;
#else
newModel.expoData[i].curveMode = oldModel.expoData[i].curveMode;
newModel.expoData[i].curveParam = oldModel.expoData[i].curveParam;
#endif
newModel.expoData[i].chn = oldModel.expoData[i].chn;
newModel.expoData[i].swtch = oldModel.expoData[i].swtch;
newModel.expoData[i].flightModes = oldModel.expoData[i].flightModes;
newModel.expoData[i].weight = oldModel.expoData[i].weight;
newModel.expoData[i].mode = oldModel.expoData[i].mode;
memcpy(newModel.expoData[i].name, oldModel.expoData[i].name, sizeof(newModel.expoData[i].name));
}
memcpy(newModel.curves, oldModel.curves, sizeof(newModel.curves));
memcpy(newModel.points, oldModel.points, sizeof(newModel.points));
for (int i=0; i<NUM_LOGICAL_SWITCH; i++) {
newModel.logicalSw[i] = oldModel.logicalSw[i];
newModel.logicalSw[i].func = oldModel.logicalSw[i].func;
newModel.logicalSw[i].v1 = oldModel.logicalSw[i].v1;
newModel.logicalSw[i].v2 = oldModel.logicalSw[i].v2;
newModel.logicalSw[i].v3 = oldModel.logicalSw[i].v3;
newModel.logicalSw[i].delay = oldModel.logicalSw[i].delay;
newModel.logicalSw[i].duration = oldModel.logicalSw[i].duration;
newModel.logicalSw[i].andsw = oldModel.logicalSw[i].andsw;
uint8_t cstate = lswFamily(newModel.logicalSw[i].func);
if (cstate == LS_FAMILY_OFS || cstate == LS_FAMILY_COMP || cstate == LS_FAMILY_DIFF) {
newModel.logicalSw[i].v1 = ConvertSource_216_to_217(oldModel.logicalSw[i].v1);
newModel.logicalSw[i].v1 = ConvertSource_216_to_217((uint8_t)newModel.logicalSw[i].v1);
if (cstate == LS_FAMILY_COMP) {
newModel.logicalSw[i].v2 = ConvertSource_216_to_217(oldModel.logicalSw[i].v2);
newModel.logicalSw[i].v2 = ConvertSource_216_to_217((uint8_t)newModel.logicalSw[i].v2);
}
}
}
@ -1239,8 +1306,7 @@ void ConvertModel_216_to_217(ModelData &model)
newModel.nSwToWarn = oldModel.nSwToWarn;
memcpy(newModel.gvars, oldModel.gvars, sizeof(newModel.gvars));
memcpy(&newModel.frsky, &oldModel.frsky, sizeof(newModel.frsky.channels)+5+sizeof(oldModel.frsky.screens));
memcpy(&newModel.frsky.varioSource, &oldModel.frsky.varioSource, 5+sizeof(newModel.frsky.rssiAlarms)+3);
memcpy(&newModel.frsky.rssiAlarms, &oldModel.frsky.rssiAlarms, sizeof(newModel.frsky.rssiAlarms));
newModel.externalModule = oldModel.externalModule;
memcpy(newModel.moduleData, oldModel.moduleData, sizeof(newModel.moduleData));
#if defined(PCBTARANIS)

View file

@ -994,8 +994,11 @@ void eeLoadModel(uint8_t id)
#endif
#if defined(CPUARM)
if (g_model.frsky.mAhPersistent) {
frskyData.hub.currentConsumption = g_model.frsky.storedMah;
for (int i=0; i<TELEM_VALUES_MAX; i++) {
TelemetrySensor & sensor = g_model.telemetrySensors[i];
if (sensor.type == TELEM_TYPE_CALCULATED && sensor.persistent) {
telemetryItems[i].value = sensor.persistentValue;
}
}
#endif

View file

@ -56,34 +56,62 @@ void testFunc()
#endif
#if defined(VOICE)
PLAY_FUNCTION(playValue, uint8_t idx)
PLAY_FUNCTION(playValue, source_t idx)
{
if (IS_FAI_FORBIDDEN(idx))
return;
getvalue_t val = getValue(idx);
switch (idx) {
#if defined(CPUARM)
case MIXSRC_FIRST_TELEM+TELEM_TX_TIME-1:
if (idx >= MIXSRC_FIRST_TELEM) {
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[(idx-MIXSRC_FIRST_TELEM) / 3];
uint8_t attr = 0;
if (telemetrySensor.prec > 0) {
if (telemetrySensor.prec == 2) {
if (val >= 5000) {
val = div100_and_round(val);
}
else {
val = div10_and_round(val);
attr = PREC1;
}
}
else {
if (val >= 500) {
val = div10_and_round(val);
}
else {
attr = PREC1;
}
}
}
PLAY_NUMBER(val, 1+telemetrySensor.unit, attr);
}
else if (idx >= MIXSRC_FIRST_TIMER && idx <= MIXSRC_LAST_TIMER) {
PLAY_DURATION(val, 0);
}
else if (idx == MIXSRC_TX_TIME) {
PLAY_DURATION(val*60, PLAY_TIME);
break;
#endif
}
else if (idx == MIXSRC_TX_VOLTAGE) {
PLAY_NUMBER(val, 1+UNIT_VOLTS, PREC1);
}
else {
if (idx <= MIXSRC_LAST_CH) {
val = calcRESXto100(val);
}
PLAY_NUMBER(val, 0, 0);
}
#else
switch (idx) {
case MIXSRC_FIRST_TELEM+TELEM_TX_VOLTAGE-1:
PLAY_NUMBER(val, 1+UNIT_VOLTS, PREC1);
break;
case MIXSRC_FIRST_TELEM+TELEM_TIMER1-1:
case MIXSRC_FIRST_TELEM+TELEM_TIMER2-1:
#if defined(CPUARM)
case MIXSRC_FIRST_TELEM+TELEM_TIMER3-1:
#endif
PLAY_DURATION(val, 0);
break;
#if defined(CPUARM) && defined(FRSKY)
case MIXSRC_FIRST_TELEM+TELEM_SWR-1:
PLAY_NUMBER(val, 0, 0);
break;
#endif
#if defined(FRSKY)
case MIXSRC_FIRST_TELEM+TELEM_RSSI_TX-1:
case MIXSRC_FIRST_TELEM+TELEM_RSSI_RX-1:
@ -91,18 +119,10 @@ PLAY_FUNCTION(playValue, uint8_t idx)
break;
case MIXSRC_FIRST_TELEM+TELEM_MIN_A1-1:
case MIXSRC_FIRST_TELEM+TELEM_MIN_A2-1:
#if defined(CPUARM)
case MIXSRC_FIRST_TELEM+TELEM_MIN_A3-1:
case MIXSRC_FIRST_TELEM+TELEM_MIN_A4-1:
#endif
idx -= TELEM_MIN_A1-TELEM_A1;
// no break
case MIXSRC_FIRST_TELEM+TELEM_A1-1:
case MIXSRC_FIRST_TELEM+TELEM_A2-1:
#if defined(CPUARM)
case MIXSRC_FIRST_TELEM+TELEM_A3-1:
case MIXSRC_FIRST_TELEM+TELEM_A4-1:
#endif
if (TELEMETRY_STREAMING()) {
idx -= (MIXSRC_FIRST_TELEM+TELEM_A1-1);
uint8_t att = 0;
@ -154,10 +174,6 @@ PLAY_FUNCTION(playValue, uint8_t idx)
break;
case MIXSRC_FIRST_TELEM+TELEM_ALT-1:
#if defined(PCBTARANIS)
PLAY_NUMBER(div10_and_round(val), 1+UNIT_DIST, PREC1);
break;
#endif
case MIXSRC_FIRST_TELEM+TELEM_MIN_ALT-1:
case MIXSRC_FIRST_TELEM+TELEM_MAX_ALT-1:
#if defined(WS_HOW_HIGH)
@ -206,6 +222,7 @@ PLAY_FUNCTION(playValue, uint8_t idx)
}
#endif
}
#endif
}
#endif

View file

@ -471,7 +471,7 @@ void menuGeneralSetup(uint8_t event)
#if defined(PCBSKY9X)
case ITEM_SETUP_CAPACITY_WARNING:
lcd_putsLeft(y, STR_CAPAWARNING);
putsTelemetryValue(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.mAhWarn*50, UNIT_MAH, attr|LEFT) ;
putsValueWithUnit(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.mAhWarn*50, UNIT_MAH, attr|LEFT) ;
if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.mAhWarn, 0, 100);
break;
#endif
@ -479,7 +479,7 @@ void menuGeneralSetup(uint8_t event)
#if defined(PCBSKY9X)
case ITEM_SETUP_TEMPERATURE_WARNING:
lcd_putsLeft(y, STR_TEMPWARNING);
putsTelemetryValue(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.temperatureWarn, UNIT_TEMPERATURE, attr|LEFT) ;
putsValueWithUnit(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.temperatureWarn, UNIT_TEMPERATURE, attr|LEFT) ;
if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureWarn, 0, 120); // 0 means no alarm
break;
#endif
@ -1349,13 +1349,13 @@ void menuGeneralDiagAna(uint8_t event)
#if defined(PCBSKY9X) && !defined(REVA)
lcd_putsLeft(6*FH+1, STR_CURRENT_CALIB);
putsTelemetryValue(LEN_CALIB_FIELDS*FW+4*FW, 6*FH+1, getCurrent(), UNIT_MILLIAMPS, (m_posVert==2 ? INVERS : 0)) ;
putsValueWithUnit(LEN_CALIB_FIELDS*FW+4*FW, 6*FH+1, getCurrent(), UNIT_MILLIAMPS, (m_posVert==2 ? INVERS : 0)) ;
if (m_posVert==2) CHECK_INCDEC_GENVAR(event, g_eeGeneral.currentCalib, -49, 49);
#endif
#if defined(PCBSKY9X)
lcd_putsLeft(7*FH+1, STR_TEMP_CALIB);
putsTelemetryValue(LEN_CALIB_FIELDS*FW+4*FW, 7*FH+1, getTemperature(), UNIT_TEMPERATURE, (m_posVert==3 ? INVERS : 0)) ;
putsValueWithUnit(LEN_CALIB_FIELDS*FW+4*FW, 7*FH+1, getTemperature(), UNIT_TEMPERATURE, (m_posVert==3 ? INVERS : 0)) ;
if (m_posVert==3) CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureCalib, -100, 100);
#endif
}

View file

@ -1219,14 +1219,14 @@ void menuModelSetup(uint8_t event)
#endif
case ITEM_MODEL_EXTENDED_LIMITS:
g_model.extendedLimits = onoffMenuItem(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event);
ON_OFF_MENU_ITEM(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event);
break;
case ITEM_MODEL_EXTENDED_TRIMS:
#if defined(CPUM64)
g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, attr, event);
ON_OFF_MENU_ITEM(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, attr, event);
#else
g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, m_posHorz<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0);
ON_OFF_MENU_ITEM(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, m_posHorz<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0);
lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_RESET_BTN, m_posHorz>0 && !s_noHi ? attr : 0);
if (attr && m_posHorz>0) {
s_editMode = 0;
@ -1253,7 +1253,7 @@ void menuModelSetup(uint8_t event)
#endif
case ITEM_MODEL_THROTTLE_REVERSED:
g_model.throttleReversed = onoffMenuItem(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEREVERSE, attr, event ) ;
ON_OFF_MENU_ITEM(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEREVERSE, attr, event ) ;
break;
case ITEM_MODEL_THROTTLE_TRACE:
@ -1270,7 +1270,7 @@ void menuModelSetup(uint8_t event)
}
case ITEM_MODEL_THROTTLE_TRIM:
g_model.thrTrim = onoffMenuItem(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event);
ON_OFF_MENU_ITEM(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event);
break;
#if defined(CPUARM)
@ -1279,7 +1279,7 @@ void menuModelSetup(uint8_t event)
break;
case ITEM_MODEL_CHECKLIST_DISPLAY:
g_model.displayChecklist = onoffMenuItem(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST, attr, event);
ON_OFF_MENU_ITEM(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST, attr, event);
break;
#endif
@ -1823,7 +1823,7 @@ void menuModelSetup(uint8_t event)
#if defined(CPUARM) && defined(PXX)
if (IS_PXX_RANGE_CHECK_ENABLE()) {
displayPopup("RSSI: ");
lcd_outdezAtt(16+4*FW, 5*FH, frskyData.rssi[0].value, BOLD);
lcd_outdezAtt(16+4*FW, 5*FH, TELEMETRY_RSSI(), BOLD);
}
#endif
}
@ -3086,7 +3086,7 @@ void menuModelExpoOne(uint8_t event)
case EXPO_FIELD_SCALE:
lcd_putsLeft(y, STR_SCALE);
putsTelemetryChannel(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw - MIXSRC_FIRST_TELEM, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr);
putsTelemetryChannelValue(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw - MIXSRC_FIRST_TELEM, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr);
if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL);
break;
#endif
@ -3172,7 +3172,7 @@ void menuModelExpoOne(uint8_t event)
#if defined(PCBTARANIS)
int x512 = getValue(ed->srcRaw);
if (ed->srcRaw >= MIXSRC_FIRST_TELEM) {
putsTelemetryChannel(LCD_W-8, 6*FH, ed->srcRaw - MIXSRC_FIRST_TELEM, x512, 0);
putsTelemetryChannelValue(LCD_W-8, 6*FH, ed->srcRaw - MIXSRC_FIRST_TELEM, x512, 0);
if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale);
}
else {
@ -4598,7 +4598,7 @@ void menuModelLogicalSwitchOne(uint8_t event)
else {
#if defined(FRSKY)
if (v1_val >= MIXSRC_FIRST_TELEM) {
putsTelemetryChannel(CSWONE_2ND_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), attr|LEFT);
putsTelemetryChannelValue(CSWONE_2ND_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), attr|LEFT);
v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1);
if (cs->func == LS_FUNC_DIFFEGREATER)
v2_min = -v2_max;
@ -4708,7 +4708,7 @@ void menuModelLogicalSwitches(uint8_t event)
uint8_t v1 = cs->v1;
putsMixerSource(CSW_2ND_COLUMN, y, v1, 0);
if (v1 >= MIXSRC_FIRST_TELEM) {
putsTelemetryChannel(CSW_3RD_COLUMN, y, v1 - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT);
putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1 - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT);
}
else {
lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT);
@ -4864,15 +4864,19 @@ void menuModelLogicalSwitches(uint8_t event)
putsMixerSource(CSW_2ND_COLUMN, y, v1_val, attr1);
if (horz == 1) {
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE);
INCDEC_ENABLE_CHECK(isSourceAvailable);
INCDEC_ENABLE_CHECK(isSourceAvailableInCustomSwitches);
}
else {
INCDEC_SET_FLAG(EE_MODEL);
INCDEC_ENABLE_CHECK(NULL);
}
#if defined(FRSKY)
#if defined(CPUARM)
putsChannelValue(CSW_3RD_COLUMN, y, v1_val, cs->v2, LEFT|attr2);
v2_min = -30000;
v2_max = 30000;
#elif defined(FRSKY)
if (v1_val >= MIXSRC_FIRST_TELEM) {
putsTelemetryChannel(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2);
putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2);
v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1);
#if defined(CPUARM)
if (cs->func == LS_FUNC_DIFFEGREATER)
@ -4916,7 +4920,7 @@ void menuModelLogicalSwitches(uint8_t event)
}
#else
if (v1_val >= MIXSRC_FIRST_TELEM) {
putsTelemetryChannel(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2);
putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2);
v2_min = -128; v2_max = 127;
}
else {
@ -5001,8 +5005,6 @@ void menuModelLogicalSwitches(uint8_t event)
getvalue_t x = getValue(v1_val);
if (v1_val < MIXSRC_GVAR1)
cs->v2 = calcRESXto100(x);
else if (v1_val - MIXSRC_FIRST_TELEM + 1 == TELEM_ALT)
cs->v2 *= 100;
eeDirty(EE_MODEL);
}
#endif
@ -5092,7 +5094,7 @@ void onCustomFunctionsMenu(const char *result)
CustomFunctionData * cfn;
uint8_t eeFlags;
if (g_menuStack[0] == menuModelCustomFunctions) {
if (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions) {
cfn = &g_model.customFn[sub];
eeFlags = EE_MODEL;
}
@ -5320,7 +5322,7 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu
break;
}
else if (func == FUNC_PLAY_VALUE) {
val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1;
val_max = MIXSRC_LAST_TELEM;
putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr);
INCDEC_ENABLE_CHECK(isSourceAvailable);
}
@ -5643,6 +5645,7 @@ void menuModelCustomScripts(uint8_t event)
enum menuModelTelemetryItems {
CASE_CPUARM(ITEM_TELEMETRY_PROTOCOL_TYPE)
#if !defined(CPUARM)
ITEM_TELEMETRY_A1_LABEL,
ITEM_TELEMETRY_A1_RANGE,
ITEM_TELEMETRY_A1_OFFSET,
@ -5653,26 +5656,50 @@ enum menuModelTelemetryItems {
ITEM_TELEMETRY_A2_OFFSET,
ITEM_TELEMETRY_A2_ALARM1,
ITEM_TELEMETRY_A2_ALARM2,
#if defined(CPUARM)
ITEM_TELEMETRY_A3_LABEL,
ITEM_TELEMETRY_A3_RANGE,
ITEM_TELEMETRY_A3_OFFSET,
ITEM_TELEMETRY_A3_ALARM1,
ITEM_TELEMETRY_A3_ALARM2,
ITEM_TELEMETRY_A4_LABEL,
ITEM_TELEMETRY_A4_RANGE,
ITEM_TELEMETRY_A4_OFFSET,
ITEM_TELEMETRY_A4_ALARM1,
ITEM_TELEMETRY_A4_ALARM2,
#endif
ITEM_TELEMETRY_RSSI_LABEL,
ITEM_TELEMETRY_RSSI_ALARM1,
ITEM_TELEMETRY_RSSI_ALARM2,
#if defined(CPUARM)
ITEM_TELEMETRY_SENSORS_LABEL,
ITEM_TELEMETRY_SENSOR1,
ITEM_TELEMETRY_SENSOR2,
ITEM_TELEMETRY_SENSOR3,
ITEM_TELEMETRY_SENSOR4,
ITEM_TELEMETRY_SENSOR5,
ITEM_TELEMETRY_SENSOR6,
ITEM_TELEMETRY_SENSOR7,
ITEM_TELEMETRY_SENSOR8,
ITEM_TELEMETRY_SENSOR9,
ITEM_TELEMETRY_SENSOR10,
ITEM_TELEMETRY_SENSOR11,
ITEM_TELEMETRY_SENSOR12,
ITEM_TELEMETRY_SENSOR13,
ITEM_TELEMETRY_SENSOR14,
ITEM_TELEMETRY_SENSOR15,
ITEM_TELEMETRY_SENSOR16,
ITEM_TELEMETRY_SENSOR17,
ITEM_TELEMETRY_SENSOR18,
ITEM_TELEMETRY_SENSOR19,
ITEM_TELEMETRY_SENSOR20,
ITEM_TELEMETRY_SENSOR21,
ITEM_TELEMETRY_SENSOR22,
ITEM_TELEMETRY_SENSOR23,
ITEM_TELEMETRY_SENSOR24,
ITEM_TELEMETRY_SENSOR25,
ITEM_TELEMETRY_SENSOR26,
ITEM_TELEMETRY_SENSOR27,
ITEM_TELEMETRY_SENSOR28,
ITEM_TELEMETRY_SENSOR29,
ITEM_TELEMETRY_SENSOR30,
ITEM_TELEMETRY_SENSOR31,
ITEM_TELEMETRY_SENSOR32,
ITEM_TELEMETRY_NEWSENSOR,
#endif
#if !defined(CPUARM)
#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
ITEM_TELEMETRY_USR_LABEL,
#if !defined(PCBTARANIS)
ITEM_TELEMETRY_USR_PROTO,
#endif
ITEM_TELEMETRY_USR_BLADES,
#endif
ITEM_TELEMETRY_USR_VOLTAGE_SOURCE,
@ -5680,8 +5707,6 @@ enum menuModelTelemetryItems {
#if defined(FAS_OFFSET) || !defined(CPUM64)
ITEM_TELEMETRY_FAS_OFFSET,
#endif
#if defined(CPUARM)
ITEM_TELEMTETRY_PERSISTENT_MAH,
#endif
CASE_VARIO(ITEM_TELEMETRY_VARIO_LABEL)
#if defined(VARIO)
@ -5690,6 +5715,7 @@ enum menuModelTelemetryItems {
CASE_VARIO(ITEM_TELEMETRY_VARIO_RANGE)
#if defined(PCBTARANIS)
ITEM_TELEMETRY_TOP_BAR_LABEL,
ITEM_TELEMETRY_TOP_BAR_VOLTAGE,
ITEM_TELEMETRY_TOP_BAR_ALTITUDE,
#endif
ITEM_TELEMETRY_SCREEN_LABEL1,
@ -5717,21 +5743,13 @@ enum menuModelTelemetryItems {
ITEM_TELEMETRY_MAX
};
#if defined(PCBTARANIS)
#define USRDATA_LINES (uint8_t)-1, 0,
#elif defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
#define USRDATA_LINES (uint8_t)-1, 0, 0,
#else
#define USRDATA_LINES
#endif
#if defined(FRSKY)
#if LCD_W >= 212
#define TELEM_COL1 (1*FW)
#define TELEM_COL2 (16*FW)
#define TELEM_COL3 (28*FW)
#define TELEM_BARS_COLMIN (3*FW+56)
#define TELEM_BARS_COLMAX (20*FW-3)
#define TELEM_BARS_COLMIN TELEM_COL2
#define TELEM_BARS_COLMAX TELEM_COL3
#define TELEM_SCRTYPE_COL TELEM_COL2
#else
#define TELEM_COL1 INDENT_WIDTH
@ -5747,12 +5765,34 @@ enum menuModelTelemetryItems {
#define IS_RANGE_DEFINED(k) (g_model.frsky.channels[k].ratio > 0)
#if defined(PCBTARANIS)
#define CHANNEL_ROWS(x) LABEL(CHANNEL), IS_RANGE_DEFINED(x) ? (uint8_t)1 : (uint8_t)0, IS_RANGE_DEFINED(x) ? (uint8_t)0 : HIDDEN_ROW, IS_RANGE_DEFINED(x) ? (uint8_t)0 : HIDDEN_ROW, IS_RANGE_DEFINED(x) ? (uint8_t)0 : HIDDEN_ROW
#define RSSI_ROWS LABEL(RSSI), 0, 0
#if defined(CPUARM)
#define CHANNELS_ROWS
#define SENSOR_ROWS(x) (isTelemetryFieldAvailable(x) ? (uint8_t)0 : HIDDEN_ROW)
#define SENSORS_ROWS LABEL(Sensors), SENSOR_ROWS(0), SENSOR_ROWS(1), SENSOR_ROWS(2), SENSOR_ROWS(3), SENSOR_ROWS(4), SENSOR_ROWS(5), SENSOR_ROWS(6), SENSOR_ROWS(7), SENSOR_ROWS(8), SENSOR_ROWS(9), SENSOR_ROWS(10), SENSOR_ROWS(11), SENSOR_ROWS(12), SENSOR_ROWS(13), SENSOR_ROWS(14), SENSOR_ROWS(15), SENSOR_ROWS(16), SENSOR_ROWS(17), SENSOR_ROWS(18), SENSOR_ROWS(19), SENSOR_ROWS(20), SENSOR_ROWS(21), SENSOR_ROWS(22), SENSOR_ROWS(23), SENSOR_ROWS(24), SENSOR_ROWS(25), SENSOR_ROWS(26), SENSOR_ROWS(27), SENSOR_ROWS(28), SENSOR_ROWS(29), SENSOR_ROWS(30), SENSOR_ROWS(31), 0,
#else
#define CHANNEL_ROWS(x) LABEL(CHANNEL), 1, 0, 2, 2
#define RSSI_ROWS LABEL(RSSI), 1, 1
#define CHANNELS_ROWS CHANNEL_ROWS(0), CHANNEL_ROWS(1),
#define SENSORS_ROWS
#endif
#if defined(FAS_OFFSET) || !defined(CPUM64)
#define IF_FAS_OFFSET(x) x,
#else
#define IF_FAS_OFFSET(x)
#endif
#if defined(CPUARM)
#define USRDATA_ROWS
#elif defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
#define USRDATA_ROWS LABEL(UsrData), 0, 0, 0, 0, IF_FAS_OFFSET(0)
#else
#define USRDATA_ROWS 0, 0, IF_FAS_OFFSET(0)
#endif
#if defined(PCBTARANIS)
#define RSSI_ROWS LABEL(RSSI), 0, 0,
#else
#define RSSI_ROWS LABEL(RSSI), 1, 1,
#endif
#if defined(LUA)
@ -5769,12 +5809,6 @@ enum menuModelTelemetryItems {
#define VARIO_RANGE_ROWS 3
#endif
#if defined(FAS_OFFSET) || !defined(CPUM64)
#define IF_FAS_OFFSET(x) x,
#else
#define IF_FAS_OFFSET(x)
#endif
#if defined(PCBTARANIS)
#define TELEMETRY_TYPE_ROWS (g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF && g_model.externalModule == MODULE_TYPE_PPM) ? (uint8_t)0 : HIDDEN_ROW,
#elif defined(CPUARM)
@ -5791,12 +5825,286 @@ enum menuModelTelemetryItems {
#endif
#define TELEMETRY_SCREEN_ROWS(x) SCREEN_TYPE_ROWS, TELEMETRY_SCREEN_LINE(x), TELEMETRY_SCREEN_LINE(x), TELEMETRY_SCREEN_LINE(x), TELEMETRY_SCREEN_LINE(x)
#define TELEMETRY_CURRENT_EDIT_SCREEN(k) (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 0 : (k < ITEM_TELEMETRY_SCREEN_LABEL3 ? 1 : (k < ITEM_TELEMETRY_SCREEN_LABEL4 ? 2 : 3)))
#define TELEMETRY_CURRENT_EDIT_CHANNEL(k) (k >= ITEM_TELEMETRY_A4_LABEL ? TELEM_ANA_A4 : (k >= ITEM_TELEMETRY_A3_LABEL ? TELEM_ANA_A3 : (k >= ITEM_TELEMETRY_A2_LABEL ? TELEM_ANA_A2 : TELEM_ANA_A1)))
#else
#define TELEMETRY_SCREEN_ROWS(x) SCREEN_TYPE_ROWS, 2, 2, 2, 2
#define TELEMETRY_CURRENT_EDIT_CHANNEL(k) (k >= ITEM_TELEMETRY_A2_LABEL ? TELEM_ANA_A2 : TELEM_ANA_A1)
#endif
#if defined(CPUARM)
enum SensorFields {
SENSOR_FIELD_NAME,
SENSOR_FIELD_TYPE,
SENSOR_FIELD_ID,
SENSOR_FIELD_FORMULA=SENSOR_FIELD_ID,
SENSOR_FIELD_UNIT,
SENSOR_FIELD_PRECISION,
SENSOR_FIELD_PARAM1,
SENSOR_FIELD_PARAM2,
SENSOR_FIELD_PARAM3,
SENSOR_FIELD_PARAM4,
SENSOR_FIELD_INPUT_FLAGS,
SENSOR_FIELD_LOGS,
SENSOR_FIELD_MAX
};
bool isSensorUnit(int sensor, uint8_t unit)
{
if (sensor == 0)
return true;
sensor -= 1;
return g_model.telemetrySensors[sensor].unit == unit;
}
bool isCellsSensor(int sensor)
{
return isSensorUnit(sensor, UNIT_CELLS);
}
bool isGPSSensor(int sensor)
{
return isSensorUnit(sensor, UNIT_GPS);
}
bool isAltSensor(int sensor)
{
return isSensorUnit(sensor, UNIT_DIST);
}
bool isVoltsSensor(int sensor)
{
return isSensorUnit(sensor, UNIT_VOLTS);
}
bool isCurrentSensor(int sensor)
{
return isSensorUnit(sensor, UNIT_AMPS);
}
bool isSensorAvailable(int sensor)
{
if (sensor == 0)
return true;
sensor -= 1;
return isTelemetryFieldAvailable(sensor);
}
#define SENSOR_2ND_COLUMN (12*FW)
#define SENSOR_3RD_COLUMN (18*FW)
#define SENSOR_UNIT_ROWS (sensor->type == TELEM_TYPE_CALCULATED && sensor->formula >= TELEM_FORMULA_CELL) ? HIDDEN_ROW : ((sensor->unit == UNIT_GPS || sensor->unit == UNIT_DATETIME) ? HIDDEN_ROW : (uint8_t)0)
#define SENSOR_PREC_ROWS (sensor->type == TELEM_TYPE_CALCULATED && sensor->formula >= TELEM_FORMULA_CELL) ? HIDDEN_ROW : ((sensor->unit == UNIT_GPS || sensor->unit == UNIT_DATETIME) ? HIDDEN_ROW : (uint8_t)0)
#define SENSOR_PARAM1_ROWS (sensor->unit == UNIT_GPS || sensor->unit == UNIT_DATETIME) ? HIDDEN_ROW : (uint8_t)0
#define SENSOR_PARAM2_ROWS (sensor->unit == UNIT_GPS || sensor->unit == UNIT_DATETIME || (sensor->type==TELEM_TYPE_CALCULATED && sensor->formula==TELEM_FORMULA_CONSUMPTION)) ? HIDDEN_ROW : (uint8_t)0
#define SENSOR_PARAM3_ROWS (sensor->type == TELEM_TYPE_CALCULATED && sensor->formula < TELEM_FORMULA_MULTIPLY) ? (uint8_t)0 : HIDDEN_ROW
#define SENSOR_PARAM4_ROWS (sensor->type == TELEM_TYPE_CALCULATED && sensor->formula < TELEM_FORMULA_MULTIPLY) ? (uint8_t)0 : HIDDEN_ROW
void menuModelSensor(uint8_t event)
{
TelemetrySensor * sensor = & g_model.telemetrySensors[s_currIdx];
SUBMENU(STR_MENUSENSOR, SENSOR_FIELD_MAX, {0, 0, sensor->type == TELEM_TYPE_CALCULATED ? (uint8_t)0 : (uint8_t)1, SENSOR_UNIT_ROWS, SENSOR_PREC_ROWS, SENSOR_PARAM1_ROWS, SENSOR_PARAM2_ROWS, SENSOR_PARAM3_ROWS, SENSOR_PARAM4_ROWS, 0 });
lcd_outdezAtt(PSIZE(TR_MENUSENSOR)*FW+1, 0, s_currIdx+1, INVERS|LEFT);
putsTelemetryChannelValue(SENSOR_2ND_COLUMN, 0, s_currIdx, getValue(MIXSRC_FIRST_TELEM+3*s_currIdx), LEFT);
int8_t sub = m_posVert;
for (uint8_t i=0; i<LCD_LINES-1; i++) {
coord_t y = MENU_TITLE_HEIGHT + 1 + i*FH;
uint8_t k = i + s_pgOfs;
for (int j=0; j<k; j++) {
if (mstate_tab[j+1] == HIDDEN_ROW)
k++;
}
uint8_t attr = (sub==k ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
switch (k) {
case SENSOR_FIELD_NAME:
editSingleName(SENSOR_2ND_COLUMN, y, STR_NAME, sensor->label, TELEM_LABEL_LEN, event, attr);
break;
case SENSOR_FIELD_TYPE:
sensor->type = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_TYPE, "\012Custom\0 Calculated", sensor->type, 0, 1, attr, event);
if (attr && checkIncDec_Ret) {
sensor->instance = 0;
if (sensor->type == TELEM_TYPE_CALCULATED) {
sensor->param = 0;
sensor->inputFlags = 0;
}
}
break;
case SENSOR_FIELD_ID:
if (sensor->type == TELEM_TYPE_CUSTOM) {
lcd_putsLeft(y, STR_ID);
lcd_outhex4(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(m_posHorz==0 ? attr : 0));
lcd_outdezAtt(SENSOR_3RD_COLUMN, y, sensor->instance, LEFT|(m_posHorz==1 ? attr : 0));
if (attr) {
switch (m_posHorz) {
case 0:
CHECK_INCDEC_MODELVAR_ZERO(event, sensor->id, 0xffff);
break;
case 1:
CHECK_INCDEC_MODELVAR_ZERO(event, sensor->instance, 0xff);
break;
}
}
}
else {
sensor->formula = selectMenuItem(SENSOR_2ND_COLUMN, y, "Formula", "\010Add\0 Average\0Min\0 Max\0 MultiplyCell\0 ConsumptDistance", sensor->formula, 0, TELEM_FORMULA_DIST, attr, event);
if (attr && checkIncDec_Ret) {
sensor->param = 0;
if (sensor->formula == TELEM_FORMULA_CELL) {
sensor->unit = UNIT_VOLTS;
sensor->prec = 2;
}
else if (sensor->formula == TELEM_FORMULA_DIST) {
sensor->unit = UNIT_DIST;
sensor->prec = 0;
}
else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) {
sensor->unit = UNIT_MAH;
sensor->prec = 0;
}
}
}
break;
case SENSOR_FIELD_UNIT:
lcd_putsLeft(y, "Unit");
// TODO flash saving with selectMenuItem where I copied those 2 lines?
lcd_putsiAtt(SENSOR_2ND_COLUMN, y, STR_VTELEMUNIT, sensor->unit, attr);
if (attr) {
CHECK_INCDEC_MODELVAR_ZERO(event, sensor->unit, UNIT_MAX);
if (checkIncDec_Ret) {
telemetryItems[s_currIdx].clear();
}
}
break;
case SENSOR_FIELD_PRECISION:
sensor->prec = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_PRECISION, "\005PREC0PREC1PREC2", sensor->prec, 0, 2, attr, event);
if (attr && checkIncDec_Ret) {
telemetryItems[s_currIdx].clear();
}
break;
case SENSOR_FIELD_PARAM1:
if (sensor->type == TELEM_TYPE_CALCULATED) {
if (sensor->formula == TELEM_FORMULA_CELL) {
lcd_putsLeft(y, "Cells sensor");
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->cell.source ? MIXSRC_FIRST_TELEM+3*(sensor->cell.source-1) : 0, attr);
if (attr) {
sensor->cell.source = checkIncDec(event, sensor->cell.source, 0, TELEM_VALUES_MAX, EE_MODEL|NO_INCDEC_MARKS, isCellsSensor);
}
break;
}
else if (sensor->formula == TELEM_FORMULA_DIST) {
lcd_putsLeft(y, "GPS sensor");
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->dist.gps ? MIXSRC_FIRST_TELEM+3*(sensor->dist.gps-1) : 0, attr);
if (attr) {
sensor->dist.gps = checkIncDec(event, sensor->dist.gps, 0, TELEM_VALUES_MAX, EE_MODEL|NO_INCDEC_MARKS, isGPSSensor);
}
break;
}
else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) {
lcd_putsLeft(y, "Amps sensor");
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->consumption.source ? MIXSRC_FIRST_TELEM+3*(sensor->consumption.source-1) : 0, attr);
if (attr) {
sensor->consumption.source = checkIncDec(event, sensor->consumption.source, 0, TELEM_VALUES_MAX, EE_MODEL|NO_INCDEC_MARKS, isCurrentSensor);
}
break;
}
}
else {
lcd_putsLeft(y, "Ratio");
if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.ratio, 0, 30000);
if (sensor->custom.ratio == 0)
lcd_putcAtt(SENSOR_2ND_COLUMN, y, '-', attr);
else
lcd_outdezAtt(SENSOR_2ND_COLUMN, y, sensor->custom.ratio, LEFT|attr|PREC1);
break;
}
// no break
case SENSOR_FIELD_PARAM2:
if (sensor->type == TELEM_TYPE_CALCULATED) {
if (sensor->formula == TELEM_FORMULA_CELL) {
sensor->cell.index = selectMenuItem(SENSOR_2ND_COLUMN, y, "Cell index", "\007Lowest\0001\0 2\0 3\0 4\0 5\0 6\0 Highest", sensor->cell.index, 0, 7, attr, event);
break;
}
else if (sensor->formula == TELEM_FORMULA_DIST) {
lcd_putsLeft(y, "Alt sensor");
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->dist.alt ? MIXSRC_FIRST_TELEM+3*(sensor->dist.alt-1) : 0, attr);
if (attr) {
sensor->dist.alt = checkIncDec(event, sensor->dist.alt, 0, TELEM_VALUES_MAX, EE_MODEL|NO_INCDEC_MARKS, isAltSensor);
}
break;
}
}
else {
lcd_putsLeft(y, NO_INDENT(STR_OFFSET));
if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.offset, -30000, +30000);
if (sensor->prec > 0) attr |= (sensor->prec == 2 ? PREC2 : PREC1);
lcd_outdezAtt(SENSOR_2ND_COLUMN, y, sensor->custom.offset, LEFT|attr);
break;
}
// no break
case SENSOR_FIELD_PARAM3:
// no break
case SENSOR_FIELD_PARAM4:
{
putsStrIdx(0, y, "Source", k-SENSOR_FIELD_PARAM1+1);
uint8_t & source = sensor->calc.sources[k-SENSOR_FIELD_PARAM1];
putsMixerSource(SENSOR_2ND_COLUMN, y, source ? MIXSRC_FIRST_TELEM+3*(source-1) : 0, attr);
if (attr) {
source = checkIncDec(event, source, 0, TELEM_VALUES_MAX, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable);
}
break;
}
case SENSOR_FIELD_INPUT_FLAGS:
sensor->inputFlags = selectMenuItem(SENSOR_2ND_COLUMN, y, "Options", "\013None\0 ""Auto Offset""Filter\0", sensor->inputFlags, 0, TELEM_INPUT_FLAGS_MAX, attr, event);
break;
case SENSOR_FIELD_LOGS:
ON_OFF_MENU_ITEM(sensor->logs, SENSOR_2ND_COLUMN, y, "Logs", attr, event);
break;
}
}
}
void onSensorMenu(const char *result)
{
uint8_t index = m_posVert - 1 - ITEM_TELEMETRY_SENSOR1;
if (index < TELEM_VALUES_MAX) {
if (result == STR_EDIT) {
pushMenu(menuModelSensor);
}
else if (result == STR_DELETE) {
delTelemetryIndex(index);
index += 1;
if (index<TELEM_VALUES_MAX && isTelemetryFieldAvailable(index))
m_posVert += 1;
else
m_posVert = 1+ITEM_TELEMETRY_NEWSENSOR;
}
}
}
#endif
#if defined(LUA)
void onTelemetryScriptFileSelectionMenu(const char *result)
{
@ -5820,7 +6128,7 @@ void onTelemetryScriptFileSelectionMenu(const char *result)
void menuModelTelemetry(uint8_t event)
{
MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX+1, {0, TELEMETRY_TYPE_ROWS CHANNEL_ROWS(0), CHANNEL_ROWS(1), CASE_CPUARM(CHANNEL_ROWS(2)) CASE_CPUARM(CHANNEL_ROWS(3)) RSSI_ROWS, USRDATA_LINES 0, 0, IF_FAS_OFFSET(0) CASE_CPUARM(0) CASE_VARIO(LABEL(Vario)) CASE_VARIO(0) CASE_VARIO(VARIO_RANGE_ROWS) CASE_PCBTARANIS(LABEL(TopBar)) CASE_PCBTARANIS(0) TELEMETRY_SCREEN_ROWS(0), TELEMETRY_SCREEN_ROWS(1), CASE_CPUARM(TELEMETRY_SCREEN_ROWS(2)) CASE_CPUARM(TELEMETRY_SCREEN_ROWS(3))});
MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX+1, {0, TELEMETRY_TYPE_ROWS CHANNELS_ROWS RSSI_ROWS SENSORS_ROWS USRDATA_ROWS CASE_VARIO(LABEL(Vario)) CASE_VARIO(0) CASE_VARIO(VARIO_RANGE_ROWS) CASE_PCBTARANIS(LABEL(TopBar)) CASE_PCBTARANIS(0) CASE_PCBTARANIS(0) TELEMETRY_SCREEN_ROWS(0), TELEMETRY_SCREEN_ROWS(1), CASE_CPUARM(TELEMETRY_SCREEN_ROWS(2)) CASE_CPUARM(TELEMETRY_SCREEN_ROWS(3))});
uint8_t sub = m_posVert - 1;
@ -5848,9 +6156,49 @@ void menuModelTelemetry(uint8_t event)
uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
uint8_t attr = (sub == k ? blink : 0);
#if !defined(CPUARM)
uint8_t ch = TELEMETRY_CURRENT_EDIT_CHANNEL(k);
FrSkyChannelData & channel = g_model.frsky.channels[ch];
uint8_t dest = TELEM_A1-1+ch;
#endif
#if defined(CPUARM)
if (k>=ITEM_TELEMETRY_SENSOR1 && k<ITEM_TELEMETRY_SENSOR1+TELEM_VALUES_MAX) {
int index = k-ITEM_TELEMETRY_SENSOR1;
lcd_outdezAtt(INDENT_WIDTH, y, index+1, LEFT|attr);
lcd_putcAtt(lcdLastPos, y, ':', attr);
lcd_putsnAtt(3*FW, y, g_model.telemetrySensors[index].label, TELEM_LABEL_LEN, ZCHAR);
if (telemetryItems[index].isFresh()) {
lcd_putc(10*FW, y, '*');
}
TelemetryItem & telemetryItem = telemetryItems[index];
if (telemetryItem.isAvailable()) {
bool isOld = telemetryItem.isOld();
lcdNextPos = TELEM_COL2;
if (isOld) lcd_putc(lcdNextPos, y, '[');
putsTelemetryChannelValue(lcdNextPos, y, index, getValue(MIXSRC_FIRST_TELEM+3*index), LEFT);
if (isOld) lcd_putc(lcdLastPos, y, ']');
}
else {
lcd_putsAtt(TELEM_COL2, y, "---", 0); // TODO shortcut
}
if (attr) {
s_editMode = 0;
s_currIdx = index;
if (event == EVT_KEY_LONG(KEY_ENTER)) {
killEvents(event);
MENU_ADD_ITEM(STR_EDIT);
MENU_ADD_ITEM(STR_DELETE);
menuHandler = onSensorMenu;
}
else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
pushMenu(menuModelSensor);
}
}
}
else
#endif
switch (k) {
#if defined(CPUARM)
@ -5859,37 +6207,36 @@ void menuModelTelemetry(uint8_t event)
break;
#endif
#if defined(CPUARM)
case ITEM_TELEMETRY_SENSORS_LABEL:
lcd_putsLeft(y, STR_TELEMETRY_SENSORS);
break;
case ITEM_TELEMETRY_NEWSENSOR:
lcd_putsAtt(0, y, STR_TELEMETRY_NEWSENSOR, attr);
if (attr && event==EVT_KEY_BREAK(KEY_ENTER)) {
s_editMode = 0;
s_currIdx = availableTelemetryIndex();
if (s_currIdx >= 0) {
pushMenu(menuModelSensor);
}
}
break;
#endif
#if !defined(CPUARM)
case ITEM_TELEMETRY_A1_LABEL:
case ITEM_TELEMETRY_A2_LABEL:
#if defined(CPUARM)
case ITEM_TELEMETRY_A3_LABEL:
case ITEM_TELEMETRY_A4_LABEL:
#endif
lcd_putsLeft(y, STR_ACHANNEL);
lcd_outdezAtt(2*FW, y, ch+1, 0);
#if defined(CPUARM)
if (channel.ratio != 0)
#endif
putsTelemetryChannel(TELEM_COL2+6*FW, y, dest, frskyData.analog[ch].value, LEFT);
putsTelemetryChannelValue(TELEM_COL2+6*FW, y, dest, frskyData.analog[ch].value, LEFT);
break;
case ITEM_TELEMETRY_A1_RANGE:
case ITEM_TELEMETRY_A2_RANGE:
#if defined(CPUARM)
case ITEM_TELEMETRY_A3_RANGE:
case ITEM_TELEMETRY_A4_RANGE:
#endif
lcd_putsLeft(y, STR_RANGE);
#if defined(CPUARM)
if (channel.ratio == 0) {
lcd_putsiAtt(TELEM_COL2, y, STR_VCSWFUNC, 0, attr);
}
else
#endif
{
putsTelemetryChannel(TELEM_COL2, y, dest, 255-channel.offset, (m_posHorz<=0 ? attr : 0)|NO_UNIT|LEFT);
putsTelemetryChannelValue(TELEM_COL2, y, dest, 255-channel.offset, (m_posHorz<=0 ? attr : 0)|NO_UNIT|LEFT);
lcd_putsiAtt(lcdLastPos, y, STR_VTELEMUNIT, channel.type, m_posHorz!=0 ? attr : 0);
}
if (attr && (s_editMode>0 || p1valdiff)) {
if (m_posHorz == 0) {
uint16_t ratio = checkIncDec(event, channel.ratio, 0, 256, EE_MODEL);
@ -5913,12 +6260,8 @@ void menuModelTelemetry(uint8_t event)
case ITEM_TELEMETRY_A1_OFFSET:
case ITEM_TELEMETRY_A2_OFFSET:
#if defined(CPUARM)
case ITEM_TELEMETRY_A3_OFFSET:
case ITEM_TELEMETRY_A4_OFFSET:
#endif
lcd_putsLeft(y, STR_OFFSET);
putsTelemetryChannel(TELEM_COL2, y, dest, 0, LEFT|attr);
putsTelemetryChannelValue(TELEM_COL2, y, dest, 0, LEFT|attr);
if (attr) channel.offset = checkIncDec(event, channel.offset, -256, 256, EE_MODEL);
break;
@ -5926,29 +6269,12 @@ void menuModelTelemetry(uint8_t event)
case ITEM_TELEMETRY_A1_ALARM2:
case ITEM_TELEMETRY_A2_ALARM1:
case ITEM_TELEMETRY_A2_ALARM2:
#if defined(CPUARM)
case ITEM_TELEMETRY_A3_ALARM1:
case ITEM_TELEMETRY_A3_ALARM2:
case ITEM_TELEMETRY_A4_ALARM1:
case ITEM_TELEMETRY_A4_ALARM2:
#endif
{
#if defined(CPUARM)
uint8_t alarm = ((k==ITEM_TELEMETRY_A1_ALARM1 || k==ITEM_TELEMETRY_A2_ALARM1 || k==ITEM_TELEMETRY_A3_ALARM1 || k==ITEM_TELEMETRY_A4_ALARM1) ? 0 : 1);
#else
uint8_t alarm = ((k==ITEM_TELEMETRY_A1_ALARM1 || k==ITEM_TELEMETRY_A2_ALARM1) ? 0 : 1);
#endif
#if defined(PCBTARANIS)
lcd_putsLeft(y, (alarm==0 ? STR_LOWALARM : STR_CRITICALALARM));
putsTelemetryChannel(TELEM_COL2, y, dest, channel.alarms_value[alarm], LEFT|attr);
if (attr && (s_editMode>0 || p1valdiff)) {
channel.alarms_value[alarm] = checkIncDec(event, channel.alarms_value[alarm], 0, 255, EE_MODEL);
}
#else
lcd_putsLeft(y, STR_ALARM);
lcd_putsiAtt(TELEM_COL2, y, STR_VALARM, ALARM_LEVEL(ch, alarm), m_posHorz<=0 ? attr : 0);
lcd_putsiAtt(TELEM_COL2+4*FW, y, STR_VALARMFN, ALARM_GREATER(ch, alarm), (m_posHorz<0 || m_posHorz==1) ? attr : 0);
putsTelemetryChannel(TELEM_COL2+6*FW, y, dest, channel.alarms_value[alarm], ((m_posHorz<0 || m_posHorz==2) ? attr : 0) | LEFT);
putsTelemetryChannelValue(TELEM_COL2+6*FW, y, dest, channel.alarms_value[alarm], ((m_posHorz<0 || m_posHorz==2) ? attr : 0) | LEFT);
if (attr && (s_editMode>0 || p1valdiff)) {
uint8_t t;
@ -5969,9 +6295,9 @@ void menuModelTelemetry(uint8_t event)
break;
}
}
#endif
break;
}
#endif
case ITEM_TELEMETRY_RSSI_LABEL:
lcd_putsLeft(y, PSTR("RSSI"));
@ -6006,38 +6332,28 @@ void menuModelTelemetry(uint8_t event)
break;
}
#if !defined(CPUARM)
#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
case ITEM_TELEMETRY_USR_LABEL:
lcd_putsLeft(y, STR_USRDATA);
break;
#if !defined(PCBTARANIS)
case ITEM_TELEMETRY_USR_PROTO:
lcd_putsLeft(y, STR_PROTO);
lcd_putsiAtt(TELEM_COL2, y, STR_VTELPROTO, g_model.frsky.usrProto, attr);
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.usrProto, USR_PROTO_LAST);
break;
#endif
case ITEM_TELEMETRY_USR_BLADES:
lcd_putsLeft(y, STR_BLADES);
#if defined(CPUARM)
lcd_outdezAtt(TELEM_COL2, y, 2+g_model.frsky.blades, attr|LEFT);
if (attr) CHECK_INCDEC_MODELVAR(event, g_model.frsky.blades, MIN_BLADES, MAX_BLADES);
#else
lcd_outdezAtt(TELEM_COL2+FWNUM, y, 2+g_model.frsky.blades, attr);
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, MAX_BLADES);
#endif
break;
#endif
case ITEM_TELEMETRY_USR_VOLTAGE_SOURCE:
lcd_putsLeft(y, STR_VOLTAGE);
#if defined(CPUARM)
lcd_putsiAtt(TELEM_COL2, y, STR_VOLTSRC, g_model.frsky.voltsSource, attr);
#else
lcd_putsiAtt(TELEM_COL2, y, STR_AMPSRC, g_model.frsky.voltsSource+1, attr);
#endif
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.voltsSource, FRSKY_VOLTS_SOURCE_LAST);
break;
@ -6056,11 +6372,6 @@ void menuModelTelemetry(uint8_t event)
if (attr) g_model.frsky.fasOffset = checkIncDec(event, g_model.frsky.fasOffset, -120, 120, EE_MODEL);
break;
#endif
#if defined(CPUARM)
case ITEM_TELEMTETRY_PERSISTENT_MAH:
g_model.frsky.mAhPersistent = onoffMenuItem(g_model.frsky.mAhPersistent, TELEM_COL2, y, STR_PERSISTENT_MAH, attr, event);
break;
#endif
#if defined(VARIO)
@ -6070,8 +6381,15 @@ void menuModelTelemetry(uint8_t event)
case ITEM_TELEMETRY_VARIO_SOURCE:
lcd_putsLeft(y, STR_SOURCE);
#if defined(CPUARM)
putsMixerSource(TELEM_COL2, y, g_model.frsky.varioSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.varioSource-1) : 0, attr);
if (attr) {
g_model.frsky.varioSource = checkIncDec(event, g_model.frsky.varioSource, 0, TELEM_VALUES_MAX, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable);
}
#else
lcd_putsiAtt(TELEM_COL2, y, STR_VARIOSRC, g_model.frsky.varioSource, attr);
if (attr) CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioSource, 0, VARIO_SOURCE_LAST);
#endif
break;
case ITEM_TELEMETRY_VARIO_RANGE:
@ -6119,8 +6437,20 @@ void menuModelTelemetry(uint8_t event)
lcd_putsLeft(y, STR_TOP_BAR);
break;
case ITEM_TELEMETRY_TOP_BAR_VOLTAGE:
lcd_putsLeft(y, STR_VOLTAGE);
putsMixerSource(TELEM_COL2, y, g_model.frsky.voltsSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.voltsSource-1) : 0, attr);
if (attr) {
g_model.frsky.voltsSource = checkIncDec(event, g_model.frsky.voltsSource, 0, TELEM_VALUES_MAX, EE_MODEL|NO_INCDEC_MARKS, isVoltsSensor);
}
break;
case ITEM_TELEMETRY_TOP_BAR_ALTITUDE:
g_model.frsky.altitudeDisplayed = onoffMenuItem(g_model.frsky.altitudeDisplayed, TELEM_COL2, y, STR_ALTITUDE, attr, event);
lcd_putsLeft(y, STR_ALTITUDE);
putsMixerSource(TELEM_COL2, y, g_model.frsky.altitudeSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.altitudeSource-1) : 0, attr);
if (attr) {
g_model.frsky.altitudeSource = checkIncDec(event, g_model.frsky.altitudeSource, 0, TELEM_VALUES_MAX, EE_MODEL|NO_INCDEC_MARKS, isAltSensor);
}
break;
#endif
@ -6222,29 +6552,53 @@ void menuModelTelemetry(uint8_t event)
#if defined(GAUGES)
if (IS_BARS_SCREEN(screenIndex)) {
FrSkyBarData & bar = g_model.frsky.screens[screenIndex].bars[lineIndex];
uint8_t barSource = bar.source;
source_t barSource = bar.source;
#if defined(CPUARM)
putsMixerSource(TELEM_COL1, y, barSource, m_posHorz==0 ? attr : 0);
if (barSource) {
putsChannelValue(TELEM_BARS_COLMIN, y, barSource, bar.barMin, (m_posHorz==1 ? attr : 0) | LEFT);
putsChannelValue(TELEM_BARS_COLMAX, y, barSource, bar.barMax, (m_posHorz==2 ? attr : 0) | LEFT);
}
#else
lcd_putsiAtt(TELEM_COL1, y, STR_VTELEMCHNS, barSource, m_posHorz==0 ? attr : 0);
if (barSource) {
putsTelemetryChannel(TELEM_BARS_COLMIN, y, barSource-1, convertBarTelemValue(barSource, bar.barMin), (m_posHorz==1 ? attr : 0) | LEFT);
putsTelemetryChannel(TELEM_BARS_COLMAX, y, barSource-1, convertBarTelemValue(barSource, 255-bar.barMax), (m_posHorz==2 ? attr : 0) | LEFT);
putsTelemetryChannelValue(TELEM_BARS_COLMIN, y, barSource-1, convertBarTelemValue(barSource, bar.barMin), (m_posHorz==1 ? attr : 0) | LEFT);
putsTelemetryChannelValue(TELEM_BARS_COLMAX, y, barSource-1, convertBarTelemValue(barSource, 255-bar.barMax), (m_posHorz==2 ? attr : 0) | LEFT);
}
#endif
else if (attr) {
MOVE_CURSOR_FROM_HERE();
}
if (attr && (s_editMode>0 || p1valdiff)) {
switch (m_posHorz) {
case 0:
bar.source = CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, barSource, TELEM_DISPLAY_MAX, isTelemetrySourceAvailable);
#if defined(CPUARM)
bar.source = CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, barSource, MIXSRC_LAST_TELEM, isSourceAvailable);
#else
bar.source = CHECK_INCDEC_MODELVAR_ZERO(event, barSource, TELEM_DISPLAY_MAX);
#endif
if (checkIncDec_Ret) {
bar.barMin = 0;
#if defined(CPUARM)
bar.barMax = 0;
#else
bar.barMax = 255 - maxBarTelemValue(bar.source);
#endif
}
break;
case 1:
#if defined(CPUARM)
bar.barMin = checkIncDec(event, bar.barMin, -30000, bar.barMax, EE_MODEL|NO_INCDEC_MARKS);
#else
bar.barMin = checkIncDec(event, bar.barMin, 0, 254-bar.barMax, EE_MODEL|NO_INCDEC_MARKS);
#endif
break;
case 2:
#if defined(CPUARM)
bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, 30000, EE_MODEL|NO_INCDEC_MARKS);
#else
bar.barMax = 255 - checkIncDec(event, 255-bar.barMax, bar.barMin+1, maxBarTelemValue(barSource), EE_MODEL|NO_INCDEC_MARKS);
#endif
break;
}
}
@ -6254,16 +6608,23 @@ void menuModelTelemetry(uint8_t event)
{
for (uint8_t c=0; c<NUM_LINE_ITEMS; c++) {
uint8_t cellAttr = (m_posHorz==c ? attr : 0);
uint8_t & value = g_model.frsky.screens[screenIndex].lines[lineIndex].sources[c];
source_t & value = g_model.frsky.screens[screenIndex].lines[lineIndex].sources[c];
#if defined(PCBTARANIS)
uint8_t pos[] = {TELEM_COL1, TELEM_COL2, TELEM_COL3};
#else
uint8_t pos[] = {INDENT_WIDTH, TELEM_COL2};
#endif
#if defined(CPUARM)
putsMixerSource(pos[c], y, value, cellAttr);
if (cellAttr && (s_editMode>0 || p1valdiff)) {
CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, value, MIXSRC_LAST_TELEM, isSourceAvailable);
}
#else
lcd_putsiAtt(pos[c], y, STR_VTELEMCHNS, value, cellAttr);
if (cellAttr && (s_editMode>0 || p1valdiff)) {
CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, value, (lineIndex==3 && c==0) ? TELEM_STATUS_MAX : TELEM_DISPLAY_MAX, isTelemetrySourceAvailable);
}
#endif
}
if (attr && m_posHorz == NUM_LINE_ITEMS) {
REPEAT_LAST_CURSOR_MOVE();

View file

@ -107,12 +107,12 @@ uint8_t switchToMix(uint8_t source)
int8_t checkIncDec_Ret;
#if defined(CPUARM)
int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, uint8_t i_flags, IsValueAvailable isValueAvailable)
int checkIncDec(uint8_t event, int val, int i_min, int i_max, uint8_t i_flags, IsValueAvailable isValueAvailable)
#else
int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, uint8_t i_flags)
#endif
{
int16_t newval = val;
int newval = val;
#if defined(DBLKEYS)
uint8_t in = KEYS_PRESSED();
@ -591,8 +591,9 @@ void check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t
if (l_posVert == 0 || (l_posVert==2 && MAXCOL(vertpos_t(1)) >= HIDDEN_ROW) || (l_posVert==3 && MAXCOL(vertpos_t(1)) >= HIDDEN_ROW && MAXCOL(vertpos_t(2)) >= HIDDEN_ROW)) {
s_pgOfs = 0;
}
else if (menuTab && horTab) {
if (maxrow > LCD_LINES-1) {
else if (horTab) {
uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
if (maxrow > max) {
while (1) {
vertpos_t firstLine = 0;
for (int numLines=0; firstLine<=maxrow && numLines<s_pgOfs; firstLine++) {
@ -605,7 +606,7 @@ void check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t
}
else {
vertpos_t lastLine = firstLine;
for (int numLines=0; lastLine<=maxrow && numLines<LCD_LINES-1; lastLine++) {
for (int numLines=0; lastLine<=maxrow && numLines<max; lastLine++) {
if (horTab[lastLine+1] != HIDDEN_ROW) {
numLines++;
}
@ -1410,50 +1411,30 @@ bool isSourceAvailable(int source)
return false;
#endif
if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM)
return isTelemetrySourceAvailable(source-MIXSRC_FIRST_TELEM+1);
if (source>=MIXSRC_RESERVE1 && source<=MIXSRC_RESERVE5)
return false;
if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) {
div_t qr = div(source-MIXSRC_FIRST_TELEM, 3);
if (qr.rem == 0)
return isTelemetryFieldAvailable(qr.quot);
else
return isTelemetryFieldComparisonAvailable(qr.quot);
}
return true;
}
bool isTelemetrySourceAvailable(int source)
bool isSourceAvailableInCustomSwitches(int source)
{
#if defined(PCBTARANIS)
if (source == TELEM_RSSI_TX)
return false;
#endif
bool result = isSourceAvailable(source);
#if !defined(SWR)
// on Taranis+ we also hide the SWR
if (source == TELEM_SWR)
return false;
#endif
if (source >= TELEM_A1 && source <= TELEM_A4) {
return g_model.frsky.channels[source-TELEM_A1].ratio != 0;
if (result && source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) {
div_t qr = div(source-MIXSRC_FIRST_TELEM, 3);
result = isTelemetryFieldComparisonAvailable(qr.quot);
}
#if !defined(RTCLOCK)
if (source == TELEM_TX_TIME)
return false;
#endif
if (source == TELEM_RESERVE0)
return false;
if (source >= TELEM_RESERVE1 && source <= TELEM_RESERVE5)
return false;
if (source >= TELEM_RESERVE6 && source <= TELEM_RESERVE10)
return false;
if (source >= TELEM_RESERVE11 && source <= TELEM_RESERVE15)
return false;
if (source == TELEM_DTE)
return false;
return true;
return result;
}
bool isInputSourceAvailable(int source)
@ -1479,7 +1460,7 @@ bool isInputSourceAvailable(int source)
return true;
if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM)
return isTelemetrySourceAvailable(source-MIXSRC_FIRST_TELEM+1);
return isTelemetryFieldAvailable(source-MIXSRC_FIRST_TELEM);
return false;
}
@ -1557,7 +1538,7 @@ bool isSwitchAvailableInLogicalSwitches(int swtch)
bool isSwitchAvailableInCustomFunctions(int swtch)
{
if (g_menuStack[0] == menuModelCustomFunctions)
if (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions)
return isSwitchAvailable(swtch, ModelCustomFunctionsContext);
else
return isSwitchAvailable(swtch, GeneralCustomFunctionsContext);
@ -1596,7 +1577,7 @@ bool isLogicalSwitchFunctionAvailable(int function)
bool isAssignableFunctionAvailable(int function)
{
bool modelFunctions = (g_menuStack[0] == menuModelCustomFunctions);
bool modelFunctions = (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions);
switch (function) {
case FUNC_OVERRIDE_CHANNEL:

View file

@ -194,9 +194,9 @@ extern int8_t s_editMode; // global editmode
#if defined(CPUARM)
typedef bool (*IsValueAvailable)(int);
int16_t checkIncDec(uint8_t event, int16_t i_pval, int16_t i_min, int16_t i_max, uint8_t i_flags=0, IsValueAvailable isValueAvailable=NULL);
int checkIncDec(uint8_t event, int val, int i_min, int i_max, uint8_t i_flags=0, IsValueAvailable isValueAvailable=NULL);
#else
int16_t checkIncDec(uint8_t event, int16_t i_pval, int16_t i_min, int16_t i_max, uint8_t i_flags=0);
int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, uint8_t i_flags=0);
#endif
#if defined(CPUM64)
@ -258,7 +258,7 @@ int8_t checkIncDecGen(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max);
#if defined(CPUARM)
bool isInputAvailable(int input);
bool isSourceAvailable(int source);
bool isTelemetrySourceAvailable(int source);
bool isSourceAvailableInCustomSwitches(int source);
bool isInputSourceAvailable(int source);
#define CHECK_INCDEC_MODELSOURCE(event, var, min, max) \
var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable)
@ -344,9 +344,11 @@ void title(const pm_char * s);
#endif
select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event);
uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event );
uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event);
int8_t switchMenuItem(coord_t x, coord_t y, int8_t value, LcdFlags attr, uint8_t event);
#define ON_OFF_MENU_ITEM(value, x, y, label, attr, event) value = onoffMenuItem(value, x, y, label, attr, event)
#if defined(CPUARM) && defined(GVARS)
#define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) gvarMenuItem(x, y, v, min, max, lcdattr, editflags, event)
#else

View file

@ -275,38 +275,31 @@ void displayTopBar()
lcd_rect(batt_icon_x+FW, BAR_Y+1, 13, 7);
lcd_vline(batt_icon_x+FW+13, BAR_Y+2, 5);
if (frskyData.rssi[0].value > 0) {
if (TELEMETRY_STREAMING()) {
/* RSSI */
LCD_ICON(batt_icon_x+3*FW+3, BAR_Y, ICON_RSSI);
lcd_rect(batt_icon_x+5*FW, BAR_Y+1, 13, 7);
/* Rx voltage */
lcdint_t voltage = 0;
uint8_t channel = 0;
if (g_model.frsky.voltsSource <= FRSKY_VOLTS_SOURCE_A4) {
channel = TELEM_A1+g_model.frsky.voltsSource-1;
voltage = frskyData.analog[g_model.frsky.voltsSource].value;
}
else if (g_model.frsky.voltsSource == FRSKY_VOLTS_SOURCE_FAS) {
channel = TELEM_VFAS-1;
voltage = frskyData.hub.vfas;
}
else if (g_model.frsky.voltsSource == FRSKY_VOLTS_SOURCE_CELLS) {
channel = TELEM_CELLS_SUM-1;
voltage = frskyData.hub.cellsSum;
}
if (voltage > 0) {
putsTelemetryChannel(batt_icon_x+7*FW+2, BAR_Y+1, channel, voltage, LEFT);
altitude_icon_x = batt_icon_x+7*FW+3;
if (g_model.frsky.voltsSource) {
TelemetryItem & voltsItem = telemetryItems[g_model.frsky.voltsSource-1];
if (voltsItem.isAvailable()) {
putsTelemetryChannelValue(batt_icon_x+7*FW+2, BAR_Y+1, g_model.frsky.voltsSource-1, voltsItem.value, LEFT);
altitude_icon_x = lcdLastPos+1;
}
else {
altitude_icon_x = batt_icon_x+7*FW+3;
}
/* Altitude */
if (g_model.frsky.altitudeDisplayed && TELEMETRY_BARO_ALT_AVAILABLE()) {
if (g_model.frsky.altitudeSource) {
TelemetryItem & altitudeItem = telemetryItems[g_model.frsky.altitudeSource-1];
if (altitudeItem.isAvailable()) {
LCD_ICON(altitude_icon_x, BAR_Y, ICON_ALTITUDE);
putsTelemetryValue(altitude_icon_x+2*FW-1, BAR_Y+1, TELEMETRY_RELATIVE_BARO_ALT_BP, UNIT_DIST, LEFT);
int32_t value = altitudeItem.value;
TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1];
if (sensor.prec) value /= sensor.prec == 2 ? 100 : 10;
putsValueWithUnit(altitude_icon_x+2*FW-1, BAR_Y+1, value, UNIT_METERS, LEFT);
}
}
}
@ -357,8 +350,8 @@ void displayTopBar()
displayTopBarGauge(batt_icon_x+FW, count, g_vbat100mV <= g_eeGeneral.vBatWarn);
/* The inside of the RSSI gauge */
if (frskyData.rssi[0].value > 0) {
displayTopBarGauge(batt_icon_x+5*FW, frskyData.rssi[0].value / 10, frskyData.rssi[0].value < getRssiAlarmValue(0));
if (TELEMETRY_RSSI() > 0) {
displayTopBarGauge(batt_icon_x+5*FW, TELEMETRY_RSSI() / 10, TELEMETRY_RSSI() < getRssiAlarmValue(0));
}
}
#endif
@ -446,10 +439,10 @@ void displayBattVoltage()
void displayVoltageOrAlarm()
{
if (g_vbat100mV > g_eeGeneral.vBatWarn && g_eeGeneral.temperatureWarn && getTemperature() >= g_eeGeneral.temperatureWarn) {
putsTelemetryValue(6*FW-1, 2*FH, getTemperature(), UNIT_TEMPERATURE, BLINK|INVERS|DBLSIZE);
putsValueWithUnit(6*FW-1, 2*FH, getTemperature(), UNIT_TEMPERATURE, BLINK|INVERS|DBLSIZE);
}
else if (g_vbat100mV > g_eeGeneral.vBatWarn && g_eeGeneral.mAhWarn && (g_eeGeneral.mAhUsed + Current_used * (488 + g_eeGeneral.currentCalib)/8192/36) / 500 >= g_eeGeneral.mAhWarn) {
putsTelemetryValue(7*FW-1, 2*FH, (g_eeGeneral.mAhUsed + Current_used*(488 + g_eeGeneral.currentCalib)/8192/36)/10, UNIT_MAH, BLINK|INVERS|DBLSIZE);
putsValueWithUnit(7*FW-1, 2*FH, (g_eeGeneral.mAhUsed + Current_used*(488 + g_eeGeneral.currentCalib)/8192/36)/10, UNIT_MAH, BLINK|INVERS|DBLSIZE);
}
else {
displayBattVoltage();

View file

@ -168,20 +168,20 @@ void menuStatisticsDebug(uint8_t event)
#if defined(PCBSKY9X) && !defined(REVA)
// current
lcd_putsLeft(MENU_DEBUG_Y_CURRENT, STR_CPU_CURRENT);
putsTelemetryValue(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CURRENT, getCurrent(), UNIT_MILLIAMPS, LEFT);
putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CURRENT, getCurrent(), UNIT_MILLIAMPS, LEFT);
uint32_t current_scale = 488 + g_eeGeneral.currentCalib;
lcd_putc(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_CURRENT, '>');
putsTelemetryValue(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CURRENT, Current_max*10*current_scale/8192, UNIT_RAW, LEFT);
putsValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CURRENT, Current_max*10*current_scale/8192, UNIT_RAW, LEFT);
// consumption
lcd_putsLeft(MENU_DEBUG_Y_MAH, STR_CPU_MAH);
putsTelemetryValue(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MAH, g_eeGeneral.mAhUsed + Current_used*current_scale/8192/36, UNIT_MAH, LEFT|PREC1);
putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MAH, g_eeGeneral.mAhUsed + Current_used*current_scale/8192/36, UNIT_MAH, LEFT|PREC1);
#endif
#if defined(PCBSKY9X)
lcd_putsLeft(MENU_DEBUG_Y_CPU_TEMP, STR_CPU_TEMP);
putsTelemetryValue(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CPU_TEMP, getTemperature(), UNIT_TEMPERATURE, LEFT);
putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CPU_TEMP, getTemperature(), UNIT_TEMPERATURE, LEFT);
lcd_putc(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_CPU_TEMP, '>');
putsTelemetryValue(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CPU_TEMP, maxTemperature+g_eeGeneral.temperatureCalib, UNIT_TEMPERATURE, LEFT);
putsValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CPU_TEMP, maxTemperature+g_eeGeneral.temperatureCalib, UNIT_TEMPERATURE, LEFT);
#endif
#if defined(COPROCESSOR)
@ -197,8 +197,8 @@ void menuStatisticsDebug(uint8_t event)
lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, PSTR("Upgr.TinyApp"),INVERS);
}
else {
putsTelemetryValue(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, Coproc_temp, UNIT_TEMPERATURE, LEFT);
putsTelemetryValue(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_COPROC, Coproc_maxtemp, UNIT_TEMPERATURE, LEFT);
putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, Coproc_temp, UNIT_TEMPERATURE, LEFT);
putsValueWithUnit(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_COPROC, Coproc_maxtemp, UNIT_TEMPERATURE, LEFT);
}
#endif

View file

@ -62,7 +62,7 @@ void displayRssiLine()
{
if (TELEMETRY_STREAMING()) {
lcd_hline(0, 55, 212, 0); // separator
uint8_t rssi = min((uint8_t)99, frskyData.rssi[0].value);
uint8_t rssi = min((uint8_t)99, TELEMETRY_RSSI());
lcd_putsn(0, STATUS_BAR_Y, STR_RX, 2); lcd_outdezNAtt(4*FW, STATUS_BAR_Y, rssi, LEADING0, 2);
lcd_rect(BAR_LEFT, 57, 78, 7);
lcd_filled_rect(BAR_LEFT+1, 58, 19*rssi/25, 5, (rssi < getRssiAlarmValue(0)) ? DOTTED : SOLID);
@ -77,11 +77,14 @@ void displayRssiLine()
{
if (TELEMETRY_STREAMING()) {
lcd_hline(0, 55, 128, 0); // separator
uint8_t rssi = min((uint8_t)99, frskyData.rssi[1].value);
uint8_t rssi;
#if !defined(CPUARM)
rssi = min((uint8_t)99, frskyData.rssi[1].value);
lcd_putsLeft(STATUS_BAR_Y, STR_TX); lcd_outdezNAtt(4*FW+1, STATUS_BAR_Y, rssi, LEADING0, 2);
lcd_rect(BAR_LEFT+1, 57, 38, 7);
lcd_filled_rect(BAR_LEFT+1, 58, 4*rssi/11, 5, (rssi < getRssiAlarmValue(0)) ? DOTTED : SOLID);
rssi = min((uint8_t)99, frskyData.rssi[0].value);
#endif
rssi = min((uint8_t)99, TELEMETRY_RSSI());
lcd_puts(104, STATUS_BAR_Y, STR_RX); lcd_outdezNAtt(105+4*FW, STATUS_BAR_Y, rssi, LEADING0, 2);
lcd_rect(65, 57, 38, 7);
uint8_t v = 4*rssi/11;
@ -94,7 +97,7 @@ void displayRssiLine()
}
#endif
#if defined(FRSKY) && defined(FRSKY_HUB) && defined(GPS)
#if defined(FRSKY) && defined(FRSKY_HUB) && defined(GPS) && !defined(CPUARM)
void displayGpsTime()
{
uint8_t att = (TELEMETRY_STREAMING() ? LEFT|LEADING0 : LEFT|LEADING0|BLINK);
@ -136,7 +139,7 @@ void displayGpsCoord(uint8_t y, char direction, int16_t bp, int16_t ap)
lcd_puts(TELEM_2ND_COLUMN, y, STR_VCSWFUNC+1/*----*/);
}
}
#else
#elif !defined(CPUARM)
#define displayGpsTime()
#define displayGpsCoord(...)
#endif
@ -146,46 +149,50 @@ NOINLINE uint8_t getRssiAlarmValue(uint8_t alarm)
return (45 - 3*alarm + g_model.frsky.rssiAlarms[alarm].value);
}
#if !defined(CPUARM)
void displayVoltageScreenLine(uint8_t y, uint8_t index)
{
putsStrIdx(0, y, STR_A, index+1, 0);
if (TELEMETRY_STREAMING()) {
putsTelemetryChannel(3*FW+6*FW+4, y-FH, index+TELEM_A1-1, frskyData.analog[index].value, DBLSIZE);
lcd_putc(12*FW-1, y-FH, '<'); putsTelemetryChannel(17*FW, y-FH, index+TELEM_A1-1, frskyData.analog[index].min, NO_UNIT);
lcd_putc(12*FW, y, '>'); putsTelemetryChannel(17*FW, y, index+TELEM_A1-1, frskyData.analog[index].max, NO_UNIT);
putsTelemetryChannelValue(3*FW+6*FW+4, y-FH, index+TELEM_A1-1, frskyData.analog[index].value, DBLSIZE);
lcd_putc(12*FW-1, y-FH, '<'); putsTelemetryChannelValue(17*FW, y-FH, index+TELEM_A1-1, frskyData.analog[index].min, NO_UNIT);
lcd_putc(12*FW, y, '>'); putsTelemetryChannelValue(17*FW, y, index+TELEM_A1-1, frskyData.analog[index].max, NO_UNIT);
}
}
#endif
uint8_t barCoord(int16_t value, int16_t min, int16_t max)
{
#if defined(CPUARM)
if (value <= min)
return 0;
else if (value >= max)
return BAR_WIDTH-1;
else
return ((int32_t)(BAR_WIDTH-1) * (value - min)) / (max - min);
#else
return limit((uint8_t)0, (uint8_t)(((int32_t)(BAR_WIDTH-1) * (value - min)) / (max - min)), (uint8_t)BAR_WIDTH);
#endif
}
#if !defined(CPUARM)
void displayVoltagesScreen()
{
// Volts / Amps / Watts / mAh
uint8_t analog = 0;
#if defined(CPUARM)
lcd_putsiAtt(0, 2*FH, STR_VOLTSRC, g_model.frsky.voltsSource, 0);
#else
lcd_putsiAtt(0, 2*FH, STR_AMPSRC, g_model.frsky.voltsSource+1, 0);
#endif
switch (g_model.frsky.voltsSource) {
case FRSKY_VOLTS_SOURCE_A1:
case FRSKY_VOLTS_SOURCE_A2:
#if defined(CPUARM)
case FRSKY_VOLTS_SOURCE_A3:
case FRSKY_VOLTS_SOURCE_A4:
#endif
displayVoltageScreenLine(2*FH, g_model.frsky.voltsSource);
analog = 1+g_model.frsky.voltsSource;
break;
#if defined(FRSKY_HUB)
case FRSKY_VOLTS_SOURCE_FAS:
putsTelemetryChannel(3*FW+6*FW+4, FH, TELEM_VFAS-1, frskyData.hub.vfas, DBLSIZE);
putsTelemetryChannelValue(3*FW+6*FW+4, FH, TELEM_VFAS-1, frskyData.hub.vfas, DBLSIZE);
break;
case FRSKY_VOLTS_SOURCE_CELLS:
putsTelemetryChannel(3*FW+6*FW+4, FH, TELEM_CELLS_SUM-1, frskyData.hub.cellsSum, DBLSIZE);
putsTelemetryChannelValue(3*FW+6*FW+4, FH, TELEM_CELLS_SUM-1, frskyData.hub.cellsSum, DBLSIZE);
break;
#endif
}
@ -195,28 +202,20 @@ void displayVoltagesScreen()
switch(g_model.frsky.currentSource) {
case FRSKY_CURRENT_SOURCE_A1:
case FRSKY_CURRENT_SOURCE_A2:
#if defined(CPUARM)
case FRSKY_CURRENT_SOURCE_A3:
case FRSKY_CURRENT_SOURCE_A4:
#endif
displayVoltageScreenLine(4*FH, g_model.frsky.currentSource-1);
break;
#if defined(FRSKY_HUB)
case FRSKY_CURRENT_SOURCE_FAS:
putsTelemetryChannel(3*FW+6*FW+4, 3*FH, TELEM_CURRENT-1, frskyData.hub.current, DBLSIZE);
putsTelemetryChannelValue(3*FW+6*FW+4, 3*FH, TELEM_CURRENT-1, frskyData.hub.current, DBLSIZE);
break;
#endif
}
putsTelemetryChannel(4, 5*FH, TELEM_POWER-1, frskyData.hub.power, LEFT|DBLSIZE);
putsTelemetryChannel(3*FW+4+4*FW+6*FW+FW, 5*FH, TELEM_CONSUMPTION-1, frskyData.hub.currentConsumption, DBLSIZE);
putsTelemetryChannelValue(4, 5*FH, TELEM_POWER-1, frskyData.hub.power, LEFT|DBLSIZE);
putsTelemetryChannelValue(3*FW+4+4*FW+6*FW+FW, 5*FH, TELEM_CONSUMPTION-1, frskyData.hub.currentConsumption, DBLSIZE);
}
else {
#if defined(CPUARM)
displayVoltageScreenLine(analog > 0 ? 5*FH : 4*FH, analog==1+FRSKY_VOLTS_SOURCE_A1 ? FRSKY_VOLTS_SOURCE_A2 : FRSKY_VOLTS_SOURCE_A1);
#else
displayVoltageScreenLine(analog > 0 ? 5*FH : 4*FH, analog ? 2-analog : 0);
#endif
if (analog == 0) displayVoltageScreenLine(6*FH, 1);
}
@ -233,21 +232,6 @@ void displayVoltagesScreen()
lcd_outdezNAtt(LCD_W, y, TELEMETRY_CELL_VOLTAGE(k), attr, 4);
y += 1*FH;
}
#if defined(PCBTARANIS)
if (frskyData.hub.cellsCount > 6) {
y = 1*FH;
for (uint8_t k=6; k<frskyData.hub.cellsCount && k<12; k++) {
#if defined(GAUGES)
uint8_t attr = (barsThresholds[THLD_CELL] && frskyData.hub.cellVolts[k] < barsThresholds[THLD_CELL]) ? BLINK|PREC2 : PREC2;
#else
uint8_t attr = PREC2;
#endif
lcd_outdezNAtt(LCD_W-3*FW-2, y, TELEMETRY_CELL_VOLTAGE(k), attr, 4);
y += 1*FH;
}
lcd_vline(LCD_W-6*FW-4, 8, 47);
} else
#endif
lcd_vline(LCD_W-3*FW-2, 8, 47);
}
#endif
@ -271,15 +255,12 @@ void displayAfterFlightScreen()
}
// Rssi
lcd_putsLeft(line, STR_MINRSSI);
#if defined(PCBTARANIS)
lcd_outdezNAtt(TELEM_2ND_COLUMN, line, frskyData.rssi[0].min, LEFT|LEADING0, 2);
#else
lcd_puts(TELEM_2ND_COLUMN, line, STR_TX);
lcd_outdezNAtt(TELEM_2ND_COLUMN+3*FW, line, frskyData.rssi[1].min, LEFT|LEADING0, 2);
lcd_puts(TELEM_2ND_COLUMN+6*FW, line, STR_RX);
lcd_outdezNAtt(TELEM_2ND_COLUMN+9*FW, line, frskyData.rssi[0].min, LEFT|LEADING0, 2);
#endif
}
#endif
bool displayGaugesTelemetryScreen(FrSkyScreenData & screen)
{
@ -287,19 +268,35 @@ bool displayGaugesTelemetryScreen(FrSkyScreenData & screen)
uint8_t barHeight = 5;
for (int8_t i=3; i>=0; i--) {
FrSkyBarData & bar = screen.bars[i];
uint8_t source = bar.source;
source_t source = bar.source;
#if defined(CPUARM)
getvalue_t barMin = bar.barMin;
getvalue_t barMax = bar.barMax;
#else
getvalue_t barMin = convertBarTelemValue(source, bar.barMin);
getvalue_t barMax = convertBarTelemValue(source, 255-bar.barMax);
#endif
if (source && barMax > barMin) {
uint8_t y = barHeight+6+i*(barHeight+6);
#if defined(CPUARM)
putsMixerSource(0, y+barHeight-5, source, 0);
#else
lcd_putsiAtt(0, y+barHeight-5, STR_VTELEMCHNS, source, 0);
lcd_rect(BAR_LEFT, y, BAR_WIDTH+1, barHeight+2);
getvalue_t value = getValue(MIXSRC_FIRST_TELEM+source-1);
#if LCD_W >= 212
putsTelemetryChannel(BAR_LEFT+2+BAR_WIDTH, y+barHeight-5, source-1, value, LEFT);
#endif
getvalue_t threshold = 0;
lcd_rect(BAR_LEFT, y, BAR_WIDTH+1, barHeight+2);
#if defined(CPUARM)
getvalue_t value = getValue(source);
#else
getvalue_t value = getValue(MIXSRC_FIRST_TELEM+source-1);
#endif
#if defined(PCBTARANIS)
putsChannel(BAR_LEFT+2+BAR_WIDTH, y+barHeight-5, source, LEFT);
#endif
uint8_t thresholdX = 0;
#if !defined(CPUARM)
getvalue_t threshold = 0;
if (source <= TELEM_TIMER_MAX)
threshold = 0;
else if (source <= TELEM_RSSI_RX)
@ -308,9 +305,7 @@ bool displayGaugesTelemetryScreen(FrSkyScreenData & screen)
threshold = g_model.frsky.channels[source-TELEM_A1].alarms_value[0];
#if defined(FRSKY_HUB)
else {
#if defined(CPUARM)
threshold = barsThresholds[source-TELEM_ALT];
#elif defined(GAUGES)
#if defined(GAUGES)
threshold = convertBarTelemValue(source, barsThresholds[source-TELEM_ALT]);
#endif
}
@ -321,13 +316,19 @@ bool displayGaugesTelemetryScreen(FrSkyScreenData & screen)
if (thresholdX == 100)
thresholdX = 0;
}
#endif
uint8_t width = barCoord(value, barMin, barMax);
#if defined(CPUARM)
uint8_t barShade = SOLID;
#else
// reversed barshade for T1/T2
uint8_t barShade = ((threshold > value) ? DOTTED : SOLID);
if (source == TELEM_T1 || source == TELEM_T2)
if (source == TELEM_T1 || source == TELEM_T2) {
barShade = -barShade;
}
#endif
lcd_filled_rect(BAR_LEFT+1, y+1, width, barHeight, barShade);
@ -350,6 +351,68 @@ bool displayGaugesTelemetryScreen(FrSkyScreenData & screen)
return barHeight < 13;
}
#if defined(CPUARM)
bool displayNumbersTelemetryScreen(FrSkyScreenData & screen)
{
// Custom Screen with numbers
uint8_t fields_count = 0;
for (uint8_t i=0; i<4; i++) {
for (uint8_t j=0; j<NUM_LINE_ITEMS; j++) {
source_t field = screen.lines[i].sources[j];
if (field > 0) {
fields_count++;
}
if (i==3) {
#if LCD_W >= 212
lcd_vline(69, 8, 48);
lcd_vline(141, 8, 48);
#else
lcd_vline(63, 8, 48);
#endif
if (!TELEMETRY_STREAMING()) {
displayRssiLine();
return fields_count;
}
}
if (field) {
LcdFlags att = (i==3 ? NO_UNIT : DBLSIZE|NO_UNIT);
#if LCD_W >= 212
coord_t pos[] = {0, 71, 143, 214};
#else
coord_t pos[] = {0, 65, 130};
#endif
if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER && i!=3) {
// there is not enough space on LCD for displaying "Tmr1" or "Tmr2" and still see the - sign, we write "T1" or "T2" instead
putsStrIdx(pos[j], 1+FH+2*FH*i, "T", field-MIXSRC_FIRST_TIMER+1, 0);
}
else if (field >= MIXSRC_FIRST_TELEM && isGPSSensor(1+(field-MIXSRC_FIRST_TELEM)/3) && telemetryItems[(field-MIXSRC_FIRST_TELEM)/3].isAvailable()) {
// we don't display GPS name, no space for it
}
else {
putsMixerSource(pos[j], 1+FH+2*FH*i, field, 0);
}
if (field >= MIXSRC_FIRST_TELEM) {
TelemetryItem & telemetryItem = telemetryItems[(field-MIXSRC_FIRST_TELEM)/3]; // TODO macro to convert a source to a telemetry index
if (!telemetryItem.isAvailable()) {
continue;
}
else if (telemetryItem.isOld()) {
att |= INVERS|BLINK;
}
}
putsChannel(pos[j+1]-2, (i==3 ? 1+FH+2*FH*i:FH+2*FH*i), field, att);
}
}
}
lcd_status_line();
return fields_count;
}
#else
bool displayNumbersTelemetryScreen(FrSkyScreenData & screen)
{
// Custom Screen with numbers
@ -397,20 +460,13 @@ bool displayNumbersTelemetryScreen(FrSkyScreenData & screen)
#else
coord_t pos[] = {0, 65, 130};
#endif
putsTelemetryChannel(pos[j+1]-2, FH+2*FH*i, field-1, value, att);
putsTelemetryChannelValue(pos[j+1]-2, FH+2*FH*i, field-1, value, att);
#if defined(CPUARM)
if (field >= TELEM_TIMER1 && field <= TELEM_TIMER_MAX && i!=3) {
// there is not enough space on LCD for displaying "Tmr1" or "Tmr2" and still see the - sign, we write "T1" or "T2" instead
putsStrIdx(pos[j], 1+FH+2*FH*i, "T", field-TELEM_TIMER1+1, 0);
}
else
#else
if (field >= TELEM_TIMER1 && field <= TELEM_TIMER_MAX && i!=3) {
// there is not enough space on LCD for displaying "Tmr1" or "Tmr2" and still see the - sign, we write "T1" or "T2" instead
field = field-TELEM_TIMER1+TELEM_T1;
}
#endif
lcd_putsiAtt(pos[j], 1+FH+2*FH*i, STR_VTELEMCHNS, field, 0);
}
}
@ -418,7 +474,24 @@ bool displayNumbersTelemetryScreen(FrSkyScreenData & screen)
lcd_status_line();
return fields_count;
}
#endif
#if defined(CPUARM)
bool displayCustomTelemetryScreen(uint8_t index)
{
FrSkyScreenData & screen = g_model.frsky.screens[index];
#if defined(GAUGES)
if (IS_BARS_SCREEN(s_frsky_view)) {
return displayGaugesTelemetryScreen(screen);
}
#endif
displayNumbersTelemetryScreen(screen);
return true;
}
#else
bool displayCustomTelemetryScreen(uint8_t index)
{
FrSkyScreenData & screen = g_model.frsky.screens[index];
@ -431,12 +504,19 @@ bool displayCustomTelemetryScreen(uint8_t index)
return displayNumbersTelemetryScreen(screen);
}
#endif
bool displayTelemetryScreen()
{
#if defined(LUA)
if (TELEMETRY_SCREEN_TYPE(s_frsky_view) == TELEMETRY_SCREEN_TYPE_SCRIPT) {
return ZEXIST(g_model.frsky.screens[s_frsky_view].script.file);
return true;
}
#endif
#if defined(CPUARM)
if (TELEMETRY_SCREEN_TYPE(s_frsky_view) == TELEMETRY_SCREEN_TYPE_NONE) {
return false;
}
#endif
@ -445,10 +525,14 @@ bool displayTelemetryScreen()
if (s_frsky_view < MAX_TELEMETRY_SCREENS) {
return displayCustomTelemetryScreen(s_frsky_view);
}
#if !defined(CPUARM)
if (s_frsky_view == TELEMETRY_VOLTAGES_SCREEN) {
displayVoltagesScreen();
}
#if defined(FRSKY_HUB)
#endif
#if !defined(CPUARM) && defined(FRSKY_HUB)
else {
displayAfterFlightScreen();
}
@ -469,11 +553,11 @@ enum NavigationDirection {
void decrTelemetryScreen()
{
if (s_frsky_view-- == 0)
s_frsky_view = FRSKY_VIEW_MAX;
s_frsky_view = TELEMETRY_VIEW_MAX;
}
void incrTelemetryScreen()
{
if (s_frsky_view++ == FRSKY_VIEW_MAX)
if (s_frsky_view++ == TELEMETRY_VIEW_MAX)
s_frsky_view = 0;
}
#endif
@ -521,19 +605,26 @@ void menuTelemetryFrsky(uint8_t event)
}
#if defined(CPUARM)
do {
for (int i=0; i<=TELEMETRY_SCREEN_TYPE_MAX; i++) {
if (direction == up) {
if (s_frsky_view-- == 0)
s_frsky_view = FRSKY_VIEW_MAX;
s_frsky_view = TELEMETRY_VIEW_MAX;
}
else if (direction == down) {
if (s_frsky_view++ == FRSKY_VIEW_MAX)
if (s_frsky_view++ == TELEMETRY_VIEW_MAX)
s_frsky_view = 0;
}
else {
direction = down;
}
} while (!displayTelemetryScreen());
if (displayTelemetryScreen()) {
return;
}
}
lcdDrawTelemetryTopBar();
lcd_puts(8*FW, 3*FH, "No Telemetry Screens");
displayRssiLine();
#else
if (!displayTelemetryScreen()) {
putEvent(event == EVT_KEY_BREAK(KEY_UP) ? event : EVT_KEY_BREAK(KEY_DOWN));

View file

@ -191,7 +191,11 @@ void lcd_putsn(coord_t x, coord_t y, const pm_char * s, unsigned char len);
void lcd_putsLeft(coord_t y, const pm_char * s);
#define lcd_putsCenter(y, s) lcd_puts((LCD_W-sizeof(TR_##s)*FW+FW-2)/2, y, STR_##s)
#if defined(CPUARM)
void lcd_outhex4(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0);
#else
void lcd_outhex4(coord_t x, coord_t y, uint16_t val);
#endif
void lcd_outdezAtt(coord_t x, coord_t y, lcdint_t val, LcdFlags mode=0);
void lcd_outdezNAtt(coord_t x, coord_t y, lcdint_t val, LcdFlags mode=0, uint8_t len=0);
void lcd_outdez8(coord_t x, coord_t y, int8_t val);
@ -216,7 +220,12 @@ void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags attr);
void putsVolts(coord_t x, coord_t y, uint16_t volts, LcdFlags att);
void putsVBat(coord_t x, coord_t y, LcdFlags att);
void putsTelemetryChannel(coord_t x, coord_t y, uint8_t channel, lcdint_t val, LcdFlags att=0);
#if !defined(BOOT)
void putsChannelValue(coord_t x, coord_t y, source_t channel, lcdint_t val, LcdFlags att=0);
void putsChannel(coord_t x, coord_t y, source_t channel, LcdFlags att=0);
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, lcdint_t val, LcdFlags att=0);
#endif
#if defined(CPUARM)
#define putstime_t int32_t

View file

@ -310,6 +310,19 @@ void lcd_putsiAtt(coord_t x, coord_t y, const pm_char * s,uint8_t idx, LcdFlags
lcd_putsnAtt(x, y, s+length*idx, length, flags & ~(BSS|ZCHAR));
}
#if defined(CPUARM)
void lcd_outhex4(coord_t x, coord_t y, uint32_t val, LcdFlags flags)
{
x += FWNUM*4+1;
for (int i=0; i<4; i++) {
x -= FWNUM;
char c = val & 0xf;
c = c>9 ? c+'A'-10 : c+'0';
lcd_putcAtt(x, y, c, flags|(c>='A' ? CONDENSED : 0));
val >>= 4;
}
}
#else
void lcd_outhex4(coord_t x, coord_t y, uint16_t val)
{
x += FWNUM*4+1;
@ -321,6 +334,7 @@ void lcd_outhex4(coord_t x, coord_t y, uint16_t val)
val >>= 4;
}
}
#endif
void lcd_outdez8(coord_t x, coord_t y, int8_t val)
{
@ -497,7 +511,7 @@ void lcd_hline(coord_t x, coord_t y, coord_t w, LcdFlags att)
lcd_hlineStip(x, y, w, 0xff, att);
}
#if defined(CPUARM)
#if defined(CPUARM) && !defined(BOOT)
void lcd_line(coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t pat, LcdFlags att)
{
int dx = x2-x1; /* the horizontal distance of the line */
@ -582,12 +596,12 @@ void lcdDrawTelemetryTopBar()
if (g_model.timers[0].mode) {
att = (timersStates[0].val<0 ? BLINK : 0);
putsTimer(22*FW+5*FWNUM+3, 0, timersStates[0].val, att, att);
lcd_putsiAtt(18*FW+2, 1, STR_VTELEMCHNS, TELEM_TIMER1, SMLSIZE);
putsMixerSource(18*FW+2, 1, MIXSRC_TIMER1, SMLSIZE);
}
if (g_model.timers[1].mode) {
att = (timersStates[1].val<0 ? BLINK : 0);
putsTimer(31*FW+5*FWNUM+3, 0, timersStates[1].val, att, att);
lcd_putsiAtt(27*FW+2, 1, STR_VTELEMCHNS, TELEM_TIMER2, SMLSIZE);
putsMixerSource(27*FW+2, 1, MIXSRC_TIMER2, SMLSIZE);
}
lcd_invert_line(0);
}
@ -608,7 +622,7 @@ void lcdDrawTelemetryTopBar()
#if defined(CPUARM) && defined(RTCLOCK)
void putsRtcTime(coord_t x, coord_t y, LcdFlags att)
{
putsTimer(x, y, getValue(MIXSRC_FIRST_TELEM-1+TELEM_TX_TIME), att, att);
putsTimer(x, y, getValue(MIXSRC_TX_TIME), att, att);
}
#endif
@ -663,7 +677,7 @@ void putsTimer(coord_t x, coord_t y, putstime_t tme, LcdFlags att, LcdFlags att2
lcd_outdezNAtt(lcdNextPos, y, qr.rem, att2|LEADING0|LEFT, 2);
}
// TODO to be optimized with putsTelemetryValue
// TODO to be optimized with putsValueWithUnit
void putsVolts(coord_t x, coord_t y, uint16_t volts, LcdFlags att)
{
lcd_outdezAtt(x, y, (int16_t)volts, (~NO_UNIT) & (att | ((att&PREC2)==PREC2 ? 0 : PREC1)));
@ -685,13 +699,13 @@ void putsMixerSource(coord_t x, coord_t y, uint8_t idx, LcdFlags att)
{
#if defined(PCBTARANIS)
if (idx == 0) {
lcd_putsiAtt(x, y, STR_VSRCRAW, 0, att);
lcd_putsiAtt(x, y, STR_VSRCRAW, 0, att); // TODO macro
}
else if (idx <= MIXSRC_LAST_INPUT) {
lcd_putcAtt(x+2, y+1, CHR_INPUT, TINSIZE);
lcd_filled_rect(x, y, 7, 7);
if (ZEXIST(g_model.inputNames[idx-MIXSRC_FIRST_INPUT]))
lcd_putsnAtt(x+8, y, g_model.inputNames[idx-MIXSRC_FIRST_INPUT], 4, ZCHAR|att);
lcd_putsnAtt(x+8, y, g_model.inputNames[idx-MIXSRC_FIRST_INPUT], LEN_INPUT_NAME, ZCHAR|att);
else
lcd_outdezNAtt(x+8, y, idx, att|LEADING0|LEFT, 2);
}
@ -723,7 +737,6 @@ void putsMixerSource(coord_t x, coord_t y, uint8_t idx, LcdFlags att)
lcd_putsiAtt(x, y, STR_VSRCRAW, idx, att);
else if (idx < MIXSRC_SW1)
putsSwitches(x, y, idx-MIXSRC_THR+1+3*(1/*+EXTRA_3POS*/), att);
// TODO would perhaps save flash if those switches were in VSRCRAW
#endif
else if (idx <= MIXSRC_LAST_LOGICAL_SWITCH)
putsSwitches(x, y, SWSRC_SW1+idx-MIXSRC_SW1, att);
@ -742,8 +755,26 @@ void putsMixerSource(coord_t x, coord_t y, uint8_t idx, LcdFlags att)
else if (idx <= MIXSRC_LAST_GVAR)
putsStrIdx(x, y, STR_GV, idx-MIXSRC_GVAR1+1, att);
#endif
else if (idx < MIXSRC_FIRST_TELEM) {
#if defined(PCBTARANIS)
lcd_putsiAtt(x, y, STR_VSRCRAW, idx-MIXSRC_Rud+1-NUM_LOGICAL_SWITCH-NUM_TRAINER-NUM_CHNOUT-MAX_GVARS, att);
#else
lcd_putsiAtt(x, y, STR_VSRCRAW, idx-MIXSRC_Rud+1-(MIXSRC_SW1-MIXSRC_THR)-NUM_LOGICAL_SWITCH-NUM_TRAINER-NUM_CHNOUT-MAX_GVARS, att);
#endif
}
#if defined(CPUARM)
else {
idx -= MIXSRC_FIRST_TELEM;
div_t qr = div(idx, 3);
lcd_putsnAtt(x, y, g_model.telemetrySensors[qr.quot].label, ZLEN(g_model.telemetrySensors[qr.quot].label), ZCHAR|att);
if (qr.rem) lcd_putcAtt(lcdLastPos, y, qr.rem==2 ? '+' : '-', att);
}
#else
else
lcd_putsiAtt(x, y, STR_VTELEMCHNS, idx-MIXSRC_FIRST_TELEM+1, att);
#endif
}
void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags att)
@ -905,8 +936,142 @@ void putsRotaryEncoderMode(coord_t x, coord_t y, uint8_t phase, uint8_t idx, Lcd
}
#endif
#if defined(FRSKY) || defined(CPUARM)
void putsTelemetryValue(coord_t x, coord_t y, lcdint_t val, uint8_t unit, LcdFlags att)
#if defined(CPUARM)
const pm_uint8_t bchunit_ar[] PROGMEM = {
UNIT_DIST, // Alt
UNIT_RAW, // Rpm
UNIT_PERCENT, // Fuel
UNIT_TEMPERATURE, // T1
UNIT_TEMPERATURE, // T2
UNIT_KTS, // Speed
UNIT_DIST, // Dist
UNIT_DIST, // GPS Alt
};
void putsValueWithUnit(coord_t x, coord_t y, lcdint_t val, uint8_t unit, LcdFlags att)
{
// convertUnit(val, unit);
lcd_outdezAtt(x, y, val, att & (~NO_UNIT));
if (!(att & NO_UNIT) && unit != UNIT_RAW) {
lcd_putsiAtt(lcdLastPos/*+1*/, y, STR_VTELEMUNIT, unit, 0);
}
}
void displayGpsCoord(coord_t x, coord_t y, char direction, int16_t bp, int16_t ap, LcdFlags att, bool seconds=true)
{
if (!direction) direction = '-';
lcd_outdezAtt(x, y, bp / 100, att); // ddd before '.'
lcd_putcAtt(lcdLastPos, y, '@', att);
uint8_t mn = bp % 100; // TODO div_t
if (g_eeGeneral.gpsFormat == 0) {
lcd_outdezNAtt(lcdNextPos, y, mn, att|LEFT|LEADING0, 2); // mm before '.'
lcd_vline(lcdLastPos, y, 2);
if (seconds) {
uint16_t ss = ap * 6 / 10;
lcd_outdezNAtt(lcdLastPos+3, y, ss / 100, att|LEFT|LEADING0, 2); // ''
lcd_plot(lcdLastPos, y+FH-2, 0); // small decimal point
lcd_outdezNAtt(lcdLastPos+2, y, ss % 100, att|LEFT|LEADING0, 2); // ''
lcd_vline(lcdLastPos, y, 2);
lcd_vline(lcdLastPos+2, y, 2);
}
lcd_putc(lcdLastPos+2, y, direction);
}
else {
lcd_outdezNAtt(lcdLastPos+FW, y, mn, att|LEFT|LEADING0, 2); // mm before '.'
lcd_plot(lcdLastPos, y+FH-2, 0); // small decimal point
lcd_outdezNAtt(lcdLastPos+2, y, ap, att|LEFT|UNSIGN|LEADING0, 4); // after '.'
lcd_putc(lcdLastPos+1, y, direction);
}
}
void displayDate(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags att)
{
if (att & DBLSIZE) {
x -= 42;
att &= ~0x0F00; // TODO constant
lcd_outdezNAtt(x, y, telemetryItem.datetime.day, att|LEADING0|LEFT, 2);
lcd_putcAtt(lcdLastPos-1, y, '-', att);
lcd_outdezNAtt(lcdNextPos-1, y, telemetryItem.datetime.month, att|LEFT, 2);
lcd_putcAtt(lcdLastPos-1, y, '-', att);
lcd_outdezAtt(lcdNextPos-1, y, telemetryItem.datetime.year, att|LEFT);
y += FH;
lcd_outdezNAtt(x, y, telemetryItem.datetime.hour, att|LEADING0|LEFT, 2);
lcd_putcAtt(lcdLastPos, y, ':', att);
lcd_outdezNAtt(lcdNextPos, y, telemetryItem.datetime.min, att|LEADING0|LEFT, 2);
lcd_putcAtt(lcdLastPos, y, ':', att);
lcd_outdezNAtt(lcdNextPos, y, telemetryItem.datetime.sec, att|LEADING0|LEFT, 2);
}
else {
lcd_outdezNAtt(x, y, telemetryItem.datetime.hour, att|LEADING0|LEFT, 2);
lcd_putcAtt(lcdLastPos, y, ':', att);
lcd_outdezNAtt(lcdNextPos, y, telemetryItem.datetime.min, att|LEADING0|LEFT, 2);
lcd_putcAtt(lcdLastPos, y, ':', att);
lcd_outdezNAtt(lcdNextPos, y, telemetryItem.datetime.sec, att|LEADING0|LEFT, 2);
}
}
void displayGpsCoords(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags att)
{
if (att & DBLSIZE) {
x -= (g_eeGeneral.gpsFormat == 0 ? 54 : 51);
att &= ~0x0F00; // TODO constant
displayGpsCoord(x, y, telemetryItem.gps.longitudeEW, telemetryItem.gps.longitude_bp, telemetryItem.gps.longitude_ap, att);
displayGpsCoord(x, y+FH, telemetryItem.gps.latitudeNS, telemetryItem.gps.latitude_bp, telemetryItem.gps.latitude_ap, att);
}
else {
displayGpsCoord(x, y, telemetryItem.gps.longitudeEW, telemetryItem.gps.longitude_bp, telemetryItem.gps.longitude_ap, att, false);
displayGpsCoord(lcdNextPos+FWNUM, y, telemetryItem.gps.latitudeNS, telemetryItem.gps.latitude_bp, telemetryItem.gps.latitude_ap, att, false);
}
}
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, lcdint_t value, LcdFlags att)
{
TelemetryItem & telemetryItem = telemetryItems[channel];
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[channel];
if (telemetrySensor.unit == UNIT_DATETIME) {
displayDate(x, y, telemetryItem, att);
}
else if (telemetrySensor.unit == UNIT_GPS) {
displayGpsCoords(x, y, telemetryItem, att);
}
else {
LcdFlags flags = att;
if (telemetrySensor.prec==2)
flags |= PREC2;
else if (telemetrySensor.prec==1)
flags |= PREC1;
putsValueWithUnit(x, y, value, telemetrySensor.unit == UNIT_CELLS ? UNIT_VOLTS : telemetrySensor.unit, flags);
}
}
void putsChannelValue(coord_t x, coord_t y, source_t channel, lcdint_t value, LcdFlags att)
{
if (channel >= MIXSRC_FIRST_TELEM) {
channel = (channel-MIXSRC_FIRST_TELEM) / 3;
putsTelemetryChannelValue(x, y, channel, value, att);
}
else if (channel >= MIXSRC_FIRST_TIMER || channel == MIXSRC_TX_TIME) {
putsTimer(x, y, value, att, att);
}
else if (channel == MIXSRC_TX_VOLTAGE) {
lcd_outdezAtt(x, y, value, att|PREC1);
}
else {
if (channel <= MIXSRC_LAST_CH) {
value = calcRESXto100(value);
}
lcd_outdezAtt(x, y, value, att);
}
}
void putsChannel(coord_t x, coord_t y, source_t channel, LcdFlags att)
{
getvalue_t value = getValue(channel);
putsChannelValue(x, y, channel, value, att);
}
#elif defined(FRSKY)
void putsValueWithUnit(coord_t x, coord_t y, lcdint_t val, uint8_t unit, LcdFlags att)
{
convertUnit(val, unit);
lcd_outdezAtt(x, y, val, att & (~NO_UNIT));
@ -926,7 +1091,7 @@ const pm_uint8_t bchunit_ar[] PROGMEM = {
UNIT_DIST, // GPS Alt
};
void putsTelemetryChannel(coord_t x, coord_t y, uint8_t channel, lcdint_t val, LcdFlags att)
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, lcdint_t val, LcdFlags att)
{
switch (channel) {
#if defined(CPUARM) && defined(RTCLOCK)
@ -979,14 +1144,14 @@ void putsTelemetryChannel(coord_t x, coord_t y, uint8_t channel, lcdint_t val, L
}
#endif
}
putsTelemetryValue(x, y, converted_value, g_model.frsky.channels[channel].type, att);
putsValueWithUnit(x, y, converted_value, g_model.frsky.channels[channel].type, att);
break;
}
#endif
case TELEM_CELL-1:
case TELEM_MIN_CELL-1:
putsTelemetryValue(x, y, val, UNIT_VOLTS, att|PREC2);
putsValueWithUnit(x, y, val, UNIT_VOLTS, att|PREC2);
break;
case TELEM_TX_VOLTAGE-1:
@ -994,36 +1159,36 @@ void putsTelemetryChannel(coord_t x, coord_t y, uint8_t channel, lcdint_t val, L
case TELEM_CELLS_SUM-1:
case TELEM_MIN_CELLS_SUM-1:
case TELEM_MIN_VFAS-1:
putsTelemetryValue(x, y, val, UNIT_VOLTS, att|PREC1);
putsValueWithUnit(x, y, val, UNIT_VOLTS, att|PREC1);
break;
case TELEM_CURRENT-1:
case TELEM_MAX_CURRENT-1:
putsTelemetryValue(x, y, val, UNIT_AMPS, att|PREC1);
putsValueWithUnit(x, y, val, UNIT_AMPS, att|PREC1);
break;
case TELEM_CONSUMPTION-1:
putsTelemetryValue(x, y, val, UNIT_MAH, att);
putsValueWithUnit(x, y, val, UNIT_MAH, att);
break;
case TELEM_POWER-1:
case TELEM_MAX_POWER-1:
putsTelemetryValue(x, y, val, UNIT_WATTS, att);
putsValueWithUnit(x, y, val, UNIT_WATTS, att);
break;
case TELEM_ACCx-1:
case TELEM_ACCy-1:
case TELEM_ACCz-1:
putsTelemetryValue(x, y, val, UNIT_RAW, att|PREC2);
putsValueWithUnit(x, y, val, UNIT_RAW, att|PREC2);
break;
case TELEM_VSPEED-1:
putsTelemetryValue(x, y, div10_and_round(val), UNIT_RAW, att|PREC1);
putsValueWithUnit(x, y, div10_and_round(val), UNIT_RAW, att|PREC1);
break;
case TELEM_ASPEED-1:
case TELEM_MAX_ASPEED-1:
putsTelemetryValue(x, y, val, UNIT_KTS, att|PREC1);
putsValueWithUnit(x, y, val, UNIT_KTS, att|PREC1);
break;
#if defined(CPUARM)
@ -1031,23 +1196,23 @@ void putsTelemetryChannel(coord_t x, coord_t y, uint8_t channel, lcdint_t val, L
#endif
case TELEM_RSSI_TX-1:
case TELEM_RSSI_RX-1:
putsTelemetryValue(x, y, val, UNIT_RAW, att);
putsValueWithUnit(x, y, val, UNIT_RAW, att);
break;
case TELEM_HDG-1:
putsTelemetryValue(x, y, val, UNIT_HDG, att);
putsValueWithUnit(x, y, val, UNIT_HDG, att);
break;
#if defined(FRSKY_SPORT)
case TELEM_ALT-1:
putsTelemetryValue(x, y, div10_and_round(val), UNIT_DIST, att|PREC1);
putsValueWithUnit(x, y, div10_and_round(val), UNIT_DIST, att|PREC1);
break;
#elif defined(WS_HOW_HIGH)
case TELEM_ALT-1:
case TELEM_MIN_ALT-1:
case TELEM_MAX_ALT-1:
if (IS_IMPERIAL_ENABLE() && IS_USR_PROTO_WS_HOW_HIGH()) {
putsTelemetryValue(x, y, val, UNIT_FEET, att);
putsValueWithUnit(x, y, val, UNIT_FEET, att);
break;
}
// no break
@ -1062,13 +1227,13 @@ void putsTelemetryChannel(coord_t x, coord_t y, uint8_t channel, lcdint_t val, L
unit = channel + 1 - TELEM_ALT;
if (channel >= TELEM_MIN_ALT-1 && channel <= TELEM_MAX_ALT-1)
unit = 0;
putsTelemetryValue(x, y, val, pgm_read_byte(bchunit_ar+unit), att);
putsValueWithUnit(x, y, val, pgm_read_byte(bchunit_ar+unit), att);
break;
}
}
}
#else // defined(FRSKY)
void putsTelemetryChannel(coord_t x, coord_t y, uint8_t channel, lcdint_t val, uint8_t att)
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, lcdint_t val, uint8_t att)
{
switch (channel) {
case TELEM_TIMER1-1:

View file

@ -109,41 +109,7 @@ const pm_char * openLogs()
}
if (f_size(&g_oLogFile) == 0) {
#if defined(RTCLOCK)
f_puts("Date,Time,", &g_oLogFile);
#else
f_puts("Time,", &g_oLogFile);
#endif
#if defined(FRSKY)
#if defined(CPUARM) && defined(SWR)
f_puts("SWR,RSSI,A1,A2,A3,A4,", &g_oLogFile);
#elif defined(CPUARM)
f_puts("RSSI,A1,A2,A3,A4,", &g_oLogFile);
#else
f_puts("Buffer,RX,TX,A1,A2,", &g_oLogFile);
#endif
#endif
#if defined(FRSKY_HUB)
if (IS_USR_PROTO_FRSKY_HUB()) {
f_puts("GPS Date,GPS Time,Long,Lat,Course,GPS Speed(kts),GPS Alt,Baro Alt(", &g_oLogFile);
f_puts(TELEMETRY_BARO_ALT_UNIT, &g_oLogFile);
f_puts("),Vertical Speed,Air Speed(kts),Temp1,Temp2,RPM,Fuel," TELEMETRY_CELLS_LABEL "Current,Consumption,Vfas,AccelX,AccelY,AccelZ,", &g_oLogFile);
}
#endif
#if defined(WS_HOW_HIGH)
if (IS_USR_PROTO_WS_HOW_HIGH()) {
f_puts("WSHH Alt,", &g_oLogFile);
}
#endif
#if defined(PCBTARANIS)
f_puts("Rud,Ele,Thr,Ail,S1,S2,S3,LS,RS,SA,SB,SC,SD,SE,SF,SG,SH\n", &g_oLogFile);
#else
f_puts("Rud,Ele,Thr,Ail,P1,P2,P3,THR,RUD,ELE,3POS,AIL,GEA,TRN\n", &g_oLogFile);
#endif
writeHeader();
}
else {
result = f_lseek(&g_oLogFile, f_size(&g_oLogFile)); // append
@ -166,11 +132,68 @@ void closeLogs()
lastLogTime = 0;
}
#if !defined(CPUARM)
getvalue_t getConvertedTelemetryValue(getvalue_t val, uint8_t unit)
{
convertUnit(val, unit);
return val;
}
#endif
void writeHeader()
{
#if defined(RTCLOCK)
f_puts("Date,Time,", &g_oLogFile);
#else
f_puts("Time,", &g_oLogFile);
#endif
#if defined(FRSKY)
#if defined(CPUARM) && defined(SWR)
f_puts("SWR,RSSI,", &g_oLogFile);
#elif defined(CPUARM)
f_puts("RSSI,", &g_oLogFile);
#else
f_puts("Buffer,RX,TX,A1,A2,", &g_oLogFile);
#if defined(FRSKY_HUB)
if (IS_USR_PROTO_FRSKY_HUB()) {
f_puts("GPS Date,GPS Time,Long,Lat,Course,GPS Speed(kts),GPS Alt,Baro Alt(", &g_oLogFile);
f_puts(TELEMETRY_BARO_ALT_UNIT, &g_oLogFile);
f_puts("),Vertical Speed,Air Speed(kts),Temp1,Temp2,RPM,Fuel," TELEMETRY_CELLS_LABEL "Current,Consumption,Vfas,AccelX,AccelY,AccelZ,", &g_oLogFile);
}
#endif
#if defined(WS_HOW_HIGH)
if (IS_USR_PROTO_WS_HOW_HIGH()) {
f_puts("WSHH Alt,", &g_oLogFile);
}
#endif
#endif
#if defined(CPUARM)
char label[TELEM_LABEL_LEN+7];
for (int i=0; i<TELEM_VALUES_MAX; i++) {
TelemetrySensor & sensor = g_model.telemetrySensors[i];
if (sensor.logs) {
memset(label, 0, sizeof(label));
zchar2str(label, sensor.label, TELEM_LABEL_LEN);
if (sensor.unit != UNIT_RAW) {
strcat(label, "(");
strncat(label, STR_VTELEMUNIT+1+3*sensor.unit, 3);
strcat(label, ")");
}
strcat(label, ",");
f_puts(label, &g_oLogFile);
}
}
#endif
#endif
#if defined(PCBTARANIS)
f_puts("Rud,Ele,Thr,Ail,S1,S2,S3,LS,RS,SA,SB,SC,SD,SE,SF,SG,SH\n", &g_oLogFile);
#else
f_puts("Rud,Ele,Thr,Ail,P1,P2,P3,THR,RUD,ELE,3POS,AIL,GEA,TRN\n", &g_oLogFile);
#endif
}
// TODO test when disk full
void writeLogs()
@ -204,23 +227,21 @@ void writeLogs()
}
f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d.%02d0,", utm.tm_year+1900, utm.tm_mon+1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec, g_ms100);
}
#else // #if defined(RTCLOCK)
#else
f_printf(&g_oLogFile, "%d,", tmr10ms);
#endif // #if defined(RTCLOCK)
#endif
#if defined(FRSKY)
#if defined(CPUARM) && defined(SWR)
f_printf(&g_oLogFile, "%d,%d,", RAW_FRSKY_MINMAX(frskyData.swr), RAW_FRSKY_MINMAX(frskyData.rssi[0]));
f_printf(&g_oLogFile, "%d,%d,", RAW_FRSKY_MINMAX(frskyData.swr), RAW_FRSKY_MINMAX(frskyData.rssi));
#elif defined(CPUARM)
f_printf(&g_oLogFile, "%d,", RAW_FRSKY_MINMAX(frskyData.rssi[0]));
f_printf(&g_oLogFile, "%d,", RAW_FRSKY_MINMAX(frskyData.rssi));
#else
f_printf(&g_oLogFile, "%d,%d,%d,", frskyStreaming, RAW_FRSKY_MINMAX(frskyData.rssi[0]), RAW_FRSKY_MINMAX(frskyData.rssi[1]));
#endif
for (uint8_t i=0; i<MAX_FRSKY_A_CHANNELS; i++) {
int16_t converted_value = applyChannelRatio(i, RAW_FRSKY_MINMAX(frskyData.analog[i]));
f_printf(&g_oLogFile, "%d.%02d,", converted_value/100, converted_value%100);
}
#endif
#if defined(FRSKY_HUB)
TELEMETRY_BARO_ALT_PREPARE();
@ -264,6 +285,28 @@ void writeLogs()
if (IS_USR_PROTO_WS_HOW_HIGH()) {
f_printf(&g_oLogFile, "%d,", TELEMETRY_RELATIVE_BARO_ALT_BP);
}
#endif
#endif
#if defined(CPUARM)
for (int i=0; i<TELEM_VALUES_MAX; i++) {
TelemetrySensor & sensor = g_model.telemetrySensors[i];
TelemetryItem & telemetryItem = telemetryItems[i];
if (sensor.logs) {
if (sensor.prec == 2) {
div_t qr = div(telemetryItem.value, 100);
f_printf(&g_oLogFile, "%d.%02d,", qr.quot, qr.rem);
}
else if (sensor.prec == 1) {
div_t qr = div(telemetryItem.value, 10);
f_printf(&g_oLogFile, "%d.%d,", qr.quot, qr.rem);
}
else {
f_printf(&g_oLogFile, "%d,", telemetryItem.value);
}
}
}
#endif
#endif
for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) {

View file

@ -130,61 +130,25 @@ static int luaGetDateTime(lua_State *L)
static void luaGetValueAndPush(int src)
{
getvalue_t value = getValue(src);
if (src >= MIXSRC_FIRST_TELEM && src <= MIXSRC_LAST_TELEM) {
src = (src-MIXSRC_FIRST_TELEM) / 3;
// telemetry values
if ((src != MIXSRC_FIRST_TELEM-1+TELEM_TX_VOLTAGE) && !TELEMETRY_STREAMING()) {
if (TELEMETRY_STREAMING() && telemetryItems[src].isAvailable()) {
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[src];
if (telemetrySensor.prec > 0)
lua_pushnumber(L, float(value)/(telemetrySensor.prec == 2 ? 100.0 : 10.0));
else
lua_pushinteger(L, value);
}
else {
// telemetry not working, return zero for telemetry sources
// except for "tx voltage"
lua_pushinteger(L, (int)0);
return;
}
}
int idx = src;
switch (src) {
case MIXSRC_FIRST_TELEM-1+TELEM_TX_VOLTAGE:
case MIXSRC_FIRST_TELEM-1+TELEM_VFAS:
case MIXSRC_FIRST_TELEM-1+TELEM_MIN_VFAS:
case MIXSRC_FIRST_TELEM-1+TELEM_CELLS_SUM:
case MIXSRC_FIRST_TELEM-1+TELEM_MIN_CELLS_SUM:
case MIXSRC_FIRST_TELEM-1+TELEM_CURRENT:
case MIXSRC_FIRST_TELEM-1+TELEM_MAX_CURRENT:
case MIXSRC_FIRST_TELEM-1+TELEM_ASPEED:
case MIXSRC_FIRST_TELEM-1+TELEM_MAX_ASPEED:
// these need to be divided by 10
lua_pushnumber(L, getValue(src)/10.0);
break;
case MIXSRC_FIRST_TELEM-1+TELEM_MIN_A1:
case MIXSRC_FIRST_TELEM-1+TELEM_MIN_A2:
case MIXSRC_FIRST_TELEM-1+TELEM_MIN_A3:
case MIXSRC_FIRST_TELEM-1+TELEM_MIN_A4:
idx -= TELEM_MIN_A1-TELEM_A1;
// no break
case MIXSRC_FIRST_TELEM-1+TELEM_A1:
case MIXSRC_FIRST_TELEM-1+TELEM_A2:
case MIXSRC_FIRST_TELEM-1+TELEM_A3:
case MIXSRC_FIRST_TELEM-1+TELEM_A4:
// convert raw Ax values to calibrated values
idx -= (MIXSRC_FIRST_TELEM+TELEM_A1-1);
lua_pushnumber(L, applyChannelRatio(idx, getValue(src))/100.0);
break;
case MIXSRC_FIRST_TELEM-1+TELEM_CELL:
case MIXSRC_FIRST_TELEM-1+TELEM_MIN_CELL:
case MIXSRC_FIRST_TELEM-1+TELEM_ALT:
case MIXSRC_FIRST_TELEM-1+TELEM_ACCx:
case MIXSRC_FIRST_TELEM-1+TELEM_ACCy:
case MIXSRC_FIRST_TELEM-1+TELEM_ACCz:
case MIXSRC_FIRST_TELEM-1+TELEM_VSPEED:
// these need to be divided by 100
lua_pushnumber(L, getValue(src)/100.0);
break;
//TODO: add other values that need special treatment
default:
lua_pushinteger(L, getValue(src));
else {
lua_pushinteger(L, value);
}
}
@ -244,6 +208,33 @@ bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags=
}
}
}
// search in telemetry
field.desc[0] = '\0';
for (int i=0; i<TELEM_VALUES_MAX; i++) {
if (isTelemetryFieldAvailable(i)) {
char sensorName[TELEM_LABEL_LEN+1];
int len = zchar2str(sensorName, g_model.telemetrySensors[i].label, TELEM_LABEL_LEN);
if (!strncmp(sensorName, name, len)) {
if (name[len] == '\0') {
field.id = MIXSRC_FIRST_TELEM + 3*i;
field.desc[0] = '\0';
return true;
}
else if (name[len] == '-' && name[len+1] == '\0') {
field.id = MIXSRC_FIRST_TELEM + 3*i + 1;
field.desc[0] = '\0';
return true;
}
else if (name[len] == '+' && name[len+1] == '\0') {
field.id = MIXSRC_FIRST_TELEM + 3*i + 2;
field.desc[0] = '\0';
return true;
}
}
}
}
return false; // not found
}
@ -278,10 +269,6 @@ static int luaGetValue(lua_State *L)
src = field.id;
}
}
if (src >= EXTRA_FIRST ) {
// one of the extra fields
return luaGetExtraValue(src);
}
luaGetValueAndPush(src);
return 1;
}
@ -434,7 +421,7 @@ static int luaLcdDrawChannel(lua_State *L)
}
int att = luaL_checkinteger(L, 4);
getvalue_t value = getValue(channel);
putsTelemetryChannel(x, y, channel-MIXSRC_FIRST_TELEM, value, att);
putsTelemetryChannelValue(x, y, channel-MIXSRC_FIRST_TELEM, value, att);
return 0;
}
@ -1202,120 +1189,6 @@ static int luaModelSetGlobalVariable(lua_State *L)
return 0;
}
static int luaModelGetTelemetryChannel(lua_State *L)
{
int idx = luaL_checkunsigned(L, 1);
if (idx < MAX_FRSKY_A_CHANNELS) {
FrSkyChannelData & channel = g_model.frsky.channels[idx];
lua_newtable(L);
double range = applyChannelRatio(idx, 255-channel.offset);
double offset = applyChannelRatio(idx, 0);
double alarm1 = applyChannelRatio(idx, channel.alarms_value[0]);
double alarm2 = applyChannelRatio(idx, channel.alarms_value[1]);
if (ANA_CHANNEL_UNIT(idx) >= UNIT_RAW) {
range /= 10;
offset /= 10;
alarm1 /= 10;
alarm2 /= 10;
}
else {
range /= 100;
offset /= 100;
alarm1 /= 100;
alarm2 /= 100;
}
lua_pushtablenumber(L, "range", range);
lua_pushtablenumber(L, "offset", offset);
lua_pushtablenumber(L, "alarm1", alarm1);
lua_pushtablenumber(L, "alarm2", alarm2);
lua_pushtableinteger(L, "unit", channel.type);
}
else {
lua_pushnil(L);
}
return 1;
}
int findmult(float value, float base)
{
int vvalue = value*10;
int vbase = base*10;
vvalue--;
int mult = 0;
for (int i=8; i>=0; i--) {
if (vvalue/vbase >= (1<<i)) {
mult = i+1;
break;
}
}
return mult;
}
static int luaModelSetTelemetryChannel(lua_State *L)
{
int idx = luaL_checkunsigned(L, 1);
if (idx < MAX_FRSKY_A_CHANNELS) {
FrSkyChannelData & channel = g_model.frsky.channels[idx];
double range = applyChannelRatio(idx, 255-channel.offset);
double offset = applyChannelRatio(idx, 0);
double alarm1 = applyChannelRatio(idx, channel.alarms_value[0]);
double alarm2 = applyChannelRatio(idx, channel.alarms_value[1]);
if (ANA_CHANNEL_UNIT(idx) >= UNIT_RAW) {
range /= 10;
offset /= 10;
alarm1 /= 10;
alarm2 /= 10;
}
else {
range /= 100;
offset /= 100;
alarm1 /= 100;
alarm2 /= 100;
}
luaL_checktype(L, -1, LUA_TTABLE);
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
luaL_checktype(L, -2, LUA_TSTRING); // key is string
const char * key = luaL_checkstring(L, -2);
if (!strcmp(key, "unit")) {
channel.type = luaL_checkinteger(L, -1);
}
else if (!strcmp(key, "range")) {
range = luaL_checknumber(L, -1);
double value = range;
if (ANA_CHANNEL_UNIT(idx) < UNIT_RAW) {
value *= 10;
}
channel.multiplier = findmult(value, 255);
channel.ratio = (int)(round(value)) / (1<<channel.multiplier);
}
else if (!strcmp(key, "offset")) {
offset = luaL_checknumber(L, -1);
}
else if (!strcmp(key, "alarm1")) {
alarm1 = luaL_checknumber(L, -1);
}
else if (!strcmp(key, "alarm2")) {
alarm2 = luaL_checknumber(L, -1);
}
}
if (range > 0) {
channel.offset = round((offset * 255) / range);
channel.alarms_value[0] = limit<int>(0, round((alarm1-offset)*255/range), 255);
channel.alarms_value[1] = limit<int>(0, round((alarm2-offset)*255/range), 255);
}
else {
channel.offset = 0;;
channel.alarms_value[0] = 0;
channel.alarms_value[1] = 0;
}
eeDirty(EE_MODEL);
}
return 0;
}
static int luaPopupInput(lua_State *L)
{
uint8_t event = luaL_checkinteger(L, 2);
@ -1534,8 +1407,6 @@ const luaL_Reg modelLib[] = {
{ "setOutput", luaModelSetOutput },
{ "getGlobalVariable", luaModelGetGlobalVariable },
{ "setGlobalVariable", luaModelSetGlobalVariable },
{ "getTelemetryChannel", luaModelGetTelemetryChannel },
{ "setTelemetryChannel", luaModelSetTelemetryChannel },
{ NULL, NULL } /* sentinel */
};
@ -1991,6 +1862,7 @@ void luaDoOneRunPermanentScript(uint8_t evt, int i)
return;
}
}
if (lua_pcall(L, inputsCount, sio ? sio->outputsCount : 0, 0) == 0) {
if (sio) {
for (int j=sio->outputsCount-1; j>=0; j--) {

View file

@ -116,7 +116,7 @@ int8_t calcRESXto100(int16_t x)
}
#endif
#if defined(HELI) || defined(FRSKY_HUB)
#if defined(HELI) || defined(FRSKY_HUB) || defined(CPUARM)
uint16_t isqrt32(uint32_t n)
{
uint16_t c = 0x8000;
@ -154,6 +154,17 @@ getvalue_t div10_and_round(getvalue_t value)
return value/10;
}
getvalue_t div100_and_round(getvalue_t value)
{
if (value >= 0 ) {
value += 50;
}
else {
value -= 50;
}
return value/100;
}
#if defined(PCBTARANIS)
double gpsToDouble(bool neg, int16_t bp, int16_t ap)
{
@ -166,7 +177,7 @@ double gpsToDouble(bool neg, int16_t bp, int16_t ap)
}
#endif
#if defined(FRSKY_HUB)
#if defined(FRSKY_HUB) && !defined(CPUARM)
void extractLatitudeLongitude(uint32_t * latitude, uint32_t * longitude)
{
div_t qr = div(frskyData.hub.gpsLatitude_bp, 100);
@ -176,17 +187,8 @@ void extractLatitudeLongitude(uint32_t * latitude, uint32_t * longitude)
*longitude = ((uint32_t)(qr.quot) * 1000000) + (((uint32_t)(qr.rem) * 10000 + frskyData.hub.gpsLongitude_ap) * 5) / 3;
}
#if defined(PCBTARANIS)
double pilotLatitude;
double pilotLongitude;
#endif
void getGpsPilotPosition()
{
#if defined(PCBTARANIS)
pilotLatitude = gpsToDouble(frskyData.hub.gpsLatitudeNS=='S', frskyData.hub.gpsLatitude_bp, frskyData.hub.gpsLatitude_ap);
pilotLongitude = gpsToDouble(frskyData.hub.gpsLongitudeEW=='W', frskyData.hub.gpsLongitude_bp, frskyData.hub.gpsLongitude_ap);
#endif
extractLatitudeLongitude(&frskyData.hub.pilotLatitude, &frskyData.hub.pilotLongitude);
uint32_t lat = frskyData.hub.pilotLatitude / 10000;
uint32_t angle2 = (lat*lat) / 10000;

View file

@ -327,23 +327,39 @@ getvalue_t getValue(uint8_t i)
else if (i<=MIXSRC_LAST_GVAR) return GVAR_VALUE(i-MIXSRC_GVAR1, getGVarFlightPhase(mixerCurrentFlightMode, i-MIXSRC_GVAR1));
#endif
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_TX_VOLTAGE) return g_vbat100mV;
#if defined(CPUARM) && defined(RTCLOCK)
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_TX_TIME) return (g_rtcTime % SECS_PER_DAY) / 60; // number of minutes from midnight
#endif
else if (i<=MIXSRC_FIRST_TELEM-1+TELEM_TIMER_MAX) return timersStates[i-MIXSRC_FIRST_TELEM+1-TELEM_TIMER1].val;
#if defined(FRSKY)
#if defined(CPUARM)
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_SWR) return frskyData.swr.value;
else if (i==MIXSRC_TX_VOLTAGE) return g_vbat100mV;
else if (i<MIXSRC_FIRST_TIMER) // TX_TIME + SPARES
#if defined(RTCLOCK)
return (g_rtcTime % SECS_PER_DAY) / 60; // number of minutes from midnight
#else
return 0;
#endif
else if (i<=MIXSRC_LAST_TIMER) return timersStates[i-MIXSRC_FIRST_TIMER].val;
#else
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_TX_VOLTAGE) return g_vbat100mV;
else if (i<=MIXSRC_FIRST_TELEM-1+TELEM_TIMER2) return timersStates[i-MIXSRC_FIRST_TELEM+1-TELEM_TIMER1].val;
#endif
#if defined(CPUARM)
else if (i<=MIXSRC_LAST_TELEM) {
i -= MIXSRC_FIRST_TELEM;
div_t qr = div(i, 3);
TelemetryItem & telemetryItem = telemetryItems[qr.quot];
switch (qr.rem) {
case 1:
return telemetryItem.valueMin;
case 2:
return telemetryItem.valueMax;
default:
return telemetryItem.value;
}
}
#elif defined(FRSKY)
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_RSSI_TX) return frskyData.rssi[1].value;
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_RSSI_RX) return frskyData.rssi[0].value;
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_A1) return frskyData.analog[TELEM_ANA_A1].value;
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_A2) return frskyData.analog[TELEM_ANA_A2].value;
#if defined(CPUARM)
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_A3) return frskyData.analog[TELEM_ANA_A3].value;
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_A4) return frskyData.analog[TELEM_ANA_A4].value;
#endif
#if defined(FRSKY_SPORT)
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_ALT) return frskyData.hub.baroAltitude;
#elif defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
@ -372,10 +388,6 @@ getvalue_t getValue(uint8_t i)
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_DTE) return frskyData.hub.dTE;
else if (i<=MIXSRC_FIRST_TELEM-1+TELEM_MIN_A1) return frskyData.analog[TELEM_ANA_A1].min;
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_MIN_A2) return frskyData.analog[TELEM_ANA_A2].min;
#if defined(CPUARM)
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_MIN_A3) return frskyData.analog[TELEM_ANA_A3].min;
else if (i==MIXSRC_FIRST_TELEM-1+TELEM_MIN_A4) return frskyData.analog[TELEM_ANA_A4].min;
#endif
else if (i<=MIXSRC_FIRST_TELEM-1+TELEM_CSW_MAX) return *(((int16_t*)(&frskyData.hub.minAltitude))+i-(MIXSRC_FIRST_TELEM-1+TELEM_MIN_ALT));
#endif
#endif

View file

@ -107,10 +107,10 @@
#define MAX_MODELS 60
#define NUM_CHNOUT 32 // number of real output channels CH1-CH32
#define MAX_FLIGHT_MODES 9
#define MAX_MIXERS 64
#define MAX_MIXERS 60
#define MAX_EXPOS 32
#define NUM_LOGICAL_SWITCH 32 // number of custom switches
#define NUM_CFN 64 // number of functions assigned to switches
#define NUM_CFN 60 // number of functions assigned to switches
#define NUM_TRAINER 16
#define NUM_POTS 3
#define NUM_XPOTS 0
@ -204,6 +204,12 @@ PACK(typedef struct {
typedef int16_t gvar_t;
#if defined(PCBTARANIS)
typedef uint16_t source_t;
#else
typedef uint8_t source_t;
#endif
#if !defined(PCBSTD)
#define LEN_GVAR_NAME 6
#define GVAR_MAX 1024
@ -238,18 +244,18 @@ typedef int16_t gvar_t;
#define GVAR_VALUE(x, p) g_model.flightModeData[p].gvars[x]
#endif
PACK(typedef struct t_TrainerMix {
PACK(typedef struct {
uint8_t srcChn:6; // 0-7 = ch1-8
uint8_t mode:2; // off,add-mode,subst-mode
int8_t studWeight;
}) TrainerMix;
PACK(typedef struct t_TrainerData {
PACK(typedef struct {
int16_t calib[4];
TrainerMix mix[4];
}) TrainerData;
PACK(typedef struct t_FrSkyRSSIAlarm {
PACK(typedef struct {
int8_t level:2;
int8_t value:6;
}) FrSkyRSSIAlarm;
@ -368,7 +374,7 @@ PACK(typedef struct {
};
#define IS_TRAINER_EXTERNAL_MODULE() (g_model.trainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || g_model.trainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)
#define MODELDATA_BITMAP char bitmap[LEN_BITMAP_NAME];
#define MODELDATA_EXTRA uint8_t externalModule; uint8_t trainerMode; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t nPotsToWarn; int8_t potPosition[NUM_POTS]; uint8_t spare[2];
#define MODELDATA_EXTRA uint8_t externalModule; uint8_t trainerMode; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t nPotsToWarn; int8_t potPosition[NUM_POTS];
#define swstate_t uint16_t
#elif defined(PCBSKY9X)
enum ModuleIndex {
@ -689,9 +695,9 @@ PACK(typedef struct {
#if defined(PCBTARANIS)
PACK(typedef struct {
uint8_t srcRaw;
uint16_t scale;
uint8_t chn;
uint32_t srcRaw:10;
uint32_t scale:14;
uint32_t chn:8;
int8_t swtch;
uint16_t flightModes;
int8_t weight;
@ -700,18 +706,17 @@ PACK(typedef struct {
char name[LEN_EXPOMIX_NAME];
int8_t offset;
CurveRef curve;
uint8_t spare;
}) ExpoData;
#define MIN_EXPO_WEIGHT -100
#define EXPO_VALID(ed) ((ed)->mode)
#define EXPO_MODE_ENABLE(ed, v) (((v)<0 && ((ed)->mode&1)) || ((v)>=0 && ((ed)->mode&2)))
#elif defined(CPUARM)
PACK(typedef struct {
uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
uint8_t chn:4;
uint8_t curveMode:2;
uint16_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
uint16_t chn:3;
uint16_t curveMode:2;
uint16_t flightModes:9;
int8_t swtch;
uint16_t flightModes;
int8_t weight;
char name[LEN_EXPOMIX_NAME];
int8_t curveParam;
@ -720,7 +725,7 @@ PACK(typedef struct {
#define EXPO_VALID(ed) ((ed)->mode)
#define EXPO_MODE_ENABLE(ed, v) (((v)<0 && ((ed)->mode&1)) || ((v)>=0 && ((ed)->mode&2)))
#elif defined(CPUM2560) || defined(CPUM2561)
PACK(typedef struct t_ExpoData {
PACK(typedef struct {
uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
uint8_t chn:2;
uint8_t curveMode:1;
@ -734,7 +739,7 @@ PACK(typedef struct t_ExpoData {
#define EXPO_VALID(ed) ((ed)->mode)
#define EXPO_MODE_ENABLE(ed, v) (((v)<0 && ((ed)->mode&1)) || ((v)>=0 && ((ed)->mode&2)))
#else
PACK(typedef struct t_ExpoData {
PACK(typedef struct {
uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both
int8_t swtch:6;
uint8_t chn:2;
@ -773,19 +778,19 @@ PACK(typedef struct t_ExpoData {
#endif
#if defined(PCBTARANIS)
PACK(typedef struct t_LimitData {
int16_t min:11;
int16_t max:11;
PACK(typedef struct {
int32_t min:11;
int32_t max:11;
int32_t ppmCenter:10;
int16_t offset:11;
int16_t ppmCenter:11;
uint8_t symetrical:1;
uint8_t revert:1;
uint8_t spare:2;
uint16_t symetrical:1;
uint16_t revert:1;
uint16_t spare:3;
int8_t curve;
char name[LEN_CHANNEL_NAME];
}) LimitData;
#else
PACK(typedef struct t_LimitData {
PACK(typedef struct {
int8_t min;
int8_t max;
int8_t ppmCenter;
@ -819,18 +824,18 @@ PACK(typedef struct t_LimitData {
PACK(typedef struct {
uint8_t destCh;
uint16_t flightModes:9;
uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
uint8_t carryTrim:1;
uint8_t mixWarn:4; // mixer warning
uint16_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
uint16_t carryTrim:1;
uint16_t mixWarn:4; // mixer warning
int16_t weight;
int8_t swtch;
uint32_t srcRaw:10;
int32_t offset:14;
int32_t swtch:8;
CurveRef curve;
uint8_t delayUp;
uint8_t delayDown;
uint8_t speedUp;
uint8_t speedDown;
uint8_t srcRaw;
int16_t offset;
char name[LEN_EXPOMIX_NAME];
}) MixData;
#else
@ -884,7 +889,7 @@ PACK( union u_int8int16_t {
#define SLOW_MAX 15 /* 7.5 seconds */
#if defined(CPUM2560) || defined(CPUM2561)
PACK(typedef struct t_MixData {
PACK(typedef struct {
uint8_t destCh:4; // 0, 1..NUM_CHNOUT
uint8_t curveMode:1; // O=curve, 1=differential
uint8_t noExpo:1;
@ -906,7 +911,7 @@ PACK(typedef struct t_MixData {
int8_t offset;
}) MixData;
#else
PACK(typedef struct t_MixData {
PACK(typedef struct {
uint8_t destCh:4; // 0, 1..NUM_CHNOUT
uint8_t curveMode:1; // O=curve, 1=differential
uint8_t noExpo:1;
@ -927,7 +932,7 @@ PACK(typedef struct t_MixData {
int8_t offset;
}) MixData;
#endif
PACK( union u_gvarint_t {
PACK(union u_gvarint_t {
struct {
int8_t lo;
uint8_t hi;
@ -943,7 +948,7 @@ private:
});
#define MD_WEIGHT(md) (u_gvarint_t(md->weight,md->weightMode).word)
PACK( union u_int8int16_t {
PACK(union u_int8int16_t {
struct {
int8_t lo;
uint8_t hi;
@ -997,11 +1002,11 @@ enum LogicalSwitchesFunctions {
#define MAX_LS_DELAY 250 /*25s*/
#define MAX_LS_ANDSW SWSRC_LAST
typedef int16_t ls_telemetry_value_t;
PACK(typedef struct t_LogicalSwitchData { // Logical Switches data
int8_t v1;
PACK(typedef struct { // Logical Switches data
uint16_t func:6;
int16_t v1:10;
int16_t v2;
int16_t v3;
uint8_t func;
uint8_t delay;
uint8_t duration;
int8_t andsw;
@ -1009,7 +1014,7 @@ PACK(typedef struct t_LogicalSwitchData { // Logical Switches data
#else
typedef uint8_t ls_telemetry_value_t;
#define MAX_LS_ANDSW 15
PACK(typedef struct t_LogicalSwitchData { // Logical Switches data
PACK(typedef struct { // Logical Switches data
int8_t v1; //input
int8_t v2; //offset
uint8_t func:4;
@ -1017,6 +1022,48 @@ PACK(typedef struct t_LogicalSwitchData { // Logical Switches data
}) LogicalSwitchData;
#endif
#if defined(CPUARM)
enum TelemetryUnit {
UNIT_RAW,
UNIT_VOLTS,
UNIT_AMPS,
UNIT_MILLIAMPS,
UNIT_KTS,
UNIT_METERS_PER_SECOND,
UNIT_KMH,
UNIT_MPH,
UNIT_METERS,
UNIT_FEET,
UNIT_CELSIUS,
UNIT_FAHRENHEIT,
UNIT_PERCENT,
UNIT_MAH,
UNIT_WATTS,
UNIT_DBM,
UNIT_RPMS,
UNIT_G,
UNIT_DEGREE,
UNIT_HOURS,
UNIT_MINUTES,
UNIT_SECONDS,
// FrSky format used for these fields, could be another format in the future
UNIT_CELLS,
UNIT_DATETIME,
UNIT_GPS,
UNIT_GPS_LONGITUDE,
UNIT_GPS_LATITUDE,
UNIT_GPS_LONGITUDE_EW,
UNIT_GPS_LATITUDE_NS,
UNIT_DATETIME_YEAR,
UNIT_DATETIME_DAY_MONTH,
UNIT_DATETIME_HOUR_MIN,
UNIT_DATETIME_SEC
};
#define UNIT_MAX UNIT_DEGREE
#define UNIT_DIST UNIT_METERS
#define UNIT_TEMPERATURE UNIT_CELSIUS
#define UNIT_SPEED UNIT_KMH
#else
enum TelemetryUnit {
UNIT_VOLTS,
UNIT_AMPS,
@ -1040,6 +1087,7 @@ enum TelemetryUnit {
UNIT_G,
UNIT_HDG,
};
#endif
#if defined(CPUARM)
PACK(typedef struct {
@ -1064,41 +1112,108 @@ PACK(typedef struct {
}) FrSkyChannelData;
#endif
#if defined(CPUARM)
#if defined(PCBTARANIS)
#define TELEM_VALUES_MAX 32
#else
#define TELEM_VALUES_MAX 16
#endif
#define TELEM_LABEL_LEN 4
//#define TELEM_FLAG_TIMEOUT 0x01
#define TELEM_FLAG_LOG 0x02
//#define TELEM_FLAG_PERSISTENT 0x04
//#define TELEM_FLAG_SCALE 0x08
#define TELEM_FLAG_AUTO_OFFSET 0x10
#define TELEM_FLAG_FILTER 0x20
#define TELEM_FLAG_LOSS_ALARM 0x40
enum TelemetrySensorType
{
TELEM_TYPE_CUSTOM,
TELEM_TYPE_CALCULATED
};
enum TelemetrySensorFormula
{
TELEM_FORMULA_ADD,
TELEM_FORMULA_AVERAGE,
TELEM_FORMULA_MIN,
TELEM_FORMULA_MAX,
TELEM_FORMULA_MULTIPLY,
TELEM_FORMULA_CELL,
TELEM_FORMULA_CONSUMPTION,
TELEM_FORMULA_DIST,
};
enum TelemetrySensorInputFlags
{
TELEM_INPUT_FLAGS_NONE,
TELEM_INPUT_FLAGS_AUTO_OFFSET,
TELEM_INPUT_FLAGS_FILTERING,
TELEM_INPUT_FLAGS_MAX=TELEM_INPUT_FLAGS_FILTERING
};
PACK(typedef struct {
union {
uint16_t id; // data identifier, for FrSky we can reuse existing ones. Source unit is derived from type.
uint16_t persistentValue;
};
union {
uint8_t instance; // instance ID to allow handling multiple instances of same value type, for FrSky can be the physical ID of the sensor
uint8_t formula;
};
char label[TELEM_LABEL_LEN]; // user defined label
uint8_t type:1; // 0=custom / 1=calculated
uint8_t unit:5; // user can choose what unit to display each value in
uint8_t prec:2;
uint8_t inputFlags:2;
uint8_t logs:1;
uint8_t persistent:1;
uint8_t spare:4;
union {
PACK(struct {
uint16_t ratio;
int16_t offset;
}) custom;
PACK(struct {
uint8_t source;
uint8_t index;
uint16_t spare;
}) cell;
PACK(struct {
uint8_t sources[4];
}) calc;
PACK(struct {
uint8_t source;
uint8_t spare[3];
}) consumption;
PACK(struct {
uint8_t gps;
uint8_t alt;
uint16_t spare;
}) dist;
uint32_t param;
};
void init(const char *label, uint8_t unit=UNIT_RAW, uint8_t prec=0);
void init(uint16_t id);
int32_t getValue(int32_t value, uint8_t unit, uint8_t prec) const;
}) TelemetrySensor;
#endif
#if !defined(CPUARM)
enum TelemetrySource {
TELEM_NONE,
TELEM_TX_VOLTAGE, LUA_EXPORT_TELEMETRY("tx-voltage", "Transmitter battery voltage [volts]")
#if defined(CPUARM)
TELEM_TX_TIME, LUA_EXPORT_TELEMETRY("clock", "RTC clock [minutes from midnight]")
TELEM_RESERVE1,
TELEM_RESERVE2,
TELEM_RESERVE3,
TELEM_RESERVE4,
TELEM_RESERVE5,
#endif
TELEM_TIMER1, LUA_EXPORT_TELEMETRY("timer1", "Timer 1 value [seconds]")
TELEM_TIMER2, LUA_EXPORT_TELEMETRY("timer2", "Timer 2 value [seconds]")
#if defined(CPUARM)
TELEM_TIMER3, LUA_EXPORT_TELEMETRY("timer3", "Timer 3 value [seconds]")
TELEM_TIMER_MAX = TELEM_TIMER3,
TELEM_SWR, LUA_EXPORT_TELEMETRY("swr", "Transmitter antenna quality [less is better]")
#else
TELEM_TIMER_MAX = TELEM_TIMER2,
#endif
TELEM_TX_VOLTAGE,
TELEM_TIMER1,
TELEM_TIMER2,
TELEM_TIMER_MAX=TELEM_TIMER2,
TELEM_RSSI_TX,
TELEM_RSSI_RX, LUA_EXPORT_TELEMETRY("rssi", "RSSI [more is better]")
#if defined(CPUARM)
TELEM_RESERVE0,
#endif
TELEM_A_FIRST,
TELEM_A1=TELEM_A_FIRST, LUA_EXPORT_TELEMETRY("a1", "A1 analogue value [units as configured]")
TELEM_A2, LUA_EXPORT_TELEMETRY("a2", "A2 analogue value [units as configured]")
#if !defined(CPUARM)
TELEM_A_LAST=TELEM_A2,
#else
TELEM_A3, LUA_EXPORT_TELEMETRY("a3", "A3 analogue value [units as configured]")
TELEM_A4, LUA_EXPORT_TELEMETRY("a4", "A4 analogue value [units as configured]")
TELEM_A_LAST=TELEM_A4,
#endif
TELEM_ALT, LUA_EXPORT_TELEMETRY("altitude", "Variometer altitude [meters]")
TELEM_RPM, LUA_EXPORT_TELEMETRY("rpm", "Rotational speed [revolutions per minute]")
TELEM_FUEL, LUA_EXPORT_TELEMETRY("fuel", "Fuel level [percent]")
@ -1120,24 +1235,10 @@ enum TelemetrySource {
TELEM_VSPEED, LUA_EXPORT_TELEMETRY("vertical-speed", "Variometer vertical speed [m/s]")
TELEM_ASPEED, LUA_EXPORT_TELEMETRY("air-speed", "Air speed [knots]")
TELEM_DTE, LUA_EXPORT_TELEMETRY("dte", "Total energy [???]")
#if defined(CPUARM)
TELEM_RESERVE6,
TELEM_RESERVE7,
TELEM_RESERVE8,
TELEM_RESERVE9,
TELEM_RESERVE10,
#endif
TELEM_MIN_A_FIRST,
TELEM_MIN_A1=TELEM_MIN_A_FIRST, LUA_EXPORT_TELEMETRY("a1-min", "A1 analogue value minimum [units as configured]")
TELEM_MIN_A2, LUA_EXPORT_TELEMETRY("a2-min", "A2 analogue value minimum [units as configured]")
#if !defined(CPUARM)
TELEM_MIN_A_LAST=TELEM_MIN_A2,
#else
TELEM_MIN_A3, LUA_EXPORT_TELEMETRY("a3-min", "A3 analogue value minimum [units as configured]")
TELEM_MIN_A4, LUA_EXPORT_TELEMETRY("a4-min", "A4 analogue value minimum [units as configured]")
TELEM_MIN_A_LAST=TELEM_MIN_A4,
#endif
// TODO: add A1-4 MAX
TELEM_MIN_ALT, LUA_EXPORT_TELEMETRY("altitude-min", "Lowest altitude [meters]")
TELEM_MAX_ALT, LUA_EXPORT_TELEMETRY("altitude-max", "Highest altitude [meters]")
TELEM_MAX_RPM, LUA_EXPORT_TELEMETRY("rpm-max", "Highest rotational speed [revolutions per minute] [meters]")
@ -1151,13 +1252,6 @@ enum TelemetrySource {
TELEM_MIN_VFAS, LUA_EXPORT_TELEMETRY("vfas-min", "Current sensor - lowest voltage [volts]")
TELEM_MAX_CURRENT, LUA_EXPORT_TELEMETRY("current-max", "Current sensor - highest current [ampers]")
TELEM_MAX_POWER, LUA_EXPORT_TELEMETRY("power-max", "Current sensor - highest power [wats]")
#if defined(CPUARM)
TELEM_RESERVE11,
TELEM_RESERVE12,
TELEM_RESERVE13,
TELEM_RESERVE14,
TELEM_RESERVE15,
#endif
TELEM_ACC,
TELEM_GPS_TIME,
TELEM_CSW_MAX = TELEM_MAX_POWER,
@ -1170,6 +1264,7 @@ enum TelemetrySource {
TELEM_STATUS_MAX = TELEM_GPS_TIME,
TELEM_FIRST_STREAMED_VALUE = TELEM_RSSI_TX,
};
#endif
enum VarioSource {
#if !defined(FRSKY_SPORT)
@ -1195,13 +1290,13 @@ enum VarioSource {
#elif defined(MAVLINK)
#define NUM_TELEMETRY 4
#else
#define NUM_TELEMETRY TELEM_TIMER_MAX
#define NUM_TELEMETRY TELEM_TIMER2
#endif
PACK(typedef struct {
uint8_t source;
uint8_t barMin; // minimum for bar display
uint8_t barMax; // ditto for max display (would usually = ratio)
source_t source;
ls_telemetry_value_t barMin; // minimum for bar display
ls_telemetry_value_t barMax; // ditto for max display (would usually = ratio)
}) FrSkyBarData;
#if defined(PCBTARANIS)
@ -1209,15 +1304,16 @@ PACK(typedef struct {
#else
#define NUM_LINE_ITEMS 2
#endif
PACK(typedef struct {
uint8_t sources[NUM_LINE_ITEMS];
source_t sources[NUM_LINE_ITEMS];
}) FrSkyLineData;
#if defined(PCBTARANIS)
#define MAX_TELEM_SCRIPT_INPUTS 4
#define MAX_TELEM_SCRIPT_INPUTS 8
PACK(typedef struct {
char file[LEN_SCRIPT_FILENAME];
int8_t inputs[MAX_TELEM_SCRIPT_INPUTS];
int16_t inputs[MAX_TELEM_SCRIPT_INPUTS];
}) TelemetryScriptData;
#endif
@ -1272,17 +1368,12 @@ enum TelemetryScreenType {
TELEMETRY_SCREEN_TYPE_MAX = TELEMETRY_SCREEN_TYPE_GAUGES
#endif
};
#define MAX_FRSKY_A_CHANNELS 4
#define MAX_TELEMETRY_SCREENS 4
#define TELEMETRY_SCREEN_TYPE(screenIndex) TelemetryScreenType((g_model.frsky.screensType >> (2*(screenIndex))) & 0x03)
#define IS_BARS_SCREEN(screenIndex) (TELEMETRY_SCREEN_TYPE(screenIndex) == TELEMETRY_SCREEN_TYPE_GAUGES)
PACK(typedef struct {
FrSkyChannelData channels[MAX_FRSKY_A_CHANNELS];
uint8_t usrProto; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon
uint8_t voltsSource:7;
uint8_t altitudeDisplayed:1;
int8_t blades; // How many blades for RPMs, 0=2 blades
uint8_t currentSource;
uint8_t voltsSource;
uint8_t altitudeSource;
uint8_t screensType; // 2bits per screen (None/Gauges/Numbers/Script)
FrSkyScreenData screens[MAX_TELEMETRY_SCREENS];
uint8_t varioSource;
@ -1291,9 +1382,6 @@ PACK(typedef struct {
int8_t varioMin;
int8_t varioMax;
FrSkyRSSIAlarm rssiAlarms[2];
uint16_t mAhPersistent:1;
uint16_t storedMah:15;
int8_t fasOffset;
}) FrSkyData;
#define MIN_BLADES -1 // 1 blade
#define MAX_BLADES 126 // 128 blades
@ -1301,7 +1389,7 @@ PACK(typedef struct {
#define MAX_FRSKY_A_CHANNELS 2
#define MAX_TELEMETRY_SCREENS 2
#define IS_BARS_SCREEN(screenIndex) (g_model.frsky.screensType & (1<<(screenIndex)))
PACK(typedef struct t_FrSkyData {
PACK(typedef struct {
FrSkyChannelData channels[MAX_FRSKY_A_CHANNELS];
uint8_t usrProto:2; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon
uint8_t blades:2; // How many blades for RPMs, 0=2 blades
@ -1388,7 +1476,7 @@ PACK(typedef struct t_SwashRingData { // Swash Ring data
#endif
#if defined(CPUARM)
PACK(typedef struct t_FlightModeData {
PACK(typedef struct {
TRIMS_ARRAY;
int8_t swtch; // swtch of phase[0] is not used
char name[LEN_FLIGHT_MODE_NAME];
@ -1398,7 +1486,7 @@ PACK(typedef struct t_FlightModeData {
PHASE_GVARS_DATA;
}) FlightModeData;
#else
PACK(typedef struct t_FlightModeData {
PACK(typedef struct {
TRIMS_ARRAY;
int8_t swtch; // swtch of phase[0] is not used
char name[LEN_FLIGHT_MODE_NAME];
@ -1636,33 +1724,33 @@ enum MixSources {
MIXSRC_CH16,
MIXSRC_LAST_CH = MIXSRC_CH1+NUM_CHNOUT-1,
MIXSRC_GVAR1, LUA_EXPORT_MULTIPLE("gvar", "Global variable %d", MAX_GVARS)
MIXSRC_LAST_GVAR = MIXSRC_GVAR1+MAX_GVARS-1,
MIXSRC_FIRST_GVAR,
MIXSRC_GVAR1 = MIXSRC_FIRST_GVAR, LUA_EXPORT_MULTIPLE("gvar", "Global variable %d", MAX_GVARS)
MIXSRC_LAST_GVAR = MIXSRC_FIRST_GVAR+MAX_GVARS-1,
#if defined(CPUARM)
MIXSRC_TX_VOLTAGE, LUA_EXPORT_TELEMETRY("tx-voltage", "Transmitter battery voltage [volts]")
MIXSRC_TX_TIME, LUA_EXPORT_TELEMETRY("clock", "RTC clock [minutes from midnight]")
MIXSRC_RESERVE1,
MIXSRC_RESERVE2,
MIXSRC_RESERVE3,
MIXSRC_RESERVE4,
MIXSRC_RESERVE5,
MIXSRC_FIRST_TIMER,
MIXSRC_TIMER1 = MIXSRC_FIRST_TIMER, LUA_EXPORT_TELEMETRY("timer1", "Timer 1 value [seconds]")
MIXSRC_TIMER2, LUA_EXPORT_TELEMETRY("timer2", "Timer 2 value [seconds]")
MIXSRC_TIMER3, LUA_EXPORT_TELEMETRY("timer3", "Timer 3 value [seconds]")
MIXSRC_LAST_TIMER = MIXSRC_TIMER3,
#endif
MIXSRC_FIRST_TELEM,
#if defined(CPUARM)
MIXSRC_LAST_TELEM = MIXSRC_FIRST_TELEM+3*TELEM_VALUES_MAX-1
#else
MIXSRC_LAST_TELEM = MIXSRC_FIRST_TELEM+NUM_TELEMETRY-1
#endif
};
#if defined(LUA)
#define EXTRA_FIRST 1000
enum LuaExtraFields {
EXTRA_LATITUDE = EXTRA_FIRST, LUA_EXPORT_EXTRA("latitude", "GPS latitude [degrees, North is positive]", \
"gpsToDouble(frskyData.hub.gpsLatitudeNS=='S', frskyData.hub.gpsLatitude_bp, frskyData.hub.gpsLatitude_ap)", \
"frskyData.hub.gpsFix")
EXTRA_LONGITUDE, LUA_EXPORT_EXTRA("longitude", "GPS longitude [degrees, East is positive]", \
"gpsToDouble(frskyData.hub.gpsLongitudeEW=='W', frskyData.hub.gpsLongitude_bp, frskyData.hub.gpsLongitude_ap)", \
"frskyData.hub.gpsFix")
EXTRA_PILOT_LATITUDE, LUA_EXPORT_EXTRA("pilot-latitude", "Latitude of frist GPS position [degrees, North is positive]", \
"pilotLatitude", "frskyData.hub.gpsFix")
EXTRA_PILOT_LONGITUDE, LUA_EXPORT_EXTRA("pilot-longitude", "Longitude of frist GPS position [degrees, East is positive]", \
"pilotLongitude", "frskyData.hub.gpsFix")
EXTRA_GPS_CLOCK, LUA_EXPORT_EXTRA("gps-clock", "GPS clock [seconds from midnight]", \
"(int)(frskyData.hub.hour)*3600 + frskyData.hub.min*60 + frskyData.hub.sec", "frskyData.hub.gpsFix")
EXTRA_FLIGHT_MODE LUA_EXPORT_EXTRA("flight-mode", "Current flight mode number [number]", \
"getFlightMode()", "true")
};
#endif // #if defined(LUA)
#define MIXSRC_FIRST (MIXSRC_NONE+1)
#define MIXSRC_LAST MIXSRC_LAST_CH
#define INPUTSRC_FIRST MIXSRC_Rud
@ -1687,19 +1775,19 @@ enum CountDownModes {
};
#if defined(CPUARM)
PACK(typedef struct t_TimerData {
int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
uint8_t countdownBeep:2;
uint8_t minuteBeep:1;
uint8_t persistent:2;
uint8_t spare:3;
PACK(typedef struct {
int32_t mode:8; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
uint32_t start:24;
int32_t value:24;
uint32_t countdownBeep:2;
uint32_t minuteBeep:1;
uint32_t persistent:2;
uint32_t spare:3;
char name[LEN_TIMER_NAME];
}) TimerData;
#define IS_MANUAL_RESET_TIMER(idx) (g_model.timers[idx].persistent == 2)
#elif defined(CPUM2560)
PACK(typedef struct t_TimerData {
PACK(typedef struct {
int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
uint16_t start;
uint8_t countdownBeep:2;
@ -1710,7 +1798,7 @@ PACK(typedef struct t_TimerData {
}) TimerData;
#define IS_MANUAL_RESET_TIMER(idx) (g_model.timers[idx].persistent == 2)
#else
PACK(typedef struct t_TimerData {
PACK(typedef struct {
int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
uint16_t start:12;
uint16_t countdownBeep:1;
@ -1815,7 +1903,7 @@ enum ThrottleSources {
THROTTLE_SOURCE_CH1,
};
enum TelemetryProtocol
enum TelemetryType
{
PROTOCOL_TELEMETRY_FIRST,
PROTOCOL_FRSKY_SPORT = PROTOCOL_TELEMETRY_FIRST,
@ -1865,7 +1953,7 @@ PACK(typedef struct {
MODELDATA_EXTRA
ARM_FIELD(uint8_t spare3[230]) // TODO dirty hack for eeprom conversions (we load the model inside the g_model structure)
ARM_FIELD(TelemetrySensor telemetrySensors[TELEM_VALUES_MAX])
}) ModelData;
extern EEGeneral g_eeGeneral;
@ -1874,4 +1962,3 @@ extern ModelData g_model;
#define TOTAL_EEPROM_USAGE (sizeof(ModelData)*MAX_MODELS + sizeof(EEGeneral))
#endif
/*eof*/

View file

@ -478,10 +478,6 @@ void modelDefault(uint8_t id)
}
#endif
#if defined(PCBTARANIS)
g_model.frsky.channels[0].ratio = 132;
#endif
#if defined(MAVLINK)
g_model.mavlink.rc_rssi_scale = 15;
g_model.mavlink.pc_rssi_en = 1;
@ -768,13 +764,42 @@ void setGVarValue(uint8_t idx, int16_t value, int8_t phase)
#endif
#if defined(CPUARM) && defined(FRSKY)
#if defined(CPUARM)
getvalue_t convert16bitsTelemValue(source_t channel, ls_telemetry_value_t value)
{
return value;
}
getvalue_t convert8bitsTelemValue(source_t channel, ls_telemetry_value_t value)
{
return value;
}
#if defined(FRSKY)
ls_telemetry_value_t minTelemValue(source_t channel)
{
return 0;
}
ls_telemetry_value_t maxTelemValue(source_t channel)
{
return 30000;
}
#endif
ls_telemetry_value_t max8bitsTelemValue(source_t channel)
{
return 30000;
}
#elif defined(FRSKY)
/*
ls_telemetry_value_t minTelemValue(uint8_t channel)
{
switch (channel) {
case TELEM_TIMER1:
case TELEM_TIMER2:
case TELEM_TIMER3:
return -3600;
case TELEM_ALT:
case TELEM_MIN_ALT:
@ -796,103 +821,33 @@ ls_telemetry_value_t minTelemValue(uint8_t channel)
return 0;
}
}
#endif
#if defined(FRSKY)
*/
ls_telemetry_value_t maxTelemValue(uint8_t channel)
{
switch (channel) {
#if defined(CPUARM)
case TELEM_TX_TIME:
return 24*60-1;
case TELEM_TIMER1:
case TELEM_TIMER2:
case TELEM_TIMER3:
return 60*60;
#endif
case TELEM_FUEL:
#if defined(CPUARM)
case TELEM_SWR:
#endif
case TELEM_RSSI_TX:
case TELEM_RSSI_RX:
return 100;
case TELEM_HDG:
return 180;
#if defined(CPUARM)
case TELEM_SPEED:
case TELEM_MAX_SPEED:
case TELEM_ASPEED:
case TELEM_MAX_ASPEED:
return 20000;
case TELEM_CELL:
case TELEM_MIN_CELL:
return 510;
case TELEM_CELLS_SUM:
case TELEM_MIN_CELLS_SUM:
case TELEM_VFAS:
case TELEM_MIN_VFAS:
return 1000;
case TELEM_VSPEED:
return 3000;
case TELEM_ACCx:
case TELEM_ACCy:
case TELEM_ACCz:
return 1000;
default:
return 30000;
#else
default:
return 255;
#endif
}
}
#endif
#if defined(CPUARM)
getvalue_t convert16bitsTelemValue(uint8_t channel, ls_telemetry_value_t value)
{
getvalue_t result;
switch (channel) {
#if defined(FRSKY_SPORT)
case TELEM_ALT:
result = value * 100;
break;
#endif
case TELEM_VSPEED:
result = value * 10;
break;
default:
result = value;
break;
}
return result;
}
ls_telemetry_value_t max8bitsTelemValue(uint8_t channel)
{
return min<ls_telemetry_value_t>(255, maxTelemValue(channel));
}
#endif
#if !defined(CPUARM)
getvalue_t convert8bitsTelemValue(uint8_t channel, ls_telemetry_value_t value)
{
getvalue_t result;
switch (channel) {
case TELEM_TIMER1:
case TELEM_TIMER2:
#if defined(CPUARM)
case TELEM_TIMER3:
#endif
result = value * 5;
break;
#if defined(FRSKY)
case TELEM_ALT:
#if defined(CPUARM)
result = 100 * (value * 8 - 500);
break;
#endif
case TELEM_GPSALT:
case TELEM_MAX_ALT:
case TELEM_MIN_ALT:
@ -941,8 +896,9 @@ getvalue_t convert8bitsTelemValue(uint8_t channel, ls_telemetry_value_t value)
}
return result;
}
#endif
#if defined(FRSKY) || defined(CPUARM)
#if defined(FRSKY)&& !defined(CPUARM)
FORCEINLINE void convertUnit(getvalue_t & val, uint8_t & unit)
{
if (IS_IMPERIAL_ENABLE()) {
@ -2100,15 +2056,20 @@ void opentxClose()
saveTimers();
#if defined(CPUARM) && defined(FRSKY)
if (g_model.frsky.mAhPersistent && g_model.frsky.storedMah!=frskyData.hub.currentConsumption) {
g_model.frsky.storedMah = frskyData.hub.currentConsumption;
#if defined(CPUARM)
for (int i=0; i<TELEM_VALUES_MAX; i++) {
TelemetrySensor & sensor = g_model.telemetrySensors[i];
if (sensor.type == TELEM_TYPE_CALCULATED) {
if (sensor.persistent && sensor.persistentValue != telemetryItems[i].value) {
sensor.persistentValue = telemetryItems[i].value;
eeDirty(EE_MODEL);
}
else if (!g_model.frsky.mAhPersistent && g_model.frsky.storedMah!=0) {
g_model.frsky.storedMah = 0;
else if (!sensor.persistent) {
sensor.persistentValue = 0;
eeDirty(EE_MODEL);
}
}
}
#endif
#if defined(PCBSKY9X)

View file

@ -243,7 +243,7 @@
#define IF_FAI_CHOICE(x)
#endif
#define IS_FAI_FORBIDDEN(idx) (IS_FAI_ENABLED() && idx > MIXSRC_FIRST_TELEM-1+TELEM_A2-1)
#define IS_FAI_FORBIDDEN(idx) (IS_FAI_ENABLED() && idx >= MIXSRC_FIRST_TELEM)
#if defined(SIMU)
#ifndef FORCEINLINE
@ -633,11 +633,12 @@ extern uint8_t pxxFlag[NUM_MODULES];
#define ZCHAR_MAX (LEN_STD_CHARS + LEN_SPECIAL_CHARS)
#endif
char hex2zchar(uint8_t hex);
char idx2char(int8_t idx);
#if defined(CPUARM) || defined(SIMU)
int8_t char2idx(char c);
void str2zchar(char *dest, const char *src, int size);
void zchar2str(char *dest, const char *src, int size);
int zchar2str(char *dest, const char *src, int size);
#endif
#include "keys.h"
@ -1029,9 +1030,7 @@ template<class t> FORCEINLINE t limit(t mi, t x, t ma) { return min(max(mi,x),ma
template<class t> void swap(t & a, t & b) { t tmp = b; b = a; a = tmp; }
#endif
#if defined(HELI) || defined(FRSKY_HUB)
uint16_t isqrt32(uint32_t n);
#endif
#if defined(CPUARM) && !defined(BOOT)
#if !defined(SIMU)
@ -1358,6 +1357,10 @@ void evalFunctions();
#include "gui/menus.h"
#if defined(CPUARM)
#include "telemetry/telemetry.h"
#endif
#if defined (FRSKY)
// FrSky Telemetry
#include "telemetry/frsky.h"
@ -1638,9 +1641,10 @@ extern union ReusableBuffer reusableBuffer;
void checkFlashOnBeep();
#if defined(FRSKY) || defined(CPUARM)
#if defined(CPUARM)
void putsValueWithUnit(coord_t x, coord_t y, lcdint_t val, uint8_t unit, LcdFlags att);
#elif defined(FRSKY)
void convertUnit(getvalue_t & val, uint8_t & unit); // TODO check FORCEINLINE on stock
void putsTelemetryValue(coord_t x, coord_t y, lcdint_t val, uint8_t unit, LcdFlags att);
#else
#define convertUnit(...)
#endif
@ -1694,19 +1698,19 @@ extern bar_threshold_t barsThresholds[THLD_MAX];
#endif
#if defined(FRSKY)
ls_telemetry_value_t minTelemValue(uint8_t channel);
ls_telemetry_value_t maxTelemValue(uint8_t channel);
ls_telemetry_value_t minTelemValue(source_t channel);
ls_telemetry_value_t maxTelemValue(source_t channel);
#else
#define minTelemValue(channel) 255
#define maxTelemValue(channel) 255
#endif
#if defined(CPUARM)
getvalue_t convert16bitsTelemValue(uint8_t channel, ls_telemetry_value_t value);
ls_telemetry_value_t max8bitsTelemValue(uint8_t channel);
getvalue_t convert16bitsTelemValue(source_t channel, ls_telemetry_value_t value);
ls_telemetry_value_t max8bitsTelemValue(source_t channel);
#endif
getvalue_t convert8bitsTelemValue(uint8_t channel, ls_telemetry_value_t value);
getvalue_t convert8bitsTelemValue(source_t channel, ls_telemetry_value_t value);
getvalue_t convertLswTelemValue(LogicalSwitchData * cs);
#if defined(CPUARM)
@ -1720,12 +1724,12 @@ getvalue_t convertLswTelemValue(LogicalSwitchData * cs);
#endif
#if defined(FRSKY) || defined(CPUARM)
lcdint_t applyChannelRatio(uint8_t channel, lcdint_t val);
lcdint_t applyChannelRatio(source_t channel, lcdint_t val);
#define ANA_CHANNEL_UNIT(channel) g_model.frsky.channels[channel].type
#endif
getvalue_t div10_and_round(getvalue_t value);
getvalue_t div100_and_round(getvalue_t value);
#if defined(FRSKY)
NOINLINE uint8_t getRssiAlarmValue(uint8_t alarm);
@ -1738,27 +1742,19 @@ extern const pm_uint8_t bchunit_ar[];
#define FRSKY_MULTIPLIER_MAX 3
#endif
#if defined(PCBTARANIS)
enum FrskyViews {
enum TelemetryViews {
TELEMETRY_CUSTOM_SCREEN_1,
TELEMETRY_CUSTOM_SCREEN_2,
#if defined(CPUARM)
TELEMETRY_CUSTOM_SCREEN_3,
TELEMETRY_CUSTOM_SCREEN_4,
TELEMETRY_VOLTAGES_SCREEN, // TODO NOT IF LUA
TELEMETRY_AFTER_FLIGHT_SCREEN, // TODO NOT IF LUA
FRSKY_VIEW_MAX = TELEMETRY_AFTER_FLIGHT_SCREEN
};
TELEMETRY_VIEW_MAX = TELEMETRY_CUSTOM_SCREEN_4
#else
enum FrskyViews {
TELEMETRY_CUSTOM_SCREEN_1,
TELEMETRY_CUSTOM_SCREEN_2,
CASE_CPUARM(TELEMETRY_CUSTOM_SCREEN_3)
CASE_CPUARM(TELEMETRY_CUSTOM_SCREEN_4)
TELEMETRY_VOLTAGES_SCREEN,
TELEMETRY_AFTER_FLIGHT_SCREEN,
FRSKY_VIEW_MAX = TELEMETRY_AFTER_FLIGHT_SCREEN
};
TELEMETRY_VIEW_MAX = TELEMETRY_AFTER_FLIGHT_SCREEN
#endif
};
extern uint8_t s_frsky_view;
@ -1769,8 +1765,6 @@ extern uint8_t s_frsky_view;
#if defined(PCBTARANIS)
double gpsToDouble(bool neg, int16_t bp, int16_t ap);
extern double pilotLatitude;
extern double pilotLongitude;
#endif
void getGpsPilotPosition();
void getGpsDistance();
@ -1790,10 +1784,7 @@ void varioWakeup();
#define IS_IMPERIAL_ENABLE() (0)
#endif
#if defined(PCBTARANIS)
#define IS_USR_PROTO_FRSKY_HUB() (1)
#define IS_USR_PROTO_WS_HOW_HIGH() (0)
#else
#if !defined(CPUARM)
#define IS_USR_PROTO_FRSKY_HUB() (g_model.frsky.usrProto == USR_PROTO_FRSKY)
#define IS_USR_PROTO_WS_HOW_HIGH() (g_model.frsky.usrProto == USR_PROTO_WS_HOW_HIGH)
#endif

View file

@ -69,6 +69,7 @@ extern FATFS g_FATFS_Obj;
extern uint8_t logDelay;
extern const pm_char * openLogs();
void writeHeader();
extern void closeLogs();
extern void writeLogs();

View file

@ -84,7 +84,7 @@ void str2zchar(char *dest, const char *src, int size)
}
}
void zchar2str(char *dest, const char *src, int size)
int zchar2str(char *dest, const char *src, int size)
{
for (int c=0; c<size; c++) {
dest[c] = idx2char(src[c]);
@ -92,6 +92,7 @@ void zchar2str(char *dest, const char *src, int size)
do {
dest[size--] = '\0';
} while (size >= 0 && dest[size] == ' ');
return size+1;
}
#endif

View file

@ -271,14 +271,18 @@ bool getLogicalSwitch(uint8_t idx)
#if defined(FRSKY)
// Telemetry
if (v1 >= MIXSRC_FIRST_TELEM) {
#if defined(CPUARM)
if (!TELEMETRY_STREAMING() || IS_FAI_FORBIDDEN(v1-1)) {
#else
if ((!TELEMETRY_STREAMING() && v1 >= MIXSRC_FIRST_TELEM+TELEM_FIRST_STREAMED_VALUE-1) || IS_FAI_FORBIDDEN(v1-1)) {
#endif
result = false;
goto DurationAndDelayProcessing;
}
y = convertLswTelemValue(ls);
#if defined(GAUGES)
#if defined(GAUGES) && !defined(CPUARM)
// Fill the telemetry bars threshold array
if (s == LS_FAMILY_OFS) {
uint8_t idx = v1-MIXSRC_FIRST_TELEM+1-TELEM_ALT;

View file

@ -99,9 +99,8 @@ inline void setup_switches()
#endif
}
#ifdef SIMU
#if defined(SIMU)
#define stop_trainer_capture()
#define rotencEnd()
#define sam_boot()
#else

View file

@ -76,6 +76,13 @@ uint8_t telemetryProtocol = 255;
#define IS_FRSKY_SPORT_PROTOCOL() (false)
#endif
#if defined(CPUARM)
void FrskyValueWithMin::reset()
{
memclear(this, sizeof(*this));
}
#endif
void FrskyValueWithMin::set(uint8_t value)
{
#if defined(CPUARM)
@ -125,21 +132,16 @@ void FrskyValueWithMinMax::set(uint8_t value, uint8_t unit)
}
}
uint16_t getChannelRatio(uint8_t channel)
#if !defined(CPUARM)
uint16_t getChannelRatio(source_t channel)
{
return (uint16_t)g_model.frsky.channels[channel].ratio << g_model.frsky.channels[channel].multiplier;
}
lcdint_t applyChannelRatio(uint8_t channel, lcdint_t val)
lcdint_t applyChannelRatio(source_t channel, lcdint_t val)
{
return ((int32_t)val+g_model.frsky.channels[channel].offset) * getChannelRatio(channel) * 2 / 51;
}
#if defined(CPUARM)
inline bool alarmRaised(uint8_t channel, uint8_t idx)
{
return g_model.frsky.channels[channel].ratio > 0 && g_model.frsky.channels[channel].alarms_value[idx] > 0 && frskyData.analog[channel].value < g_model.frsky.channels[channel].alarms_value[idx];
}
#endif
#if defined(TELEMETREZ)
@ -258,22 +260,12 @@ NOINLINE void processSerialData(uint8_t data)
#if defined(FRSKY_SPORT)
if (IS_FRSKY_SPORT_PROTOCOL() && frskyRxBufferCount >= FRSKY_SPORT_PACKET_SIZE) {
frskySportProcessPacket(frskyRxBuffer);
processSportPacket(frskyRxBuffer);
dataState = STATE_DATA_IDLE;
}
#endif
}
enum AlarmsCheckSteps {
ALARM_SWR_STEP,
ALARM_RSSI_STEP,
ALARM_A1_STEP,
ALARM_A2_STEP,
ALARM_A3_STEP,
ALARM_A4_STEP,
ALARM_STEPS_COUNT
};
void telemetryWakeup()
{
#if defined(CPUARM)
@ -331,6 +323,14 @@ void telemetryWakeup()
}
#endif
#if defined(CPUARM)
for (int i=0; i<TELEM_VALUES_MAX; i++) {
const TelemetrySensor & sensor = g_model.telemetrySensors[i];
if (sensor.type == TELEM_TYPE_CALCULATED) {
telemetryItems[i].eval(sensor);
}
}
#endif
#if defined(VARIO)
if (TELEMETRY_STREAMING() && !IS_FAI_ENABLED()) {
@ -340,76 +340,38 @@ void telemetryWakeup()
#if defined(CPUARM)
static tmr10ms_t alarmsCheckTime = 0;
static uint8_t alarmsCheckStep = 0;
#define SCHEDULE_NEXT_ALARMS_CHECK(seconds) alarmsCheckTime = get_tmr10ms() + (100*(seconds))
if (int32_t(get_tmr10ms() - alarmsCheckTime) > 0) {
alarmsCheckTime = get_tmr10ms() + 100; /* next check in 1 second */
SCHEDULE_NEXT_ALARMS_CHECK(1/*second*/);
uint8_t now = TelemetryItem::now();
for (int i=0; i<TELEM_VALUES_MAX; i++) {
if (isTelemetryFieldAvailable(i)) {
uint8_t lastReceived = telemetryItems[i].lastReceived;
if (lastReceived < TELEMETRY_VALUE_TIMER_CYCLE && uint8_t(now - lastReceived) > TELEMETRY_VALUE_OLD_THRESHOLD) {
telemetryItems[i].lastReceived = TELEMETRY_VALUE_OLD;
}
}
}
if (alarmsCheckStep == ALARM_SWR_STEP) {
#if defined(PCBTARANIS) && defined(SWR)
if (IS_FRSKY_SPORT_PROTOCOL() && frskyData.swr.value > 0x33) {
AUDIO_SWR_RED();
POPUP_WARNING(STR_ANTENNAPROBLEM);
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
SCHEDULE_NEXT_ALARMS_CHECK(10/*seconds*/);
}
#endif
}
else if (TELEMETRY_STREAMING()) {
if (alarmsCheckStep == ALARM_RSSI_STEP) {
if (getRssiAlarmValue(1) && frskyData.rssi[0].value < getRssiAlarmValue(1)) {
AUDIO_RSSI_RED();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
else if (getRssiAlarmValue(0) && frskyData.rssi[0].value < getRssiAlarmValue(0)) {
AUDIO_RSSI_ORANGE();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
}
else if (alarmsCheckStep == ALARM_A1_STEP) {
if (alarmRaised(TELEM_ANA_A1, 1)) {
AUDIO_A1_RED();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
else if (alarmRaised(TELEM_ANA_A1, 0)) {
AUDIO_A1_ORANGE();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
}
else if (alarmsCheckStep == ALARM_A2_STEP) {
if (alarmRaised(TELEM_ANA_A2, 1)) {
AUDIO_A2_RED();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
else if (alarmRaised(TELEM_ANA_A2, 0)) {
AUDIO_A2_ORANGE();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
}
else if (alarmsCheckStep == ALARM_A3_STEP) {
if (alarmRaised(TELEM_ANA_A3, 1)) {
AUDIO_A3_RED();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
else if (alarmRaised(TELEM_ANA_A3, 0)) {
AUDIO_A3_ORANGE();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
}
else if (alarmsCheckStep == ALARM_A4_STEP) {
if (alarmRaised(TELEM_ANA_A4, 1)) {
AUDIO_A4_RED();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
else if (alarmRaised(TELEM_ANA_A4, 0)) {
AUDIO_A4_ORANGE();
alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3 seconds */
}
}
}
if (++alarmsCheckStep == ALARM_STEPS_COUNT) {
alarmsCheckStep = 0;
if (TELEMETRY_STREAMING()) {
if (getRssiAlarmValue(1) && TELEMETRY_RSSI() < getRssiAlarmValue(1)) {
AUDIO_RSSI_RED();
SCHEDULE_NEXT_ALARMS_CHECK(10/*seconds*/);
}
else if (getRssiAlarmValue(0) && TELEMETRY_RSSI() < getRssiAlarmValue(0)) {
AUDIO_RSSI_ORANGE();
SCHEDULE_NEXT_ALARMS_CHECK(10/*seconds*/);
}
}
}
@ -429,7 +391,6 @@ void telemetryWakeup()
void telemetryInterrupt10ms()
{
#if defined(CPUARM)
uint16_t voltage = frskyData.hub.cellsSum; /* unit: 1/10 volts */
#elif defined(FRSKY_HUB)
uint16_t voltage = 0; /* unit: 1/10 volts */
for (uint8_t i=0; i<frskyData.hub.cellsCount; i++)
@ -443,17 +404,19 @@ void telemetryInterrupt10ms()
if (TELEMETRY_STREAMING()) {
if (!TELEMETRY_OPENXSENSOR()) {
// power calculation
uint8_t channel = g_model.frsky.voltsSource;
#if defined(CPUARM)
if (channel <= FRSKY_VOLTS_SOURCE_A4) {
voltage = applyChannelRatio(channel, frskyData.analog[channel].value) / 10;
for (int i=0; i<TELEM_VALUES_MAX; i++) {
const TelemetrySensor & sensor = g_model.telemetrySensors[i];
if (sensor.type == TELEM_TYPE_CALCULATED) {
telemetryItems[i].per10ms(sensor);
}
}
#else
// power calculation
uint8_t channel = g_model.frsky.voltsSource;
if (channel <= FRSKY_VOLTS_SOURCE_A2) {
voltage = applyChannelRatio(channel, frskyData.analog[channel].value) / 10;
}
#endif
#if defined(FRSKY_HUB)
else if (channel == FRSKY_VOLTS_SOURCE_FAS) {
@ -472,22 +435,21 @@ void telemetryInterrupt10ms()
current = applyChannelRatio(channel, frskyData.analog[channel].value) / 10;
}
#if defined(CPUARM)
frskyData.hub.power = (current * voltage) / 100;
#else
frskyData.hub.power = ((current>>1) * (voltage>>1)) / 25;
#endif
frskyData.hub.currentPrescale += current;
if (frskyData.hub.currentPrescale >= 3600) {
frskyData.hub.currentConsumption += 1;
frskyData.hub.currentPrescale -= 3600;
}
#endif
}
#if !defined(CPUARM)
if (frskyData.hub.power > frskyData.hub.maxPower) {
frskyData.hub.maxPower = frskyData.hub.power;
}
#endif
}
#if defined(WS_HOW_HIGH)
@ -501,8 +463,12 @@ void telemetryInterrupt10ms()
}
else {
#if !defined(SIMU)
#if defined(CPUARM)
frskyData.rssi.reset();
#else
frskyData.rssi[0].set(0);
frskyData.rssi[1].set(0);
#endif
#endif
}
}
@ -511,6 +477,12 @@ void telemetryReset()
{
memclear(&frskyData, sizeof(frskyData));
#if defined(CPUARM)
for (int index=0; index<TELEM_VALUES_MAX; index++) {
telemetryItems[index].clear();
}
#endif
frskyStreaming = 0; // reset counter only if valid frsky packets are being detected
link_counter = 0;
@ -518,7 +490,7 @@ void telemetryReset()
telemetryState = TELEMETRY_INIT;
#endif
#if defined(FRSKY_HUB)
#if defined(FRSKY_HUB) && !defined(CPUARM)
frskyData.hub.gpsLatitude_bp = 2;
frskyData.hub.gpsLongitude_bp = 2;
frskyData.hub.gpsFix = -1;
@ -527,16 +499,18 @@ void telemetryReset()
#if defined(SIMU)
#if defined(CPUARM)
#if defined(SWR)
frskyData.swr.value = 30;
#endif
#endif
frskyData.rssi.value = 75;
#else
frskyData.rssi[0].value = 75;
frskyData.rssi[1].value = 75;
frskyData.analog[TELEM_ANA_A1].set(120, UNIT_VOLTS);
frskyData.analog[TELEM_ANA_A2].set(240, UNIT_VOLTS);
#if defined(CPUARM)
frskyData.analog[TELEM_ANA_A3].set(100, UNIT_VOLTS);
frskyData.analog[TELEM_ANA_A4].set(200, UNIT_VOLTS);
#endif
#if !defined(CPUARM)
frskyData.hub.fuelLevel = 75;
frskyData.hub.rpm = 12000;
frskyData.hub.vfas = 100;
@ -577,9 +551,6 @@ void telemetryReset()
frskyData.hub.baroAltitude_bp = 50;
frskyData.hub.minAltitude = 10;
frskyData.hub.maxAltitude = 500;
#if defined(CPUARM)
frskyData.hub.baroAltitude = 340*100; //in cm
#endif
frskyData.hub.accelY = 100;
frskyData.hub.temperature1 = -30;
@ -588,6 +559,17 @@ void telemetryReset()
frskyData.hub.current = 55;
frskyData.hub.maxCurrent = 65;
#endif
#endif
#if 0
setTelemetryValue(TELEM_PROTO_FRSKY_SPORT, RSSI_ID, 0, 75, UNIT_RAW, 0);
setTelemetryValue(TELEM_PROTO_FRSKY_SPORT, T1_FIRST_ID, 0, 100, UNIT_CELSIUS, 0);
setTelemetryValue(TELEM_PROTO_FRSKY_SPORT, T1_FIRST_ID, 1, 200, UNIT_CELSIUS, 0);
setTelemetryValue(TELEM_PROTO_FRSKY_SPORT, ALT_FIRST_ID, 1, 1000, UNIT_METERS, 2);
setTelemetryValue(TELEM_PROTO_FRSKY_SPORT, CELLS_FIRST_ID, 1, 0x10010020, UNIT_CELLS, 0);
setTelemetryValue(TELEM_PROTO_FRSKY_SPORT, CELLS_FIRST_ID, 1, 0x10010020, UNIT_CELLS, 0);
setTelemetryValue(TELEM_PROTO_FRSKY_SPORT, CURR_FIRST_ID, 1, 100, UNIT_AMPS, 2);
#endif
}
void telemetryInit(void)
@ -611,70 +593,6 @@ void telemetryInit(void)
}
#if defined(CPUARM)
void frskySetCellsCount(uint8_t cellscount)
{
if (cellscount <= DIM(frskyData.hub.cellVolts)) {
frskyData.hub.cellsCount = cellscount;
frskyData.hub.cellsState = 0;
frskyData.hub.minCells = 0;
frskyData.hub.minCell = 0;
}
}
void frskySetCellVoltage(uint8_t battnumber, frskyCellVoltage_t cellVolts)
{
// TRACE("frskySetCellVoltage() %d, %d", battnumber, cellVolts);
if (battnumber < frskyData.hub.cellsCount) {
// set cell voltage
if (cellVolts > 50) // Filter out bogus cell values apparently sent by the FLVSS in some cases
frskyData.hub.cellVolts[battnumber] = cellVolts;
if (cellVolts != 0) {
frskyData.hub.cellsState |= (1 << battnumber);
if (frskyData.hub.cellsState == (1<<frskyData.hub.cellsCount)-1) {
// we received voltage of all cells
frskyData.hub.cellsState = 0;
// calculate Cells, Cells-, Cell and Cell-
uint16_t cellsSum = 0; /* unit: 1/10 volts */
frskyCellVoltage_t minCellVolts = -1;
for (uint8_t i=0; i<frskyData.hub.cellsCount; i++) {
frskyCellVoltage_t tmpCellVolts = frskyData.hub.cellVolts[i];
cellsSum += tmpCellVolts;
if (tmpCellVolts < minCellVolts) {
// update minimum cell voltage (Cell)
minCellVolts = tmpCellVolts;
}
}
frskyData.hub.minCellVolts = minCellVolts;
frskyData.hub.cellsSum = cellsSum / (10 / TELEMETRY_CELL_VOLTAGE_MUTLIPLIER);
// update cells sum minimum (Cells-)
if (!frskyData.hub.minCells || frskyData.hub.cellsSum < frskyData.hub.minCells) {
frskyData.hub.minCells = frskyData.hub.cellsSum;
}
// update minimum cell voltage (Cell-)
if (!frskyData.hub.minCell || frskyData.hub.minCellVolts < frskyData.hub.minCell) {
frskyData.hub.minCell = frskyData.hub.minCellVolts;
}
}
}
}
}
void frskyUpdateCells(void)
{
// Voltage => Cell number + Cell voltage
uint8_t battnumber = ((frskyData.hub.volts & 0x00F0) >> 4);
if (battnumber >= frskyData.hub.cellsCount) {
frskySetCellsCount(battnumber+1);
}
frskyCellVoltage_t cellVolts = (frskyCellVoltage_t) (((((frskyData.hub.volts & 0xFF00) >> 8) + ((frskyData.hub.volts & 0x000F) << 8))) / (5*TELEMETRY_CELL_VOLTAGE_MUTLIPLIER));
frskySetCellVoltage(battnumber, cellVolts);
}
#elif defined(FRSKY_HUB)
void frskyUpdateCells(void)
{

View file

@ -50,6 +50,103 @@
#define FRSKY_SPORT_AVERAGING 4
#define FRSKY_D_AVERAGING 8
// FrSky PRIM IDs (1 byte)
#define DATA_FRAME 0x10
// FrSky old DATA IDs (1 byte)
#define GPS_ALT_BP_ID 0x01
#define TEMP1_ID 0x02
#define RPM_ID 0x03
#define FUEL_ID 0x04
#define TEMP2_ID 0x05
#define VOLTS_ID 0x06
#define GPS_ALT_AP_ID 0x09
#define BARO_ALT_BP_ID 0x10
#define GPS_SPEED_BP_ID 0x11
#define GPS_LONG_BP_ID 0x12
#define GPS_LAT_BP_ID 0x13
#define GPS_COURS_BP_ID 0x14
#define GPS_DAY_MONTH_ID 0x15
#define GPS_YEAR_ID 0x16
#define GPS_HOUR_MIN_ID 0x17
#define GPS_SEC_ID 0x18
#define GPS_SPEED_AP_ID 0x19
#define GPS_LONG_AP_ID 0x1A
#define GPS_LAT_AP_ID 0x1B
#define GPS_COURS_AP_ID 0x1C
#define BARO_ALT_AP_ID 0x21
#define GPS_LONG_EW_ID 0x22
#define GPS_LAT_NS_ID 0x23
#define ACCEL_X_ID 0x24
#define ACCEL_Y_ID 0x25
#define ACCEL_Z_ID 0x26
#define CURRENT_ID 0x28
#define VARIO_ID 0x30
#define VFAS_ID 0x39
#define VOLTS_BP_ID 0x3A
#define VOLTS_AP_ID 0x3B
#define FRSKY_LAST_ID 0x3F
#define D_RSSI_ID 0xF0
#define D_A1_ID 0xF1
#define D_A2_ID 0xF2
// FrSky new DATA IDs (2 bytes)
#define ALT_FIRST_ID 0x0100
#define ALT_LAST_ID 0x010f
#define VARIO_FIRST_ID 0x0110
#define VARIO_LAST_ID 0x011f
#define CURR_FIRST_ID 0x0200
#define CURR_LAST_ID 0x020f
#define VFAS_FIRST_ID 0x0210
#define VFAS_LAST_ID 0x021f
#define CELLS_FIRST_ID 0x0300
#define CELLS_LAST_ID 0x030f
#define T1_FIRST_ID 0x0400
#define T1_LAST_ID 0x040f
#define T2_FIRST_ID 0x0410
#define T2_LAST_ID 0x041f
#define RPM_FIRST_ID 0x0500
#define RPM_LAST_ID 0x050f
#define FUEL_FIRST_ID 0x0600
#define FUEL_LAST_ID 0x060f
#define ACCX_FIRST_ID 0x0700
#define ACCX_LAST_ID 0x070f
#define ACCY_FIRST_ID 0x0710
#define ACCY_LAST_ID 0x071f
#define ACCZ_FIRST_ID 0x0720
#define ACCZ_LAST_ID 0x072f
#define GPS_LONG_LATI_FIRST_ID 0x0800
#define GPS_LONG_LATI_LAST_ID 0x080f
#define GPS_ALT_FIRST_ID 0x0820
#define GPS_ALT_LAST_ID 0x082f
#define GPS_SPEED_FIRST_ID 0x0830
#define GPS_SPEED_LAST_ID 0x083f
#define GPS_COURS_FIRST_ID 0x0840
#define GPS_COURS_LAST_ID 0x084f
#define GPS_TIME_DATE_FIRST_ID 0x0850
#define GPS_TIME_DATE_LAST_ID 0x085f
#define A3_FIRST_ID 0x0900
#define A3_LAST_ID 0x090f
#define A4_FIRST_ID 0x0910
#define A4_LAST_ID 0x091f
#define AIR_SPEED_FIRST_ID 0x0a00
#define AIR_SPEED_LAST_ID 0x0a0f
#define RSSI_ID 0xf101
#define ADC1_ID 0xf102
#define ADC2_ID 0xf103
#define BATT_ID 0xf104
#define SWR_ID 0xf105
// Default sensor data IDs (Physical IDs + CRC)
#define DATA_ID_VARIO 0x00 // 0
#define DATA_ID_FLVSS 0xA1 // 1
#define DATA_ID_FAS 0x22 // 2
#define DATA_ID_GPS 0x83 // 3
#define DATA_ID_RPM 0xE4 // 4
#define DATA_ID_SP2UH 0x45 // 5
#define DATA_ID_SP2UR 0xC6 // 6
// Global Fr-Sky telemetry data variables
extern uint8_t frskyStreaming; // >0 (true) == data is streaming in. 0 = nodata detected for some time
@ -70,14 +167,15 @@ extern uint8_t telemetryState;
#endif
#if defined(CPUARM)
#define TELEMETRY_AVERAGE_COUNT 3 //we actually average one more reading!
#define TELEMETRY_AVERAGE_COUNT 3 // we actually average one more reading!
#define RAW_FRSKY_MINMAX(v) v.values[TELEMETRY_AVERAGE_COUNT-1]
class FrskyValueWithMin {
public:
uint8_t value; //fitered value (average of last TELEMETRY_AVERAGE_COUNT+1 values)
uint8_t value; // fitered value (average of last TELEMETRY_AVERAGE_COUNT+1 values)
uint8_t min;
uint8_t values[TELEMETRY_AVERAGE_COUNT];
void set(uint8_t value);
void reset();
};
#else
#define RAW_FRSKY_MINMAX(v) v.value
@ -97,97 +195,9 @@ class FrskyValueWithMinMax: public FrskyValueWithMin {
};
#if defined(CPUARM)
PACK(struct FrskySerialData {
int16_t spare1;
int16_t gpsAltitude_bp; // 0x01 before punct
int16_t temperature1; // 0x02 -20 .. 250 deg. celcius
uint16_t rpm; // 0x03 0..60,000 revs. per minute
uint16_t fuelLevel; // 0x04 0, 25, 50, 75, 100 percent
int16_t temperature2; // 0x05 -20 .. 250 deg. celcius
uint16_t volts; // 0x06 1/500V increments (0..4.2V)
uint32_t distFromEarthAxis;// 2 spares reused
int16_t gpsAltitude_ap; // 0x01+8 after punct
uint16_t spare2[6];
int16_t baroAltitude_bp; // 0x10 0..9,999 meters
uint16_t gpsSpeed_bp; // 0x11 before punct
uint16_t gpsLongitude_bp; // 0x12 before punct
uint16_t gpsLatitude_bp; // 0x13 before punct
uint16_t gpsCourse_bp; // 0x14 before punct (0..359.99 deg. -- seemingly 2-decimal precision)
uint8_t day; // 0x15
uint8_t month; // 0x15
uint16_t year; // 0x16
uint8_t hour; // 0x17
uint8_t min; // 0x17
uint16_t sec; // 0x18
uint16_t gpsSpeed_ap; // 0x11+8
uint16_t gpsLongitude_ap; // 0x12+8
uint16_t gpsLatitude_ap; // 0x13+8
uint16_t gpsCourse_ap; // 0x14+8
uint32_t pilotLatitude; // 2 spares reused
uint32_t pilotLongitude; // 2 spares reused
uint16_t baroAltitude_ap; // 0x21 after punct
uint16_t gpsLongitudeEW; // 0x1A+8 East/West
uint16_t gpsLatitudeNS; // 0x1B+8 North/South
int16_t accelX; // 0x24 1/256th gram (-8g ~ +8g)
int16_t accelY; // 0x25 1/256th gram (-8g ~ +8g)
int16_t accelZ; // 0x26 1/256th gram (-8g ~ +8g)
int16_t spare3;
uint16_t current; // 0x28 Current
int16_t spare4[7];
int16_t varioSpeed; // 0x30 Vertical speed in cm/s
int32_t baroAltitudeOffset;
int32_t baroAltitude;
int32_t gpsAltitudeOffset;
uint32_t gpsDistance;
uint16_t vfas; // 0x39 Added to FrSky protocol for home made sensors with a better precision
uint16_t volts_bp; // 0x3A
uint16_t volts_ap; // 0x3B
uint16_t spare5[4];
// end of FrSky Hub data
/* these fields must keep this order! */
int16_t minAltitude;
int16_t maxAltitude;
uint16_t maxRpm;
int16_t maxTemperature1;
int16_t maxTemperature2;
uint16_t maxGpsSpeed;
uint16_t maxGpsDistance;
uint16_t maxAirSpeed;
int16_t minCell;
int16_t minCells;
int16_t minVfas;
uint16_t maxCurrent;
uint16_t maxPower;
/* end */
uint8_t gpsDistNeeded:1; // 1bits out of 16bits spare reused
int8_t gpsFix:2; // 2bits out of 16bits spare reused: -1=never fixed, 0=not fixed now, 1=fixed
uint8_t openXsensor:1; // 1bits out of 16bits spare reused: we receive data from the openXsensor
uint8_t varioHighPrecision:1;
uint8_t spare6:3;
int32_t gpsAltitude;
uint16_t currentConsumption;
uint16_t currentPrescale;
uint16_t power;
uint8_t cellsCount;
uint8_t sensorCellsCount[2];
uint16_t cellVolts[12];
int16_t cellsSum;
uint16_t cellsState;
uint16_t minCellVolts;
uint16_t airSpeed;
uint16_t dTE;
});
#elif defined(FRSKY_HUB)
PACK(struct FrskySerialData {
int16_t baroAltitudeOffset;// spare reused
int16_t gpsAltitude_bp; // 0x01 before punct
@ -306,14 +316,20 @@ enum TelemAnas {
TELEM_ANA_COUNT
};
#if defined(CPUARM)
struct FrskyData {
#if defined(SWR)
FrskyValueWithMin swr; // TODO Min not needed
#endif
FrskyValueWithMin rssi; // TODO Min not needed
};
#else
struct FrskyData {
FrskyValueWithMinMax analog[TELEM_ANA_COUNT];
FrskyValueWithMin rssi[2];
#if defined(CPUARM)
FrskyValueWithMin swr;
#endif
FrskySerialData hub;
};
#endif
enum AlarmLevel {
alarm_off = 0,
@ -326,13 +342,12 @@ enum AlarmLevel {
#define ALARM_LEVEL(channel, alarm) ((g_model.frsky.channels[channel].alarms_level >> (2*alarm)) & 3)
#if defined(CPUARM)
#define TELEMETRY_STREAMING() (frskyData.rssi[0].value > 0)
#define TELEMETRY_STREAMING() (frskyData.rssi.value > 0)
#define TELEMETRY_RSSI() (frskyData.rssi.value)
#define TELEMETRY_RSSI_MIN() (frskyData.rssi.min)
#define TELEMETRY_CELL_VOLTAGE_MUTLIPLIER 1
#define TELEMETRY_BARO_ALT_AVAILABLE() SWITCH_SIMU(true, frskyData.hub.baroAltitudeOffset)
#define TELEMETRY_BARO_ALT_UNIT (IS_IMPERIAL_ENABLE() ? LENGTH_UNIT_IMP : LENGTH_UNIT_METR)
#define TELEMETRY_GPS_SPEED_BP frskyData.hub.gpsSpeed_bp
#define TELEMETRY_GPS_SPEED_AP frskyData.hub.gpsSpeed_ap
@ -371,6 +386,8 @@ enum AlarmLevel {
#define TELEMETRY_OPENXSENSOR() (0)
#else
#define TELEMETRY_STREAMING() (frskyStreaming > 0)
#define TELEMETRY_RSSI() (frskyData.rssi[0].value)
#define TELEMETRY_RSSI_MIN() (frskyData.rssi[0].min)
#define TELEMETRY_CELL_VOLTAGE_MUTLIPLIER 2
@ -453,11 +470,12 @@ enum FrSkyDataState {
#endif
// FrSky D Protocol
void processHubPacket(uint8_t id, int16_t value);
void frskyDSendNextAlarm(void);
void frskyDProcessPacket(uint8_t *packet);
// FrSky S.PORT Protocol
void frskySportProcessPacket(uint8_t *packet);
void processSportPacket(uint8_t *packet);
void telemetryWakeup(void);
void telemetryReset();

View file

@ -48,7 +48,7 @@
#define RSSI2PKT 0xf6
#define RSSI_REQUEST 0xf1
#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
#if !defined(CPUARM) && (defined(FRSKY_HUB) || defined(WS_HOW_HIGH))
void checkMinMaxAltitude()
{
if (TELEMETRY_RELATIVE_BARO_ALT_BP > frskyData.hub.maxAltitude)
@ -93,7 +93,11 @@ void parseTelemHubByte(uint8_t byte)
state = TS_IDLE;
}
else {
structPos = byte*2;
#if defined(CPUARM)
structPos = byte;
#else
structPos = byte * 2;
#endif
state = TS_DATA_LOW;
}
return;
@ -106,6 +110,10 @@ void parseTelemHubByte(uint8_t byte)
state = TS_IDLE;
#if defined(CPUARM)
processHubPacket(structPos, (byte << 8) + lowByte);
#else
#if defined(GPS)
if ((uint8_t)structPos == offsetof(FrskySerialData, gpsLatitude_bp)) {
if (lowByte || byte)
@ -256,10 +264,11 @@ void parseTelemHubByte(uint8_t byte)
break;
#endif
}
#endif
}
#endif
#if defined(WS_HOW_HIGH)
#if defined(WS_HOW_HIGH) && !defined(CPUARM)
void parseTelemWSHowHighByte(uint8_t byte)
{
if (frskyUsrStreaming < (WSHH_TIMEOUT10ms - 10)) {
@ -275,6 +284,31 @@ void parseTelemWSHowHighByte(uint8_t byte)
}
#endif
#if defined(CPUARM)
void frskyDProcessPacket(uint8_t *packet)
{
// What type of packet?
switch (packet[0])
{
case LINKPKT: // A1/A2/RSSI values
{
setTelemetryValue(TELEM_PROTO_FRSKY_D, D_A1_ID, 0, packet[1], UNIT_VOLTS, 0);
setTelemetryValue(TELEM_PROTO_FRSKY_D, D_A2_ID, 0, packet[2], UNIT_VOLTS, 0);
setTelemetryValue(TELEM_PROTO_FRSKY_D, D_RSSI_ID, 0, packet[3], UNIT_RAW, 0);
frskyData.rssi.set(packet[3]);
frskyStreaming = FRSKY_TIMEOUT10ms; // reset counter only if valid frsky packets are being detected
break;
}
case USRPKT: // User Data packet
uint8_t numBytes = 3 + (packet[1] & 0x07); // sanitize in case of data corruption leading to buffer overflow
for (uint8_t i=3; i<numBytes; i++) {
parseTelemHubByte(packet[i]);
}
break;
}
}
#else
void frskyDProcessPacket(uint8_t *packet)
{
// What type of packet?
@ -315,6 +349,7 @@ void frskyDProcessPacket(uint8_t *packet)
#endif
}
}
#endif
#if !defined(PCBTARANIS)
@ -347,6 +382,7 @@ void frskyDSendNextAlarm(void)
}
#endif
#if 0
uint8_t *ptr = &frskyTxBuffer[0];
*ptr++ = START_STOP; // Start of packet
@ -376,6 +412,9 @@ void frskyDSendNextAlarm(void)
*ptr++ = START_STOP; // End of packet
telemetryTransmitBuffer(frskyTxBuffer, ptr - &frskyTxBuffer[0]);
#elif !defined(WIN32)
#warning "FrSky module alarms removed!"
#endif
}
#else
@ -460,4 +499,160 @@ bool isFrskyAlarmRaised(uint8_t idx)
}
#endif
#if defined(CPUARM)
struct FrSkyDSensor {
const uint8_t id;
const char * name;
const TelemetryUnit unit;
const uint8_t prec;
};
const FrSkyDSensor frskyDSensors[] = {
{ D_RSSI_ID, ZSTR_RSSI, UNIT_RAW, 0 },
{ D_A1_ID, ZSTR_A1, UNIT_VOLTS, 0 },
{ D_A2_ID, ZSTR_A2, UNIT_VOLTS, 0 },
{ RPM_ID, ZSTR_RPM, UNIT_RAW, 0 },
{ FUEL_ID, ZSTR_FUEL, UNIT_PERCENT, 0 },
{ TEMP1_ID, ZSTR_TEMP, UNIT_CELSIUS, 0 },
{ TEMP2_ID, ZSTR_TEMP, UNIT_CELSIUS, 0 },
{ CURRENT_ID, ZSTR_CURR, UNIT_AMPS, 1 },
{ ACCEL_X_ID, ZSTR_ACCX, UNIT_G, 3 },
{ ACCEL_Y_ID, ZSTR_ACCY, UNIT_G, 3 },
{ ACCEL_Z_ID, ZSTR_ACCZ, UNIT_G, 3 },
{ VARIO_ID, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 2 },
{ VFAS_ID, ZSTR_VFAS, UNIT_VOLTS, 2 },
{ BARO_ALT_AP_ID, ZSTR_ALT, UNIT_METERS, 2 },
{ GPS_SPEED_BP_ID, ZSTR_GSPD, UNIT_KTS, 0 },
{ GPS_COURS_BP_ID, ZSTR_HDG, UNIT_DEGREE, 0 },
{ VOLTS_ID, ZSTR_CELLS, UNIT_CELLS, 2 },
{ GPS_ALT_BP_ID, ZSTR_GPSALT, UNIT_METERS, 0 },
{ GPS_HOUR_MIN_ID, ZSTR_GPSDATETIME, UNIT_DATETIME, 0 },
{ GPS_LAT_AP_ID, ZSTR_GPS, UNIT_GPS, 0 },
{ 0, NULL, UNIT_RAW, 0 } // sentinel
};
const FrSkyDSensor * getFrSkyDSensor(uint8_t id)
{
const FrSkyDSensor * result = NULL;
for (const FrSkyDSensor * sensor = frskyDSensors; sensor->id; sensor++) {
if (id == sensor->id) {
result = sensor;
break;
}
}
return result;
}
void processHubPacket(uint8_t id, int16_t value)
{
static uint8_t lastId = 0;
static uint16_t lastValue = 0;
TelemetryUnit unit = UNIT_RAW;
uint8_t precision = 0;
int32_t data = value;
if (id > FRSKY_LAST_ID || id == GPS_SPEED_AP_ID || id == GPS_ALT_AP_ID || id == GPS_COURS_AP_ID) {
return;
}
if (id == GPS_LAT_BP_ID || id == GPS_LONG_BP_ID || id == GPS_ALT_BP_ID || id == BARO_ALT_BP_ID || id == VOLTS_BP_ID) {
lastId = id;
lastValue = value;
return;
}
if (id == GPS_LAT_AP_ID) {
if (lastId == GPS_LAT_BP_ID) {
data += lastValue << 16;
unit = UNIT_GPS_LATITUDE;
}
else {
return;
}
}
else if (id == GPS_LONG_AP_ID) {
if (lastId == GPS_LONG_BP_ID) {
data += lastValue << 16;
id = GPS_LAT_AP_ID;
unit = UNIT_GPS_LONGITUDE;
}
else {
return;
}
}
else if (id == GPS_LAT_NS_ID) {
id = GPS_LAT_AP_ID;
unit = UNIT_GPS_LATITUDE_NS;
}
else if (id == GPS_LONG_EW_ID) {
id = GPS_LAT_AP_ID;
unit = UNIT_GPS_LONGITUDE_EW;
}
else if (id == BARO_ALT_AP_ID) {
if (lastId == BARO_ALT_BP_ID) {
data += lastValue * 100;
unit = UNIT_METERS;
precision = 2;
}
else {
return;
}
}
else if (id == VOLTS_ID) {
unit = UNIT_CELLS;
}
else if (id == GPS_DAY_MONTH_ID) {
id = GPS_HOUR_MIN_ID;
unit = UNIT_DATETIME_DAY_MONTH;
}
else if (id == GPS_HOUR_MIN_ID) {
unit = UNIT_DATETIME_HOUR_MIN;
}
else if (id == GPS_SEC_ID) {
id = GPS_HOUR_MIN_ID;
unit = UNIT_DATETIME_SEC;
}
else if (id == GPS_YEAR_ID) {
id = GPS_HOUR_MIN_ID;
unit = UNIT_DATETIME_YEAR;
}
else {
const FrSkyDSensor * sensor = getFrSkyDSensor(id);
if (sensor) {
unit = sensor->unit;
precision = sensor->prec;
}
}
setTelemetryValue(TELEM_PROTO_FRSKY_D, id, 0, data, unit, precision);
}
void frskyDSetDefault(int index, uint16_t id)
{
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[index];
telemetrySensor.id = id;
telemetrySensor.instance = 0;
const FrSkyDSensor * sensor = getFrSkyDSensor(id);
if (sensor) {
TelemetryUnit unit = sensor->unit;
if (unit == UNIT_CELLS)
unit = UNIT_VOLTS;
uint8_t prec = min<uint8_t>(2, sensor->prec);
telemetrySensor.init(sensor->name, unit, prec);
if (id >= D_A1_ID && id <= D_A2_ID) {
telemetrySensor.prec = 1;
telemetrySensor.custom.ratio = 132;
telemetrySensor.inputFlags = TELEM_INPUT_FLAGS_FILTERING;
}
else if (id == D_RSSI_ID) {
telemetrySensor.inputFlags = TELEM_INPUT_FLAGS_FILTERING;
}
}
else {
telemetrySensor.init(id);
}
eeDirty(EE_MODEL);
}
#endif

View file

@ -36,229 +36,48 @@
#include "../opentx.h"
// FrSky PRIM IDs (1 byte)
#define DATA_FRAME 0x10
struct FrSkySportSensor {
const uint16_t firstId;
const uint16_t lastId;
const char * name;
const TelemetryUnit unit;
const uint8_t prec;
};
// FrSky old DATA IDs (1 byte)
#define GPS_ALT_BP_ID 0x01
#define TEMP1_ID 0x02
#define RPM_ID 0x03
#define FUEL_ID 0x04
#define TEMP2_ID 0x05
#define VOLTS_ID 0x06
#define GPS_ALT_AP_ID 0x09
#define BARO_ALT_BP_ID 0x10
#define GPS_SPEED_BP_ID 0x11
#define GPS_LONG_BP_ID 0x12
#define GPS_LAT_BP_ID 0x13
#define GPS_COURS_BP_ID 0x14
#define GPS_DAY_MONTH_ID 0x15
#define GPS_YEAR_ID 0x16
#define GPS_HOUR_MIN_ID 0x17
#define GPS_SEC_ID 0x18
#define GPS_SPEED_AP_ID 0x19
#define GPS_LONG_AP_ID 0x1A
#define GPS_LAT_AP_ID 0x1B
#define GPS_COURS_AP_ID 0x1C
#define BARO_ALT_AP_ID 0x21
#define GPS_LONG_EW_ID 0x22
#define GPS_LAT_NS_ID 0x23
#define ACCEL_X_ID 0x24
#define ACCEL_Y_ID 0x25
#define ACCEL_Z_ID 0x26
#define CURRENT_ID 0x28
#define VARIO_ID 0x30
#define VFAS_ID 0x39
#define VOLTS_BP_ID 0x3A
#define VOLTS_AP_ID 0x3B
#define FRSKY_LAST_ID 0x3F
const FrSkySportSensor sportSensors[] = {
{ RSSI_ID, RSSI_ID, ZSTR_RSSI, UNIT_RAW, 0 },
{ ADC1_ID, ADC1_ID, ZSTR_A1, UNIT_VOLTS, 0 },
{ ADC2_ID, ADC2_ID, ZSTR_A2, UNIT_VOLTS, 0 },
{ BATT_ID, BATT_ID, ZSTR_BATT, UNIT_VOLTS, 0 },
{ T1_FIRST_ID, T2_LAST_ID, ZSTR_TEMP, UNIT_CELSIUS, 0 },
{ RPM_FIRST_ID, RPM_LAST_ID, ZSTR_RPM, UNIT_RPMS, 0 },
{ FUEL_FIRST_ID, FUEL_LAST_ID, ZSTR_FUEL, UNIT_PERCENT, 0 },
{ ALT_FIRST_ID, ALT_LAST_ID, ZSTR_ALT, UNIT_METERS, 2 },
{ VARIO_FIRST_ID, VARIO_LAST_ID, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 2 },
{ ACCX_FIRST_ID, ACCX_LAST_ID, ZSTR_ACCX, UNIT_G, 2 },
{ ACCY_FIRST_ID, ACCY_LAST_ID, ZSTR_ACCY, UNIT_G, 2 },
{ ACCZ_FIRST_ID, ACCZ_LAST_ID, ZSTR_ACCZ, UNIT_G, 2 },
{ CURR_FIRST_ID, CURR_LAST_ID, ZSTR_CURR, UNIT_AMPS, 1 },
{ VFAS_FIRST_ID, VFAS_LAST_ID, ZSTR_VFAS, UNIT_VOLTS, 2 },
{ AIR_SPEED_FIRST_ID, AIR_SPEED_LAST_ID, ZSTR_ASPD, UNIT_METERS_PER_SECOND, 1 },
{ GPS_SPEED_FIRST_ID, GPS_SPEED_LAST_ID, ZSTR_GSPD, UNIT_KTS, 3 },
{ CELLS_FIRST_ID, CELLS_LAST_ID, ZSTR_CELLS, UNIT_CELLS, 2 },
{ GPS_ALT_FIRST_ID, GPS_ALT_LAST_ID, ZSTR_GPSALT, UNIT_METERS, 2 },
{ GPS_TIME_DATE_FIRST_ID, GPS_TIME_DATE_LAST_ID, ZSTR_GPSDATETIME, UNIT_DATETIME, 0 },
{ GPS_LONG_LATI_FIRST_ID, GPS_LONG_LATI_LAST_ID, ZSTR_GPS, UNIT_GPS, 0 },
{ 0, 0, NULL, UNIT_RAW, 0 } // sentinel
};
// FrSky new DATA IDs (2 bytes)
#define ALT_FIRST_ID 0x0100
#define ALT_LAST_ID 0x010f
#define VARIO_FIRST_ID 0x0110
#define VARIO_LAST_ID 0x011f
#define CURR_FIRST_ID 0x0200
#define CURR_LAST_ID 0x020f
#define VFAS_FIRST_ID 0x0210
#define VFAS_LAST_ID 0x021f
#define CELLS_FIRST_ID 0x0300
#define CELLS_LAST_ID 0x030f
#define T1_FIRST_ID 0x0400
#define T1_LAST_ID 0x040f
#define T2_FIRST_ID 0x0410
#define T2_LAST_ID 0x041f
#define RPM_FIRST_ID 0x0500
#define RPM_LAST_ID 0x050f
#define FUEL_FIRST_ID 0x0600
#define FUEL_LAST_ID 0x060f
#define ACCX_FIRST_ID 0x0700
#define ACCX_LAST_ID 0x070f
#define ACCY_FIRST_ID 0x0710
#define ACCY_LAST_ID 0x071f
#define ACCZ_FIRST_ID 0x0720
#define ACCZ_LAST_ID 0x072f
#define GPS_LONG_LATI_FIRST_ID 0x0800
#define GPS_LONG_LATI_LAST_ID 0x080f
#define GPS_ALT_FIRST_ID 0x0820
#define GPS_ALT_LAST_ID 0x082f
#define GPS_SPEED_FIRST_ID 0x0830
#define GPS_SPEED_LAST_ID 0x083f
#define GPS_COURS_FIRST_ID 0x0840
#define GPS_COURS_LAST_ID 0x084f
#define GPS_TIME_DATE_FIRST_ID 0x0850
#define GPS_TIME_DATE_LAST_ID 0x085f
#define A3_FIRST_ID 0x0900
#define A3_LAST_ID 0x090f
#define A4_FIRST_ID 0x0910
#define A4_LAST_ID 0x091f
#define AIR_SPEED_FIRST_ID 0x0a00
#define AIR_SPEED_LAST_ID 0x0a0f
#define RSSI_ID 0xf101
#define ADC1_ID 0xf102
#define ADC2_ID 0xf103
#define BATT_ID 0xf104
#define SWR_ID 0xf105
// Default sensor data IDs (Physical IDs + CRC)
#define DATA_ID_VARIO 0x00 // 0
#define DATA_ID_FLVSS 0xA1 // 1
#define DATA_ID_FAS 0x22 // 2
#define DATA_ID_GPS 0x83 // 3
#define DATA_ID_RPM 0xE4 // 4
#define DATA_ID_SP2UH 0x45 // 5
#define DATA_ID_SP2UR 0xC6 // 6
void setBaroAltitude(int32_t baroAltitude)
const FrSkySportSensor * getFrSkySportSensor(uint16_t id)
{
// First received barometer altitude => Altitude offset
if (!frskyData.hub.baroAltitudeOffset)
frskyData.hub.baroAltitudeOffset = -baroAltitude;
baroAltitude += frskyData.hub.baroAltitudeOffset;
frskyData.hub.baroAltitude = baroAltitude;
baroAltitude /= 100;
if (baroAltitude > frskyData.hub.maxAltitude)
frskyData.hub.maxAltitude = baroAltitude;
if (baroAltitude < frskyData.hub.minAltitude)
frskyData.hub.minAltitude = baroAltitude;
}
void processHubPacket(uint8_t id, uint16_t value)
{
if (id > FRSKY_LAST_ID)
return;
if (id == GPS_LAT_BP_ID) {
if (value)
frskyData.hub.gpsFix = 1;
else if (frskyData.hub.gpsFix > 0 && frskyData.hub.gpsLatitude_bp > 1)
frskyData.hub.gpsFix = 0;
}
else if (id == GPS_LONG_BP_ID) {
if (value)
frskyData.hub.gpsFix = 1;
else if (frskyData.hub.gpsFix > 0 && frskyData.hub.gpsLongitude_bp > 1)
frskyData.hub.gpsFix = 0;
}
if (id == GPS_ALT_BP_ID || (id >= GPS_ALT_AP_ID && id <= GPS_LAT_NS_ID && id != BARO_ALT_BP_ID && id != BARO_ALT_AP_ID)) {
// if we don't have a fix, we may discard the value
if (frskyData.hub.gpsFix <= 0)
return;
}
((uint16_t*)&frskyData.hub)[id] = value;
switch (id) {
case RPM_ID:
frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2);
if (frskyData.hub.rpm > frskyData.hub.maxRpm)
frskyData.hub.maxRpm = frskyData.hub.rpm;
break;
case TEMP1_ID:
if (frskyData.hub.temperature1 > frskyData.hub.maxTemperature1)
frskyData.hub.maxTemperature1 = frskyData.hub.temperature1;
break;
case TEMP2_ID:
if (frskyData.hub.temperature2 > frskyData.hub.maxTemperature2)
frskyData.hub.maxTemperature2 = frskyData.hub.temperature2;
break;
case CURRENT_ID:
if ((int16_t)frskyData.hub.current > 0 && ((int16_t)frskyData.hub.current + g_model.frsky.fasOffset) > 0)
frskyData.hub.current += g_model.frsky.fasOffset;
else
frskyData.hub.current = 0;
if (frskyData.hub.current > frskyData.hub.maxCurrent)
frskyData.hub.maxCurrent = frskyData.hub.current;
break;
case VOLTS_AP_ID:
#if defined(FAS_BSS)
frskyData.hub.vfas = (frskyData.hub.volts_bp * 10 + frskyData.hub.volts_ap);
#else
frskyData.hub.vfas = ((frskyData.hub.volts_bp * 100 + frskyData.hub.volts_ap * 10) * 21) / 110;
#endif
if (!frskyData.hub.minVfas || frskyData.hub.vfas < frskyData.hub.minVfas)
frskyData.hub.minVfas = frskyData.hub.vfas;
break;
case BARO_ALT_AP_ID:
if (frskyData.hub.baroAltitude_ap > 9)
frskyData.hub.varioHighPrecision = true;
if (!frskyData.hub.varioHighPrecision)
frskyData.hub.baroAltitude_ap *= 10;
setBaroAltitude((int32_t)100 * frskyData.hub.baroAltitude_bp + (frskyData.hub.baroAltitude_bp >= 0 ? frskyData.hub.baroAltitude_ap : -frskyData.hub.baroAltitude_ap));
break;
case GPS_ALT_AP_ID:
{
frskyData.hub.gpsAltitude = (frskyData.hub.gpsAltitude_bp * 100) + frskyData.hub.gpsAltitude_ap;
if (!frskyData.hub.gpsAltitudeOffset)
frskyData.hub.gpsAltitudeOffset = -frskyData.hub.gpsAltitude;
if (!frskyData.hub.baroAltitudeOffset) {
int altitude = TELEMETRY_RELATIVE_GPS_ALT_BP;
if (altitude > frskyData.hub.maxAltitude)
frskyData.hub.maxAltitude = altitude;
if (altitude < frskyData.hub.minAltitude)
frskyData.hub.minAltitude = altitude;
}
if (!frskyData.hub.pilotLatitude && !frskyData.hub.pilotLongitude) {
// First received GPS position => Pilot GPS position
getGpsPilotPosition();
}
else if (frskyData.hub.gpsDistNeeded || g_menuStack[g_menuStackPtr] == menuTelemetryFrsky) {
getGpsDistance();
}
const FrSkySportSensor * result = NULL;
for (const FrSkySportSensor * sensor = sportSensors; sensor->firstId; sensor++) {
if (id >= sensor->firstId && id <= sensor->lastId) {
result = sensor;
break;
}
case GPS_SPEED_BP_ID:
// Speed => Max speed
if (frskyData.hub.gpsSpeed_bp > frskyData.hub.maxGpsSpeed)
frskyData.hub.maxGpsSpeed = frskyData.hub.gpsSpeed_bp;
break;
case VOLTS_ID:
frskyUpdateCells();
break;
case GPS_HOUR_MIN_ID:
frskyData.hub.hour = ((uint8_t)(frskyData.hub.hour + g_eeGeneral.timezone + 24)) % 24;
break;
case ACCEL_X_ID:
case ACCEL_Y_ID:
case ACCEL_Z_ID:
((int16_t*)(&frskyData.hub))[id] /= 10;
break;
}
return result;
}
bool checkSportPacket(uint8_t *packet)
@ -279,7 +98,7 @@ bool checkSportPacket(uint8_t *packet)
#define SPORT_DATA_U32(packet) (*((uint32_t *)(packet+4)))
#define HUB_DATA_U16(packet) (*((uint16_t *)(packet+4)))
void frskySportProcessPacket(uint8_t *packet)
void processSportPacket(uint8_t *packet)
{
uint8_t dataId = packet[0];
uint8_t prim = packet[1];
@ -289,207 +108,72 @@ void frskySportProcessPacket(uint8_t *packet)
return;
}
switch (prim)
{
case DATA_FRAME:
if (prim == DATA_FRAME) {
uint32_t data = SPORT_DATA_S32(packet);
if (appId == RSSI_ID) {
frskyStreaming = FRSKY_TIMEOUT10ms; // reset counter only if valid frsky packets are being detected
link_counter += 256 / FRSKY_SPORT_AVERAGING;
frskyData.rssi[0].set(SPORT_DATA_U8(packet));
data = SPORT_DATA_U8(packet);
frskyData.rssi.set(data);
}
if (appId == SWR_ID) {
frskyData.swr.set(SPORT_DATA_U8(packet));
else if (appId == SWR_ID) {
#if defined(SWR)
data = SPORT_DATA_U8(packet);
frskyData.swr.set(data);
#else
// SWR skipped (not reliable on Taranis+)
return;
#endif
}
else if (frskyData.rssi[0].value > 0) {
if (appId == ADC1_ID || appId == ADC2_ID) {
// A1/A2 of DxR receivers
uint8_t idx = appId - ADC1_ID;
frskyData.analog[idx].set(SPORT_DATA_U8(packet), g_model.frsky.channels[idx].type);
#if defined(VARIO)
uint8_t varioSource = g_model.frsky.varioSource - VARIO_SOURCE_A1;
if (varioSource == appId-ADC1_ID) {
frskyData.hub.varioSpeed = applyChannelRatio(varioSource, frskyData.analog[varioSource].value);
}
#endif
}
else if (appId == BATT_ID) {
frskyData.analog[TELEM_ANA_A1].set(SPORT_DATA_U8(packet), UNIT_VOLTS);
}
else if ((appId >> 8) == 0) {
if (TELEMETRY_STREAMING()/* because when Rx is OFF it happens that some old A1/A2 values are sent from the XJT module*/) {
if ((appId >> 8) == 0) {
// The old FrSky IDs
uint8_t id = (uint8_t)appId;
uint16_t value = HUB_DATA_U16(packet);
processHubPacket(id, value);
}
else if (appId >= T1_FIRST_ID && appId <= T1_LAST_ID) {
frskyData.hub.temperature1 = SPORT_DATA_S32(packet);
if (frskyData.hub.temperature1 > frskyData.hub.maxTemperature1)
frskyData.hub.maxTemperature1 = frskyData.hub.temperature1;
}
else if (appId >= T2_FIRST_ID && appId <= T2_LAST_ID) {
frskyData.hub.temperature2 = SPORT_DATA_S32(packet);
if (frskyData.hub.temperature2 > frskyData.hub.maxTemperature2)
frskyData.hub.maxTemperature2 = frskyData.hub.temperature2;
}
else if (appId >= RPM_FIRST_ID && appId <= RPM_LAST_ID) {
frskyData.hub.rpm = SPORT_DATA_U32(packet) / (g_model.frsky.blades+2);
if (frskyData.hub.rpm > frskyData.hub.maxRpm)
frskyData.hub.maxRpm = frskyData.hub.rpm;
}
else if (appId >= FUEL_FIRST_ID && appId <= FUEL_LAST_ID) {
frskyData.hub.fuelLevel = SPORT_DATA_U32(packet);
}
else if (appId >= ALT_FIRST_ID && appId <= ALT_LAST_ID) {
setBaroAltitude(SPORT_DATA_S32(packet));
}
else if (appId >= VARIO_FIRST_ID && appId <= VARIO_LAST_ID) {
frskyData.hub.varioSpeed = SPORT_DATA_S32(packet);
}
else if (appId >= ACCX_FIRST_ID && appId <= ACCX_LAST_ID) {
frskyData.hub.accelX = SPORT_DATA_S32(packet);
}
else if (appId >= ACCY_FIRST_ID && appId <= ACCY_LAST_ID) {
frskyData.hub.accelY = SPORT_DATA_S32(packet);
}
else if (appId >= ACCZ_FIRST_ID && appId <= ACCZ_LAST_ID) {
frskyData.hub.accelZ = SPORT_DATA_S32(packet);
}
else if (appId >= CURR_FIRST_ID && appId <= CURR_LAST_ID) {
frskyData.hub.current = SPORT_DATA_U32(packet);
if (((int16_t)frskyData.hub.current + g_model.frsky.fasOffset)>0)
frskyData.hub.current += g_model.frsky.fasOffset;
else
frskyData.hub.current = 0;
if (frskyData.hub.current > frskyData.hub.maxCurrent)
frskyData.hub.maxCurrent = frskyData.hub.current;
}
else if (appId >= VFAS_FIRST_ID && appId <= VFAS_LAST_ID) {
frskyData.hub.vfas = SPORT_DATA_U32(packet)/10; //TODO: remove /10 and display with PREC2 when using SPORT
if (!frskyData.hub.minVfas || frskyData.hub.vfas < frskyData.hub.minVfas)
frskyData.hub.minVfas = frskyData.hub.vfas;
}
else if (appId >= AIR_SPEED_FIRST_ID && appId <= AIR_SPEED_LAST_ID) {
frskyData.hub.airSpeed = SPORT_DATA_U32(packet);
if (frskyData.hub.airSpeed > frskyData.hub.maxAirSpeed)
frskyData.hub.maxAirSpeed = frskyData.hub.airSpeed;
}
else if (appId >= GPS_SPEED_FIRST_ID && appId <= GPS_SPEED_LAST_ID) {
frskyData.hub.gpsSpeed_bp = (uint16_t) (SPORT_DATA_U32(packet)/1000);
if (frskyData.hub.gpsSpeed_bp > frskyData.hub.maxGpsSpeed)
frskyData.hub.maxGpsSpeed = frskyData.hub.gpsSpeed_bp;
}
else if (appId >= GPS_TIME_DATE_FIRST_ID && appId <= GPS_TIME_DATE_LAST_ID) {
uint32_t gps_time_date = SPORT_DATA_U32(packet);
if (gps_time_date & 0x000000ff) {
frskyData.hub.year = (uint16_t) ((gps_time_date & 0xff000000) >> 24);
frskyData.hub.month = (uint8_t) ((gps_time_date & 0x00ff0000) >> 16);
frskyData.hub.day = (uint8_t) ((gps_time_date & 0x0000ff00) >> 8);
}
else {
frskyData.hub.hour = (uint8_t) ((gps_time_date & 0xff000000) >> 24);
frskyData.hub.min = (uint8_t) ((gps_time_date & 0x00ff0000) >> 16);
frskyData.hub.sec = (uint16_t) ((gps_time_date & 0x0000ff00) >> 8);
frskyData.hub.hour = ((uint8_t) (frskyData.hub.hour + g_eeGeneral.timezone + 24)) % 24;
if (appId == ADC1_ID || appId == ADC2_ID || appId == BATT_ID) {
data = SPORT_DATA_U8(packet);
}
const FrSkySportSensor * sensor = getFrSkySportSensor(appId);
TelemetryUnit unit = UNIT_RAW;
uint8_t precision = 0;
if (sensor) {
unit = sensor->unit;
precision = sensor->prec;
}
setTelemetryValue(TELEM_PROTO_FRSKY_SPORT, appId, dataId, data, unit, precision);
}
}
else if (appId >= GPS_COURS_FIRST_ID && appId <= GPS_COURS_LAST_ID) {
uint32_t course = SPORT_DATA_U32(packet);
frskyData.hub.gpsCourse_bp = course / 100;
frskyData.hub.gpsCourse_ap = course % 100;
}
else if (appId >= GPS_ALT_FIRST_ID && appId <= GPS_ALT_LAST_ID) {
frskyData.hub.gpsAltitude = SPORT_DATA_S32(packet);
if (!frskyData.hub.gpsAltitudeOffset)
frskyData.hub.gpsAltitudeOffset = -frskyData.hub.gpsAltitude;
if (!frskyData.hub.baroAltitudeOffset) {
int altitude = TELEMETRY_RELATIVE_GPS_ALT_BP;
if (altitude > frskyData.hub.maxAltitude)
frskyData.hub.maxAltitude = altitude;
if (altitude < frskyData.hub.minAltitude)
frskyData.hub.minAltitude = altitude;
}
if (frskyData.hub.gpsFix > 0) {
if (!frskyData.hub.pilotLatitude && !frskyData.hub.pilotLongitude) {
// First received GPS position => Pilot GPS position
getGpsPilotPosition();
}
else if (frskyData.hub.gpsDistNeeded || g_menuStack[g_menuStackPtr] == menuTelemetryFrsky) {
getGpsDistance();
}
}
}
else if (appId >= GPS_LONG_LATI_FIRST_ID && appId <= GPS_LONG_LATI_LAST_ID) {
uint32_t gps_long_lati_data = SPORT_DATA_U32(packet);
uint32_t gps_long_lati_b1w, gps_long_lati_a1w;
gps_long_lati_b1w = (gps_long_lati_data & 0x3fffffff) / 10000;
gps_long_lati_a1w = (gps_long_lati_data & 0x3fffffff) % 10000;
switch ((gps_long_lati_data & 0xc0000000) >> 30) {
case 0:
frskyData.hub.gpsLatitude_bp = (gps_long_lati_b1w / 60 * 100) + (gps_long_lati_b1w % 60);
frskyData.hub.gpsLatitude_ap = gps_long_lati_a1w;
frskyData.hub.gpsLatitudeNS = 'N';
break;
case 1:
frskyData.hub.gpsLatitude_bp = (gps_long_lati_b1w / 60 * 100) + (gps_long_lati_b1w % 60);
frskyData.hub.gpsLatitude_ap = gps_long_lati_a1w;
frskyData.hub.gpsLatitudeNS = 'S';
break;
case 2:
frskyData.hub.gpsLongitude_bp = (gps_long_lati_b1w / 60 * 100) + (gps_long_lati_b1w % 60);
frskyData.hub.gpsLongitude_ap = gps_long_lati_a1w;
frskyData.hub.gpsLongitudeEW = 'E';
break;
case 3:
frskyData.hub.gpsLongitude_bp = (gps_long_lati_b1w / 60 * 100) + (gps_long_lati_b1w % 60);
frskyData.hub.gpsLongitude_ap = gps_long_lati_a1w;
frskyData.hub.gpsLongitudeEW = 'W';
break;
}
if (frskyData.hub.gpsLongitudeEW && frskyData.hub.gpsLatitudeNS) {
frskyData.hub.gpsFix = 1;
}
else if (frskyData.hub.gpsFix > 0) {
frskyData.hub.gpsFix = 0;
}
}
else if (appId >= A3_FIRST_ID && appId <= A3_LAST_ID) {
frskyData.analog[TELEM_ANA_A3].set((SPORT_DATA_U32(packet)*255+165)/330, UNIT_VOLTS);
}
else if (appId >= A4_FIRST_ID && appId <= A4_LAST_ID) {
frskyData.analog[TELEM_ANA_A4].set((SPORT_DATA_U32(packet)*255+165)/330, UNIT_VOLTS);
}
else if (appId >= CELLS_FIRST_ID && appId <= CELLS_LAST_ID) {
uint32_t data = SPORT_DATA_U32(packet);
uint8_t battnumber = data & 0xF;
uint8_t cells = (data & 0xF0) >> 4;
bool useSecondCell = (battnumber+1 < cells);
if (dataId == DATA_ID_FLVSS) {
// first sensor, remember its cell count
frskyData.hub.sensorCellsCount[0] = cells;
cells += frskyData.hub.sensorCellsCount[1];
}
else {
// second sensor connected
frskyData.hub.sensorCellsCount[1] = cells;
cells += frskyData.hub.sensorCellsCount[0];
battnumber += frskyData.hub.sensorCellsCount[0];
}
if (cells != frskyData.hub.cellsCount) {
frskySetCellsCount(cells);
}
frskySetCellVoltage(battnumber, (frskyCellVoltage_t) ((data & 0x000FFF00) >> 8) / 5);
if (useSecondCell) {
frskySetCellVoltage(battnumber+1, (frskyCellVoltage_t) ((data & 0xFFF00000) >> 20) / 5);
}
}
}
break;
}
}
void frskySportSetDefault(int index, uint16_t id, uint8_t instance)
{
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[index];
telemetrySensor.id = id;
telemetrySensor.instance = instance;
const FrSkySportSensor * sensor = getFrSkySportSensor(id);
if (sensor) {
TelemetryUnit unit = sensor->unit;
if (unit == UNIT_CELLS)
unit = UNIT_VOLTS;
uint8_t prec = min<uint8_t>(2, sensor->prec);
telemetrySensor.init(sensor->name, unit, prec);
if (id >= ADC1_ID && id <= BATT_ID) {
telemetrySensor.prec = 1;
telemetrySensor.custom.ratio = 132;
telemetrySensor.inputFlags = TELEM_INPUT_FLAGS_FILTERING;
}
}
else {
telemetrySensor.init(id);
}
eeDirty(EE_MODEL);
}

523
radio/src/telemetry/telemetry.cpp Executable file
View file

@ -0,0 +1,523 @@
#include "../opentx.h"
TelemetryItem telemetryItems[TELEM_VALUES_MAX];
void TelemetryItem::gpsReceived()
{
if (!distFromEarthAxis) {
gps.extractLatitudeLongitude(&pilotLatitude, &pilotLongitude);
uint32_t lat = pilotLatitude / 10000;
uint32_t angle2 = (lat*lat) / 10000;
uint32_t angle4 = angle2 * angle2;
distFromEarthAxis = 139*(((uint32_t)10000000-((angle2*(uint32_t)123370)/81)+(angle4/25))/12500);
}
lastReceived = now();
}
void TelemetryItem::setValue(const TelemetrySensor & sensor, int32_t newVal, uint32_t unit, uint32_t prec)
{
if (unit == UNIT_CELLS) {
uint32_t data = uint32_t(newVal);
uint8_t cellIndex = data & 0xF;
uint8_t count = (data & 0xF0) >> 4;
if (count != cells.count) {
clear();
cells.count = count;
}
cells.values[cellIndex].set(((data & 0x000FFF00) >> 8) / 5);
if (cellIndex+1 < cells.count) {
cells.values[cellIndex+1].set(((data & 0xFFF00000) >> 20) / 5);
}
if (cellIndex+2 >= cells.count) {
newVal = 0;
for (int i=0; i<count; i++) {
if (cells.values[i].state) {
newVal += cells.values[i].value;
}
else {
// we didn't receive all cells values
return;
}
}
newVal = sensor.getValue(newVal, UNIT_VOLTS, prec);
}
else {
// we didn't receive all cells values
return;
}
}
else if (unit == UNIT_DATETIME) {
uint32_t data = uint32_t(newVal);
if (data & 0x000000ff) {
datetime.year = (uint16_t) ((data & 0xff000000) >> 24);
datetime.month = (uint8_t) ((data & 0x00ff0000) >> 16);
datetime.day = (uint8_t) ((data & 0x0000ff00) >> 8);
datetime.datestate = 1;
}
else {
datetime.hour = ((uint8_t) ((data & 0xff000000) >> 24) + g_eeGeneral.timezone + 24) % 24;
datetime.min = (uint8_t) ((data & 0x00ff0000) >> 16);
datetime.sec = (uint16_t) ((data & 0x0000ff00) >> 8);
datetime.timestate = 1;
}
if (datetime.year == 0) {
return;
}
newVal = 0;
}
else if (unit == UNIT_GPS) {
uint32_t gps_long_lati_data = uint32_t(newVal);
uint32_t gps_long_lati_b1w, gps_long_lati_a1w;
gps_long_lati_b1w = (gps_long_lati_data & 0x3fffffff) / 10000;
gps_long_lati_a1w = (gps_long_lati_data & 0x3fffffff) % 10000;
switch ((gps_long_lati_data & 0xc0000000) >> 30) {
case 0:
gps.latitude_bp = (gps_long_lati_b1w / 60 * 100) + (gps_long_lati_b1w % 60);
gps.latitude_ap = gps_long_lati_a1w;
gps.latitudeNS = 'N';
break;
case 1:
gps.latitude_bp = (gps_long_lati_b1w / 60 * 100) + (gps_long_lati_b1w % 60);
gps.latitude_ap = gps_long_lati_a1w;
gps.latitudeNS = 'S';
break;
case 2:
gps.longitude_bp = (gps_long_lati_b1w / 60 * 100) + (gps_long_lati_b1w % 60);
gps.longitude_ap = gps_long_lati_a1w;
gps.longitudeEW = 'E';
break;
case 3:
gps.longitude_bp = (gps_long_lati_b1w / 60 * 100) + (gps_long_lati_b1w % 60);
gps.longitude_ap = gps_long_lati_a1w;
gps.longitudeEW = 'W';
break;
}
if (gps.longitudeEW && gps.latitudeNS) {
gpsReceived();
}
return;
}
else if (unit >= UNIT_GPS_LONGITUDE && unit <= UNIT_GPS_LATITUDE_NS) {
uint32_t data = uint32_t(newVal);
switch (unit) {
case UNIT_GPS_LONGITUDE:
gps.longitude_bp = data >> 16;
gps.longitude_ap = data & 0xFFFF;
break;
case UNIT_GPS_LATITUDE:
gps.latitude_bp = data >> 16;
gps.latitude_ap = data & 0xFFFF;
break;
case UNIT_GPS_LONGITUDE_EW:
gps.longitudeEW = data;
break;
case UNIT_GPS_LATITUDE_NS:
gps.latitudeNS = data;
break;
}
if (gps.longitudeEW && gps.latitudeNS && gps.longitude_ap && gps.latitude_ap) {
gpsReceived();
}
return;
}
else if (unit == UNIT_DATETIME_YEAR) {
datetime.year = newVal;
return;
}
else if (unit == UNIT_DATETIME_DAY_MONTH) {
uint32_t data = uint32_t(newVal);
datetime.month = data >> 8;
datetime.day = data & 0xFF;
datetime.datestate = 1;
return;
}
else if (unit == UNIT_DATETIME_HOUR_MIN) {
uint32_t data = uint32_t(newVal);
datetime.hour = ((data & 0xFF) + g_eeGeneral.timezone + 24) % 24;
datetime.min = data >> 8;
}
else if (unit == UNIT_DATETIME_SEC) {
datetime.sec = newVal & 0xFF;
datetime.timestate = 1;
newVal = 0;
}
else {
newVal = sensor.getValue(newVal, unit, prec);
if (sensor.inputFlags == TELEM_INPUT_FLAGS_AUTO_OFFSET) {
if (!isAvailable()) {
offsetAuto = -newVal;
}
newVal += offsetAuto;
}
else if (sensor.inputFlags == TELEM_INPUT_FLAGS_FILTERING) {
if (!isAvailable()) {
for (int i=0; i<TELEMETRY_AVERAGE_COUNT; i++) {
filterValues[i] = newVal;
}
}
else {
// calculate the average from values[] and value
// also shift readings in values [] array
unsigned int sum = filterValues[0];
for (int i=0; i<TELEMETRY_AVERAGE_COUNT-1; i++) {
int32_t tmp = filterValues[i+1];
filterValues[i] = tmp;
sum += tmp;
}
filterValues[TELEMETRY_AVERAGE_COUNT-1] = newVal;
sum += newVal;
newVal = sum/(TELEMETRY_AVERAGE_COUNT+1);
}
}
}
if (!isAvailable()) {
valueMin = newVal;
valueMax = newVal;
}
else if (newVal < valueMin) {
valueMin = newVal;
}
else if (newVal > valueMax) {
valueMax = newVal;
if (sensor.unit == UNIT_VOLTS) {
valueMin = newVal;
}
}
value = newVal;
lastReceived = now();
}
bool TelemetryItem::isAvailable()
{
return (lastReceived != TELEMETRY_VALUE_UNAVAILABLE);
}
bool TelemetryItem::isFresh()
{
return (lastReceived < TELEMETRY_VALUE_TIMER_CYCLE) && (uint8_t(now() - lastReceived) < 2);
}
bool TelemetryItem::isOld()
{
return (lastReceived == TELEMETRY_VALUE_OLD);
}
void TelemetryItem::per10ms(const TelemetrySensor & sensor)
{
switch (sensor.formula) {
case TELEM_FORMULA_CONSUMPTION:
if (sensor.consumption.source) {
TelemetrySensor & currentSensor = g_model.telemetrySensors[sensor.consumption.source-1];
TelemetryItem & currentItem = telemetryItems[sensor.consumption.source-1];
if (!currentItem.isAvailable()) {
return;
}
else if (currentItem.isOld()) {
lastReceived = TELEMETRY_VALUE_OLD;
return;
}
int32_t current = convertTelemetryValue(currentItem.value, currentSensor.unit, currentSensor.prec, UNIT_AMPS, 1);
currentItem.consumption.prescale += current;
if (currentItem.consumption.prescale >= 3600) {
currentItem.consumption.prescale -= 3600;
setValue(sensor, value+1, sensor.unit, sensor.prec);
}
}
break;
default:
break;
}
}
void TelemetryItem::eval(const TelemetrySensor & sensor)
{
switch (sensor.formula) {
case TELEM_FORMULA_CELL:
if (sensor.cell.source) {
TelemetryItem & cellsItem = telemetryItems[sensor.cell.source-1];
if (cellsItem.isOld()) {
lastReceived = TELEMETRY_VALUE_OLD;
}
else {
uint8_t index = sensor.cell.index;
if (index == 0 || index == 7) {
bool lowest = (index == 0);
index = 0;
for (int i=0; i<cellsItem.cells.count; i++) {
if (cellsItem.cells.values[i].state) {
if (index == 0 || (lowest && cellsItem.cells.values[i].value < cellsItem.cells.values[index-1].value) || (!lowest && cellsItem.cells.values[i].value > cellsItem.cells.values[index-1].value)) {
index = i+1;
}
}
else {
index = 0;
break;
}
}
}
index -= 1;
if (index < cellsItem.cells.count && cellsItem.cells.values[index].state) {
setValue(sensor, cellsItem.cells.values[index].value, UNIT_VOLTS, 2);
}
}
}
break;
case TELEM_FORMULA_DIST:
if (sensor.dist.gps) {
TelemetryItem gpsItem = telemetryItems[sensor.dist.gps-1];
TelemetryItem * altItem = NULL;
if (!gpsItem.isAvailable()) {
return;
}
else if (gpsItem.isOld()) {
lastReceived = TELEMETRY_VALUE_OLD;
return;
}
if (sensor.dist.alt) {
altItem = &telemetryItems[sensor.dist.alt-1];
if (!altItem->isAvailable()) {
return;
}
else if (altItem->isOld()) {
lastReceived = TELEMETRY_VALUE_OLD;
return;
}
}
uint32_t latitude, longitude;
gpsItem.gps.extractLatitudeLongitude(&latitude, &longitude);
uint32_t angle = (latitude > gpsItem.pilotLatitude) ? latitude - gpsItem.pilotLatitude : gpsItem.pilotLatitude - latitude;
uint32_t dist = EARTH_RADIUS * angle / 1000000;
uint32_t result = dist*dist;
angle = (longitude > gpsItem.pilotLongitude) ? longitude - gpsItem.pilotLongitude : gpsItem.pilotLongitude - longitude;
dist = gpsItem.distFromEarthAxis * angle / 1000000;
result += dist*dist;
if (altItem) {
dist = abs(altItem->value);
uint8_t prec = g_model.telemetrySensors[sensor.dist.alt-1].prec;
if (prec > 0)
dist /= (prec==2 ? 100 : 10);
result += dist*dist;
}
setValue(sensor, isqrt32(result), UNIT_METERS);
}
break;
case TELEM_FORMULA_ADD:
case TELEM_FORMULA_AVERAGE:
case TELEM_FORMULA_MIN:
case TELEM_FORMULA_MAX:
case TELEM_FORMULA_MULTIPLY:
{
int32_t value=0, count=0, available=0, maxitems=4, mulprec=0;
if (sensor.formula == TELEM_FORMULA_MULTIPLY) {
maxitems = 2;
value = 1;
}
for (int i=0; i<maxitems; i++) {
uint8_t source = sensor.calc.sources[i];
if (source) {
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[source-1];
TelemetryItem & telemetryItem = telemetryItems[source-1];
if (sensor.formula == TELEM_FORMULA_AVERAGE) {
if (telemetryItem.isAvailable())
available = 1;
else
continue;
if (telemetryItem.isOld())
continue;
}
else {
if (!telemetryItem.isAvailable()) {
return;
}
else if (telemetryItem.isOld()) {
lastReceived = TELEMETRY_VALUE_OLD;
return;
}
}
count += 1;
if (sensor.formula == TELEM_FORMULA_MULTIPLY) {
mulprec += telemetrySensor.prec;
value *= convertTelemetryValue(telemetryItem.value, telemetrySensor.unit, 0, sensor.unit, 0);
}
else {
int32_t sensorValue = convertTelemetryValue(telemetryItem.value, telemetrySensor.unit, telemetrySensor.prec, sensor.unit, sensor.prec);
if (sensor.formula == TELEM_FORMULA_MIN)
value = (count==1 ? sensorValue : min<int32_t>(value, sensorValue));
else if (sensor.formula == TELEM_FORMULA_MAX)
value = (count==1 ? sensorValue : max<int32_t>(value, sensorValue));
else
value += sensorValue;
}
}
}
if (sensor.formula == TELEM_FORMULA_AVERAGE) {
if (count == 0) {
if (available)
lastReceived = TELEMETRY_VALUE_OLD;
return;
}
else {
value = (value + count/2) / count;
}
}
else if (sensor.formula == TELEM_FORMULA_MULTIPLY) {
if (count == 0)
return;
value = convertTelemetryValue(value, sensor.unit, mulprec, sensor.unit, sensor.prec);
}
setValue(sensor, value, sensor.unit, sensor.prec);
break;
}
default:
break;
}
}
int getTelemetryIndex(TelemetryProtocol protocol, uint16_t id, uint8_t instance)
{
int available = -1;
for (int index=0; index<TELEM_VALUES_MAX; index++) {
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[index];
if (telemetrySensor.id == id && telemetrySensor.instance == instance) {
return index;
}
else if (available < 0 && telemetrySensor.id == 0) {
available = index;
}
}
if (available >= 0) {
switch (protocol) {
#if defined(FRSKY_SPORT)
case TELEM_PROTO_FRSKY_SPORT:
frskySportSetDefault(available, id, instance);
break;
#endif
case TELEM_PROTO_FRSKY_D:
frskyDSetDefault(available, id);
break;
default:
break;
}
}
return available;
}
void delTelemetryIndex(uint8_t index)
{
memclear(&g_model.telemetrySensors[index], sizeof(TelemetrySensor));
telemetryItems[index].clear();
eeDirty(EE_MODEL);
}
int availableTelemetryIndex()
{
for (int index=0; index<TELEM_VALUES_MAX; index++) {
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[index];
if (telemetrySensor.id == 0 && telemetrySensor.type == 0) {
return index;
}
}
return -1;
}
void setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t instance, int32_t value, uint32_t unit, uint32_t prec)
{
int index = getTelemetryIndex(protocol, id, instance);
if (index >= 0) {
telemetryItems[index].setValue(g_model.telemetrySensors[index], value, unit, prec);
}
else {
// TODO error too many sensors
}
}
void TelemetrySensor::init(const char *label, uint8_t unit, uint8_t prec)
{
memclear(this->label, TELEM_LABEL_LEN);
strncpy(this->label, label, TELEM_LABEL_LEN);
this->unit = unit;
this->prec = prec;
// this->inputFlags = inputFlags;
}
void TelemetrySensor::init(uint16_t id)
{
char label[4];
label[0] = hex2zchar((id & 0xf000) >> 12);
label[1] = hex2zchar((id & 0x0f00) >> 8);
label[2] = hex2zchar((id & 0x00f0) >> 4);
label[3] = hex2zchar((id & 0x000f) >> 0);
init(label);
}
int32_t convertTelemetryValue(int32_t value, uint8_t unit, uint8_t prec, uint8_t destUnit, uint8_t destPrec)
{
for (int i=prec; i<destPrec; i++)
value *= 10;
if (unit == UNIT_METERS) {
if (destUnit == UNIT_FEET) {
// m to ft *105/32
value = (value * 105) / 32;
}
}
else if (unit == UNIT_KTS) {
if (destUnit == UNIT_KMH) {
// kts to km/h
value = (value * 1852) / 1000;
}
else if (destUnit == UNIT_MPH) {
// kts to mph
value = (value * 23) / 20;
}
}
else if (unit == UNIT_CELSIUS) {
if (destUnit == UNIT_FAHRENHEIT) {
// T(°F) = T(°C)×1,8 + 32
value = 32 + (value*18)/10;
}
}
for (int i=destPrec; i<prec; i++)
value /= 10;
return value;
}
int32_t TelemetrySensor::getValue(int32_t value, uint8_t unit, uint8_t prec) const
{
if (type == TELEM_TYPE_CUSTOM && custom.ratio) {
if (this->prec == 2) {
value *= 10;
prec = 2;
}
else {
prec = 1;
}
value = (custom.ratio * value + 122) / 255;
}
value = convertTelemetryValue(value, unit, prec, this->unit, this->prec);
if (type == TELEM_TYPE_CUSTOM) {
value += custom.offset;
}
return value;
}

182
radio/src/telemetry/telemetry.h Executable file
View file

@ -0,0 +1,182 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef TELEMETRY_H
#define TELEMETRY_H
enum TelemetryProtocol
{
TELEM_PROTO_FRSKY_D,
TELEM_PROTO_FRSKY_SPORT,
};
#define TELEMETRY_VALUE_TIMER_CYCLE 200 /*20 seconds*/
#define TELEMETRY_VALUE_OLD_THRESHOLD 150 /*15 seconds*/
#define TELEMETRY_VALUE_UNAVAILABLE 255
#define TELEMETRY_VALUE_OLD 254
#define TELEMETRY_AVERAGE_COUNT 3
PACK(struct CellValue
{
uint16_t value:15;
uint16_t state:1;
void set(uint16_t value)
{
if (value > 50) {
this->value = value;
this->state = 1;
}
}
});
class TelemetryItem
{
public:
union {
int32_t value; // value, stored as uint32_t but interpreted accordingly to type
uint32_t distFromEarthAxis;
};
union {
int32_t valueMin; // min store
uint32_t pilotLongitude;
};
union {
int32_t valueMax; // max store
uint32_t pilotLatitude;
};
uint8_t lastReceived; // for detection of sensor loss
union {
int32_t offsetAuto;
int32_t filterValues[TELEMETRY_AVERAGE_COUNT];
struct {
uint16_t prescale;
} consumption;
struct {
uint8_t count;
CellValue values[6];
} cells;
struct {
uint8_t datestate;
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t timestate;
uint8_t hour;
uint8_t min;
uint8_t sec;
} datetime;
struct {
uint16_t longitude_bp;
uint16_t longitude_ap;
char longitudeEW;
uint16_t latitude_bp;
uint16_t latitude_ap;
char latitudeNS;
// pilot longitude is stored in min
// pilot latitude is stored in max
// distFromEarthAxis is stored in value
void extractLatitudeLongitude(uint32_t * latitude, uint32_t * longitude)
{
div_t qr = div(latitude_bp, 100);
*latitude = ((uint32_t)(qr.quot) * 1000000) + (((uint32_t)(qr.rem) * 10000 + latitude_ap) * 5) / 3;
qr = div(longitude_bp, 100);
*longitude = ((uint32_t)(qr.quot) * 1000000) + (((uint32_t)(qr.rem) * 10000 + longitude_ap) * 5) / 3;
}
} gps;
};
static uint8_t now()
{
return (get_tmr10ms() / 10) % TELEMETRY_VALUE_TIMER_CYCLE;
}
TelemetryItem()
{
clear();
}
void clear()
{
memset(this, 0, sizeof(*this));
lastReceived = TELEMETRY_VALUE_UNAVAILABLE;
}
void eval(const TelemetrySensor & sensor);
void per10ms(const TelemetrySensor & sensor);
void setValue(const TelemetrySensor & sensor, int32_t newVal, uint32_t unit, uint32_t prec=0);
bool isAvailable();
bool isFresh();
bool isOld();
void gpsReceived();
};
extern TelemetryItem telemetryItems[TELEM_VALUES_MAX];
inline bool isTelemetryFieldAvailable(int index)
{
TelemetrySensor & sensor = g_model.telemetrySensors[index];
return sensor.type == TELEM_TYPE_CALCULATED || sensor.id != 0;
}
inline bool isTelemetryFieldComparisonAvailable(int index)
{
TelemetrySensor & sensor = g_model.telemetrySensors[index];
if (sensor.type == TELEM_TYPE_CALCULATED)
return true;
if (sensor.unit == UNIT_GPS)
return false;
if (sensor.unit == UNIT_DATETIME)
return false;
return (sensor.id != 0);
}
void setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t instance, int32_t value, uint32_t unit, uint32_t prec);
void delTelemetryIndex(uint8_t index);
int availableTelemetryIndex();
int32_t getTelemetryValue(uint8_t index, uint8_t & prec);
int32_t convertTelemetryValue(int32_t value, uint8_t unit, uint8_t prec, uint8_t destUnit, uint8_t destPrec);
void frskySportSetDefault(int index, uint16_t type, uint8_t instance);
void frskyDSetDefault(int index, uint16_t id);
#endif

View file

@ -36,7 +36,7 @@
#include "gtests.h"
#if defined(FRSKY) && !defined(FRSKY_SPORT)
#if defined(FRSKY) && !defined(CPUARM)
extern void frskyDProcessPacket(uint8_t *packet);
TEST(FrSky, gpsNfuel)
{
@ -126,7 +126,7 @@ TEST(FrSkySPORT, checkCrc)
EXPECT_EQ(checkSportPacket(pkt+1), true);
}
extern void frskySportProcessPacket(uint8_t *packet);
extern void processSportPacket(uint8_t *packet);
extern bool checkSportPacket(uint8_t *packet);
extern void frskyCalculateCellStats(void);
extern void displayVoltagesScreen();
@ -166,7 +166,8 @@ void generateSportCellPacket(uint8_t * packet, uint8_t cells, uint8_t battnumber
#define _V(volts) (volts/TELEMETRY_CELL_VOLTAGE_MUTLIPLIER)
TEST(FrSkySPORT, frskySetCellVoltage)
#if 0
TEST(FrSkySPORT, DISABLED_frskySetCellVoltage)
{
uint8_t packet[FRSKY_SPORT_PACKET_SIZE];
@ -174,12 +175,12 @@ TEST(FrSkySPORT, frskySetCellVoltage)
TELEMETRY_RESET();
// test that simulates 3 cell battery
generateSportCellPacket(packet, 3, 0, _V(410), _V(420)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(410), _V(420)); processSportPacket(packet);
EXPECT_EQ(checkSportPacket(packet), true) << "Bad CRC generation in setSportPacketCrc()";
generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); processSportPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(405), _V(300)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(405), _V(300)); processSportPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.cellsCount, 3);
EXPECT_EQ(frskyData.hub.cellVolts[0], _V(405));
@ -191,11 +192,11 @@ TEST(FrSkySPORT, frskySetCellVoltage)
EXPECT_EQ(frskyData.hub.minCells, _V(113)); //all time cells sum minimum
EXPECT_EQ(frskyData.hub.cellsSum, _V(113)); //current cells sum
generateSportCellPacket(packet, 3, 0, _V(405), _V(250)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(405), _V(250)); processSportPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); processSportPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(410), _V(420)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(410), _V(420)); processSportPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.cellsCount, 3);
EXPECT_EQ(frskyData.hub.cellVolts[0], _V(410));
@ -208,9 +209,9 @@ TEST(FrSkySPORT, frskySetCellVoltage)
EXPECT_EQ(frskyData.hub.cellsSum, _V(126)); //current cells sum
//add another two cells - 5 cell battery
generateSportCellPacket(packet, 5, 0, _V(418), _V(408)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 5, 2, _V(415), _V(420)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 5, 4, _V(410), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 5, 0, _V(418), _V(408)); processSportPacket(packet);
generateSportCellPacket(packet, 5, 2, _V(415), _V(420)); processSportPacket(packet);
generateSportCellPacket(packet, 5, 4, _V(410), _V( 0)); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.cellsCount, 5);
EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418));
@ -225,9 +226,9 @@ TEST(FrSkySPORT, frskySetCellVoltage)
EXPECT_EQ(frskyData.hub.cellsSum, _V(207)); //current cells sum
//simulate very low voltage for cell 3
generateSportCellPacket(packet, 5, 0, _V(418), _V(408)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 5, 2, _V(100), _V(420)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 5, 4, _V(410), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 5, 0, _V(418), _V(408)); processSportPacket(packet);
generateSportCellPacket(packet, 5, 2, _V(100), _V(420)); processSportPacket(packet);
generateSportCellPacket(packet, 5, 4, _V(410), _V( 0)); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.cellsCount, 5);
EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418));
@ -242,9 +243,9 @@ TEST(FrSkySPORT, frskySetCellVoltage)
EXPECT_EQ(frskyData.hub.cellsSum, _V(175)); //current cells sum
//back to normal (but with reversed order of packets)
generateSportCellPacket(packet, 5, 4, _V(410), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 5, 0, _V(418), _V(408)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 5, 2, _V(412), _V(420)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 5, 4, _V(410), _V( 0)); processSportPacket(packet);
generateSportCellPacket(packet, 5, 0, _V(418), _V(408)); processSportPacket(packet);
generateSportCellPacket(packet, 5, 2, _V(412), _V(420)); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.cellsCount, 5);
EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418));
@ -261,22 +262,20 @@ TEST(FrSkySPORT, frskySetCellVoltage)
//display test
lcd_clear();
g_model.frsky.voltsSource = FRSKY_VOLTS_SOURCE_A1;
displayVoltagesScreen();
EXPECT_TRUE(checkScreenshot("one_sensor_votages_screen"));
}
TEST(FrSkySPORT, StrangeCellsBug)
TEST(FrSkySPORT, DISABLED_StrangeCellsBug)
{
TELEMETRY_RESET();
uint8_t pkt[] = { 0x7E, 0x48, 0x10, 0x00, 0x03, 0x30, 0x15, 0x50, 0x81, 0xD5 };
EXPECT_EQ(checkSportPacket(pkt+1), true);
frskySportProcessPacket(pkt+1);
processSportPacket(pkt+1);
EXPECT_EQ(frskyData.hub.cellsCount, 3);
EXPECT_EQ(frskyData.hub.cellVolts[0], _V(000)); // now we ignore such low values
EXPECT_EQ(frskyData.hub.cellVolts[1], _V(413));
}
TEST(FrSkySPORT, frskySetCellVoltageTwoSensors)
TEST(FrSkySPORT, DISABLED_frskySetCellVoltageTwoSensors)
{
uint8_t packet[FRSKY_SPORT_PACKET_SIZE];
@ -284,8 +283,8 @@ TEST(FrSkySPORT, frskySetCellVoltageTwoSensors)
TELEMETRY_RESET();
//sensor 1: 3 cell battery
generateSportCellPacket(packet, 3, 0, _V(418), _V(416)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(415), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(418), _V(416)); processSportPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(415), _V( 0)); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.cellsCount, 3);
EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418));
@ -298,12 +297,12 @@ TEST(FrSkySPORT, frskySetCellVoltageTwoSensors)
EXPECT_EQ(frskyData.hub.cellsSum, _V(124)); //current cells sum
//sensor 2: 4 cell battery
generateSportCellPacket(packet, 4, 6, _V(410), _V(420)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 4, 8, _V(400), _V(405)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 4, 6, _V(410), _V(420)); processSportPacket(packet);
generateSportCellPacket(packet, 4, 8, _V(400), _V(405)); processSportPacket(packet);
//we need to send all cells from first battery before a new calculation will be made
generateSportCellPacket(packet, 3, 0, _V(418), _V(416)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(415), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(418), _V(416)); processSportPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(415), _V( 0)); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.cellsCount, 7);
EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418));
@ -321,10 +320,10 @@ TEST(FrSkySPORT, frskySetCellVoltageTwoSensors)
EXPECT_EQ(frskyData.hub.cellsSum, _V(288)); //current cells sum
//now change some voltages
generateSportCellPacket(packet, 3, 2, _V(415), _V( 0)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 4, 8, _V(390), _V(370)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(420), _V(410)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 4, 6, _V(410), _V(420)); frskySportProcessPacket(packet);
generateSportCellPacket(packet, 3, 2, _V(415), _V( 0)); processSportPacket(packet);
generateSportCellPacket(packet, 4, 8, _V(390), _V(370)); processSportPacket(packet);
generateSportCellPacket(packet, 3, 0, _V(420), _V(410)); processSportPacket(packet);
generateSportCellPacket(packet, 4, 6, _V(410), _V(420)); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.cellsCount, 7);
EXPECT_EQ(frskyData.hub.cellVolts[0], _V(420));
@ -344,8 +343,6 @@ TEST(FrSkySPORT, frskySetCellVoltageTwoSensors)
//display test
lcd_clear();
g_model.frsky.voltsSource = FRSKY_VOLTS_SOURCE_A1;
displayVoltagesScreen();
EXPECT_TRUE(checkScreenshot("two_sensor_votages_screen"));
}
void generateSportFasVoltagePacket(uint8_t * packet, uint32_t voltage)
@ -357,7 +354,7 @@ void generateSportFasVoltagePacket(uint8_t * packet, uint32_t voltage)
setSportPacketCrc(packet);
}
TEST(FrSkySPORT, frskyVfas)
TEST(FrSkySPORT, DISABLED_frskyVfas)
{
uint8_t packet[FRSKY_SPORT_PACKET_SIZE];
@ -365,19 +362,19 @@ TEST(FrSkySPORT, frskyVfas)
TELEMETRY_RESET();
// tests for Vfas
generateSportFasVoltagePacket(packet, 5000); frskySportProcessPacket(packet);
generateSportFasVoltagePacket(packet, 5000); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.vfas, 500);
EXPECT_EQ(frskyData.hub.minVfas, 500);
generateSportFasVoltagePacket(packet, 6524); frskySportProcessPacket(packet);
generateSportFasVoltagePacket(packet, 6524); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.vfas, 652);
EXPECT_EQ(frskyData.hub.minVfas, 500);
generateSportFasVoltagePacket(packet, 1248); frskySportProcessPacket(packet);
generateSportFasVoltagePacket(packet, 1248); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.vfas, 124);
EXPECT_EQ(frskyData.hub.minVfas, 124);
generateSportFasVoltagePacket(packet, 2248); frskySportProcessPacket(packet);
generateSportFasVoltagePacket(packet, 2248); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.vfas, 224);
EXPECT_EQ(frskyData.hub.minVfas, 124);
}
@ -399,24 +396,24 @@ TEST(FrSkySPORT, frskyCurrent)
g_model.frsky.fasOffset = -5; /* unit: 1/10 amps */
// tests for Curr
generateSportFasCurrentPacket(packet, 0); frskySportProcessPacket(packet);
generateSportFasCurrentPacket(packet, 0); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.current, 0);
EXPECT_EQ(frskyData.hub.maxCurrent, 0);
// measured current less then offset - value should be zero
generateSportFasCurrentPacket(packet, 4); frskySportProcessPacket(packet);
generateSportFasCurrentPacket(packet, 4); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.current, 0);
EXPECT_EQ(frskyData.hub.maxCurrent, 0);
generateSportFasCurrentPacket(packet, 10); frskySportProcessPacket(packet);
generateSportFasCurrentPacket(packet, 10); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.current, 5);
EXPECT_EQ(frskyData.hub.maxCurrent, 5);
generateSportFasCurrentPacket(packet, 500); frskySportProcessPacket(packet);
generateSportFasCurrentPacket(packet, 500); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.current, 495);
EXPECT_EQ(frskyData.hub.maxCurrent, 495);
generateSportFasCurrentPacket(packet, 200); frskySportProcessPacket(packet);
generateSportFasCurrentPacket(packet, 200); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.current, 195);
EXPECT_EQ(frskyData.hub.maxCurrent, 495);
@ -424,18 +421,20 @@ TEST(FrSkySPORT, frskyCurrent)
TELEMETRY_RESET();
g_model.frsky.fasOffset = 5; /* unit: 1/10 amps */
generateSportFasCurrentPacket(packet, 0); frskySportProcessPacket(packet);
generateSportFasCurrentPacket(packet, 0); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.current, 5);
EXPECT_EQ(frskyData.hub.maxCurrent, 5);
generateSportFasCurrentPacket(packet, 500); frskySportProcessPacket(packet);
generateSportFasCurrentPacket(packet, 500); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.current, 505);
EXPECT_EQ(frskyData.hub.maxCurrent, 505);
generateSportFasCurrentPacket(packet, 200); frskySportProcessPacket(packet);
generateSportFasCurrentPacket(packet, 200); processSportPacket(packet);
EXPECT_EQ(frskyData.hub.current, 205);
EXPECT_EQ(frskyData.hub.maxCurrent, 505);
}
#endif
#endif //#if defined(FRSKY_SPORT)

View file

@ -43,7 +43,7 @@ inline void MIXER_RESET()
inline void TELEMETRY_RESET()
{
memclear(&frskyData, sizeof(frskyData));
frskyData.rssi[0].value = 100;
TELEMETRY_RSSI() = 100;
}
void MIXER_RESET();

View file

@ -76,30 +76,6 @@ TEST(Lua, testSetModelInfo)
EXPECT_ZSTREQ("Model 1", g_model.header.name);
}
TEST(Lua, testSetTelemetryChannel)
{
// set
luaExecStr("channel = model.getTelemetryChannel(0)");
luaExecStr("channel.range = 100.0");
luaExecStr("channel.offset = -10.0");
luaExecStr("channel.alarm1 = 60");
luaExecStr("channel.alarm2 = 50");
luaExecStr("model.setTelemetryChannel(0, channel)");
EXPECT_EQ(g_model.frsky.channels[0].multiplier, 2);
EXPECT_EQ(g_model.frsky.channels[0].ratio, 250);
EXPECT_EQ(g_model.frsky.channels[0].offset, -26);
EXPECT_EQ(g_model.frsky.channels[0].alarms_value[0], 179);
EXPECT_EQ(g_model.frsky.channels[0].alarms_value[1], 153);
//verify in Lua
luaExecStr("channel = model.getTelemetryChannel(0)");
luaExecStr("if math.abs(channel.range - 100) > 0.5 then error('channel.range is: '..channel.range) end");
luaExecStr("if math.abs(channel.offset + 10) > 0.5 then error('channel.offset is: '..channel.offset) end");
luaExecStr("if math.abs(channel.alarm1 - 60) > 0.5 then error('channel.alarm1 is: '..channel.alarm1) end");
luaExecStr("if math.abs(channel.alarm2 - 50) > 0.5 then error('channel.alarm2 is: '..channel.alarm2) end");
}
TEST(Lua, testPanicProtection)
{
bool passed = false;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 904 B

View file

@ -78,8 +78,8 @@ TEST(getSwitch, OldTypeStickyCSW)
{
MODEL_RESET();
MIXER_RESET();
g_model.logicalSw[0] = { SWSRC_SA0, 0, 0, LS_FUNC_AND };
g_model.logicalSw[1] = { SWSRC_SW1, SWSRC_SW2, 0, LS_FUNC_OR };
g_model.logicalSw[0] = { LS_FUNC_AND, SWSRC_SA0, 0, 0, };
g_model.logicalSw[1] = { LS_FUNC_OR, SWSRC_SW1, SWSRC_SW2, 0 };
evalLogicalSwitches();
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
@ -111,8 +111,8 @@ TEST(getSwitch, nullSW)
EXPECT_EQ(getSwitch(0), true);
}
#if defined(PCBTARANIS) && defined(FRSKY)
TEST(getSwitch, VfasWithDelay)
#if 0
TEST(getSwitch, DISABLED_VfasWithDelay)
{
MODEL_RESET();
MIXER_RESET();
@ -155,7 +155,7 @@ TEST(getSwitch, VfasWithDelay)
//now turn on telemetry
EXPECT_EQ(TELEMETRY_STREAMING(), false);
frskyData.rssi[0].value = 50;
TELEMETRY_RSSI() = 50;
EXPECT_EQ(TELEMETRY_STREAMING(), true);
//vfas is 15.0V so L1 should still be FALSE
@ -203,7 +203,7 @@ TEST(getSwitch, VfasWithDelay)
//now stop telemetry, L1 should become FALSE immediatelly
frskyData.rssi[0].value = 0;
TELEMETRY_RSSI() = 0;
EXPECT_EQ(TELEMETRY_STREAMING(), false);
evalLogicalSwitches();
@ -216,7 +216,7 @@ TEST(getSwitch, VfasWithDelay)
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
}
TEST(getSwitch, RssiWithDuration)
TEST(getSwitch, DISABLED_RssiWithDuration)
{
MODEL_RESET();
MIXER_RESET();
@ -242,7 +242,7 @@ TEST(getSwitch, RssiWithDuration)
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
//now set RSSI to 5, L1 should still be FALSE
frskyData.rssi[0].value = 5;
TELEMETRY_RSSI() = 5;
evalLogicalSwitches();
EXPECT_EQ(TELEMETRY_STREAMING(), true);
@ -255,7 +255,7 @@ TEST(getSwitch, RssiWithDuration)
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
//now set RSSI to 100, L1 should become TRUE for 0.5s
frskyData.rssi[0].value = 100;
TELEMETRY_RSSI() = 100;
evalLogicalSwitches();
EXPECT_EQ(TELEMETRY_STREAMING(), true);
@ -284,7 +284,7 @@ TEST(getSwitch, RssiWithDuration)
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
//repeat telemetry streaming OFF and ON to test for duration processing
frskyData.rssi[0].value = 0;
TELEMETRY_RSSI() = 0;
evalLogicalSwitches();
EXPECT_EQ(TELEMETRY_STREAMING(), false);
@ -293,7 +293,7 @@ TEST(getSwitch, RssiWithDuration)
EXPECT_EQ(getSwitch(SWSRC_SW1), false);
//now set RSSI to 100, L1 should become TRUE for 0.5s
frskyData.rssi[0].value = 100;
TELEMETRY_RSSI() = 100;
evalLogicalSwitches();
EXPECT_EQ(TELEMETRY_STREAMING(), true);
@ -349,7 +349,7 @@ TEST(getSwitch, inputWithTrim)
modelDefault(0);
MIXER_RESET();
g_model.logicalSw[0] = { MIXSRC_FIRST_INPUT, 0, 0, LS_FUNC_VPOS };
g_model.logicalSw[0] = { LS_FUNC_VPOS, MIXSRC_FIRST_INPUT, 0, 0 };
doMixerCalculations();
evalLogicalSwitches();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 980 B

View file

@ -74,12 +74,7 @@ const pm_char STR_OPEN9X[] PROGMEM =
ISTR(FUNCSOUNDS)
ISTR(VTELEMCHNS)
#if defined(FRSKY) || defined(CPUARM)
#if defined(CPUARM)
ISTR(VTELEMUNIT_IMP)
ISTR(VTELEMUNIT_METR)
#else
ISTR(VTELEMUNIT)
#endif
ISTR(VALARM)
ISTR(VALARMFN)
ISTR(VTELPROTO)
@ -350,6 +345,7 @@ const pm_char STR_EXTERNALRF[] PROGMEM = TR_EXTERNALRF;
const pm_char STR_COUNTRYCODE[] PROGMEM = TR_COUNTRYCODE;
const pm_char STR_FAILSAFE[] PROGMEM = TR_FAILSAFE;
const pm_char STR_FAILSAFESET[] PROGMEM = TR_FAILSAFESET;
const pm_char STR_MENUSENSOR[] PROGMEM = TR_MENUSENSOR;
#endif
const pm_char STR_INVERT_THR[] PROGMEM = TR_INVERT_THR;
@ -513,6 +509,10 @@ const pm_char STR_BLCOLOR[] PROGMEM = TR_BLCOLOR;
const pm_char STR_LOWALARM[] PROGMEM = TR_LOWALARM;
const pm_char STR_CRITICALALARM[] PROGMEM = TR_CRITICALALARM;
const pm_char STR_TELEMETRY_TYPE[] PROGMEM = TR_TELEMETRY_TYPE;
const pm_char STR_TELEMETRY_SENSORS[] PROGMEM = TR_TELEMETRY_SENSORS;
const pm_char STR_TELEMETRY_NEWSENSOR[] PROGMEM = TR_TELEMETRY_NEWSENSOR;
const pm_char STR_ID[] PROGMEM = TR_ID;
const pm_char STR_PRECISION[] PROGMEM = TR_PRECISION;
#endif
#if defined(PCBTARANIS)
@ -531,7 +531,7 @@ const pm_char STR_BLCOLOR[] PROGMEM = TR_BLCOLOR;
const pm_char STR_PTS[] PROGMEM = TR_PTS;
const pm_char STR_SMOOTH[] PROGMEM = TR_SMOOTH;
const pm_char STR_COPY_STICKS_TO_OFS[] PROGMEM = TR_COPY_STICKS_TO_OFS;
const pm_char STR_COPY_TRIMS_TO_OFS[] PROGMEM = TR_COPY_TRIMS_TO_OFS;
const pm_char STR_COPY_TRIMS_TO_OFS[] PROGMEM = TR_COPY_TRIMS_TO_OFS;
const pm_char STR_TOP_BAR[] PROGMEM = TR_TOP_BAR;
const pm_char STR_ALTITUDE[] PROGMEM = TR_ALTITUDE;
const pm_char STR_SCALE[] PROGMEM = TR_SCALE;

View file

@ -124,9 +124,8 @@ extern const pm_char STR_OPEN9X[];
#define OFS_VTELEMCHNS (OFS_FUNCSOUNDS + sizeof(TR_FUNCSOUNDS))
#if defined(FRSKY) || defined(CPUARM)
#if defined(CPUARM)
#define OFS_VTELEMUNIT_IMP (OFS_VTELEMCHNS + sizeof(TR_VTELEMCHNS))
#define OFS_VTELEMUNIT_METR (OFS_VTELEMUNIT_IMP + sizeof(TR_VTELEMUNIT_IMP))
#define OFS_VALARM (OFS_VTELEMUNIT_METR + sizeof(TR_VTELEMUNIT_METR))
#define OFS_VTELEMUNIT (OFS_VTELEMCHNS + sizeof(TR_VTELEMCHNS))
#define OFS_VALARM (OFS_VTELEMUNIT + sizeof(TR_VTELEMUNIT))
#else
#define OFS_VTELEMUNIT (OFS_VTELEMCHNS + sizeof(TR_VTELEMCHNS))
#define OFS_VALARM (OFS_VTELEMUNIT + sizeof(TR_VTELEMUNIT))
@ -228,7 +227,7 @@ extern const pm_char STR_OPEN9X[];
#if defined(FRSKY) || defined(CPUARM)
#if defined(CPUARM)
#define STR_VTELEMUNIT (STR_OPEN9X + (g_eeGeneral.imperial ? OFS_VTELEMUNIT_IMP : OFS_VTELEMUNIT_METR))
#define STR_VTELEMUNIT (STR_OPEN9X + OFS_VTELEMUNIT)
#define STR_VOLTSRC (STR_OPEN9X + OFS_VOLTSRC)
#else
#define STR_VTELEMUNIT (STR_OPEN9X + OFS_VTELEMUNIT)
@ -506,6 +505,7 @@ extern const pm_char STR_INTERNALRF[];
extern const pm_char STR_EXTERNALRF[];
extern const pm_char STR_FAILSAFE[];
extern const pm_char STR_FAILSAFESET[];
extern const pm_char STR_MENUSENSOR[];
extern const pm_char STR_COUNTRYCODE[];
#endif
@ -710,6 +710,10 @@ extern const pm_char STR_BLCOLOR[];
extern const pm_char STR_LOWALARM[];
extern const pm_char STR_CRITICALALARM[];
extern const pm_char STR_TELEMETRY_TYPE[];
extern const pm_char STR_TELEMETRY_SENSORS[];
extern const pm_char STR_TELEMETRY_NEWSENSOR[];
extern const pm_char STR_ID[];
extern const pm_char STR_PRECISION[];
#endif
#if defined(PCBTARANIS)
@ -728,7 +732,7 @@ extern const pm_char STR_BLCOLOR[];
extern const pm_char STR_PTS[];
extern const pm_char STR_SMOOTH[];
extern const pm_char STR_COPY_STICKS_TO_OFS[];
extern const pm_char STR_COPY_TRIMS_TO_OFS[];
extern const pm_char STR_COPY_TRIMS_TO_OFS[];
extern const pm_char STR_TOP_BAR[];
extern const pm_char STR_ALTITUDE[];
extern const pm_char STR_SCALE[];

View file

@ -789,6 +789,7 @@
#define TR_EXTERNALRF "Externí RF modul"
#define TR_FAILSAFE "Mód Failsafe"
#define TR_FAILSAFESET "NASTAVENÍ FAILSAFE"
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE "Kód regionu"
#define TR_VOICELANG "Jazyk hlasu"
#define TR_UNITSSYSTEM "Jednotky"
@ -821,6 +822,8 @@
#define TR_MODELIDUSED TR("ID již použito","ID modelu je již použito")
#define TR_MODULE INDENT "Modul"
#define TR_TELEMETRY_TYPE TR("Typ", "Typ telemetrie")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE INDENT "Rozsah kanálů"
#define TR_LOWALARM INDENT "Nízký Alarm"
#define TR_CRITICALALARM INDENT "Kritický Alarm"
@ -950,3 +953,5 @@
#define TR_VIEW_NOTES "Zobrazit poznámky"
#define TR_MODS_FORBIDDEN "Změny nejsou povoleny!"
#define TR_UNLOCKED "Odemčeno"
#define TR_ID "ID"
#define TR_PRECISION "Precision"

View file

@ -793,6 +793,7 @@
#define TR_EXTERNALRF TR("---Externes HF-Modul---","----Externes HF-Modul----------") //9XR-Pro
#define TR_FAILSAFE "Failsafe-Modus"
#define TR_FAILSAFESET "Failsafe Einst."
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE "Landescode"
#define TR_VOICELANG "Sprach-Ansage"
#define TR_UNITSSYSTEM "Einheiten"
@ -825,6 +826,8 @@
#define TR_MODELIDUSED TR("ID schon benutzt","Modell-ID schon benutzt")
#define TR_MODULE INDENT "Modul-Typ"
#define TR_TELEMETRY_TYPE TR("Typ", "Telemetrytyp")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE TR(INDENT "Kanäle", INDENT "Ausgangs Kanäle") //wg 9XR-Pro
#define TR_LOWALARM INDENT "Vor-Alarm bei"
#define TR_CRITICALALARM INDENT "Kritisch-Alarm"
@ -954,4 +957,6 @@
#define TR_VIEW_NOTES "Zeige Notizen"
#define TR_MODS_FORBIDDEN "Veränderungen verboten!"
#define TR_UNLOCKED "Entsperrt"
#define TR_ID "ID"
#define TR_PRECISION "Precision"

View file

@ -357,10 +357,8 @@
#if defined(CPUARM)
#define LEN_VUNITSSYSTEM TR("\006", "\010")
#define TR_VUNITSSYSTEM TR("Metric""Imper.", "Metric\0 ""Imperial")
#define LEN_VTELEMUNIT_METR "\003"
#define TR_VTELEMUNIT_METR "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_METR LENGTH_UNIT_METR "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT_IMP "\003"
#define TR_VTELEMUNIT_IMP "v\0 ""A\0 ""m/s""-\0 " SPEED_UNIT_IMP LENGTH_UNIT_IMP "@\0 ""%\0 ""mA\0""mAh""W\0 "
#define LEN_VTELEMUNIT "\003"
#define TR_VTELEMUNIT "-\0 ""v\0 ""A\0 ""mA\0""kts""m/s""kmh""mph""m\0 ""ft\0""@C\0""@F\0""%\0 ""mAh""W\0 ""dBm""rpm""g\0 ""@\0"
#else
#if defined(IMPERIAL_UNITS)
#define LENGTH_UNIT LENGTH_UNIT_IMP
@ -476,7 +474,14 @@
#define TR_CYC_VSRCRAW "[C1]""[C2]""[C3]"
#endif
#define TR_VSRCRAW "---\0""Rud\0""Ele\0""Thr\0""Ail\0" TR_POTS_VSRCRAW TR_ROTARY_ENCODERS "MAX\0" TR_CYC_VSRCRAW "TrmR" "TrmE" "TrmT" "TrmA" TR_SW_VSRCRAW
#if defined(CPUARM)
#define TR_RESERVE_VSRCRAW "[--]"
#define TR_EXTRA_VSRCRAW "Batt""Time" TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW TR_RESERVE_VSRCRAW "Tmr1""Tmr2""Tmr3"
#else
#define TR_EXTRA_VSRCRAW
#endif
#define TR_VSRCRAW "---\0""Rud\0""Ele\0""Thr\0""Ail\0" TR_POTS_VSRCRAW TR_ROTARY_ENCODERS "MAX\0" TR_CYC_VSRCRAW "TrmR" "TrmE" "TrmT" "TrmA" TR_SW_VSRCRAW TR_EXTRA_VSRCRAW
#define LEN_VTMRMODES "\003"
#define TR_VTMRMODES "OFF""ON\0""THs""TH%""THt"
@ -801,6 +806,7 @@
#define TR_EXTERNALRF "External RF"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafe mode")
#define TR_FAILSAFESET "FAILSAFE SETTINGS"
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE "Country Code"
#define TR_VOICELANG "Voice Language"
#define TR_UNITSSYSTEM "Units"
@ -833,6 +839,8 @@
#define TR_MODELIDUSED TR("ID already used","Model ID already used")
#define TR_MODULE INDENT "Module"
#define TR_TELEMETRY_TYPE TR("Type", "Telemetry Type")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE TR(INDENT "Ch. Range", INDENT "Channel Range")
#define TR_LOWALARM INDENT "Low Alarm"
#define TR_CRITICALALARM INDENT "Critical Alarm"
@ -962,3 +970,27 @@
#define TR_VIEW_NOTES "View Notes"
#define TR_MODS_FORBIDDEN "Modifications forbidden!"
#define TR_UNLOCKED "Unlocked"
#define TR_ID "ID"
#define TR_PRECISION "Precision"
#define ZSTR_RSSI "RSSI"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
#define ZSTR_BATT "Batt"
#define ZSTR_ALT "Alt"
#define ZSTR_TEMP "Temp"
#define ZSTR_RPM "RPM"
#define ZSTR_FUEL "Fuel"
#define ZSTR_VSPD "VSpd"
#define ZSTR_ACCX "AccX"
#define ZSTR_ACCY "AccY"
#define ZSTR_ACCZ "AccZ"
#define ZSTR_CURR "Curr"
#define ZSTR_VFAS "VFAS"
#define ZSTR_ASPD "ASpd"
#define ZSTR_GSPD "GSpd"
#define ZSTR_HDG "Hdg"
#define ZSTR_CELLS "Cels"
#define ZSTR_GPSALT "GAlt"
#define ZSTR_GPSDATETIME "Date"
#define ZSTR_GPS "GPS"

View file

@ -786,6 +786,7 @@
#define TR_EXTERNALRF "Externa RF"
#define TR_FAILSAFE INDENT"Modo sgdad."
#define TR_FAILSAFESET "AJUSTES SGDAD."
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE "Codigo Pais"
#define TR_VOICELANG "Idioma voces"
#define TR_UNITSSYSTEM "Unidades"
@ -818,6 +819,8 @@
#define TR_MODELIDUSED TR("ID en uso", "ID modelo en uso")
#define TR_MODULE INDENT "Modulo"
#define TR_TELEMETRY_TYPE TR("Type", "Telemetry Type")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE INDENT "Gama de canales"
#define TR_LOWALARM INDENT "Alarma baja"
#define TR_CRITICALALARM INDENT "Alarma Critica"
@ -947,3 +950,5 @@
#define TR_VIEW_NOTES "View Notes"
#define TR_MODS_FORBIDDEN "Modifications forbidden!"
#define TR_UNLOCKED "Unlocked"
#define TR_ID "ID"
#define TR_PRECISION "Precision"

View file

@ -786,6 +786,7 @@
#define TR_EXTERNALRF "External RF"
#define TR_FAILSAFE INDENT "Failsafe mode"
#define TR_FAILSAFESET "FAILSAFE SETTINGS"
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE "Country Code"
#define TR_VOICELANG "Voice Language"
#define TR_UNITSSYSTEM "Units"
@ -818,6 +819,8 @@
#define TR_MODELIDUSED TR("ID already used","Model ID already used")
#define TR_MODULE INDENT "Module"
#define TR_TELEMETRY_TYPE TR("Type", "Telemetry Type")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE INDENT "Channel Range"
#define TR_LOWALARM INDENT "Low Alarm"
#define TR_CRITICALALARM INDENT "Critical Alarm"
@ -947,3 +950,5 @@
#define TR_VIEW_NOTES "View Notes"
#define TR_MODS_FORBIDDEN "Muutokset kielletty!"
#define TR_UNLOCKED "Avattu"
#define TR_ID "ID"
#define TR_PRECISION "Precision"

View file

@ -786,6 +786,7 @@
#define TR_EXTERNALRF "HF externe"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Type failsafe")
#define TR_FAILSAFESET "REGLAGES FAILSAFE"
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE TR("Zone géo.","Zone géographique")
#define TR_VOICELANG TR("Langue voix", "Langue annonces vocales")
#define TR_UNITSSYSTEM "Unités"
@ -818,6 +819,8 @@
#define TR_MODELIDUSED TR("ID déjà affecté", "No de modèle déjà utilisé")
#define TR_MODULE INDENT "Type de module"
#define TR_TELEMETRY_TYPE "Type télémesure"
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Ajout d'un nouveau capteur..."
#define TR_CHANNELRANGE TR(INDENT "Canaux", INDENT "Plage de canaux")
#define TR_LOWALARM INDENT "Alarme basse"
#define TR_CRITICALALARM INDENT "Alarme critique"
@ -947,3 +950,5 @@
#define TR_VIEW_NOTES "Voir Notes"
#define TR_MODS_FORBIDDEN "Modifications désactivées!"
#define TR_UNLOCKED "Déverrouillé"
#define TR_ID "ID"
#define TR_PRECISION "Precision"

View file

@ -786,6 +786,7 @@
#define TR_EXTERNALRF "Modulo esterno"
#define TR_FAILSAFE "Modo failsafe"
#define TR_FAILSAFESET TR("FAILSAFE","IMPOSTAZIONI FAILSAFE")
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE TR("Codice Paese","Standard 2.4Ghz")
#define TR_VOICELANG "Lingua Voce"
#define TR_UNITSSYSTEM "Unità"
@ -818,6 +819,8 @@
#define TR_MODELIDUSED TR("ID già usato","ID Modello già usato")
#define TR_MODULE INDENT "Modulo"
#define TR_TELEMETRY_TYPE "Tipo Telemetria"
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE INDENT "Numero Canali"
#define TR_LOWALARM INDENT "Allarme Basso"
#define TR_CRITICALALARM INDENT "Allarme Critico"
@ -947,3 +950,5 @@
#define TR_VIEW_NOTES "Vedi Note"
#define TR_MODS_FORBIDDEN "Modifica proibita!"
#define TR_UNLOCKED "Sbloccato"
#define TR_ID "ID"
#define TR_PRECISION "Precision"

View file

@ -786,6 +786,7 @@
#define TR_EXTERNALRF "Zewn.Moduł RF"
#define TR_FAILSAFE TR(INDENT"Failsafe",INDENT"Tryb Failsafe")
#define TR_FAILSAFESET "USTAWIENIE FAILSAFE"
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE "Kod regionu"
#define TR_VOICELANG "Język głosu"
#define TR_UNITSSYSTEM "Jednostki"
@ -818,6 +819,8 @@
#define TR_MODELIDUSED TR("ID zajęte","ID modelu zajęte")
#define TR_MODULE INDENT "Moduł"
#define TR_TELEMETRY_TYPE "Typ Telemetri"
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE TR(INDENT "ZakrKn",INDENT "Zakres kanału")
#define TR_LOWALARM INDENT "Alarm niski"
#define TR_CRITICALALARM INDENT "Alarm krytyczny"
@ -947,3 +950,5 @@
#define TR_VIEW_NOTES "Pokaż Notki"
#define TR_MODS_FORBIDDEN "Modyfikacje zabronione!"
#define TR_UNLOCKED "Odblokowane"
#define TR_ID "ID"
#define TR_PRECISION "Precision"

View file

@ -786,6 +786,7 @@
#define TR_EXTERNALRF "External RF"
#define TR_FAILSAFE "Failsafe mode"
#define TR_FAILSAFESET "FAILSAFE SETTINGS"
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE "Country Code"
#define TR_VOICELANG "Voice Language"
#define TR_UNITSSYSTEM "Units"
@ -818,6 +819,8 @@
#define TR_MODELIDUSED TR("ID already used","Model ID already used")
#define TR_MODULE INDENT "Module"
#define TR_TELEMETRY_TYPE TR("Type", "Telemetry Type")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE INDENT "Channel Range"
#define TR_LOWALARM INDENT "Low Alarm"
#define TR_CRITICALALARM INDENT "Critical Alarm"
@ -947,3 +950,5 @@
#define TR_VIEW_NOTES "View Notes"
#define TR_MODS_FORBIDDEN "Modifications forbidden!"
#define TR_UNLOCKED "Unlocked"
#define TR_ID "ID"
#define TR_PRECISION "Precision"

View file

@ -786,6 +786,7 @@
#define TR_EXTERNALRF "Extern Radiomodul"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafeläge")
#define TR_FAILSAFESET "FailsafeInställning"
#define TR_MENUSENSOR "SENSOR"
#define TR_COUNTRYCODE "Landskod"
#define TR_VOICELANG "Röstspråk"
#define TR_UNITSSYSTEM "Enheter"
@ -818,6 +819,8 @@
#define TR_MODELIDUSED TR("ID finns redan","ModellID används redan")
#define TR_MODULE INDENT "Modul"
#define TR_TELEMETRY_TYPE "Telemetrityp"
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_TELEMETRY_NEWSENSOR INDENT "Add a new sensor..."
#define TR_CHANNELRANGE INDENT "Kanalområde"
#define TR_LOWALARM INDENT "Låg-alarm"
#define TR_CRITICALALARM INDENT "Kritiskt alarm"
@ -947,3 +950,5 @@
#define TR_VIEW_NOTES "Visa Noteringars"
#define TR_MODS_FORBIDDEN "Modifikationer förbjudna!"
#define TR_UNLOCKED "Olåst"
#define TR_ID "ID"
#define TR_PRECISION "Precision"

View file

@ -57,33 +57,6 @@ enum CzechPrompts {
CZ_PROMPT_RPMS = CZ_PROMPT_UNITS_BASE+(UNIT_RPMS*4),
CZ_PROMPT_G = CZ_PROMPT_UNITS_BASE+(UNIT_G*4),
CZ_PROMPT_LABELS_BASE = 194,
CZ_PROMPT_TIMER1 = CZ_PROMPT_LABELS_BASE+TELEM_TIMER1,
CZ_PROMPT_TIMER2 = CZ_PROMPT_LABELS_BASE+TELEM_TIMER2,
CZ_PROMPT_RSSI_TX = CZ_PROMPT_LABELS_BASE+TELEM_RSSI_TX,
CZ_PROMPT_RSSI_RX = CZ_PROMPT_LABELS_BASE+TELEM_RSSI_RX,
CZ_PROMPT_A1 = CZ_PROMPT_LABELS_BASE+TELEM_A1,
CZ_PROMPT_A2 = CZ_PROMPT_LABELS_BASE+TELEM_A2,
CZ_PROMPT_ALTITUDE = CZ_PROMPT_LABELS_BASE+TELEM_ALT,
CZ_PROMPT_RPM = CZ_PROMPT_LABELS_BASE+TELEM_RPM,
CZ_PROMPT_ESSENCE = CZ_PROMPT_LABELS_BASE+TELEM_FUEL,
CZ_PROMPT_T1 = CZ_PROMPT_LABELS_BASE+TELEM_T1,
CZ_PROMPT_T2 = CZ_PROMPT_LABELS_BASE+TELEM_T2,
CZ_PROMPT_VITESSE = CZ_PROMPT_LABELS_BASE+TELEM_SPEED,
CZ_PROMPT_DISTANCE = CZ_PROMPT_LABELS_BASE+TELEM_DIST,
CZ_PROMPT_GPSALTITUDE = CZ_PROMPT_LABELS_BASE+TELEM_GPSALT,
CZ_PROMPT_ELEMENTS_LIPO = CZ_PROMPT_LABELS_BASE+TELEM_CELL,
CZ_PROMPT_TOTAL_LIPO = CZ_PROMPT_LABELS_BASE+TELEM_CELLS_SUM,
CZ_PROMPT_VFAS = CZ_PROMPT_LABELS_BASE+TELEM_VFAS,
CZ_PROMPT_COURANT = CZ_PROMPT_LABELS_BASE+TELEM_CURRENT,
CZ_PROMPT_CONSOMMATION = CZ_PROMPT_LABELS_BASE+TELEM_CONSUMPTION,
CZ_PROMPT_PUISSANCE = CZ_PROMPT_LABELS_BASE+TELEM_POWER,
CZ_PROMPT_ACCELx = CZ_PROMPT_LABELS_BASE+TELEM_ACCx,
CZ_PROMPT_ACCELy = CZ_PROMPT_LABELS_BASE+TELEM_ACCy,
CZ_PROMPT_ACCELz = CZ_PROMPT_LABELS_BASE+TELEM_ACCz,
CZ_PROMPT_HDG = CZ_PROMPT_LABELS_BASE+TELEM_HDG,
CZ_PROMPT_VARIO = CZ_PROMPT_LABELS_BASE+TELEM_VSPEED,
};
#if defined(VOICE)
@ -116,6 +89,7 @@ I18N_PLAY_FUNCTION(cz, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
#if !defined(CPUARM)
if (unit) {
unit--;
convertUnit(number, unit);
@ -127,18 +101,19 @@ I18N_PLAY_FUNCTION(cz, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
unit = UNIT_KTS;
}
}
#if defined(CPUARM)
if ((att & PREC1) && (unit == UNIT_FEET || (unit == UNIT_DIST && number >= 100))) {
number = div10_and_round(number);
att -= PREC1;
}
#endif
unit++;
}
#endif
int8_t mode = MODE(att);
if (mode > 0) {
#if defined(CPUARM)
if (mode == 2) {
number /= 10;
}
#else
// we assume that we are PREC1
#endif
div_t qr = div(number, 10);
if (qr.rem) {
PLAY_NUMBER(qr.quot, 0, ZENSKY);

View file

@ -58,33 +58,6 @@ enum GermanPrompts {
DE_PROMPT_RPMS = DE_PROMPT_UNITS_BASE+UNIT_RPMS,
DE_PROMPT_G= DE_PROMPT_UNITS_BASE+UNIT_G,
DE_PROMPT_LABELS_BASE = 128,
DE_PROMPT_TIMER1 = DE_PROMPT_LABELS_BASE+TELEM_TIMER1,
DE_PROMPT_TIMER2 = DE_PROMPT_LABELS_BASE+TELEM_TIMER2,
DE_PROMPT_RSSI_TX = DE_PROMPT_LABELS_BASE+TELEM_RSSI_TX,
DE_PROMPT_RSSI_RX = DE_PROMPT_LABELS_BASE+TELEM_RSSI_RX,
DE_PROMPT_A1 = DE_PROMPT_LABELS_BASE+TELEM_A1,
DE_PROMPT_A2 = DE_PROMPT_LABELS_BASE+TELEM_A2,
DE_PROMPT_ALTITUDE = DE_PROMPT_LABELS_BASE+TELEM_ALT,
DE_PROMPT_RPM = DE_PROMPT_LABELS_BASE+TELEM_RPM,
DE_PROMPT_ESSENCE = DE_PROMPT_LABELS_BASE+TELEM_FUEL,
DE_PROMPT_T1 = DE_PROMPT_LABELS_BASE+TELEM_T1,
DE_PROMPT_T2 = DE_PROMPT_LABELS_BASE+TELEM_T2,
DE_PROMPT_VITESSE = DE_PROMPT_LABELS_BASE+TELEM_SPEED,
DE_PROMPT_DISTANCE = DE_PROMPT_LABELS_BASE+TELEM_DIST,
DE_PROMPT_GPSALTITUDE = DE_PROMPT_LABELS_BASE+TELEM_GPSALT,
DE_PROMPT_ELEMENTS_LIPO = DE_PROMPT_LABELS_BASE+TELEM_CELL,
DE_PROMPT_TOTAL_LIPO = DE_PROMPT_LABELS_BASE+TELEM_CELLS_SUM,
DE_PROMPT_VFAS = DE_PROMPT_LABELS_BASE+TELEM_VFAS,
DE_PROMPT_COURANT = DE_PROMPT_LABELS_BASE+TELEM_CURRENT,
DE_PROMPT_CONSOMMATION = DE_PROMPT_LABELS_BASE+TELEM_CONSUMPTION,
DE_PROMPT_PUISSANCE = DE_PROMPT_LABELS_BASE+TELEM_POWER,
DE_PROMPT_ACCELx = DE_PROMPT_LABELS_BASE+TELEM_ACCx,
DE_PROMPT_ACCELy = DE_PROMPT_LABELS_BASE+TELEM_ACCy,
DE_PROMPT_ACCELz = DE_PROMPT_LABELS_BASE+TELEM_ACCz,
DE_PROMPT_HDG = DE_PROMPT_LABELS_BASE+TELEM_HDG,
DE_PROMPT_VARIO = DE_PROMPT_LABELS_BASE+TELEM_VSPEED,
};
#if defined(VOICE)
@ -106,6 +79,7 @@ I18N_PLAY_FUNCTION(de, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
#if !defined(CPUARM)
if (unit) {
unit--;
convertUnit(number, unit);
@ -117,18 +91,20 @@ I18N_PLAY_FUNCTION(de, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
unit = UNIT_KTS;
}
}
#if defined(CPUARM)
if ((att & PREC1) && (unit == UNIT_FEET || (unit == UNIT_DIST && number >= 100))) {
number = div10_and_round(number);
att -= PREC1;
}
#endif
unit++;
}
#endif
int8_t mode = MODE(att);
if (mode > 0) {
div_t qr = div(number, (mode == 1 ? 10 : 100));
#if defined(CPUARM)
if (mode == 2) {
number /= 10;
}
#else
// we assume that we are PREC1
#endif
div_t qr = div(number, 10);
if (qr.rem > 0) {
PLAY_NUMBER(qr.quot, 0, 0);
PUSH_NUMBER_PROMPT(DE_PROMPT_COMMA);

View file

@ -93,6 +93,7 @@ I18N_PLAY_FUNCTION(en, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
#if !defined(CPUARM)
if (unit) {
unit--;
convertUnit(number, unit);
@ -104,18 +105,19 @@ I18N_PLAY_FUNCTION(en, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
unit = UNIT_KTS;
}
}
#if defined(CPUARM)
if ((att & PREC1) && (unit == UNIT_FEET || (unit == UNIT_DIST && number >= 100))) {
number = div10_and_round(number);
att -= PREC1;
}
#endif
unit++;
}
#endif
int8_t mode = MODE(att);
if (mode > 0) {
#if defined(CPUARM)
if (mode == 2) {
number /= 10;
}
#else
// we assume that we are PREC1
#endif
div_t qr = div(number, 10);
if (qr.rem) {
PLAY_NUMBER(qr.quot, 0, 0);

View file

@ -82,33 +82,6 @@ enum SpanishPrompts {
ES_PROMPT_RPMS = ES_PROMPT_UNITS_BASE+UNIT_RPMS,
ES_PROMPT_G= ES_PROMPT_UNITS_BASE+UNIT_G,
ES_PROMPT_LABELS_BASE = 139,
ES_PROMPT_TIMER1 = ES_PROMPT_LABELS_BASE+TELEM_TIMER1,
ES_PROMPT_TIMER2 = ES_PROMPT_LABELS_BASE+TELEM_TIMER2,
ES_PROMPT_RSSI_TX = ES_PROMPT_LABELS_BASE+TELEM_RSSI_TX,
ES_PROMPT_RSSI_RX = ES_PROMPT_LABELS_BASE+TELEM_RSSI_RX,
ES_PROMPT_A1 = ES_PROMPT_LABELS_BASE+TELEM_A1,
ES_PROMPT_A2 = ES_PROMPT_LABELS_BASE+TELEM_A2,
ES_PROMPT_ALTITUDE = ES_PROMPT_LABELS_BASE+TELEM_ALT,
ES_PROMPT_RPM = ES_PROMPT_LABELS_BASE+TELEM_RPM,
ES_PROMPT_ESSENCE = ES_PROMPT_LABELS_BASE+TELEM_FUEL,
ES_PROMPT_T1 = ES_PROMPT_LABELS_BASE+TELEM_T1,
ES_PROMPT_T2 = ES_PROMPT_LABELS_BASE+TELEM_T2,
ES_PROMPT_VITESSE = ES_PROMPT_LABELS_BASE+TELEM_SPEED,
ES_PROMPT_DISTANCE = ES_PROMPT_LABELS_BASE+TELEM_DIST,
ES_PROMPT_GPSALTITUDE = ES_PROMPT_LABELS_BASE+TELEM_GPSALT,
ES_PROMPT_ELEMENTS_LIPO = ES_PROMPT_LABELS_BASE+TELEM_CELL,
ES_PROMPT_TOTAL_LIPO = ES_PROMPT_LABELS_BASE+TELEM_CELLS_SUM,
ES_PROMPT_VFAS = ES_PROMPT_LABELS_BASE+TELEM_VFAS,
ES_PROMPT_COURANT = ES_PROMPT_LABELS_BASE+TELEM_CURRENT,
ES_PROMPT_CONSOMMATION = ES_PROMPT_LABELS_BASE+TELEM_CONSUMPTION,
ES_PROMPT_PUISSANCE = ES_PROMPT_LABELS_BASE+TELEM_POWER,
ES_PROMPT_ACCELx = ES_PROMPT_LABELS_BASE+TELEM_ACCx,
ES_PROMPT_ACCELy = ES_PROMPT_LABELS_BASE+TELEM_ACCy,
ES_PROMPT_ACCELz = ES_PROMPT_LABELS_BASE+TELEM_ACCz,
ES_PROMPT_HDG = ES_PROMPT_LABELS_BASE+TELEM_HDG,
ES_PROMPT_VARIO = ES_PROMPT_LABELS_BASE+TELEM_VSPEED,
};
#if defined(VOICE)
@ -130,6 +103,7 @@ I18N_PLAY_FUNCTION(es, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
#if !defined(CPUARM)
if (unit) {
unit--;
convertUnit(number, unit);
@ -141,18 +115,20 @@ I18N_PLAY_FUNCTION(es, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
unit = UNIT_KTS;
}
}
#if defined(CPUARM)
if ((att & PREC1) && (unit == UNIT_FEET || (unit == UNIT_DIST && number >= 100))) {
number = div10_and_round(number);
att -= PREC1;
}
#endif
unit++;
}
#endif
int8_t mode = MODE(att);
if (mode > 0) {
div_t qr = div(number, (mode == 1 ? 10 : 100));
#if defined(CPUARM)
if (mode == 2) {
number /= 10;
}
#else
// we assume that we are PREC1
#endif
div_t qr = div(number, 10);
if (qr.rem > 0) {
PLAY_NUMBER(qr.quot, 0, 0);
PUSH_NUMBER_PROMPT(ES_PROMPT_VIRGOLA);

View file

@ -63,33 +63,6 @@ enum FrenchPrompts {
FR_PROMPT_MINUTE = FR_PROMPT_UNITS_BASE+UNIT_MINUTES,
FR_PROMPT_SECONDE = FR_PROMPT_UNITS_BASE+UNIT_SECONDS,
FR_PROMPT_LABELS_BASE = 145,
FR_PROMPT_TIMER1 = FR_PROMPT_LABELS_BASE+TELEM_TIMER1,
FR_PROMPT_TIMER2 = FR_PROMPT_LABELS_BASE+TELEM_TIMER2,
FR_PROMPT_RSSI_TX = FR_PROMPT_LABELS_BASE+TELEM_RSSI_TX,
FR_PROMPT_RSSI_RX = FR_PROMPT_LABELS_BASE+TELEM_RSSI_RX,
FR_PROMPT_A1 = FR_PROMPT_LABELS_BASE+TELEM_A1,
FR_PROMPT_A2 = FR_PROMPT_LABELS_BASE+TELEM_A2,
FR_PROMPT_ALTITUDE = FR_PROMPT_LABELS_BASE+TELEM_ALT,
FR_PROMPT_RPM = FR_PROMPT_LABELS_BASE+TELEM_RPM,
FR_PROMPT_ESSENCE = FR_PROMPT_LABELS_BASE+TELEM_FUEL,
FR_PROMPT_T1 = FR_PROMPT_LABELS_BASE+TELEM_T1,
FR_PROMPT_T2 = FR_PROMPT_LABELS_BASE+TELEM_T2,
FR_PROMPT_VITESSE = FR_PROMPT_LABELS_BASE+TELEM_SPEED,
FR_PROMPT_DISTANCE = FR_PROMPT_LABELS_BASE+TELEM_DIST,
FR_PROMPT_GPSALTITUDE = FR_PROMPT_LABELS_BASE+TELEM_GPSALT,
FR_PROMPT_ELEMENTS_LIPO = FR_PROMPT_LABELS_BASE+TELEM_CELL,
FR_PROMPT_TOTAL_LIPO = FR_PROMPT_LABELS_BASE+TELEM_CELLS_SUM,
FR_PROMPT_VFAS = FR_PROMPT_LABELS_BASE+TELEM_VFAS,
FR_PROMPT_COURANT = FR_PROMPT_LABELS_BASE+TELEM_CURRENT,
FR_PROMPT_CONSOMMATION = FR_PROMPT_LABELS_BASE+TELEM_CONSUMPTION,
FR_PROMPT_PUISSANCE = FR_PROMPT_LABELS_BASE+TELEM_POWER,
FR_PROMPT_ACCELx = FR_PROMPT_LABELS_BASE+TELEM_ACCx,
FR_PROMPT_ACCELy = FR_PROMPT_LABELS_BASE+TELEM_ACCy,
FR_PROMPT_ACCELz = FR_PROMPT_LABELS_BASE+TELEM_ACCz,
FR_PROMPT_HDG = FR_PROMPT_LABELS_BASE+TELEM_HDG,
FR_PROMPT_VARIO = FR_PROMPT_LABELS_BASE+TELEM_VSPEED,
FR_PROMPT_VIRGULE_BASE = 180, //,0 - ,9
};
@ -114,6 +87,7 @@ I18N_PLAY_FUNCTION(fr, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
#if !defined(CPUARM)
if (unit) {
unit--;
convertUnit(number, unit);
@ -125,18 +99,19 @@ I18N_PLAY_FUNCTION(fr, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
unit = UNIT_KTS;
}
}
#if defined(CPUARM)
if ((att & PREC1) && (unit == UNIT_FEET || (unit == UNIT_DIST && number >= 100))) {
number = div10_and_round(number);
att -= PREC1;
}
#endif
unit++;
}
#endif
int8_t mode = MODE(att);
if (mode > 0) {
#if defined(CPUARM)
if (mode == 2) {
number /= 10;
}
#else
// we assume that we are PREC1
#endif
div_t qr = div(number, 10);
if (qr.rem) {
PLAY_NUMBER(qr.quot, 0, 0);

View file

@ -93,6 +93,7 @@ I18N_PLAY_FUNCTION(hu, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
#if !defined(CPUARM)
if (unit) {
unit--;
convertUnit(number, unit);
@ -104,18 +105,19 @@ I18N_PLAY_FUNCTION(hu, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
unit = UNIT_KTS;
}
}
#if defined(CPUARM)
if ((att & PREC1) && (unit == UNIT_FEET || (unit == UNIT_DIST && number >= 100))) {
number = div10_and_round(number);
att -= PREC1;
}
#endif
unit++;
}
#endif
int8_t mode = MODE(att);
if (mode > 0) {
#if defined(CPUARM)
if (mode == 2) {
number /= 10;
}
#else
// we assume that we are PREC1
#endif
div_t qr = div(number, 10);
if (qr.rem) {
PLAY_NUMBER(qr.quot, 0, 0);

View file

@ -54,33 +54,6 @@ enum ItalianPrompts {
IT_PROMPT_FEET = IT_PROMPT_UNITS_BASE+UNIT_FEET,
IT_PROMPT_KTS = IT_PROMPT_UNITS_BASE+UNIT_KTS,
IT_PROMPT_LABELS_BASE = 131,
IT_PROMPT_TIMER1 = IT_PROMPT_LABELS_BASE+TELEM_TIMER1,
IT_PROMPT_TIMER2 = IT_PROMPT_LABELS_BASE+TELEM_TIMER2,
IT_PROMPT_RSSI_TX = IT_PROMPT_LABELS_BASE+TELEM_RSSI_TX,
IT_PROMPT_RSSI_RX = IT_PROMPT_LABELS_BASE+TELEM_RSSI_RX,
IT_PROMPT_A1 = IT_PROMPT_LABELS_BASE+TELEM_A1,
IT_PROMPT_A2 = IT_PROMPT_LABELS_BASE+TELEM_A2,
IT_PROMPT_ALTITUDE = IT_PROMPT_LABELS_BASE+TELEM_ALT,
IT_PROMPT_RPM = IT_PROMPT_LABELS_BASE+TELEM_RPM,
IT_PROMPT_ESSENCE = IT_PROMPT_LABELS_BASE+TELEM_FUEL,
IT_PROMPT_T1 = IT_PROMPT_LABELS_BASE+TELEM_T1,
IT_PROMPT_T2 = IT_PROMPT_LABELS_BASE+TELEM_T2,
IT_PROMPT_VITESSE = IT_PROMPT_LABELS_BASE+TELEM_SPEED,
IT_PROMPT_DISTANCE = IT_PROMPT_LABELS_BASE+TELEM_DIST,
IT_PROMPT_GPSALTITUDE = IT_PROMPT_LABELS_BASE+TELEM_GPSALT,
IT_PROMPT_ELEMENTS_LIPO = IT_PROMPT_LABELS_BASE+TELEM_CELL,
IT_PROMPT_TOTAL_LIPO = IT_PROMPT_LABELS_BASE+TELEM_CELLS_SUM,
IT_PROMPT_VFAS = IT_PROMPT_LABELS_BASE+TELEM_VFAS,
IT_PROMPT_COURANT = IT_PROMPT_LABELS_BASE+TELEM_CURRENT,
IT_PROMPT_CONSOMMATION = IT_PROMPT_LABELS_BASE+TELEM_CONSUMPTION,
IT_PROMPT_PUISSANCE = IT_PROMPT_LABELS_BASE+TELEM_POWER,
IT_PROMPT_ACCELx = IT_PROMPT_LABELS_BASE+TELEM_ACCx,
IT_PROMPT_ACCELy = IT_PROMPT_LABELS_BASE+TELEM_ACCy,
IT_PROMPT_ACCELz = IT_PROMPT_LABELS_BASE+TELEM_ACCz,
IT_PROMPT_HDG = IT_PROMPT_LABELS_BASE+TELEM_HDG,
IT_PROMPT_VARIO = IT_PROMPT_LABELS_BASE+TELEM_VSPEED,
};
#if defined(VOICE)
@ -102,6 +75,7 @@ I18N_PLAY_FUNCTION(it, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
#if !defined(CPUARM)
if (unit) {
unit--;
convertUnit(number, unit);
@ -113,18 +87,20 @@ I18N_PLAY_FUNCTION(it, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
unit = UNIT_KTS;
}
}
#if defined(CPUARM)
if ((att & PREC1) && (unit == UNIT_FEET || (unit == UNIT_DIST && number >= 100))) {
number = div10_and_round(number);
att -= PREC1;
}
#endif
unit++;
}
#endif
int8_t mode = MODE(att);
if (mode > 0) {
div_t qr = div(number, (mode == 1 ? 10 : 100));
#if defined(CPUARM)
if (mode == 2) {
number /= 10;
}
#else
// we assume that we are PREC1
#endif
div_t qr = div(number, 10);
if (qr.rem > 0) {
PLAY_NUMBER(qr.quot, 0, 0);
PUSH_NUMBER_PROMPT(IT_PROMPT_VIRGOLA);

View file

@ -58,34 +58,6 @@ enum PolishPrompts {
PL_PROMPT_SECONDS = PL_PROMPT_UNITS_BASE+(UNIT_SECONDS*4),
PL_PROMPT_RPMS = PL_PROMPT_UNITS_BASE+(UNIT_RPMS*4),
PL_PROMPT_G = PL_PROMPT_UNITS_BASE+(UNIT_G*4),
PL_PROMPT_LABELS_BASE = 250,
PL_PROMPT_TIMER1 = PL_PROMPT_LABELS_BASE+TELEM_TIMER1,
PL_PROMPT_TIMER2 = PL_PROMPT_LABELS_BASE+TELEM_TIMER2,
PL_PROMPT_RSSI_TX = PL_PROMPT_LABELS_BASE+TELEM_RSSI_TX,
PL_PROMPT_RSSI_RX = PL_PROMPT_LABELS_BASE+TELEM_RSSI_RX,
PL_PROMPT_A1 = PL_PROMPT_LABELS_BASE+TELEM_A1,
PL_PROMPT_A2 = PL_PROMPT_LABELS_BASE+TELEM_A2,
PL_PROMPT_ALTITUDE = PL_PROMPT_LABELS_BASE+TELEM_ALT,
PL_PROMPT_RPM = PL_PROMPT_LABELS_BASE+TELEM_RPM,
PL_PROMPT_ESSENCE = PL_PROMPT_LABELS_BASE+TELEM_FUEL,
PL_PROMPT_T1 = PL_PROMPT_LABELS_BASE+TELEM_T1,
PL_PROMPT_T2 = PL_PROMPT_LABELS_BASE+TELEM_T2,
PL_PROMPT_VITESSE = PL_PROMPT_LABELS_BASE+TELEM_SPEED,
PL_PROMPT_DISTANCE = PL_PROMPT_LABELS_BASE+TELEM_DIST,
PL_PROMPT_GPSALTITUDE = PL_PROMPT_LABELS_BASE+TELEM_GPSALT,
PL_PROMPT_ELEMENTS_LIPO = PL_PROMPT_LABELS_BASE+TELEM_CELL,
PL_PROMPT_TOTAL_LIPO = PL_PROMPT_LABELS_BASE+TELEM_CELLS_SUM,
PL_PROMPT_VFAS = PL_PROMPT_LABELS_BASE+TELEM_VFAS,
PL_PROMPT_COURANT = PL_PROMPT_LABELS_BASE+TELEM_CURRENT,
PL_PROMPT_CONSOMMATION = PL_PROMPT_LABELS_BASE+TELEM_CONSUMPTION,
PL_PROMPT_PUISSANCE = PL_PROMPT_LABELS_BASE+TELEM_POWER,
PL_PROMPT_ACCELx = PL_PROMPT_LABELS_BASE+TELEM_ACCx,
PL_PROMPT_ACCELy = PL_PROMPT_LABELS_BASE+TELEM_ACCy,
PL_PROMPT_ACCELz = PL_PROMPT_LABELS_BASE+TELEM_ACCz,
PL_PROMPT_HDG = PL_PROMPT_LABELS_BASE+TELEM_HDG,
PL_PROMPT_VARIO = PL_PROMPT_LABELS_BASE+TELEM_VSPEED,
};
#if defined(VOICE)
@ -126,6 +98,7 @@ I18N_PLAY_FUNCTION(pl, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
#if !defined(CPUARM)
if (unit) {
unit--;
convertUnit(number, unit);
@ -137,18 +110,19 @@ I18N_PLAY_FUNCTION(pl, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
unit = UNIT_KTS;
}
}
#if defined(CPUARM)
if ((att & PREC1) && (unit == UNIT_FEET || (unit == UNIT_DIST && number >= 100))) {
number = div10_and_round(number);
att -= PREC1;
}
#endif
unit++;
}
#endif
int8_t mode = MODE(att);
if (mode > 0) {
#if defined(CPUARM)
if (mode == 2) {
number /= 10;
}
#else
// we assume that we are PREC1
#endif
div_t qr = div(number, 10);
if (qr.rem) {
PLAY_NUMBER(qr.quot, 0, ZENSKI);
@ -160,9 +134,10 @@ I18N_PLAY_FUNCTION(pl, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
PUSH_NUMBER_PROMPT(PL_PROMPT_UNITS_BASE+((unit-1)*4)+3);
return;
}
else
else {
number = qr.quot;
}
}
int16_t tmp = number;

View file

@ -76,34 +76,6 @@ enum PortuguesePrompts {
PT_PROMPT_WATTS = PT_PROMPT_UNITS_BASE+UNIT_WATTS,
PT_PROMPT_FEET = PT_PROMPT_UNITS_BASE+UNIT_FEET,
PT_PROMPT_KTS = PT_PROMPT_UNITS_BASE+UNIT_KTS,
PT_PROMPT_LABELS_BASE = 140,
PT_PROMPT_TIMER1 = PT_PROMPT_LABELS_BASE+TELEM_TIMER1,
PT_PROMPT_TIMER2 = PT_PROMPT_LABELS_BASE+TELEM_TIMER2,
PT_PROMPT_RSSI_TX = PT_PROMPT_LABELS_BASE+TELEM_RSSI_TX,
PT_PROMPT_RSSI_RX = PT_PROMPT_LABELS_BASE+TELEM_RSSI_RX,
PT_PROMPT_A1 = PT_PROMPT_LABELS_BASE+TELEM_A1,
PT_PROMPT_A2 = PT_PROMPT_LABELS_BASE+TELEM_A2,
PT_PROMPT_ALTITUDE = PT_PROMPT_LABELS_BASE+TELEM_ALT,
PT_PROMPT_RPM = PT_PROMPT_LABELS_BASE+TELEM_RPM,
PT_PROMPT_ESSENCE = PT_PROMPT_LABELS_BASE+TELEM_FUEL,
PT_PROMPT_T1 = PT_PROMPT_LABELS_BASE+TELEM_T1,
PT_PROMPT_T2 = PT_PROMPT_LABELS_BASE+TELEM_T2,
PT_PROMPT_VITESSE = PT_PROMPT_LABELS_BASE+TELEM_SPEED,
PT_PROMPT_DISTANCE = PT_PROMPT_LABELS_BASE+TELEM_DIST,
PT_PROMPT_GPSALTITUDE = PT_PROMPT_LABELS_BASE+TELEM_GPSALT,
PT_PROMPT_ELEMENTS_LIPO = PT_PROMPT_LABELS_BASE+TELEM_CELL,
PT_PROMPT_TOTAL_LIPO = PT_PROMPT_LABELS_BASE+TELEM_CELLS_SUM,
PT_PROMPT_VFAS = PT_PROMPT_LABELS_BASE+TELEM_VFAS,
PT_PROMPT_COURANT = PT_PROMPT_LABELS_BASE+TELEM_CURRENT,
PT_PROMPT_CONSOMMATION = PT_PROMPT_LABELS_BASE+TELEM_CONSUMPTION,
PT_PROMPT_PUISSANCE = PT_PROMPT_LABELS_BASE+TELEM_POWER,
PT_PROMPT_ACCELx = PT_PROMPT_LABELS_BASE+TELEM_ACCx,
PT_PROMPT_ACCELy = PT_PROMPT_LABELS_BASE+TELEM_ACCy,
PT_PROMPT_ACCELz = PT_PROMPT_LABELS_BASE+TELEM_ACCz,
PT_PROMPT_HDG = PT_PROMPT_LABELS_BASE+TELEM_HDG,
PT_PROMPT_VARIO = PT_PROMPT_LABELS_BASE+TELEM_VSPEED,
};
#if defined(VOICE)
@ -115,6 +87,7 @@ I18N_PLAY_FUNCTION(pt, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
number = -number;
}
#if !defined(CPUARM)
if (unit) {
unit--;
convertUnit(number, unit);
@ -126,18 +99,20 @@ I18N_PLAY_FUNCTION(pt, playNumber, getvalue_t number, uint8_t unit, uint8_t att)
unit = UNIT_KTS;
}
}
#if defined(CPUARM)
if ((att & PREC1) && (unit == UNIT_FEET || (unit == UNIT_DIST && number >= 100))) {
number = div10_and_round(number);
att -= PREC1;
}
#endif
unit++;
}
#endif
int8_t mode = MODE(att);
if (mode > 0) {
div_t qr = div(number, (mode == 1 ? 10 : 100));
#if defined(CPUARM)
if (mode == 2) {
number /= 10;
}
#else
// we assume that we are PREC1
#endif
div_t qr = div(number, 10);
if (qr.rem > 0) {
PLAY_NUMBER(qr.quot, 0, 0);
PUSH_NUMBER_PROMPT(PT_PROMPT_VIRGULA);

Some files were not shown because too many files have changed in this diff Show more