Add more protocols which can run with the CC2500

Use CC2500 only when emulating NRF250K/XN297_250K
This commit is contained in:
Pascal Langer 2021-02-16 19:06:23 +01:00
parent 49c3af12f9
commit 0844ec2efd
20 changed files with 1067 additions and 1111 deletions

View File

@ -14,7 +14,7 @@ Multiprotocol is distributed in the hope that it will be useful,
*/ */
// Compatible with GD005 C-17 and GD006 DA62 planes. // Compatible with GD005 C-17 and GD006 DA62 planes.
#if defined(GD00X_NRF24L01_INO) #if defined(GD00X_CCNRF_INO)
#include "iface_nrf250k.h" #include "iface_nrf250k.h"

View File

@ -14,7 +14,7 @@ Multiprotocol is distributed in the hope that it will be useful,
*/ */
// Compatible with KF606 plane. // Compatible with KF606 plane.
#if defined(KF606_NRF24L01_INO) #if defined(KF606_CCNRF_INO)
#include "iface_nrf250k.h" #include "iface_nrf250k.h"
@ -93,7 +93,7 @@ uint16_t KF606_callback()
if(--bind_counter==0) if(--bind_counter==0)
{ {
BIND_DONE; BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 3); XN297L_SetTXAddr(rx_tx_addr, 3);
} }
KF606_send_packet(); KF606_send_packet();
return KF606_PACKET_PERIOD; return KF606_PACKET_PERIOD;

View File

@ -277,7 +277,7 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(FY326_NRF24L01_INO) #if defined(FY326_NRF24L01_INO)
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback }, {PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
#endif #endif
#if defined(GD00X_NRF24L01_INO) #if defined(GD00X_CCNRF_INO)
{PROTO_GD00X, STR_GD00X, STR_SUBTYPE_GD00X, 2, OPTION_RFTUNE, 0, 0, SW_NRF, GD00X_init, GD00X_callback }, {PROTO_GD00X, STR_GD00X, STR_SUBTYPE_GD00X, 2, OPTION_RFTUNE, 0, 0, SW_NRF, GD00X_init, GD00X_callback },
#endif #endif
#if defined(GW008_NRF24L01_INO) #if defined(GW008_NRF24L01_INO)
@ -310,7 +310,7 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(JJRC345_NRF24L01_INO) #if defined(JJRC345_NRF24L01_INO)
{PROTO_JJRC345, STR_JJRC345, STR_SUBTYPE_JJRC345, 2, OPTION_NONE, 0, 0, SW_NRF, JJRC345_init, JJRC345_callback }, {PROTO_JJRC345, STR_JJRC345, STR_SUBTYPE_JJRC345, 2, OPTION_NONE, 0, 0, SW_NRF, JJRC345_init, JJRC345_callback },
#endif #endif
#if defined(KF606_NRF24L01_INO) #if defined(KF606_CCNRF_INO)
{PROTO_KF606, STR_KF606, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback }, {PROTO_KF606, STR_KF606, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
#endif #endif
#if defined(KN_NRF24L01_INO) #if defined(KN_NRF24L01_INO)
@ -352,7 +352,7 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(Q303_NRF24L01_INO) #if defined(Q303_NRF24L01_INO)
{PROTO_Q303, STR_Q303, STR_SUBTYPE_Q303, 4, OPTION_NONE, 0, 0, SW_NRF, Q303_init, Q303_callback }, {PROTO_Q303, STR_Q303, STR_SUBTYPE_Q303, 4, OPTION_NONE, 0, 0, SW_NRF, Q303_init, Q303_callback },
#endif #endif
#if defined(Q90C_NRF24L01_INO) #if defined(Q90C_CCNRF_INO)
{PROTO_Q90C, STR_Q90C, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, Q90C_init, Q90C_callback }, {PROTO_Q90C, STR_Q90C, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, Q90C_init, Q90C_callback },
#endif #endif
#if defined(RLINK_CC2500_INO) #if defined(RLINK_CC2500_INO)
@ -373,7 +373,7 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(SKYARTEC_CC2500_INO) #if defined(SKYARTEC_CC2500_INO)
{PROTO_SKYARTEC, STR_SKYARTEC, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 1, SW_CC2500, SKYARTEC_init, SKYARTEC_callback }, {PROTO_SKYARTEC, STR_SKYARTEC, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 1, SW_CC2500, SKYARTEC_init, SKYARTEC_callback },
#endif #endif
#if defined(SLT_NRF24L01_INO) #if defined(SLT_CCNRF_INO)
{PROTO_SLT, STR_SLT, STR_SUBTYPE_SLT, 5, OPTION_RFTUNE, 0, 1, SW_NRF, SLT_init, SLT_callback }, {PROTO_SLT, STR_SLT, STR_SUBTYPE_SLT, 5, OPTION_RFTUNE, 0, 1, SW_NRF, SLT_init, SLT_callback },
#endif #endif
#if defined(SYMAX_NRF24L01_INO) #if defined(SYMAX_NRF24L01_INO)
@ -391,7 +391,7 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(V761_NRF24L01_INO) #if defined(V761_NRF24L01_INO)
{PROTO_V761, STR_V761, STR_SUBTYPE_V761, 2, OPTION_NONE, 0, 0, SW_NRF, V761_init, V761_callback }, {PROTO_V761, STR_V761, STR_SUBTYPE_V761, 2, OPTION_NONE, 0, 0, SW_NRF, V761_init, V761_callback },
#endif #endif
#if defined(V911S_NRF24L01_INO) #if defined(V911S_CCNRF_INO)
{PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback }, {PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback },
#endif #endif
#if defined(WK2x01_CYRF6936_INO) #if defined(WK2x01_CYRF6936_INO)

View File

@ -19,7 +19,7 @@
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 3 #define VERSION_MINOR 3
#define VERSION_REVISION 2 #define VERSION_REVISION 2
#define VERSION_PATCH_LEVEL 45 #define VERSION_PATCH_LEVEL 46
//****************** //******************
// Protocols // Protocols

View File

@ -1075,6 +1075,23 @@ inline void tx_resume()
#endif #endif
} }
void rf_switch(uint8_t comp)
{
PE1_off;
PE2_off;
switch(comp)
{
case SW_CC2500:
PE2_on;
break;
case SW_CYRF:
PE2_on;
case SW_NRF:
PE1_on;
break;
}
}
// Protocol start // Protocol start
static void protocol_init() static void protocol_init()
{ {
@ -1144,19 +1161,7 @@ static void protocol_init()
//Save index //Save index
multi_protocols_index = index; multi_protocols_index = index;
//Set the RF switch //Set the RF switch
PE1_off; rf_switch(multi_protocols[multi_protocols_index].rfSwitch);
PE2_off;
switch(multi_protocols[multi_protocols_index].rfSwitch)
{
case SW_CC2500:
PE2_on;
break;
case SW_CYRF:
PE2_on;
case SW_NRF:
PE1_on;
break;
}
//Init protocol //Init protocol
multi_protocols[multi_protocols_index].Init(); multi_protocols[multi_protocols_index].Init();
//Save call back function address //Save call back function address

View File

@ -16,7 +16,7 @@
#ifdef NRF24L01_INSTALLED #ifdef NRF24L01_INSTALLED
#include "iface_nrf24l01.h" #include "iface_nrf24l01.h"
#include "iface_xn297.h"
//--------------------------- //---------------------------
// NRF24L01+ SPI Specific Functions // NRF24L01+ SPI Specific Functions
@ -250,319 +250,6 @@ uint8_t NRF24L01_packet_ack()
return PKT_PENDING; return PKT_PENDING;
} }
///////////////
// XN297 emulation layer
uint8_t xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
uint8_t xn297_addr_len;
uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5];
uint8_t xn297_crc = 0;
// xn297 address / pcf / payload scramble table
const uint8_t xn297_scramble[] = {
0xE3, 0xB1, 0x4B, 0xEA, 0x85, 0xBC, 0xE5, 0x66,
0x0D, 0xAE, 0x8C, 0x88, 0x12, 0x69, 0xEE, 0x1F,
0xC7, 0x62, 0x97, 0xD5, 0x0B, 0x79, 0xCA, 0xCC,
0x1B, 0x5D, 0x19, 0x10, 0x24, 0xD3, 0xDC, 0x3F,
0x8E, 0xC5, 0x2F, 0xAA, 0x16, 0xF3, 0x95 };
// scrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
0x2138, 0x129F, 0xB3A0, 0x2988, 0x23CA, 0xC0CB,
0x0C6C, 0xB329, 0xA0A1, 0x0A16, 0xA9D0 };
// unscrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3D5F, 0xA6F1, 0x3A23, 0xAA16, 0x1CAF,
0x62B2, 0xE0EB, 0x0821, 0xBE07, 0x5F1A, 0xAF15,
0x4F0A, 0xAD24, 0x5E48, 0xED34, 0x068C, 0xF2C9,
0x1852, 0xDF36, 0x129D, 0xB17C, 0xD5F5, 0x70D7,
0xB798, 0x5133, 0x67DB, 0xD94E, 0x0A5B, 0xE445,
0xE6A5, 0x26E7, 0xBDAB, 0xC379, 0x8E20 };
// scrambled enhanced mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled_enhanced[] = {
0x0000, 0x7EBF, 0x3ECE, 0x07A4, 0xCA52, 0x343B,
0x53F8, 0x8CD0, 0x9EAC, 0xD0C0, 0x150D, 0x5186,
0xD251, 0xA46F, 0x8435, 0xFA2E, 0x7EBD, 0x3C7D,
0x94E0, 0x3D5F, 0xA685, 0x4E47, 0xF045, 0xB483,
0x7A1F, 0xDEA2, 0x9642, 0xBF4B, 0x032F, 0x01D2,
0xDC86, 0x92A5, 0x183A, 0xB760, 0xA953 };
// unscrambled enhanced mode crc xorout table
// unused so far
#ifdef XN297DUMP_NRF24L01_INO
const uint16_t xn297_crc_xorout_enhanced[] = {
0x0000, 0x8BE6, 0xD8EC, 0xB87A, 0x42DC, 0xAA89,
0x83AF, 0x10E4, 0xE83E, 0x5C29, 0xAC76, 0x1C69,
0xA4B2, 0x5961, 0xB4D3, 0x2A50, 0xCB27, 0x5128,
0x7CDB, 0x7A14, 0xD5D2, 0x57D7, 0xE31D, 0xCE42,
0x648D, 0xBF2D, 0x653B, 0x190C, 0x9117, 0x9A97,
0xABFC, 0xE68E, 0x0DE7, 0x28A2, 0x1965 };
#endif
void XN297_SetTXAddr(const uint8_t* addr, uint8_t len)
{
if (len > 5) len = 5;
if (len < 3) len = 3;
uint8_t buf[] = { 0x55, 0x0F, 0x71, 0x0C, 0x00 }; // bytes for XN297 preamble 0xC710F55 (28 bit)
xn297_addr_len = len;
if (xn297_addr_len < 4)
for (uint8_t i = 0; i < 4; ++i)
buf[i] = buf[i+1];
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, buf, 5);
// Receive address is complicated. We need to use scrambled actual address as a receive address
// but the TX code now assumes fixed 4-byte transmit address for preamble. We need to adjust it
// first. Also, if the scrambled address begins with 1 nRF24 will look for preamble byte 0xAA
// instead of 0x55 to ensure enough 0-1 transitions to tune the receiver. Still need to experiment
// with receiving signals.
memcpy(xn297_tx_addr, addr, len);
}
void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
{
if (len > 5) len = 5;
if (len < 3) len = 3;
uint8_t buf[] = { 0, 0, 0, 0, 0 };
memcpy(buf, addr, len);
memcpy(xn297_rx_addr, addr, len);
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
buf[i] = xn297_rx_addr[i];
if(xn297_scramble_enabled)
buf[i] ^= xn297_scramble[xn297_addr_len-i-1];
}
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
}
void XN297_Configure(uint8_t flags)
{
xn297_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
}
void XN297_SetScrambledMode(const uint8_t mode)
{
xn297_scramble_enabled = mode;
}
void XN297_WritePayload(uint8_t* msg, uint8_t len)
{
uint8_t buf[32];
uint8_t last = 0;
if (xn297_addr_len < 4)
{
// If address length (which is defined by receive address length)
// is less than 4 the TX address can't fit the preamble, so the last
// byte goes here
buf[last++] = 0x55;
}
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[i];
last++;
}
for (uint8_t i = 0; i < len; ++i)
{
// bit-reverse bytes in packet
buf[last] = bit_reverse(msg[i]);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[xn297_addr_len+i];
last++;
}
if (xn297_crc)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc16_update( buf[i], 8);
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
}
NRF24L01_WritePayload(buf, last);
}
void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{
uint8_t packet[32];
uint8_t scramble_index=0;
uint8_t last = 0;
static uint8_t pid=0;
// address
if (xn297_addr_len < 4)
{
// If address length (which is defined by receive address length)
// is less than 4 the TX address can't fit the preamble, so the last
// byte goes here
packet[last++] = 0x55;
}
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
packet[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
last++;
}
// pcf
packet[last] = (len << 1) | (pid>>1);
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
last++;
packet[last] = (pid << 7) | (noack << 6);
// payload
packet[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
for (uint8_t i = 0; i < len-1; ++i)
{
last++;
packet[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
}
last++;
packet[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++] & 0xc0;
// crc
if (xn297_crc)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc16_update( packet[i], 8);
crc16_update( packet[last] & 0xc0, 2);
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
//else
// crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
packet[last++] |= (crc >> 8) >> 2;
packet[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
packet[last++] = (crc & 0xff) << 6;
}
NRF24L01_WritePayload(packet, last);
pid++;
if(pid>3)
pid=0;
}
boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget if using CRC to do a +2 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buf[32];
if (xn297_crc)
NRF24L01_ReadPayload(buf, len+2); // Read payload + CRC
else
NRF24L01_ReadPayload(buf, len);
// Decode payload
for(uint8_t i=0; i<len; i++)
{
uint8_t b_in=buf[i];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i+xn297_addr_len];
msg[i] = bit_reverse(b_in);
}
if (!xn297_crc)
return true; // No CRC so OK by default...
// Calculate CRC
crc = 0xb5d2;
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc16_update( b_in, 8);
}
//process payload
for (uint8_t i = 0; i < len; ++i)
crc16_update( buf[i], 8);
//xorout
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
//test
if( (crc >> 8) == buf[len] && (crc & 0xff) == buf[len+1])
return true; // CRC OK
return false; // CRC NOK
}
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget do a +2 and if using CRC add +4 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buffer[32];
uint8_t pcf_size; // pcf payload size
if (xn297_crc)
NRF24L01_ReadPayload(buffer, len+4); // Read pcf + payload + CRC
else
NRF24L01_ReadPayload(buffer, len+2); // Read pcf + payload
pcf_size = buffer[0];
if(xn297_scramble_enabled)
pcf_size ^= xn297_scramble[xn297_addr_len];
pcf_size = pcf_size >> 1;
for(int i=0; i<len; i++)
{
msg[i] = bit_reverse((buffer[i+1] << 2) | (buffer[i+2] >> 6));
if(xn297_scramble_enabled)
msg[i] ^= bit_reverse((xn297_scramble[xn297_addr_len+i+1] << 2) |
(xn297_scramble[xn297_addr_len+i+2] >> 6));
}
if (!xn297_crc)
return pcf_size; // No CRC so OK by default...
// Calculate CRC
crc = 0xb5d2;
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc16_update( b_in, 8);
}
//process payload
for (uint8_t i = 0; i < len+1; ++i)
crc16_update( buffer[i], 8);
crc16_update( buffer[len+1] & 0xc0, 2);
//xorout
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
#ifdef XN297DUMP_NRF24L01_INO
else
crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
#endif
uint16_t crcxored=(buffer[len+1]<<10)|(buffer[len+2]<<2)|(buffer[len+3]>>6) ;
if( crc == crcxored)
return pcf_size; // CRC OK
return 0; // CRC NOK
}
// End of XN297 emulation
// //
// HS6200 emulation layer // HS6200 emulation layer
/////////////////////////// ///////////////////////////

View File

@ -12,65 +12,42 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef NRF24L01_INSTALLED #if defined(CC2500_INSTALLED) || defined(NRF24L01_INSTALLED)
#include "iface_nrf250k.h" #include "iface_nrf250k.h"
#include "iface_xn297.h"
static void __attribute__((unused)) XN297L_Init() static void __attribute__((unused)) XN297L_Init()
{ {
prev_option = option;
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
debugln("Using NRF");
PE1_on; //NRF24L01 antenna RF3 by default
PE2_off; //NRF24L01 antenna RF3 by default
NRF24L01_Initialize();
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
return;
}
//CC2500 //CC2500
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
debugln("Using CC2500"); debugln("Using CC2500");
xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
PE1_off; // antenna RF2 rf_switch(SW_CC2500);
PE2_on;
CC2500_250K_Init(); CC2500_250K_Init();
#elif defined(NRF24L01_INSTALLED)
debugln("Using NRF");
rf_switch(SW_NRF);
NRF24L01_Initialize();
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
#endif #endif
} }
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len) static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len)
{ {
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0)
#endif
{//NRF
XN297_SetTXAddr(addr,len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
if (len > 5) len = 5; if (len > 5) len = 5;
if (len < 3) len = 3; if (len < 3) len = 3;
xn297_addr_len = len; xn297_addr_len = len;
memcpy(xn297_tx_addr, addr, len); memcpy(xn297_tx_addr, addr, len);
#elif defined(NRF24L01_INSTALLED)
XN297_SetTXAddr(addr,len);
#endif #endif
} }
static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len) static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len)
{ {
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0)
#endif
{//NRF
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(msg, len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
uint8_t buf[32]; uint8_t buf[32];
uint8_t last = 0; uint8_t last = 0;
uint8_t i; uint8_t i;
@ -116,23 +93,17 @@ static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t le
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last); CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
// transmit // transmit
CC2500_Strobe(CC2500_STX); CC2500_Strobe(CC2500_STX);
#elif defined(NRF24L01_INSTALLED)
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(msg, len);
#endif #endif
} }
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack) static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{ {
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0)
#endif
{//NRF
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WriteEnhancedPayload(msg, len, noack);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
uint8_t buf[32]; uint8_t buf[32];
uint8_t scramble_index=0; uint8_t scramble_index=0;
uint8_t last = 0; uint8_t last = 0;
@ -204,75 +175,54 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last); CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
// transmit // transmit
CC2500_Strobe(CC2500_STX); CC2500_Strobe(CC2500_STX);
#elif defined(NRF24L01_INSTALLED)
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WriteEnhancedPayload(msg, len, noack);
#endif #endif
} }
static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq) static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
{ //calibrate hopping frequencies { //calibrate hopping frequencies
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0)
#endif
return; //NRF
#ifdef CC2500_INSTALLED
CC2500_250K_HoppingCalib(num_freq); CC2500_250K_HoppingCalib(num_freq);
#elif defined(NRF24L01_INSTALLED)
(void)num_freq;
#endif #endif
} }
static void __attribute__((unused)) XN297L_Hopping(uint8_t index) static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
{ {
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0)
#endif
{//NRF
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
return;
}
#ifdef CC2500_INSTALLED
CC2500_250K_Hopping(index); CC2500_250K_Hopping(index);
#elif defined(NRF24L01_INSTALLED)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
#endif #endif
} }
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number) static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
{ //change channel { //change channel
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0)
#endif
{//NRF
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
return;
}
#ifdef CC2500_INSTALLED
CC2500_250K_RFChannel(number); CC2500_250K_RFChannel(number);
#elif defined(NRF24L01_INSTALLED)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
#endif #endif
} }
static void __attribute__((unused)) XN297L_SetPower() static void __attribute__((unused)) XN297L_SetPower()
{ {
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0)
#endif
{//NRF
NRF24L01_SetPower();
return;
}
#ifdef CC2500_INSTALLED
CC2500_SetPower(); CC2500_SetPower();
#elif defined(NRF24L01_INSTALLED)
NRF24L01_SetPower();
#endif #endif
} }
static void __attribute__((unused)) XN297L_SetFreqOffset() static void __attribute__((unused)) XN297L_SetFreqOffset()
{ // Frequency offset { // Frequency offset
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0 && prev_option==0) CC2500_SetFreqOffset();
#endif
return; //NRF
#ifdef CC2500_INSTALLED
if (prev_option != option)
{
if(prev_option==0 || option==0)
CHANGE_PROTOCOL_FLAG_on; // switch from NRF <-> CC2500
CC2500_SetFreqOffset();
}
#endif #endif
} }
@ -280,46 +230,31 @@ static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t* addr, uint8_t len
{ {
if (len > 5) len = 5; if (len > 5) len = 5;
if (len < 3) len = 3; if (len < 3) len = 3;
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0) CC2500_250K_NRF_SetTXAddr(addr, len);
#endif #elif defined(NRF24L01_INSTALLED)
{//NRF
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2); NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, len); NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
CC2500_250K_NRF_SetTXAddr(addr, len);
#endif #endif
} }
static void __attribute__((unused)) NRF250K_WritePayload(uint8_t* msg, uint8_t len) static void __attribute__((unused)) NRF250K_WritePayload(uint8_t* msg, uint8_t len)
{ {
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0) CC2500_250K_NRF_WritePayload(msg, len);
#endif #elif defined(NRF24L01_INSTALLED)
{//NRF
NRF24L01_FlushTx(); NRF24L01_FlushTx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT)); NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
NRF24L01_WritePayload(msg, len); NRF24L01_WritePayload(msg, len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
CC2500_250K_NRF_WritePayload(msg, len);
#endif #endif
} }
static boolean __attribute__((unused)) NRF250K_IsPacketSent() static boolean __attribute__((unused)) NRF250K_IsPacketSent()
{ {
#ifdef CC2500_INSTALLED #if defined(CC2500_INSTALLED)
if(option==0) return true; // don't know on the CC2500 how to detect if the packet has been transmitted...
#endif #elif defined(NRF24L01_INSTALLED)
{ //NRF
return NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS); return NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS);
} #endif
return true; // don't know on the CC2500 how to detect if the packet has been transmitted...
} }
#endif
#endif

View File

@ -15,6 +15,10 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(OMP_CC2500_INO) #if defined(OMP_CC2500_INO)
#ifndef NRF24L01_INSTALLED
#undef OMP_HUB_TELEMETRY
#endif
#include "iface_nrf250k.h" #include "iface_nrf250k.h"
//#define FORCE_OMP_ORIGINAL_ID //#define FORCE_OMP_ORIGINAL_ID
@ -29,11 +33,9 @@ Multiprotocol is distributed in the hope that it will be useful,
static void __attribute__((unused)) OMP_send_packet() static void __attribute__((unused)) OMP_send_packet()
{ {
#ifdef OMP_HUB_TELEMETRY #ifdef OMP_HUB_TELEMETRY
if(option==0) rf_switch(SW_CC2500);
prev_option=option=1; // Select the CC2500 by default #endif
PE1_off; PE2_on; // CC2500 antenna RF2
#endif
if(IS_BIND_IN_PROGRESS) if(IS_BIND_IN_PROGRESS)
{ {
@ -109,10 +111,6 @@ static void __attribute__((unused)) OMP_send_packet()
static void __attribute__((unused)) OMP_RF_init() static void __attribute__((unused)) OMP_RF_init()
{ {
//Config CC2500 //Config CC2500
#ifdef OMP_HUB_TELEMETRY
if(option==0)
prev_option=option=1; // Select the CC2500
#endif
XN297L_Init(); XN297L_Init();
XN297L_SetTXAddr((uint8_t*)"FLPBD", 5); XN297L_SetTXAddr((uint8_t*)"FLPBD", 5);
XN297L_HoppingCalib(OMP_RF_NUM_CHANNELS); // Calibrate all channels XN297L_HoppingCalib(OMP_RF_NUM_CHANNELS); // Calibrate all channels
@ -120,8 +118,9 @@ static void __attribute__((unused)) OMP_RF_init()
#ifdef OMP_HUB_TELEMETRY #ifdef OMP_HUB_TELEMETRY
//Config NRF //Config NRF
prev_option=option=0; // Select the NRF rf_switch(SW_NRF);
XN297L_Init(); NRF24L01_Initialize();
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
XN297_Configure(_BV(NRF24L01_00_EN_CRC)); XN297_Configure(_BV(NRF24L01_00_EN_CRC));
XN297_SetRXAddr(rx_tx_addr, 5); // Set the RX address XN297_SetRXAddr(rx_tx_addr, 5); // Set the RX address
NRF24L01_SetTxRxMode(TXRX_OFF); // Turn it off for now NRF24L01_SetTxRxMode(TXRX_OFF); // Turn it off for now
@ -270,7 +269,7 @@ uint16_t OMP_callback()
} }
} }
NRF_CE_on; NRF_CE_on;
PE1_on;PE2_off; // NRF24L01 antenna RF3 rf_switch(SW_NRF);
phase = OMP_DATA; phase = OMP_DATA;
return OMP_PACKET_PERIOD-OMP_WRITE_TIME; return OMP_PACKET_PERIOD-OMP_WRITE_TIME;
#endif #endif

View File

@ -14,7 +14,7 @@ Multiprotocol is distributed in the hope that it will be useful,
*/ */
// Compatible with Q90C quad. // Compatible with Q90C quad.
#if defined(Q90C_NRF24L01_INO) #if defined(Q90C_CCNRF_INO)
#include "iface_nrf250k.h" #include "iface_nrf250k.h"

View File

@ -1,281 +1,281 @@
/* /*
This project is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful, Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
// Last sync with deviation main github branch // Last sync with deviation main github branch
#if defined(SLT_NRF24L01_INO) #if defined(SLT_CCNRF_INO)
#include "iface_nrf250k.h" #include "iface_nrf250k.h"
//#define SLT_Q200_FORCE_ID //#define SLT_Q200_FORCE_ID
// For code readability // For code readability
#define SLT_PAYLOADSIZE_V1 7 #define SLT_PAYLOADSIZE_V1 7
#define SLT_PAYLOADSIZE_V2 11 #define SLT_PAYLOADSIZE_V2 11
#define SLT_NFREQCHANNELS 15 #define SLT_NFREQCHANNELS 15
#define SLT_TXID_SIZE 4 #define SLT_TXID_SIZE 4
#define SLT_BIND_CHANNEL 0x50 #define SLT_BIND_CHANNEL 0x50
enum{ enum{
// flags going to packet[6] (Q200) // flags going to packet[6] (Q200)
FLAG_Q200_FMODE = 0x20, FLAG_Q200_FMODE = 0x20,
FLAG_Q200_VIDON = 0x10, FLAG_Q200_VIDON = 0x10,
FLAG_Q200_FLIP = 0x08, FLAG_Q200_FLIP = 0x08,
FLAG_Q200_VIDOFF= 0x04, FLAG_Q200_VIDOFF= 0x04,
}; };
enum{ enum{
// flags going to packet[6] (MR100 & Q100) // flags going to packet[6] (MR100 & Q100)
FLAG_MR100_FMODE = 0x20, FLAG_MR100_FMODE = 0x20,
FLAG_MR100_FLIP = 0x04, FLAG_MR100_FLIP = 0x04,
FLAG_MR100_VIDEO = 0x02, FLAG_MR100_VIDEO = 0x02,
FLAG_MR100_PICTURE = 0x01, FLAG_MR100_PICTURE = 0x01,
}; };
enum { enum {
SLT_BUILD=0, SLT_BUILD=0,
SLT_DATA1, SLT_DATA1,
SLT_DATA2, SLT_DATA2,
SLT_DATA3, SLT_DATA3,
SLT_BIND1, SLT_BIND1,
SLT_BIND2, SLT_BIND2,
}; };
static void __attribute__((unused)) SLT_RF_init() static void __attribute__((unused)) SLT_RF_init()
{ {
NRF250K_Init(); NRF250K_Init();
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE); NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
} }
static void __attribute__((unused)) SLT_set_freq(void) static void __attribute__((unused)) SLT_set_freq(void)
{ {
// Frequency hopping sequence generation // Frequency hopping sequence generation
for (uint8_t i = 0; i < SLT_TXID_SIZE; ++i) for (uint8_t i = 0; i < SLT_TXID_SIZE; ++i)
{ {
uint8_t next_i = (i+1) % SLT_TXID_SIZE; // is & 3 better than % 4 ? uint8_t next_i = (i+1) % SLT_TXID_SIZE; // is & 3 better than % 4 ?
uint8_t base = i < 2 ? 0x03 : 0x10; uint8_t base = i < 2 ? 0x03 : 0x10;
hopping_frequency[i*4 + 0] = (rx_tx_addr[i] & 0x3f) + base; hopping_frequency[i*4 + 0] = (rx_tx_addr[i] & 0x3f) + base;
hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base; hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base;
hopping_frequency[i*4 + 2] = (rx_tx_addr[i] >> 4) + (rx_tx_addr[next_i] & 0x03)*0x10 + base; hopping_frequency[i*4 + 2] = (rx_tx_addr[i] >> 4) + (rx_tx_addr[next_i] & 0x03)*0x10 + base;
hopping_frequency[i*4 + 3] = (rx_tx_addr[i] >> 6) + (rx_tx_addr[next_i] & 0x0f)*0x04 + base; hopping_frequency[i*4 + 3] = (rx_tx_addr[i] >> 6) + (rx_tx_addr[next_i] & 0x0f)*0x04 + base;
} }
// Unique freq // Unique freq
uint8_t max_freq=0x50; //V1 and V2 uint8_t max_freq=0x50; //V1 and V2
if(sub_protocol==Q200) if(sub_protocol==Q200)
max_freq=45; max_freq=45;
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i) for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
{ {
if(sub_protocol==Q200 && hopping_frequency[i] >= max_freq) if(sub_protocol==Q200 && hopping_frequency[i] >= max_freq)
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03; hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
uint8_t done = 0; uint8_t done = 0;
while (!done) while (!done)
{ {
done = 1; done = 1;
for (uint8_t j = 0; j < i; ++j) for (uint8_t j = 0; j < i; ++j)
if (hopping_frequency[i] == hopping_frequency[j]) if (hopping_frequency[i] == hopping_frequency[j])
{ {
done = 0; done = 0;
hopping_frequency[i] += 7; hopping_frequency[i] += 7;
if (hopping_frequency[i] >= max_freq) if (hopping_frequency[i] >= max_freq)
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03; hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
} }
} }
} }
//Bind channel //Bind channel
hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL; hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL;
//Calib all channels //Calib all channels
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1); NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
} }
static void __attribute__((unused)) SLT_wait_radio() static void __attribute__((unused)) SLT_wait_radio()
{ {
if (packet_sent) if (packet_sent)
while (!NRF250K_IsPacketSent()); while (!NRF250K_IsPacketSent());
packet_sent = 0; packet_sent = 0;
} }
static void __attribute__((unused)) SLT_send_packet(uint8_t len) static void __attribute__((unused)) SLT_send_packet(uint8_t len)
{ {
SLT_wait_radio(); SLT_wait_radio();
NRF250K_WritePayload(packet, len); NRF250K_WritePayload(packet, len);
packet_sent = 1; packet_sent = 1;
} }
static void __attribute__((unused)) SLT_build_packet() static void __attribute__((unused)) SLT_build_packet()
{ {
static uint8_t calib_counter=0; static uint8_t calib_counter=0;
// Set radio channel - once per packet batch // Set radio channel - once per packet batch
NRF250K_SetFreqOffset(); // Set frequency offset NRF250K_SetFreqOffset(); // Set frequency offset
NRF250K_Hopping(hopping_frequency_no); NRF250K_Hopping(hopping_frequency_no);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS) if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0; hopping_frequency_no = 0;
// aileron, elevator, throttle, rudder, gear, pitch // aileron, elevator, throttle, rudder, gear, pitch
uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed
for (uint8_t i = 0; i < 4; ++i) for (uint8_t i = 0; i < 4; ++i)
{ {
uint16_t v = convert_channel_10b(CH_AETR[i], false); uint16_t v = convert_channel_10b(CH_AETR[i], false);
if(sub_protocol>SLT_V2 && (i==CH2 || i==CH3) ) if(sub_protocol>SLT_V2 && (i==CH2 || i==CH3) )
v=1023-v; // reverse throttle and elevator channels for Q100/Q200/MR100 protocols v=1023-v; // reverse throttle and elevator channels for Q100/Q200/MR100 protocols
packet[i] = v; packet[i] = v;
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0); e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
} }
// Extra bits for AETR // Extra bits for AETR
packet[4] = e; packet[4] = e;
// 8-bit channels // 8-bit channels
packet[5] = convert_channel_8b(CH5); packet[5] = convert_channel_8b(CH5);
packet[6] = convert_channel_8b(CH6); packet[6] = convert_channel_8b(CH6);
if(sub_protocol!=SLT_V1) if(sub_protocol!=SLT_V1)
{ {
if(sub_protocol==Q200) if(sub_protocol==Q200)
packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE) packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE)
|GET_FLAG(CH10_SW, FLAG_Q200_FLIP) |GET_FLAG(CH10_SW, FLAG_Q200_FLIP)
|GET_FLAG(CH11_SW, FLAG_Q200_VIDON) |GET_FLAG(CH11_SW, FLAG_Q200_VIDON)
|GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF); |GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF);
else if(sub_protocol==MR100 || sub_protocol==Q100) else if(sub_protocol==MR100 || sub_protocol==Q100)
packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE) packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE)
|GET_FLAG(CH10_SW, FLAG_MR100_FLIP) |GET_FLAG(CH10_SW, FLAG_MR100_FLIP)
|GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but... |GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but...
|GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but... |GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but...
packet[7]=convert_channel_8b(CH7); packet[7]=convert_channel_8b(CH7);
packet[8]=convert_channel_8b(CH8); packet[8]=convert_channel_8b(CH8);
packet[9]=0xAA; //normal mode for Q100/Q200, unknown for V2/MR100 packet[9]=0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
packet[10]=0x00; //normal mode for Q100/Q200, unknown for V2/MR100 packet[10]=0x00; //normal mode for Q100/Q200, unknown for V2/MR100
if((sub_protocol==Q100 || sub_protocol==Q200) && CH13_SW) if((sub_protocol==Q100 || sub_protocol==Q200) && CH13_SW)
{//Calibrate {//Calibrate
packet[9]=0x77; //enter calibration packet[9]=0x77; //enter calibration
if(calib_counter>=20 && calib_counter<=25) // 7 packets for Q100 / 3 packets for Q200 if(calib_counter>=20 && calib_counter<=25) // 7 packets for Q100 / 3 packets for Q200
packet[10]=0x20; //launch calibration packet[10]=0x20; //launch calibration
calib_counter++; calib_counter++;
if(calib_counter>250) calib_counter=250; if(calib_counter>250) calib_counter=250;
} }
else else
calib_counter=0; calib_counter=0;
} }
} }
static void __attribute__((unused)) SLT_send_bind_packet() static void __attribute__((unused)) SLT_send_bind_packet()
{ {
SLT_wait_radio(); SLT_wait_radio();
NRF250K_Hopping(SLT_NFREQCHANNELS); //Bind channel NRF250K_Hopping(SLT_NFREQCHANNELS); //Bind channel
BIND_IN_PROGRESS; //Limit TX power to bind level BIND_IN_PROGRESS; //Limit TX power to bind level
NRF250K_SetPower(); NRF250K_SetPower();
BIND_DONE; BIND_DONE;
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE); NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE); memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE);
if(phase==SLT_BIND2) if(phase==SLT_BIND2)
SLT_send_packet(SLT_TXID_SIZE); SLT_send_packet(SLT_TXID_SIZE);
else // SLT_BIND1 else // SLT_BIND1
SLT_send_packet(SLT_PAYLOADSIZE_V2); SLT_send_packet(SLT_PAYLOADSIZE_V2);
} }
#define SLT_TIMING_BUILD 1000 #define SLT_TIMING_BUILD 1000
#define SLT_V1_TIMING_PACKET 1000 #define SLT_V1_TIMING_PACKET 1000
#define SLT_V2_TIMING_PACKET 2042 #define SLT_V2_TIMING_PACKET 2042
#define SLT_V1_TIMING_BIND2 1000 #define SLT_V1_TIMING_BIND2 1000
#define SLT_V2_TIMING_BIND1 6507 #define SLT_V2_TIMING_BIND1 6507
#define SLT_V2_TIMING_BIND2 2112 #define SLT_V2_TIMING_BIND2 2112
uint16_t SLT_callback() uint16_t SLT_callback()
{ {
switch (phase) switch (phase)
{ {
case SLT_BUILD: case SLT_BUILD:
#ifdef MULTI_SYNC #ifdef MULTI_SYNC
telemetry_set_input_sync(sub_protocol==SLT_V1?20000:13730); telemetry_set_input_sync(sub_protocol==SLT_V1?20000:13730);
#endif #endif
SLT_build_packet(); SLT_build_packet();
NRF250K_SetPower(); //Change power level NRF250K_SetPower(); //Change power level
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE); NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
phase++; phase++;
return SLT_TIMING_BUILD; return SLT_TIMING_BUILD;
case SLT_DATA1: case SLT_DATA1:
case SLT_DATA2: case SLT_DATA2:
phase++; phase++;
if(sub_protocol==SLT_V1) if(sub_protocol==SLT_V1)
{ {
SLT_send_packet(SLT_PAYLOADSIZE_V1); SLT_send_packet(SLT_PAYLOADSIZE_V1);
return SLT_V1_TIMING_PACKET; return SLT_V1_TIMING_PACKET;
} }
else //V2 else //V2
{ {
SLT_send_packet(SLT_PAYLOADSIZE_V2); SLT_send_packet(SLT_PAYLOADSIZE_V2);
return SLT_V2_TIMING_PACKET; return SLT_V2_TIMING_PACKET;
} }
case SLT_DATA3: case SLT_DATA3:
if(sub_protocol==SLT_V1) if(sub_protocol==SLT_V1)
SLT_send_packet(SLT_PAYLOADSIZE_V1); SLT_send_packet(SLT_PAYLOADSIZE_V1);
else //V2 else //V2
SLT_send_packet(SLT_PAYLOADSIZE_V2); SLT_send_packet(SLT_PAYLOADSIZE_V2);
if (++packet_count >= 100) if (++packet_count >= 100)
{// Send bind packet {// Send bind packet
packet_count = 0; packet_count = 0;
if(sub_protocol==SLT_V1) if(sub_protocol==SLT_V1)
{ {
phase=SLT_BIND2; phase=SLT_BIND2;
return SLT_V1_TIMING_BIND2; return SLT_V1_TIMING_BIND2;
} }
else //V2 else //V2
{ {
phase=SLT_BIND1; phase=SLT_BIND1;
return SLT_V2_TIMING_BIND1; return SLT_V2_TIMING_BIND1;
} }
} }
else else
{// Continue to send normal packets {// Continue to send normal packets
phase = SLT_BUILD; phase = SLT_BUILD;
if(sub_protocol==SLT_V1) if(sub_protocol==SLT_V1)
return 20000-SLT_TIMING_BUILD; return 20000-SLT_TIMING_BUILD;
else //V2 else //V2
return 13730-SLT_TIMING_BUILD; return 13730-SLT_TIMING_BUILD;
} }
case SLT_BIND1: case SLT_BIND1:
SLT_send_bind_packet(); SLT_send_bind_packet();
phase++; phase++;
return SLT_V2_TIMING_BIND2; return SLT_V2_TIMING_BIND2;
case SLT_BIND2: case SLT_BIND2:
SLT_send_bind_packet(); SLT_send_bind_packet();
phase = SLT_BUILD; phase = SLT_BUILD;
if(sub_protocol==SLT_V1) if(sub_protocol==SLT_V1)
return 20000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2; return 20000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2;
else //V2 else //V2
return 13730-SLT_TIMING_BUILD-SLT_V2_TIMING_BIND1-SLT_V2_TIMING_BIND2; return 13730-SLT_TIMING_BUILD-SLT_V2_TIMING_BIND1-SLT_V2_TIMING_BIND2;
} }
return 19000; return 19000;
} }
void SLT_init() void SLT_init()
{ {
BIND_DONE; // Not a TX bind protocol BIND_DONE; // Not a TX bind protocol
packet_count = 0; packet_count = 0;
packet_sent = 0; packet_sent = 0;
hopping_frequency_no = 0; hopping_frequency_no = 0;
if(sub_protocol==Q200) if(sub_protocol==Q200)
{ //Q200: Force high part of the ID otherwise it won't bind { //Q200: Force high part of the ID otherwise it won't bind
rx_tx_addr[0]=0x01; rx_tx_addr[0]=0x01;
rx_tx_addr[1]=0x02; rx_tx_addr[1]=0x02;
#ifdef SLT_Q200_FORCE_ID // ID taken from TX dumps #ifdef SLT_Q200_FORCE_ID // ID taken from TX dumps
rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x6A;rx_tx_addr[3]=0x31; rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x6A;rx_tx_addr[3]=0x31;
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/ /* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
#endif #endif
} }
SLT_RF_init(); SLT_RF_init();
SLT_set_freq(); SLT_set_freq();
phase = SLT_BUILD; phase = SLT_BUILD;
} }
#endif #endif

View File

@ -14,7 +14,7 @@
*/ */
// compatible with V911S // compatible with V911S
#if defined(V911S_NRF24L01_INO) #if defined(V911S_CCNRF_INO)
#include "iface_nrf250k.h" #include "iface_nrf250k.h"
@ -144,7 +144,7 @@ uint16_t V911S_callback()
if (bind_counter == 0) if (bind_counter == 0)
{ {
BIND_DONE; BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 5); XN297L_SetTXAddr(rx_tx_addr, 5);
packet_period=V911S_PACKET_PERIOD; packet_period=V911S_PACKET_PERIOD;
} }
else if(bind_counter==100) // same as original TX... else if(bind_counter==100) // same as original TX...
@ -193,7 +193,7 @@ void V911S_init(void)
} }
else else
{ {
XN297_SetTXAddr(rx_tx_addr, 5); XN297L_SetTXAddr(rx_tx_addr, 5);
packet_period= V911S_PACKET_PERIOD; packet_period= V911S_PACKET_PERIOD;
} }
hopping_frequency_no=0; hopping_frequency_no=0;

View File

@ -260,7 +260,7 @@
#undef FRSKY_RX_CC2500_INO #undef FRSKY_RX_CC2500_INO
#undef HITEC_CC2500_INO #undef HITEC_CC2500_INO
#undef HOTT_CC2500_INO #undef HOTT_CC2500_INO
#undef OMP_CC2500_INO // Use both CC2500 and NRF code #undef OMP_CC2500_INO //CC2500 for control and NRF for telemetry
#undef REDPINE_CC2500_INO #undef REDPINE_CC2500_INO
#undef RLINK_CC2500_INO #undef RLINK_CC2500_INO
#undef SCANNER_CC2500_INO #undef SCANNER_CC2500_INO
@ -283,35 +283,36 @@
#undef FQ777_NRF24L01_INO #undef FQ777_NRF24L01_INO
#undef FX816_NRF24L01_INO #undef FX816_NRF24L01_INO
#undef FY326_NRF24L01_INO #undef FY326_NRF24L01_INO
#undef GD00X_NRF24L01_INO
#undef GW008_NRF24L01_INO #undef GW008_NRF24L01_INO
#undef H8_3D_NRF24L01_INO #undef H8_3D_NRF24L01_INO
#undef HISKY_NRF24L01_INO #undef HISKY_NRF24L01_INO
#undef HONTAI_NRF24L01_INO #undef HONTAI_NRF24L01_INO
#undef JJRC345_NRF24L01_INO #undef JJRC345_NRF24L01_INO
#undef KF606_NRF24L01_INO
#undef KN_NRF24L01_INO #undef KN_NRF24L01_INO
#undef LOLI_NRF24L01_INO #undef LOLI_NRF24L01_INO
#undef MJXQ_NRF24L01_INO #undef MJXQ_NRF24L01_INO
#undef MT99XX_NRF24L01_INO #undef MT99XX_NRF24L01_INO
#undef NCC1701_NRF24L01_INO #undef NCC1701_NRF24L01_INO
#undef OMP_CC2500_INO // Use both CC2500 and NRF code
#undef POTENSIC_NRF24L01_INO #undef POTENSIC_NRF24L01_INO
#undef PROPEL_NRF24L01_INO #undef PROPEL_NRF24L01_INO
#undef Q303_NRF24L01_INO #undef Q303_NRF24L01_INO
#undef Q90C_NRF24L01_INO
#undef REALACC_NRF24L01_INO #undef REALACC_NRF24L01_INO
#undef SHENQI_NRF24L01_INO #undef SHENQI_NRF24L01_INO
#undef SLT_NRF24L01_INO
#undef SYMAX_NRF24L01_INO #undef SYMAX_NRF24L01_INO
#undef TIGER_NRF24L01_INO #undef TIGER_NRF24L01_INO
#undef V2X2_NRF24L01_INO #undef V2X2_NRF24L01_INO
#undef V761_NRF24L01_INO #undef V761_NRF24L01_INO
#undef V911S_NRF24L01_INO
#undef XK_NRF24L01_INO #undef XK_NRF24L01_INO
#undef YD717_NRF24L01_INO #undef YD717_NRF24L01_INO
#undef ZSX_NRF24L01_INO #undef ZSX_NRF24L01_INO
#endif #endif
#if not defined(CC2500_INSTALLED) && not defined(NRF24L01_INSTALLED)
#undef GD00X_CCNRF_INO
#undef KF606_CCNRF_INO
#undef Q90C_CCNRF_INO
#undef SLT_CCNRF_INO
#undef V911S_CCNRF_INO
#endif
#if not defined(STM32_BOARD) #if not defined(STM32_BOARD)
#undef SX1276_INSTALLED #undef SX1276_INSTALLED
#endif #endif

View File

@ -212,8 +212,6 @@ uint16_t XK_callback()
void XK_init() void XK_init()
{ {
if(sub_protocol==X420)
option=prev_option=0; // Forcing the use of NRF24L01@1Mbps
BIND_IN_PROGRESS; // Autobind protocol BIND_IN_PROGRESS; // Autobind protocol
XK_initialize_txid(); XK_initialize_txid();
XK_RF_init(); XK_RF_init();

265
Multiprotocol/XN297_EMU.ino Normal file
View File

@ -0,0 +1,265 @@
#if defined(CC2500_INSTALLED) || defined(NRF24L01_INSTALLED)
#include "iface_xn297.h"
#endif
#ifdef NRF24L01_INSTALLED
void XN297_SetTXAddr(const uint8_t* addr, uint8_t len)
{
if (len > 5) len = 5;
if (len < 3) len = 3;
uint8_t buf[] = { 0x55, 0x0F, 0x71, 0x0C, 0x00 }; // bytes for XN297 preamble 0xC710F55 (28 bit)
xn297_addr_len = len;
if (xn297_addr_len < 4)
for (uint8_t i = 0; i < 4; ++i)
buf[i] = buf[i+1];
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, buf, 5);
// Receive address is complicated. We need to use scrambled actual address as a receive address
// but the TX code now assumes fixed 4-byte transmit address for preamble. We need to adjust it
// first. Also, if the scrambled address begins with 1 nRF24 will look for preamble byte 0xAA
// instead of 0x55 to ensure enough 0-1 transitions to tune the receiver. Still need to experiment
// with receiving signals.
memcpy(xn297_tx_addr, addr, len);
}
void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
{
if (len > 5) len = 5;
if (len < 3) len = 3;
uint8_t buf[] = { 0, 0, 0, 0, 0 };
memcpy(buf, addr, len);
memcpy(xn297_rx_addr, addr, len);
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
buf[i] = xn297_rx_addr[i];
if(xn297_scramble_enabled)
buf[i] ^= xn297_scramble[xn297_addr_len-i-1];
}
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
}
void XN297_Configure(uint8_t flags)
{
xn297_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
}
void XN297_SetScrambledMode(const uint8_t mode)
{
xn297_scramble_enabled = mode;
}
void XN297_WritePayload(uint8_t* msg, uint8_t len)
{
uint8_t buf[32];
uint8_t last = 0;
if (xn297_addr_len < 4)
{
// If address length (which is defined by receive address length)
// is less than 4 the TX address can't fit the preamble, so the last
// byte goes here
buf[last++] = 0x55;
}
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[i];
last++;
}
for (uint8_t i = 0; i < len; ++i)
{
// bit-reverse bytes in packet
buf[last] = bit_reverse(msg[i]);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[xn297_addr_len+i];
last++;
}
if (xn297_crc)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc16_update( buf[i], 8);
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
}
NRF24L01_WritePayload(buf, last);
}
void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{
uint8_t packet[32];
uint8_t scramble_index=0;
uint8_t last = 0;
static uint8_t pid=0;
// address
if (xn297_addr_len < 4)
{
// If address length (which is defined by receive address length)
// is less than 4 the TX address can't fit the preamble, so the last
// byte goes here
packet[last++] = 0x55;
}
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
packet[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
last++;
}
// pcf
packet[last] = (len << 1) | (pid>>1);
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
last++;
packet[last] = (pid << 7) | (noack << 6);
// payload
packet[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
for (uint8_t i = 0; i < len-1; ++i)
{
last++;
packet[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
}
last++;
packet[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++] & 0xc0;
// crc
if (xn297_crc)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc16_update( packet[i], 8);
crc16_update( packet[last] & 0xc0, 2);
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
//else
// crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
packet[last++] |= (crc >> 8) >> 2;
packet[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
packet[last++] = (crc & 0xff) << 6;
}
NRF24L01_WritePayload(packet, last);
pid++;
if(pid>3)
pid=0;
}
boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget if using CRC to do a +2 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buf[32];
if (xn297_crc)
NRF24L01_ReadPayload(buf, len+2); // Read payload + CRC
else
NRF24L01_ReadPayload(buf, len);
// Decode payload
for(uint8_t i=0; i<len; i++)
{
uint8_t b_in=buf[i];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i+xn297_addr_len];
msg[i] = bit_reverse(b_in);
}
if (!xn297_crc)
return true; // No CRC so OK by default...
// Calculate CRC
crc = 0xb5d2;
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc16_update( b_in, 8);
}
//process payload
for (uint8_t i = 0; i < len; ++i)
crc16_update( buf[i], 8);
//xorout
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
//test
if( (crc >> 8) == buf[len] && (crc & 0xff) == buf[len+1])
return true; // CRC OK
return false; // CRC NOK
}
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget do a +2 and if using CRC add +4 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buffer[32];
uint8_t pcf_size; // pcf payload size
if (xn297_crc)
NRF24L01_ReadPayload(buffer, len+4); // Read pcf + payload + CRC
else
NRF24L01_ReadPayload(buffer, len+2); // Read pcf + payload
pcf_size = buffer[0];
if(xn297_scramble_enabled)
pcf_size ^= xn297_scramble[xn297_addr_len];
pcf_size = pcf_size >> 1;
for(int i=0; i<len; i++)
{
msg[i] = bit_reverse((buffer[i+1] << 2) | (buffer[i+2] >> 6));
if(xn297_scramble_enabled)
msg[i] ^= bit_reverse((xn297_scramble[xn297_addr_len+i+1] << 2) |
(xn297_scramble[xn297_addr_len+i+2] >> 6));
}
if (!xn297_crc)
return pcf_size; // No CRC so OK by default...
// Calculate CRC
crc = 0xb5d2;
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc16_update( b_in, 8);
}
//process payload
for (uint8_t i = 0; i < len+1; ++i)
crc16_update( buffer[i], 8);
crc16_update( buffer[len+1] & 0xc0, 2);
//xorout
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
#ifdef XN297DUMP_NRF24L01_INO
else
crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
#endif
uint16_t crcxored=(buffer[len+1]<<10)|(buffer[len+2]<<2)|(buffer[len+3]>>6) ;
if( crc == crcxored)
return pcf_size; // CRC OK
return 0; // CRC NOK
}
// End of XN297 emulation
#endif

View File

@ -200,6 +200,7 @@
#define FRSKY_RX_CC2500_INO #define FRSKY_RX_CC2500_INO
#define HITEC_CC2500_INO #define HITEC_CC2500_INO
#define HOTT_CC2500_INO #define HOTT_CC2500_INO
#define OMP_CC2500_INO //CC2500 for control and NRF for telemetry
#define SCANNER_CC2500_INO #define SCANNER_CC2500_INO
#define FUTABA_CC2500_INO #define FUTABA_CC2500_INO
#define SKYARTEC_CC2500_INO #define SKYARTEC_CC2500_INO
@ -222,35 +223,36 @@
#define FQ777_NRF24L01_INO #define FQ777_NRF24L01_INO
#define FX816_NRF24L01_INO #define FX816_NRF24L01_INO
#define FY326_NRF24L01_INO #define FY326_NRF24L01_INO
#define GD00X_NRF24L01_INO
#define GW008_NRF24L01_INO #define GW008_NRF24L01_INO
#define HISKY_NRF24L01_INO #define HISKY_NRF24L01_INO
#define HONTAI_NRF24L01_INO #define HONTAI_NRF24L01_INO
#define H8_3D_NRF24L01_INO #define H8_3D_NRF24L01_INO
#define JJRC345_NRF24L01_INO #define JJRC345_NRF24L01_INO
#define KF606_NRF24L01_INO
#define KN_NRF24L01_INO #define KN_NRF24L01_INO
#define LOLI_NRF24L01_INO #define LOLI_NRF24L01_INO
#define MJXQ_NRF24L01_INO #define MJXQ_NRF24L01_INO
#define MT99XX_NRF24L01_INO #define MT99XX_NRF24L01_INO
#define NCC1701_NRF24L01_INO #define NCC1701_NRF24L01_INO
#define OMP_CC2500_INO //Need both CC2500 and NRF
#define POTENSIC_NRF24L01_INO #define POTENSIC_NRF24L01_INO
#define PROPEL_NRF24L01_INO #define PROPEL_NRF24L01_INO
#define Q303_NRF24L01_INO #define Q303_NRF24L01_INO
#define Q90C_NRF24L01_INO
#define REALACC_NRF24L01_INO #define REALACC_NRF24L01_INO
#define SHENQI_NRF24L01_INO #define SHENQI_NRF24L01_INO
#define SLT_NRF24L01_INO
#define SYMAX_NRF24L01_INO #define SYMAX_NRF24L01_INO
#define TIGER_NRF24L01_INO #define TIGER_NRF24L01_INO
#define V2X2_NRF24L01_INO #define V2X2_NRF24L01_INO
#define V761_NRF24L01_INO #define V761_NRF24L01_INO
#define V911S_NRF24L01_INO
#define XK_NRF24L01_INO #define XK_NRF24L01_INO
#define YD717_NRF24L01_INO #define YD717_NRF24L01_INO
#define ZSX_NRF24L01_INO #define ZSX_NRF24L01_INO
//The protocols below need either a CC2500 or NRF24L01 to be installed
#define GD00X_CCNRF_INO
#define KF606_CCNRF_INO
#define Q90C_CCNRF_INO
#define SLT_CCNRF_INO
#define V911S_CCNRF_INO
//The protocols below need a SX1276 to be installed //The protocols below need a SX1276 to be installed
#define FRSKYR9_SX1276_INO #define FRSKYR9_SX1276_INO

View File

@ -29,7 +29,7 @@
#undef FRSKYX_CC2500_INO #undef FRSKYX_CC2500_INO
#undef KN_NRF24L01_INO #undef KN_NRF24L01_INO
#undef SLT_NRF24L01_INO #undef SLT_CCNRF_INO
#undef FY326_NRF24L01_INO #undef FY326_NRF24L01_INO
#undef FQ777_NRF24L01_INO #undef FQ777_NRF24L01_INO

View File

@ -102,9 +102,4 @@ enum {
#define REUSE_TX_PL 0xE3 #define REUSE_TX_PL 0xE3
//#define NOP 0xFF //#define NOP 0xFF
// XN297 emulation layer
enum {
XN297_UNSCRAMBLED = 0,
XN297_SCRAMBLED
};
#endif #endif

View File

@ -4,10 +4,10 @@
#if defined (CC2500_INSTALLED) #if defined (CC2500_INSTALLED)
#include "iface_cc2500.h" #include "iface_cc2500.h"
#endif #elif defined (NRF24L01_INSTALLED)
#if defined (NRF24L01_INSTALLED)
#include "iface_nrf24l01.h" #include "iface_nrf24l01.h"
#endif #endif
#include "iface_xn297.h"
//XN297L //XN297L
static void __attribute__((unused)) XN297L_Init(); static void __attribute__((unused)) XN297L_Init();

View File

@ -0,0 +1,83 @@
#ifndef _IFACE_XN297_H_
#define _IFACE_XN297_H_
#if defined (CC2500_INSTALLED)
#include "iface_cc2500.h"
#endif
#if defined (NRF24L01_INSTALLED)
#include "iface_nrf24l01.h"
#endif
///////////////
// XN297 emulation layer
// XN297 emulation layer
enum {
XN297_UNSCRAMBLED = 0,
XN297_SCRAMBLED
};
uint8_t xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
uint8_t xn297_addr_len;
uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5];
uint8_t xn297_crc = 0;
// xn297 address / pcf / payload scramble table
const uint8_t xn297_scramble[] = {
0xE3, 0xB1, 0x4B, 0xEA, 0x85, 0xBC, 0xE5, 0x66,
0x0D, 0xAE, 0x8C, 0x88, 0x12, 0x69, 0xEE, 0x1F,
0xC7, 0x62, 0x97, 0xD5, 0x0B, 0x79, 0xCA, 0xCC,
0x1B, 0x5D, 0x19, 0x10, 0x24, 0xD3, 0xDC, 0x3F,
0x8E, 0xC5, 0x2F, 0xAA, 0x16, 0xF3, 0x95 };
// scrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
0x2138, 0x129F, 0xB3A0, 0x2988, 0x23CA, 0xC0CB,
0x0C6C, 0xB329, 0xA0A1, 0x0A16, 0xA9D0 };
// unscrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3D5F, 0xA6F1, 0x3A23, 0xAA16, 0x1CAF,
0x62B2, 0xE0EB, 0x0821, 0xBE07, 0x5F1A, 0xAF15,
0x4F0A, 0xAD24, 0x5E48, 0xED34, 0x068C, 0xF2C9,
0x1852, 0xDF36, 0x129D, 0xB17C, 0xD5F5, 0x70D7,
0xB798, 0x5133, 0x67DB, 0xD94E, 0x0A5B, 0xE445,
0xE6A5, 0x26E7, 0xBDAB, 0xC379, 0x8E20 };
// scrambled enhanced mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled_enhanced[] = {
0x0000, 0x7EBF, 0x3ECE, 0x07A4, 0xCA52, 0x343B,
0x53F8, 0x8CD0, 0x9EAC, 0xD0C0, 0x150D, 0x5186,
0xD251, 0xA46F, 0x8435, 0xFA2E, 0x7EBD, 0x3C7D,
0x94E0, 0x3D5F, 0xA685, 0x4E47, 0xF045, 0xB483,
0x7A1F, 0xDEA2, 0x9642, 0xBF4B, 0x032F, 0x01D2,
0xDC86, 0x92A5, 0x183A, 0xB760, 0xA953 };
// unscrambled enhanced mode crc xorout table
// unused so far
#ifdef XN297DUMP_NRF24L01_INO
const uint16_t xn297_crc_xorout_enhanced[] = {
0x0000, 0x8BE6, 0xD8EC, 0xB87A, 0x42DC, 0xAA89,
0x83AF, 0x10E4, 0xE83E, 0x5C29, 0xAC76, 0x1C69,
0xA4B2, 0x5961, 0xB4D3, 0x2A50, 0xCB27, 0x5128,
0x7CDB, 0x7A14, 0xD5D2, 0x57D7, 0xE31D, 0xCE42,
0x648D, 0xBF2D, 0x653B, 0x190C, 0x9117, 0x9A97,
0xABFC, 0xE68E, 0x0DE7, 0x28A2, 0x1965 };
#endif
#ifdef NRF24L01_INSTALLED
void XN297_SetTXAddr(const uint8_t*, uint8_t);
void XN297_SetRXAddr(const uint8_t*, uint8_t);
void XN297_Configure(uint8_t);
void XN297_SetScrambledMode(const uint8_t);
void XN297_WritePayload(uint8_t*, uint8_t);
void XN297_WriteEnhancedPayload(uint8_t*, uint8_t, uint8_t);
boolean XN297_ReadPayload(uint8_t*, uint8_t);
uint8_t XN297_ReadEnhancedPayload(uint8_t*, uint8_t);
#endif
#endif

View File

@ -352,6 +352,225 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
Option is used to select between WBUS=0 and PPM=1 Option is used to select between WBUS=0 and PPM=1
***
# CYRF6936 RF Module
If USE_CYRF6936_CH15_TUNING is enabled, the value of channel 15 is used by all CYRF6936 protocols for tuning the frequency. This is required in rare cases where some CYRF6936 modules and/or RXs have an inaccurate crystal oscillator.
## DEVO - *7*
Extended limits and failsafe supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
RX output will match the Devo standard EATR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
Basic telemetry is available if RX supports it: TX_RSSI, A1 (set the ratio to 12.7) and A2 (set the ratio to 12.7)
Bind procedure using serial:
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode.
- Turn on the TX, set protocol = Devo with option=0, turn off the TX (TX is now in autobind mode).
- Turn on RX (RX LED fast blink).
- Turn on TX (RX LED solid, TX LED fast blink).
- Wait for bind on the TX to complete (TX LED solid).
- Make sure to set a uniq RX_Num value for model match.
- Change option to 1 to use the global ID.
- Do not touch option/RX_Num anymore.
Bind procedure using PPM:
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode.
- Turn on RX (RX LED fast blink).
- Turn the dial to the model number running protocol DEVO on the module.
- Press the bind button and turn on the TX. TX is now in autobind mode.
- Release bind button after 1 second: RX LED solid, TX LED fast blink.
- Wait for bind on the TX to complete (TX LED solid).
- Press the bind button for 1 second. TX/RX is now in fixed ID mode.
- To verify that the TX is in fixed mode: power cycle the TX, the module LED should be solid ON (no blink).
- Note: Autobind/fixed ID mode is linked to the RX_Num number. Which means that you can have multiple dial numbers set to the same protocol DEVO with different RX_Num and have different bind modes at the same time. It enables PPM users to get model match under DEVO.
### Sub_protocol 8CH - *0*
### Sub_protocol 10CH - *1*
### Sub_protocol 12CH - *2*
### Sub_protocol 6CH - *3*
### Sub_protocol 7CH - *4*
## WK2X01 - *30*
Extended limits supported
Autobind protocol
Note: RX ouput will always be AETR independently of the input AETR, RETA...
### Sub_protocol WK2801 - *0*
Failsafe supported.
This roughly corresponds to the number of channels supported, but many of the newer 6-channel receivers actually support the WK2801 protocol. It is recommended to try the WK2801 protocol 1st when working with older Walkera models before attempting the WK2601 or WK2401 mode, as the WK2801 is a superior protocol. The WK2801 protocol supports up to 8 channels.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
Bind procedure using serial:
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode.
- Turn on the TX, set protocol = WK2X01, sub_protocol = WK2801 with option=0, turn off the TX (TX is now in autobind mode).
- Turn on RX (RX LED fast blink).
- Turn on TX (RX LED solid, TX LED fast blink).
- Wait for bind on the TX to complete (TX LED solid).
- Make sure to set a uniq RX_Num value for model match.
- Change option to 1 to use the global ID.
- Do not touch option/RX_Num anymore.
Bind procedure using PPM:
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode.
- Turn on RX (RX LED fast blink).
- Turn the dial to the model number running protocol protocol WK2X01 and sub_protocol WK2801 on the module.
- Press the bind button and turn on the TX. TX is now in autobind mode.
- Release bind button after 1 second: RX LED solid, TX LED fast blink.
- Wait for bind on the TX to complete (TX LED solid).
- Press the bind button for 1 second. TX/RX is now in fixed ID mode.
- To verify that the TX is in fixed mode: power cycle the TX, the module LED should be solid ON (no blink).
- Note: Autobind/fixed ID mode is linked to the RX_Num number. Which means that you can have multiple dial numbers set to the same protocol DEVO with different RX_Num and have different bind modes at the same time. It enables PPM users to get model match under DEVO.
### Sub_protocol WK2401 - *1*
The WK2401 protocol is used to control older Walkera models.
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
### Sub_protocol W6_5_1 - *2*
WK2601 5+1: AIL, ELE, THR, RUD, GYRO (ch 7) are proportional. Gear (ch 5) is binary. Ch 6 is disabled
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|GEAR|DIS|GYRO
### Sub_protocol W6_6_1 - *3*
WK2601 6+1: AIL, ELE, THR, RUD, COL (ch 6), GYRO (ch 7) are proportional. Gear (ch 5) is binary. **This mode is highly experimental.**
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|GEAR|COL|GYRO
### Sub_protocol W6_HEL - *4* and W6HEL_I - *5*
WK2601 Heli: AIL, ELE, THR, RUD, GYRO are proportional. Gear (ch 5) is binary. COL (ch 6) is linked to Thr. If Ch6 >= 0, the receiver will apply a 3D curve to the Thr. If Ch6 < 0, the receiver will apply normal curves to the Thr. The value of Ch6 defines the ratio of COL to THR.
W6HEL_I: Invert COL servo
option= maximum range of COL servo
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|GEAR|COL|GYRO
## DSM - *6*
Extended limits supported
Telemetry enabled for TSSI and plugins
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|CH14
---|---|---|---|---|---|---|---|---|----|----|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|TH_KILL
Notes:
- The "AUTO" sub protocol is recommended to automatically select the best settings for your DSM RX. If the RX doesn't bind or work properly after bind, don't hesitate to test different combinations of sub protocol and number of channels until you have something working.
- Servo refresh rate is 22ms unless you select 11ms available in OpenTX 2.3.10+
- RX output will match the Spektrum standard TAER independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- RX output will match the Spektrum standard throw (1500µs +/- 400µs -> 1100..1900µs) for a 100% input. This is true for both Serial and PPM input. For PPM, make sure the end points PPM_MIN_100 and PPM_MAX_100 in _config.h are matching your TX ouput. The maximum ouput is 1000..2000µs based on an input of 125%.
- If you want to override the above and get maximum throw either uncomment in _config.h the line #define DSM_MAX_THROW or on OpenTX 2.3.3+ use the "Enable max throw" feature on the GUI (0=No,1=Yes). In this mode to achieve standard throw use a channel weight of 84%.
- TH_KILL is a feature which is enabled on channel 14 by default (can be disabled/changed) in the _config.h file. Some models (X-Vert, Blade 230S...) require a special position to instant stop the motor(s). If the channel 14 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%. For example, a value of -80% applied on channel 14 will instantly kill the motors on the X-Vert.
- To allow SAFE to be ON with a switch assignment you must remove the bind plug after powering up the RX but before turning on the TX to bind. If you select Autodetect to bind, The MPM will choose DSMX 11ms and Channels 1-7 ( Change to 1-9 if you wish to assign switch above channel 7 ). Then in order to use the manuals diagram of both sticks "Down-Inside" to set a SAFE Select Switch Designation, you must have Throttle and Elevator channels set to Normal direction but the Aileron and Rudder set to Reverse direction. If setting up a new model with all channels set to Normal you can hold both sticks "Down- OUTSIDE" to assign the switch with 5x flips. Tested on a Mode2 radio.
Option=number of channels from 3 to 12. Option|0x80 enables Max Throw. Option|0x40 enables a servo refresh rate of 11ms.
### Sub_protocol DSM2_1F - *0*
DSM2, Resolution 1024, servo refresh rate can only be 22ms
### Sub_protocol DSM2_2F - *1*
DSM2, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
### Sub_protocol DSMX_1F - *2*
DSMX, Resolution 2048, servo refresh rate can only be 22ms
### Sub_protocol DSMX_2F - *3*
DSMX, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
### Sub_protocol AUTO - *4*
"AUTO" is recommended to automatically select the best settings for your DSM RX.
## DSM_RX - *70*
The DSM receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
Notes:
- Automatically detect DSM 2/X 11/22ms 1024/2048res
- Bind should be done with all other modules off in the radio
- Available in OpenTX 2.3.3+, Trainer Mode Master/Multi
- Channels 1..4 are remapped to the module default channel order unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- Extended limits supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
## E010R5 - *81*
Models: E010 R5 red boards, JJRC H36, H36F and H36S
**Only 4 IDs are available**. More IDs can be added if you send me your "unused" original TX.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|CALIB|HEADLESS|RTH|GLIDE
## E129 - *83*
Models: Eachine E129/E130 and Twister Ninja 250
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|Take off/Land|Emergency|Trim A|Trim E|Trim R
Trims can be done to some extent on the AETR channels directly but if you push them too far you won't be able to arm like explained below. In this case use the associated trim TrimA/E/R instead.
Take off with a none spring throttle is easier by putting both sticks down outwards (like on the original radio) in Mode 1/2, not sure about other modes.
Calib is the same as the original radio with both sticks down and to the left in Mode 1/2, not sure about other modes.
## J6Pro - *22*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
## MLINK - *78*
Extended limits supported
Bind: the RX must be really close to the TX
**Failsafe MUST be configured once with the desired channel values (hold or no pulses are not supported) while the RX is up (wait 10+sec for the RX to learn the config) and then failsafe MUST be set to RX/Receiver otherwise the servos will jitter!!!**
Telemetry: the 2 RXs I have are sending different information in different format
- RX-5: RX_RSSI=RSSI=sort of RSSI or link quality, RX_LQI=number of connection lost, TX_RSSI=RSSI from the TX perspective, TX_LQI=percentage of received telemetry packets
- RX-9-DR: A1=RX Batt (Ratio=12.7), **RX_RSSI=TX_LQI**=percentage of received telemetry packets **from the TX** perspective **not RX**, TX_RSSI=RSSI from the TX perspective, TX_LQI=percentage of received telemetry packets
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
## Traxxas - *43*
Receiver 6519
Extended limits supported
CH1|CH2|CH3|CH4
---|---|---|---
AUX3|AUX4|THROTTLE|STEERING
## WFLY - *40*
Receivers: WFR04S, WFR07S, WFR09S
Extended limits supported
option=number of channels from 4 to 9. An invalid option value will end up sending 9 channels.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
*** ***
# CC2500 RF Module # CC2500 RF Module
@ -622,6 +841,28 @@ Recommended for best telemetry performance.
Telemetry compatibility mode when Sync does not work due to an old firmware on the RX. Telemetry compatibility mode when Sync does not work due to an old firmware on the RX.
You should definitively upgrade your receivers/sensors to the latest firmware versions: https://www.rcgroups.com/forums/showpost.php?p=44668015&postcount=18022 You should definitively upgrade your receivers/sensors to the latest firmware versions: https://www.rcgroups.com/forums/showpost.php?p=44668015&postcount=18022
## OMP - *77*
Model: OMPHOBBY M1 & M2 Helis, T720 RC Glider
Telemetry is supported only if a NRF24L01 RF component is installed:
- A1 = battery voltage including "recovered" battery voltage from corrupted telemetry packets
- A2 = battery voltage from only good telemetry packets
- How to calculate accurately the OpenTX Ratio and Offset:
Set the Ratio to 12.7 and Offset to 0, plug 2 batteries with extreme voltage values, write down the values Batt1=12.5V & Telem1=12.2V, Batt2=7V & Telem2=6.6V then calculate/set Ratio=12.7*[(12.5-7)/(12.2-6.6)]=12.47 => 12.5 and Offset=12.5-12.2*[(12.5-7)/(12.2-6.6)]=0.517 => 0.5
- RX_RSSI = TQly = percentage of received telemetry packets (good and corrupted) from the model which has nothing to do with how well the RX is receiving the TX
Option for this protocol corresponds to the CC2500 fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T_PITCH|R|T_HOLD|IDLE|MODE
IDLE= 3 pos switch: -100% Normal, 0% Idle1, +100% Idle2
From the TX manual: MODE= 3 pos switch -100% Attitude, 0% Attitude(?), +100% 3D
For M2: MODE= 3 pos switch -100% 6G, 0% 3D, +100% 3D
## Scanner - *54* ## Scanner - *54*
2.4GHz scanner accessible using the OpenTX 2.3 Spectrum Analyser tool. 2.4GHz scanner accessible using the OpenTX 2.3 Spectrum Analyser tool.
@ -680,223 +921,128 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7
A|E|T|R|CH5|CH6|CH7 A|E|T|R|CH5|CH6|CH7
*** ***
# CYRF6936 RF Module # CC2500 and/or NRF24L01 RF Module(s)
If USE_CYRF6936_CH15_TUNING is enabled, the value of channel 15 is used by all CYRF6936 protocols for tuning the frequency. This is required in rare cases where some CYRF6936 modules and/or RXs have an inaccurate crystal oscillator. If a CC2500 is installed it will be used for all the below protocols. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
## DEVO - *7* If only a NRF24L01 is installed then these protocols might be problematic because they are using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
Extended limits and failsafe supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12 ## GD00X - *47*
---|---|---|---|---|---|---|---|---|---|---|--- Model: GD005 C-17 Transport, GD006 DA62 and ZC-Z50
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
RX output will match the Devo standard EATR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI. CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A||T||TRIM|LED|RATE
Basic telemetry is available if RX supports it: TX_RSSI, A1 (set the ratio to 12.7) and A2 (set the ratio to 12.7) TRIM: either use this channel for trim only or add a mixer with aileron to increase the roll rate.
Bind procedure using serial: RATE: -100% high rate, +100% low rate
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode.
- Turn on the TX, set protocol = Devo with option=0, turn off the TX (TX is now in autobind mode).
- Turn on RX (RX LED fast blink).
- Turn on TX (RX LED solid, TX LED fast blink).
- Wait for bind on the TX to complete (TX LED solid).
- Make sure to set a uniq RX_Num value for model match.
- Change option to 1 to use the global ID.
- Do not touch option/RX_Num anymore.
Bind procedure using PPM: ### Sub_protocol GD_V1 - *0*
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode. First generation of GD models, ZC-Z50
- Turn on RX (RX LED fast blink).
- Turn the dial to the model number running protocol DEVO on the module.
- Press the bind button and turn on the TX. TX is now in autobind mode.
- Release bind button after 1 second: RX LED solid, TX LED fast blink.
- Wait for bind on the TX to complete (TX LED solid).
- Press the bind button for 1 second. TX/RX is now in fixed ID mode.
- To verify that the TX is in fixed mode: power cycle the TX, the module LED should be solid ON (no blink).
- Note: Autobind/fixed ID mode is linked to the RX_Num number. Which means that you can have multiple dial numbers set to the same protocol DEVO with different RX_Num and have different bind modes at the same time. It enables PPM users to get model match under DEVO.
### Sub_protocol 8CH - *0* ### Sub_protocol GD_V2 - *1*
### Sub_protocol 10CH - *1* New generation of GD models
### Sub_protocol 12CH - *2*
### Sub_protocol 6CH - *3*
### Sub_protocol 7CH - *4*
## WK2X01 - *30* ## KF606 - *49*
Extended limits supported Model: KF606
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A||T||TRIM
## Q90C - *72*
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|FMODE|VTX+
FMODE: -100% angle, 0% horizon, +100% acro
VTX+: -100%->+100% channel+
## SLT - *11*
Autobind protocol Autobind protocol
Note: RX ouput will always be AETR independently of the input AETR, RETA... ### Sub_protocol V1 - *0*
### Sub_protocol WK2801 - *0* CH1|CH2|CH3|CH4|CH5|CH6
Failsafe supported. ---|---|---|---|---|---
A|E|T|R|GEAR|PITCH
This roughly corresponds to the number of channels supported, but many of the newer 6-channel receivers actually support the WK2801 protocol. It is recommended to try the WK2801 protocol 1st when working with older Walkera models before attempting the WK2601 or WK2401 mode, as the WK2801 is a superior protocol. The WK2801 protocol supports up to 8 channels. ### Sub_protocol V2 - *1*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|--- ---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8 A|E|T|R|CH5|CH6|CH7|CH8
Bind procedure using serial: ### Sub_protocol Q100 - *2*
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode. Models: Dromida Ominus UAV
- Turn on the TX, set protocol = WK2X01, sub_protocol = WK2801 with option=0, turn off the TX (TX is now in autobind mode).
- Turn on RX (RX LED fast blink).
- Turn on TX (RX LED solid, TX LED fast blink).
- Wait for bind on the TX to complete (TX LED solid).
- Make sure to set a uniq RX_Num value for model match.
- Change option to 1 to use the global ID.
- Do not touch option/RX_Num anymore.
Bind procedure using PPM: CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode. ---|---|---|---|---|---|---|---|---|---|---|---|---
- Turn on RX (RX LED fast blink). A|E|T|R|RATES|-|CH7|CH8|MODE|FLIP|-|-|CALIB
- Turn the dial to the model number running protocol protocol WK2X01 and sub_protocol WK2801 on the module.
- Press the bind button and turn on the TX. TX is now in autobind mode.
- Release bind button after 1 second: RX LED solid, TX LED fast blink.
- Wait for bind on the TX to complete (TX LED solid).
- Press the bind button for 1 second. TX/RX is now in fixed ID mode.
- To verify that the TX is in fixed mode: power cycle the TX, the module LED should be solid ON (no blink).
- Note: Autobind/fixed ID mode is linked to the RX_Num number. Which means that you can have multiple dial numbers set to the same protocol DEVO with different RX_Num and have different bind modes at the same time. It enables PPM users to get model match under DEVO.
### Sub_protocol WK2401 - *1* RATES takes any value between -50..+50%: -50%=min rates, 0%=mid rates (stock setting), +50%=max rates
The WK2401 protocol is used to control older Walkera models.
CH1|CH2|CH3|CH4 CH7 and CH8 have no visible effect
---|---|---|---
A|E|T|R
### Sub_protocol W6_5_1 - *2* MODE: -100% level, +100% acro
WK2601 5+1: AIL, ELE, THR, RUD, GYRO (ch 7) are proportional. Gear (ch 5) is binary. Ch 6 is disabled
CH1|CH2|CH3|CH4|CH5|CH6|CH7 FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (rear red LED goes out while active) -100%..+100% or +100%..-100%
---|---|---|---|---|---|---
A|E|T|R|GEAR|DIS|GYRO
### Sub_protocol W6_6_1 - *3* CALIB: -100% normal mode, +100% gyro calibration
WK2601 6+1: AIL, ELE, THR, RUD, COL (ch 6), GYRO (ch 7) are proportional. Gear (ch 5) is binary. **This mode is highly experimental.**
CH1|CH2|CH3|CH4|CH5|CH6|CH7 ### Sub_protocol Q200 - *3*
---|---|---|---|---|---|--- Model: Dromida Ominus Quadcopter FPV, the Nine Eagles - FENG FPV and may be others
A|E|T|R|GEAR|COL|GYRO
### Sub_protocol W6_HEL - *4* and W6HEL_I - *5* Dromida Ominus FPV channels mapping:
WK2601 Heli: AIL, ELE, THR, RUD, GYRO are proportional. Gear (ch 5) is binary. COL (ch 6) is linked to Thr. If Ch6 >= 0, the receiver will apply a 3D curve to the Thr. If Ch6 < 0, the receiver will apply normal curves to the Thr. The value of Ch6 defines the ratio of COL to THR.
W6HEL_I: Invert COL servo CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|RATES|-|CH7|CH8|MODE|FLIP|VID_ON|VID_OFF|CALIB
option= maximum range of COL servo FENG FPV: channels mapping:
CH1|CH2|CH3|CH4|CH5|CH6|CH7 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|--- ---|---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|GEAR|COL|GYRO A|E|T|R|RATES|-|CH7|CH8|FLIP|MODE|VID_ON|VID_OFF|CALIB
## DSM - *6* RATES takes any value between -50..+50%: -50%=min rates, 0%=mid rates (stock setting), +50%=max rates
Extended limits supported
Telemetry enabled for TSSI and plugins CH7 and CH8 have no visible effect
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|CH14 MODE: -100% level, +100% acro
---|---|---|---|---|---|---|---|---|----|----|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|TH_KILL
Notes: FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (rear red LED goes out while active) -100%..+100% or +100%..-100%
- The "AUTO" sub protocol is recommended to automatically select the best settings for your DSM RX. If the RX doesn't bind or work properly after bind, don't hesitate to test different combinations of sub protocol and number of channels until you have something working.
- Servo refresh rate is 22ms unless you select 11ms available in OpenTX 2.3.10+
- RX output will match the Spektrum standard TAER independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- RX output will match the Spektrum standard throw (1500µs +/- 400µs -> 1100..1900µs) for a 100% input. This is true for both Serial and PPM input. For PPM, make sure the end points PPM_MIN_100 and PPM_MAX_100 in _config.h are matching your TX ouput. The maximum ouput is 1000..2000µs based on an input of 125%.
- If you want to override the above and get maximum throw either uncomment in _config.h the line #define DSM_MAX_THROW or on OpenTX 2.3.3+ use the "Enable max throw" feature on the GUI (0=No,1=Yes). In this mode to achieve standard throw use a channel weight of 84%.
- TH_KILL is a feature which is enabled on channel 14 by default (can be disabled/changed) in the _config.h file. Some models (X-Vert, Blade 230S...) require a special position to instant stop the motor(s). If the channel 14 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%. For example, a value of -80% applied on channel 14 will instantly kill the motors on the X-Vert.
- To allow SAFE to be ON with a switch assignment you must remove the bind plug after powering up the RX but before turning on the TX to bind. If you select Autodetect to bind, The MPM will choose DSMX 11ms and Channels 1-7 ( Change to 1-9 if you wish to assign switch above channel 7 ). Then in order to use the manuals diagram of both sticks "Down-Inside" to set a SAFE Select Switch Designation, you must have Throttle and Elevator channels set to Normal direction but the Aileron and Rudder set to Reverse direction. If setting up a new model with all channels set to Normal you can hold both sticks "Down- OUTSIDE" to assign the switch with 5x flips. Tested on a Mode2 radio.
Option=number of channels from 3 to 12. Option|0x80 enables Max Throw. Option|0x40 enables a servo refresh rate of 11ms.
### Sub_protocol DSM2_1F - *0* CALIB: -100% normal mode, +100% gyro calibration
DSM2, Resolution 1024, servo refresh rate can only be 22ms
### Sub_protocol DSM2_2F - *1*
DSM2, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
### Sub_protocol DSMX_1F - *2*
DSMX, Resolution 2048, servo refresh rate can only be 22ms
### Sub_protocol DSMX_2F - *3*
DSMX, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
### Sub_protocol AUTO - *4*
"AUTO" is recommended to automatically select the best settings for your DSM RX.
## DSM_RX - *70* ### Sub_protocol MR100 - *4*
The DSM receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,... Models: Vista UAV, FPV, FPV v2
Notes:
- Automatically detect DSM 2/X 11/22ms 1024/2048res
- Bind should be done with all other modules off in the radio
- Available in OpenTX 2.3.3+, Trainer Mode Master/Multi
- Channels 1..4 are remapped to the module default channel order unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- Extended limits supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|---- ---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12 A|E|T|R|RATES|-|CH7|CH8|MODE|FLIP|VIDEO|PICTURE
## E010R5 - *81* RATES takes any value between -50..+50%: -50%=min rates, 0%=mid rates (stock setting), +50%=max rates
Models: E010 R5 red boards, JJRC H36, H36F and H36S
**Only 4 IDs are available**. More IDs can be added if you send me your "unused" original TX. CH7 and CH8 have no visible effect
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10 FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (rear red LED goes out while active) -100%..+100% or +100%..-100%
---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|CALIB|HEADLESS|RTH|GLIDE
## E129 - *83* MODE: -100% level, +100% acro
Models: Eachine E129/E130 and Twister Ninja 250
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9 ## V911S - *46*
---|---|---|---|---|---|---|---|---
A|E|T|R|Take off/Land|Emergency|Trim A|Trim E|Trim R
Trims can be done to some extent on the AETR channels directly but if you push them too far you won't be able to arm like explained below. In this case use the associated trim TrimA/E/R instead. CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|CALIB
Take off with a none spring throttle is easier by putting both sticks down outwards (like on the original radio) in Mode 1/2, not sure about other modes. ### Sub_protocol V911S - *0*
Models: WLtoys V911S, XK A110
Calib is the same as the original radio with both sticks down and to the left in Mode 1/2, not sure about other modes. ### Sub_protocol E119 - *1*
Models: Eachine E119
## J6Pro - *22*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
## MLINK - *78*
Extended limits supported
Bind: the RX must be really close to the TX
**Failsafe MUST be configured once with the desired channel values (hold or no pulses are not supported) while the RX is up (wait 10+sec for the RX to learn the config) and then failsafe MUST be set to RX/Receiver otherwise the servos will jitter!!!**
Telemetry: the 2 RXs I have are sending different information in different format
- RX-5: RX_RSSI=RSSI=sort of RSSI or link quality, RX_LQI=number of connection lost, TX_RSSI=RSSI from the TX perspective, TX_LQI=percentage of received telemetry packets
- RX-9-DR: A1=RX Batt (Ratio=12.7), **RX_RSSI=TX_LQI**=percentage of received telemetry packets **from the TX** perspective **not RX**, TX_RSSI=RSSI from the TX perspective, TX_LQI=percentage of received telemetry packets
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
## Traxxas - *43*
Receiver 6519
Extended limits supported
CH1|CH2|CH3|CH4
---|---|---|---
AUX3|AUX4|THROTTLE|STEERING
## WFLY - *40*
Receivers: WFR04S, WFR07S, WFR09S
Extended limits supported
option=number of channels from 4 to 9. An invalid option value will end up sending 9 channels.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
*** ***
# NRF24L01 RF Module # NRF24L01 RF Module
@ -1173,27 +1319,6 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|--- ---|---|---|---|---|---|---|---
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT A|E|T|R|FLIP|RTH|HEADLESS|EXPERT
## GD00X - *47*
Model: GD005 C-17 Transport, GD006 DA62 and ZC-Z50
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A||T||TRIM|LED|RATE
TRIM: either use this channel for trim only or add a mixer with aileron to increase the roll rate.
RATE: -100% high rate, +100% low rate
### Sub_protocol GD_V1 - *0*
First generation of GD models, ZC-Z50
### Sub_protocol GD_V2 - *1*
New generation of GD models
## GW008 - *32* ## GW008 - *32*
Model: Global Drone GW008 from Banggood Model: Global Drone GW008 from Banggood
@ -1290,17 +1415,6 @@ Model: DF-Models SkyTumbler
RTH not supported RTH not supported
## KF606 - *49*
Model: KF606
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A||T||TRIM
## LOLI - *82* ## LOLI - *82*
LOLI3 receivers: https://github.com/wooddoor/Loli3 LOLI3 receivers: https://github.com/wooddoor/Loli3
@ -1345,9 +1459,9 @@ Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol E010 - *4* ### Sub_protocol E010 - *4*
15 TX IDs available, change RX_Num value 0..14 to cycle through them 15 TX IDs available, change RX_Num value 0..14 to cycle through them
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components. If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md). If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
### Sub_protocol H26WH - *5* ### Sub_protocol H26WH - *5*
CH6| CH6|
@ -1377,9 +1491,9 @@ Model: Yi Zhan i6S
Only one model can be flown at the same time since the ID is hardcoded. Only one model can be flown at the same time since the ID is hardcoded.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components. If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md). If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
### Sub_protocol LS - *3* ### Sub_protocol LS - *3*
Models: LS114, 124, 215 Models: LS114, 124, 215
@ -1426,30 +1540,6 @@ CH1|CH2|CH3|CH4|CH5
---|---|---|---|--- ---|---|---|---|---
A|E|T|R|Warp A|E|T|R|Warp
## OMP - *77*
Model: OMPHOBBY M1 & M2 Helis, T720 RC Glider
This protocol requires both a NRF24L01 and CC2500 RF components to operate.
Telemetry supported:
- A1 = battery voltage including "recovered" battery voltage from corrupted telemetry packets
- A2 = battery voltage from only good telemetry packets
- How to calculate accurately the OpenTX Ratio and Offset:
Set the Ratio to 12.7 and Offset to 0, plug 2 batteries with extreme voltage values, write down the values Batt1=12.5V & Telem1=12.2V, Batt2=7V & Telem2=6.6V then calculate/set Ratio=12.7*[(12.5-7)/(12.2-6.6)]=12.47 => 12.5 and Offset=12.5-12.2*[(12.5-7)/(12.2-6.6)]=0.517 => 0.5
- RX_RSSI = TQly = percentage of received telemetry packets (good and corrupted) from the model which has nothing to do with how well the RX is receiving the TX
Option for this protocol corresponds to the CC2500 fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T_PITCH|R|T_HOLD|IDLE|MODE
IDLE= 3 pos switch: -100% Normal, 0% Idle1, +100% Idle2
From the TX manual: MODE= 3 pos switch -100% Attitude, 0% Attitude(?), +100% 3D
For M2: MODE= 3 pos switch -100% 6G, 0% 3D, +100% 3D
## Potensic - *51* ## Potensic - *51*
Model: Potensic A20 Model: Potensic A20
@ -1501,9 +1591,9 @@ A|E|T|R
### Sub_protocol Q303 - *0* ### Sub_protocol Q303 - *0*
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components. If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md). If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
CH5|CH6|CH7|CH8|CH9|CH10|CH11 CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|--- ---|---|---|---|---|---|---
@ -1538,19 +1628,6 @@ ARM|FLIP
ARM is 3 positions: -100%=land / 0%=manual / +100%=take off ARM is 3 positions: -100%=land / 0%=manual / +100%=take off
## Q90C - *72*
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|FMODE|VTX+
FMODE: -100% angle, 0% horizon, +100% acro
VTX+: -100%->+100% channel+
## Realacc - *76* ## Realacc - *76*
Model: Realacc R11 Model: Realacc R11
@ -1581,82 +1658,6 @@ CH1|CH2|CH3|CH4
Throttle +100%=full forward,0%=stop,-100%=full backward. Throttle +100%=full forward,0%=stop,-100%=full backward.
## SLT - *11*
Autobind protocol
This protocol is known to be problematic because it's using the NRF24L01 with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is a hardware issue with the accuracy of the components. (some Jumper models seem to be using a NRF24L01 clone)
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
### Sub_protocol V1 - *0*
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|GEAR|PITCH
### Sub_protocol V2 - *1*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
### Sub_protocol Q100 - *2*
Models: Dromida Ominus UAV
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|RATES|-|CH7|CH8|MODE|FLIP|-|-|CALIB
RATES takes any value between -50..+50%: -50%=min rates, 0%=mid rates (stock setting), +50%=max rates
CH7 and CH8 have no visible effect
MODE: -100% level, +100% acro
FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (rear red LED goes out while active) -100%..+100% or +100%..-100%
CALIB: -100% normal mode, +100% gyro calibration
### Sub_protocol Q200 - *3*
Model: Dromida Ominus Quadcopter FPV, the Nine Eagles - FENG FPV and may be others
Dromida Ominus FPV channels mapping:
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|RATES|-|CH7|CH8|MODE|FLIP|VID_ON|VID_OFF|CALIB
FENG FPV: channels mapping:
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|RATES|-|CH7|CH8|FLIP|MODE|VID_ON|VID_OFF|CALIB
RATES takes any value between -50..+50%: -50%=min rates, 0%=mid rates (stock setting), +50%=max rates
CH7 and CH8 have no visible effect
MODE: -100% level, +100% acro
FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (rear red LED goes out while active) -100%..+100% or +100%..-100%
CALIB: -100% normal mode, +100% gyro calibration
### Sub_protocol MR100 - *4*
Models: Vista UAV, FPV, FPV v2
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|RATES|-|CH7|CH8|MODE|FLIP|VIDEO|PICTURE
RATES takes any value between -50..+50%: -50%=min rates, 0%=mid rates (stock setting), +50%=max rates
CH7 and CH8 have no visible effect
FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (rear red LED goes out while active) -100%..+100% or +100%..-100%
MODE: -100% level, +100% acro
## Symax - *10* ## Symax - *10*
Autobind protocol Autobind protocol
@ -1739,21 +1740,6 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
A|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN A|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
## V911S - *46*
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|CALIB
### Sub_protocol V911S - *0*
Models: WLtoys V911S, XK A110
### Sub_protocol E119 - *1*
Models: Eachine E119
## XK - *62* ## XK - *62*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
@ -1765,9 +1751,9 @@ Flight_modes: -100%=M-Mode, 0%=6G-Mode, +100%=V-Mode. CH6-CH10 are mementary swi
### Sub_protocol X450 - *0* ### Sub_protocol X450 - *0*
Models: XK X450 (TX=X8) Models: XK X450 (TX=X8)
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components. If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md). If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
### Sub_protocol X420 - *1* ### Sub_protocol X420 - *1*
Models: XK X420/X520 (TX=X4) Models: XK X420/X520 (TX=X4)