1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-19 22:35:12 +03:00

Graupner HoTT: full telemetry (#7627)

This commit is contained in:
pascallanger 2020-05-30 12:11:36 +02:00 committed by GitHub
parent fe9750fc0c
commit fa1e6f087c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 742 additions and 133 deletions

View file

@ -21,19 +21,41 @@
-- To start operation: -- To start operation:
-- Write "HoTT" at address 0..3 -- Write "HoTT" at address 0..3
-- Write 0xFF at address 4 will request the buffer to be cleared -- Write 0xFF at address 4 will request the buffer to be cleared
-- Write 0xDF at address 5 -- Write 0x0F at address 5
-- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters -- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters
-- by 8 lines -- by 8 lines
-- Write at address 5 sends an order to the RX: 0xDF=start, 0xD7=prev page, -- Write at address 5 sends an order to the RX: 0xXF=start, 0xX7=prev page,
-- 0xDE=next page, 0xD9=enter, 0xDD=next or 0xDB=prev -- 0xXE=next page, 0xX9=enter, 0xXD=next or 0xXB=prev with X being the sensor
-- to request data from 8=RX only, 9=Vario, A=GPS, B=Cust, C=ESC, D=GAM, E=EAM
-- Write at address 4 the value 0xFF will request the buffer to be cleared -- Write at address 4 the value 0xFF will request the buffer to be cleared
-- !! Before exiting the script must write 0 at address 0 for normal operation !! -- !! Before exiting the script must write 0 at address 0 for normal operation !!
--############################################################################### --###############################################################################
HoTT_Sensor = 0
Timer_128 = 100
local function HoTT_Release() local function HoTT_Release()
multiBuffer( 0, 0 ) multiBuffer( 0, 0 )
end end
local function HoTT_Send(button)
multiBuffer( 5, 0x80+(HoTT_Sensor*16) + button)
end
local function HoTT_Sensor_Inc()
local detected_sensors=multiBuffer( 4 )
local a
if detected_sensors ~= 0xFF then
repeat
HoTT_Sensor=(HoTT_Sensor+1)%7 -- Switch to next sensor
if HoTT_Sensor ~= 0 then
a = math.floor(detected_sensors/ (2^(HoTT_Sensor-1))) -- shift right
end
until HoTT_Sensor==0 or a % 2 == 1
HoTT_Send( 0x0F )
end
end
local function HoTT_Draw_LCD() local function HoTT_Draw_LCD()
local i local i
local value local value
@ -41,12 +63,14 @@ local function HoTT_Draw_LCD()
local result local result
local offset=0 local offset=0
local sensor_name = { "", "+Vario", "+GPS", "+Cust", "+ESC", "+GAM", "+EAM" }
lcd.clear() lcd.clear()
if LCD_W == 480 then if LCD_W == 480 then
--Draw title --Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, "Graupner HoTT RX configuration", MENU_TITLE_COLOR) lcd.drawText(1, 5, "Graupner HoTT: config RX" .. sensor_name[HoTT_Sensor+1] .. " - Menu cycle Sensors", MENU_TITLE_COLOR)
--Draw RX Menu --Draw RX Menu
if multiBuffer( 4 ) == 0xFF then if multiBuffer( 4 ) == 0xFF then
lcd.drawText(10,50,"No HoTT telemetry...", BLINK) lcd.drawText(10,50,"No HoTT telemetry...", BLINK)
@ -56,9 +80,9 @@ local function HoTT_Draw_LCD()
value=multiBuffer( line*21+6+i ) value=multiBuffer( line*21+6+i )
if value > 0x80 then if value > 0x80 then
value = value - 0x80 value = value - 0x80
lcd.drawText(10+i*16,32+16*line,string.char(value).." ",INVERS) lcd.drawText(10+i*16,32+20*line,string.char(value).." ",INVERS)
else else
lcd.drawText(10+i*16,32+16*line,string.char(value)) lcd.drawText(10+i*16,32+20*line,string.char(value))
end end
end end
end end
@ -68,6 +92,14 @@ local function HoTT_Draw_LCD()
if multiBuffer( 4 ) == 0xFF then if multiBuffer( 4 ) == 0xFF then
lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE) lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE)
else else
if Timer_128 ~= 0 then
--Intro page
Timer_128 = Timer_128 - 1
lcd.drawScreenTitle("Graupner Hott",0,0)
lcd.drawText(2,17,"Configuration of RX" .. sensor_name[HoTT_Sensor+1] ,SMLSIZE)
lcd.drawText(2,37,"Press menu to cycle Sensors" ,SMLSIZE)
else
--Menu page
for line = 0, 7, 1 do for line = 0, 7, 1 do
for i = 0, 21-1, 1 do for i = 0, 21-1, 1 do
value=multiBuffer( line*21+6+i ) value=multiBuffer( line*21+6+i )
@ -82,6 +114,7 @@ local function HoTT_Draw_LCD()
end end
end end
end end
end
-- Init -- Init
local function HoTT_Init() local function HoTT_Init()
@ -98,7 +131,10 @@ local function HoTT_Init()
--Request init of the RX buffer --Request init of the RX buffer
multiBuffer( 4, 0xFF ) multiBuffer( 4, 0xFF )
--Request RX to send the config menu --Request RX to send the config menu
multiBuffer( 5, 0xDF ) HoTT_Send( 0x0F )
HoTT_Sensor = 0;
HoTT_Detected_Sensors=0;
Timer_128 = 100
end end
-- Main -- Main
@ -111,18 +147,21 @@ local function HoTT_Run(event)
return 2 return 2
else else
if event == EVT_VIRTUAL_PREV_PAGE then if event == EVT_VIRTUAL_PREV_PAGE then
killEvents(event); killEvents(event)
multiBuffer( 5, 0xD7 ) HoTT_Send( 0x07 )
elseif event == EVT_VIRTUAL_NEXT_PAGE then
multiBuffer( 5, 0xDE )
elseif event == EVT_VIRTUAL_ENTER then elseif event == EVT_VIRTUAL_ENTER then
multiBuffer( 5, 0xD9 ) HoTT_Send( 0x09 )
elseif event == EVT_VIRTUAL_NEXT then
multiBuffer( 5, 0xDD )
elseif event == EVT_VIRTUAL_PREV then elseif event == EVT_VIRTUAL_PREV then
multiBuffer( 5, 0xDB ) HoTT_Send( 0x0B )
elseif event == EVT_VIRTUAL_NEXT then
HoTT_Send( 0x0D )
elseif event == EVT_VIRTUAL_NEXT_PAGE then
HoTT_Send( 0x0E )
elseif event == EVT_VIRTUAL_MENU then
Timer_128 = 100
HoTT_Sensor_Inc()
else else
multiBuffer( 5, 0xDF ) HoTT_Send( 0x0F )
end end
HoTT_Draw_LCD() HoTT_Draw_LCD()
return 0 return 0

View file

@ -21,19 +21,41 @@
-- To start operation: -- To start operation:
-- Write "HoTT" at address 0..3 -- Write "HoTT" at address 0..3
-- Write 0xFF at address 4 will request the buffer to be cleared -- Write 0xFF at address 4 will request the buffer to be cleared
-- Write 0xDF at address 5 -- Write 0x0F at address 5
-- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters -- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters
-- by 8 lines -- by 8 lines
-- Write at address 5 sends an order to the RX: 0xDF=start, 0xD7=prev page, -- Write at address 5 sends an order to the RX: 0xXF=start, 0xX7=prev page,
-- 0xDE=next page, 0xD9=enter, 0xDD=next or 0xDB=prev -- 0xXE=next page, 0xX9=enter, 0xXD=next or 0xXB=prev with X being the sensor
-- to request data from 8=RX only, 9=Vario, A=GPS, B=Cust, C=ESC, D=GAM, E=EAM
-- Write at address 4 the value 0xFF will request the buffer to be cleared -- Write at address 4 the value 0xFF will request the buffer to be cleared
-- !! Before exiting the script must write 0 at address 0 for normal operation !! -- !! Before exiting the script must write 0 at address 0 for normal operation !!
--############################################################################### --###############################################################################
HoTT_Sensor = 0
Timer_128 = 100
local function HoTT_Release() local function HoTT_Release()
multiBuffer( 0, 0 ) multiBuffer( 0, 0 )
end end
local function HoTT_Send(button)
multiBuffer( 5, 0x80+(HoTT_Sensor*16) + button)
end
local function HoTT_Sensor_Inc()
local detected_sensors=multiBuffer( 4 )
local a
if detected_sensors ~= 0xFF then
repeat
HoTT_Sensor=(HoTT_Sensor+1)%7 -- Switch to next sensor
if HoTT_Sensor ~= 0 then
a = math.floor(detected_sensors/ (2^(HoTT_Sensor-1))) -- shift right
end
until HoTT_Sensor==0 or a % 2 == 1
HoTT_Send( 0x0F )
end
end
local function HoTT_Draw_LCD() local function HoTT_Draw_LCD()
local i local i
local value local value
@ -41,12 +63,14 @@ local function HoTT_Draw_LCD()
local result local result
local offset=0 local offset=0
local sensor_name = { "", "+Vario", "+GPS", "+Cust", "+ESC", "+GAM", "+EAM" }
lcd.clear() lcd.clear()
if LCD_W == 480 then if LCD_W == 480 then
--Draw title --Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, "Graupner HoTT RX configuration", MENU_TITLE_COLOR) lcd.drawText(1, 5, "Graupner HoTT: config RX" .. sensor_name[HoTT_Sensor+1] .. " - Menu cycle Sensors", MENU_TITLE_COLOR)
--Draw RX Menu --Draw RX Menu
if multiBuffer( 4 ) == 0xFF then if multiBuffer( 4 ) == 0xFF then
lcd.drawText(10,50,"No HoTT telemetry...", BLINK) lcd.drawText(10,50,"No HoTT telemetry...", BLINK)
@ -56,9 +80,9 @@ local function HoTT_Draw_LCD()
value=multiBuffer( line*21+6+i ) value=multiBuffer( line*21+6+i )
if value > 0x80 then if value > 0x80 then
value = value - 0x80 value = value - 0x80
lcd.drawText(10+i*16,32+16*line,string.char(value).." ",INVERS) lcd.drawText(10+i*16,32+20*line,string.char(value).." ",INVERS)
else else
lcd.drawText(10+i*16,32+16*line,string.char(value)) lcd.drawText(10+i*16,32+20*line,string.char(value))
end end
end end
end end
@ -68,6 +92,14 @@ local function HoTT_Draw_LCD()
if multiBuffer( 4 ) == 0xFF then if multiBuffer( 4 ) == 0xFF then
lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE) lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE)
else else
if Timer_128 ~= 0 then
--Intro page
Timer_128 = Timer_128 - 1
lcd.drawScreenTitle("Graupner Hott",0,0)
lcd.drawText(2,17,"Configuration of RX" .. sensor_name[HoTT_Sensor+1] ,SMLSIZE)
lcd.drawText(2,37,"Press menu to cycle Sensors" ,SMLSIZE)
else
--Menu page
for line = 0, 7, 1 do for line = 0, 7, 1 do
for i = 0, 21-1, 1 do for i = 0, 21-1, 1 do
value=multiBuffer( line*21+6+i ) value=multiBuffer( line*21+6+i )
@ -82,6 +114,7 @@ local function HoTT_Draw_LCD()
end end
end end
end end
end
-- Init -- Init
local function HoTT_Init() local function HoTT_Init()
@ -98,7 +131,10 @@ local function HoTT_Init()
--Request init of the RX buffer --Request init of the RX buffer
multiBuffer( 4, 0xFF ) multiBuffer( 4, 0xFF )
--Request RX to send the config menu --Request RX to send the config menu
multiBuffer( 5, 0xDF ) HoTT_Send( 0x0F )
HoTT_Sensor = 0;
HoTT_Detected_Sensors=0;
Timer_128 = 100
end end
-- Main -- Main
@ -111,18 +147,21 @@ local function HoTT_Run(event)
return 2 return 2
else else
if event == EVT_VIRTUAL_PREV_PAGE then if event == EVT_VIRTUAL_PREV_PAGE then
killEvents(event); killEvents(event)
multiBuffer( 5, 0xD7 ) HoTT_Send( 0x07 )
elseif event == EVT_VIRTUAL_NEXT_PAGE then
multiBuffer( 5, 0xDE )
elseif event == EVT_VIRTUAL_ENTER then elseif event == EVT_VIRTUAL_ENTER then
multiBuffer( 5, 0xD9 ) HoTT_Send( 0x09 )
elseif event == EVT_VIRTUAL_NEXT then
multiBuffer( 5, 0xDD )
elseif event == EVT_VIRTUAL_PREV then elseif event == EVT_VIRTUAL_PREV then
multiBuffer( 5, 0xDB ) HoTT_Send( 0x0B )
elseif event == EVT_VIRTUAL_NEXT then
HoTT_Send( 0x0D )
elseif event == EVT_VIRTUAL_NEXT_PAGE then
HoTT_Send( 0x0E )
elseif event == EVT_VIRTUAL_MENU then
Timer_128 = 100
HoTT_Sensor_Inc()
else else
multiBuffer( 5, 0xDF ) HoTT_Send( 0x0F )
end end
HoTT_Draw_LCD() HoTT_Draw_LCD()
return 0 return 0

View file

@ -21,19 +21,41 @@
-- To start operation: -- To start operation:
-- Write "HoTT" at address 0..3 -- Write "HoTT" at address 0..3
-- Write 0xFF at address 4 will request the buffer to be cleared -- Write 0xFF at address 4 will request the buffer to be cleared
-- Write 0xDF at address 5 -- Write 0x0F at address 5
-- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters -- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters
-- by 8 lines -- by 8 lines
-- Write at address 5 sends an order to the RX: 0xDF=start, 0xD7=prev page, -- Write at address 5 sends an order to the RX: 0xXF=start, 0xX7=prev page,
-- 0xDE=next page, 0xD9=enter, 0xDD=next or 0xDB=prev -- 0xXE=next page, 0xX9=enter, 0xXD=next or 0xXB=prev with X being the sensor
-- to request data from 8=RX only, 9=Vario, A=GPS, B=Cust, C=ESC, D=GAM, E=EAM
-- Write at address 4 the value 0xFF will request the buffer to be cleared -- Write at address 4 the value 0xFF will request the buffer to be cleared
-- !! Before exiting the script must write 0 at address 0 for normal operation !! -- !! Before exiting the script must write 0 at address 0 for normal operation !!
--############################################################################### --###############################################################################
HoTT_Sensor = 0
Timer_128 = 100
local function HoTT_Release() local function HoTT_Release()
multiBuffer( 0, 0 ) multiBuffer( 0, 0 )
end end
local function HoTT_Send(button)
multiBuffer( 5, 0x80+(HoTT_Sensor*16) + button)
end
local function HoTT_Sensor_Inc()
local detected_sensors=multiBuffer( 4 )
local a
if detected_sensors ~= 0xFF then
repeat
HoTT_Sensor=(HoTT_Sensor+1)%7 -- Switch to next sensor
if HoTT_Sensor ~= 0 then
a = math.floor(detected_sensors/ (2^(HoTT_Sensor-1))) -- shift right
end
until HoTT_Sensor==0 or a % 2 == 1
HoTT_Send( 0x0F )
end
end
local function HoTT_Draw_LCD() local function HoTT_Draw_LCD()
local i local i
local value local value
@ -41,12 +63,14 @@ local function HoTT_Draw_LCD()
local result local result
local offset=0 local offset=0
local sensor_name = { "", "+Vario", "+GPS", "+Cust", "+ESC", "+GAM", "+EAM" }
lcd.clear() lcd.clear()
if LCD_W == 480 then if LCD_W == 480 then
--Draw title --Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, "Graupner HoTT RX configuration", MENU_TITLE_COLOR) lcd.drawText(1, 5, "Graupner HoTT: config RX" .. sensor_name[HoTT_Sensor+1] .. " - Menu cycle Sensors", MENU_TITLE_COLOR)
--Draw RX Menu --Draw RX Menu
if multiBuffer( 4 ) == 0xFF then if multiBuffer( 4 ) == 0xFF then
lcd.drawText(10,50,"No HoTT telemetry...", BLINK) lcd.drawText(10,50,"No HoTT telemetry...", BLINK)
@ -56,9 +80,9 @@ local function HoTT_Draw_LCD()
value=multiBuffer( line*21+6+i ) value=multiBuffer( line*21+6+i )
if value > 0x80 then if value > 0x80 then
value = value - 0x80 value = value - 0x80
lcd.drawText(10+i*16,32+16*line,string.char(value).." ",INVERS) lcd.drawText(10+i*16,32+20*line,string.char(value).." ",INVERS)
else else
lcd.drawText(10+i*16,32+16*line,string.char(value)) lcd.drawText(10+i*16,32+20*line,string.char(value))
end end
end end
end end
@ -68,6 +92,14 @@ local function HoTT_Draw_LCD()
if multiBuffer( 4 ) == 0xFF then if multiBuffer( 4 ) == 0xFF then
lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE) lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE)
else else
if Timer_128 ~= 0 then
--Intro page
Timer_128 = Timer_128 - 1
lcd.drawScreenTitle("Graupner Hott",0,0)
lcd.drawText(2,17,"Configuration of RX" .. sensor_name[HoTT_Sensor+1] ,SMLSIZE)
lcd.drawText(2,37,"Press menu to cycle Sensors" ,SMLSIZE)
else
--Menu page
for line = 0, 7, 1 do for line = 0, 7, 1 do
for i = 0, 21-1, 1 do for i = 0, 21-1, 1 do
value=multiBuffer( line*21+6+i ) value=multiBuffer( line*21+6+i )
@ -82,6 +114,7 @@ local function HoTT_Draw_LCD()
end end
end end
end end
end
-- Init -- Init
local function HoTT_Init() local function HoTT_Init()
@ -98,7 +131,10 @@ local function HoTT_Init()
--Request init of the RX buffer --Request init of the RX buffer
multiBuffer( 4, 0xFF ) multiBuffer( 4, 0xFF )
--Request RX to send the config menu --Request RX to send the config menu
multiBuffer( 5, 0xDF ) HoTT_Send( 0x0F )
HoTT_Sensor = 0;
HoTT_Detected_Sensors=0;
Timer_128 = 100
end end
-- Main -- Main
@ -111,18 +147,21 @@ local function HoTT_Run(event)
return 2 return 2
else else
if event == EVT_VIRTUAL_PREV_PAGE then if event == EVT_VIRTUAL_PREV_PAGE then
killEvents(event); killEvents(event)
multiBuffer( 5, 0xD7 ) HoTT_Send( 0x07 )
elseif event == EVT_VIRTUAL_NEXT_PAGE then
multiBuffer( 5, 0xDE )
elseif event == EVT_VIRTUAL_ENTER then elseif event == EVT_VIRTUAL_ENTER then
multiBuffer( 5, 0xD9 ) HoTT_Send( 0x09 )
elseif event == EVT_VIRTUAL_NEXT then
multiBuffer( 5, 0xDD )
elseif event == EVT_VIRTUAL_PREV then elseif event == EVT_VIRTUAL_PREV then
multiBuffer( 5, 0xDB ) HoTT_Send( 0x0B )
elseif event == EVT_VIRTUAL_NEXT then
HoTT_Send( 0x0D )
elseif event == EVT_VIRTUAL_NEXT_PAGE then
HoTT_Send( 0x0E )
elseif event == EVT_VIRTUAL_MENU then
Timer_128 = 100
HoTT_Sensor_Inc()
else else
multiBuffer( 5, 0xDF ) HoTT_Send( 0x0F )
end end
HoTT_Draw_LCD() HoTT_Draw_LCD()
return 0 return 0

View file

@ -393,7 +393,7 @@ void sendSport(uint8_t moduleIdx)
void sendHott(uint8_t moduleIdx) void sendHott(uint8_t moduleIdx)
{ {
if (Multi_Buffer && memcmp(Multi_Buffer, "HoTT", 4) == 0 && Multi_Buffer[5] >= 0xD7 && Multi_Buffer[5] <= 0xDF) { if (Multi_Buffer && memcmp(Multi_Buffer, "HoTT", 4) == 0 && (Multi_Buffer[5] & 0x80) && (Multi_Buffer[5] & 0x0F) >= 0x07) {
// HoTT Lua script is running // HoTT Lua script is running
sendMulti(moduleIdx, Multi_Buffer[5]); sendMulti(moduleIdx, Multi_Buffer[5]);
} }

View file

@ -227,6 +227,8 @@ void processHubPacket(uint8_t id, int16_t value)
else if (id == VOLTS_ID) { else if (id == VOLTS_ID) {
unit = UNIT_CELLS; unit = UNIT_CELLS;
uint32_t cellData = (uint32_t)data; uint32_t cellData = (uint32_t)data;
if (((cellData & 0x00F0) >> 4) >= MAX_CELLS)
return;
data = ((cellData & 0x00F0) << 12) + (((((cellData & 0xFF00) >> 8) + ((cellData & 0x000F) << 8))) / 5); data = ((cellData & 0x00F0) << 12) + (((((cellData & 0xFF00) >> 8) + ((cellData & 0x000F) << 8))) / 5);
} }
else if (id == GPS_DAY_MONTH_ID) { else if (id == GPS_DAY_MONTH_ID) {

View file

@ -139,6 +139,8 @@ void sportProcessTelemetryPacket(uint16_t id, uint8_t subId, uint8_t instance, u
if (unit == UNIT_CELLS) { if (unit == UNIT_CELLS) {
uint8_t cellsCount = (data & 0xF0) >> 4; uint8_t cellsCount = (data & 0xF0) >> 4;
uint8_t cellIndex = (data & 0x0F); uint8_t cellIndex = (data & 0x0F);
if (cellIndex >= MAX_CELLS)
return;
uint32_t mask = (cellsCount << 24) + (cellIndex << 16); uint32_t mask = (cellsCount << 24) + (cellIndex << 16);
setTelemetryValue(PROTOCOL_TELEMETRY_FRSKY_SPORT, id, subId, instance, mask + (((data & 0x000FFF00) >> 8) / 5), unit, precision); setTelemetryValue(PROTOCOL_TELEMETRY_FRSKY_SPORT, id, subId, instance, mask + (((data & 0x000FFF00) >> 8) / 5), unit, precision);
if (cellIndex+1 < cellsCount) { if (cellIndex+1 < cellsCount) {

View file

@ -18,24 +18,25 @@
/* Telemetry /* Telemetry
packet[0] = TX RSSI value packet[0] = TX RSSI value
packet[1] = TX LQI value packet[1] = TX LQI value
packet[2] = frame number packet[2] = Telemetry type
packet[3-12] telemetry data packet[3] = Telemetry page
packet[4-13] = Telemetry data
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. Telemetry type: 0x00 RX, 0x09 Vario, 0x0A GPS, 0x0B not seen, 0x0C ESC, 0x0D GAM, 0x0E EAM, 0x80 Text config mode
Here is a description of the telemetry data for each frame number: Telemetry page: 0x00..0x04 for all telemetry except Text config mode which is 0x00..0x12. The pages can be present or not, they also do not have to follow each others.
- frame 0x00
[3] = [12] = ?? Here is a description of the RX telemetry:
[4] = RX_Voltage*10 in V [2] = 0x00 -> Telemetry type RX
[5] = Temperature-20 in °C [3] = 0x00 -> Telemetry page 0
[6] = RX_RSSI [4] = ?? looks to be a copy of [7]
[7] = RX_LQI ?? [5] = RX_Voltage*10 in V
[8] = RX_STR ?? [6] = Temperature-20 in °C
[9,10] = [10]*256+[9]=max lost packet time in ms, max value seems 2s=0x7D0 [7] = RX_RSSI CC2500 formated (a<128:a/2-71dBm, a>=128:(a-256)/2-71dBm)
[11] = 0x00 ?? [8] = RX_LQI in %
- frame 0x01 Unknown [9] = RX_MIN_Voltage*10 in V
- frame 0x02 Unknown [10,11] = [11]*256+[10]=max lost packet time in ms, max value seems 2s=0x7D0
- frame 0x03 Unknown [12] = 0x00 ??
- frame 0x04 Unknown [13] = ?? looks to be a copy of [7]
*/ */
struct HottSensor struct HottSensor
@ -49,22 +50,54 @@ struct HottSensor
// telemetry frames // telemetry frames
enum enum
{ {
HOTT_FRAME_00 = 0x00, HOTT_PAGE_00 = 0x00,
HOTT_FRAME_01 = 0x01, HOTT_PAGE_01 = 0x01,
HOTT_FRAME_02 = 0x02, HOTT_PAGE_02 = 0x02,
HOTT_FRAME_03 = 0x03, HOTT_PAGE_03 = 0x03,
HOTT_FRAME_04 = 0x04, HOTT_PAGE_04 = 0x04,
}; };
#define HOTT_TELEM_NORMAL 0x00 enum
#define HOTT_TELEM_BIND 0x40 {
#define HOTT_TELEM_MENU 0x80 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,
};
// telemetry sensors ID // telemetry sensors ID
enum enum
{ {
HOTT_ID_RX_VOLTAGE = 0x0004, // RX_Batt Voltage HOTT_ID_RX_VOLTAGE = 0x0004, // RX_Batt Voltage
HOTT_ID_TEMP1 = 0x0005, // RX Temperature sensor HOTT_ID_TEMP1 = 0x0005, // RX Temperature sensor
HOTT_ID_VARIO = 0x0006, // Vario sensor
HOTT_ID_ALT = 0x0007, // Alt sensor
HOTT_ID_HDG = 0x0008, // Heading sensor
HOTT_ID_GSPD = 0x0008, // Ground speed sensor
HOTT_ID_GPS_LAT_LONG = 0x0009, // GPS sensor
HOTT_ID_GPS_COUNT = 0x000A, // GPS sat count
HOTT_ID_CELS = 0x000B, // Cels L sensor
HOTT_ID_CELS_H = 0x000C, // Cels H sensor
HOTT_ID_VOLT1 = 0x000D, // Voltage sensor
HOTT_ID_VOLT2 = 0x000E, // Voltage sensor
HOTT_ID_AMP1 = 0x000F, // Amp sensor
HOTT_ID_AMP2 = 0x0010, // Amp sensor
HOTT_ID_RPM1 = 0x0011, // RPM sensor
HOTT_ID_RPM2 = 0x0012, // RPM sensor
HOTT_ID_ESC_VIN = 0x0013, // ESC Volt
HOTT_ID_ESC_CUR = 0x0014, // ESC Amp
HOTT_ID_ESC_TBEC = 0x0015, // BEC Temp
HOTT_ID_ESC_BCUR = 0x0016, // BEC Cur
HOTT_ID_ESC_VBEC = 0x0017, // BEC Volt
HOTT_ID_BCAPA = 0x0018, // Batt capacity
HOTT_ID_TEMP2 = 0x0019, // Temperature sensor 2
HOTT_ID_AIR_SPEED = 0x001A,
HOTT_ID_VOLT3 = 0x001B, // Voltage sensor
HOTT_ID_FUEL = 0x001C, // Fuel percentage
HOTT_TX_RSSI_ID = 0xFF00, // Pseudo id outside 1 byte range of Hott sensors HOTT_TX_RSSI_ID = 0xFF00, // Pseudo id outside 1 byte range of Hott sensors
HOTT_TX_LQI_ID = 0xFF01, // Pseudo id outside 1 byte range of Hott sensors HOTT_TX_LQI_ID = 0xFF01, // Pseudo id outside 1 byte range of Hott sensors
HOTT_RX_RSSI_ID = 0xFF02, // Pseudo id outside 1 byte range of Hott sensors HOTT_RX_RSSI_ID = 0xFF02, // Pseudo id outside 1 byte range of Hott sensors
@ -72,14 +105,35 @@ enum
}; };
const HottSensor hottSensors[] = { const HottSensor hottSensors[] = {
//frame 00 //HOTT_TELEM_RX
{HOTT_ID_RX_VOLTAGE, ZSTR_BATT, UNIT_VOLTS, 1}, // RX_Batt Voltage {HOTT_ID_RX_VOLTAGE, ZSTR_BATT, UNIT_VOLTS, 1}, // RX_Batt Voltage
{HOTT_ID_TEMP1, ZSTR_TEMP1, UNIT_CELSIUS, 0}, // RX Temperature sensor {HOTT_ID_TEMP1, ZSTR_TEMP1, UNIT_CELSIUS, 0}, // Temperature sensor 1
//frame 01 {HOTT_ID_TEMP2, ZSTR_TEMP2, UNIT_CELSIUS, 0}, // Temperature sensor 2
//frame 02 {HOTT_ID_VARIO, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 2}, // Vario sensor
//frame 03 {HOTT_ID_ALT, ZSTR_ALT, UNIT_METERS, 0}, // Alt sensor
//frame 04 {HOTT_ID_HDG, ZSTR_HDG, UNIT_DEGREE, 0}, // Heading sensor
{HOTT_TX_RSSI_ID, ZSTR_TX_RSSI, UNIT_RAW, 0}, // Pseudo id outside 1 byte range of Hott sensors {HOTT_ID_GSPD, ZSTR_GSPD, UNIT_KMH, 0}, // Ground speed sensor
{HOTT_ID_GPS_LAT_LONG, ZSTR_GPS, UNIT_GPS, 0}, // GPS position
{HOTT_ID_GPS_COUNT, ZSTR_SATELLITES, UNIT_RAW, 0}, // GPS sat count
{HOTT_ID_VOLT1, ZSTR_A1, UNIT_VOLTS, 1}, // Voltage sensor 1
{HOTT_ID_VOLT2, ZSTR_A2, UNIT_VOLTS, 1}, // Voltage sensor 2
{HOTT_ID_VOLT3, ZSTR_A3, UNIT_VOLTS, 1}, // Voltage sensor 3
{HOTT_ID_AMP1, ZSTR_CURR, UNIT_AMPS, 1}, // Amp sensor 1
{HOTT_ID_AMP2, ZSTR_CURR, UNIT_AMPS, 1}, // Amp sensor 2
{HOTT_ID_RPM1, ZSTR_RPM, UNIT_RPMS, 0}, // RPM1
{HOTT_ID_RPM2, ZSTR_RPM2, UNIT_RPMS, 0}, // RPM2
{HOTT_ID_ESC_VIN, ZSTR_ESC_VIN, UNIT_VOLTS, 1}, // ESC VIN
{HOTT_ID_BCAPA, ZSTR_SMART_BAT_CAPACITY, UNIT_MAH, 2}, // Batt Capa
{HOTT_ID_ESC_CUR, ZSTR_ESC_CUR, UNIT_AMPS, 1}, // ESC Amp
{HOTT_ID_ESC_TBEC, ZSTR_ESC_TBEC, UNIT_CELSIUS, 0}, // ESC BEC Temp
{HOTT_ID_ESC_BCUR, ZSTR_ESC_BCUR, UNIT_AMPS, 1}, // ESC BEC Amp
{HOTT_ID_ESC_VBEC, ZSTR_ESC_VBEC, UNIT_VOLTS, 1}, // ESC BEC Volt
{HOTT_ID_CELS, ZSTR_CELLS, UNIT_CELLS, 2}, // Batt cells
{HOTT_ID_CELS_H, ZSTR_CELLS, UNIT_CELLS, 2}, // Batt H cells
{HOTT_ID_AIR_SPEED, ZSTR_ASPD, UNIT_KMH, 0}, // Air speed
{HOTT_ID_FUEL, ZSTR_FUEL, UNIT_PERCENT, 0}, // Fuel
{HOTT_TX_RSSI_ID, ZSTR_TX_RSSI, UNIT_DB, 0}, // Pseudo id outside 1 byte range of Hott sensors
{HOTT_TX_LQI_ID, ZSTR_TX_QUALITY, UNIT_RAW, 0}, // Pseudo id outside 1 byte range of Hott sensors {HOTT_TX_LQI_ID, ZSTR_TX_QUALITY, UNIT_RAW, 0}, // Pseudo id outside 1 byte range of Hott sensors
{HOTT_RX_RSSI_ID, ZSTR_RSSI, UNIT_DB, 0}, // RX RSSI {HOTT_RX_RSSI_ID, ZSTR_RSSI, UNIT_DB, 0}, // RX RSSI
{HOTT_RX_LQI_ID, ZSTR_RX_QUALITY, UNIT_RAW, 0}, // RX LQI {HOTT_RX_LQI_ID, ZSTR_RX_QUALITY, UNIT_RAW, 0}, // RX LQI
@ -95,10 +149,18 @@ const HottSensor * getHottSensor(uint16_t id)
return nullptr; return nullptr;
} }
int16_t processHoTTdBm(uint8_t value)
{
if (value >= 128) {
value = 256 - value;
}
return value / 2 -71;
}
void processHottPacket(const uint8_t * packet) void processHottPacket(const uint8_t * packet)
{ {
// Set TX RSSI Value // Set TX RSSI Value
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_TX_RSSI_ID, 0, 0, packet[0]>>1, UNIT_RAW, 0); setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_TX_RSSI_ID, 0, 0, processHoTTdBm(packet[0]), UNIT_RAW, 0);
// Set TX LQI Value // Set TX LQI Value
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_TX_LQI_ID, 0, 0, packet[1], UNIT_RAW, 0); setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_TX_LQI_ID, 0, 0, packet[1], UNIT_RAW, 0);
@ -110,7 +172,7 @@ void processHottPacket(const uint8_t * packet)
// Page X [5..13] = 9 ascii chars to be displayed, char is highlighted when ascii|0x80 // 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 // 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: // 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 or D // 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 // 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) { if (Multi_Buffer && memcmp(Multi_Buffer, "HoTT", 4) == 0) {
// HoTT Lua script is running // HoTT Lua script is running
@ -119,20 +181,30 @@ void processHottPacket(const uint8_t * packet)
memset(&Multi_Buffer[6], ' ', HOTT_MENU_NBR_PAGE * 9); // Clear text buffer memset(&Multi_Buffer[6], ' ', HOTT_MENU_NBR_PAGE * 9); // Clear text buffer
} }
if (packet[3] < HOTT_MENU_NBR_PAGE && Multi_Buffer[5] >= 0xD7 && Multi_Buffer[5] <= 0xDF) { 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 current menu being received 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 memcpy(&Multi_Buffer[6 + packet[3] * 9], &packet[5], 9); // Store the received page in the buffer
} }
return; return;
} }
#endif #endif
struct HottGPSMinutes
{
uint16_t value: 14;
uint16_t isNegative: 1;
uint16_t spare: 1;
};
const HottSensor * sensor; const HottSensor * sensor;
int32_t value; int32_t value;
static uint8_t prev_page = 0, prev_value = 0;
static HottGPSMinutes min = {};
int16_t deg = 0, sec = 0;
if (packet[2] == HOTT_TELEM_NORMAL) { switch (packet[2]) { // Telemetry type
switch (packet[3]) { case HOTT_TELEM_RX:
case HOTT_FRAME_00: if (packet[3] == 0) { // Telemetry page: only page 0 is for RX
// RX_VOLT // RX_VOLT
value = packet[5]; value = packet[5];
sensor = getHottSensor(HOTT_ID_RX_VOLTAGE); sensor = getHottSensor(HOTT_ID_RX_VOLTAGE);
@ -142,21 +214,433 @@ void processHottPacket(const uint8_t * packet)
sensor = getHottSensor(HOTT_ID_TEMP1); sensor = getHottSensor(HOTT_ID_TEMP1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP1, 0, 0, value, sensor->unit, sensor->precision); setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP1, 0, 0, value, sensor->unit, sensor->precision);
// RX_RSSI // RX_RSSI
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_RX_RSSI_ID, 0, 0, packet[7], UNIT_DB, 0); setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_RX_RSSI_ID, 0, 0, processHoTTdBm(packet[7]), UNIT_DB, 0);
// RX_LQI // RX_LQI
telemetryData.rssi.set(packet[8]); telemetryData.rssi.set(packet[8]);
if (packet[8] > 0) if (packet[8] > 0)
telemetryStreaming = TELEMETRY_TIMEOUT10ms; telemetryStreaming = TELEMETRY_TIMEOUT10ms;
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_RX_LQI_ID, 0, 0, packet[8], UNIT_RAW, 0); setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_RX_LQI_ID, 0, 0, packet[8], UNIT_RAW, 0);
}
break; break;
default: case HOTT_TELEM_VARIO:
// unknown // https://github.com/betaflight/betaflight/blob/1d8a0e9fd61cf01df7b34805e84365df72d9d68d/src/main/telemetry/hott.h#L240
value = (packet[7] << 24) | (packet[6] << 16) | (packet[5] << 8) | packet[4]; switch (packet[3]) { // Telemetry page 1,2,3,4
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, 0xFE00 | packet[3], 0, 0, value, UNIT_RAW, 0); case HOTT_PAGE_01:
// packet[6 ] uint8_t altitude_L; //#06 Altitude low uint8_t. In meters. A value of 500 means 0m
// packet[7 ] uint8_t altitude_H; //#07 Altitude high uint8_t
value = packet[6] + (packet[7] << 8) - 500;
sensor = getHottSensor(HOTT_ID_ALT);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ALT, 0, HOTT_TELEM_VARIO, value, sensor->unit, sensor->precision);
// packet[12] uint8_t climbrate_L; //#12 Climb rate in m/s. Steps of 0.01m/s. Value of 30000 = 0.00 m/s
// packet[13] uint8_t climbrate_H; //#13 Climb rate in m/s
value = packet[12] + (packet[13] << 8) - 30000;
sensor = getHottSensor(HOTT_ID_VARIO);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO, 0, HOTT_TELEM_VARIO, value, sensor->unit, sensor->precision);
break;
case HOTT_PAGE_02:
// packet[12] uint8_t compass_direction; //#42 Compass heading in 2<> steps. 1 = 2<>
value = packet[12] * 2;
sensor = getHottSensor(HOTT_ID_HDG);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_HDG, 0, HOTT_TELEM_VARIO, value, sensor->unit, sensor->precision);
break;
case HOTT_PAGE_03:
break;
case HOTT_PAGE_04:
break; 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:
// packet[7 ] uint8_t flight_direction; //#07 flight direction in 2 degreees/step (1 = 2degrees);
value = packet[7] * 2;
sensor = getHottSensor(HOTT_ID_HDG);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_HDG, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
// packet[8 ] uint8_t gps_speed_L; //08 km/h
// packet[9 ] uint8_t gps_speed_H; //#09
value = packet[8] + (packet[9] << 8);
sensor = getHottSensor(HOTT_ID_GSPD);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GSPD, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
// packet[10] uint8_t pos_NS; //#10 north = 0, south = 1
// packet[11] uint8_t pos_NS_dm_L; //#11 degree minutes ie N48<34>39<33>988
// packet[12] uint8_t pos_NS_dm_H; //#12
// packet[13] uint8_t pos_NS_sec_L; //#13 position seconds
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_LAT_LONG, 0, HOTT_TELEM_GPS, value, UNIT_GPS_LATITUDE, 0);
}
// packet[5 ] uint8_t pos_EW; //#15 east = 0, west = 1
// packet[6 ] uint8_t pos_EW_dm_L; //#16 degree minutes ie. E9<45>25<32>9360
// packet[7 ] uint8_t pos_EW_dm_H; //#17
// packet[8 ] uint8_t pos_EW_sec_L; //#18 position seconds
// packet[9 ] uint8_t pos_EW_sec_H; //#19
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_LAT_LONG, 0, HOTT_TELEM_GPS, value, UNIT_GPS_LONGITUDE, 0);
// packet[10] uint8_t home_distance_L; //#20 meters
// packet[11] uint8_t home_distance_H; //#21
// packet[12] uint8_t altitude_L; //#22 meters. Value of 500 = 0m
// packet[13] uint8_t altitude_H; //#23
value = packet[12] + (packet[13] << 8) - 500;
sensor = getHottSensor(HOTT_ID_ALT);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ALT, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
break;
case HOTT_PAGE_03:
// packet[4 ] uint8_t climbrate_L; //#24 m/s 0.01m/s resolution. Value of 30000 = 0.00 m/s
// packet[5 ] uint8_t climbrate_H; //#25
value = packet[4] + (packet[5] << 8) - 30000;
sensor = getHottSensor(HOTT_ID_VARIO);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO, 0, HOTT_TELEM_GPS, value, sensor->unit, sensor->precision);
// packet[6 ] uint8_t climbrate3s; //#26 climbrate in m/3s resolution, value of 120 = 0 m/3s
// packet[7 ] uint8_t gps_satelites; //#27 sat count
sensor = getHottSensor(HOTT_ID_GPS_COUNT);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_GPS_COUNT, 0, HOTT_TELEM_GPS, packet[7], 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:
// packet[7 ] uint8_t input_v_L; //#07 Input voltage low byte
// packet[8 ] uint8_t input_v_H; //#08
value = packet[7] + (packet[8] << 8);
sensor = getHottSensor(HOTT_ID_ESC_VIN);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_VIN, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
// packet[11] uint8_t batt_cap_L; //#11 battery capacity in 10mAh steps
// packet[12] uint8_t batt_cap_H; //#12
value = packet[11] + (packet[12] << 8);
sensor = getHottSensor(HOTT_ID_BCAPA);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_BCAPA, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
// packet[13] uint8_t esc_temp; //#13 ESC temperature
value = packet[13] - 20;
sensor = getHottSensor(HOTT_ID_TEMP1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP1, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
break;
case HOTT_PAGE_02:
// packet[5 ] uint8_t current_L; //#15 Current in 0.1 steps
// packet[6 ] uint8_t current_H; //#16
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);
// packet[9 ] uint8_t rpm_L; //#19 RPM in 10U/min steps
// packet[10] uint8_t rpm_H; //#20
value = (packet[9] + (packet[10] << 8)) * 10;
sensor = getHottSensor(HOTT_ID_RPM1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RPM1, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
break;
case HOTT_PAGE_03:
// packet[8 ] uint8_t bec_v; //#28 BEC voltage
value = packet[8];
sensor = getHottSensor(HOTT_ID_ESC_VBEC);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_VBEC, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
// packet[10] uint8_t bec_current; //#30 BEC current
value = packet[10];
sensor = getHottSensor(HOTT_ID_ESC_BCUR);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_BCUR, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
break;
case HOTT_PAGE_04:
// packet[4 ] uint8_t bec_temp; //#34 BEC temperature
value = packet[4] - 20;
sensor = getHottSensor(HOTT_ID_ESC_TBEC);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ESC_TBEC, 0, HOTT_TELEM_ESC, value, sensor->unit, sensor->precision);
// packet[6 ] uint8_t motor_temp; //#36 Motor or external sensor temperature
value = packet[6] - 20;
sensor = getHottSensor(HOTT_ID_TEMP2);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP2, 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:
sensor = getHottSensor(HOTT_ID_CELS);
// packet[7 ] uint8_t cell1_L; //#07 cell 1 voltage lower value. 0.02V steps, 124=2.48V
value = packet[7] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 0 << 16 | value, sensor->unit, sensor->precision);
// packet[8 ] uint8_t cell2_L; //#08
value = packet[8] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 1 << 16 | value, sensor->unit, sensor->precision);
// packet[9 ] uint8_t cell3_L; //#09
value = packet[9] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 2 << 16 | value, sensor->unit, sensor->precision);
// packet[10] uint8_t cell4_L; //#10
value = packet[10] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 3 << 16 | value, sensor->unit, sensor->precision);
// packet[11] uint8_t cell5_L; //#11
value = packet[11] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 4 << 16 | value, sensor->unit, sensor->precision);
// packet[12] uint8_t cell6_L; //#12
value = packet[12] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 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)) {
// packet[4 ] uint8_t batt1_H; //#14
value = prev_value + (packet[4] << 8);
sensor = getHottSensor(HOTT_ID_VOLT2);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT2, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
}
// packet[5 ] uint8_t batt2_L; //#15 battery 2 voltage LSB value. 0.1V steps. 50 = 5.5V
// packet[6 ] uint8_t batt2_H; //#16
value = packet[5] + (packet[6] << 8);
sensor = getHottSensor(HOTT_ID_VOLT3);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT3, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
// packet[7 ] uint8_t temperature1; //#17 temperature 1. offset of 20. a value of 20 = 0<>C
value = packet[7] - 20;
sensor = getHottSensor(HOTT_ID_TEMP1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
// packet[8 ] uint8_t temperature2; //#18 temperature 2. offset of 20. a value of 20 = 0<>C
value = packet[8] - 20;
sensor = getHottSensor(HOTT_ID_TEMP2);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP2, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
// packet[9 ] uint8_t fuel_procent; //#19 Fuel capacity in %. Values 0--100, graphical display ranges: 0-25% 50% 75% 100%
value = packet[9];
sensor = getHottSensor(HOTT_ID_FUEL);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_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
// packet[12] uint8_t rpm_L; //#22 RPM in 10 RPM steps. 300 = 3000rpm
// packet[13] uint8_t rpm_H; //#23
value = (packet[12] + (packet[13] << 8)) * 10;
sensor = getHottSensor(HOTT_ID_RPM1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RPM1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
break;
case HOTT_PAGE_03:
// packet[4 ] uint8_t altitude_L; //#24 altitude in meters. offset of 500, 500 = 0m
// packet[5 ] uint8_t altitude_H; //#25
value = packet[4] + (packet[5] << 8) - 500;
sensor = getHottSensor(HOTT_ID_ALT);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ALT, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
// packet[6 ] uint8_t climbrate_L; //#26 climb rate in 0.01m/s. Value of 30000 = 0.00 m/s
// packet[7 ] uint8_t climbrate_H; //#27
value = packet[6] + (packet[7] << 8) - 30000;
sensor = getHottSensor(HOTT_ID_VARIO);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO, 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
// packet[9 ] uint8_t current_L; //#29 current in 0.1A steps
// packet[10] uint8_t current_H; //#30
value = packet[9] + (packet[10] << 8);
sensor = getHottSensor(HOTT_ID_AMP1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_AMP1, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
// packet[11] uint8_t main_voltage_L; //#31 Main power voltage using 0.1V steps
// packet[12] uint8_t main_voltage_H; //#32
value = packet[11] + (packet[12] << 8);
sensor = getHottSensor(HOTT_ID_VOLT1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT1, 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:
// packet[4 ] uint8_t batt_cap_H; //#34
if (prev_page == ((HOTT_TELEM_GAM << 4) | HOTT_PAGE_03)) {
value = prev_value + (packet[4] << 8);
sensor = getHottSensor(HOTT_ID_BCAPA);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_BCAPA, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
}
// packet[5 ] uint8_t speed_L; //#35 (air?) speed in km/h(?) we are using ground speed here per default
// packet[6 ] uint8_t speed_H; //#36
value = packet[5] + (packet[6] << 8);
sensor = getHottSensor(HOTT_ID_AIR_SPEED);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_AIR_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
// packet[9 ] uint8_t rpm2_L; //#39 RPM in 10 RPM steps. 300 = 3000rpm
// packet[10] uint8_t rpm2_H; //#40
value = (packet[9] + (packet[10] << 8)) * 10;
sensor = getHottSensor(HOTT_ID_RPM2);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RPM2, 0, HOTT_TELEM_GAM, value, sensor->unit, sensor->precision);
// packet[11] uint8_t general_error_number;//#41 Voice error == 12. 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:
sensor = getHottSensor(HOTT_ID_CELS);
// packet[7 ] uint8_t cell1_L; //#07 cell 1 voltage lower value. 0.02V steps, 124=2.48V
value = packet[7] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 0 << 16 | value, sensor->unit, sensor->precision);
// packet[8 ] uint8_t cell2_L; //#08
value = packet[8] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 1 << 16 | value, sensor->unit, sensor->precision);
// packet[9 ] uint8_t cell3_L; //#09
value = packet[9] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 2 << 16 | value, sensor->unit, sensor->precision);
// packet[10] uint8_t cell4_L; //#10
value = packet[10] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 3 << 16 | value, sensor->unit, sensor->precision);
// packet[11] uint8_t cell5_L; //#11
value = packet[11] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 4 << 16 | value, sensor->unit, sensor->precision);
// packet[12] uint8_t cell6_L; //#12
value = packet[12] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 5 << 16 | value, sensor->unit, sensor->precision);
// packet[13] uint8_t cell7_L; //#13
// value = packet[13] << 1;
// if(value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 6 << 16 | value, sensor->unit, sensor->precision);
break;
case HOTT_PAGE_02:
sensor = getHottSensor(HOTT_ID_CELS);
// packet[4 ] uint8_t cell1_H; //#14 cell 1 voltage high value. 0.02V steps, 124=2.48V
value = packet[4] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 0 << 16 | value, sensor->unit, sensor->precision);
// packet[5 ] uint8_t cell2_H; //#15
value = packet[5] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 1 << 16 | value, sensor->unit, sensor->precision);
// packet[6 ] uint8_t cell3_H; //#16
value = packet[6] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 2 << 16 | value, sensor->unit, sensor->precision);
// packet[7 ] uint8_t cell4_H; //#17
value = packet[7] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 3 << 16 | value, sensor->unit, sensor->precision);
// packet[8 ] uint8_t cell5_H; //#18
value = packet[8] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 4 << 16 | value, sensor->unit, sensor->precision);
// packet[9 ] uint8_t cell6_H; //#19
value = packet[9] << 1;
if (value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS_H, 0, HOTT_TELEM_EAM, 5 << 16 | value, sensor->unit, sensor->precision);
// packet[10] uint8_t cell7_H; //#20
//value = packet[10] << 1;
//if(value) setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_CELS, 0, HOTT_TELEM_EAM, 13 << 16 | value, sensor->unit, sensor->precision);
// packet[11] uint8_t batt1_voltage_L; //#21 battery 1 voltage lower value in 100mv steps, 50=5V. optionally cell8_L value 0.02V steps
// packet[12] uint8_t batt1_voltage_H; //#22
value = packet[11] + (packet[12] << 8);
sensor = getHottSensor(HOTT_ID_VOLT2);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT2, 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:
if (prev_page == ((HOTT_TELEM_EAM << 4) | HOTT_PAGE_02)) {
// packet[4 ] uint8_t batt2_voltage_H; //#24
value = prev_value + (packet[4] << 8);
sensor = getHottSensor(HOTT_ID_VOLT3);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT3, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
}
// packet[5 ] uint8_t temp1; //#25 Temperature sensor 1. 20=0<>, 46=26<32> - offset of 20.
value = packet[5] - 20;
sensor = getHottSensor(HOTT_ID_TEMP1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP1, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
// packet[6 ] uint8_t temp2; //#26 temperature sensor 2
value = packet[6] - 20;
sensor = getHottSensor(HOTT_ID_TEMP2);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_TEMP2, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
// packet[7 ] uint8_t altitude_L; //#27 Attitude lower value. unit: meters. Value of 500 = 0m
// packet[8 ] uint8_t altitude_H; //#28
value = packet[7] + (packet[8] << 8) - 500;
sensor = getHottSensor(HOTT_ID_ALT);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_ALT, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
// packet[9 ] uint8_t current_L; //#29 Current in 0.1 steps
// packet[10] uint8_t current_H; //#30
value = packet[9] + (packet[10] << 8);
sensor = getHottSensor(HOTT_ID_AMP1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_AMP1, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
// packet[11] uint8_t main_voltage_L; //#31 Main power voltage (drive) in 0.1V steps
// packet[12] uint8_t main_voltage_H; //#32
value = packet[11] + (packet[12] << 8);
sensor = getHottSensor(HOTT_ID_VOLT1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VOLT1, 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:
// packet[4 ] uint8_t batt_cap_H; //#34
if (prev_page == ((HOTT_TELEM_EAM << 4) | HOTT_PAGE_03)) {
value = prev_value + (packet[4] << 8);
sensor = getHottSensor(HOTT_ID_BCAPA);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_BCAPA, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
}
// packet[5 ] uint8_t climbrate_L; //#35 climb rate in 0.01m/s. Value of 30000 = 0.00 m/s
// packet[6 ] uint8_t climbrate_H; //#36
value = packet[5] + (packet[6] << 8) - 30000;
sensor = getHottSensor(HOTT_ID_VARIO);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_VARIO, 0, HOTT_TELEM_EAM, value, sensor->unit, sensor->precision);
// packet[7 ] uint8_t climbrate3s; //#37 climbrate in m/3sec. Value of 120 = 0m/3sec
// packet[8 ] uint8_t rpm_L; //#38 RPM. Steps: 10 U/min
// packet[9 ] uint8_t rpm_H; //#39
value = (packet[8] + (packet[9] << 8)) * 10;
sensor = getHottSensor(HOTT_ID_RPM1);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_RPM1, 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
// packet[12] uint8_t speed_L; //#42 (air?) speed in km/h. Steps 1km/h
// packet[13] uint8_t speed_H; //#43
value = packet[12] + (packet[13] << 8);
sensor = getHottSensor(HOTT_ID_AIR_SPEED);
setTelemetryValue(PROTOCOL_TELEMETRY_HOTT, HOTT_ID_AIR_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) void hottSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance)

View file

@ -21,6 +21,7 @@
#include "telemetry.h" #include "telemetry.h"
#include "multi.h" #include "multi.h"
constexpr int32_t MULTI_DESIRED_VERSION = (1 << 24) | (3 << 16) | (1 << 8) | 1;
#define MULTI_CHAN_BITS 11 #define MULTI_CHAN_BITS 11
extern uint8_t g_moduleIdx; extern uint8_t g_moduleIdx;
@ -561,7 +562,7 @@ void MultiModuleStatus::getStatusString(char * statusText) const
return; return;
} }
if (major <= 1 && minor <= 3 && revision <= 0 && patch < 91 && SLOW_BLINK_ON_PHASE) { if ((((major << 24) | (minor << 16) | (revision << 8) | patch) < MULTI_DESIRED_VERSION) && SLOW_BLINK_ON_PHASE) {
strcpy(statusText, STR_MODULE_UPGRADE); strcpy(statusText, STR_MODULE_UPGRADE);
} }
else { else {

View file

@ -27,6 +27,7 @@
#define TELEMETRY_AVERAGE_COUNT 3 // we actually average one more reading! #define TELEMETRY_AVERAGE_COUNT 3 // we actually average one more reading!
#define RAW_FRSKY_MINMAX(v) v.values[TELEMETRY_AVERAGE_COUNT-1] #define RAW_FRSKY_MINMAX(v) v.values[TELEMETRY_AVERAGE_COUNT-1]
#define MAX_CELLS 6
class TelemetryValue { class TelemetryValue {
public: public:

View file

@ -90,6 +90,8 @@ void TelemetryItem::setValue(const TelemetrySensor & sensor, int32_t val, uint32
uint32_t data = uint32_t(newVal); uint32_t data = uint32_t(newVal);
uint8_t cellsCount = (data >> 24); uint8_t cellsCount = (data >> 24);
uint8_t cellIndex = ((data >> 16) & 0x0F); uint8_t cellIndex = ((data >> 16) & 0x0F);
if (cellIndex >= MAX_CELLS)
return;
uint16_t cellValue = (data & 0xFFFF); uint16_t cellValue = (data & 0xFFFF);
if (cellsCount == 0) { if (cellsCount == 0) {
cellsCount = (cellIndex >= cells.count ? cellIndex + 1 : cells.count); cellsCount = (cellIndex >= cells.count ? cellIndex + 1 : cells.count);

View file

@ -57,7 +57,7 @@ class TelemetryItem
} consumption; } consumption;
struct { struct {
uint8_t count; uint8_t count;
CellValue values[6]; CellValue values[MAX_CELLS];
} cells; } cells;
struct { struct {
uint16_t year; // full year (4 digits) uint16_t year; // full year (4 digits)