From 4bb4bd97926818bb0414e0cdef5dd522f11aa1a7 Mon Sep 17 00:00:00 2001 From: Pascal Langer Date: Tue, 21 Aug 2018 14:58:44 +0200 Subject: [PATCH] New protocol WFLY (40) Use the CYRF6936 RF component Extended limit supported No sub protocol option=number of channels between 4 and 9. If outside of the range default=9. --- Multiprotocol/CYRF6936_SPI.ino | 10 +- Multiprotocol/DSM_cyrf6936.ino | 6 +- Multiprotocol/Hitec_cc2500.ino | 8 +- Multiprotocol/J6Pro_cyrf6936.ino | 12 +- Multiprotocol/Multi.txt | 1 + Multiprotocol/Multiprotocol.h | 4 +- Multiprotocol/Multiprotocol.ino | 10 +- Multiprotocol/Validate.h | 1 + Multiprotocol/WFLY_cyrf6936.ino | 294 +++++++++++++++++++++++++++++++ Multiprotocol/_Config.h | 41 +++-- 10 files changed, 347 insertions(+), 40 deletions(-) create mode 100644 Multiprotocol/WFLY_cyrf6936.ino diff --git a/Multiprotocol/CYRF6936_SPI.ino b/Multiprotocol/CYRF6936_SPI.ino index bcc0d6c..20136b8 100644 --- a/Multiprotocol/CYRF6936_SPI.ino +++ b/Multiprotocol/CYRF6936_SPI.ino @@ -98,13 +98,15 @@ void CYRF_SetTxRxMode(uint8_t mode) { if(mode==TXRX_OFF) { - CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24); // 4=IDLE, 8=TX, C=RX + if(protocol!=PROTO_WFLY) + CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24); // 4=IDLE, 8=TX, C=RX CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x00); // XOUT=0 PACTL=0 } else { //Set the post tx/rx state - CYRF_WriteRegister(CYRF_0F_XACT_CFG, mode == TX_EN ? 0x28 : 0x2C); // 4=IDLE, 8=TX, C=RX + if(protocol!=PROTO_WFLY) + CYRF_WriteRegister(CYRF_0F_XACT_CFG, mode == TX_EN ? 0x28 : 0x2C); // 4=IDLE, 8=TX, C=RX if(mode == TX_EN) #ifdef ORANGE_TX_BLUE CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x20); // XOUT=1, PACTL=0 @@ -203,9 +205,9 @@ void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length) static void CYRF_WriteDataPacketLen(const uint8_t dpbuffer[], uint8_t len) { CYRF_WriteRegister(CYRF_01_TX_LENGTH, len); - CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40); + CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x43); // 0x40 CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, dpbuffer, len); - CYRF_WriteRegister(CYRF_02_TX_CTRL, 0xBF); + CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x83); // 0xBF } void CYRF_WriteDataPacket(const uint8_t dpbuffer[]) diff --git a/Multiprotocol/DSM_cyrf6936.ino b/Multiprotocol/DSM_cyrf6936.ino index 98fc67f..5586227 100644 --- a/Multiprotocol/DSM_cyrf6936.ino +++ b/Multiprotocol/DSM_cyrf6936.ino @@ -448,9 +448,9 @@ uint16_t ReadDsm() case DSM_CH1_CHECK_B: case DSM_CH2_CHECK_A: case DSM_CH2_CHECK_B: - start=micros(); - while ((uint8_t)micros()-start < 100) // Wait max 100µs, max I've seen is 50µs - if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02) + start=(uint8_t)micros(); + while ((uint8_t)((uint8_t)micros()-(uint8_t)start) < 100) // Wait max 100µs, max I've seen is 50µs + if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00) break; if(phase==DSM_CH1_CHECK_A || phase==DSM_CH1_CHECK_B) { diff --git a/Multiprotocol/Hitec_cc2500.ino b/Multiprotocol/Hitec_cc2500.ino index cdcc3ee..2f57628 100644 --- a/Multiprotocol/Hitec_cc2500.ino +++ b/Multiprotocol/Hitec_cc2500.ino @@ -39,13 +39,11 @@ enum { HITEC_RX2 = 0x08, }; -#define HITEC_FREQ0_VAL 0xE8 - const PROGMEM uint8_t HITEC_init_values[] = { /* 00 */ 0x2F, 0x2E, 0x2F, 0x07, 0xD3, 0x91, 0xFF, 0x04, - /* 08 */ 0x45, 0x00, 0x00, 0x12, 0x00, 0x5C, 0x85, HITEC_FREQ0_VAL + HITEC_COARSE, + /* 08 */ 0x45, 0x00, 0x00, 0x12, 0x00, 0x5C, 0x85, 0xE8 + HITEC_COARSE, /* 10 */ 0x3D, 0x3B, 0x73, 0x73, 0x7A, 0x01, 0x07, 0x30, - /* 18 */ 0x08, 0x1D, 0x1C, 0xC7, 0x00, 0xB0, 0x87, 0x6B, + /* 18 */ 0x08, 0x1D, 0x1C, 0xC7, 0x40, 0xB0, 0x87, 0x6B, /* 20 */ 0xF8, 0xB6, 0x10, 0xEA, 0x0A, 0x00, 0x11 }; @@ -325,7 +323,7 @@ uint16_t ReadHITEC() // 0C,1C,A1,2B,00,16,00,00,00,00,00,16,00,2C,8E // 0C,1C,A1,2B,00,17,00,00,00,42,44,17,00,48,8D -> 42=>temperature3 0x42-0x28=26°C,44=>temperature4 0x44-0x28=28°C // 0C,1C,A1,2B,00,18,00,00,00,00,00,18,00,50,92 - debug(",telem"); + debug(",telem,%02x",pkt[14]&0x7F); #if defined(HITEC_FW_TELEMETRY) if(sub_protocol==OPT_FW) { diff --git a/Multiprotocol/J6Pro_cyrf6936.ino b/Multiprotocol/J6Pro_cyrf6936.ino index ff8b43f..454739a 100644 --- a/Multiprotocol/J6Pro_cyrf6936.ino +++ b/Multiprotocol/J6Pro_cyrf6936.ino @@ -128,7 +128,7 @@ static void __attribute__((unused)) j6pro_set_radio_channels() uint16_t ReadJ6Pro() { - uint32_t start; + uint16_t start; switch(phase) { @@ -144,11 +144,11 @@ uint16_t ReadJ6Pro() phase = J6PRO_BIND_03_START; return 3000; //3msec case J6PRO_BIND_03_START: - start=micros(); - while (micros()-start < 500) // Wait max 500µs - if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x06) - break; - CYRF_ConfigRFChannel(0x53); + start=(uint16_t)micros(); + while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 500) // Wait max 500µs + if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00) + break; // Packet transmission complete + CYRF_ConfigRFChannel(0x53); CYRF_SetTxRxMode(RX_EN); //CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a); CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x80); diff --git a/Multiprotocol/Multi.txt b/Multiprotocol/Multi.txt index 577f81d..c0741c2 100644 --- a/Multiprotocol/Multi.txt +++ b/Multiprotocol/Multi.txt @@ -37,3 +37,4 @@ 37,CORONA,COR_V1,COR_V2,FD_V3 38,CFlie 39,Hitec,OPT_FW,OPT_HUB,MINIMA +40,WFLY diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index c39ffbb..b0eb649 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -19,7 +19,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 2 #define VERSION_REVISION 0 -#define VERSION_PATCH_LEVEL 31 +#define VERSION_PATCH_LEVEL 32 //****************** // Protocols @@ -66,6 +66,7 @@ enum PROTOCOLS PROTO_CORONA = 37, // =>CC2500 PROTO_CFLIE = 38, // =>NRF24L01 PROTO_HITEC = 39, // =>CC2500 + PROTO_WFLY = 40, // =>CYRF6936 }; enum Flysky @@ -569,6 +570,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p -- CORONA 37 CFlie 38 Hitec 39 + WFLY 40 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 6c1ae97..daa6541 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -108,10 +108,8 @@ uint16_t crc; uint8_t crc8; uint16_t seed; uint16_t failsafe_count; -// uint16_t state; uint8_t len; -uint8_t RX_num; #if defined(FRSKYX_CC2500_INO) || defined(SFHSS_CC2500_INO) uint8_t calData[48]; @@ -157,6 +155,7 @@ uint8_t option; uint8_t cur_protocol[3]; uint8_t prev_option; uint8_t prev_power=0xFD; // unused power value +uint8_t RX_num; //Serial RX variables #define BAUD 100000 @@ -975,6 +974,13 @@ static void protocol_init() remote_callback = ReadDsm; break; #endif + #if defined(WFLY_CYRF6936_INO) + case PROTO_WFLY: + PE2_on; //antenna RF4 + next_callback = initWFLY(); + remote_callback = ReadWFLY; + break; + #endif #if defined(DEVO_CYRF6936_INO) case PROTO_DEVO: #ifdef ENABLE_PPM diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index 9308fa0..aec20da 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -143,6 +143,7 @@ #undef DEVO_CYRF6936_INO #undef DSM_CYRF6936_INO #undef J6PRO_CYRF6936_INO + #undef WFLY_CYRF6936_INO #undef WK2x01_CYRF6936_INO #endif #ifndef CC2500_INSTALLED diff --git a/Multiprotocol/WFLY_cyrf6936.ino b/Multiprotocol/WFLY_cyrf6936.ino new file mode 100644 index 0000000..c4bf9e6 --- /dev/null +++ b/Multiprotocol/WFLY_cyrf6936.ino @@ -0,0 +1,294 @@ +/* + 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(WFLY_CYRF6936_INO) + +#include "iface_cyrf6936.h" + +//#define WFLY_FORCE_ID +#define WFLY_BIND_COUNT 1500 // around 15s +#define WFLY_NUM_FREQUENCE 4 +#define WFLY_BIND_CHANNEL 0x09 + +enum { + WFLY_BIND_TX=0, + WFLY_BIND_PREP_RX, + WFLY_BIND_RX, + WFLY_PREP_DATA, + WFLY_DATA, +}; + +const uint8_t PROGMEM WFLY_sop_bind[]={ 0x5A, 0xCC, 0xAE, 0x46, 0xB6, 0x31, 0xAE, 0x46 }; +const uint8_t PROGMEM WFLY_sop_data[]={ 0xEF, 0x64, 0xB0, 0x2A, 0xD2, 0x8F, 0xB1, 0x2A }; + +//Most of the bytes are unknown... 1C A7 looks to be the bind ID, BF 13 is the TX ID, 15 is the channel used to send the hopping frequencies. +const uint8_t PROGMEM WFLY_bind_packet[]={ 0x1C, 0xA7, 0x60, 0x04, 0x04, 0xBF, 0x13, 0x15, 0xC5, 0x40, 0x8A, 0x37, 0xE0, 0xE8, 0x03, 0xA3 }; + + +const uint8_t PROGMEM WFLY_init_vals[][2] = { + //Init from dump + {CYRF_1D_MODE_OVERRIDE, 0x19}, // Reset + {CYRF_32_AUTO_CAL_TIME, 0x3C}, // Default init value + {CYRF_35_AUTOCAL_OFFSET, 0x14}, // Default init value + {CYRF_1B_TX_OFFSET_LSB, 0x55}, // Default init value + {CYRF_1C_TX_OFFSET_MSB, 0x05}, // Default init value + {CYRF_06_RX_CFG, 0x48 | 0x02}, // LNA enabled, Fast Turn Mode enabled, adding overwrite enable to not lockup RX + {CYRF_10_FRAMING_CFG, 0xE8}, // SOP enable + {CYRF_03_TX_CFG, 0x08 | CYRF_BIND_POWER}, // Original=0x0F, 8DR Mode, 32 chip codes + {CYRF_0C_XTAL_CTRL, 0xC4}, // Enable XOUT as GPIO + {CYRF_0D_IO_CFG, 0x04}, // Enable PACTL as GPIO + {CYRF_0F_XACT_CFG, 0x21}, // Abort current operation + {CYRF_1E_RX_OVERRIDE, 0x00}, // Accept packets with 0 seed for bind + {CYRF_15_CRC_SEED_LSB, 0x00}, // CRC seed for bind + {CYRF_16_CRC_SEED_MSB, 0x00}, // CRC seed for bind +}; + +static void __attribute__((unused)) WFLY_cyrf_bind_config() +{ + for(uint8_t i = 0; i < sizeof(init_vals) / 2; i++) + CYRF_WriteRegister(pgm_read_byte_near(&WFLY_init_vals[i][0]), pgm_read_byte_near(&WFLY_init_vals[i][1])); + + CYRF_PROGMEM_ConfigSOPCode(WFLY_sop_bind); + CYRF_ConfigRFChannel(WFLY_BIND_CHANNEL); + CYRF_SetTxRxMode(TX_EN); +} + +static void __attribute__((unused)) WFLY_cyrf_data_config() +{ + for(uint8_t i = 0; i < (sizeof(init_vals) / 2)-3; i++) + CYRF_WriteRegister(pgm_read_byte_near(&WFLY_init_vals[i][0]), pgm_read_byte_near(&WFLY_init_vals[i][1])); + + //CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x08); // Do not accept CRC with 0 seed but not needed since the RX is not sending any data... + CYRF_WriteRegister(CYRF_15_CRC_SEED_LSB, rx_tx_addr[2]); + CYRF_WriteRegister(CYRF_16_CRC_SEED_MSB, rx_tx_addr[3]); + + CYRF_PROGMEM_ConfigSOPCode(WFLY_sop_data); + CYRF_SetTxRxMode(TX_EN); +} + +static uint16_t __attribute__((unused)) WFLY_send_data_packet() +{ + packet_count++; + packet[0] = rx_tx_addr[2]; + packet[1] = rx_tx_addr[3]; + if(packet_count%4==3) + { // Send the hopping frequencies + packet[2]=0x70; // packet type + packet[3]=0x04; // unknown + packet[4]=0x00; // unknown + packet[5]=0x04; // unknown + packet[6]=hopping_frequency[0]; + packet[7]=hopping_frequency[0]; + packet[8]=hopping_frequency[1]; + packet[9]=hopping_frequency[2]; + len=10; // packet[10] contains the checksum + } + else + { // Send sticks packet + uint8_t nbr_ch=option; + if(nbr_ch<4) nbr_ch=9; // 4 channels min can be sent, default to 9 + if(nbr_ch>9) nbr_ch=9; // 9 channels max can be sent + packet[2]=nbr_ch-3; // nbr of channels to follow + packet[3]=packet_count>>2; // packet counter 0x00..0x3F + len=4; + for(uint8_t i=0;i<3;i++) + { // Channels + uint16_t ch = convert_channel_16b_nolimit(i*4+0,151,847); + uint8_t offset=i*5; + packet[3+offset]|=ch<<6; + packet[4+offset]=ch>>2; + len++; + if(--nbr_ch==0) break; + ch = convert_channel_16b_nolimit(i*4+1,151,847); + packet[5+offset]=ch; + packet[6+offset]=ch>>8; + len+=2; + if(--nbr_ch==0) break; + ch = convert_channel_16b_nolimit(i*4+2,151,847); + packet[6+offset]|=ch<<2; + packet[7+offset]=ch>>6; + len++; + if(--nbr_ch==0) break; + ch = convert_channel_16b_nolimit(i*4+3,151,847); + packet[7+offset]|=ch<<4; + packet[8+offset]=ch>>4; + len++; + if(--nbr_ch==0) break; + } + } + + uint8_t sum=0; + for(uint8_t i = 0; i < len; i++) + sum += packet[i]; + packet[len] = sum; + + CYRF_ConfigRFChannel(hopping_frequency[(packet_count)%4]); + CYRF_SetPower(0x08); + CYRF_WriteDataPacketLen(packet, len+1); + + switch(packet_count%4) + { + case 0: + return 1393; + case 1: + return 1330; + case 2: + return 1555; + } + return 1093; // case 3 +} + +uint16_t ReadWFLY() +{ + uint8_t status,len,sum=0,check=0; + uint8_t start; + static uint8_t retry; + + switch(phase) + { + case WFLY_BIND_TX: + CYRF_SetTxRxMode(TX_EN); + CYRF_WriteDataPacketLen(packet, sizeof(WFLY_bind_packet)); + debug("P="); + for(uint8_t i=0;i=10) + { // Good packet received + if(pkt[2]==0x64) + { // Switch to normal mode + BIND_DONE; + phase=WFLY_PREP_DATA; + return 10000; + } + memcpy((void *)packet,(void *)pkt,0x10); // Send back to the RX what we've just received with no modifications + } + phase=WFLY_BIND_TX; + return 200; + } + } + if(status & 0x85 || --retry == 0) + { // RX error or no answer + debugln("Abort"); + CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Enable RX abort + CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x21); // Force end state + CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Disable RX abort + phase=WFLY_BIND_TX; // Retry sending bind packet + } + return 700; + case WFLY_PREP_DATA: + WFLY_cyrf_data_config(); + packet_count=0; + phase++; + case WFLY_DATA: + start=micros(); + while ((uint8_t)((uint8_t)micros()-(uint8_t)start) < 200) + if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00) + break; // Packet transmission complete + return WFLY_send_data_packet(); + } + return 1000; +} + +uint16_t initWFLY() +{ + //Random start channel + uint8_t ch=0x0A+random(0xfefefefe)%0x0E; + if(ch%3==0) + ch++; // remove these channels as they seem to not be working... + rf_ch_num=0x0C+(rx_tx_addr[1]%4)*3; // use the start channels which do not seem to work to send the hopping table instead + + #ifdef WFLY_FORCE_ID // data taken from TX dump + rx_tx_addr[2]=0xBF; // ID + rx_tx_addr[3]=0x13; // ID + ch=0x16; // value seen between 0x0A and 0x17 + rc_ch_num=0x15 // RF channel to send the current hopping table + #endif + + debug("ID:") + for(uint8_t i=0;i<2;i++) + debug(" %02X", rx_tx_addr[2+i]); + debugln(""); + + hopping_frequency[0]=ch; + hopping_frequency[1]=ch+0x1E; + hopping_frequency[2]=ch+0x2D; + hopping_frequency[3]=rf_ch_num; // RF channel used to send the current hopping table + + debug("RF Channels:") + for(uint8_t i=0;i