2015-12-30 01:41:12 +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/>.
*/
2016-09-01 14:00:42 +02:00
# if defined(DSM_CYRF6936_INO)
2015-12-30 01:41:12 +01:00
# include "iface_cyrf6936.h"
2020-09-09 10:45:14 +02:00
//#define DSM_DEBUG_FWD_PGM
2023-12-18 12:02:57 +01:00
//#define DEBUG_BIND 1
2020-06-18 10:53:03 +02:00
2023-08-27 15:08:10 +01:00
# define CLONE_BIT_MASK 0x20
2016-09-19 18:58:09 +02:00
# define DSM_BIND_CHANNEL 0x0d //13 This can be any odd channel
2015-12-30 01:41:12 +01:00
2023-12-18 12:02:57 +01:00
//During binding we will send BIND_COUNT packets
2015-12-30 01:41:12 +01:00
//One packet each 10msec
2023-12-18 12:02:57 +01:00
//
// Most RXs seems to work properly with a long BIND send count (3s): Spektrum, OrangeRX.
// Lemon-RX G2s seems to have a timeout waiting for the channel to get quiet after the
// first good BIND packet.. If using 3s (300), Lemon-RX will not transmit the BIND-Response packet.
# define DSM_BIND_COUNT 180 // About 1.8s
# define DSM_BIND_COUNT_READ 600 // About 4.2s of waiting for Response
2015-12-30 01:41:12 +01:00
enum {
2016-09-19 18:58:09 +02:00
DSM_BIND_WRITE = 0 ,
DSM_BIND_CHECK ,
DSM_BIND_READ ,
DSM_CHANSEL ,
DSM_CH1_WRITE_A ,
DSM_CH1_CHECK_A ,
DSM_CH2_WRITE_A ,
DSM_CH2_CHECK_A ,
DSM_CH2_READ_A ,
DSM_CH1_WRITE_B ,
DSM_CH1_CHECK_B ,
DSM_CH2_WRITE_B ,
DSM_CH2_CHECK_B ,
DSM_CH2_READ_B ,
2015-12-30 01:41:12 +01:00
} ;
2016-09-19 18:58:09 +02:00
//
uint8_t ch_map [ 14 ] ;
2018-09-10 09:58:31 +02:00
const uint8_t PROGMEM DSM_ch_map_progmem [ ] [ 14 ] = {
2020-06-12 00:25:09 +02:00
//22+11ms for 3..7 channels
{ 1 , 0 , 2 , 0xff , 0xff , 0xff , 0xff , 1 , 0 , 2 , 0xff , 0xff , 0xff , 0xff } , //3ch - Guess
2016-09-24 13:58:06 +02:00
{ 1 , 0 , 2 , 3 , 0xff , 0xff , 0xff , 1 , 0 , 2 , 3 , 0xff , 0xff , 0xff } , //4ch - Guess
{ 1 , 0 , 2 , 3 , 4 , 0xff , 0xff , 1 , 0 , 2 , 3 , 4 , 0xff , 0xff } , //5ch - Guess
{ 1 , 5 , 2 , 3 , 0 , 4 , 0xff , 1 , 5 , 2 , 3 , 0 , 4 , 0xff } , //6ch - HP6DSM
2020-06-12 00:25:09 +02:00
{ 1 , 5 , 2 , 4 , 3 , 6 , 0 , 1 , 5 , 2 , 4 , 3 , 6 , 0 } , //7ch - DX6i
2016-09-24 13:58:06 +02:00
//22ms for 8..12 channels
{ 1 , 5 , 2 , 3 , 6 , 0xff , 0xff , 4 , 0 , 7 , 0xff , 0xff , 0xff , 0xff } , //8ch - DX8/DX7
{ 1 , 5 , 2 , 3 , 6 , 0xff , 0xff , 4 , 0 , 7 , 8 , 0xff , 0xff , 0xff } , //9ch - Guess
{ 1 , 5 , 2 , 3 , 6 , 0xff , 0xff , 4 , 0 , 7 , 8 , 9 , 0xff , 0xff } , //10ch - Guess
{ 1 , 5 , 2 , 3 , 6 , 10 , 0xff , 4 , 0 , 7 , 8 , 9 , 0xff , 0xff } , //11ch - Guess
2020-06-13 16:20:51 +02:00
{ 1 , 5 , 2 , 4 , 6 , 10 , 0xff , 0 , 7 , 3 , 8 , 9 , 11 , 0xff } , //12ch - DX18/DX8G2
2020-06-12 00:25:09 +02:00
//11ms for 8..11 channels
2016-09-24 13:58:06 +02:00
{ 1 , 5 , 2 , 3 , 6 , 7 , 0xff , 1 , 5 , 2 , 4 , 0 , 0xff , 0xff } , //8ch - DX7
{ 1 , 5 , 2 , 3 , 6 , 7 , 0xff , 1 , 5 , 2 , 4 , 0 , 8 , 0xff } , //9ch - Guess
2020-06-13 16:20:51 +02:00
{ 1 , 5 , 2 , 3 , 4 , 8 , 9 , 1 , 5 , 2 , 3 , 0 , 7 , 6 } , //10ch - DX18
{ 1 , 5 , 2 , 3 , 4 , 8 , 9 , 1 , 10 , 2 , 3 , 0 , 7 , 6 } , //11ch - Guess
2016-09-24 13:58:06 +02:00
} ;
2016-09-19 18:58:09 +02:00
2017-01-03 19:07:10 +01:00
static void __attribute__ ( ( unused ) ) DSM_build_bind_packet ( )
2015-12-30 01:41:12 +01:00
{
uint8_t i ;
uint16_t sum = 384 - 0x10 ; //
2016-04-06 12:57:42 +02:00
packet [ 0 ] = 0xff ^ cyrfmfg_id [ 0 ] ;
packet [ 1 ] = 0xff ^ cyrfmfg_id [ 1 ] ;
2015-12-30 01:41:12 +01:00
packet [ 2 ] = 0xff ^ cyrfmfg_id [ 2 ] ;
2016-04-06 12:57:42 +02:00
packet [ 3 ] = 0xff ^ cyrfmfg_id [ 3 ] ;
2015-12-30 01:41:12 +01:00
packet [ 4 ] = packet [ 0 ] ;
packet [ 5 ] = packet [ 1 ] ;
packet [ 6 ] = packet [ 2 ] ;
packet [ 7 ] = packet [ 3 ] ;
for ( i = 0 ; i < 8 ; i + + )
sum + = packet [ i ] ;
packet [ 8 ] = sum > > 8 ;
packet [ 9 ] = sum & 0xff ;
2020-06-12 00:25:09 +02:00
packet [ 10 ] = 0x01 ; // ???
if ( sub_protocol = = DSM_AUTO )
packet [ 11 ] = 12 ;
else
2021-03-30 12:10:29 +02:00
packet [ 11 ] = num_ch ; // DX5 DSMR sends 0x48...
2016-09-19 18:58:09 +02:00
2021-03-30 12:10:29 +02:00
if ( sub_protocol = = DSMR )
packet [ 12 ] = 0xa2 ;
else if ( sub_protocol = = DSM2_1F )
packet [ 12 ] = num_ch < 8 ? 0x01 : 0x02 ; // DSM2/1024 1 or 2 packets depending on the number of channels
2021-03-04 10:08:52 +01:00
else if ( sub_protocol = = DSM2_2F )
2021-03-30 12:10:29 +02:00
packet [ 12 ] = 0x12 ; // DSM2/2048 2 packets
2021-03-04 10:08:52 +01:00
else if ( sub_protocol = = DSMX_1F )
2016-09-19 18:58:09 +02:00
# if defined DSM_TELEMETRY
packet [ 12 ] = 0xb2 ; // DSMX/2048 2 packets
# else
2019-06-23 17:13:30 +02:00
packet [ 12 ] = num_ch < 8 ? 0xa2 : 0xb2 ; // DSMX/2048 1 or 2 packets depending on the number of channels
2016-09-19 18:58:09 +02:00
# endif
2021-03-04 10:08:52 +01:00
else // DSMX_2F && DSM_AUTO
2021-03-30 12:10:29 +02:00
packet [ 12 ] = 0xb2 ; // DSMX/2048 2 packets
2020-06-12 00:25:09 +02:00
packet [ 13 ] = 0x00 ; //???
2015-12-30 01:41:12 +01:00
for ( i = 8 ; i < 14 ; i + + )
sum + = packet [ i ] ;
packet [ 14 ] = sum > > 8 ;
packet [ 15 ] = sum & 0xff ;
}
2017-01-03 19:07:10 +01:00
static void __attribute__ ( ( unused ) ) DSM_initialize_bind_phase ( )
2016-09-21 14:29:09 +02:00
{
CYRF_ConfigRFChannel ( DSM_BIND_CHANNEL ) ; //This seems to be random?
2016-09-23 16:01:18 +02:00
//64 SDR Mode is configured so only the 8 first values are needed but need to write 16 values...
2020-05-17 15:45:23 +02:00
uint8_t code [ 16 ] ;
2023-12-01 10:58:56 +01:00
DSM_read_code ( code , 0 , 8 ) ;
CYRF_ConfigDataCode ( code ) ;
2017-01-03 19:07:10 +01:00
DSM_build_bind_packet ( ) ;
2016-09-21 14:29:09 +02:00
}
2017-01-03 19:07:10 +01:00
static void __attribute__ ( ( unused ) ) DSM_update_channels ( )
2016-09-16 17:59:57 +02:00
{
2016-09-19 18:58:09 +02:00
prev_option = option ;
2020-06-12 00:25:09 +02:00
num_ch = option & 0x0F ; // Remove flags 0x80=max_throw, 0x40=11ms
if ( num_ch < 3 | | num_ch > 12 )
2019-06-23 17:13:30 +02:00
num_ch = 6 ; // Default to 6 channels if invalid choice...
2016-09-19 18:58:09 +02:00
2024-03-18 16:57:54 +01:00
# ifndef MULTI_AIR
if ( sub_protocol = = DSMR & & num_ch > 7 )
num_ch = 7 ; // Max 7 channels in DSMR
if ( sub_protocol = = DSM2_SFC & & num_ch > 3 )
num_ch = 3 ; // Max 3 channels in DSM2_SFC
# endif
2021-03-30 12:10:29 +02:00
2016-09-24 13:58:06 +02:00
// Create channel map based on number of channels and refresh rate
2020-06-12 00:25:09 +02:00
uint8_t idx = num_ch - 3 ;
if ( ( option & 0x40 ) & & num_ch > 7 & & num_ch < 12 )
idx + = 5 ; // In 11ms mode change index only for channels 8..11
2016-09-24 13:58:06 +02:00
for ( uint8_t i = 0 ; i < 14 ; i + + )
2018-09-10 09:58:31 +02:00
ch_map [ i ] = pgm_read_byte_near ( & DSM_ch_map_progmem [ idx ] [ i ] ) ;
2016-09-16 17:59:57 +02:00
}
2017-01-03 19:07:10 +01:00
static void __attribute__ ( ( unused ) ) DSM_build_data_packet ( uint8_t upper )
2015-12-30 01:41:12 +01:00
{
2016-09-19 18:58:09 +02:00
uint8_t bits = 11 ;
2023-08-27 15:08:10 +01:00
// Check if clone flag has changed
if ( ( prev_option & CLONE_BIT_MASK ) ! = ( option & CLONE_BIT_MASK ) )
{
DSM_init ( ) ;
prev_option ^ = CLONE_BIT_MASK ;
}
2016-09-19 18:58:09 +02:00
if ( prev_option ! = option )
2017-01-03 19:07:10 +01:00
DSM_update_channels ( ) ;
2016-09-19 18:58:09 +02:00
2021-03-30 12:10:29 +02:00
if ( sub_protocol = = DSMX_2F | | sub_protocol = = DSMX_1F )
2020-06-12 00:25:09 +02:00
{ //DSMX
2015-12-30 01:41:12 +01:00
packet [ 0 ] = cyrfmfg_id [ 2 ] ;
2016-04-06 12:57:42 +02:00
packet [ 1 ] = cyrfmfg_id [ 3 ] ;
2015-12-30 01:41:12 +01:00
}
else
2021-03-30 12:10:29 +02:00
{ //DSM2 && DSMR
2015-12-30 01:41:12 +01:00
packet [ 0 ] = ( 0xff ^ cyrfmfg_id [ 2 ] ) ;
2016-04-06 12:57:42 +02:00
packet [ 1 ] = ( 0xff ^ cyrfmfg_id [ 3 ] ) ;
2021-03-04 10:08:52 +01:00
if ( sub_protocol = = DSM2_1F )
bits = 10 ; // Only DSM2_1F is using a resolution of 1024
2015-12-30 01:41:12 +01:00
}
2020-09-09 10:45:14 +02:00
2024-02-23 11:05:02 +01:00
# ifndef MULTI_AIR
2024-03-18 16:57:54 +01:00
if ( sub_protocol = = DSMR | | sub_protocol = = DSM2_SFC )
2021-03-30 12:10:29 +02:00
{
2024-02-23 11:05:02 +01:00
for ( uint8_t i = 0 ; i < 7 ; i + + )
{
uint16_t value = 0x0000 ;
if ( i < num_ch )
value = Channel_data [ i ] < < 1 ;
packet [ i * 2 + 2 ] = ( value > > 8 ) & 0xff ;
packet [ i * 2 + 3 ] = ( value > > 0 ) & 0xff ;
}
return ;
2021-03-30 12:10:29 +02:00
}
2024-02-23 11:05:02 +01:00
# endif
2018-11-20 16:54:55 +01:00
# ifdef DSM_THROTTLE_KILL_CH
2018-11-23 10:03:55 +01:00
uint16_t kill_ch = Channel_data [ DSM_THROTTLE_KILL_CH - 1 ] ;
2018-11-20 16:54:55 +01:00
# endif
2016-09-19 18:58:09 +02:00
for ( uint8_t i = 0 ; i < 7 ; i + + )
2015-12-30 01:41:12 +01:00
{
2020-06-12 00:25:09 +02:00
uint8_t idx = ch_map [ ( upper ? 7 : 0 ) + i ] ; // 1,5,2,3,0,4
uint16_t value = 0xffff ;
if ( ( option & 0x40 ) = = 0 & & num_ch < 8 & & upper )
idx = 0xff ; // in 22ms do not transmit upper channels if <8, is it the right method???
2016-08-22 18:17:14 +02:00
if ( idx ! = 0xff )
2015-12-30 01:41:12 +01:00
{
2018-01-09 11:56:42 +01:00
/* Spektrum own remotes transmit normal values during bind and actually use this (e.g. Nano CP X) to
select the transmitter mode ( e . g . computer vs non - computer radio ) , so always send normal output */
2018-11-20 16:54:55 +01:00
# ifdef DSM_THROTTLE_KILL_CH
2019-10-08 18:52:47 +02:00
if ( idx = = CH1 & & kill_ch < = 604 )
{ //Activate throttle kill only if channel is throttle and DSM_THROTTLE_KILL_CH below -50%
2020-06-12 00:25:09 +02:00
if ( kill_ch < CHANNEL_MIN_100 ) // restrict val to 0...400
2018-11-20 16:54:55 +01:00
kill_ch = 0 ;
else
kill_ch - = CHANNEL_MIN_100 ;
2018-11-23 10:03:55 +01:00
value = ( kill_ch * 21 ) / 25 ; // kill channel -100%->904us ... -50%->1100us *0x150/400
2018-11-20 16:54:55 +01:00
}
else
2018-01-09 16:04:04 +01:00
# endif
2018-11-20 16:54:55 +01:00
# ifdef DSM_MAX_THROW
2021-03-13 11:01:51 +01:00
value = Channel_data [ CH_TAER [ idx ] ] ; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
2018-11-20 16:54:55 +01:00
# else
2019-11-05 19:12:06 +01:00
if ( option & 0x80 )
2021-03-13 11:01:51 +01:00
value = Channel_data [ CH_TAER [ idx ] ] ; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
2019-11-05 19:12:06 +01:00
else
2020-12-16 16:14:45 +01:00
value = convert_channel_16b_nolimit ( CH_TAER [ idx ] , 0x156 , 0x6AA , false ) ; // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on a DX8 G2 dump
2018-11-20 16:54:55 +01:00
# endif
2018-01-08 19:37:14 +01:00
if ( bits = = 10 ) value > > = 1 ;
2016-09-24 13:58:06 +02:00
value | = ( upper & & i = = 0 ? 0x8000 : 0 ) | ( idx < < bits ) ;
2015-12-30 01:41:12 +01:00
}
2021-03-30 12:10:29 +02:00
packet [ i * 2 + 2 ] = value > > 8 ;
packet [ i * 2 + 3 ] = value ;
2015-12-30 01:41:12 +01:00
}
2020-09-09 10:45:14 +02:00
# ifdef DSM_FWD_PGM
if ( upper = = 0 & & DSM_SerialRX & & ( DSM_SerialRX_val [ 0 ] & 0xF8 ) = = 0x70 )
{ // Send forward programming data if available
for ( uint8_t i = 0 ; i < ( DSM_SerialRX_val [ 0 ] & 0x07 ) ; i + + )
{
packet [ i * 2 + 4 ] = 0x70 + i ;
packet [ i * 2 + 5 ] = DSM_SerialRX_val [ i + 1 ] ;
}
DSM_SerialRX = false ;
2020-09-09 16:47:32 +02:00
# ifdef DSM_DEBUG_FWD_PGM
2020-09-09 10:45:14 +02:00
debug ( " FWD= " ) ;
for ( uint8_t i = 4 ; i < 16 ; i + + )
debug ( " %02X " , packet [ i ] ) ;
debugln ( " " ) ;
# endif
}
# endif
2015-12-30 01:41:12 +01:00
}
2016-09-19 18:58:09 +02:00
static uint8_t __attribute__ ( ( unused ) ) DSM_Check_RX_packet ( )
{
2020-06-13 16:20:51 +02:00
uint8_t result = 1 ; // assume good packet
2016-09-19 18:58:09 +02:00
uint16_t sum = 384 - 0x10 ;
for ( uint8_t i = 1 ; i < 9 ; i + + )
{
2019-09-30 17:35:12 +02:00
sum + = packet_in [ i ] ;
2016-09-19 18:58:09 +02:00
if ( i < 5 )
2019-09-30 17:35:12 +02:00
if ( packet_in [ i ] ! = ( 0xff ^ cyrfmfg_id [ i - 1 ] ) )
2020-06-13 16:20:51 +02:00
result = 0 ; // bad packet
2016-09-19 18:58:09 +02:00
}
2019-09-30 17:35:12 +02:00
if ( packet_in [ 9 ] ! = ( sum > > 8 ) & & packet_in [ 10 ] ! = ( uint8_t ) sum )
2016-09-19 18:58:09 +02:00
result = 0 ;
return result ;
}
2021-02-09 18:23:33 +01:00
uint16_t DSM_callback ( )
2015-12-30 01:41:12 +01:00
{
2022-11-17 10:29:53 +01:00
# if defined MULTI_EU
2024-03-18 16:57:54 +01:00
if ( sub_protocol = = DSM2_1F | | sub_protocol = = DSM2_2F | | sub_protocol = = DSM2_SFC )
{
SUB_PROTO_INVALID ;
2022-11-17 10:29:53 +01:00
return 11000 ;
2024-03-18 16:57:54 +01:00
}
2022-11-17 10:29:53 +01:00
# endif
2024-02-23 11:05:02 +01:00
# if defined MULTI_AIR
2024-03-18 16:57:54 +01:00
if ( sub_protocol = = DSMR | | sub_protocol = = DSM2_SFC )
{
SUB_PROTO_INVALID ;
2024-02-23 11:05:02 +01:00
return 11000 ;
2024-03-18 16:57:54 +01:00
}
2024-02-23 11:05:02 +01:00
# endif
2019-08-01 14:23:08 +02:00
# define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
# ifdef STM32_BOARD
2019-11-27 12:08:17 +01:00
# define DSM_WRITE_DELAY 1600 // Time after write to verify write complete
2019-08-01 14:23:08 +02:00
# else
# define DSM_WRITE_DELAY 1950 // Time after write to verify write complete
# endif
# define DSM_READ_DELAY 600 // Time before write to check read phase, and switch channels. Was 400 but 600 seems what the 328p needs to read a packet
2016-09-20 18:27:09 +02:00
# if defined DSM_TELEMETRY
uint8_t rx_phase ;
uint8_t len ;
# endif
2016-10-16 19:51:42 +02:00
uint8_t start ;
2020-06-18 10:53:03 +02:00
2016-09-19 18:58:09 +02:00
switch ( phase )
2015-12-30 01:41:12 +01:00
{
2016-09-19 18:58:09 +02:00
case DSM_BIND_WRITE :
if ( bind_counter - - = = 0 )
2016-09-20 18:27:09 +02:00
# if defined DSM_TELEMETRY
2020-06-12 00:25:09 +02:00
phase = DSM_BIND_CHECK ; //Check RX answer
2016-09-20 18:27:09 +02:00
# else
2020-06-12 00:25:09 +02:00
phase = DSM_CHANSEL ; //Switch to normal mode
2016-09-20 18:27:09 +02:00
# endif
2016-09-19 18:58:09 +02:00
CYRF_WriteDataPacket ( packet ) ;
return 10000 ;
2016-09-20 18:27:09 +02:00
# if defined DSM_TELEMETRY
2016-09-19 18:58:09 +02:00
case DSM_BIND_CHECK :
2023-12-18 12:02:57 +01:00
# if DEBUG_BIND
debugln ( " Bind Check " ) ;
# endif
//64 SDR Mode is configured so only the 8 first values are needed
CYRF_ConfigDataCode ( ( const uint8_t * ) " \x98 \x88 \x1B \xE4 \x30 \x79 \x03 \x84 " ) ;
2020-06-12 00:25:09 +02:00
CYRF_SetTxRxMode ( RX_EN ) ; //Receive mode
CYRF_WriteRegister ( CYRF_05_RX_CTRL , 0x87 ) ; //Prepare to receive
2023-12-18 12:02:57 +01:00
bind_counter = DSM_BIND_COUNT_READ ; //Timeout of 4.2s if no packet received
2020-06-12 00:25:09 +02:00
phase + + ; // change from BIND_CHECK to BIND_READ
2016-09-19 18:58:09 +02:00
return 2000 ;
case DSM_BIND_READ :
//Read data from RX
rx_phase = CYRF_ReadRegister ( CYRF_07_RX_IRQ_STATUS ) ;
2020-06-12 00:25:09 +02:00
if ( ( rx_phase & 0x03 ) = = 0x02 ) // RXC=1, RXE=0 then 2nd check is required (debouncing)
2016-09-19 18:58:09 +02:00
rx_phase | = CYRF_ReadRegister ( CYRF_07_RX_IRQ_STATUS ) ;
if ( ( rx_phase & 0x07 ) = = 0x02 )
2016-09-23 16:01:18 +02:00
{ // data received with no errors
2020-06-12 00:25:09 +02:00
CYRF_WriteRegister ( CYRF_07_RX_IRQ_STATUS , 0x80 ) ; // Need to set RXOW before data read
2020-05-17 15:45:23 +02:00
if ( CYRF_ReadRegister ( CYRF_09_RX_COUNT ) = = 10 ) // Len
2016-09-19 18:58:09 +02:00
{
2020-05-17 15:45:23 +02:00
CYRF_ReadDataPacketLen ( packet_in + 1 , 10 ) ;
if ( DSM_Check_RX_packet ( ) )
{
2023-12-18 12:02:57 +01:00
# if DEBUG_BIND
debug ( " Bind " ) ;
for ( uint8_t i = 0 ; i < 10 ; i + + )
debug ( " %02X " , packet_in [ i + 1 ] ) ;
debugln ( " " ) ;
# endif
2020-05-17 15:45:23 +02:00
packet_in [ 0 ] = 0x80 ;
2020-06-10 09:03:41 +02:00
packet_in [ 6 ] & = 0x0F ; // It looks like there is a flag 0x40 being added by some receivers
if ( packet_in [ 6 ] > 12 ) packet_in [ 6 ] = 12 ;
2020-06-12 00:25:09 +02:00
else if ( packet_in [ 6 ] < 3 ) packet_in [ 6 ] = 6 ;
2020-05-17 15:45:23 +02:00
telemetry_link = 1 ; // Send received data on serial
phase + + ;
return 2000 ;
}
2016-09-19 18:58:09 +02:00
}
2020-05-18 01:13:08 +02:00
CYRF_WriteRegister ( CYRF_29_RX_ABORT , 0x20 ) ; // Abort RX operation
CYRF_SetTxRxMode ( RX_EN ) ; // Force end state read
CYRF_WriteRegister ( CYRF_29_RX_ABORT , 0x00 ) ; // Clear abort RX operation
CYRF_WriteRegister ( CYRF_05_RX_CTRL , 0x83 ) ; // Prepare to receive
2016-09-16 17:59:57 +02:00
}
2016-09-23 16:01:18 +02:00
else
if ( ( rx_phase & 0x02 ) ! = 0x02 )
{ // data received with errors
CYRF_WriteRegister ( CYRF_29_RX_ABORT , 0x20 ) ; // Abort RX operation
CYRF_SetTxRxMode ( RX_EN ) ; // Force end state read
CYRF_WriteRegister ( CYRF_29_RX_ABORT , 0x00 ) ; // Clear abort RX operation
CYRF_WriteRegister ( CYRF_05_RX_CTRL , 0x83 ) ; // Prepare to receive
}
2016-09-19 23:43:14 +02:00
if ( - - bind_counter = = 0 )
2016-09-23 16:01:18 +02:00
{ // Exit if no answer has been received for some time
2023-12-18 12:02:57 +01:00
# if DEBUG_BIND
debugln ( " Bind Read TIMEOUT " ) ;
# endif
2020-05-17 15:45:23 +02:00
phase + + ; // DSM_CHANSEL
2016-09-19 23:43:14 +02:00
return 7000 ;
}
2016-09-19 18:58:09 +02:00
return 7000 ;
2016-09-20 18:27:09 +02:00
# endif
2016-09-19 18:58:09 +02:00
case DSM_CHANSEL :
2015-12-30 01:41:12 +01:00
BIND_DONE ;
2017-01-03 19:07:10 +01:00
DSM_cyrf_configdata ( ) ;
2015-12-30 01:41:12 +01:00
CYRF_SetTxRxMode ( TX_EN ) ;
2016-04-06 12:57:42 +02:00
hopping_frequency_no = 0 ;
2021-03-30 12:10:29 +02:00
phase = DSM_CH1_WRITE_A ; // in fact phase++
2024-03-18 16:57:54 +01:00
# ifndef MULTI_AIR
2021-03-30 12:10:29 +02:00
if ( sub_protocol = = DSMR )
DSM_set_sop_data_crc ( false , true ) ;
else
2024-03-18 16:57:54 +01:00
# endif
2021-03-30 12:10:29 +02:00
DSM_set_sop_data_crc ( true , sub_protocol = = DSMX_2F | | sub_protocol = = DSMX_1F ) ; //prep CH1
2015-12-30 01:41:12 +01:00
return 10000 ;
2016-09-19 18:58:09 +02:00
case DSM_CH1_WRITE_A :
2019-11-11 19:15:39 +01:00
# ifdef MULTI_SYNC
2024-03-18 16:57:54 +01:00
if ( sub_protocol ! = DSM2_SFC )
telemetry_set_input_sync ( 11000 ) ; // Always request 11ms spacing even if we don't use half of it in 22ms mode
else
telemetry_set_input_sync ( 6500 ) ;
2019-11-11 19:15:39 +01:00
# endif
2024-03-18 16:57:54 +01:00
# ifndef MULTI_AIR
2021-03-30 12:10:29 +02:00
if ( sub_protocol = = DSMR )
CYRF_SetPower ( 0x08 ) ; //Keep transmit power in sync
else
2024-03-18 16:57:54 +01:00
# endif
2021-03-30 12:10:29 +02:00
CYRF_SetPower ( 0x28 ) ; //Keep transmit power in sync
2016-09-19 18:58:09 +02:00
case DSM_CH1_WRITE_B :
2020-09-09 10:45:14 +02:00
DSM_build_data_packet ( phase = = DSM_CH1_WRITE_B ) ; // build lower or upper channels
2016-09-19 18:58:09 +02:00
case DSM_CH2_WRITE_A :
case DSM_CH2_WRITE_B :
2021-03-30 12:10:29 +02:00
CYRF_ReadRegister ( CYRF_04_TX_IRQ_STATUS ) ; // clear IRQ flags
2015-12-30 01:41:12 +01:00
CYRF_WriteDataPacket ( packet ) ;
2020-06-12 00:25:09 +02:00
#if 0
for ( uint8_t i = 0 ; i < 16 ; i + + )
debug ( " %02X " , packet [ i ] ) ;
debugln ( " " ) ;
# endif
2021-03-30 12:10:29 +02:00
phase + + ; // change from WRITE to CHECK mode
2016-04-06 12:57:42 +02:00
return DSM_WRITE_DELAY ;
2016-09-19 18:58:09 +02:00
case DSM_CH1_CHECK_A :
case DSM_CH1_CHECK_B :
case DSM_CH2_CHECK_A :
case DSM_CH2_CHECK_B :
2018-08-21 14:58:44 +02:00
start = ( uint8_t ) micros ( ) ;
while ( ( uint8_t ) ( ( uint8_t ) micros ( ) - ( uint8_t ) start ) < 100 ) // Wait max 100µs, max I've seen is 50µs
if ( ( CYRF_ReadRegister ( CYRF_02_TX_CTRL ) & 0x80 ) = = 0x00 )
2015-12-30 01:41:12 +01:00
break ;
2019-08-01 14:23:08 +02:00
2021-03-30 12:10:29 +02:00
if ( ( phase = = DSM_CH1_CHECK_A | | phase = = DSM_CH1_CHECK_B ) & & sub_protocol ! = DSMR )
2016-10-16 19:51:42 +02:00
{
# if defined DSM_TELEMETRY
// reset cyrf6936 if freezed after switching from TX to RX
if ( ( ( CYRF_ReadRegister ( CYRF_04_TX_IRQ_STATUS ) & 0x22 ) = = 0x20 ) | | ( CYRF_ReadRegister ( CYRF_02_TX_CTRL ) & 0x80 ) )
{
CYRF_Reset ( ) ;
2017-01-03 19:07:10 +01:00
DSM_cyrf_config ( ) ;
DSM_cyrf_configdata ( ) ;
2016-10-16 19:51:42 +02:00
CYRF_SetTxRxMode ( TX_EN ) ;
}
# endif
2021-03-30 12:10:29 +02:00
DSM_set_sop_data_crc ( true , sub_protocol = = DSMX_2F | | sub_protocol = = DSMX_1F ) ; // prep CH2
phase + + ; // change from CH1_CHECK to CH2_WRITE
2016-10-16 19:51:42 +02:00
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
}
2016-04-06 12:57:42 +02:00
# if defined DSM_TELEMETRY
2016-09-19 18:58:09 +02:00
phase + + ; // change from CH2_CHECK to CH2_READ
CYRF_SetTxRxMode ( RX_EN ) ; //Receive mode
CYRF_WriteRegister ( CYRF_05_RX_CTRL , 0x87 ) ; //0x80??? //Prepare to receive
2024-03-18 16:57:54 +01:00
# ifndef MULTI_AIR
if ( sub_protocol = = DSMR )
{
phase = DSM_CH2_READ_B ;
return 11000 - DSM_WRITE_DELAY - DSM_READ_DELAY ;
}
if ( sub_protocol = = DSM2_SFC )
return 6500 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY ;
2020-06-18 10:53:03 +02:00
# endif
2016-04-06 12:57:42 +02:00
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY ;
2016-09-19 18:58:09 +02:00
case DSM_CH2_READ_A :
case DSM_CH2_READ_B :
2016-04-06 12:57:42 +02:00
//Read telemetry
2016-09-19 18:58:09 +02:00
rx_phase = CYRF_ReadRegister ( CYRF_07_RX_IRQ_STATUS ) ;
if ( ( rx_phase & 0x03 ) = = 0x02 ) // RXC=1, RXE=0 then 2nd check is required (debouncing)
rx_phase | = CYRF_ReadRegister ( CYRF_07_RX_IRQ_STATUS ) ;
if ( ( rx_phase & 0x07 ) = = 0x02 )
2016-04-06 12:57:42 +02:00
{ // good data (complete with no errors)
CYRF_WriteRegister ( CYRF_07_RX_IRQ_STATUS , 0x80 ) ; // need to set RXOW before data read
2016-09-19 18:58:09 +02:00
len = CYRF_ReadRegister ( CYRF_09_RX_COUNT ) ;
2019-09-30 17:35:12 +02:00
if ( len > TELEMETRY_BUFFER_SIZE - 2 )
len = TELEMETRY_BUFFER_SIZE - 2 ;
CYRF_ReadDataPacketLen ( packet_in + 1 , len ) ;
2020-09-09 16:47:32 +02:00
# ifdef DSM_DEBUG_FWD_PGM
2020-09-09 10:45:14 +02:00
//debug(" %02X", packet_in[1]);
if ( packet_in [ 1 ] = = 9 )
{
for ( uint8_t i = 0 ; i < len ; i + + )
debug ( " %02X " , packet_in [ i + 1 ] ) ;
debugln ( " " ) ;
}
# endif
2019-09-30 17:35:12 +02:00
packet_in [ 0 ] = CYRF_ReadRegister ( CYRF_13_RSSI ) & 0x1F ; // store RSSI of the received telemetry signal
2016-04-06 12:57:42 +02:00
telemetry_link = 1 ;
}
2016-09-23 16:01:18 +02:00
CYRF_WriteRegister ( CYRF_29_RX_ABORT , 0x20 ) ; // Abort RX operation
2024-03-18 16:57:54 +01:00
if ( phase = = DSM_CH2_READ_A & & ( sub_protocol = = DSM2_1F | | sub_protocol = = DSMX_1F | | sub_protocol = = DSM2_SFC ) & & num_ch < 8 ) // 22ms mode
2016-04-06 12:57:42 +02:00
{
2016-09-23 16:01:18 +02:00
CYRF_SetTxRxMode ( RX_EN ) ; // Force end state read
CYRF_WriteRegister ( CYRF_29_RX_ABORT , 0x00 ) ; // Clear abort RX operation
2016-09-19 18:58:09 +02:00
CYRF_WriteRegister ( CYRF_05_RX_CTRL , 0x87 ) ; //0x80??? //Prepare to receive
2016-09-23 16:01:18 +02:00
phase = DSM_CH2_READ_B ;
2024-03-18 16:57:54 +01:00
# ifndef MULTI_AIR
if ( sub_protocol = = DSM2_SFC )
return 6500 ;
2020-06-18 10:53:03 +02:00
# endif
2016-04-06 12:57:42 +02:00
return 11000 ;
}
2016-09-19 18:58:09 +02:00
if ( phase = = DSM_CH2_READ_A )
phase = DSM_CH1_WRITE_B ; //Transmit upper
2016-04-06 12:57:42 +02:00
else
2016-09-19 18:58:09 +02:00
phase = DSM_CH1_WRITE_A ; //Transmit lower
2016-09-23 16:01:18 +02:00
CYRF_SetTxRxMode ( TX_EN ) ; //TX mode
CYRF_WriteRegister ( CYRF_29_RX_ABORT , 0x00 ) ; //Clear abort RX operation
2021-03-30 12:10:29 +02:00
DSM_set_sop_data_crc ( false , sub_protocol = = DSMX_2F | | sub_protocol = = DSMX_1F | | sub_protocol = = DSMR ) ;
2016-04-06 12:57:42 +02:00
return DSM_READ_DELAY ;
# else
// No telemetry
2021-03-04 10:08:52 +01:00
DSM_set_sop_data_crc ( phase = = DSM_CH1_CHECK_A | | phase = = DSM_CH1_CHECK_B , sub_protocol = = DSMX_2F | | sub_protocol = = DSMX_1F ) ;
2016-09-19 18:58:09 +02:00
if ( phase = = DSM_CH2_CHECK_A )
2015-12-30 01:41:12 +01:00
{
2021-03-04 10:08:52 +01:00
if ( num_ch > 7 | | sub_protocol = = DSM2_2F | | sub_protocol = = DSMX_2F )
2016-09-19 18:58:09 +02:00
phase = DSM_CH1_WRITE_B ; //11ms mode or upper to transmit change from CH2_CHECK_A to CH1_WRITE_A
else
{ //Normal mode 22ms
phase = DSM_CH1_WRITE_A ; // change from CH2_CHECK_A to CH1_WRITE_A (ie no upper)
2024-03-18 16:57:54 +01:00
# ifndef MULTI_AIR
if ( sub_protocol = = DSM2_SFC )
return 6500 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
2020-06-18 10:53:03 +02:00
# endif
2016-09-19 18:58:09 +02:00
return 22000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
2016-03-13 09:29:25 +01:00
}
2015-12-30 01:41:12 +01:00
}
else
2016-09-19 18:58:09 +02:00
phase = DSM_CH1_WRITE_A ; // change from CH2_CHECK_B to CH1_WRITE_A (upper already transmitted so transmit lower)
2024-03-18 16:57:54 +01:00
# ifndef MULTI_AIR
if ( sub_protocol = = DSM2_SFC )
return 6500 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
2020-06-18 10:53:03 +02:00
# endif
2016-04-06 12:57:42 +02:00
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
# endif
2015-12-30 01:41:12 +01:00
}
return 0 ;
}
2021-03-30 12:10:29 +02:00
2024-02-23 11:05:02 +01:00
# ifndef MULTI_AIR
2021-03-30 12:10:29 +02:00
const uint8_t PROGMEM DSMR_ID_FREQ [ ] [ 4 + 23 ] = {
{ 0x71 , 0x74 , 0x1c , 0xe4 , 0x11 , 0x2f , 0x17 , 0x3d , 0x23 , 0x3b , 0x0f , 0x21 , 0x25 , 0x49 , 0x1d , 0x13 , 0x4d , 0x1f , 0x41 , 0x4b , 0x47 , 0x05 , 0x27 , 0x15 , 0x19 , 0x3f , 0x07 } ,
{ 0xfe , 0xfe , 0xfe , 0xfe , 0x45 , 0x31 , 0x33 , 0x4b , 0x11 , 0x29 , 0x49 , 0x3f , 0x09 , 0x13 , 0x47 , 0x21 , 0x1d , 0x43 , 0x1f , 0x05 , 0x41 , 0x19 , 0x1b , 0x2d , 0x15 , 0x4d , 0x0f } ,
{ 0xfe , 0xff , 0xff , 0xff , 0x2a , 0x06 , 0x22 , 0x28 , 0x16 , 0x24 , 0x38 , 0x0e , 0x32 , 0x2e , 0x14 , 0x3a , 0x04 , 0x44 , 0x0c , 0x42 , 0x1c , 0x4a , 0x10 , 0x36 , 0x3c , 0x48 , 0x26 } ,
{ 0xff , 0xfe , 0xff , 0xff , 0x28 , 0x34 , 0x48 , 0x46 , 0x3a , 0x12 , 0x18 , 0x32 , 0x14 , 0x42 , 0x16 , 0x40 , 0x22 , 0x44 , 0x1c , 0x0a , 0x36 , 0x20 , 0x10 , 0x0c , 0x3c , 0x26 , 0x2e } ,
{ 0xff , 0xff , 0xfe , 0xff , 0x3c , 0x16 , 0x04 , 0x48 , 0x1e , 0x4a , 0x10 , 0x18 , 0x22 , 0x28 , 0x38 , 0x40 , 0x20 , 0x06 , 0x3e , 0x42 , 0x30 , 0x1a , 0x2c , 0x1c , 0x46 , 0x14 , 0x34 } ,
{ 0xff , 0xff , 0xff , 0xfe , 0x4d , 0x39 , 0x1b , 0x13 , 0x45 , 0x2f , 0x0d , 0x3d , 0x0b , 0x11 , 0x47 , 0x2d , 0x19 , 0x1d , 0x23 , 0x35 , 0x33 , 0x3b , 0x21 , 0x31 , 0x17 , 0x0f , 0x43 } ,
{ 0xff , 0xff , 0xff , 0xff , 0x14 , 0x28 , 0x2e , 0x32 , 0x3e , 0x10 , 0x38 , 0x0e , 0x12 , 0x06 , 0x2c , 0x26 , 0x30 , 0x4c , 0x34 , 0x16 , 0x04 , 0x3a , 0x42 , 0x48 , 0x36 , 0x46 , 0x1a } ,
{ 0x00 , 0xff , 0xff , 0xff , 0x3e , 0x30 , 0x42 , 0x24 , 0x06 , 0x0e , 0x14 , 0x1c , 0x08 , 0x10 , 0x20 , 0x22 , 0x04 , 0x32 , 0x0c , 0x44 , 0x3c , 0x46 , 0x4a , 0x26 , 0x4c , 0x48 , 0x1e } ,
{ 0xff , 0x00 , 0xff , 0xff , 0x38 , 0x0e , 0x22 , 0x2a , 0x44 , 0x3a , 0x4a , 0x3e , 0x16 , 0x20 , 0x36 , 0x24 , 0x46 , 0x18 , 0x1e , 0x12 , 0x1c , 0x30 , 0x2c , 0x14 , 0x06 , 0x0c , 0x40 } ,
{ 0x00 , 0x00 , 0xff , 0xff , 0x06 , 0x4c , 0x26 , 0x08 , 0x46 , 0x3e , 0x30 , 0x12 , 0x38 , 0x1c , 0x04 , 0x4a , 0x2c , 0x1a , 0x20 , 0x3a , 0x18 , 0x36 , 0x28 , 0x2e , 0x22 , 0x40 , 0x10 } ,
{ 0xff , 0xff , 0x00 , 0xff , 0x12 , 0x06 , 0x3c , 0x2a , 0x22 , 0x38 , 0x48 , 0x4c , 0x32 , 0x44 , 0x26 , 0x16 , 0x0c , 0x28 , 0x2c , 0x36 , 0x1c , 0x1a , 0x42 , 0x10 , 0x08 , 0x4a , 0x34 } ,
{ 0x00 , 0xff , 0x00 , 0xff , 0x04 , 0x4c , 0x4a , 0x28 , 0x2a , 0x24 , 0x14 , 0x1e , 0x40 , 0x48 , 0x44 , 0x2c , 0x2e , 0x1a , 0x12 , 0x46 , 0x3a , 0x0e , 0x18 , 0x1c , 0x20 , 0x10 , 0x42 } ,
{ 0xff , 0x00 , 0x00 , 0xff , 0x06 , 0x10 , 0x14 , 0x16 , 0x48 , 0x18 , 0x44 , 0x2c , 0x0a , 0x26 , 0x24 , 0x42 , 0x36 , 0x30 , 0x38 , 0x3e , 0x0c , 0x3c , 0x34 , 0x46 , 0x2a , 0x32 , 0x0e } ,
{ 0x00 , 0x00 , 0x00 , 0xff , 0x2c , 0x0a , 0x46 , 0x28 , 0x38 , 0x24 , 0x14 , 0x06 , 0x04 , 0x10 , 0x18 , 0x30 , 0x12 , 0x20 , 0x3a , 0x1a , 0x32 , 0x3c , 0x3e , 0x4a , 0x1e , 0x44 , 0x36 } ,
{ 0x00 , 0x00 , 0x00 , 0x00 , 0x45 , 0x23 , 0x07 , 0x37 , 0x4b , 0x13 , 0x3d , 0x31 , 0x19 , 0x2b , 0x2f , 0x2d , 0x1f , 0x4d , 0x3f , 0x1b , 0x43 , 0x27 , 0x3b , 0x11 , 0x05 , 0x0d , 0x17 } ,
{ 0xff , 0xff , 0xff , 0x00 , 0x0b , 0x4b , 0x1d , 0x39 , 0x09 , 0x0f , 0x49 , 0x25 , 0x07 , 0x35 , 0x3b , 0x05 , 0x33 , 0x17 , 0x2d , 0x11 , 0x2b , 0x29 , 0x1f , 0x45 , 0x1b , 0x41 , 0x47 } ,
{ 0x00 , 0xff , 0xff , 0x00 , 0x41 , 0x35 , 0x11 , 0x25 , 0x29 , 0x27 , 0x33 , 0x47 , 0x4d , 0x31 , 0x05 , 0x37 , 0x15 , 0x1f , 0x23 , 0x07 , 0x1b , 0x0f , 0x3b , 0x49 , 0x19 , 0x3f , 0x0b } ,
{ 0xff , 0x00 , 0xff , 0x00 , 0x25 , 0x47 , 0x05 , 0x0b , 0x45 , 0x1f , 0x2b , 0x27 , 0x2d , 0x09 , 0x07 , 0x43 , 0x49 , 0x29 , 0x4d , 0x39 , 0x33 , 0x41 , 0x17 , 0x0f , 0x15 , 0x19 , 0x3b } ,
{ 0x00 , 0x00 , 0xff , 0x00 , 0x3b , 0x05 , 0x21 , 0x0d , 0x1b , 0x43 , 0x17 , 0x2d , 0x1d , 0x25 , 0x4b , 0x35 , 0x4d , 0x3f , 0x07 , 0x09 , 0x37 , 0x41 , 0x15 , 0x1f , 0x0f , 0x27 , 0x29 } ,
{ 0xff , 0xff , 0x00 , 0x00 , 0x2b , 0x35 , 0x1b , 0x1d , 0x0f , 0x47 , 0x09 , 0x0d , 0x45 , 0x41 , 0x21 , 0x11 , 0x2f , 0x43 , 0x27 , 0x33 , 0x4b , 0x37 , 0x13 , 0x19 , 0x4d , 0x23 , 0x17 } ,
{ 0x00 , 0xff , 0x00 , 0x00 , 0x1b , 0x1d , 0x33 , 0x13 , 0x2b , 0x27 , 0x09 , 0x41 , 0x25 , 0x17 , 0x19 , 0x2d , 0x4b , 0x37 , 0x45 , 0x11 , 0x21 , 0x0d , 0x3d , 0x4d , 0x07 , 0x39 , 0x43 } ,
{ 0xff , 0x00 , 0x00 , 0x00 , 0x37 , 0x27 , 0x43 , 0x4b , 0x39 , 0x13 , 0x07 , 0x0d , 0x25 , 0x17 , 0x29 , 0x1b , 0x1d , 0x45 , 0x19 , 0x2d , 0x0b , 0x3d , 0x15 , 0x47 , 0x1f , 0x21 , 0x4d } } ;
2024-02-23 11:05:02 +01:00
# endif
2021-03-30 12:10:29 +02:00
2021-02-09 18:23:33 +01:00
void DSM_init ( )
2015-12-30 01:41:12 +01:00
{
2021-03-30 12:10:29 +02:00
if ( sub_protocol = = DSMR )
{
2024-02-23 11:05:02 +01:00
# ifndef MULTI_AIR
if ( option & CLONE_BIT_MASK )
SUB_PROTO_INVALID ;
else
{
2024-03-18 16:57:54 +01:00
//SUB_PROTO_VALID;
2024-02-23 11:05:02 +01:00
uint8_t row = rx_tx_addr [ 3 ] % 22 ;
for ( uint8_t i = 0 ; i < 4 ; i + + )
cyrfmfg_id [ i ] = pgm_read_byte_near ( & DSMR_ID_FREQ [ row ] [ i ] ) ;
for ( uint8_t i = 0 ; i < 23 ; i + + )
hopping_frequency [ i ] = pgm_read_byte_near ( & DSMR_ID_FREQ [ row ] [ i + 4 ] ) ;
}
# endif
2021-03-30 12:10:29 +02:00
}
else
{
2023-08-27 15:08:10 +01:00
if ( option & CLONE_BIT_MASK )
{
if ( eeprom_read_byte ( ( EE_ADDR ) DSM_CLONE_EEPROM_OFFSET + 4 ) = = 0xF0 )
{
//read cloned ID from EEPROM
uint16_t temp = DSM_CLONE_EEPROM_OFFSET ;
for ( uint8_t i = 0 ; i < 4 ; i + + )
cyrfmfg_id [ i ] = eeprom_read_byte ( ( EE_ADDR ) temp + + ) ;
2024-03-18 16:57:54 +01:00
# if DEBUG_BIND
debugln ( " Using cloned ID " ) ;
debug ( " Clone ID= " )
for ( uint8_t i = 0 ; i < 4 ; i + + )
debug ( " %02x " , cyrfmfg_id [ i ] ) ;
debugln ( " " ) ;
# endif
2023-08-27 15:08:10 +01:00
}
else
{
SUB_PROTO_INVALID ;
2024-03-18 16:57:54 +01:00
# if DEBUG_BIND
2023-12-18 12:02:57 +01:00
debugln ( " No valid cloned ID " ) ;
2024-03-18 16:57:54 +01:00
# endif
2023-08-27 15:08:10 +01:00
}
}
else
{
2024-03-18 16:57:54 +01:00
//SUB_PROTO_VALID;
2023-08-27 15:08:10 +01:00
CYRF_GetMfgData ( cyrfmfg_id ) ;
}
2021-03-30 12:10:29 +02:00
}
2023-08-27 15:08:10 +01:00
//Model match
cyrfmfg_id [ 3 ] ^ = RX_num ;
2021-03-30 12:10:29 +02:00
2016-09-23 16:01:18 +02:00
//Calc sop_col
sop_col = ( cyrfmfg_id [ 0 ] + cyrfmfg_id [ 1 ] + cyrfmfg_id [ 2 ] + 2 ) & 0x07 ;
2021-03-30 12:10:29 +02:00
2023-08-27 15:08:10 +01:00
//We cannot manipulate the ID if we are cloning
if ( ! ( option & CLONE_BIT_MASK ) )
{
//Fix for OrangeRX using wrong DSM_pncodes by preventing access to "Col 8"
if ( sop_col = = 0 & & sub_protocol ! = DSMR )
{
2024-03-18 16:57:54 +01:00
cyrfmfg_id [ rx_tx_addr [ 0 ] % 3 ] ^ = 0x01 ; //Change a bit so sop_col will be different from 0
sop_col = ( cyrfmfg_id [ 0 ] + cyrfmfg_id [ 1 ] + cyrfmfg_id [ 2 ] + 2 ) & 0x07 ;
2023-08-27 15:08:10 +01:00
}
2016-09-23 16:01:18 +02:00
}
2021-03-30 12:10:29 +02:00
2020-05-17 15:45:23 +02:00
//Calc CRC seed
seed = ( cyrfmfg_id [ 0 ] < < 8 ) + cyrfmfg_id [ 1 ] ;
2021-03-30 12:10:29 +02:00
2016-09-23 16:01:18 +02:00
//Hopping frequencies
2021-03-04 10:08:52 +01:00
if ( sub_protocol = = DSMX_2F | | sub_protocol = = DSMX_1F )
2017-01-03 19:07:10 +01:00
DSM_calc_dsmx_channel ( ) ;
2021-03-30 12:10:29 +02:00
else if ( sub_protocol ! = DSMR )
2015-12-30 01:41:12 +01:00
{
uint8_t tmpch [ 10 ] ;
CYRF_FindBestChannels ( tmpch , 10 , 5 , 3 , 75 ) ;
//
uint8_t idx = random ( 0xfefefefe ) % 10 ;
hopping_frequency [ 0 ] = tmpch [ idx ] ;
while ( 1 )
{
idx = random ( 0xfefefefe ) % 10 ;
if ( tmpch [ idx ] ! = hopping_frequency [ 0 ] )
break ;
}
hopping_frequency [ 1 ] = tmpch [ idx ] ;
}
2021-03-30 12:10:29 +02:00
2015-12-30 01:41:12 +01:00
//
2017-01-03 19:07:10 +01:00
DSM_cyrf_config ( ) ;
2015-12-30 01:41:12 +01:00
CYRF_SetTxRxMode ( TX_EN ) ;
//
2017-01-03 19:07:10 +01:00
DSM_update_channels ( ) ;
2016-09-23 16:01:18 +02:00
//
2018-01-03 13:04:58 +01:00
if ( IS_BIND_IN_PROGRESS )
2015-12-30 01:41:12 +01:00
{
2017-01-03 19:07:10 +01:00
DSM_initialize_bind_phase ( ) ;
2016-09-19 18:58:09 +02:00
phase = DSM_BIND_WRITE ;
2024-03-18 16:57:54 +01:00
bind_counter = DSM_BIND_COUNT ;
# if DEBUG_BIND
debugln ( " Bind Started: write count=%d " , bind_counter ) ;
# endif
2015-12-30 01:41:12 +01:00
}
else
2023-12-18 12:02:57 +01:00
phase = DSM_CHANSEL ;
2015-12-30 01:41:12 +01:00
}
2017-04-12 16:10:18 +02:00
# endif