2016-09-09 18:34:20 +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(HONTAI_NRF24L01_INO)
2021-03-17 17:05:42 +01:00
# include "iface_xn297.h" // mix of nrf and xn297 at 1Mb...
2016-09-09 18:34:20 +02:00
# define HONTAI_BIND_COUNT 80
# define HONTAI_PACKET_PERIOD 13500
2016-12-12 18:07:38 +01:00
# define FQ777_951_PACKET_PERIOD 10000
2016-09-09 18:34:20 +02:00
# define HONTAI_INITIAL_WAIT 500
2016-12-12 18:07:38 +01:00
# define HONTAI_BIND_PACKET_SIZE 10
2016-09-09 18:34:20 +02:00
# define HONTAI_PACKET_SIZE 12
# define HONTAI_RF_BIND_CHANNEL 0
enum {
HONTAI_FLAG_FLIP = 0x01 ,
HONTAI_FLAG_PICTURE = 0x02 ,
HONTAI_FLAG_VIDEO = 0x04 ,
HONTAI_FLAG_HEADLESS = 0x08 ,
HONTAI_FLAG_RTH = 0x10 ,
HONTAI_FLAG_CALIBRATE = 0x20 ,
} ;
2021-02-11 10:54:55 +01:00
static void __attribute__ ( ( unused ) ) HONTAI_send_packet ( )
2016-09-09 18:34:20 +02:00
{
2021-02-11 10:54:55 +01:00
if ( IS_BIND_IN_PROGRESS )
2016-09-09 18:34:20 +02:00
{
memcpy ( packet , rx_tx_addr , 5 ) ;
memset ( & packet [ 5 ] , 0 , 3 ) ;
2021-02-11 10:54:55 +01:00
packet_length = HONTAI_BIND_PACKET_SIZE ;
2016-09-09 18:34:20 +02:00
}
else
{
2021-03-17 17:05:42 +01:00
/*if(sub_protocol == JJRCX1)
NRF24L01_WriteReg ( NRF24L01_05_RF_CH , hopping_frequency [ hopping_frequency_no + + ] ) ;
else */
XN297_Hopping ( hopping_frequency_no + + ) ;
hopping_frequency_no % = 3 ;
2016-12-12 18:07:38 +01:00
memset ( packet , 0 , HONTAI_PACKET_SIZE ) ;
2018-01-08 19:37:14 +01:00
packet [ 3 ] = convert_channel_16b_limit ( THROTTLE , 0 , 127 ) < < 1 ; // Throttle
packet [ 4 ] = convert_channel_16b_limit ( AILERON , 63 , 0 ) ; // Aileron
packet [ 5 ] = convert_channel_16b_limit ( ELEVATOR , 0 , 63 ) ; // Elevator
packet [ 6 ] = convert_channel_16b_limit ( RUDDER , 0 , 63 ) ; // Rudder
2018-01-30 12:02:45 +01:00
if ( sub_protocol = = X5C1 )
2018-01-08 19:37:14 +01:00
packet [ 7 ] = convert_channel_16b_limit ( AILERON , 0 , 63 ) - 31 ; // Aileron trim
2016-09-10 11:28:53 +08:00
else
2018-01-08 19:37:14 +01:00
packet [ 7 ] = convert_channel_16b_limit ( AILERON , 0 , 32 ) - 16 ; // Aileron trim
packet [ 8 ] = convert_channel_16b_limit ( RUDDER , 0 , 32 ) - 16 ; // Rudder trim
2018-01-30 12:02:45 +01:00
if ( sub_protocol = = X5C1 )
2018-01-08 19:37:14 +01:00
packet [ 9 ] = convert_channel_16b_limit ( ELEVATOR , 0 , 63 ) - 31 ; // Elevator trim
2016-09-10 11:28:53 +08:00
else
2018-01-08 19:37:14 +01:00
packet [ 9 ] = convert_channel_16b_limit ( ELEVATOR , 0 , 32 ) - 16 ; // Elevator trim
2016-12-12 18:07:38 +01:00
switch ( sub_protocol )
{
2018-01-30 12:02:45 +01:00
case HONTAI :
2016-12-12 18:07:38 +01:00
packet [ 0 ] = 0x0B ;
2018-01-08 19:37:14 +01:00
packet [ 3 ] | = GET_FLAG ( CH7_SW , 0x01 ) ; // Picture
packet [ 4 ] | = GET_FLAG ( CH10_SW , 0x80 ) // RTH
| GET_FLAG ( CH9_SW , 0x40 ) ; // Headless
packet [ 5 ] | = GET_FLAG ( CH11_SW , 0x80 ) // Calibrate
| GET_FLAG ( CH5_SW , 0x40 ) ; // Flip
packet [ 6 ] | = GET_FLAG ( CH8_SW , 0x80 ) ; // Video
2016-12-12 18:07:38 +01:00
break ;
2018-01-30 12:02:45 +01:00
case JJRCX1 :
2018-01-08 19:37:14 +01:00
packet [ 0 ] = GET_FLAG ( CH6_SW , 0x02 ) ; // Arm
packet [ 3 ] | = GET_FLAG ( CH7_SW , 0x01 ) ; // Picture
2016-12-12 18:07:38 +01:00
packet [ 4 ] | = 0x80 ; // unknown
2018-01-08 19:37:14 +01:00
packet [ 5 ] | = GET_FLAG ( CH11_SW , 0x80 ) // Calibrate
| GET_FLAG ( CH5_SW , 0x40 ) ; // Flip
packet [ 6 ] | = GET_FLAG ( CH8_SW , 0x80 ) ; // Video
2016-12-12 18:07:38 +01:00
packet [ 8 ] = 0xC0 // high rate, no rudder trim
2018-01-08 19:37:14 +01:00
| GET_FLAG ( CH10_SW , 0x02 ) // RTH
| GET_FLAG ( CH9_SW , 0x01 ) ; // Headless
2016-12-12 18:07:38 +01:00
break ;
2018-01-30 12:02:45 +01:00
case X5C1 :
2016-12-12 18:07:38 +01:00
packet [ 0 ] = 0x0B ;
2018-01-08 19:37:14 +01:00
packet [ 3 ] | = GET_FLAG ( CH7_SW , 0x01 ) ; // Picture
2016-12-12 18:07:38 +01:00
packet [ 4 ] = 0x80 // unknown
2018-01-08 19:37:14 +01:00
| GET_FLAG ( CH6_SW , 0x40 ) ; // Lights
packet [ 5 ] | = GET_FLAG ( CH11_SW , 0x80 ) // Calibrate
| GET_FLAG ( CH5_SW , 0x40 ) ; // Flip
packet [ 6 ] | = GET_FLAG ( CH8_SW , 0x80 ) ; // Video
2016-12-12 18:07:38 +01:00
packet [ 8 ] = 0xC0 // high rate, no rudder trim
2018-01-08 19:37:14 +01:00
| GET_FLAG ( CH10_SW , 0x02 ) // RTH
| GET_FLAG ( CH9_SW , 0x01 ) ; // Headless
2016-12-12 18:07:38 +01:00
break ;
2018-01-30 12:02:45 +01:00
case FQ777_951 :
2018-01-08 19:37:14 +01:00
packet [ 0 ] = GET_FLAG ( CH7_SW , 0x01 ) // Picture
| GET_FLAG ( CH8_SW , 0x02 ) ; // Video
packet [ 3 ] | = GET_FLAG ( CH5_SW , 0x01 ) ; // Flip
2016-12-12 18:07:38 +01:00
packet [ 4 ] | = 0xC0 ; // High rate (mid=0xa0, low=0x60)
2018-01-08 19:37:14 +01:00
packet [ 5 ] | = GET_FLAG ( CH11_SW , 0x80 ) ; // Calibrate
packet [ 6 ] | = GET_FLAG ( CH9_SW , 0x40 ) ; // Headless
2016-12-12 18:07:38 +01:00
break ;
}
2021-02-11 10:54:55 +01:00
packet_length = HONTAI_PACKET_SIZE ;
2016-09-09 18:34:20 +02:00
}
2021-02-11 10:54:55 +01:00
// CRC 16 bits reflected in and out
crc = 0xFFFF ;
for ( uint8_t i = 0 ; i < packet_length - 2 ; i + + )
crc16_update ( bit_reverse ( packet [ i ] ) , 8 ) ;
crc ^ = 0xFFFF ;
packet [ packet_length - 2 ] = bit_reverse ( crc > > 8 ) ;
packet [ packet_length - 1 ] = bit_reverse ( crc ) ;
2016-09-09 18:34:20 +02:00
// Power on, TX mode, 2byte CRC
2021-03-17 17:05:42 +01:00
/*if(sub_protocol == JJRCX1)
{
NRF24L01_SetPower ( ) ;
2016-09-09 18:34:20 +02:00
NRF24L01_SetTxRxMode ( TX_EN ) ;
2021-03-17 17:05:42 +01:00
NRF24L01_WriteReg ( NRF24L01_07_STATUS , 0x70 ) ;
NRF24L01_FlushTx ( ) ;
}
else */
{
XN297_SetPower ( ) ;
XN297_SetTxRxMode ( TX_EN ) ;
}
2016-09-09 18:34:20 +02:00
2018-01-30 12:02:45 +01:00
if ( sub_protocol = = JJRCX1 )
2021-02-11 10:54:55 +01:00
NRF24L01_WritePayload ( packet , packet_length ) ;
2016-09-09 18:34:20 +02:00
else
2021-02-11 10:54:55 +01:00
XN297_WritePayload ( packet , packet_length ) ;
2016-09-09 18:34:20 +02:00
}
2021-02-09 18:23:33 +01:00
static void __attribute__ ( ( unused ) ) HONTAI_RF_init ( )
2016-09-09 18:34:20 +02:00
{
2021-03-17 17:05:42 +01:00
XN297_Configure ( XN297_CRCEN , XN297_SCRAMBLED , XN297_1M ) ; // this will select the nrf and initialize it, therefore both sub protocols can use common instructions
2018-01-30 12:02:45 +01:00
if ( sub_protocol = = JJRCX1 )
2016-09-09 18:34:20 +02:00
{
2021-03-17 17:05:42 +01:00
//NRF24L01_Initialize();
NRF24L01_WriteRegisterMulti ( NRF24L01_10_TX_ADDR , ( uint8_t * ) " \xd2 \xb5 \x99 \xb3 \x4a " , 5 ) ;
2016-09-09 18:34:20 +02:00
NRF24L01_WriteReg ( NRF24L01_04_SETUP_RETR , 0xff ) ; // JJRC uses dynamic payload length
NRF24L01_WriteReg ( NRF24L01_1C_DYNPD , 0x3f ) ; // match other stock settings even though AA disabled...
NRF24L01_WriteReg ( NRF24L01_1D_FEATURE , 0x07 ) ;
2021-03-17 17:05:42 +01:00
//NRF24L01_WriteReg(NRF24L01_05_RF_CH, HONTAI_RF_BIND_CHANNEL);
2016-09-09 18:34:20 +02:00
}
2021-03-17 17:05:42 +01:00
else
{
XN297_SetTXAddr ( ( const uint8_t * ) " \xd2 \xb5 \x99 \xb3 \x4a " , 5 ) ;
//XN297_HoppingCalib(3);
}
XN297_RFChannel ( HONTAI_RF_BIND_CHANNEL ) ;
2016-09-09 18:34:20 +02:00
}
2016-12-12 18:07:38 +01:00
const uint8_t PROGMEM HONTAI_hopping_frequency_nonels [ ] [ 3 ] = {
2016-09-09 18:34:20 +02:00
{ 0x05 , 0x19 , 0x28 } , // Hontai
{ 0x0a , 0x1e , 0x2d } } ; // JJRC X1
2016-12-12 18:07:38 +01:00
const uint8_t PROGMEM HONTAI_addr_vals [ 4 ] [ 16 ] = {
2016-09-09 18:34:20 +02:00
{ 0x24 , 0x26 , 0x2a , 0x2c , 0x32 , 0x34 , 0x36 , 0x4a , 0x4c , 0x4e , 0x54 , 0x56 , 0x5a , 0x64 , 0x66 , 0x6a } ,
{ 0x92 , 0x94 , 0x96 , 0x9a , 0xa4 , 0xa6 , 0xac , 0xb2 , 0xb4 , 0xb6 , 0xca , 0xcc , 0xd2 , 0xd4 , 0xd6 , 0xda } ,
{ 0x93 , 0x95 , 0x99 , 0x9b , 0xa5 , 0xa9 , 0xab , 0xad , 0xb3 , 0xb5 , 0xc9 , 0xcb , 0xcd , 0xd3 , 0xd5 , 0xd9 } ,
{ 0x25 , 0x29 , 0x2b , 0x2d , 0x33 , 0x35 , 0x49 , 0x4b , 0x4d , 0x59 , 0x5b , 0x65 , 0x69 , 0x6b , 0x6d , 0x6e } } ;
static void __attribute__ ( ( unused ) ) HONTAI_init2 ( )
{
uint8_t data_tx_addr [ 5 ] ;
//TX address
2016-12-12 18:07:38 +01:00
data_tx_addr [ 0 ] = pgm_read_byte_near ( & HONTAI_addr_vals [ 0 ] [ rx_tx_addr [ 3 ] & 0x0f ] ) ;
data_tx_addr [ 1 ] = pgm_read_byte_near ( & HONTAI_addr_vals [ 1 ] [ ( rx_tx_addr [ 3 ] > > 4 ) & 0x0f ] ) ;
data_tx_addr [ 2 ] = pgm_read_byte_near ( & HONTAI_addr_vals [ 2 ] [ rx_tx_addr [ 4 ] & 0x0f ] ) ;
data_tx_addr [ 3 ] = pgm_read_byte_near ( & HONTAI_addr_vals [ 3 ] [ ( rx_tx_addr [ 4 ] > > 4 ) & 0x0f ] ) ;
2016-09-09 18:34:20 +02:00
data_tx_addr [ 4 ] = 0x24 ;
2018-01-30 12:02:45 +01:00
if ( sub_protocol = = JJRCX1 )
2021-03-17 17:05:42 +01:00
NRF24L01_WriteRegisterMulti ( NRF24L01_10_TX_ADDR , data_tx_addr , 5 ) ;
2016-09-09 18:34:20 +02:00
else
2021-03-17 17:05:42 +01:00
XN297_SetTXAddr ( data_tx_addr , 5 ) ;
2016-09-09 18:34:20 +02:00
//Hopping frequency table
for ( uint8_t i = 0 ; i < 3 ; i + + )
2018-01-30 12:02:45 +01:00
hopping_frequency [ i ] = pgm_read_byte_near ( & HONTAI_hopping_frequency_nonels [ sub_protocol = = JJRCX1 ? 1 : 0 ] [ i ] ) ;
2016-09-09 18:34:20 +02:00
hopping_frequency_no = 0 ;
}
static void __attribute__ ( ( unused ) ) HONTAI_initialize_txid ( )
{
rx_tx_addr [ 4 ] = rx_tx_addr [ 2 ] ;
2018-01-30 12:02:45 +01:00
if ( sub_protocol = = HONTAI | | sub_protocol = = FQ777_951 )
2016-09-09 18:34:20 +02:00
{
rx_tx_addr [ 0 ] = 0x4c ; // first three bytes some kind of model id? - set same as stock tx
rx_tx_addr [ 1 ] = 0x4b ;
rx_tx_addr [ 2 ] = 0x3a ;
}
else
{
rx_tx_addr [ 0 ] = 0x4b ; // JJRC X1
rx_tx_addr [ 1 ] = 0x59 ;
rx_tx_addr [ 2 ] = 0x3a ;
}
}
uint16_t HONTAI_callback ( )
{
2021-02-12 11:21:42 +01:00
# ifdef MULTI_SYNC
telemetry_set_input_sync ( packet_period ) ;
# endif
2021-02-11 10:54:55 +01:00
if ( bind_counter )
2016-09-09 18:34:20 +02:00
{
bind_counter - - ;
if ( bind_counter = = 0 )
{
HONTAI_init2 ( ) ;
BIND_DONE ;
}
}
2021-02-12 11:21:42 +01:00
HONTAI_send_packet ( ) ;
2019-10-10 23:12:09 +02:00
return packet_period ;
2016-09-09 18:34:20 +02:00
}
2021-02-09 18:23:33 +01:00
void HONTAI_init ( )
2016-09-09 18:34:20 +02:00
{
2016-09-10 09:42:39 +02:00
BIND_IN_PROGRESS ; // autobind protocol
2016-09-09 18:34:20 +02:00
bind_counter = HONTAI_BIND_COUNT ;
HONTAI_initialize_txid ( ) ;
2021-02-09 18:23:33 +01:00
HONTAI_RF_init ( ) ;
2019-10-10 23:12:09 +02:00
packet_period = sub_protocol = = FQ777_951 ? FQ777_951_PACKET_PERIOD : HONTAI_PACKET_PERIOD ;
2016-09-09 18:34:20 +02:00
}
# endif