/* This project is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Multiprotocol is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. */ #if defined(E129_CYRF6936_INO) #include "iface_rf2500.h" //#define E129_FORCE_ID //#define C186_FORCE_ID #define E129_BIND_CH 0x2D //45 #define E129_PAYLOAD_SIZE 16 #define C186_PAYLOAD_SIZE 19 static void __attribute__((unused)) E129_build_data_packet() { //Build the packet memset(packet,0,packet_length); packet[ 0] = packet_length - 1; // Packet length if(IS_BIND_IN_PROGRESS) { packet[ 1] = 0xA4; packet[ 2] = bit_reverse(rx_tx_addr[2]); packet[ 3] = bit_reverse(rx_tx_addr[3]); packet[ 4] = bit_reverse(rx_tx_addr[0]); packet[ 5] = bit_reverse(rx_tx_addr[1]); for(uint8_t i=0; i<4; i++) packet[6+i]=hopping_frequency[i]-2; } else { packet[ 1] = 0xA6; // Set to A5 every few packets?? //Flags if(sub_protocol == E129_E129) packet[ 2] = 0xF7; // High rate 0xF7, low 0xF4 else //C186 { packet[ 2] = 0xFA; // High rate 0xFA, medium 0xF7, low 0xF4 packet[13] = bit_reverse(rx_tx_addr[2]); packet[14] = bit_reverse(rx_tx_addr[3]); packet[15] = bit_reverse(rx_tx_addr[0]); packet[16] = bit_reverse(rx_tx_addr[1]); } packet[ 3] = GET_FLAG(CH10_SW, 0x40) // C159: loop flight 0x40 | GET_FLAG(CH11_SW, 0x08); // C129V2: flip //Other flags seen in packet[3] // Flag 0x04 is set on some helis (C159/C190) // E129 Mode: short press=0x20->0x00->0x20->..., long press=0x10->0x30->0x10->... => C186 throttle trim is doing the same:up=short press and down=long press packet[ 4] = GET_FLAG(CH5_SW, 0x20) // Take off/Land 0x20 | GET_FLAG(CH6_SW, 0x04) // Emergency stop 0x04 | GET_FLAG(CH12_SW, 0x80); // C190: debug mode->remote THR trim down sets 0x80 //Other flags seen in packet[4] // C190 remote LANDING sets 0x10 // C190 remote THR trim down sets 0x80 //Channels and trims uint16_t val = convert_channel_10b(AILERON,false); uint8_t trim = convert_channel_8b(CH7) & 0xFC; packet[ 5] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8 packet[ 6] = val; // channel (0x000...0x200...0x3FF) val = convert_channel_10b(ELEVATOR,false); trim = convert_channel_8b(CH8) & 0xFC; packet[ 7] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8 packet[ 8] = val; // channel (0x000...0x200...0x3FF) if(packet_count>200) val = convert_channel_10b(THROTTLE,false); else {//Allow bind to complete with throttle not centered packet_count++; val=0x200; } packet[ 9] = (0x1F<<2) | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8 packet[10] = val; // channel (0x000...0x200...0x3FF) val = convert_channel_10b(RUDDER,false); trim = convert_channel_8b(CH9) & 0xFC; packet[11] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8 packet[12] = val; // channel (0x000...0x200...0x3FF) } //Check for(uint8_t i=0;i<packet_length-2;i++) packet[packet_length-2] += packet[i]; if(sub_protocol == E129_C186) packet[packet_length-2] -= 0x80; RF2500_BuildPayload(packet); } uint16_t E129_callback() { //Set RF channel if(phase==0) RF2500_RFChannel(IS_BIND_IN_PROGRESS ? E129_BIND_CH : hopping_frequency[hopping_frequency_no]); //Send packet RF2500_SendPayload(); //E129 sends twice on same channel, not the C186 but there is a bug somewhere if I don't send the packets back to back if(phase==0) { phase++; return 1260; } //Bind if(bind_counter) if(--bind_counter==0) { BIND_DONE; RF2500_SetTXAddr(rx_tx_addr); // 4 bytes of address } //Build packet E129_build_data_packet(); //Set power RF2500_SetPower(); //Hopp hopping_frequency_no++; hopping_frequency_no &= 3; phase=0; if(sub_protocol==E129_E129) return 5200-1260; return 5500-1260; //E129_C186 } void E129_init() { BIND_IN_PROGRESS; // Autobind protocol bind_counter = 384; // ~2sec //RF2500 emu init packet_length = sub_protocol == E129_E129?E129_PAYLOAD_SIZE:C186_PAYLOAD_SIZE; RF2500_Init(packet_length, true); // 16/19 bytes, Scrambled //Freq hopping calc_fh_channels(4); for(uint8_t i=0; i<4; i++) if(hopping_frequency[i]==E129_BIND_CH) hopping_frequency[i]++; #ifdef E129_FORCE_ID rx_tx_addr[0]=0xC1; rx_tx_addr[1]=0x22; rx_tx_addr[2]=0x05; rx_tx_addr[3]=0xA3; hopping_frequency[0]=0x3C; //60 hopping_frequency[1]=0x49; //73 hopping_frequency[2]=0x4B; //75 hopping_frequency[3]=0x41; //65 #endif #ifdef C186_FORCE_ID rx_tx_addr[0]=0x91; rx_tx_addr[1]=0x02; rx_tx_addr[2]=0x5D; rx_tx_addr[3]=0x33; hopping_frequency[0]=0x44 + 2; hopping_frequency[1]=0x41 + 2; hopping_frequency[2]=0x43 + 2; hopping_frequency[3]=0x49 + 2; #endif RF2500_SetTXAddr((uint8_t*)"\xE2\x32\xE0\xC8"); // 4 bytes of bind address E129_build_data_packet(); hopping_frequency_no=0; packet_count=0; phase=0; } #endif