/* ************************** * By Midelic on RCGroups * ************************** 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(FRSKYX_CC2500_INO) #include "iface_cc2500.h" uint8_t chanskip; uint8_t calData[48][3]; uint8_t channr; uint8_t pass_ = 1 ; uint8_t counter_rst; uint8_t ctr; uint8_t FS_flag=0; // uint8_t ptr[4]={0x01,0x12,0x23,0x30}; //uint8_t ptr[4]={0x00,0x11,0x22,0x33}; const PROGMEM uint8_t hop_data[]={ 0x02, 0xD4, 0xBB, 0xA2, 0x89, 0x70, 0x57, 0x3E, 0x25, 0x0C, 0xDE, 0xC5, 0xAC, 0x93, 0x7A, 0x61, 0x48, 0x2F, 0x16, 0xE8, 0xCF, 0xB6, 0x9D, 0x84, 0x6B, 0x52, 0x39, 0x20, 0x07, 0xD9, 0xC0, 0xA7, 0x8E, 0x75, 0x5C, 0x43, 0x2A, 0x11, 0xE3, 0xCA, 0xB1, 0x98, 0x7F, 0x66, 0x4D, 0x34, 0x1B, 0x00, 0x1D, 0x03 }; static uint8_t __attribute__((unused)) hop(uint8_t byte) { return pgm_read_byte_near(&hop_data[byte]); } static void __attribute__((unused)) set_start(uint8_t ch ) { cc2500_strobe(CC2500_SIDLE); cc2500_writeReg(CC2500_23_FSCAL3, calData[ch][0]); cc2500_writeReg(CC2500_24_FSCAL2, calData[ch][1]); cc2500_writeReg(CC2500_25_FSCAL1, calData[ch][2]); cc2500_writeReg(CC2500_0A_CHANNR, ch==47?0:pgm_read_word(&hop_data[ch])); } static void __attribute__((unused)) frskyX_init() { CC2500_Reset(); for(uint8_t i=0;i<36;i++) { uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]); uint8_t val=pgm_read_byte_near(&cc2500_conf[i][1]); if(reg==CC2500_06_PKTLEN) val=0x1E; else if(reg==CC2500_08_PKTCTRL0) val=0x01; else if(reg==CC2500_0B_FSCTRL1) val=0x0A; else if(reg==CC2500_10_MDMCFG4) val=0x7B; else if(reg==CC2500_11_MDMCFG3) val=0x61; else if(reg==CC2500_12_MDMCFG2) val=0x13; else if(reg==CC2500_15_DEVIATN) val=0x51; cc2500_writeReg(reg,val); } cc2500_writeReg(CC2500_07_PKTCTRL1, 0x04); cc2500_writeReg(CC2500_0C_FSCTRL0, option); cc2500_strobe(CC2500_SIDLE); // for(uint8_t c=0;c < 47;c++){//calibrate hop channels cc2500_strobe(CC2500_SIDLE); cc2500_writeReg(CC2500_0A_CHANNR,pgm_read_word(&hop_data[c])); cc2500_strobe(CC2500_SCAL); delayMicroseconds(900);// calData[c][0] = cc2500_readReg(CC2500_23_FSCAL3); calData[c][1] = cc2500_readReg(CC2500_24_FSCAL2); calData[c][2] = cc2500_readReg(CC2500_25_FSCAL1); } cc2500_strobe(CC2500_SIDLE); cc2500_writeReg(CC2500_0A_CHANNR,0x00); cc2500_strobe(CC2500_SCAL); delayMicroseconds(900); calData[47][0] = cc2500_readReg(CC2500_23_FSCAL3); calData[47][1] = cc2500_readReg(CC2500_24_FSCAL2); calData[47][2] = cc2500_readReg(CC2500_25_FSCAL1); //#######END INIT######## } static void __attribute__((unused)) initialize_data(uint8_t adr) { cc2500_writeReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack cc2500_writeReg(CC2500_18_MCSM0, 0x8); cc2500_writeReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]); cc2500_writeReg(CC2500_07_PKTCTRL1,0x05); } static uint8_t __attribute__((unused)) crc_Byte( uint8_t byte ) { crc = (crc<<8) ^ pgm_read_word(&CRCTable[((uint8_t)(crc>>8) ^ byte) & 0xFF]); return byte; } static uint16_t __attribute__((unused)) scaleForPXX( uint8_t i ) { //mapped 860,2140(125%) range to 64,1984(PXX values); return (uint16_t)(((Servo_data[i]-PPM_MIN)*3)>>1)+64; } static void __attribute__((unused)) frskyX_build_bind_packet() { crc=0; packet[0] = 0x1D; packet[1] = 0x03; packet[2] = 0x01; // packet[3] = crc_Byte(rx_tx_addr[3]); packet[4] = crc_Byte(rx_tx_addr[2]); int idx = ((state -FRSKY_BIND) % 10) * 5; packet[5] = crc_Byte(idx); packet[6] = crc_Byte(pgm_read_word(&hop_data[idx++])); packet[7] = crc_Byte(pgm_read_word(&hop_data[idx++])); packet[8] = crc_Byte(pgm_read_word(&hop_data[idx++])); packet[9] = crc_Byte(pgm_read_word(&hop_data[idx++])); packet[10] = crc_Byte(pgm_read_word(&hop_data[idx++])); packet[11] = crc_Byte(0x02); packet[12] = crc_Byte(RX_num); // for(uint8_t i=13;i<28;i++) packet[i]=crc_Byte(0); // packet[28]=highByte(crc); packet[29]=lowByte(crc); // } static void __attribute__((unused)) frskyX_data_frame() { //0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12 // uint8_t lpass = pass_ ; uint16_t chan_0 ; uint16_t chan_1 ; uint8_t flag2 = 0; uint8_t startChan = 0; crc = 0; //static uint8_t p = 0; // packet[0] = 0x1D; packet[1] = rx_tx_addr[3]; packet[2] = rx_tx_addr[2]; packet[3] = crc_Byte(0x02); // packet[4] = crc_Byte((ctr<<6)+channr); //*64 packet[5] = crc_Byte(counter_rst); packet[6] = crc_Byte(RX_num); // FLAGS 00 - standard packet //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet //20 - range check packet packet[7] = crc_Byte(FS_flag); packet[8] = crc_Byte(flag2); // if ( lpass & 1 ) startChan += 8 ; for(uint8_t i = 0; i <12 ; i+=3) {//12 bytes chan_0 = scaleForPXX(startChan); if(lpass & 1 ) chan_0+=2048; packet[9+i] = crc_Byte(lowByte(chan_0));//3 bytes*4 startChan++; chan_1 = scaleForPXX(startChan); if(lpass & 1 ) chan_1+= 2048; startChan++; packet[9+i+1]=crc_Byte((((chan_0>>8) & 0x0F)|(chan_1 << 4))); packet[9+i+2]=crc_Byte(chan_1>>4); } //packet[21]=crc_Byte(0x08);//first packet[21]=crc_Byte(0x80);//??? when received first telemetry frame is changed to 0x80 //packet[21]=crc_Byte(ptr[p]);//??? //p=(p+1)%4;//repeating 4 bytes sequence pattern every 4th frame. pass_=lpass+1; for (uint8_t i=22;i<28;i++) packet[i]=crc_Byte(0); packet[28]=highByte(crc); packet[29]=lowByte(crc); } uint16_t ReadFrSkyX() { switch(state) { default: set_start(47); CC2500_SetPower(); cc2500_strobe(CC2500_SFRX); // frskyX_build_bind_packet(); cc2500_strobe(CC2500_SIDLE); cc2500_writeFifo(packet, packet[0]+1); state++; return 9000; case FRSKY_BIND_DONE: initialize_data(0); channr=0; BIND_DONE; state++; break; case FRSKY_DATA1: LED_ON; CC2500_SetTxRxMode(TX_EN); set_start(channr); CC2500_SetPower(); cc2500_strobe(CC2500_SFRX); channr = (channr+chanskip)%47; cc2500_strobe(CC2500_SIDLE); cc2500_writeFifo(packet, packet[0]+1); // frskyX_data_frame(); state++; return 5500; case FRSKY_DATA2: CC2500_SetTxRxMode(RX_EN); cc2500_strobe(CC2500_SIDLE); state++; return 200; case FRSKY_DATA3: cc2500_strobe(CC2500_SRX); state++; return 3000; case FRSKY_DATA4: len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; if (len &&(len>2; //for test*************** //rx_tx_addr[3]=0xB3; //rx_tx_addr[2]=0xFD; //************************ frskyX_init(); // if(IS_AUTOBIND_FLAG_on) { state = FRSKY_BIND; initialize_data(1); } else { state = FRSKY_DATA1; initialize_data(0); } return 10000; } #endif