diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 21185c68d..3237be1b7 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -584,7 +584,7 @@ if(ARCH STREQUAL ARM) endif() if(MULTIMODULE) add_definitions(-DMULTIMODULE) - set(SRC ${SRC} pulses/multi_arm.cpp) + set(SRC ${SRC} pulses/multi_arm.cpp telemetry/spektrum.cpp) endif() add_definitions(-DCPUARM) add_definitions(-DFRSKY -DFRSKY_SPORT -DFRSKY_HUB -DGPS -DPXX -DDSM2) diff --git a/radio/src/gui/horus/menu_model_telemetry.cpp b/radio/src/gui/horus/menu_model_telemetry.cpp index 22a600e5a..431e9876c 100644 --- a/radio/src/gui/horus/menu_model_telemetry.cpp +++ b/radio/src/gui/horus/menu_model_telemetry.cpp @@ -436,6 +436,14 @@ bool menuModelTelemetry(evt_t event) lcdDrawText(TELEM_COL2, y, "---"); // TODO shortcut } TelemetrySensor * sensor = & g_model.telemetrySensors[index]; +#ifdef MULTIMODULE + if (IS_SPEKTRUM_PROTOCOL()) { + // Spektrum does not (yet?) really support multiple sensor of the same type. But a lot of + // different sensor display the same information (e.g. voltage, capacity). Show the id + // of the sensor in the overview to ease figuring out what sensors belong together + lcdDrawHexNumber(TELEM_COL4, y, sensor->id, LEFT); + } else +#endif if (sensor->type == TELEM_TYPE_CUSTOM && !g_model.ignoreSensorIds) { lcdDrawNumber(TELEM_COL4, y, sensor->instance, LEFT); } @@ -465,7 +473,7 @@ bool menuModelTelemetry(evt_t event) case ITEM_TELEMETRY_SENSORS_LABEL: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TELEMETRY_SENSORS); lcdDrawText(TELEM_COL2, y, STR_VALUE, 0); - if (!g_model.ignoreSensorIds) { + if (!g_model.ignoreSensorIds && !IS_SPEKTRUM_PROTOCOL()) { lcdDrawText(TELEM_COL4, y, STR_ID, 0); } break; diff --git a/radio/src/gui/taranis/menu_model_telemetry.cpp b/radio/src/gui/taranis/menu_model_telemetry.cpp index e16c027df..94472738b 100644 --- a/radio/src/gui/taranis/menu_model_telemetry.cpp +++ b/radio/src/gui/taranis/menu_model_telemetry.cpp @@ -433,6 +433,14 @@ void menuModelTelemetry(uint8_t event) lcdDrawText(TELEM_COL2, y, "---", 0); // TODO shortcut } TelemetrySensor * sensor = & g_model.telemetrySensors[index]; +#ifdef MULTIMODULE + if (IS_SPEKTRUM_PROTOCOL()) { + // Spektrum does not (yet?) really support multiple sensor of the same type. But a lot of + // different sensor display the same information (e.g. voltage, capacity). Show the id + // of the sensor in the overview to ease figuring out what sensors belong together + lcdDrawHexNumber(TELEM_COL3, y, sensor->id, LEFT); + } else +#endif if (sensor->type == TELEM_TYPE_CUSTOM && !g_model.ignoreSensorIds) { lcdDrawNumber(TELEM_COL3, y, sensor->instance, LEFT); } @@ -461,7 +469,7 @@ void menuModelTelemetry(uint8_t event) case ITEM_TELEMETRY_SENSORS_LABEL: lcd_putsLeft(y, STR_TELEMETRY_SENSORS); lcdDrawText(TELEM_COL2, y, STR_VALUE, 0); - if (!g_model.ignoreSensorIds) { + if (!g_model.ignoreSensorIds && !IS_SPEKTRUM_PROTOCOL()) { lcdDrawText(TELEM_COL3, y, STR_ID, 0); } break; diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index a7274df08..c05d1500e 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -609,7 +609,8 @@ enum TelemetryType PROTOCOL_FRSKY_SPORT = PROTOCOL_TELEMETRY_FIRST, PROTOCOL_FRSKY_D, PROTOCOL_FRSKY_D_SECONDARY, - PROTOCOL_PULSES_CROSSFIRE + PROTOCOL_PULSES_CROSSFIRE, + PROTOCOL_SPEKTRUM }; enum DisplayTrims diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index ed40591d3..447a28eae 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -86,6 +86,7 @@ PACK(struct PxxTimerPulsesData { uint32_t pcmOnesCount; }); +#define MULTIMODULE_BAUDRATE 100000 #if defined(MULTIMODULE) #define MAX_PULSES_TRANSITIONS 300 #else diff --git a/radio/src/targets/horus/board_horus.h b/radio/src/targets/horus/board_horus.h index f1e079a66..38221eb99 100644 --- a/radio/src/targets/horus/board_horus.h +++ b/radio/src/targets/horus/board_horus.h @@ -271,7 +271,7 @@ int32_t getVolume(void); #define VOLUME_LEVEL_DEF 12 // Telemetry driver -void telemetryPortInit(uint32_t baudrate); +void telemetryPortInit(uint32_t baudrate, int mode); void telemetryPortSetDirectionOutput(void); void sportSendBuffer(uint8_t * buffer, uint32_t count); int telemetryGetByte(uint8_t * byte); diff --git a/radio/src/targets/horus/telemetry_driver.cpp b/radio/src/targets/horus/telemetry_driver.cpp index 1a2457d71..359ef92b7 100644 --- a/radio/src/targets/horus/telemetry_driver.cpp +++ b/radio/src/targets/horus/telemetry_driver.cpp @@ -22,7 +22,7 @@ DMAFifo<512> telemetryFifo __DMA (TELEMETRY_DMA_Stream_RX); -void telemetryPortInit(uint32_t baudrate) +void telemetryPortInit(uint32_t baudrate, int mode) { if (baudrate == 0) { USART_DeInit(TELEMETRY_USART); @@ -56,9 +56,15 @@ void telemetryPortInit(uint32_t baudrate) GPIO_ResetBits(TELEMETRY_GPIO_DIR, TELEMETRY_DIR_GPIO_PIN); USART_InitStructure.USART_BaudRate = baudrate; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_Parity = USART_Parity_No; + if (mode == TELEMETRY_SERIAL_8E2) { + USART_InitStructure.USART_WordLength = USART_WordLength_9b; + USART_InitStructure.USART_StopBits = USART_StopBits_2; + USART_InitStructure.USART_Parity = USART_Parity_Even; + } else { + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + } USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; diff --git a/radio/src/targets/sky9x/board_sky9x.h b/radio/src/targets/sky9x/board_sky9x.h index 085ad9c3f..9bed3f45b 100644 --- a/radio/src/targets/sky9x/board_sky9x.h +++ b/radio/src/targets/sky9x/board_sky9x.h @@ -290,7 +290,7 @@ void rotencEnd(); void debugPutc(const char c); // Telemetry driver -void telemetryPortInit(uint32_t baudrate); +void telemetryPortInit(uint32_t baudrate, int mode); uint32_t telemetryTransmitPending(); void telemetryTransmitBuffer(uint8_t * buffer, uint32_t size); void rxPdcUsart( void (*pChProcess)(uint8_t x) ); diff --git a/radio/src/targets/sky9x/telemetry_driver.cpp b/radio/src/targets/sky9x/telemetry_driver.cpp index 4b784b5e0..a33d421f1 100644 --- a/radio/src/targets/sky9x/telemetry_driver.cpp +++ b/radio/src/targets/sky9x/telemetry_driver.cpp @@ -34,7 +34,7 @@ uint16_t DsmRxTimeout; // USART0 configuration // Work in Progress, UNTESTED // Uses PA5 and PA6 (RXD and TXD) -void UART2_Configure(uint32_t baudrate, uint32_t masterClock) +void UART2_Configure(uint32_t baudrate, uint32_t masterClock, int mode) { register Usart *pUsart = SECOND_USART; @@ -48,7 +48,10 @@ void UART2_Configure(uint32_t baudrate, uint32_t masterClock) pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS; // Configure mode - pUsart->US_MR = 0x000008C0 ; // NORMAL, No Parity, 8 bit + if (mode == TELEMETRY_SERIAL_8E2) + pUsart->US_MR = 0x000020C0 ; + else + pUsart->US_MR = 0x000008C0 ; // NORMAL, No Parity, 8 bit // Configure baudrate // Asynchronous, no oversampling @@ -163,10 +166,10 @@ uint32_t telemetryTransmitPending() return x ; } -void telemetryPortInit(uint32_t baudrate) +void telemetryPortInit(uint32_t baudrate, int mode) { #if !defined(SIMU) - UART2_Configure(baudrate, Master_frequency); + UART2_Configure(baudrate, Master_frequency, mode); startPdcUsartReceive(); #endif } diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index de675f7e1..057e02c6e 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -327,7 +327,7 @@ void eepromWriteBlock(uint8_t * buffer, uint32_t address, uint32_t size); void debugPutc(const char c); // Telemetry driver -void telemetryPortInit(uint32_t baudrate); +void telemetryPortInit(uint32_t baudrate, int mode); void telemetryPortSetDirectionOutput(void); void sportSendBuffer(uint8_t * buffer, uint32_t count); int telemetryGetByte(uint8_t * byte); diff --git a/radio/src/targets/taranis/telemetry_driver.cpp b/radio/src/targets/taranis/telemetry_driver.cpp index 9c7040ce5..30a850a82 100644 --- a/radio/src/targets/taranis/telemetry_driver.cpp +++ b/radio/src/targets/taranis/telemetry_driver.cpp @@ -23,8 +23,7 @@ Fifo telemetryFifo; uint32_t telemetryErrors = 0; -void telemetryPortInit(uint32_t baudrate) -{ +void telemetryPortInit(uint32_t baudrate, int mode) { if (baudrate == 0) { USART_DeInit(TELEMETRY_USART); return; @@ -57,9 +56,15 @@ void telemetryPortInit(uint32_t baudrate) GPIO_ResetBits(TELEMETRY_GPIO_DIR, TELEMETRY_DIR_GPIO_PIN); USART_InitStructure.USART_BaudRate = baudrate; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_Parity = USART_Parity_No; + if (mode == TELEMETRY_SERIAL_8E2) { + USART_InitStructure.USART_WordLength = USART_WordLength_9b; + USART_InitStructure.USART_StopBits = USART_StopBits_2; + USART_InitStructure.USART_Parity = USART_Parity_Even; + } else { + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + } USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(TELEMETRY_USART, &USART_InitStructure); diff --git a/radio/src/telemetry/frsky.h b/radio/src/telemetry/frsky.h index 86600b03c..f82e524be 100644 --- a/radio/src/telemetry/frsky.h +++ b/radio/src/telemetry/frsky.h @@ -442,6 +442,7 @@ enum TelemetryProtocol TELEM_PROTO_FRSKY_D, TELEM_PROTO_FRSKY_SPORT, TELEM_PROTO_CROSSFIRE, + TELEM_PROTO_SPEKTRUM }; enum TelemAnas { diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp index d6a7f74d1..a496b73bb 100644 --- a/radio/src/telemetry/frsky_sport.cpp +++ b/radio/src/telemetry/frsky_sport.cpp @@ -460,7 +460,7 @@ bool sportUpdatePowerOn(ModuleIndex module) sportWaitState(SPORT_IDLE, 500); - telemetryPortInit(FRSKY_SPORT_BAUDRATE); + telemetryPortInit(FRSKY_SPORT_BAUDRATE, TELEMETRY_SERIAL_8N1); #if defined(PCBTARANIS) || defined(PCBHORUS) if (module == INTERNAL_MODULE) diff --git a/radio/src/telemetry/spektrum.cpp b/radio/src/telemetry/spektrum.cpp new file mode 100644 index 000000000..064e2a735 --- /dev/null +++ b/radio/src/telemetry/spektrum.cpp @@ -0,0 +1,381 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "opentx.h" + +#include "spektrum.h" + +/* + * Documentation of the Spektrum protocol is available under + * http://www.rcgroups.com/forums/showthread.php?t=1726960&page=22#post34091390 + * Multi module adds two byte header of 0xAA [RSSI of telemetry packet] [16 byte message] + */ + +/* + * The 16 byte message is formated as follows + * [ic2 address] [secondary id] [14 byte ic2 address (type) specific data] + * we translate the secondary to the instance of the sensor + * + * OpenTX Mapping + * + * instance = secondary id (almost always 0) + * subid = 0 (always 0) + * id = i2c address <<8 | start byte + */ + + + +#define I2C_PSEUDO_TX 0xf0 +#define SPEKTRUM_TELEMETRY_LENGTH 18 + +#define I2C_HIGH_CURRENT 0x03 +#define I2C_GPS 0x17 +#define I2C_GPS2 0x17 +#define I2C_CELLS 0x3a +#define I2C_QOS 0x7f + + +enum SpektrumDataType : uint8_t { + int8, + int16, + int32, + uint8, + uint16, + uint32, + uint8bcd, + uint16bcd, + uint32bcd, + custom +}; + +struct SpektrumSensor { + const uint8_t i2caddress; + const uint8_t startByte; + const SpektrumDataType dataType; + const char *name; + const TelemetryUnit unit; + const uint8_t precision; +}; + +const SpektrumSensor spektrumSensors[] = { + // High voltage internal sensor + {0x01, 0, int16, ZSTR_A1, UNIT_VOLTS, 1}, + + // Temperature internal sensor + {0x02, 0, int16, ZSTR_TEMP1, UNIT_CELSIUS, 1}, + + // High current internal sensor (0x03), 300A/2048 resolution + {I2C_HIGH_CURRENT, 0, int16, ZSTR_CURR, UNIT_AMPS, 1}, + + //Powerbox (also mentioned as 0x7D but that is also transmitter frame data) + {0x0a, 0, uint16, ZSTR_BATT1_VOLTAGE, UNIT_VOLTS, 2}, + {0x0a, 2, uint16, ZSTR_BATT2_VOLTAGE, UNIT_VOLTS, 2}, + {0x0a, 4, uint16, ZSTR_BATT1_CONSUMPTION, UNIT_MAH, 0}, + {0x0a, 6, uint16, ZSTR_BATT2_CONSUMPTION, UNIT_MAH, 0}, + + // AirSpeed, also has max (+2, int16) + {0x11, 0, int16, ZSTR_ASPD, UNIT_KMH, 0}, + + // Altitude, also has max (+2, int16) + {0x12, 0, int16, ZSTR_ALT, UNIT_METERS, 1}, + + + // {0x38, strain} + + // G-Force (+min, max) + {0x14, 0, int16, ZSTR_ACCX, UNIT_G, 2}, + {0x14, 2, int16, ZSTR_ACCY, UNIT_G, 2}, + {0x14, 4, int16, ZSTR_ACCZ, UNIT_G, 2}, + + + // 0x15, JETCAT/TURBINE, BCD Encoded values + // TODO: Add decoding of status information + // {0x15, 0, uint8, ZSTR_STATUS, UNIT_BITFIELD, 0}, + {0x15, 1, uint8bcd, ZSTR_THROTTLE, UNIT_PERCENT, 0}, + {0x15, 2, uint16bcd, ZSTR_A1, UNIT_VOLTS, 2}, + {0x15, 4, uint16bcd, ZSTR_A2, UNIT_VOLTS, 2}, + {0x15, 6, uint32bcd, ZSTR_RPM, UNIT_RPMS, 0}, + {0x15, 10, uint16bcd, ZSTR_TEMP1, UNIT_CELSIUS, 0}, + // {0x15, 0, uint8, ZSTR_STATUS, UNIT_BITFIELD, 0}, + + // 0x16-0x17 GPS + // GPS is bcd encoded and also uses flags. Hard to get right without an actual GPS Sensor + // Time/date is also BCD encoded but so this FrSky's, so treat it as uint32 + {I2C_GPS2, 0, uint16bcd, ZSTR_GSPD, UNIT_KTS, 1}, + {I2C_GPS2, 2, uint32, ZSTR_GPSDATETIME, UNIT_DATETIME, 0}, + + + //{0x17, 2, uint32, ZSTR_GPSDATETIME, UNIT_DATETIME}, utc in bcd HH:MM:SS.S + {0x17, 6, uint8bcd, ZSTR_SATELLITES, UNIT_RAW, 0}, + //{0x17, 7, uint8bcd, ZSTR_GPSALT, UNIT_METERS}, altitude high bits + + // 0x19 Jetcat flow rate + // {0x19, 0, uint16bcd, ZSTR_FUEL_CONSUMPTION, UNIT_MILLILITERS_PER_MINUTE, 1}, missing ml/min + {0x19, 2, uint32bcd, ZSTR_FUEL, UNIT_MILLILITERS, 1}, + + // 0x1a Gyro + {0x1a, 0, int16, ZSTR_GYROX, UNIT_DEGREE, 1}, + {0x1a, 2, int16, ZSTR_GYROY, UNIT_DEGREE, 1}, + {0x1a, 4, int16, ZSTR_GYROZ, UNIT_DEGREE, 1}, + + // 0x1b Attitude & Mag Compass + // mag Units are tbd so probably no sensor in existance, ignore them for now + {0x1b, 0, int16, ZSTR_ROLL, UNIT_DEGREE, 1}, + {0x1b, 2, int16, ZSTR_PITCH, UNIT_DEGREE, 1}, + {0x1b, 4, int16, ZSTR_YAW, UNIT_DEGREE, 1}, + + // {0x20, esc}, does not exist in the wild? + + // Dual Cell monitor (0x34) + {0x34, 0, int16, ZSTR_BATT1_CURRENT, UNIT_AMPS, 1}, + {0x34, 2, int16, ZSTR_BATT1_CONSUMPTION, UNIT_MAH, 1}, + {0x34, 4, uint16, ZSTR_BATT1_TEMP, UNIT_CELSIUS, 1}, + {0x34, 6, int16, ZSTR_BATT2_CURRENT, UNIT_AMPS, 1}, + {0x34, 8, int16, ZSTR_BATT2_CONSUMPTION, UNIT_MAH, 1}, + {0x34, 10, uint16, ZSTR_BATT2_TEMP, UNIT_CELSIUS, 1}, + + // Tank pressure + custom input bits (ignore for now) + //{0x38, 0, uint16, ZSTR_STATUS_BITS, UNIT_BITFIELD, 0}, + //{0x38, 0, uint16, ZSTR_PRESSSURE, UNIT_PSI, 1}, + + // Cells (0x3a) + {I2C_CELLS, 0, uint16, ZSTR_CELLS, UNIT_VOLTS, 2}, + {I2C_CELLS, 2, uint16, ZSTR_CELLS, UNIT_VOLTS, 2}, + {I2C_CELLS, 4, uint16, ZSTR_CELLS, UNIT_VOLTS, 2}, + {I2C_CELLS, 6, uint16, ZSTR_CELLS, UNIT_VOLTS, 2}, + {I2C_CELLS, 8, uint16, ZSTR_CELLS, UNIT_VOLTS, 2}, + {I2C_CELLS, 10, uint16, ZSTR_CELLS, UNIT_VOLTS, 2}, + {I2C_CELLS, 12, uint16, ZSTR_TEMP2, UNIT_CELSIUS, 2}, + + + // Vario-S + {0x40, 0, int16, ZSTR_ALT, UNIT_METERS, 1}, + {0x40, 2, int16, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 1}, + + // 0x50-0x56 custom 3rd party sensors + //{0x50, 0, int16, ZSTR_} + + + // 0x7d are transmitter channels frame data [7], probably only available on the Spektrum + // telemetry bus on the model itself + + // RPM/Volts/Temperature + {0x7e, 0, uint16, ZSTR_RPM, UNIT_RPMS, 0}, + {0x7e, 2, uint16, ZSTR_A3, UNIT_VOLTS, 2}, + {0x7e, 4, int16, ZSTR_TEMP2, UNIT_FAHRENHEIT, 0}, + + // 0x7f, QoS DATA, also called Flight Log,, with A, B, L, R, F, H? + // A - Antenna Fades on Receiver A + // B - Antenna Fades on Receiver B + // L - Antenna Fades on left Receiver + // R - Antenna Fades on right Receiver + // F - Frame losses + {I2C_QOS, 0, uint16, ZSTR_QOS_A, UNIT_RAW, 0}, + {I2C_QOS, 2, uint16, ZSTR_QOS_B, UNIT_RAW, 0}, + {I2C_QOS, 4, uint16, ZSTR_QOS_L, UNIT_RAW, 0}, + {I2C_QOS, 6, uint16, ZSTR_QOS_R, UNIT_RAW, 0}, + {I2C_QOS, 8, uint16, ZSTR_QOS_F, UNIT_RAW, 0}, + {I2C_QOS, 10, uint16, ZSTR_QOS_H, UNIT_RAW, 0}, + {I2C_QOS, 12, uint16, ZSTR_A2, UNIT_VOLTS, 2}, + + {I2C_PSEUDO_TX, 0, uint8, ZSTR_TX_RSSI, UNIT_RAW, 0}, + {0, 0, int16, NULL, UNIT_RAW, 0} //sentinel +}; + +// The bcd int parameter has wrong endian +static int32_t bcdToInt16(uint16_t bcd) { + return (bcd & 0x0f00) + 10 * (bcd & 0xf000) + 100 * (bcd & 0x000f) + 1000 * (bcd & 0x00f0); +} + +// The bcd int parameter has wrong endian +static int32_t bcdToInt8(uint8_t bcd) { + return (bcd & 0xf) + 10 * (bcd & 0xf0); +} + +static int32_t bcdToInt32(uint32_t bcd) { + return bcdToInt16(bcd >> 16) + 10000 * bcdToInt32(bcd); +} + +// Spektrum uses Big Endian data types +static int32_t spektrumGetValue(uint8_t *packet, int startByte, SpektrumDataType type) { + uint8_t *data = packet + startByte; + switch (type) { + case uint8: + return *((uint8_t *) (data)); + case int8: + return *((int8_t *) (data)); + case int16: + return (int16_t) ((uint16_t) (data[1] + (data[0] << 8))); + case uint16: + return ((uint16_t) (data[1] + (data[0] << 8))); + case int32: + return ((int32_t) (data[3] + (data[2] << 8) + (data[1] << 16) + (data[0] << 24))); + case uint32: + return ((uint32_t) (data[3] + (data[2] << 8) + (data[1] << 16) + (data[0] << 24))); + case uint16bcd: + return bcdToInt16(*(uint16_t *) (data)); + case uint8bcd: + return bcdToInt8(*(uint8_t *) (data)); + case uint32bcd: + return bcdToInt32(*(uint32_t *) data); + default: + return -1; + } +} + +bool isSpektrumValidValue(int32_t value, const SpektrumDataType type) { + switch (type) { + case uint16: + return value != 0xffff; + case int16: + return value != 0x7fff; + case int32: + return value != 0x7fffffff; + case uint32: + return ((uint32_t) value) != 0xffffffff; + default: + return true; + } +} + +void processSpektrumPacket(uint8_t *packet) { + + setTelemetryValue(TELEM_PROTO_SPEKTRUM, (I2C_PSEUDO_TX << 8) + 1, 0, 0, packet[1], UNIT_RAW, 0); + // highest bit indicates that TM1100 is in use, ignore it + uint8_t i2cAddress = (packet[2] & 0x7f); + uint8_t instance = packet[3]; + + for (const SpektrumSensor *sensor = spektrumSensors; sensor->i2caddress; sensor++) { + if (i2cAddress == sensor->i2caddress) { + + // Extract value, skip header + int32_t value = spektrumGetValue(packet + 4, sensor->startByte, sensor->dataType); + + if (!isSpektrumValidValue(value, sensor->dataType)) + continue; + + if (i2cAddress == I2C_CELLS && sensor->unit == UNIT_VOLTS) { + // Map to FrSky style cell values + + int cellIndex = (sensor->startByte / 2) << 16; + value = value | cellIndex; + } + + if (sensor->i2caddress == I2C_HIGH_CURRENT && sensor->unit == UNIT_AMPS) + // Spektrum's documents talks says: Resolution: 300A/2048 = 0.196791 A/tick + // Note that 300/2048 = 0,1464. DeviationTX also uses the 0.196791 figure + value = value * 196791 / 100000; + + else if (sensor->i2caddress == I2C_GPS2 && sensor->unit == UNIT_DATETIME) { + // Frsky time is HH:MM:SS:00 bcd encodes while spektrum uses 0HH:MM:SS.S + value = (value & 0xfffffff0) << 4; + } + + // Check if this looks like a LemonRX Transceiver, they use QoS Frame loss A as RSSI indicator(0-100) + if (i2cAddress == I2C_QOS && sensor->startByte == 0) { + if (spektrumGetValue(packet + 4, 2, uint16) == 0x8000 && + spektrumGetValue(packet + 4, 4, uint16) == 0x8000 && + spektrumGetValue(packet + 4, 6, uint16) == 0x8000 && + spektrumGetValue(packet + 4, 8, uint16) == 0x8000) { + telemetryData.rssi.set(value); + } else { + // Otherwise use the received signal strength of the telemetry packet as indicator + // Range is 0-31, multiply by 3 to get an almost full reading for 0x1f, the maximum the cyrf chip reports + telemetryData.rssi.set(packet[1] * 3); + } + telemetryStreaming = TELEMETRY_TIMEOUT10ms; + } + + + uint16_t pseudoId = (sensor->i2caddress << 8 | sensor->startByte); + setTelemetryValue(TELEM_PROTO_SPEKTRUM, pseudoId, 0, instance, value, sensor->unit, sensor->precision); + } + } +} + +void processSpektrumTelemetryData(uint8_t data) { + if (telemetryRxBufferCount == 0 && data != 0xAA) { + TRACE("[SPK] invalid start byte 0x%02X", data); + return; + } + + if (telemetryRxBufferCount < TELEMETRY_RX_PACKET_SIZE) { + telemetryRxBuffer[telemetryRxBufferCount++] = data; + } + else { + TRACE("[SPK] array size %d error", telemetryRxBufferCount); + telemetryRxBufferCount = 0; + } + + if (telemetryRxBufferCount >= SPEKTRUM_TELEMETRY_LENGTH) { + + debugPrintf("[SPK] Packet 0x%02X rssi 0x%02X: ic2 0x%02x, %02x: ", + telemetryRxBuffer[0], telemetryRxBuffer[1], telemetryRxBuffer[2], telemetryRxBuffer[3]); + for (int i = 4; i < SPEKTRUM_TELEMETRY_LENGTH; i += 4) { + debugPrintf("%02X%02X %02X%02X ", telemetryRxBuffer[i], telemetryRxBuffer[i + 1], + telemetryRxBuffer[i + 2], telemetryRxBuffer[i + 3]); + } + debugPrintf("\r\n"); + processSpektrumPacket(telemetryRxBuffer); + telemetryRxBufferCount = 0; + } +} + +const SpektrumSensor *getSpektrumSensor(uint16_t pseudoId) { + uint8_t startByte = (uint8_t) (pseudoId & 0xff); + uint8_t i2cadd = (uint8_t) (pseudoId >> 8); + for (const SpektrumSensor *sensor = spektrumSensors; sensor->i2caddress; sensor++) { + if (i2cadd == sensor->i2caddress && startByte == sensor->startByte) + return sensor; + } + return nullptr; +} + +void spektrumSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance) { + TelemetrySensor &telemetrySensor = g_model.telemetrySensors[index]; + telemetrySensor.id = id; + telemetrySensor.subId = subId; + telemetrySensor.instance = instance; + + const SpektrumSensor *sensor = getSpektrumSensor(id); + if (sensor) { + TelemetryUnit unit = sensor->unit; + uint8_t prec = min(2, sensor->precision); + telemetrySensor.init(sensor->name, unit, prec); + + if (unit == UNIT_RPMS) { + telemetrySensor.custom.ratio = 1; + telemetrySensor.custom.offset = 1; + } else if (unit == UNIT_FAHRENHEIT) { + if (!IS_IMPERIAL_ENABLE()) { + telemetrySensor.unit = UNIT_CELSIUS; + } + + } else if (unit == UNIT_METERS) { + if (IS_IMPERIAL_ENABLE()) { + telemetrySensor.unit = UNIT_FEET; + } + } + } else { + telemetrySensor.init(id); + } + + storageDirty(EE_MODEL); +} \ No newline at end of file diff --git a/radio/src/telemetry/spektrum.h b/radio/src/telemetry/spektrum.h new file mode 100644 index 000000000..e78b44a98 --- /dev/null +++ b/radio/src/telemetry/spektrum.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SPEKTRUM_H +#define _SPEKTRUM_H + +void processSpektrumTelemetryData(uint8_t data); +void spektrumSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance); + +#endif diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 2b1f57c86..59098f058 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -64,6 +64,12 @@ void processTelemetryData(uint8_t data) processCrossfireTelemetryData(data); return; } +#endif +#if defined(MULTIMODULE) + if (telemetryProtocol == PROTOCOL_SPEKTRUM) { + processSpektrumTelemetryData(data); + return; + } #endif processFrskyTelemetryData(data); } @@ -401,14 +407,20 @@ void telemetryReset() #if defined(CPUARM) // we don't reset the telemetry here as we would also reset the consumption after model load -void telemetryInit(uint8_t protocol) -{ +void telemetryInit(uint8_t protocol) { +#if defined(MULTIMODULE) + // TODO: Is there a better way to communicate this to this function? + if (g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE) { + // The DIY Multi module always speaks 100000 baud regardless of the telemetry protocol in use + telemetryPortInit(MULTIMODULE_BAUDRATE, TELEMETRY_SERIAL_8E2); + } else +#endif if (protocol == PROTOCOL_FRSKY_D) { - telemetryPortInit(FRSKY_D_BAUDRATE); + telemetryPortInit(FRSKY_D_BAUDRATE, TELEMETRY_SERIAL_8N1); } #if defined(CROSSFIRE) else if (protocol == PROTOCOL_PULSES_CROSSFIRE) { - telemetryPortInit(CROSSFIRE_BAUDRATE); + telemetryPortInit(CROSSFIRE_BAUDRATE, TELEMETRY_SERIAL_8N1); #if defined(LUA) outputTelemetryBufferSize = 0; outputTelemetryBufferTrigger = 0; @@ -417,11 +429,11 @@ void telemetryInit(uint8_t protocol) } #endif else if (protocol == PROTOCOL_FRSKY_D_SECONDARY) { - telemetryPortInit(0); + telemetryPortInit(0, TELEMETRY_SERIAL_8N1); serial2TelemetryInit(PROTOCOL_FRSKY_D_SECONDARY); } else { - telemetryPortInit(FRSKY_SPORT_BAUDRATE); + telemetryPortInit(FRSKY_SPORT_BAUDRATE, TELEMETRY_SERIAL_8N1); #if defined(LUA) outputTelemetryBufferSize = 0; outputTelemetryBufferTrigger = 0x7E; diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index 02fad4745..953a61b2d 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -41,6 +41,9 @@ #if defined(CROSSFIRE) #include "crossfire.h" #endif +#if defined(MULTIMODULE) + #include "spektrum.h" +#endif extern uint8_t telemetryStreaming; // >0 (true) == data is streaming in. 0 = no data detected for some time @@ -61,10 +64,15 @@ extern uint8_t telemetryState; #define TELEMETRY_TIMEOUT10ms 100 // 1 second +enum TelemetrySerialMode { + TELEMETRY_SERIAL_8N1, + TELEMETRY_SERIAL_8E2 +}; + #if defined(CROSSFIRE) #define TELEMETRY_RX_PACKET_SIZE 64 #else -#define TELEMETRY_RX_PACKET_SIZE 19 // 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1) +#define TELEMETRY_RX_PACKET_SIZE 19 // 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1), multimodule Spektrum telemetry is 18 bytes #endif extern uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE]; @@ -122,6 +130,7 @@ void frskyDSetDefault(int index, uint16_t id); extern uint8_t telemetryProtocol; #define IS_FRSKY_D_PROTOCOL() (telemetryProtocol == PROTOCOL_FRSKY_D) #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_FRSKY_SPORT) +#define IS_SPEKTRUM_PROTOCOL() (telemetryProtocol == PROTOCOL_SPEKTRUM) #else #define IS_FRSKY_D_PROTOCOL() (true) #define IS_FRSKY_SPORT_PROTOCOL() (false) @@ -134,10 +143,21 @@ inline uint8_t modelTelemetryProtocol() if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_CROSSFIRE) return PROTOCOL_PULSES_CROSSFIRE; #endif - if (g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) + if (g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) { return g_model.telemetryProtocol; - else +#if defined(MULTIMODULE) + } else if (g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE) { + if (g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol == MM_RF_PROTO_DSM2) + return PROTOCOL_SPEKTRUM; + else if ((g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol == MM_RF_PROTO_FRSKY) && (g_model.moduleData[EXTERNAL_MODULE].subType == 1)) + // D8 + return PROTOCOL_FRSKY_D; + else + return PROTOCOL_FRSKY_SPORT; +#endif + } else { return PROTOCOL_FRSKY_SPORT; + } } #define MODEL_TELEMETRY_PROTOCOL() modelTelemetryProtocol() #elif defined(CPUARM) diff --git a/radio/src/telemetry/telemetry_sensors.cpp b/radio/src/telemetry/telemetry_sensors.cpp index 3654ddc4d..f71a71fff 100644 --- a/radio/src/telemetry/telemetry_sensors.cpp +++ b/radio/src/telemetry/telemetry_sensors.cpp @@ -497,6 +497,11 @@ void setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, u case TELEM_PROTO_CROSSFIRE: crossfireSetDefault(index, id, instance); break; +#endif +#if defined(MULTIMODULE) + case TELEM_PROTO_SPEKTRUM: + spektrumSetDefault(index, id, subId, instance); + break; #endif default: return; @@ -571,6 +576,10 @@ int32_t convertTelemetryValue(int32_t value, uint8_t unit, uint8_t prec, uint8_t // T(°F) = T(°C)×1,8 + 32 value = 32 + (value*18) / 10; } + } else if (unit == UNIT_FAHRENHEIT) { + if (destUnit == UNIT_CELSIUS) { + value = (value - 32) * 10/18; + } } else { const UnitConversionRule * p = unitConversionTable; diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 9be73841a..094937c62 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -1252,6 +1252,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1269,6 +1272,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1285,3 +1290,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 5e2e1ef03..dc81836ec 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -1273,6 +1273,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1288,21 +1291,30 @@ #define ZSTR_BATT2_VOLTAGE "RB2V" #define ZSTR_BATT1_CURRENT "RB1A" #define ZSTR_BATT2_CURRENT "RB2A" -#define ZSTR_BATT1_CONSUMPTION "RB1C" -#define ZSTR_BATT2_CONSUMPTION "RB2C" -#define ZSTR_RB_STATE "RBS" -#define ZSTR_CHANS_STATE "RBCS" -#define ZSTR_RX_RSSI1 "1RSS" -#define ZSTR_RX_RSSI2 "2RSS" -#define ZSTR_RX_QUALITY "RQly" -#define ZSTR_RX_SNR "RSNR" -#define ZSTR_ANTENNA "ANT" -#define ZSTR_RF_MODE "RFMD" -#define ZSTR_TX_POWER "TPWR" -#define ZSTR_TX_RSSI "TRSS" -#define ZSTR_TX_QUALITY "TQly" -#define ZSTR_TX_SNR "TSNR" -#define ZSTR_PITCH "Ptch" -#define ZSTR_ROLL "Roll" -#define ZSTR_YAW "Yaw" -#define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_BATT1_CONSUMPTION "RB1C" +#define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" +#define ZSTR_RB_STATE "RBS" +#define ZSTR_CHANS_STATE "RBCS" +#define ZSTR_RX_RSSI1 "1RSS" +#define ZSTR_RX_RSSI2 "2RSS" +#define ZSTR_RX_QUALITY "RQly" +#define ZSTR_RX_SNR "RSNR" +#define ZSTR_ANTENNA "ANT" +#define ZSTR_RF_MODE "RFMD" +#define ZSTR_TX_POWER "TPWR" +#define ZSTR_TX_RSSI "TRSS" +#define ZSTR_TX_QUALITY "TQly" +#define ZSTR_TX_SNR "TSNR" +#define ZSTR_PITCH "Ptch" +#define ZSTR_ROLL "Roll" +#define ZSTR_YAW "Yaw" +#define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 312f6f436..d572364ca 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -1273,6 +1273,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1290,6 +1293,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1306,3 +1311,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 762eccddd..9e5a27587 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -1214,6 +1214,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1231,6 +1234,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1247,3 +1252,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 47f3c7594..40fdc2d6e 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -1214,6 +1214,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1231,6 +1234,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1247,3 +1252,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 4d628f9c2..cff60d615 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -1246,6 +1246,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1263,6 +1266,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1279,3 +1284,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "PV" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index e7e43c453..995791949 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -1250,6 +1250,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1267,6 +1270,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1283,3 +1288,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 63b3bfcdd..c44df1598 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -1265,6 +1265,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1282,6 +1285,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1298,3 +1303,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index edbbfe419..e853bd6cb 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -1252,6 +1252,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1269,6 +1272,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1285,3 +1290,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index b7e2713f0..680fc29bc 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -1209,6 +1209,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1226,6 +1229,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1242,3 +1247,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 045e4ed36..56a33bd29 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -1267,6 +1267,9 @@ #define ZSTR_ACCX "AccX" #define ZSTR_ACCY "AccY" #define ZSTR_ACCZ "AccZ" +#define ZSTR_GYROX "GYRX" +#define ZSTR_GYROY "GYRY" +#define ZSTR_GYROZ "GYRZ" #define ZSTR_CURR "Curr" #define ZSTR_CAPACITY "Capa" #define ZSTR_VFAS "VFAS" @@ -1284,6 +1287,8 @@ #define ZSTR_BATT2_CURRENT "RB2A" #define ZSTR_BATT1_CONSUMPTION "RB1C" #define ZSTR_BATT2_CONSUMPTION "RB2C" +#define ZSTR_BATT1_TEMP "RB1T" +#define ZSTR_BATT2_TEMP "RB2T" #define ZSTR_RB_STATE "RBS" #define ZSTR_CHANS_STATE "RBCS" #define ZSTR_RX_RSSI1 "1RSS" @@ -1300,3 +1305,10 @@ #define ZSTR_ROLL "Roll" #define ZSTR_YAW "Yaw" #define ZSTR_FLIGHT_MODE "FM" +#define ZSTR_THROTTLE "Thr" +#define ZSTR_QOS_A "FdeA" +#define ZSTR_QOS_B "FdeB" +#define ZSTR_QOS_L "FdeL" +#define ZSTR_QOS_R "FdeR" +#define ZSTR_QOS_F "FLss" +#define ZSTR_QOS_H "Hold"