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

Spektrum telemetry implementation (#3659)

* Implementation of Spektrum Telemetry for the DYI Multimodule.

I can only test a subset of sensors and these look okay

* Implement conversion from Fahrenheit to Celsius

* Minor fixes for Spektrum telemetry

* Add some more sensors, show sensor ID instead of instance in the overview
This commit is contained in:
Arne Schwabe 2016-07-22 17:38:11 +02:00 committed by Bertrand Songis
parent a28cbf88f3
commit 352de89838
29 changed files with 662 additions and 48 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -86,6 +86,7 @@ PACK(struct PxxTimerPulsesData {
uint32_t pcmOnesCount;
});
#define MULTIMODULE_BAUDRATE 100000
#if defined(MULTIMODULE)
#define MAX_PULSES_TRANSITIONS 300
#else

View file

@ -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);

View file

@ -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;

View file

@ -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) );

View file

@ -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
}

View file

@ -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);

View file

@ -23,8 +23,7 @@
Fifo<uint8_t, TELEMETRY_FIFO_SIZE> 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);

View file

@ -442,6 +442,7 @@ enum TelemetryProtocol
TELEM_PROTO_FRSKY_D,
TELEM_PROTO_FRSKY_SPORT,
TELEM_PROTO_CROSSFIRE,
TELEM_PROTO_SPEKTRUM
};
enum TelemAnas {

View file

@ -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)

View file

@ -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<uint8_t>(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);
}

View file

@ -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

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"