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:
parent
a28cbf88f3
commit
352de89838
29 changed files with 662 additions and 48 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -86,6 +86,7 @@ PACK(struct PxxTimerPulsesData {
|
|||
uint32_t pcmOnesCount;
|
||||
});
|
||||
|
||||
#define MULTIMODULE_BAUDRATE 100000
|
||||
#if defined(MULTIMODULE)
|
||||
#define MAX_PULSES_TRANSITIONS 300
|
||||
#else
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -442,6 +442,7 @@ enum TelemetryProtocol
|
|||
TELEM_PROTO_FRSKY_D,
|
||||
TELEM_PROTO_FRSKY_SPORT,
|
||||
TELEM_PROTO_CROSSFIRE,
|
||||
TELEM_PROTO_SPEKTRUM
|
||||
};
|
||||
|
||||
enum TelemAnas {
|
||||
|
|
|
@ -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)
|
||||
|
|
381
radio/src/telemetry/spektrum.cpp
Normal file
381
radio/src/telemetry/spektrum.cpp
Normal 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);
|
||||
}
|
27
radio/src/telemetry/spektrum.h
Normal file
27
radio/src/telemetry/spektrum.h
Normal 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
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue