/* 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(MLINK_CYRF6936_INO) #include "iface_cyrf6936.h" #undef MLINK_HUB_TELEMETRY #define MLINK_FORCE_ID #define MLINK_BIND_COUNT 696 // around 20s #define MLINK_NUM_FREQ 78 #define MLINK_BIND_CHANNEL 0x01 #define MLINK_PACKET_SIZE 8 enum { MLINK_BIND_TX=0, MLINK_BIND_PREP_RX, MLINK_BIND_RX, MLINK_PREP_DATA, MLINK_SEND1, MLINK_CHECK1, MLINK_SEND2, MLINK_CHECK2, MLINK_SEND3, MLINK_CHECK3, MLINK_RX, MLINK_CHECK4, }; uint8_t MLINK_Data_Code[16], MLINK_CRC_Init, MLINK_Unk_6_2; const uint8_t PROGMEM MLINK_init_vals[][2] = { //Init from dump { CYRF_01_TX_LENGTH, 0x08 }, // Length of packet { CYRF_02_TX_CTRL, 0x40 }, // Clear TX Buffer { CYRF_03_TX_CFG, 0x3C }, //0x3E in normal mode, 0x3C in bind mode: SDR 64 chip codes (=8 bytes data code used) { CYRF_05_RX_CTRL, 0x00 }, { CYRF_06_RX_CFG, 0x93 }, // AGC enabled, overwrite enable, valid flag enable { CYRF_0B_PWR_CTRL, 0x00 }, //{ CYRF_0C_XTAL_CTRL, 0x00 }, // Set to GPIO on reset //{ CYRF_0D_IO_CFG, 0x00 }, // Set to GPIO on reset //{ CYRF_0E_GPIO_CTRL, 0x00 }, // Set by the CYRF_SetTxRxMode function { CYRF_0F_XACT_CFG, 0x04 }, // end state idle { CYRF_10_FRAMING_CFG, 0x00 }, // SOP disabled { CYRF_11_DATA32_THOLD, 0x05 }, // not used??? { CYRF_12_DATA64_THOLD, 0x0F }, // 64 Chip Data PN Code Correlator Threshold { CYRF_14_EOP_CTRL, 0x05 }, // 5 consecutive noncorrelations symbol for EOP { CYRF_15_CRC_SEED_LSB, 0x00 }, // not used??? { CYRF_16_CRC_SEED_MSB, 0x00 }, // not used??? { CYRF_1B_TX_OFFSET_LSB,0x00 }, { CYRF_1C_TX_OFFSET_MSB,0x00 }, { CYRF_1D_MODE_OVERRIDE,0x00 }, { CYRF_1E_RX_OVERRIDE, 0x14 }, // RX CRC16 is disabled and Force Receive Data Rate { CYRF_1F_TX_OVERRIDE, 0x04 }, // TX CRC16 is disabled { CYRF_26_XTAL_CFG, 0x08 }, { CYRF_29_RX_ABORT, 0x00 }, { CYRF_32_AUTO_CAL_TIME,0x3C }, { CYRF_35_AUTOCAL_OFFSET,0x14 }, { CYRF_39_ANALOG_CTRL, 0x03 }, // Receive invert and all slow }; static void __attribute__((unused)) MLINK_cyrf_config() { for(uint8_t i = 0; i < sizeof(MLINK_init_vals) / 2; i++) CYRF_WriteRegister(pgm_read_byte_near(&MLINK_init_vals[i][0]), pgm_read_byte_near(&MLINK_init_vals[i][1])); CYRF_WritePreamble(0x333304); CYRF_SetTxRxMode(TX_EN); } static void __attribute__((unused)) MLINK_send_bind_data_packet() { uint8_t p_c=packet_count>>1; memset(packet, p_c<0x16?0x00:0xFF, MLINK_PACKET_SIZE-1); packet[0]=0x0F; // bind packet[1]=p_c; switch(p_c) { case 0x00: packet[2]=0x40; //unknown but seems constant packet[4]=0x01; //unknown but seems constant packet[5]=0x03; //unknown but seems constant packet[6]=0xE3; //unknown but seems constant break; case 0x05: packet[6]=MLINK_CRC_Init; //CRC init value break; case 0x06: packet[2]=MLINK_Unk_6_2; //unknown and different //Start of hopping frequencies for(uint8_t i=0;i<4;i++) packet[i+3]=hopping_frequency[i]; break; case 0x15: packet[6]=0x51; //unknown but seems constant break; case 0x16: packet[2]=0x51; //unknown but seems constant packet[3]=0xEC; //unknown but seems constant packet[4]=0x05; //unknown but seems constant break; case 0x1A: packet[1]=0xFF; memset(&packet[2],0x00,5); break; } if(p_c>=0x01 && p_c<=0x04) {//DATA_CODE uint8_t p_c_5=(p_c-1)*5; for(uint8_t i=0;i<5;i++) if(i+p_c_5<16) packet[i+2]=MLINK_Data_Code[i+p_c_5]; } else if(p_c>=0x07 && p_c<=0x15) {//Hopping frequencies uint8_t p_c_5=5*(p_c-6)-1; for(uint8_t i=0;i<5;i++) if(i+p_c_50x19) { packet[1]=0xFF; memset(&packet[2], 0x00, MLINK_PACKET_SIZE-3); } //Calculate CRC crc8=0xFF; // Init = 0xFF for(uint8_t i=0;i>8; packet[i*2+2]=tmp; } //Calculate CRC crc8=bit_reverse(hopping_frequency_no + MLINK_CRC_Init); // Init = relected freq index + offset for(uint8_t i=0;i 0x19*2) { if(packet[0] == 0x8F) packet_count++; else if(packet[0] == 0x9F) packet_count=0x80; // End bind else packet_count=0; // Restart bind... } } } } else packet_count=0; CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Enable RX abort CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24); // Force end state CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Disable RX abort phase=MLINK_BIND_TX; // Retry sending bind packet CYRF_SetTxRxMode(TX_EN); // Transmit mode if(packet_count) return 18136; case MLINK_BIND_TX: if(--bind_counter==0 || packet_count>=0x1B*2) { // Switch to normal mode BIND_DONE; phase=MLINK_PREP_DATA; return 22720; } MLINK_send_bind_data_packet(); if(packet_count == 0 || packet_count > 0x19*2) { phase++; // MLINK_BIND_PREP_RX return 4700; // Original is 4900 } packet_count++; if(packet_count&1) return 6000; return 22720; case MLINK_BIND_PREP_RX: start=micros(); while ((uint8_t)((uint8_t)micros()-(uint8_t)start) < 200) // Wait max 200µs for TX to finish if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00) break; // Packet transmission complete CYRF_SetTxRxMode(RX_EN); // Receive mode CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x82); // Prepare to receive phase++; //MLINK_BIND_RX return 28712-4700; case MLINK_PREP_DATA: CYRF_ConfigDataCode(MLINK_Data_Code,16); MLINK_CRC_Init += 0xED; hopping_frequency_no = 0x00; CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]); CYRF_SetPower(0x38); #ifdef MLINK_HUB_TELEMETRY packet_count = 0; telemetry_lost = 1; #endif phase++; case MLINK_SEND1: MLINK_build_data_packet(); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40); CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, packet, MLINK_PACKET_SIZE); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x82); phase++; return 4880; case MLINK_CHECK1: status=CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); //debugln("C1:%02X",status); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x00); phase++; return 1111; case MLINK_SEND2: MLINK_build_data_packet(); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40); CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, packet, MLINK_PACKET_SIZE); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x82); phase++; return 4617; case MLINK_CHECK2: status=CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); //debugln("C2:%02X",status); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x00); phase++; if(hopping_frequency_no%5==0) return 1017; return 1422; case MLINK_SEND3: MLINK_build_data_packet(); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40); CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, packet, MLINK_PACKET_SIZE); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x82); phase++; return 4611; case MLINK_CHECK3: status=CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); //debugln("C3:%02X",status); CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x00); //check RX but there is nothing to check... status=CYRF_ReadRegister(CYRF_05_RX_CTRL); //debugln("CTRL:%02X",status); len=CYRF_ReadRegister(CYRF_09_RX_COUNT); //debugln("L=%02X",len) if( len && len<=8 ) CYRF_ReadDataPacketLen(packet, len*2); CYRF_WriteRegister(CYRF_05_RX_CTRL,0x00); //Next channel hopping_frequency_no++; if(hopping_frequency_no>=MLINK_NUM_FREQ) hopping_frequency_no=0; CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]); //Receive telemetry if(hopping_frequency_no%5==0) {//Receive telemetry CYRF_SetTxRxMode(RX_EN); // Receive mode CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x82); // Prepare to receive phase++; //MLINK_RX return 8038; } else CYRF_SetPower(0x38); phase=MLINK_SEND1; return 4470; case MLINK_RX: #ifdef MLINK_HUB_TELEMETRY //TX LQI calculation packet_count++; if(packet_count>=100) { packet_count=0; TX_LQI=telemetry_counter; if(telemetry_counter==0) telemetry_lost = 1; telemetry_counter = 0; } #endif status=CYRF_ReadRegister(CYRF_05_RX_CTRL);//CYRF_07_RX_IRQ_STATUS); debug("T(%02X):",status); //status=CYRF_ReadRegister(CYRF_05_RX_CTRL); //if( (status&0x80) == 0 ) {//Packet received len=CYRF_ReadRegister(CYRF_09_RX_COUNT); debug("(%X)",len) if( len && len<=8 ) { CYRF_ReadDataPacketLen(packet_in, len*2); #ifdef MLINK_HUB_TELEMETRY if(len==8) { //Check CRC crc8=bit_reverse(MLINK_CRC_Init); for(uint8_t i=0;i