2018-08-03 18:29:24 +02:00
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol 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.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(HITEC_CC2500_INO)
#include "iface_cc2500.h"
2018-08-04 23:47:15 +02:00
//#define HITEC_FORCE_ID //Use the ID and hopping table from the original dump
2018-08-03 18:29:24 +02:00
#define HITEC_COARSE 0
#define HITEC_PACKET_LEN 13
#define HITEC_TX_ID_LEN 2
#define HITEC_BIND_COUNT 444 // 10sec
#define HITEC_NUM_FREQUENCE 21
#define HITEC_BIND_NUM_FREQUENCE 14
enum {
HITEC_START = 0x00 ,
HITEC_CALIB = 0x01 ,
HITEC_PREP = 0x02 ,
HITEC_DATA1 = 0x03 ,
HITEC_DATA2 = 0x04 ,
HITEC_DATA3 = 0x05 ,
HITEC_DATA4 = 0x06 ,
HITEC_RX1 = 0x07 ,
HITEC_RX2 = 0x08 ,
};
const PROGMEM uint8_t HITEC_init_values [] = {
/* 00 */ 0x2F , 0x2E , 0x2F , 0x07 , 0xD3 , 0x91 , 0xFF , 0x04 ,
2018-08-21 14:58:44 +02:00
/* 08 */ 0x45 , 0x00 , 0x00 , 0x12 , 0x00 , 0x5C , 0x85 , 0xE8 + HITEC_COARSE ,
2018-08-03 18:29:24 +02:00
/* 10 */ 0x3D , 0x3B , 0x73 , 0x73 , 0x7A , 0x01 , 0x07 , 0x30 ,
2018-08-21 14:58:44 +02:00
/* 18 */ 0x08 , 0x1D , 0x1C , 0xC7 , 0x40 , 0xB0 , 0x87 , 0x6B ,
2018-08-03 18:29:24 +02:00
/* 20 */ 0xF8 , 0xB6 , 0x10 , 0xEA , 0x0A , 0x00 , 0x11
};
static void __attribute__ (( unused )) HITEC_CC2500_init ()
{
CC2500_Strobe ( CC2500_SIDLE );
for ( uint8_t i = 0 ; i < 39 ; ++ i )
CC2500_WriteReg ( i , pgm_read_byte_near ( & HITEC_init_values [ i ]));
CC2500_WriteReg ( CC2500_0C_FSCTRL0 , option );
2021-04-02 17:42:44 +02:00
prev_option = option ;
2018-08-03 18:29:24 +02:00
CC2500_SetTxRxMode ( TX_EN );
CC2500_SetPower ();
}
// Generate RF channels
static void __attribute__ (( unused )) HITEC_RF_channels ()
{
//Normal hopping
uint8_t idx = 0 ;
uint32_t rnd = MProtocol_id ;
while ( idx < HITEC_NUM_FREQUENCE )
{
uint8_t i ;
uint8_t count_0_47 = 0 , count_48_93 = 0 , count_94_140 = 0 ;
rnd = rnd * 0x0019660D + 0x3C6EF35F ; // Randomization
// Use least-significant byte and make sure it's pair.
uint8_t next_ch = (( rnd >> 8 ) % 141 ) & 0xFE ;
// Check that it's not duplicated and spread uniformly
for ( i = 0 ; i < idx ; i ++ ) {
if ( hopping_frequency [ i ] == next_ch )
break ;
if ( hopping_frequency [ i ] <= 47 )
count_0_47 ++ ;
else if ( hopping_frequency [ i ] <= 93 )
count_48_93 ++ ;
else
count_94_140 ++ ;
}
if ( i != idx )
continue ;
if ( ( next_ch <= 47 && count_0_47 < 8 ) || ( next_ch >= 48 && next_ch <= 93 && count_48_93 < 8 ) || ( next_ch >= 94 && count_94_140 < 8 ) )
hopping_frequency [ idx ++ ] = next_ch ; //find hopping frequency
}
}
static void __attribute__ (( unused )) HITEC_tune_chan ()
{
CC2500_Strobe ( CC2500_SIDLE );
if ( IS_BIND_IN_PROGRESS )
CC2500_WriteReg ( CC2500_0A_CHANNR , hopping_frequency_no * 10 );
else
CC2500_WriteReg ( CC2500_0A_CHANNR , hopping_frequency [ hopping_frequency_no ]);
CC2500_Strobe ( CC2500_SFTX );
CC2500_Strobe ( CC2500_SCAL );
CC2500_Strobe ( CC2500_STX );
}
static void __attribute__ (( unused )) HITEC_change_chan_fast ()
{
CC2500_Strobe ( CC2500_SIDLE );
if ( IS_BIND_IN_PROGRESS )
CC2500_WriteReg ( CC2500_0A_CHANNR , hopping_frequency_no * 10 );
else
CC2500_WriteReg ( CC2500_0A_CHANNR , hopping_frequency [ hopping_frequency_no ]);
CC2500_WriteReg ( CC2500_25_FSCAL1 , calData [ hopping_frequency_no ]);
}
static void __attribute__ (( unused )) HITEC_build_packet ()
{
2018-08-06 18:32:39 +02:00
static boolean F5_frame = false ;
static uint8_t F5_counter = 0 ;
2018-08-05 15:46:24 +02:00
uint8_t offset ;
2018-08-06 18:32:39 +02:00
packet [ 1 ] = rx_tx_addr [ 1 ];
packet [ 2 ] = rx_tx_addr [ 2 ];
packet [ 3 ] = rx_tx_addr [ 3 ];
2018-08-06 01:42:12 +02:00
packet [ 22 ] = 0xEE ; // unknown always 0xEE
2018-08-03 18:29:24 +02:00
if ( IS_BIND_IN_PROGRESS )
{
2018-08-06 01:42:12 +02:00
packet [ 0 ] = 0x16 ; // 22 bytes to follow
2018-08-03 18:29:24 +02:00
memset ( packet + 5 , 0x00 , 14 );
switch ( bind_phase )
{
2018-08-06 01:42:12 +02:00
case 0x72 : // first part of the hopping table
2018-08-03 18:29:24 +02:00
for ( uint8_t i = 0 ; i < 14 ; i ++ )
packet [ 5 + i ] = hopping_frequency [ i ] >> 1 ;
break ;
2018-08-06 01:42:12 +02:00
case 0x73 : // second part of the hopping table
2018-08-03 18:29:24 +02:00
for ( uint8_t i = 0 ; i < 7 ; i ++ )
packet [ 5 + i ] = hopping_frequency [ i + 14 ] >> 1 ;
break ;
case 0x74 :
packet [ 7 ] = 0x55 ; // unknown but bind does not complete if not there
packet [ 8 ] = 0x55 ; // unknown but bind does not complete if not there
break ;
case 0x7B :
2018-08-06 01:42:12 +02:00
packet [ 5 ] = hopping_frequency [ 13 ] >> 1 ; // if not there the Optima link is jerky...
2020-03-21 19:00:40 +01:00
packet [ 14 ] = 0x2A ;
packet [ 15 ] = 0x46 ; // unknown but if 0x45 then 17=0x46, if 0x46 then 17=0x46 or 0x47, if 0x47 then 0x45 or 0x46
packet [ 16 ] = 0x2A ;
packet [ 17 ] = 0x47 ;
packet [ 18 ] = 0x2A ;
2018-08-03 18:29:24 +02:00
break ;
}
2018-08-09 19:51:07 +02:00
if ( sub_protocol == MINIMA )
2018-08-03 18:29:24 +02:00
packet [ 4 ] = bind_phase + 0x10 ;
2018-08-09 19:51:07 +02:00
else
packet [ 4 ] = bind_phase ; // Optima: increments based on RX answer
2018-08-07 13:24:45 +02:00
packet [ 19 ] = 0x08 ; // packet sequence
2018-08-06 01:42:12 +02:00
offset = 20 ; // packet[20] and [21]
2018-08-03 18:29:24 +02:00
}
else
{
2018-08-06 01:42:12 +02:00
packet [ 0 ] = 0x1A ; // 26 bytes to follow
2018-08-03 18:29:24 +02:00
for ( uint8_t i = 0 ; i < 9 ; i ++ )
{
2020-12-16 16:14:45 +01:00
uint16_t ch = convert_channel_16b_nolimit ( i , 0x1B87 , 0x3905 , false );
2018-08-03 18:29:24 +02:00
packet [ 4 + 2 * i ] = ch >> 8 ;
packet [ 5 + 2 * i ] = ch & 0xFF ;
}
2018-08-07 13:24:45 +02:00
packet [ 23 ] = 0x80 ; // packet sequence
2018-08-06 01:42:12 +02:00
offset = 24 ; // packet[24] and [25]
packet [ 26 ] = 0x00 ; // unknown always 0 and the RX doesn't seem to care about the value?
2018-08-03 18:29:24 +02:00
}
2018-08-05 15:46:24 +02:00
2018-08-06 18:32:39 +02:00
if ( F5_frame )
{ // No idea what it is but Minima RXs are expecting these frames to work to work
packet [ offset ] = 0xF5 ;
packet [ offset + 1 ] = 0xDF ;
if (( F5_counter % 9 ) == 0 )
packet [ offset + 1 ] -= 0x04 ; // every 8 packets send 0xDB
F5_counter ++ ;
F5_counter %= 59 ; // every 6 0xDB packets wait only 4 to resend instead of 8
F5_frame = false ; // alternate
if ( IS_BIND_IN_PROGRESS )
packet [ offset + 1 ] ++ ; // when binding the values are 0xE0 and 0xDC
2018-08-05 15:46:24 +02:00
}
else
{
packet [ offset ] = 0x00 ;
packet [ offset + 1 ] = 0x00 ;
2018-08-06 18:32:39 +02:00
F5_frame = true ; // alternate
2018-08-05 15:46:24 +02:00
}
2018-08-03 18:29:24 +02:00
/* debug("P:");
for(uint8_t i=0;i<packet[0]+1;i++)
debug("%02X,",packet[i]);
debugln("");
*/
}
static void __attribute__ (( unused )) HITEC_send_packet ()
{
CC2500_WriteData ( packet , packet [ 0 ] + 1 );
if ( IS_BIND_IN_PROGRESS )
2018-08-07 13:24:45 +02:00
{
packet [ 19 ] >>= 1 ; // packet sequence
if ( ( packet [ 4 ] & 0xFE ) == 0x82 )
{ // Minima
packet [ 4 ] ^= 1 ; // alternate 0x82 and 0x83
if ( packet [ 4 ] & 0x01 )
for ( uint8_t i = 0 ; i < 7 ; i ++ ) // 0x83
packet [ 5 + i ] = hopping_frequency [ i + 14 ] >> 1 ;
else
for ( uint8_t i = 0 ; i < 14 ; i ++ ) // 0x82
packet [ 5 + i ] = hopping_frequency [ i ] >> 1 ;
}
}
2018-08-03 18:29:24 +02:00
else
2018-08-07 13:24:45 +02:00
packet [ 23 ] >>= 1 ; // packet sequence
2018-08-03 18:29:24 +02:00
}
2021-02-09 18:23:33 +01:00
uint16_t HITEC_callback ()
2018-08-03 18:29:24 +02:00
{
switch ( phase )
{
case HITEC_START :
HITEC_CC2500_init ();
bind_phase = 0x72 ;
if ( IS_BIND_IN_PROGRESS )
{
2018-08-08 14:54:37 +02:00
bind_counter = HITEC_BIND_COUNT ;
2018-08-03 18:29:24 +02:00
rf_ch_num = HITEC_BIND_NUM_FREQUENCE ;
}
else
{
bind_counter = 0 ;
rf_ch_num = HITEC_NUM_FREQUENCE ;
//Set TXID
2018-08-06 18:32:39 +02:00
CC2500_WriteReg ( CC2500_05_SYNC0 , rx_tx_addr [ 2 ]);
CC2500_WriteReg ( CC2500_04_SYNC1 , rx_tx_addr [ 3 ]);
2018-08-03 18:29:24 +02:00
}
hopping_frequency_no = 0 ;
HITEC_tune_chan ();
phase = HITEC_CALIB ;
return 2000 ;
case HITEC_CALIB :
calData [ hopping_frequency_no ] = CC2500_ReadReg ( CC2500_25_FSCAL1 );
hopping_frequency_no ++ ;
if ( hopping_frequency_no < rf_ch_num )
HITEC_tune_chan ();
else
{
hopping_frequency_no = 0 ;
phase = HITEC_PREP ;
}
return 2000 ;
/* Work cycle: 22.5ms */
#define HITEC_PACKET_PERIOD 22500
#define HITEC_PREP_TIMING 462
#define HITEC_DATA_TIMING 2736
#define HITEC_RX1_TIMING 4636
case HITEC_PREP :
if ( prev_option == option )
{ // No user frequency change
2019-11-11 19:15:39 +01:00
#ifdef MULTI_SYNC
telemetry_set_input_sync ( HITEC_PACKET_PERIOD );
#endif
2018-08-03 18:29:24 +02:00
HITEC_change_chan_fast ();
hopping_frequency_no ++ ;
if ( hopping_frequency_no >= rf_ch_num )
hopping_frequency_no = 0 ;
CC2500_SetPower ();
CC2500_SetTxRxMode ( TX_EN );
HITEC_build_packet ();
phase ++ ;
}
else
phase = HITEC_START ; // Restart the tune process if option is changed to get good tuned values
return HITEC_PREP_TIMING ;
case HITEC_DATA1 :
case HITEC_DATA2 :
case HITEC_DATA3 :
case HITEC_DATA4 :
HITEC_send_packet ();
phase ++ ;
return HITEC_DATA_TIMING ;
case HITEC_RX1 :
CC2500_SetTxRxMode ( RX_EN );
CC2500_Strobe ( CC2500_SRX ); // Turn RX ON
phase ++ ;
return HITEC_RX1_TIMING ;
case HITEC_RX2 :
uint8_t len = CC2500_ReadReg ( CC2500_3B_RXBYTES | CC2500_READ_BURST ) & 0x7F ;
2019-09-30 17:35:12 +02:00
if ( len && len < TELEMETRY_BUFFER_SIZE )
2018-08-03 18:29:24 +02:00
{ // Something has been received
2019-09-30 17:35:12 +02:00
CC2500_ReadData ( packet_in , len );
if ( ( packet_in [ len - 1 ] & 0x80 ) && packet_in [ 0 ] == len - 3 && packet_in [ 1 ] == rx_tx_addr [ 1 ] && packet_in [ 2 ] == rx_tx_addr [ 2 ] && packet_in [ 3 ] == rx_tx_addr [ 3 ])
2018-08-03 18:29:24 +02:00
{ //valid crc && length ok && tx_id ok
debug ( "RX:l=%d" , len );
for ( uint8_t i = 0 ; i < len ; i ++ )
2019-09-30 17:35:12 +02:00
debug ( ",%02X" , packet_in [ i ]);
2018-08-03 18:29:24 +02:00
if ( IS_BIND_IN_PROGRESS )
{
if ( len == 13 ) // Bind packets have a length of 13
2018-08-06 01:42:12 +02:00
{ // bind packet: 0A,00,E5,F2,7X,05,06,07,08,09,00
2018-08-03 18:29:24 +02:00
debug ( ",bind" );
boolean check = true ;
2020-03-21 19:00:40 +01:00
for ( uint8_t i = 5 ; i < 10 ; i ++ )
if ( packet_in [ i ] != i ) check = false ;
2019-09-30 17:35:12 +02:00
if (( packet_in [ 4 ] & 0xF0 ) == 0x70 && check )
2018-08-03 18:29:24 +02:00
{
2019-09-30 17:35:12 +02:00
bind_phase = packet_in [ 4 ] + 1 ;
2018-08-03 18:29:24 +02:00
if ( bind_phase == 0x7B )
bind_counter = 164 ; // in dumps the RX stops to reply at 0x7B so wait a little and exit
}
}
}
else
2019-09-30 17:35:12 +02:00
if ( len == 15 && packet_in [ 4 ] == 0 && packet_in [ 12 ] == 0 )
2018-08-07 19:35:31 +02:00
{ // Valid telemetry packets
// no station:
// 0C,1C,A1,2B,00,00,00,00,00,00,00,8D,00,64,8E -> 00 8D=>RX battery voltage 0x008D/28=5.03V
// with HTS-SS:
// 0C,1C,A1,2B,00,11,AF,00,2D,00,8D,11,00,4D,96 -> 00 8D=>RX battery voltage 0x008D/28=5.03V
// 0C,1C,A1,2B,00,12,00,00,00,00,00,12,00,52,93
// 0C,1C,A1,2B,00,13,00,00,00,00,46,13,00,52,8B -> 46=>temperature2 0x46-0x28=30°C
// 0C,1C,A1,2B,00,14,00,00,00,00,41,14,00,2C,93 -> 41=>temperature1 0x41-0x28=25°C
// 0C,1C,A1,2B,00,15,00,2A,00,0E,00,15,00,44,96 -> 2A 00=>rpm1=420, 0E 00=>rpm2=140
// 0C,1C,A1,2B,00,16,00,00,00,00,00,16,00,2C,8E
// 0C,1C,A1,2B,00,17,00,00,00,42,44,17,00,48,8D -> 42=>temperature3 0x42-0x28=26°C,44=>temperature4 0x44-0x28=28°C
// 0C,1C,A1,2B,00,18,00,00,00,00,00,18,00,50,92
2019-09-30 17:35:12 +02:00
debug ( ",telem,%02x" , packet_in [ 14 ] & 0x7F );
2019-09-22 17:11:23 +02:00
#if defined(HITEC_FW_TELEMETRY) || defined(HITEC_HUB_TELEMETRY)
2019-09-30 17:35:12 +02:00
TX_RSSI = packet_in [ 13 ];
2019-09-22 17:11:23 +02:00
if ( TX_RSSI >= 128 )
TX_RSSI -= 128 ;
else
TX_RSSI += 128 ;
2019-09-30 17:35:12 +02:00
TX_LQI = packet_in [ 14 ] & 0x7F ;
2019-09-22 17:11:23 +02:00
#endif
2018-08-09 09:59:30 +02:00
#if defined(HITEC_FW_TELEMETRY)
2018-08-09 19:51:07 +02:00
if ( sub_protocol == OPT_FW )
2018-08-07 19:35:31 +02:00
{
2018-08-09 19:51:07 +02:00
// 8 bytes telemetry packets => see at the end of this file how to fully decode it
2019-09-30 17:35:12 +02:00
packet_in [ 0 ] = TX_RSSI ; // TX RSSI
packet_in [ 1 ] = TX_LQI ; // TX LQI
uint8_t offset = packet_in [ 5 ] == 0 ? 1 : 0 ;
2018-08-09 19:51:07 +02:00
for ( uint8_t i = 5 ; i < 11 ; i ++ )
2019-09-30 17:35:12 +02:00
packet_in [ i - 3 ] = packet_in [ i + offset ]; // frame number followed by 5 bytes of data
2018-08-09 19:51:07 +02:00
telemetry_link = 2 ; // telemetry forward available
}
#endif
#if defined(HITEC_HUB_TELEMETRY)
if ( sub_protocol == OPT_HUB )
{
2019-09-30 17:35:12 +02:00
switch ( packet_in [ 5 ]) // telemetry frame number
2018-08-09 19:51:07 +02:00
{
case 0x00 :
2019-09-30 17:35:12 +02:00
v_lipo1 = ( packet_in [ 10 ]) << 5 | ( packet_in [ 11 ]) >> 3 ; // calculation in float is volt=(packet_in[10]<<8+packet_in[11])/28
2018-08-09 19:51:07 +02:00
break ;
case 0x11 :
2019-09-30 17:35:12 +02:00
v_lipo1 = ( packet_in [ 9 ]) << 5 | ( packet_in [ 10 ]) >> 3 ; // calculation in float is volt=(packet_in[9]<<8+packet_in[10])/28
2018-08-09 19:51:07 +02:00
break ;
case 0x18 :
2019-09-30 17:35:12 +02:00
v_lipo2 = ( packet_in [ 6 ]) << 5 | ( packet_in [ 7 ]) >> 3 ; // calculation in float is volt=(packet_in[6]<<8+packet_in[7])/10
2018-08-09 19:51:07 +02:00
break ;
}
telemetry_link = 1 ; // telemetry hub available
2018-08-07 19:35:31 +02:00
}
2018-08-03 18:29:24 +02:00
#endif
}
debugln ( "" );
}
}
2018-08-06 18:32:39 +02:00
CC2500_Strobe ( CC2500_SFRX ); // Flush the RX FIFO buffer
2018-08-03 18:29:24 +02:00
phase = HITEC_PREP ;
if ( bind_counter )
{
bind_counter -- ;
if ( ! bind_counter )
{
BIND_DONE ;
phase = HITEC_START ;
}
}
return ( HITEC_PACKET_PERIOD - HITEC_PREP_TIMING - 4 * HITEC_DATA_TIMING - HITEC_RX1_TIMING );
}
return 0 ;
}
2021-02-09 18:23:33 +01:00
void HITEC_init ()
2018-08-03 18:29:24 +02:00
{
HITEC_RF_channels ();
2018-08-06 01:42:12 +02:00
#ifdef HITEC_FORCE_ID // ID and channels taken from dump
2018-08-06 18:32:39 +02:00
rx_tx_addr [ 1 ] = 0x00 ;
2018-08-03 18:29:24 +02:00
rx_tx_addr [ 2 ] = 0x03 ;
2018-08-06 18:32:39 +02:00
rx_tx_addr [ 3 ] = 0x6A ;
2018-08-03 18:29:24 +02:00
memcpy (( void * ) hopping_frequency ,( void * ) " \x00\x3A\x4A\x32\x0C\x58\x2A\x10\x26\x20\x08\x60\x68\x70\x78\x80\x88\x56\x5E\x66\x6E " , HITEC_NUM_FREQUENCE );
#endif
phase = HITEC_START ;
}
2018-08-07 19:35:31 +02:00
/* Full telemetry
2018-08-08 00:37:59 +02:00
packet[0] = TX RSSI value
packet[1] = TX LQI value
packet[2] = frame number
packet[3-7] telemetry data
2019-09-22 17:11:23 +02:00
The frame number takes the following values: 0x00, 0x11, 0x12, ..., 0x1C. The frames can be present or not, they also do not have to follow each others.
2018-08-08 00:37:59 +02:00
Here is a description of the telemetry data for each frame number:
2018-08-07 19:35:31 +02:00
- frame 0x00
data byte 0 -> 0x00 unknown
data byte 1 -> 0x00 unknown
data byte 2 -> 0x00 unknown
data byte 3 -> RX Batt Volt_H
data byte 4 -> RX Batt Volt_L => RX Batt=(Volt_H*256+Volt_L)/28
- frame 0x11
data byte 0 -> 0xAF start of frame
data byte 1 -> 0x00 unknown
2019-09-22 17:11:23 +02:00
data byte 2 -> 0x2D station type 0x2D=standard station nitro or electric, 0xAC=advanced station
data byte 3 -> RX Batt Volt_H
data byte 4 -> RX Batt Volt_L => RX Batt=(Volt_H*256+Volt_L)/28
2018-08-07 19:35:31 +02:00
- frame 0x12
data byte 0 -> Lat_sec_H GPS : latitude second
data byte 1 -> Lat_sec_L signed int : 1/100 of second
data byte 2 -> Lat_deg_min_H GPS : latitude degree.minute
data byte 3 -> Lat_deg_min_L signed int : +=North, - = south
data byte 4 -> Time_second GPS Time
- frame 0x13
data byte 0 -> GPS Longitude second
data byte 1 -> signed int : 1/100 of second
data byte 2 -> GPS Longitude degree.minute
data byte 3 -> signed int : +=Est, - = west
data byte 4 -> Temp2 Temperature2=Temp2-40°C
- frame 0x14
data byte 0 -> Speed_H
2019-09-22 17:11:23 +02:00
data byte 1 -> Speed_L GPS Speed=Speed_H*256+Speed_L km/h
2018-08-07 19:35:31 +02:00
data byte 2 -> Alti_sea_H
2019-09-22 17:11:23 +02:00
data byte 3 -> Alti_sea_L GPS Altitude=Alti_sea_H*256+Alti_sea_L m
2018-08-07 19:35:31 +02:00
data byte 4 -> Temp1 Temperature1=Temp1-40°C
- frame 0x15
data byte 0 -> FUEL
data byte 1 -> RPM1_L
data byte 2 -> RPM1_H RPM1=RPM1_H*256+RPM1_L
data byte 3 -> RPM2_L
data byte 4 -> RPM2_H RPM2=RPM2_H*256+RPM2_L
- frame 0x16
data byte 0 -> Date_year GPS Date
data byte 1 -> Date_month
data byte 2 -> Date_day
data byte 3 -> Time_hour GPS Time
data byte 4 -> Time_min
- frame 0x17
2019-09-22 17:11:23 +02:00
data byte 0 -> COURSEH
data byte 1 -> COURSEL GPS heading = COURSEH*256+COURSEL in degrees
data byte 2 -> Count GPS satellites
2018-08-07 19:35:31 +02:00
data byte 3 -> Temp3 Temperature3=Temp2-40°C
data byte 4 -> Temp4 Temperature4=Temp3-40°C
- frame 0x18
2019-09-25 19:10:55 +02:00
data byte 0 -> Volt_L Volt=(Volt_H*256+Volt_L)/10 V
2019-09-22 17:11:23 +02:00
data byte 1 -> Volt_H
2019-09-25 19:10:55 +02:00
data byte 2 -> AMP_L
data byte 3 -> AMP_H Amp=(AMP1_*256+AMP_L -180)/14 in signed A
2019-09-22 17:11:23 +02:00
- frame 0x19 Servo sensor
data byte 0 -> AMP_Servo1 Amp=AMP_Servo1/10 in A
data byte 1 -> AMP_Servo2 Amp=AMP_Servo2/10 in A
data byte 2 -> AMP_Servo3 Amp=AMP_Servo3/10 in A
data byte 3 -> AMP_Servo4 Amp=AMP_Servo4/10 in A
- frame 0x1A
data byte 2 -> ASpeed_H Air speed=ASpeed_H*256+ASpeed_L km/h
data byte 3 -> ASpeed_L
- frame 0x1B Variometer sensor
data byte 0 -> Alti1H
data byte 1 -> Alti1L Altitude unfiltered
data byte 2 -> Alti2H
data byte 3 -> Alti2L Altitude filtered
- frame 0x1C Unknown
2019-09-25 19:10:55 +02:00
- frame 0x22 Unknown
2018-08-07 19:35:31 +02:00
*/
2018-08-03 18:29:24 +02:00
#endif