Fix telemetry FrSkyX protocol

This commit is contained in:
midelic 2017-11-04 17:14:29 +01:00 committed by GitHub
parent 57a78535f2
commit d451af365a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 3098 additions and 2942 deletions

View File

@ -1,292 +1,292 @@
/* ************************** /* **************************
* By Midelic on RCGroups * * By Midelic on RCGroups *
************************** **************************
This project is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful, Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
#if defined(FRSKYX_CC2500_INO) #if defined(FRSKYX_CC2500_INO)
#include "iface_cc2500.h" #include "iface_cc2500.h"
uint8_t chanskip; uint8_t chanskip;
//uint8_t seq_last_sent; //uint8_t seq_last_sent;
//uint8_t seq_last_rcvd; //uint8_t seq_last_rcvd;
uint8_t FrX_send_seq ; uint8_t FrX_send_seq ;
uint8_t FrX_receive_seq ; uint8_t FrX_receive_seq ;
static void __attribute__((unused)) set_start(uint8_t ch ) static void __attribute__((unused)) set_start(uint8_t ch )
{ {
CC2500_Strobe(CC2500_SIDLE); CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]); CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]);
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]); CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
} }
static void __attribute__((unused)) frskyX_init() static void __attribute__((unused)) frskyX_init()
{ {
FRSKY_init_cc2500((sub_protocol&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC FRSKY_init_cc2500((sub_protocol&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC
// //
for(uint8_t c=0;c < 48;c++) for(uint8_t c=0;c < 48;c++)
{//calibrate hop channels {//calibrate hop channels
CC2500_Strobe(CC2500_SIDLE); CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR,hopping_frequency[c]); CC2500_WriteReg(CC2500_0A_CHANNR,hopping_frequency[c]);
CC2500_Strobe(CC2500_SCAL); CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);// delayMicroseconds(900);//
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1); calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
} }
//#######END INIT######## //#######END INIT########
} }
static void __attribute__((unused)) initialize_data(uint8_t adr) static void __attribute__((unused)) initialize_data(uint8_t adr)
{ {
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
CC2500_WriteReg(CC2500_18_MCSM0, 0x8); CC2500_WriteReg(CC2500_18_MCSM0, 0x8);
CC2500_WriteReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]); CC2500_WriteReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]);
CC2500_WriteReg(CC2500_07_PKTCTRL1,0x05); CC2500_WriteReg(CC2500_07_PKTCTRL1,0x05);
} }
//**CRC** //**CRC**
const uint16_t PROGMEM CRC_Short[]={ const uint16_t PROGMEM CRC_Short[]={
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7 }; 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7 };
static uint16_t CRCTable(uint8_t val) static uint16_t CRCTable(uint8_t val)
{ {
uint16_t word ; uint16_t word ;
word = pgm_read_word(&CRC_Short[val&0x0F]) ; word = pgm_read_word(&CRC_Short[val&0x0F]) ;
val /= 16 ; val /= 16 ;
return word ^ (0x1081 * val) ; return word ^ (0x1081 * val) ;
} }
static uint16_t __attribute__((unused)) crc_x(uint8_t *data, uint8_t len) static uint16_t __attribute__((unused)) crc_x(uint8_t *data, uint8_t len)
{ {
uint16_t crc = 0; uint16_t crc = 0;
for(uint8_t i=0; i < len; i++) for(uint8_t i=0; i < len; i++)
crc = (crc<<8) ^ CRCTable((uint8_t)(crc>>8) ^ *data++); crc = (crc<<8) ^ CRCTable((uint8_t)(crc>>8) ^ *data++);
return crc; return crc;
} }
// 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182 // 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182
//64=860,1024=1500,1984=2140//Taranis 125% //64=860,1024=1500,1984=2140//Taranis 125%
static uint16_t __attribute__((unused)) scaleForPXX( uint8_t i ) static uint16_t __attribute__((unused)) scaleForPXX( uint8_t i )
{ //mapped 860,2140(125%) range to 64,1984(PXX values); { //mapped 860,2140(125%) range to 64,1984(PXX values);
return (uint16_t)(((Servo_data[i]-servo_min_125)*3)>>1)+64; return (uint16_t)(((Servo_data[i]-servo_min_125)*3)>>1)+64;
} }
static void __attribute__((unused)) frskyX_build_bind_packet() static void __attribute__((unused)) frskyX_build_bind_packet()
{ {
packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC
packet[1] = 0x03; packet[1] = 0x03;
packet[2] = 0x01; packet[2] = 0x01;
// //
packet[3] = rx_tx_addr[3]; packet[3] = rx_tx_addr[3];
packet[4] = rx_tx_addr[2]; packet[4] = rx_tx_addr[2];
int idx = ((state -FRSKY_BIND) % 10) * 5; int idx = ((state -FRSKY_BIND) % 10) * 5;
packet[5] = idx; packet[5] = idx;
packet[6] = hopping_frequency[idx++]; packet[6] = hopping_frequency[idx++];
packet[7] = hopping_frequency[idx++]; packet[7] = hopping_frequency[idx++];
packet[8] = hopping_frequency[idx++]; packet[8] = hopping_frequency[idx++];
packet[9] = hopping_frequency[idx++]; packet[9] = hopping_frequency[idx++];
packet[10] = hopping_frequency[idx++]; packet[10] = hopping_frequency[idx++];
packet[11] = 0x02; packet[11] = 0x02;
packet[12] = RX_num; packet[12] = RX_num;
// //
uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ; uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ;
memset(&packet[13], 0, limit - 13); memset(&packet[13], 0, limit - 13);
uint16_t lcrc = crc_x(&packet[3], limit-3); uint16_t lcrc = crc_x(&packet[3], limit-3);
// //
packet[limit++] = lcrc >> 8; packet[limit++] = lcrc >> 8;
packet[limit] = lcrc; packet[limit] = lcrc;
// //
} }
static void __attribute__((unused)) frskyX_data_frame() 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 //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
// //
static uint8_t lpass; static uint8_t lpass;
uint16_t chan_0 ; uint16_t chan_0 ;
uint16_t chan_1 ; uint16_t chan_1 ;
uint8_t startChan = 0; uint8_t startChan = 0;
// //
packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC
packet[1] = rx_tx_addr[3]; packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2]; packet[2] = rx_tx_addr[2];
packet[3] = 0x02; packet[3] = 0x02;
// //
packet[4] = (chanskip<<6)|hopping_frequency_no; packet[4] = (chanskip<<6)|hopping_frequency_no;
packet[5] = chanskip>>2; packet[5] = chanskip>>2;
packet[6] = RX_num; packet[6] = RX_num;
//packet[7] = FLAGS 00 - standard packet //packet[7] = FLAGS 00 - standard packet
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
//20 - range check packet //20 - range check packet
packet[7] = 0; packet[7] = 0;
packet[8] = 0; packet[8] = 0;
// //
if ( lpass & 1 ) if ( lpass & 1 )
startChan += 8 ; startChan += 8 ;
for(uint8_t i = 0; i <12 ; i+=3) for(uint8_t i = 0; i <12 ; i+=3)
{//12 bytes {//12 bytes
chan_0 = scaleForPXX(startChan); chan_0 = scaleForPXX(startChan);
if(lpass & 1 ) if(lpass & 1 )
chan_0+=2048; chan_0+=2048;
startChan+=1; startChan+=1;
// //
chan_1 = scaleForPXX(startChan); chan_1 = scaleForPXX(startChan);
if(lpass & 1 ) if(lpass & 1 )
chan_1+= 2048; chan_1+= 2048;
startChan+=1; startChan+=1;
// //
packet[9+i] = lowByte(chan_0);//3 bytes*4 packet[9+i] = lowByte(chan_0);//3 bytes*4
packet[9+i+1]=(((chan_0>>8) & 0x0F)|(chan_1 << 4)); packet[9+i+1]=(((chan_0>>8) & 0x0F)|(chan_1 << 4));
packet[9+i+2]=chan_1>>4; packet[9+i+2]=chan_1>>4;
} }
packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start
if(sub_protocol & 1 )// in X8 mode send only 8ch every 9ms if(sub_protocol & 1 )// in X8 mode send only 8ch every 9ms
lpass = 0 ; lpass = 0 ;
else else
lpass += 1 ; lpass += 1 ;
uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ; uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ;
for (uint8_t i=22;i<limit;i++) for (uint8_t i=22;i<limit;i++)
packet[i]=0; packet[i]=0;
uint16_t lcrc = crc_x(&packet[3], limit-3); uint16_t lcrc = crc_x(&packet[3], limit-3);
packet[limit++]=lcrc>>8;//high byte packet[limit++]=lcrc>>8;//high byte
packet[limit]=lcrc;//low byte packet[limit]=lcrc;//low byte
} }
uint16_t ReadFrSkyX() uint16_t ReadFrSkyX()
{ {
switch(state) switch(state)
{ {
default: default:
set_start(47); set_start(47);
CC2500_SetPower(); CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX); CC2500_Strobe(CC2500_SFRX);
// //
frskyX_build_bind_packet(); frskyX_build_bind_packet();
CC2500_Strobe(CC2500_SIDLE); CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteData(packet, packet[0]+1); CC2500_WriteData(packet, packet[0]+1);
if(IS_BIND_DONE_on) if(IS_BIND_DONE_on)
state = FRSKY_BIND_DONE; state = FRSKY_BIND_DONE;
else else
state++; state++;
return 9000; return 9000;
case FRSKY_BIND_DONE: case FRSKY_BIND_DONE:
initialize_data(0); initialize_data(0);
hopping_frequency_no=0; hopping_frequency_no=0;
BIND_DONE; BIND_DONE;
state++; state++;
break; break;
case FRSKY_DATA1: case FRSKY_DATA1:
if ( prev_option != option ) if ( prev_option != option )
{ {
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
prev_option = option ; prev_option = option ;
} }
CC2500_SetTxRxMode(TX_EN); CC2500_SetTxRxMode(TX_EN);
set_start(hopping_frequency_no); set_start(hopping_frequency_no);
CC2500_SetPower(); CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX); CC2500_Strobe(CC2500_SFRX);
hopping_frequency_no = (hopping_frequency_no+chanskip)%47; hopping_frequency_no = (hopping_frequency_no+chanskip)%47;
CC2500_Strobe(CC2500_SIDLE); CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteData(packet, packet[0]+1); CC2500_WriteData(packet, packet[0]+1);
// //
// frskyX_data_frame(); // frskyX_data_frame();
state++; state++;
return 5500; return 5200;
case FRSKY_DATA2: case FRSKY_DATA2:
CC2500_SetTxRxMode(RX_EN); CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SIDLE); CC2500_Strobe(CC2500_SIDLE);
state++; state++;
return 200; return 200;
case FRSKY_DATA3: case FRSKY_DATA3:
CC2500_Strobe(CC2500_SRX); CC2500_Strobe(CC2500_SRX);
state++; state++;
return 2800; return 3100;
case FRSKY_DATA4: case FRSKY_DATA4:
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && (len<=(0x0E + 3))) //Telemetry frame is 17 if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
{ {
packet_count=0; packet_count=0;
CC2500_ReadData(pkt, len); CC2500_ReadData(pkt, len);
#if defined TELEMETRY #if defined TELEMETRY
frsky_check_telemetry(pkt,len); //check if valid telemetry packets frsky_check_telemetry(pkt,len); //check if valid telemetry packets
//parse telemetry packets here //parse telemetry packets here
//The same telemetry function used by FrSky(D8). //The same telemetry function used by FrSky(D8).
#endif #endif
} }
else else
{ {
packet_count++; packet_count++;
// restart sequence on missed packet - might need count or timeout instead of one missed // restart sequence on missed packet - might need count or timeout instead of one missed
if(packet_count>100) if(packet_count>100)
{//~1sec {//~1sec
// seq_last_sent = 0; // seq_last_sent = 0;
// seq_last_rcvd = 8; // seq_last_rcvd = 8;
FrX_send_seq = 0x08 ; FrX_send_seq = 0x08 ;
FrX_receive_seq = 0 ; // FrX_receive_seq = 0 ;
packet_count=0; packet_count=0;
#if defined TELEMETRY #if defined TELEMETRY
telemetry_lost=1; telemetry_lost=1;
#endif #endif
} }
CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO
} }
frskyX_data_frame(); frskyX_data_frame();
if ( FrX_send_seq != 0x08 ) if ( FrX_send_seq != 0x08 )
{ {
FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ; FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ;
} }
state = FRSKY_DATA1; state = FRSKY_DATA1;
return 500; return 500;
} }
return 1; return 1;
} }
uint16_t initFrSkyX() uint16_t initFrSkyX()
{ {
set_rx_tx_addr(MProtocol_id_master); set_rx_tx_addr(MProtocol_id_master);
Frsky_init_hop(); Frsky_init_hop();
packet_count=0; packet_count=0;
while(!chanskip) while(!chanskip)
chanskip=random(0xfefefefe)%47; chanskip=random(0xfefefefe)%47;
//for test*************** //for test***************
//rx_tx_addr[3]=0xB3; //rx_tx_addr[3]=0xB3;
//rx_tx_addr[2]=0xFD; //rx_tx_addr[2]=0xFD;
//************************ //************************
frskyX_init(); frskyX_init();
// //
if(IS_AUTOBIND_FLAG_on) if(IS_AUTOBIND_FLAG_on)
{ {
state = FRSKY_BIND; state = FRSKY_BIND;
initialize_data(1); initialize_data(1);
} }
else else
{ {
state = FRSKY_DATA1; state = FRSKY_DATA1;
initialize_data(0); initialize_data(0);
} }
// seq_last_sent = 0; // seq_last_sent = 0;
// seq_last_rcvd = 8; // seq_last_rcvd = 8;
uint8_t FrX_send_seq = 0x08 ; FrX_send_seq = 0x08 ;
uint8_t FrX_receive_seq = 0 ; FrX_receive_seq = 0 ;
return 10000; return 10000;
} }
#endif #endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff