4 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
19 packet[0] = TX RSSI value
20 packet[1] = TX LQI value
21 packet[2] = frame number
22 packet[3-12] telemetry data
24 The frame number takes the following values: 0x00, 0x01, 0x02, 0x03 and 0x04. The frames can be present or not, they also do not have to follow each others.
25 Here is a description of the telemetry data for each frame number:
28 [4] = RX_Voltage*10 in V
29 [5] = Temperature-20 in °C
33 [9,10] = [10]*256+[9]=max lost packet time in ms, max value seems 2s=0x7D0
45 const TelemetryUnit unit
;
46 const uint8_t precision
;
59 #define HOTT_TELEM_NORMAL 0x00
60 #define HOTT_TELEM_BIND 0x40
61 #define HOTT_TELEM_MENU 0x80
63 // telemetry sensors ID
66 HOTT_ID_RX_VOLTAGE
= 0x0004,// RX_Batt Voltage
67 HOTT_ID_TEMP1
= 0x0005, // RX Temperature sensor
68 TX_RSSI_ID
= 0xFF00, // Pseudo id outside 1 byte range of Hott sensors
69 TX_LQI_ID
= 0xFF01, // Pseudo id outside 1 byte range of Hott sensors
70 RX_RSSI_ID
= 0xFF02, // Pseudo id outside 1 byte range of Hott sensors
71 RX_LQI_ID
= 0xFF03, // Pseudo id outside 1 byte range of Hott sensors
74 const HottSensor hottSensors
[] = {
76 {HOTT_ID_RX_VOLTAGE
, ZSTR_BATT
, UNIT_VOLTS
, 1}, // RX_Batt Voltage
77 {HOTT_ID_TEMP1
, ZSTR_TEMP1
, UNIT_CELSIUS
, 0}, // RX Temperature sensor
82 {TX_RSSI_ID
, ZSTR_TX_RSSI
, UNIT_RAW
, 0}, // Pseudo id outside 1 byte range of Hott sensors
83 {TX_LQI_ID
, ZSTR_TX_QUALITY
, UNIT_RAW
, 0}, // Pseudo id outside 1 byte range of Hott sensors
84 {RX_RSSI_ID
, ZSTR_RSSI
, UNIT_DB
, 0}, // RX RSSI
85 {RX_LQI_ID
, ZSTR_RX_QUALITY
, UNIT_RAW
, 0}, // RX LQI
86 {0x00, NULL
, UNIT_RAW
, 0}, // sentinel
89 const HottSensor
* getHottSensor(uint16_t id
)
91 for (const HottSensor
* sensor
= hottSensors
; sensor
->id
; sensor
++) {
98 void processHottPacket(const uint8_t * packet
)
101 setTelemetryValue(PROTOCOL_TELEMETRY_HOTT
, TX_RSSI_ID
, 0, 0, packet
[0]>>1, UNIT_RAW
, 0);
103 setTelemetryValue(PROTOCOL_TELEMETRY_HOTT
, TX_LQI_ID
, 0, 0, packet
[1], UNIT_RAW
, 0);
106 #define HOTT_MENU_NBR_PAGE 0x13
107 // Config menu consists of the different telem pages put all together
108 // [3] = config mennu page 0x00 to 0x12.
109 // 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'
110 // Page X [5..13] = 9 ascii chars to be displayed, char is highlighted when ascii|0x80
111 // Screen display is 21 characters large which means that once the first 21 chars are filled go to the begining of the next line
112 // Menu commands are sent through TX packets:
113 // packet[28]= 0xXF=>no key press, 0xXD=>down, 0xXB=>up, 0xX9=>enter, 0xXE=>right, 0xX7=>left with X=0 or D
114 // packet[29]= 0xX1/0xX9 with X=0 or X counting 0,1,1,2,2,..,9,9
115 if (Multi_Buffer
&& memcmp(Multi_Buffer
, "HoTT", 4) == 0) {
116 // HoTT Lua script is running
117 if (Multi_Buffer
[4] == 0xFF) {
119 memset(&Multi_Buffer
[6], ' ', HOTT_MENU_NBR_PAGE
* 9); // Clear text buffer
122 if (packet
[3] < HOTT_MENU_NBR_PAGE
&& Multi_Buffer
[5] >= 0xD7 && Multi_Buffer
[5] <= 0xDF) {
123 Multi_Buffer
[4] = packet
[4]; // Store current menu being received
124 memcpy(&Multi_Buffer
[6 + packet
[3] * 9], &packet
[5], 9); // Store the received page in the buffer
130 const HottSensor
* sensor
;
133 if (packet
[2] == HOTT_TELEM_NORMAL
) {
138 sensor
= getHottSensor(HOTT_ID_RX_VOLTAGE
);
139 setTelemetryValue(PROTOCOL_TELEMETRY_HOTT
, HOTT_ID_RX_VOLTAGE
, 0, 0, value
, sensor
->unit
, sensor
->precision
);
141 value
= packet
[6] - 20;
142 sensor
= getHottSensor(HOTT_ID_TEMP1
);
143 setTelemetryValue(PROTOCOL_TELEMETRY_HOTT
, HOTT_ID_TEMP1
, 0, 0, value
, sensor
->unit
, sensor
->precision
);
145 setTelemetryValue(PROTOCOL_TELEMETRY_HOTT
, RX_RSSI_ID
, 0, 0, packet
[7], UNIT_DB
, 0);
147 telemetryData
.rssi
.set(packet
[8]);
149 telemetryStreaming
= TELEMETRY_TIMEOUT10ms
;
150 setTelemetryValue(PROTOCOL_TELEMETRY_HOTT
, RX_LQI_ID
, 0, 0, packet
[8], UNIT_RAW
, 0);
155 value
= (packet
[7] << 24) | (packet
[6] << 16) | (packet
[5] << 8) | packet
[4];
156 setTelemetryValue(PROTOCOL_TELEMETRY_HOTT
, 0xFE00 | packet
[3], 0, 0, value
, UNIT_RAW
, 0);
162 void hottSetDefault(int index
, uint16_t id
, uint8_t subId
, uint8_t instance
)
164 TelemetrySensor
&telemetrySensor
= g_model
.telemetrySensors
[index
];
165 telemetrySensor
.id
= id
;
166 telemetrySensor
.subId
= subId
;
167 telemetrySensor
.instance
= instance
;
169 const HottSensor
* sensor
= getHottSensor(id
);
171 TelemetryUnit unit
= sensor
->unit
;
172 uint8_t prec
= min
<uint8_t>(2, sensor
->precision
);
173 telemetrySensor
.init(sensor
->name
, unit
, prec
);
174 if (unit
== UNIT_RPMS
) {
175 telemetrySensor
.custom
.ratio
= 1;
176 telemetrySensor
.custom
.offset
= 1;
180 telemetrySensor
.init(id
);
183 storageDirty(EE_MODEL
);