diff --git a/Multiprotocol/Multi.txt b/Multiprotocol/Multi.txt index 3b1b8f1..b416a3b 100644 --- a/Multiprotocol/Multi.txt +++ b/Multiprotocol/Multi.txt @@ -40,4 +40,6 @@ 40,WFLY 41,BUGS 42,BUGSMINI +43,Traxxas +44,NCC1701 63,Test diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index f0f1717..a05fb0e 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -19,7 +19,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 2 #define VERSION_REVISION 1 -#define VERSION_PATCH_LEVEL 3 +#define VERSION_PATCH_LEVEL 4 //****************** // Protocols @@ -69,6 +69,8 @@ enum PROTOCOLS PROTO_WFLY = 40, // =>CYRF6936 PROTO_BUGS = 41, // =>A7105 PROTO_BUGSMINI = 42, // =>NRF24L01 + PROTO_TRAXXAS = 43, // =>CYRF6936 + PROTO_NCC1701 = 44, // =>NRF24L01 PROTO_TEST = 63, // =>NRF24L01 }; @@ -581,6 +583,8 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- WFLY 40 BUGS 41 BUGSMINI 42 + TRAXXAS 43 + NCC1701 44 BindBit=> 0x80 1=Bind/0=No AutoBindBit=> 0x40 1=Yes /0=No RangeCheck=> 0x20 1=Yes /0=No diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index d74a131..0072d44 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -89,7 +89,7 @@ uint8_t Channel_AUX; // Protocol variables uint8_t cyrfmfg_id[6];//for dsm2 and devo uint8_t rx_tx_addr[5]; -uint8_t rx_id[4]; +uint8_t rx_id[5]; uint8_t phase; uint16_t bind_counter; uint8_t bind_phase; @@ -1193,6 +1193,12 @@ static void protocol_init() remote_callback = BUGSMINI_callback; break; #endif + #if defined(NCC1701_NRF24L01_INO) + case PROTO_NCC1701: + next_callback=initNCC(); + remote_callback = NCC_callback; + break; + #endif #if defined(TEST_NRF24L01_INO) case PROTO_TEST: next_callback=initTest(); diff --git a/Multiprotocol/NCC1701_nrf24l01.ino b/Multiprotocol/NCC1701_nrf24l01.ino new file mode 100644 index 0000000..abb6164 --- /dev/null +++ b/Multiprotocol/NCC1701_nrf24l01.ino @@ -0,0 +1,243 @@ +/* + This project is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Multiprotocol is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Multiprotocol. If not, see . + */ + +#if defined(NCC1701_NRF24L01_INO) + +#include "iface_nrf24l01.h" + +#define NCC_WRITE_WAIT 2000 +#define NCC_PACKET_INTERVAL 10333 +#define NCC_TX_PACKET_LEN 16 +#define NCC_RX_PACKET_LEN 13 + +enum { + NCC_BIND_TX1=0, + NCC_BIND_RX1, + NCC_BIND_TX2, + NCC_BIND_RX2, + NCC_DATA, +}; + +static void __attribute__((unused)) NCC_init() +{ + NRF24L01_Initialize(); + NRF24L01_SetTxRxMode(TX_EN); + + NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address + NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5); + NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5); + + NRF24L01_FlushTx(); + NRF24L01_FlushRx(); + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit + NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes + NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only + NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, NCC_RX_PACKET_LEN); // Enable rx pipe 0 + NRF24L01_SetBitrate(NRF24L01_BR_250K); // NRF24L01_BR_1M, NRF24L01_BR_2M, NRF24L01_BR_250K + NRF24L01_SetPower(); + NRF24L01_FlushRx(); + NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to TX mode and disable CRC + | (1 << NRF24L01_00_CRCO) + | (1 << NRF24L01_00_PWR_UP) + | (0 << NRF24L01_00_PRIM_RX)); +} + +uint8_t NCC_xorout[]={0x80, 0x44, 0x64, 0x75, 0x6C, 0x71, 0x2A, 0x36, 0x7C, 0xF1, 0x6E, 0x52, 0x09, 0x9D}; +static void __attribute__((unused)) NCC_Crypt_Packet() +{ + uint16_t crc=0; + for(uint8_t i=0; i< NCC_TX_PACKET_LEN-2; i++) + { + packet[i]^=NCC_xorout[i]; + crc=crc16_update(crc, packet[i], 8); + } + crc^=0x60DE; + packet[NCC_TX_PACKET_LEN-2]=crc>>8; + packet[NCC_TX_PACKET_LEN-1]=crc; +} +static boolean __attribute__((unused)) NCC_Decrypt_Packet() +{ + uint16_t crc=0; + debug("RX: "); + for(uint8_t i=0; i< NCC_RX_PACKET_LEN-2; i++) + { + crc=crc16_update(crc, packet[i], 8); + packet[i]^=NCC_xorout[i]; + debug("%02X ",packet[i]); + } + crc^=0xA950; + if( (crc>>8)==packet[NCC_RX_PACKET_LEN-2] && (crc&0xFF)==packet[NCC_RX_PACKET_LEN-1] ) + {// CRC match + debugln("OK"); + return true; + } + debugln("NOK"); + return false; +} + +static void __attribute__((unused)) NCC_Write_Packet() +{ + packet[0]=0xAA; + packet[1]=rx_tx_addr[0]; + packet[2]=rx_tx_addr[1]; + packet[3]=rx_id[0]; + packet[4]=rx_id[1]; + packet[5]=convert_channel_8b(THROTTLE)>>2; // 00-3D + packet[6]=convert_channel_8b(ELEVATOR); // original: 61-80-9F but works with 00-80-FF + packet[7]=convert_channel_8b(AILERON ); // original: 61-80-9F but works with 00-80-FF + packet[8]=convert_channel_8b(RUDDER ); // original: 61-80-9F but works with 00-80-FF + packet[9]=rx_id[2]; + packet[10]=rx_id[3]; + packet[11]=rx_id[4]; + packet[12]=0x02; // default:0x00 -> Warp:0x02 ?? + packet[13]=packet[5]+packet[6]+packet[7]+packet[8]+packet[12]; + if(phase==NCC_BIND_TX1) + { + packet[0]=0xBB; + packet[5]=0x01; + packet[6]=rx_tx_addr[2]; + memset((void *)(packet+7),0x55,7); + hopping_frequency_no^=1; + } + else + { + hopping_frequency_no++; + if(hopping_frequency_no>2) hopping_frequency_no=0; + } + // change frequency + NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]); + // switch to TX mode and disable CRC + NRF24L01_SetTxRxMode(TXRX_OFF); + NRF24L01_SetTxRxMode(TX_EN); + NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) + | (1 << NRF24L01_00_CRCO) + | (1 << NRF24L01_00_PWR_UP) + | (0 << NRF24L01_00_PRIM_RX)); + // clear packet status bits and TX FIFO + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); + NRF24L01_FlushTx(); + // send packet + NCC_Crypt_Packet(); + NRF24L01_WritePayload(packet,NCC_TX_PACKET_LEN); + NRF24L01_SetPower(); +} + +uint16_t NCC_callback() +{ + switch(phase) + { + case NCC_BIND_TX1: + if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) + { // RX fifo data ready + NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN); + if(NCC_Decrypt_Packet()) + { + rx_id[0]=packet[3]; + rx_id[1]=packet[4]; + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit + phase=NCC_BIND_TX2; + return NCC_PACKET_INTERVAL; + } + } + NCC_Write_Packet(); + phase = NCC_BIND_RX1; + return NCC_WRITE_WAIT; + case NCC_BIND_RX1: + // switch to RX mode and disable CRC + NRF24L01_SetTxRxMode(TXRX_OFF); + NRF24L01_SetTxRxMode(RX_EN); + NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) + | (1 << NRF24L01_00_CRCO) + | (1 << NRF24L01_00_PWR_UP) + | (1 << NRF24L01_00_PRIM_RX)); + NRF24L01_FlushRx(); + phase = NCC_BIND_TX1; + return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT; + case NCC_BIND_TX2: + if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) + { // RX fifo data ready + NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN); + if(NCC_Decrypt_Packet()) + { + rx_id[2]=packet[8]; + rx_id[3]=packet[9]; + rx_id[4]=packet[10]; + NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit + BIND_DONE; + phase=NCC_DATA; + return NCC_PACKET_INTERVAL; + } + } + NCC_Write_Packet(); + phase = NCC_BIND_RX2; + return NCC_WRITE_WAIT; + case NCC_BIND_RX2: + // switch to RX mode and disable CRC + NRF24L01_SetTxRxMode(TXRX_OFF); + NRF24L01_SetTxRxMode(RX_EN); + NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) + | (1 << NRF24L01_00_CRCO) + | (1 << NRF24L01_00_PWR_UP) + | (1 << NRF24L01_00_PRIM_RX)); + NRF24L01_FlushRx(); + phase = NCC_BIND_TX2; + return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT; + case NCC_DATA: + NCC_Write_Packet(); + return NCC_PACKET_INTERVAL; + } + return 0; +} + +const uint8_t PROGMEM NCC_TX_DATA[][6]= { + { 0x6D, 0x97, 0x04, 0x48, 0x43, 0x26 }, + { 0x35, 0x4B, 0x80, 0x44, 0x4C, 0x0B }, + { 0x50, 0xE2, 0x32, 0x2D, 0x4B, 0x0A }, + { 0xBF, 0x34, 0xF3, 0x45, 0x4D, 0x0D }, + { 0xDD, 0x7D, 0x5A, 0x46, 0x28, 0x23 }, + { 0xED, 0x19, 0x06, 0x2C, 0x4A, 0x09 }, + { 0xE9, 0xA8, 0x91, 0x2B, 0x49, 0x07 }, + { 0x66, 0x17, 0x7D, 0x48, 0x43, 0x26 }, + { 0xC2, 0x93, 0x55, 0x44, 0x4C, 0x0B }, +}; + +uint16_t initNCC(void) +{ + BIND_IN_PROGRESS; // autobind protocol + + // Load TX data + uint8_t rand=rx_tx_addr[3]%9; + for(uint8_t i=0; i<3; i++) + { + rx_tx_addr[i]=pgm_read_byte_near(&NCC_TX_DATA[rand][i]); + hopping_frequency[i]=pgm_read_byte_near(&NCC_TX_DATA[rand][i+3]); + } + + // RX data is acquired during bind + rx_id[0]=0x00; + rx_id[1]=0x00; + rx_id[2]=0x20; + rx_id[3]=0x20; + rx_id[4]=0x20; + + hopping_frequency[4]=0x08; // bind channel 1 + hopping_frequency[5]=0x2A; // bind channel 2 + hopping_frequency_no=4; // start with bind + NCC_init(); + phase=NCC_BIND_TX1; + return 10000; +} + +#endif diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index c18b023..eff35ee 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -146,6 +146,7 @@ #undef J6PRO_CYRF6936_INO #undef WFLY_CYRF6936_INO #undef WK2x01_CYRF6936_INO + #undef TRAXXAS_CYRF6936_INO #endif #ifndef CC2500_INSTALLED #undef FRSKYD_CC2500_INO @@ -181,6 +182,7 @@ #undef H8_3D_NRF24L01_INO #undef CFLIE_NRF24L01_INO #undef BUGSMINI_NRF24L01_INO + #undef NCC1701_NRF24L01_INO #endif //Make sure telemetry is selected correctly diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index 6a8d910..04c66f4 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -159,6 +159,7 @@ #define J6PRO_CYRF6936_INO #define WFLY_CYRF6936_INO #define WK2x01_CYRF6936_INO +//#define TRAXXAS_CYRF6936_INO //The protocols below need a CC2500 to be installed #define CORONA_CC2500_INO @@ -188,6 +189,7 @@ #define KN_NRF24L01_INO #define MJXQ_NRF24L01_INO #define MT99XX_NRF24L01_INO +#define NCC1701_NRF24L01_INO #define Q303_NRF24L01_INO #define SHENQI_NRF24L01_INO #define SLT_NRF24L01_INO @@ -571,6 +573,10 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= { Q100 Q200 MR100 + PROTO_TRAXXAS + NONE + PROTO_NCC1701 + NONE */ // RX_Num is used for TX & RX match. Using different RX_Num values for each receiver will prevent starting a model with the false config loaded...