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
2020-06-18 10:53:03 +02:00
//#define DSM_GR300
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
//During binding we will send BIND_COUNT/2 packets
//One packet each 10msec
2016-09-19 18:58:09 +02:00
# define DSM_BIND_COUNT 300
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
packet [ 11 ] = num_ch ;
2016-09-19 18:58:09 +02:00
if ( sub_protocol = = DSM2_22 )
2020-06-12 00:25:09 +02:00
packet [ 12 ] = num_ch < 8 ? 0x01 : 0x02 ; // DSM2/1024 1 or 2 packets depending on the number of channels
else if ( sub_protocol = = DSM2_11 )
2016-09-19 18:58:09 +02:00
packet [ 12 ] = 0x12 ; // DSM2/2048 2 packets
2020-06-12 00:25:09 +02:00
else if ( sub_protocol = = DSMX_22 )
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
2020-06-12 00:25:09 +02:00
else // DSMX_11 && DSM_AUTO
packet [ 12 ] = 0xb2 ; // DSMX/2048 2 packets
2016-09-19 18:58:09 +02:00
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 ] ;
DSM_read_code ( code , 0 , 8 , 8 ) ;
CYRF_ConfigDataCode ( code , 16 ) ;
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
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 ;
2016-03-13 09:29:25 +01:00
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
2016-09-21 14:29:09 +02:00
if ( sub_protocol = = DSMX_11 | | sub_protocol = = DSMX_22 )
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
2020-06-12 00:25:09 +02:00
{ //DSM2
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 ] ) ;
2016-09-19 18:58:09 +02:00
if ( sub_protocol = = DSM2_22 )
2020-06-12 00:25:09 +02:00
bits = 10 ; // Only DSM2_22 is using a resolution of 1024
2015-12-30 01:41:12 +01:00
}
2020-09-09 10:45:14 +02:00
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
2020-05-17 15:45:23 +02: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 )
value = Channel_data [ CH_TAER [ idx ] ] ; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
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
}
packet [ i * 2 + 2 ] = ( value > > 8 ) & 0xff ;
packet [ i * 2 + 3 ] = ( value > > 0 ) & 0xff ;
}
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 ;
}
2016-09-01 14:00:42 +02:00
uint16_t ReadDsm ( )
2015-12-30 01:41:12 +01:00
{
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
# ifdef DSM_GR300
uint16_t timing = 5000 + ( convert_channel_8b ( CH13 ) * 100 ) ;
debugln ( " T=%u " , timing ) ;
# endif
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 :
2016-09-23 16:01:18 +02:00
//64 SDR Mode is configured so only the 8 first values are needed but we need to write 16 values...
2020-05-18 01:13:08 +02:00
CYRF_ConfigDataCode ( ( const uint8_t * ) " \x98 \x88 \x1B \xE4 \x30 \x79 \x03 \x84 " , 16 ) ;
2020-06-12 00:25:09 +02:00
CYRF_SetTxRxMode ( RX_EN ) ; //Receive mode
CYRF_WriteRegister ( CYRF_05_RX_CTRL , 0x87 ) ; //Prepare to receive
bind_counter = 2 * DSM_BIND_COUNT ; //Timeout of 4.2s if no packet received
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 ( ) )
{
2020-06-12 00:25:09 +02:00
debug ( " Bind " ) ;
for ( uint8_t i = 0 ; i < 10 ; i + + )
debug ( " %02X " , packet_in [ i + 1 ] ) ;
debugln ( " " ) ;
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
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 ;
2016-09-19 18:58:09 +02:00
phase = DSM_CH1_WRITE_A ; // in fact phase++
2020-05-17 15:45:23 +02:00
DSM_set_sop_data_crc ( phase = = DSM_CH1_CHECK_A | | phase = = DSM_CH1_CHECK_B , sub_protocol = = DSMX_11 | | sub_protocol = = DSMX_22 ) ;
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
telemetry_set_input_sync ( 11000 ) ; // Always request 11ms spacing even if we don't use half of it in 22ms mode
# endif
2021-01-28 09:09:43 +01: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 :
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
2016-09-19 18:58:09 +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
2016-10-16 19:51:42 +02:00
if ( phase = = DSM_CH1_CHECK_A | | phase = = DSM_CH1_CHECK_B )
{
# 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
2020-05-17 15:45:23 +02:00
DSM_set_sop_data_crc ( phase = = DSM_CH1_CHECK_A | | phase = = DSM_CH1_CHECK_B , sub_protocol = = DSMX_11 | | sub_protocol = = DSMX_22 ) ;
2016-10-16 19:51:42 +02:00
phase + + ; // change from CH1_CHECK to CH2_WRITE
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
2020-06-18 10:53:03 +02:00
# ifdef DSM_GR300
if ( num_ch = = 3 )
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY ;
# 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
2019-06-23 17:13:30 +02:00
if ( phase = = DSM_CH2_READ_A & & ( sub_protocol = = DSM2_22 | | sub_protocol = = DSMX_22 ) & & 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 ;
2020-06-18 10:53:03 +02:00
# ifdef DSM_GR300
if ( num_ch = = 3 )
return timing ;
# 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
2020-05-17 15:45:23 +02:00
DSM_set_sop_data_crc ( phase = = DSM_CH1_CHECK_A | | phase = = DSM_CH1_CHECK_B , sub_protocol = = DSMX_11 | | sub_protocol = = DSMX_22 ) ;
2016-04-06 12:57:42 +02:00
return DSM_READ_DELAY ;
# else
// No telemetry
2020-05-17 15:45:23 +02:00
DSM_set_sop_data_crc ( phase = = DSM_CH1_CHECK_A | | phase = = DSM_CH1_CHECK_B , sub_protocol = = DSMX_11 | | sub_protocol = = DSMX_22 ) ;
2016-09-19 18:58:09 +02:00
if ( phase = = DSM_CH2_CHECK_A )
2015-12-30 01:41:12 +01:00
{
2019-06-23 17:13:30 +02:00
if ( num_ch > 7 | | sub_protocol = = DSM2_11 | | sub_protocol = = DSMX_11 )
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)
2020-06-18 10:53:03 +02:00
# ifdef DSM_GR300
if ( num_ch = = 3 )
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
# 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)
2020-06-18 10:53:03 +02:00
# ifdef DSM_GR300
if ( num_ch = = 3 )
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
# 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 ;
}
2016-09-01 14:00:42 +02:00
uint16_t initDsm ( )
2015-12-30 01:41:12 +01:00
{
2016-09-23 16:01:18 +02:00
CYRF_GetMfgData ( cyrfmfg_id ) ;
2016-04-06 12:57:42 +02:00
//Model match
2016-09-23 16:01:18 +02:00
cyrfmfg_id [ 3 ] ^ = RX_num ;
//Calc sop_col
sop_col = ( cyrfmfg_id [ 0 ] + cyrfmfg_id [ 1 ] + cyrfmfg_id [ 2 ] + 2 ) & 0x07 ;
2018-09-10 09:58:31 +02:00
//Fix for OrangeRX using wrong DSM_pncodes by preventing access to "Col 8"
2016-09-23 16:01:18 +02:00
if ( sop_col = = 0 )
{
2016-09-24 13:58:06 +02:00
cyrfmfg_id [ rx_tx_addr [ 0 ] % 3 ] ^ = 0x01 ; //Change a bit so sop_col will be different from 0
2016-09-23 16:01:18 +02:00
sop_col = ( cyrfmfg_id [ 0 ] + cyrfmfg_id [ 1 ] + cyrfmfg_id [ 2 ] + 2 ) & 0x07 ;
}
2020-05-17 15:45:23 +02:00
//Calc CRC seed
seed = ( cyrfmfg_id [ 0 ] < < 8 ) + cyrfmfg_id [ 1 ] ;
2016-09-23 16:01:18 +02:00
//Hopping frequencies
2016-09-19 18:58:09 +02:00
if ( sub_protocol = = DSMX_11 | | sub_protocol = = DSMX_22 )
2017-01-03 19:07:10 +01:00
DSM_calc_dsmx_channel ( ) ;
2015-12-30 01:41:12 +01:00
else
{
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 ] ;
}
//
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 ;
bind_counter = DSM_BIND_COUNT ;
2015-12-30 01:41:12 +01:00
}
else
2016-09-19 18:58:09 +02:00
phase = DSM_CHANSEL ; //
2015-12-30 01:41:12 +01:00
return 10000 ;
}
2017-04-12 16:10:18 +02:00
# endif