2024-02-15 15:51:20 +01: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/>.
*/
2024-09-26 01:11:19 -07:00
// Compatible with SGF22, ParkTen F22S, KF700 J20
2024-02-15 15:51:20 +01:00
# if defined(SGF22_NRF24L01_INO)
# include "iface_xn297.h"
2024-02-19 18:34:27 +01:00
//#define FORCE_SGF22_ORIGINAL_ID
2024-02-15 15:51:20 +01:00
2024-09-02 18:14:25 +02:00
# define SGF22_PACKET_PERIOD 11950 //10240
# define SGF22_BIND_RF_CHANNEL 78
# define SGF22_PAYLOAD_SIZE 12
# define SGF22_BIND_COUNT 50
# define SGF22_RF_NUM_CHANNELS 4
# define SGF22_F22S_BIND_RF_CHANNEL 10
2024-09-26 01:11:19 -07:00
# define SGF22_J20_BIND_RF_CHANNEL 28
2024-02-15 15:51:20 +01:00
2024-02-16 10:24:44 +01:00
//packet[8]
# define SGF22_FLAG_3D 0x00
# define SGF22_FLAG_ROLL 0x08
2024-02-15 18:24:58 +01:00
# define SGF22_FLAG_LIGHT 0x04
2024-02-16 10:24:44 +01:00
# define SGF22_FLAG_VIDEO 0x10
2024-02-15 18:24:58 +01:00
# define SGF22_FLAG_6G 0x40
# define SGF22_FLAG_VERTICAL 0xC0
2024-09-26 01:11:19 -07:00
# define SGF22_J20_FLAG_HORIZONTAL 0x80
2024-10-09 10:09:21 +02:00
//#define SGF22_J20_FLAG_SPEED 0x01 // Up/Down trim, not implemented
2024-09-26 01:11:19 -07:00
2024-02-16 10:24:44 +01:00
//packet[9]
2024-10-09 10:09:21 +02:00
# define SGF22_FLAG_PHOTO 0x40 // #define SGF22_J20_FLAG_INVERT 0x40
2024-09-26 01:11:19 -07:00
# define SGF22_FLAG_TRIMRESET 0x04
2024-10-09 10:09:21 +02:00
# define SGF22_J20_FLAG_FIXHEIGHT 0x80
2024-02-15 18:24:58 +01:00
2024-02-15 15:51:20 +01:00
static void __attribute__ ( ( unused ) ) SGF22_send_packet ( )
{
if ( IS_BIND_IN_PROGRESS )
{
2024-02-15 18:24:58 +01:00
packet [ 0 ] = 0x5B ;
packet [ 8 ] = 0x00 ; // ??? do they have to be 0 for bind to succeed ?
packet [ 9 ] = 0x00 ; // ??? do they have to be 0 for bind to succeed ?
2024-02-15 15:51:20 +01:00
packet [ 10 ] = 0xAA ;
packet [ 11 ] = 0x55 ;
}
else
{
//hop
2024-02-15 18:24:58 +01:00
XN297_Hopping ( packet_sent & 0x03 ) ; // ??? from the dumps I can't really say how hop and seq are sync, there could be an offset (0,1,2,3)...
2024-02-21 11:41:23 +01:00
//sequence from 02 to 7A by increments of 4, sometimes with a flag 0x80 from 82 to FA, I can't tell from the dumps when the switch happens
2024-02-15 15:51:20 +01:00
if ( ( packet_sent & 0x03 ) = = 0x02 )
packet_count = packet_sent ;
packet_sent + + ;
if ( packet_sent > 0x7B )
packet_sent = 0 ;
//packet
packet [ 0 ] = 0x1B ;
2024-09-26 01:11:19 -07:00
packet [ 8 ] = SGF22_FLAG_3D // CH5 -100%, F22 & F22S - 3D mode, J20 - Gyro off
| GET_FLAG ( CH6_SW , SGF22_FLAG_ROLL ) // roll
| GET_FLAG ( CH7_SW , SGF22_FLAG_LIGHT ) // push up throttle trim for light in the stock TX
| GET_FLAG ( CH9_SW , SGF22_FLAG_VIDEO ) ; // push down throttle trim for video in the stock TX
if ( Channel_data [ CH5 ] > CHANNEL_MAX_COMMAND )
packet [ 8 ] | = SGF22_FLAG_VERTICAL ; // CH5 100%, vertical mode (torque)
else if ( Channel_data [ CH5 ] > CHANNEL_MIN_COMMAND )
packet [ 8 ] | = ( sub_protocol = = SGF22_J20 ? SGF22_J20_FLAG_HORIZONTAL : SGF22_FLAG_6G ) ; // CH5 0%, F22 & F22S - 6G mode, J20 - Horizontal mode
packet [ 9 ] = GET_FLAG ( CH8_SW , SGF22_FLAG_PHOTO ) // F22: photo, press in throttle trim in the stock TX, J20: invert flight
2024-10-09 10:09:21 +02:00
| GET_FLAG ( CH10_SW , ( sub_protocol = = SGF22_J20 ? SGF22_J20_FLAG_FIXHEIGHT : SGF22_FLAG_TRIMRESET ) ) ; // F22: Both sticks down inwards in the stock TX, J20: Altitude hold
2024-02-15 18:24:58 +01:00
packet [ 10 ] = 0x42 ; // no fine tune
packet [ 11 ] = 0x10 ; // no fine tune
2024-02-15 15:51:20 +01:00
}
2024-09-02 18:14:25 +02:00
if ( sub_protocol = = SGF22_F22S )
packet [ 0 ] + = 6 ;
2024-09-26 01:11:19 -07:00
else if ( sub_protocol = = SGF22_J20 )
packet [ 0 ] + = 3 ;
2024-02-15 18:24:58 +01:00
packet [ 1 ] = packet_count ; // sequence
2024-02-15 15:51:20 +01:00
packet [ 2 ] = rx_tx_addr [ 2 ] ;
packet [ 3 ] = rx_tx_addr [ 3 ] ;
packet [ 4 ] = convert_channel_8b ( THROTTLE ) ;
packet [ 5 ] = convert_channel_8b ( RUDDER ) ;
packet [ 6 ] = convert_channel_8b ( ELEVATOR ) ;
packet [ 7 ] = convert_channel_8b ( AILERON ) ;
XN297_SetPower ( ) ;
XN297_SetTxRxMode ( TX_EN ) ;
XN297_WriteEnhancedPayload ( packet , SGF22_PAYLOAD_SIZE , 0 ) ;
#if 0
debug_time ( " " ) ;
for ( uint8_t i = 0 ; i < SGF22_PAYLOAD_SIZE ; i + + )
debug ( " %02X " , packet [ i ] ) ;
debugln ( " " ) ;
# endif
}
static void __attribute__ ( ( unused ) ) SGF22_initialize_txid ( )
{
2024-04-24 07:00:44 +02:00
uint16_t val = ( rx_tx_addr [ 2 ] < < 8 ) | rx_tx_addr [ 3 ] ;
if ( rx_tx_addr [ 2 ] > ( 0xFF - rx_tx_addr [ 3 ] ) )
val - - ;
val % = 5 ;
2024-02-19 18:34:27 +01:00
const uint8_t hop [ 5 ] [ 4 ] =
{ { 0x0C , 0x2A , 0x1B , 0x39 } ,
{ 0x0F , 0x2D , 0x1E , 0x3D } ,
{ 0x12 , 0x31 , 0x21 , 0x41 } ,
{ 0x15 , 0x34 , 0x24 , 0x44 } ,
{ 0x18 , 0x37 , 0x27 , 0x47 } } ;
memcpy ( hopping_frequency , & hop [ val ] , SGF22_RF_NUM_CHANNELS ) ;
2024-03-21 16:33:16 +01:00
2024-02-19 18:34:27 +01:00
/*//Same code sze...
hopping_frequency [ 0 ] = 0x0C + 3 * val ;
hopping_frequency [ 1 ] = hopping_frequency [ 0 ] + 0x1E ;
if ( val > 1 ) hopping_frequency [ 1 ] + + ;
hopping_frequency [ 2 ] = hopping_frequency [ 0 ] + 0x0F ;
hopping_frequency [ 3 ] = hopping_frequency [ 1 ] + 0x0F ;
if ( val ) hopping_frequency [ 3 ] + + ; */
2024-02-15 15:51:20 +01:00
# ifdef FORCE_SGF22_ORIGINAL_ID
2024-03-29 16:19:20 +01:00
rx_tx_addr [ 2 ] = 0x1F ; // TX2:27 TX3:2B
rx_tx_addr [ 3 ] = 0x61 ; // TX2:51 TX3:0C
2024-02-15 15:51:20 +01:00
memcpy ( hopping_frequency , " \x15 \x34 \x24 \x44 " , SGF22_RF_NUM_CHANNELS ) ; //Original dump=>21=0x15,52=0x34,36=0x24,68=0x44
# endif
2024-02-19 18:34:27 +01:00
#if 0
debug ( " ID: %02X %02X, C: " , rx_tx_addr [ 2 ] , rx_tx_addr [ 3 ] ) ;
for ( uint8_t i = 0 ; i < SGF22_RF_NUM_CHANNELS ; i + + )
debug ( " %02X " , hopping_frequency [ i ] ) ;
debugln ( " " ) ;
# endif
2024-02-15 15:51:20 +01:00
}
static void __attribute__ ( ( unused ) ) SGF22_RF_init ( )
{
XN297_Configure ( XN297_CRCEN , XN297_SCRAMBLED , XN297_1M ) ;
XN297_SetTXAddr ( ( uint8_t * ) " \xC7 \x95 \x3C \xBB \xA5 " , 5 ) ;
2024-10-09 10:09:21 +02:00
const uint8_t bind_chan [ ] = { SGF22_BIND_RF_CHANNEL , SGF22_F22S_BIND_RF_CHANNEL , SGF22_J20_BIND_RF_CHANNEL } ;
2024-09-26 01:11:19 -07:00
XN297_RFChannel ( bind_chan [ sub_protocol ] ) ; // Set bind channel
2024-02-15 15:51:20 +01:00
}
uint16_t SGF22_callback ( )
{
if ( phase = = 0 )
{
phase + + ;
# ifdef MULTI_SYNC
telemetry_set_input_sync ( SGF22_PACKET_PERIOD ) ;
# endif
SGF22_send_packet ( ) ;
if ( IS_BIND_IN_PROGRESS )
{
if ( - - bind_counter = = 0 )
BIND_DONE ;
}
}
else
{ //send 3 times in total the same packet
2024-02-15 16:28:52 +01:00
NRF24L01_Strobe ( REUSE_TX_PL ) ;
2024-02-15 15:51:20 +01:00
phase + + ;
if ( phase > 2 )
{
phase = 0 ;
return SGF22_PACKET_PERIOD - 2 * 1550 ;
}
}
return 1550 ;
}
void SGF22_init ( )
{
BIND_IN_PROGRESS ; // autobind protocol
SGF22_initialize_txid ( ) ;
SGF22_RF_init ( ) ;
bind_counter = SGF22_BIND_COUNT ;
2024-03-29 16:19:20 +01:00
packet_sent = packet_count = 0x26 ; // TX2:26 TX3:26
2024-02-15 15:51:20 +01:00
phase = 0 ;
}
# endif