* transferred respective OpenTX updates to HoTT telemetry * integrated LUA function flushAudio from OpenTx * sensor names moved to “untranslated.h” reverted *.h.txt to original mainline content removed leading "Z" in sensor name defines
944 lines
48 KiB
C++
944 lines
48 KiB
C++
/*
|
||
* Copyright (C) EdgeTX
|
||
*
|
||
* Based on code named
|
||
* opentx - https://github.com/opentx/opentx
|
||
* 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"
|
||
|
||
/* HoTT Telemetry
|
||
|
||
HoTT telemetry comprises of one and up to eight devices connected to the receiver's one-wire serial bus. The devices
|
||
have unique ID's and each decive ID may be present on the bus only once.
|
||
|
||
HoTT telemetry knows to operating modes, Binary mode (normal operating mode) and Text mode (configuration mode).
|
||
Telemetry data is passed from the receiver via MPM to OpenTx in pages. The pages can be present or not, they
|
||
also do not have to follow each others.
|
||
|
||
Telemetry device IDs:
|
||
0x00 RX, 0x09 Vario, 0x0A GPS, 0x0B not seen, 0x0C ESC, 0x0D GAM, 0x0E EAM, 0x80 Text config mode
|
||
|
||
Binary mode:
|
||
Each page consists of a four byte header followed by ten bytes data plus a single byte warning code.
|
||
|
||
Generic telemetry page layout in binary mode:
|
||
[0] = TX RSSI value, downlink signal strength (rx --> tx as seen by tx)
|
||
CC2500 formated (a<128:a/2-71dBm, a>=128:(a-256)/2-71dBm)
|
||
[1] = TX LQI value, downlink signal quality (rx --> tx as seen by tx)
|
||
[2] = ID of device that sent the packet, see telemetry devices ID above
|
||
[3] = telemetry page number.
|
||
[4]..[13] = 10 data bytes
|
||
[14] = RX, GAM, EAM, ESC, GPS, VARIO warnings
|
||
|
||
Telemetry pages in binary mode:
|
||
0x00 for RX binary data
|
||
0x01..0x04 for GAM, EAM, ESC, GPS, VARIO binary data
|
||
|
||
Every binary data frame sent by the RX has 10 data bytes.
|
||
Page layout of the RX telemetry page 0 in binary mode
|
||
[0] = TX RSSI value, downlink signal strength (rx --> tx as seen by tx)
|
||
CC2500 formated (a<128:a/2-71dBm, a>=128:(a-256)/2-71dBm)
|
||
[1] = TX LQI value, downlink signal quality (rx --> tx as seen by tx)
|
||
[2] = ID of device that sent the packet, see telemetry devices ID above
|
||
[3] = telemetry page number.
|
||
[4] = ?? looks to be a copy of [7]
|
||
[5] = RX_Voltage*10 in V
|
||
[6] = Temperature-20 in °C
|
||
[7] = Uplink signal strength (tx --> rx as seen by the rx):
|
||
CC2500 formated (a<128:a/2-71dBm, a>=128:(a-256)/2-71dBm)
|
||
[8] = Uplink signal quality (tx --> rx as seen by the tx) in percent
|
||
[9] = RX_MIN_Voltage*10 in V
|
||
[10,11] = [11]*256+[10]=max lost packet time in ms, max value is 2s=0x7D0
|
||
[12] = RX Event (1 = low battery voltage, 2 low/high temp warning, other = general event)
|
||
[13] = ?? looks to be a copy of [7]
|
||
[14] = RX, GAM, EAM, ESC, GPS, VARIO warnings
|
||
|
||
Every binary data frame sent by GAM, EAM, ESC, GPS, VARIO has a length of 45 bytes with 40 bytes
|
||
of device specific data, see e.g.
|
||
https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L240
|
||
The 40 data bytes are sent in 10 byte segments through pages 1 to 4.
|
||
|
||
Page layout for GAM, EAM, ESC, GPS, VARIO telemetry pages 1 to 4:
|
||
[0] = TX RSSI value, downlink signal strength (rx --> tx as seen by tx)
|
||
CC2500 formated (a<128:a/2-71dBm, a>=128:(a-256)/2-71dBm)
|
||
[1] = TX LQI value, downlink signal quality (rx --> tx as seen by tx)
|
||
[2] = ID of device that sent the packet, see telemetry devices ID above
|
||
[3] = telemetry page number.
|
||
[4]..[13] = data bytes 4-13, data bytes 14-23, data bytes 24, 33, data bytes 34-42
|
||
[14] = RX, GAM, EAM, ESC, GPS, VARIO warnings
|
||
|
||
Text Mode:
|
||
Telemetry pages in text mode:
|
||
0x00..0x12
|
||
|
||
Every text mode data frame sent by GAM, EAM, ESC, GPS, VARIO has a length of 173 bytes with 168 bytes
|
||
of data representing 8 lines of 21 characters to display. The 168 bytes of data are sent through pages
|
||
0 to 19.
|
||
|
||
RSSI:
|
||
The packet[0] TX RSSI and packet[7] RX RSSI values describe estimates of the signal level in the
|
||
currently active channel from TX to RX (RX values, uplinked control data) and RX to TX (TX values,
|
||
downlinked telemetry data). RSSI values are based on the current gain setting in the RX chain
|
||
and telemetry frames. The downlink (telemetry) uses lower transmission power. Therefore TX RSSI
|
||
and RX RSSI values are not comparable as different gain values may be used.
|
||
Usually TX RSSI even indicates stronger downlink signal strength compared to uplink signal strength
|
||
because the TX amplifies the signal higher due to the lower power of the downlink signal.
|
||
|
||
LQI:
|
||
LQI (link quality) values in packet[1] and packet[8] also take decodability, i.e. the effort
|
||
to extract meaningful data in account and are because of this the best indicator to determine the quality of
|
||
the link. LQI values are presented asrelative numbers (0-100%).
|
||
|
||
OpenTX RSSI value:
|
||
For Graupner HoTT OpenTX doesn't use the RX RSSI value but instead uses the more
|
||
meaningful RX_LQI value in packet[8]. Hence the default OpenTX RSSI warnig and critical thresholds can
|
||
be adjusted to more appropriate values to indicate link problems.
|
||
|
||
Failsafe trigger:
|
||
Graupner receivers do not trigger failsafe based on RSSI and LQI directly. They do trigger
|
||
failsafe based on the maximum time no decodable data packet has been received. The default threshhold
|
||
seems to be 1000ms
|
||
*/
|
||
|
||
enum
|
||
{
|
||
HOTT_PAGE_00 = 0x00,
|
||
HOTT_PAGE_01 = 0x01,
|
||
HOTT_PAGE_02 = 0x02,
|
||
HOTT_PAGE_03 = 0x03,
|
||
HOTT_PAGE_04 = 0x04,
|
||
};
|
||
|
||
enum DeviceID
|
||
{
|
||
HOTT_TELEM_RX = 0x00,
|
||
HOTT_TELEM_VARIO = 0x09,
|
||
HOTT_TELEM_GPS = 0x0A,
|
||
HOTT_TELEM_ESC = 0x0C,
|
||
HOTT_TELEM_GAM = 0x0D,
|
||
HOTT_TELEM_EAM = 0x0E,
|
||
HOTT_TELEM_TEXT = 0x80,
|
||
HOTT_TELEM_TX = 0xFF
|
||
} ;
|
||
|
||
// telemetry sensors ID
|
||
enum TelemetrySensorID
|
||
{
|
||
// TX from 0xFF01
|
||
HOTT_ID_TX_RSSI_DL = (HOTT_TELEM_TX << 8) + 1, // downlink signal strength (rx --> tx as seen by tx)
|
||
HOTT_ID_TX_LQI_DL = (HOTT_TELEM_TX << 8) + 2, // downlink signal quality (rx --> tx s seen by tx)
|
||
|
||
// RX from 0x0001
|
||
HOTT_ID_RX_RSSI_UL = (HOTT_TELEM_RX << 8) + 1, // uplink signal strength (tx --> rx as seen by rx)
|
||
HOTT_ID_RX_LQI_UL = (HOTT_TELEM_RX << 8) + 2, // uplink signal quality (tx --> rx as seen by rx)
|
||
HOTT_ID_RX_VLT = (HOTT_TELEM_RX << 8) + 3, // RX battery voltage
|
||
HOTT_ID_RX_TMP = (HOTT_TELEM_RX << 8) + 4, // RX temperature
|
||
HOTT_ID_RX_BAT_MIN = (HOTT_TELEM_RX << 8) + 5, // RX lowest rx voltage
|
||
HOTT_ID_RX_VPCK = (HOTT_TELEM_RX << 8) + 6, // RX VPack
|
||
HOTT_ID_RX_EVENT = (HOTT_TELEM_RX << 8) + 7, // RX event + GAM, EAM, VARIO, GPS, ESC warnings
|
||
|
||
// Vario from 0x0901
|
||
HOTT_ID_VARIO_ALT = (HOTT_TELEM_VARIO << 8) + 1, // Vario altitude
|
||
HOTT_ID_VARIO_VV = (HOTT_TELEM_VARIO << 8) + 2, // Vario vertical velocity
|
||
HOTT_ID_VARIO_HDG = (HOTT_TELEM_VARIO << 8) + 3, // Vario heading
|
||
|
||
// GPS from 0x0A01
|
||
HOTT_ID_GPS_HDG = (HOTT_TELEM_GPS << 8) + 1, // GPS heading
|
||
HOTT_ID_GPS_SPEED = (HOTT_TELEM_GPS << 8) + 2, // GPS ground speed
|
||
HOTT_ID_GPS_LL = (HOTT_TELEM_GPS << 8) + 3, // GPS lat/long
|
||
HOTT_ID_GPS_DST = (HOTT_TELEM_GPS << 8) + 4, // GPS lat/long
|
||
HOTT_ID_GPS_ALT = (HOTT_TELEM_GPS << 8) + 5, // GPS altitude
|
||
HOTT_ID_GPS_VV = (HOTT_TELEM_GPS << 8) + 6, // GPS distance
|
||
HOTT_ID_GPS_NSATS = (HOTT_TELEM_GPS << 8) + 7, // GPS number of satellites
|
||
|
||
//ESC from 0x0C01
|
||
HOTT_ID_ESC_VLT = (HOTT_TELEM_ESC << 8) + 1, // ESC battery voltage
|
||
HOTT_ID_ESC_CAP = (HOTT_TELEM_ESC << 8) + 2, // ESC battery capacity consumed
|
||
HOTT_ID_ESC_TMP = (HOTT_TELEM_ESC << 8) + 3, // ESC temperature
|
||
HOTT_ID_ESC_CUR = (HOTT_TELEM_ESC << 8) + 4, // ESC current
|
||
HOTT_ID_ESC_RPM = (HOTT_TELEM_ESC << 8) + 5, // ESC motor rpm
|
||
HOTT_ID_ESC_BEC_VLT = (HOTT_TELEM_ESC << 8) + 6, // ESC BEC voltage
|
||
HOTT_ID_ESC_BEC_CUR = (HOTT_TELEM_ESC << 8) + 7, // ESC BEC current
|
||
HOTT_ID_ESC_BEC_TMP = (HOTT_TELEM_ESC << 8) + 8, // BEC BEC temperature
|
||
HOTT_ID_ESC_MOT_TMP = (HOTT_TELEM_ESC << 8) + 9, // ESC motor or external temperature
|
||
|
||
// GAM from 0x0D01
|
||
HOTT_ID_GAM_CELS = (HOTT_TELEM_GAM << 8) + 1, // GAM Cells
|
||
HOTT_ID_GAM_VLT1 = (HOTT_TELEM_GAM << 8) + 2, // GAM voltage battery 1
|
||
HOTT_ID_GAM_VLT2 = (HOTT_TELEM_GAM << 8) + 3, // GAM volatge battery 2
|
||
HOTT_ID_GAM_TMP1 = (HOTT_TELEM_GAM << 8) + 4, // GAM temperature 1
|
||
HOTT_ID_GAM_TMP2 = (HOTT_TELEM_GAM << 8) + 5, // GAM temperature 2
|
||
HOTT_ID_GAM_FUEL = (HOTT_TELEM_GAM << 8) + 6, // GAM fuel percentage
|
||
HOTT_ID_GAM_RPM1 = (HOTT_TELEM_GAM << 8) + 7, // GAM rpm 1
|
||
HOTT_ID_GAM_ALT = (HOTT_TELEM_GAM << 8) + 8, // GAM altitude
|
||
HOTT_ID_GAM_VV = (HOTT_TELEM_GAM << 8) + 9, // GAM vertical velocity
|
||
HOTT_ID_GAM_CUR = (HOTT_TELEM_GAM << 8) + 10, // GAM current
|
||
HOTT_ID_GAM_VLT3 = (HOTT_TELEM_GAM << 8) + 11, // GAM voltage battery 3
|
||
HOTT_ID_GAM_CAP = (HOTT_TELEM_GAM << 8) + 12, // GAM battery capacity
|
||
HOTT_ID_GAM_SPEED = (HOTT_TELEM_GAM << 8) + 13, // GAM speed
|
||
HOTT_ID_GAM_RPM2 = (HOTT_TELEM_GAM << 8) + 14, // GAM rmp 2
|
||
|
||
//EAM from 0x0E01
|
||
HOTT_ID_EAM_CELS_L = (HOTT_TELEM_EAM << 8) + 1, // EAM Cells L voltage
|
||
HOTT_ID_EAM_CELS_H = (HOTT_TELEM_EAM << 8) + 2, // EAM Cells H voltage
|
||
HOTT_ID_EAM_VLT1 = (HOTT_TELEM_EAM << 8) + 3, // EAM Voltage battery 1
|
||
HOTT_ID_EAM_VLT2 = (HOTT_TELEM_EAM << 8) + 4, // EAM Voltage battery 2
|
||
HOTT_ID_EAM_TMP1 = (HOTT_TELEM_EAM << 8) + 5, // EAM temperature 1
|
||
HOTT_ID_EAM_TMP2 = (HOTT_TELEM_EAM << 8) + 6, // EAM temperature 2
|
||
HOTT_ID_EAM_ALT = (HOTT_TELEM_EAM << 8) + 7, // EAM altitude
|
||
HOTT_ID_EAM_CUR = (HOTT_TELEM_EAM << 8) + 8, // EAM current
|
||
HOTT_ID_EAM_VLT3 = (HOTT_TELEM_EAM << 8) + 9, // EAM battery voltage 3
|
||
HOTT_ID_EAM_CAP = (HOTT_TELEM_EAM << 8) + 10, // EAM Batt capacity
|
||
HOTT_ID_EAM_VV = (HOTT_TELEM_EAM << 8) + 11, // EAM vertical velcocity
|
||
HOTT_ID_EAM_RPM = (HOTT_TELEM_EAM << 8) + 12, // EAM rpm
|
||
HOTT_ID_EAM_SPEED = (HOTT_TELEM_EAM << 8) + 13 // EAM speed
|
||
};
|
||
|
||
struct HottSensor
|
||
{
|
||
const uint16_t id;
|
||
const char * name;
|
||
const TelemetryUnit unit;
|
||
const uint8_t precision;
|
||
};
|
||
|
||
const HottSensor hottSensors[] = {
|
||
// TX
|
||
{ HOTT_ID_TX_RSSI_DL, STR_HOTT_ID_TX_RSSI_DL, UNIT_DB, 0}, // downlink signal strength (rx --> tx as seen by tx)
|
||
{ HOTT_ID_TX_LQI_DL, STR_HOTT_ID_TX_LQI_DL, UNIT_RAW, 0}, // downlink signal quality (rx --> tx s seen by tx)
|
||
|
||
// RX
|
||
{ HOTT_ID_RX_RSSI_UL, STR_HOTT_ID_RX_RSSI_UL, UNIT_DB, 0 }, // uplink signal strength (tx --> rx as seen by rx)
|
||
{ HOTT_ID_RX_LQI_UL, STR_HOTT_ID_RX_LQI_UL, UNIT_RAW, 0 }, // uplink signal quality (tx --> rx as seen by rx)
|
||
{ HOTT_ID_RX_VLT, STR_HOTT_ID_RX_VLT, UNIT_VOLTS, 1 }, // RX battery voltage
|
||
{ HOTT_ID_RX_TMP, STR_HOTT_ID_RX_TMP, UNIT_CELSIUS, 0 }, // RX temperature
|
||
{ HOTT_ID_RX_BAT_MIN, STR_HOTT_ID_RX_BAT_MIN, UNIT_VOLTS, 1 }, // RX lowest rx voltage
|
||
{ HOTT_ID_RX_VPCK, STR_HOTT_ID_RX_VPCK, UNIT_MS, 0 }, // RX VPack
|
||
{ HOTT_ID_RX_EVENT, STR_HOTT_ID_RX_EVENT, UNIT_RAW, 0 }, // RX event and other devices warnings
|
||
|
||
// Vario
|
||
{ HOTT_ID_VARIO_ALT, STR_HOTT_ID_VARIO_ALT, UNIT_METERS, 0 }, // Vario altitude
|
||
{ HOTT_ID_VARIO_VV, STR_HOTT_ID_VARIO_VV, UNIT_METERS_PER_SECOND, 2 }, // Vario vertical velocity
|
||
{ HOTT_ID_VARIO_HDG, STR_HOTT_ID_VARIO_HDG, UNIT_DEGREE, 0 }, // Vario heading
|
||
|
||
// GPS
|
||
{ HOTT_ID_GPS_HDG, STR_HOTT_ID_GPS_HDG, UNIT_DEGREE, 0 }, // GPS heading
|
||
{ HOTT_ID_GPS_SPEED, STR_HOTT_ID_GPS_SPEED, UNIT_KMH, 0 } , // GPS ground speed
|
||
{ HOTT_ID_GPS_LL, STR_HOTT_ID_GPS_LL, UNIT_GPS, 0 }, // GPS lat/long
|
||
{ HOTT_ID_GPS_DST, STR_HOTT_ID_GPS_DST, UNIT_METERS, 0 }, // GPS distance
|
||
{ HOTT_ID_GPS_ALT, STR_HOTT_ID_GPS_ALT, UNIT_METERS, 0 }, // GPS altitude
|
||
{ HOTT_ID_GPS_VV, STR_HOTT_ID_GPS_VV, UNIT_METERS_PER_SECOND, 2}, // GPS vertical velocity
|
||
{ HOTT_ID_GPS_NSATS, STR_HOTT_ID_GPS_NSATS, UNIT_RAW, 0 }, // GPS number of satellites
|
||
|
||
// ESC
|
||
{ HOTT_ID_ESC_VLT, STR_HOTT_ID_ESC_VLT, UNIT_VOLTS, 1 }, // ESC battery voltage
|
||
{ HOTT_ID_ESC_CAP, STR_HOTT_ID_ESC_CAP, UNIT_MAH, 0 }, // ESC battery capacity consumed
|
||
{ HOTT_ID_ESC_TMP, STR_HOTT_ID_ESC_TMP, UNIT_CELSIUS, 0 }, // ESC temperature
|
||
{ HOTT_ID_ESC_CUR, STR_HOTT_ID_ESC_CUR, UNIT_AMPS, 1 }, // ESC current
|
||
{ HOTT_ID_ESC_RPM, STR_HOTT_ID_ESC_RPM, UNIT_RPMS, 0 }, // ESC motor rpm
|
||
{ HOTT_ID_ESC_BEC_VLT, STR_HOTT_ID_ESC_BEC_VLT, UNIT_VOLTS, 1 }, // ESC BEC voltage
|
||
{ HOTT_ID_ESC_BEC_CUR, STR_HOTT_ID_ESC_BEC_CUR, UNIT_AMPS, 1 }, // ESC BEC current
|
||
{ HOTT_ID_ESC_BEC_TMP, STR_HOTT_ID_ESC_BEC_TMP, UNIT_CELSIUS, 0 }, // BEC BEC temperature
|
||
{ HOTT_ID_ESC_MOT_TMP, STR_HOTT_ID_ESC_MOT_TMP, UNIT_CELSIUS, 0 }, // ESC motor or external temperature
|
||
|
||
// GAM
|
||
{ HOTT_ID_GAM_CELS, STR_HOTT_ID_GAM_CELS, UNIT_CELLS, 2}, // GAM Cels L
|
||
{ HOTT_ID_GAM_VLT1, STR_HOTT_ID_GAM_VLT1, UNIT_VOLTS, 1 }, // GAM voltage battery 1
|
||
{ HOTT_ID_GAM_VLT2, STR_HOTT_ID_GAM_VLT2, UNIT_VOLTS, 1 }, // GAM volatge battery 2
|
||
{ HOTT_ID_GAM_TMP1, STR_HOTT_ID_GAM_TMP1, UNIT_CELSIUS, 0 }, // GAM temperature 1
|
||
{ HOTT_ID_GAM_TMP2, STR_HOTT_ID_GAM_TMP2, UNIT_CELSIUS, 0 }, // GAM temperature 2
|
||
{ HOTT_ID_GAM_FUEL, STR_HOTT_ID_GAM_FUEL, UNIT_PERCENT, 0}, // GAM fuel percentage
|
||
{ HOTT_ID_GAM_RPM1, STR_HOTT_ID_GAM_RPM1, UNIT_RPMS, 0 }, // GAM rpm 1
|
||
{ HOTT_ID_GAM_ALT, STR_HOTT_ID_GAM_ALT, UNIT_METERS, 0 }, // GAM altitude
|
||
{ HOTT_ID_GAM_VV, STR_HOTT_ID_GAM_VV, UNIT_METERS_PER_SECOND, 2 }, // GAM vertical velocity
|
||
{ HOTT_ID_GAM_CUR, STR_HOTT_ID_GAM_CUR, UNIT_AMPS, 1 }, // GAM current
|
||
{ HOTT_ID_GAM_VLT3, STR_HOTT_ID_GAM_VLT3, UNIT_VOLTS, 1 }, // GAM voltage battery 3
|
||
{ HOTT_ID_GAM_CAP, STR_HOTT_ID_GAM_CAP, UNIT_MAH, 0 }, // GAM battery capacity
|
||
{ HOTT_ID_GAM_SPEED, STR_HOTT_ID_GAM_SPEED, UNIT_KMH, 0 } , // GAM speed
|
||
{ HOTT_ID_GAM_RPM2, STR_HOTT_ID_GAM_RPM2, UNIT_RPMS, 0 }, // GAM rmp 2
|
||
|
||
//EAM
|
||
{ HOTT_ID_EAM_CELS_L, STR_HOTT_ID_EAM_CELS_L, UNIT_CELLS, 2}, // EAM Cells L voltage
|
||
{ HOTT_ID_EAM_CELS_H, STR_HOTT_ID_EAM_CELS_H, UNIT_CELLS, 2}, // EAM Cells H voltage
|
||
{ HOTT_ID_EAM_VLT1, STR_HOTT_ID_EAM_VLT1, UNIT_VOLTS, 1 }, // EAM Voltage battery 1
|
||
{ HOTT_ID_EAM_VLT2, STR_HOTT_ID_EAM_VLT2, UNIT_VOLTS, 1 }, // EAM Voltage battery 2
|
||
{ HOTT_ID_EAM_TMP1, STR_HOTT_ID_EAM_TMP1, UNIT_CELSIUS, 0 }, // EAM temperature 1
|
||
{ HOTT_ID_EAM_TMP2, STR_HOTT_ID_EAM_TMP2, UNIT_CELSIUS, 0 }, // EAM temperature 2
|
||
{ HOTT_ID_EAM_ALT, STR_HOTT_ID_EAM_ALT, UNIT_METERS, 0 }, // EAM altitude
|
||
{ HOTT_ID_EAM_CUR, STR_HOTT_ID_EAM_CUR, UNIT_AMPS, 1 }, // EAM current
|
||
{ HOTT_ID_EAM_VLT3, STR_HOTT_ID_EAM_VLT3, UNIT_VOLTS, 1 }, // EAM battery voltage 3
|
||
{ HOTT_ID_EAM_CAP, STR_HOTT_ID_EAM_CAP, UNIT_MAH, 0 }, // EAM Batt capacity
|
||
{ HOTT_ID_EAM_VV, STR_HOTT_ID_EAM_VV, UNIT_METERS_PER_SECOND, 2 }, // EAM vertical velcocity
|
||
{ HOTT_ID_EAM_RPM, STR_HOTT_ID_EAM_RPM, UNIT_RPMS, 0 }, // EAM rpm
|
||
{ HOTT_ID_EAM_SPEED, STR_HOTT_ID_EAM_SPEED, UNIT_KMH, 0 } , // EAM speed
|
||
|
||
// sentinel
|
||
{0x00, NULL, UNIT_RAW, 0} // sentinel
|
||
};
|
||
|
||
const HottSensor * getHottSensor(uint16_t id)
|
||
{
|
||
for (const HottSensor * sensor = hottSensors; sensor->id; sensor++) {
|
||
if (id == sensor->id)
|
||
return sensor;
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
int16_t processHoTTdBm(int16_t value)
|
||
// The RSSI value read from the RSSI status register is a 2’s complement number. The following
|
||
// procedure implements the CC2500 data sheet specification to convert the RSSI reading to an
|
||
// absolute power level (RSSI_dBm).
|
||
// 1) Read the RSSI status register
|
||
// 2) Convert the reading from a hexadecimal number to a decimal number (RSSI_dec)
|
||
// 3) If RSSI_dec ≥ 128 then RSSI_dBm = (RSSI_dec - 256)/2 – RSSI_offset
|
||
// 4) Else if RSSI_dec < 128 then RSSI_dBm = (RSSI_dec)/2 – RSSI_offset
|
||
{
|
||
if (value >= 128) {
|
||
value -= 256;
|
||
}
|
||
return value/2 - 71;
|
||
}
|
||
|
||
uint8_t processHoTTWarnings(const uint8_t * packet) {
|
||
// Translates rx events to warnings and transfers GAM, EAM, GPS, VARIO, ESC warnings
|
||
//
|
||
// Two types of warnings have to be considered:
|
||
// 1. Rx events - these are critical events and should be treated with priority
|
||
// 0 = no event
|
||
// 1 = rx low battery warning based on the threshold set in the rx configuration
|
||
// 2 = rx temp warning based on the threshold set in the rx configuration
|
||
// others = not sure, make it known as general event
|
||
//
|
||
// 2. GAM, EAM, VARIO, GPS, EAM - these may be informational but also flight critical
|
||
// 0 = no warning
|
||
// other = warnings based on device specific setting either set by HoTT device configuration
|
||
// or external software, e.g. third party devices like YGE ESC's or SM Unisens/GPS Logger
|
||
//
|
||
// For a list of warnings see HoTT_warnings.txt
|
||
//
|
||
// Rx events are passed from MPM in page 0, packet[12]
|
||
// Other device warnings are passed in packet[14]
|
||
//
|
||
// As only one warning can be transferred to the user the device warnigs are prioritized
|
||
// by the order RX, ESC, GAM, EAM, VARIO, GPS
|
||
//
|
||
// The final result is passed to the user for further processing in the HOTT_ID_RX_EVENT telemetry sensor.
|
||
// Users may process warnings with a combination of logical switches and special funtions to announce the warning
|
||
// or lua scripts
|
||
|
||
#define DEVICE (packet[2])
|
||
#define PAGE (packet[3])
|
||
#define RXTEMP (packet[6] - 20)
|
||
#define RXEVENT (packet[12])
|
||
#define WARN (packet[14])
|
||
|
||
enum HoTTWarnDevices { // lists devices in order of priority
|
||
HOTT_WARN_RX = 0, // if two or more devices issue warnigs in the same le
|
||
HOTT_WARN_ESC, // polling cyc the device with the lower enum value wins
|
||
HOTT_WARN_GAM,
|
||
HOTT_WARN_EAM,
|
||
HOTT_WARN_VARIO,
|
||
HOTT_WARN_GPS,
|
||
HOTT_WARN_LAST // delimiter
|
||
};
|
||
|
||
static uint8_t warnings[HOTT_WARN_LAST] = {}; // to memorize the warnings status of each HoTT device
|
||
// until it gets updated again
|
||
|
||
if ( PAGE == 0 && DEVICE == HOTT_TELEM_RX) { // sending device is RX
|
||
switch (RXEVENT) { // fetch RX event parameter from RX telemetry data
|
||
case 0: // rx doesn't indicate an event
|
||
warnings[HOTT_WARN_RX] = 0; // translate to warning 0 (no warning)
|
||
break;
|
||
|
||
case 1: // low rx battery event
|
||
warnings[HOTT_WARN_RX] = 64; // translate to warning 64
|
||
break;
|
||
|
||
case 2: // rx temperature event, find reason
|
||
warnings[HOTT_WARN_RX] = // check rx temp
|
||
RXTEMP >= 50 ? 44: 43; // > 50 degrees, high temperature warning, translate to warning 44
|
||
break; // < 50 degrees, low temperature warning, translate to warning 43
|
||
|
||
default:
|
||
warnings[HOTT_WARN_RX] = 53; // other rx events -> translate to general receiver warning
|
||
}
|
||
} else {
|
||
if (PAGE > 0 && PAGE <= 4) { // sending device is other than rx
|
||
switch (DEVICE) {
|
||
case HOTT_TELEM_ESC: // sending device is ESC
|
||
warnings[HOTT_WARN_ESC] = WARN;
|
||
break;
|
||
|
||
case HOTT_TELEM_GAM: // sending device is GAM
|
||
warnings[HOTT_WARN_GAM] = WARN;
|
||
break;
|
||
|
||
case HOTT_TELEM_EAM: // sending device is EAM
|
||
warnings[HOTT_WARN_EAM] = WARN;
|
||
break;
|
||
|
||
case HOTT_TELEM_VARIO: // sending device is VARIO
|
||
warnings[HOTT_WARN_VARIO] = WARN;
|
||
break;
|
||
|
||
case HOTT_TELEM_GPS: // sending device is GPS
|
||
warnings[HOTT_WARN_GPS] = WARN;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
for(uint8_t i = 0; i < HOTT_WARN_LAST; i++) { // go through list of devices and see if warning was issued
|
||
uint8_t deviceWarn = warnings[i]; // using device priorities in the order of the HoTTWarnDevice enum
|
||
|
||
if (deviceWarn > 0 && // if warning was issued by device #i
|
||
(deviceWarn < 27 || deviceWarn > 36)) // always exclude climb rate beeps (meant for tx's without voice output)
|
||
return deviceWarn; // return warning
|
||
}
|
||
|
||
return 0; // return 0 (no warning)
|
||
}
|
||
|
||
void processHottPacket(const uint8_t * packet)
|
||
{
|
||
#if defined(LUA)
|
||
#define HOTT_MENU_NBR_PAGE 0x13
|
||
// Config menu consists of the different telem pages put all together
|
||
// [3] = config mennu page 0x00 to 0x12.
|
||
// Page X [4] = seems like all the telem pages with the same value are going together to make the full config menu text. Seen so far 'a', 'b', 'c', 'd'
|
||
// Page X [5..13] = 9 ascii chars to be displayed, char is highlighted when ascii|0x80
|
||
// Screen display is 21 characters large which means that once the first 21 chars are filled go to the begining of the next line
|
||
// Menu commands are sent through TX packets:
|
||
// packet[28]= 0xXF=>no key press, 0xXD=>down, 0xXB=>up, 0xX9=>enter, 0xXE=>right, 0xX7=>left with X=0, 9=Vario, A=GPS, B=Unknown, C=ESC, D=GAM, or E=EAM
|
||
// packet[29]= 0xX1/0xX9 with X=0 or X counting 0,1,1,2,2,..,9,9
|
||
if (Multi_Buffer && memcmp(Multi_Buffer, "HoTT", 4) == 0) {
|
||
// HoTT Lua script is running
|
||
if (Multi_Buffer[4] == 0xFF) {
|
||
// Init
|
||
memset(&Multi_Buffer[6], ' ', HOTT_MENU_NBR_PAGE * 9); // Clear text buffer
|
||
}
|
||
|
||
if (packet[2] == HOTT_TELEM_TEXT && packet[3] < HOTT_MENU_NBR_PAGE && (Multi_Buffer[5] & 0x80) && (Multi_Buffer[5] & 0x0F) >= 0x07) {
|
||
Multi_Buffer[4] = packet[4]; // Store detected sensors
|
||
memcpy(&Multi_Buffer[6 + packet[3] * 9], &packet[5], 9); // Store the received page in the buffer
|
||
}
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
struct HottGPSMinutes
|
||
{
|
||
uint16_t value: 14;
|
||
uint16_t isNegative: 1;
|
||
uint16_t spare: 1;
|
||
};
|
||
|
||
const HottSensor *sensor;
|
||
int32_t value;
|
||
static uint8_t prev_page = 0, prev_value = 0;
|
||
static HottGPSMinutes min = {};
|
||
int16_t deg = 0, sec = 0;
|
||
|
||
// Set RX Event (HoTT warnings)
|
||
value = processHoTTWarnings(packet);
|
||
sensor = getHottSensor(HOTT_ID_RX_EVENT);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RX_EVENT, 0, 0, value, sensor->unit, sensor->precision);
|
||
|
||
// Set TX RSSI Value
|
||
value = processHoTTdBm(packet[0]);
|
||
sensor = getHottSensor(HOTT_ID_TX_RSSI_DL);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TX_RSSI_DL, 0, 0, value, sensor->unit, sensor->precision);
|
||
|
||
// Set TX LQI Value
|
||
value = packet[1];
|
||
sensor = getHottSensor(HOTT_ID_TX_LQI_DL);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TX_LQI_DL, 0, 0, value, sensor->unit, sensor->precision);
|
||
|
||
switch (packet[2]) { // Telemetry type
|
||
case HOTT_TELEM_RX:
|
||
if (packet[3] == HOTT_PAGE_00) { // Telemetry page: only page 0 is for RX
|
||
// rx battery voltage
|
||
value = packet[5];
|
||
sensor = getHottSensor(HOTT_ID_RX_VLT);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RX_VLT, 0, HOTT_TELEM_RX, value, sensor->unit, sensor->precision);
|
||
|
||
// rx temperature
|
||
value = packet[6] - 20;
|
||
sensor = getHottSensor(HOTT_ID_RX_TMP);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RX_TMP, 0, HOTT_TELEM_RX, value, sensor->unit, sensor->precision);
|
||
|
||
// uplink RSSI
|
||
value = processHoTTdBm(packet[7]);
|
||
sensor = getHottSensor(HOTT_ID_RX_RSSI_UL);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RX_RSSI_UL, 0, HOTT_TELEM_RX, value, sensor->unit, sensor->precision);
|
||
|
||
// uplink quality
|
||
value = packet[8];
|
||
|
||
telemetryData.rssi.set(value);
|
||
if (value > 0)
|
||
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
|
||
|
||
sensor = getHottSensor(HOTT_ID_RX_LQI_UL);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RX_LQI_UL, 0, HOTT_TELEM_RX, value, sensor->unit, sensor->precision);
|
||
|
||
// RX_lowest voltage
|
||
value = packet[9];
|
||
sensor = getHottSensor(HOTT_ID_RX_BAT_MIN);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RX_BAT_MIN, 0, HOTT_TELEM_RX, value, sensor->unit, sensor->precision);
|
||
|
||
// RX_VPACK
|
||
value = packet[10] + (packet[11] << 8);
|
||
sensor = getHottSensor(HOTT_ID_RX_VPCK);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RX_VPCK, 0, 0, value, sensor->unit, sensor->precision);
|
||
}
|
||
break;
|
||
|
||
case HOTT_TELEM_VARIO:
|
||
// https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L240
|
||
switch (packet[3]) { // Telemetry page 1,2,3,4
|
||
case HOTT_PAGE_01:
|
||
// Vario altitude
|
||
value = packet[6] + (packet[7] << 8) - 500;
|
||
sensor = getHottSensor(HOTT_ID_VARIO_ALT);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO_ALT, 0, HOTT_TELEM_VARIO, value, sensor->unit, sensor->precision);
|
||
|
||
// Vario vertical velocity
|
||
value = packet[12] + (packet[13] << 8) - 30000;
|
||
sensor = getHottSensor(HOTT_ID_VARIO_VV);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO_VV, 0, HOTT_TELEM_VARIO, value, sensor->unit, sensor->precision);
|
||
break;
|
||
|
||
case HOTT_PAGE_02:
|
||
break;
|
||
|
||
case HOTT_PAGE_03:
|
||
break;
|
||
|
||
case HOTT_PAGE_04:
|
||
// Vario heading
|
||
value = packet[12] * 2;
|
||
sensor = getHottSensor(HOTT_ID_VARIO_HDG);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO_HDG, 0, HOTT_TELEM_VARIO, value, sensor->unit, sensor->precision);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case HOTT_TELEM_GPS:
|
||
// https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L378
|
||
switch (packet[3]) { // Telemetry page 1,2,3,4
|
||
case HOTT_PAGE_01:
|
||
// GPS heading
|
||
value = packet[7] * 2;
|
||
sensor = getHottSensor(HOTT_ID_GPS_HDG);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_HDG, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
|
||
|
||
// GPS speed
|
||
value = packet[8] + (packet[9] << 8);
|
||
sensor = getHottSensor(HOTT_ID_GPS_SPEED);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_SPEED, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
|
||
|
||
// GPS latitude
|
||
min.value = (int16_t) (packet[11] + (packet[12] << 8));
|
||
if (packet[10] == 1) {
|
||
min.isNegative = true;
|
||
}
|
||
break;
|
||
|
||
case HOTT_PAGE_02:
|
||
if (prev_page == ((HOTT_TELEM_GPS << 4) | HOTT_PAGE_01)) {
|
||
// packet[4 ] uint8_t pos_NS_sec_H; //#14
|
||
deg = min.value / 100;
|
||
min.value = min.value - deg * 100;
|
||
sec = prev_value + (packet[4] << 8);
|
||
value = deg * 1000000 + (min.value * 1000000 + sec * 100) / 60;
|
||
if (min.isNegative) {
|
||
value = -value;
|
||
}
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_LL, 0, HOTT_TELEM_GPS, value, UNIT_GPS_LATITUDE, 0);
|
||
}
|
||
|
||
// GPS longitude
|
||
min.value = (int16_t) (packet[6] + (packet[7] << 8));
|
||
sec = (int16_t) (packet[8] + (packet[9] << 8));
|
||
deg = min.value / 100;
|
||
min.value = min.value - deg * 100;
|
||
value = deg * 1000000 + (min.value * 1000000 + sec * 100) / 60;
|
||
if (packet[5] == 1) {
|
||
value = -value;
|
||
}
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_LL, 0, HOTT_TELEM_GPS, value, UNIT_GPS_LONGITUDE, 0);
|
||
|
||
// GPS distance to model
|
||
value = packet[10] + (packet[11] << 8);
|
||
sensor = getHottSensor(HOTT_ID_GPS_DST);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_DST, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
|
||
|
||
// GPS altitude
|
||
value = packet[12] + (packet[13] << 8) - 500;
|
||
sensor = getHottSensor(HOTT_ID_GPS_ALT);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_ALT, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
|
||
break;
|
||
|
||
case HOTT_PAGE_03:
|
||
// GPS vertical velocity
|
||
value = packet[4] + (packet[5] << 8) - 30000;
|
||
sensor = getHottSensor(HOTT_ID_GPS_VV);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_VV, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
|
||
|
||
// GPS number of satellites
|
||
value = packet[7];
|
||
sensor = getHottSensor(HOTT_ID_GPS_NSATS);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_NSATS, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
|
||
|
||
// packet[8 ] uint8_t gps_fix_char; //#28 GPS fix character. display, 'D' = DGPS, '2' = 2D, '3' = 3D, '-' = no fix. Where appears this char???
|
||
// packet[9 ] uint8_t home_direction;//#29 direction from starting point to Model position (2 degree steps)
|
||
// packet[10] uint8_t angle_roll; //#30 angle roll in 2 degree steps
|
||
// packet[11] uint8_t angle_nick; //#31 angle in 2degree steps
|
||
// packet[12] uint8_t angle_compass; //#32 angle in 2degree steps. 1 = 2�, 255 = - 2� (1 uint8_t) North = 0�
|
||
// packet[13] uint8_t gps_time_h; //#33 UTC time hours
|
||
break;
|
||
|
||
case HOTT_PAGE_04:
|
||
// packet[4 ] uint8_t gps_time_m; //#34 UTC time minutes
|
||
// packet[5 ] uint8_t gps_time_s; //#35 UTC time seconds
|
||
// packet[6 ] uint8_t gps_time_sss; //#36 UTC time milliseconds
|
||
// packet[7 ] uint8_t msl_altitude_L;//#37 mean sea level altitude
|
||
// packet[8 ] uint8_t msl_altitude_H;//#38
|
||
// packet[9 ] uint8_t vibration; //#39 vibrations level in %
|
||
// packet[10] uint8_t free_char1; //#40 appears right to home distance
|
||
// packet[11] uint8_t free_char2; //#41 appears right to home direction
|
||
// packet[12] uint8_t free_char3; //#42 GPS ASCII D=DGPS 2=2D 3=3D -=No Fix
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case HOTT_TELEM_ESC:
|
||
// https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L454
|
||
switch (packet[3]) { // Telemetry page 1,2,3,4
|
||
case HOTT_PAGE_01:
|
||
// ESC battery voltage
|
||
value = packet[7] + (packet[8] << 8);
|
||
sensor = getHottSensor(HOTT_ID_ESC_VLT);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_VLT, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
|
||
|
||
// ESC battery capacity consumed
|
||
value = (packet[11] + (packet[12] << 8)) * 10;
|
||
sensor = getHottSensor(HOTT_ID_ESC_CAP);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_CAP, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
|
||
|
||
// ESC temperature
|
||
value = packet[13] - 20;
|
||
sensor = getHottSensor(HOTT_ID_ESC_TMP);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_TMP, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
|
||
break;
|
||
|
||
case HOTT_PAGE_02:
|
||
// ESC battery current
|
||
value = packet[5] + (packet[6] << 8);
|
||
sensor = getHottSensor(HOTT_ID_ESC_CUR);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_CUR, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
|
||
|
||
// ESC motor rpm
|
||
value = (packet[9] + (packet[10] << 8)) * 10;
|
||
sensor = getHottSensor(HOTT_ID_ESC_RPM);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_RPM, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
|
||
break;
|
||
|
||
case HOTT_PAGE_03:
|
||
// ESC BEC voltage
|
||
value = packet[8];
|
||
sensor = getHottSensor(HOTT_ID_ESC_BEC_VLT);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_BEC_VLT, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
|
||
|
||
// ESC BEC current
|
||
value = packet[10];
|
||
sensor = getHottSensor(HOTT_ID_ESC_BEC_CUR);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_BEC_CUR, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
|
||
break;
|
||
|
||
case HOTT_PAGE_04:
|
||
// ESC BEC temperature
|
||
value = packet[4] - 20;
|
||
sensor = getHottSensor(HOTT_ID_ESC_BEC_TMP);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_BEC_TMP, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
|
||
|
||
// ESC motor temp or external temperature sensor
|
||
value = packet[6] - 20;
|
||
sensor = getHottSensor(HOTT_ID_ESC_MOT_TMP);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_MOT_TMP, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case HOTT_TELEM_GAM:
|
||
// https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L151
|
||
switch (packet[3]) { // Telemetry page 1,2,3,4
|
||
case HOTT_PAGE_01:
|
||
// GAM cell voltages
|
||
sensor = getHottSensor(HOTT_ID_GAM_CELS);
|
||
value = packet[7] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_CELS, 0, HOTT_TELEM_GAM, 0 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[8] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_CELS, 0, HOTT_TELEM_GAM, 1 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[9] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_CELS, 0, HOTT_TELEM_GAM, 2 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[10] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_CELS, 0, HOTT_TELEM_GAM, 3 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[11] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_CELS, 0, HOTT_TELEM_GAM, 4 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[12] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_CELS, 0, HOTT_TELEM_GAM, 5 << 16 | value, sensor->unit, sensor->precision);
|
||
|
||
// packet[13] uint8_t batt1_L; //#13 battery 1 voltage LSB value. 0.1V steps. 50 = 5.5V
|
||
break;
|
||
|
||
case HOTT_PAGE_02:
|
||
if (prev_page == ((HOTT_TELEM_GAM << 4) | HOTT_PAGE_01)) {
|
||
// GAM voltage battery 1
|
||
value = prev_value + (packet[4] << 8);
|
||
sensor = getHottSensor(HOTT_ID_GAM_VLT1);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_VLT1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
}
|
||
|
||
// GAM voltage battery 2
|
||
value = packet[5] + (packet[6] << 8);
|
||
sensor = getHottSensor(HOTT_ID_GAM_VLT2);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_VLT2, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// GAM temperature 1
|
||
value = packet[7] - 20;
|
||
sensor = getHottSensor(HOTT_ID_GAM_TMP1);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_TMP1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// GAM temperature 2
|
||
value = packet[8] - 20;
|
||
sensor = getHottSensor(HOTT_ID_GAM_TMP2);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_TMP2, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// GAM fuel percentage
|
||
value = packet[9];
|
||
sensor = getHottSensor(HOTT_ID_GAM_FUEL);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_FUEL, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// packet[10] uint8_t fuel_ml_L; //#20 Fuel in ml scale. Full = 65535!
|
||
// packet[11] uint8_t fuel_ml_H; //#21
|
||
|
||
// GAM rpm 1
|
||
value = (packet[12] + (packet[13] << 8)) * 10;
|
||
sensor = getHottSensor(HOTT_ID_GAM_RPM1);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_RPM1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
break;
|
||
|
||
case HOTT_PAGE_03:
|
||
// GAM altitude
|
||
value = packet[4] + (packet[5] << 8) - 500;
|
||
sensor = getHottSensor(HOTT_ID_GAM_ALT);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_ALT, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// GAM vertical velocity
|
||
value = packet[6] + (packet[7] << 8) - 30000;
|
||
sensor = getHottSensor(HOTT_ID_GAM_VV);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_VV, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// packet[8 ] uint8_t climbrate3s; //#28 climb rate in m/3sec. Value of 120 = 0m/3sec
|
||
|
||
// GAM current
|
||
value = packet[9] + (packet[10] << 8);
|
||
sensor = getHottSensor(HOTT_ID_GAM_CUR);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_CUR, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// GAM voltage battery 3
|
||
value = packet[11] + (packet[12] << 8);
|
||
sensor = getHottSensor(HOTT_ID_GAM_VLT3);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_VLT3, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// packet[13] uint8_t batt_cap_L; //#33 used battery capacity in 10mAh steps
|
||
break;
|
||
|
||
case HOTT_PAGE_04:
|
||
// GAM capacity
|
||
if (prev_page == ((HOTT_TELEM_GAM << 4) | HOTT_PAGE_03)) {
|
||
value = (prev_value + (packet[4] << 8)) * 10;
|
||
sensor = getHottSensor(HOTT_ID_GAM_CAP);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_CAP, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
}
|
||
|
||
// GAM speed
|
||
value = packet[5] + (packet[6] << 8);
|
||
sensor = getHottSensor(HOTT_ID_GAM_SPEED);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_SPEED, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// packet[7 ] uint8_t min_cell_volt; //#37 minimum cell voltage in 2mV steps. 124 = 2,48V
|
||
// packet[8 ] uint8_t min_cell_volt_num; //#38 number of the cell with the lowest voltage
|
||
|
||
// GAM rpm 2
|
||
value = (packet[9] + (packet[10] << 8)) * 10;
|
||
sensor = getHottSensor(HOTT_ID_GAM_RPM2);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GAM_RPM2, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
|
||
|
||
// packet[11] uint8_t general_error_number;//#41 Voice error == 12 (max. speed). TODO: more docu
|
||
// packet[12] uint8_t pressure; //#42 Pressure up to 16bar. 0,1bar scale. 20 = 2bar
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case HOTT_TELEM_EAM:
|
||
// https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L288
|
||
switch (packet[3]) { // Telemetry page 1,2,3,4
|
||
case HOTT_PAGE_01:
|
||
// EAM cell voltages 1-7 (1 to 6 transferred)
|
||
sensor = getHottSensor(HOTT_ID_EAM_CELS_L);
|
||
value = packet[7] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_L, 0, HOTT_TELEM_EAM, 0 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[8] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_L, 0, HOTT_TELEM_EAM, 1 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[9] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_L, 0, HOTT_TELEM_EAM, 2 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[10] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_L, 0, HOTT_TELEM_EAM, 3 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[11] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_L, 0, HOTT_TELEM_EAM, 4 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[12] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_L, 0, HOTT_TELEM_EAM, 5 << 16 | value, sensor->unit, sensor->precision);
|
||
// value = packet[13] << 1;
|
||
// if(value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_L, 0, HOTT_TELEM_EAM, 6 << 16 | value, sensor->unit, sensor->precision);
|
||
break;
|
||
|
||
case HOTT_PAGE_02:
|
||
// EAM cell voltages 8-14 (8 to 13 transferred)
|
||
sensor = getHottSensor(HOTT_ID_EAM_CELS_H);
|
||
value = packet[4] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_H, 0, HOTT_TELEM_EAM, 0 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[5] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_H, 0, HOTT_TELEM_EAM, 1 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[6] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_H, 0, HOTT_TELEM_EAM, 2 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[7] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_H, 0, HOTT_TELEM_EAM, 3 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[8] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_H, 0, HOTT_TELEM_EAM, 4 << 16 | value, sensor->unit, sensor->precision);
|
||
value = packet[9] << 1;
|
||
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_H, 0, HOTT_TELEM_EAM, 5 << 16 | value, sensor->unit, sensor->precision);
|
||
//value = packet[10] << 1;
|
||
//if(value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CELS_H, 0, HOTT_TELEM_EAM, 13 << 16 | value, sensor->unit, sensor->precision);
|
||
|
||
// EAM voltage battery 1
|
||
value = packet[11] + (packet[12] << 8);
|
||
sensor = getHottSensor(HOTT_ID_EAM_VLT1);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_VLT1, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
|
||
// packet[13] uint8_t batt2_voltage_L; //#23 battery 2 voltage lower value in 100mv steps, 50=5V. optionally cell8_H value. 0.02V steps
|
||
break;
|
||
|
||
case HOTT_PAGE_03:
|
||
// EAM voltage battery 2
|
||
if (prev_page == ((HOTT_TELEM_EAM << 4) | HOTT_PAGE_02)) {
|
||
value = prev_value + (packet[4] << 8);
|
||
sensor = getHottSensor(HOTT_ID_EAM_VLT2);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_VLT2, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
}
|
||
|
||
// EAM temperature 1
|
||
value = packet[5] - 20;
|
||
sensor = getHottSensor(HOTT_ID_EAM_TMP1);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_TMP1, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
|
||
// EAM temperature 2
|
||
value = packet[6] - 20;
|
||
sensor = getHottSensor(HOTT_ID_EAM_TMP2);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_TMP2, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
|
||
//EAM altitude
|
||
value = packet[7] + (packet[8] << 8) - 500;
|
||
sensor = getHottSensor(HOTT_ID_EAM_ALT);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_ALT, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
|
||
// EAM current
|
||
value = packet[9] + (packet[10] << 8);
|
||
sensor = getHottSensor(HOTT_ID_EAM_CUR);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CUR, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
|
||
// EAM voltage battery 3 (main)
|
||
value = packet[11] + (packet[12] << 8);
|
||
sensor = getHottSensor(HOTT_ID_EAM_VLT3);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_VLT3, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
// packet[13] uint8_t batt_cap_L; //#33 used battery capacity in 10mAh steps
|
||
break;
|
||
|
||
case HOTT_PAGE_04:
|
||
// EAM capacity
|
||
if (prev_page == ((HOTT_TELEM_EAM << 4) | HOTT_PAGE_03)) {
|
||
value = (prev_value + (packet[4] << 8)) * 10;
|
||
sensor = getHottSensor(HOTT_ID_EAM_CAP);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_CAP, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
}
|
||
|
||
// EAM vertical velocity
|
||
value = packet[5] + (packet[6] << 8) - 30000;
|
||
sensor = getHottSensor(HOTT_ID_EAM_VV);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_VV, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
|
||
// packet[7 ] uint8_t climbrate3s; //#37 climbrate in m/3sec. Value of 120 = 0m/3sec
|
||
|
||
// EAM rpm
|
||
value = (packet[8] + (packet[9] << 8)) * 10;
|
||
sensor = getHottSensor(HOTT_ID_EAM_RPM);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_RPM, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
|
||
// packet[10] uint8_t electric_min; //#40 Electric minutes. Time does start, when motor current is > 3 A
|
||
// packet[11] uint8_t electric_sec; //#41
|
||
|
||
// EAM speed
|
||
value = packet[12] + (packet[13] << 8);
|
||
sensor = getHottSensor(HOTT_ID_EAM_SPEED);
|
||
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_EAM_SPEED, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
prev_page = (packet[2] << 4) | packet[3]; // concatenate telemetry type and page
|
||
prev_value = packet[13]; // page overflow
|
||
}
|
||
|
||
void hottSetDefault(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 HottSensor * sensor = getHottSensor(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 {
|
||
telemetrySensor.init(id);
|
||
}
|
||
|
||
storageDirty(EE_MODEL);
|
||
}
|