Added FrSkyX protocol, Added MT99xx YZ sub protocol, Ram usage optimization

This commit is contained in:
pascallanger 2016-02-05 17:27:51 +01:00
parent c5b1e73312
commit b393d2666d
10 changed files with 794 additions and 292 deletions

View File

@ -42,8 +42,7 @@ enum {
DSM2_CH2_READ_B = BIND_COUNT1 + 10, DSM2_CH2_READ_B = BIND_COUNT1 + 10,
}; };
const uint8_t PROGMEM pncodes[5][9][8] = {
const uint8_t pncodes[5][9][8] = {
/* Note these are in order transmitted (LSB 1st) */ /* Note these are in order transmitted (LSB 1st) */
{ /* Row 0 */ { /* Row 0 */
/* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8}, /* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8},
@ -102,6 +101,12 @@ const uint8_t pncodes[5][9][8] = {
}, },
}; };
static void __attribute__((unused)) read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
{
for(uint8_t i=0;i<len;i++)
buf[i]=pgm_read_byte_near( &pncodes[row][col][i] );
}
// //
uint8_t chidx; uint8_t chidx;
uint8_t sop_col; uint8_t sop_col;
@ -109,8 +114,6 @@ uint8_t data_col;
uint16_t cyrf_state; uint16_t cyrf_state;
uint8_t crcidx; uint8_t crcidx;
uint8_t binding; uint8_t binding;
uint16_t crc;
/* /*
#ifdef USE_FIXED_MFGID #ifdef USE_FIXED_MFGID
const uint8_t cyrfmfg_id[6] = {0x5e, 0x28, 0xa3, 0x1b, 0x00, 0x00}; //dx8 const uint8_t cyrfmfg_id[6] = {0x5e, 0x28, 0xa3, 0x1b, 0x00, 0x00}; //dx8
@ -309,17 +312,20 @@ static void __attribute__((unused)) cyrf_config()
static void __attribute__((unused)) initialize_bind_state() static void __attribute__((unused)) initialize_bind_state()
{ {
const uint8_t pn_bind[] = { 0xc6,0x94,0x22,0xfe,0x48,0xe6,0x57,0x4e }; uint8_t code[32];
uint8_t data_code[32];
CYRF_ConfigRFChannel(BIND_CHANNEL); //This seems to be random? CYRF_ConfigRFChannel(BIND_CHANNEL); //This seems to be random?
uint8_t pn_row = get_pn_row(BIND_CHANNEL); uint8_t pn_row = get_pn_row(BIND_CHANNEL);
//printf("Ch: %d Row: %d SOP: %d Data: %d\n", BIND_CHANNEL, pn_row, sop_col, data_col); //printf("Ch: %d Row: %d SOP: %d Data: %d\n", BIND_CHANNEL, pn_row, sop_col, data_col);
CYRF_ConfigCRCSeed(crc); CYRF_ConfigCRCSeed(crc);
CYRF_ConfigSOPCode(pncodes[pn_row][sop_col]);
memcpy(data_code, pncodes[pn_row][data_col], 16); read_code(code,pn_row,sop_col,8);
memcpy(data_code + 16, pncodes[0][8], 8); CYRF_ConfigSOPCode(code);
memcpy(data_code + 24, pn_bind, 8); read_code(code,pn_row,data_col,16);
CYRF_ConfigDataCode(data_code, 32); read_code(code+16,0,8,8);
memcpy(code + 24, "\xc6\x94\x22\xfe\x48\xe6\x57\x4e", 8);
CYRF_ConfigDataCode(code, 32);
build_bind_packet(); build_bind_packet();
} }
@ -349,12 +355,17 @@ static void __attribute__((unused)) cyrf_configdata()
static void __attribute__((unused)) set_sop_data_crc() static void __attribute__((unused)) set_sop_data_crc()
{ {
uint8_t code[16];
uint8_t pn_row = get_pn_row(hopping_frequency[chidx]); uint8_t pn_row = get_pn_row(hopping_frequency[chidx]);
//printf("Ch: %d Row: %d SOP: %d Data: %d\n", ch[chidx], pn_row, sop_col, data_col); //printf("Ch: %d Row: %d SOP: %d Data: %d\n", ch[chidx], pn_row, sop_col, data_col);
CYRF_ConfigRFChannel(hopping_frequency[chidx]); CYRF_ConfigRFChannel(hopping_frequency[chidx]);
CYRF_ConfigCRCSeed(crcidx ? ~crc : crc); CYRF_ConfigCRCSeed(crcidx ? ~crc : crc);
CYRF_ConfigSOPCode(pncodes[pn_row][sop_col]);
CYRF_ConfigDataCode(pncodes[pn_row][data_col], 16); read_code(code,pn_row,sop_col,8);
CYRF_ConfigSOPCode(code);
read_code(code,pn_row,data_col,16);
CYRF_ConfigDataCode(code, 16);
if(sub_protocol == DSMX) if(sub_protocol == DSMX)
chidx = (chidx + 1) % 23; chidx = (chidx + 1) % 23;
else else

View File

@ -1,4 +1,7 @@
/*
/* **************************
* 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
@ -11,11 +14,302 @@
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 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
};
uint8_t hop(uint8_t byte)
{
return pgm_read_byte_near(&hop_data[byte]);
}
uint16_t initFrSkyX()
{
while(!chanskip)
{
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
chanskip=random(0xfefefefe)%47;
}
while((chanskip-ctr)%4)
ctr=(ctr+1)%4;
counter_rst=(chanskip-ctr)>>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;
}
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<MAX_PKT))
{
cc2500_readFifo(pkt, len);
#if defined TELEMETRY
frsky_check_telemetry(pkt,len); //check if valid telemetry packets
//parse telemetry packets here
//The same telemetry function used by FrSky(D8).
#endif
}
state = FRSKY_DATA1;
return 300;
}
return 1;
}
void 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]));
}
void frskyX_init()
{
CC2500_Reset();
cc2500_writeReg(CC2500_02_IOCFG0, 0x06);
cc2500_writeReg(CC2500_00_IOCFG2, 0x06);
cc2500_writeReg(CC2500_17_MCSM1, 0x0C);
cc2500_writeReg(CC2500_18_MCSM0, 0x18);
cc2500_writeReg(CC2500_06_PKTLEN, 0x1E);
cc2500_writeReg(CC2500_07_PKTCTRL1, 0x04);
cc2500_writeReg(CC2500_08_PKTCTRL0, 0x01);
cc2500_writeReg(CC2500_3E_PATABLE, 0xff);
cc2500_writeReg(CC2500_0B_FSCTRL1, 0x0A);
cc2500_writeReg(CC2500_0C_FSCTRL0, 0x00);
cc2500_writeReg(CC2500_0D_FREQ2, 0x5c);
cc2500_writeReg(CC2500_0E_FREQ1, 0x76);
cc2500_writeReg(CC2500_0F_FREQ0, 0x27);
cc2500_writeReg(CC2500_10_MDMCFG4, 0x7B);
cc2500_writeReg(CC2500_11_MDMCFG3, 0x61);
cc2500_writeReg(CC2500_12_MDMCFG2, 0x13);
cc2500_writeReg(CC2500_13_MDMCFG1, 0x23);
cc2500_writeReg(CC2500_14_MDMCFG0, 0x7a);
cc2500_writeReg(CC2500_15_DEVIATN, 0x51);
cc2500_writeReg(CC2500_19_FOCCFG, 0x16);
cc2500_writeReg(CC2500_1A_BSCFG, 0x6c);
cc2500_writeReg(CC2500_1B_AGCCTRL2,0x43);
cc2500_writeReg(CC2500_1C_AGCCTRL1,0x40);
cc2500_writeReg(CC2500_1D_AGCCTRL0,0x91);
cc2500_writeReg(CC2500_21_FREND1, 0x56);
cc2500_writeReg(CC2500_22_FREND0, 0x10);
cc2500_writeReg(CC2500_23_FSCAL3, 0xa9);
cc2500_writeReg(CC2500_24_FSCAL2, 0x0A);
cc2500_writeReg(CC2500_25_FSCAL1, 0x00);
cc2500_writeReg(CC2500_26_FSCAL0, 0x11);
cc2500_writeReg(CC2500_29_FSTEST, 0x59);
cc2500_writeReg(CC2500_2C_TEST2, 0x88);
cc2500_writeReg(CC2500_2D_TEST1, 0x31);
cc2500_writeReg(CC2500_2E_TEST0, 0x0B);
cc2500_writeReg(CC2500_03_FIFOTHR, 0x07);
cc2500_writeReg(CC2500_09_ADDR, 0x00);
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########
}
void 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);
}
void 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);
//
}
void 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 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;
}
uint8_t crc_Byte( uint8_t byte )
{
crc = (crc<<8) ^ pgm_read_word(&CRCTable[((uint8_t)(crc>>8) ^ byte) & 0xFF]);
return byte;
}
#endif #endif

View File

@ -20,7 +20,6 @@
//##########Variables######## //##########Variables########
//uint32_t state; //uint32_t state;
//uint8_t len; //uint8_t len;
uint8_t telemetry_counter=0;
/* /*
enum { enum {
@ -128,8 +127,6 @@ static void __attribute__((unused)) frsky2way_build_bind_packet()
packet[17] = 0x01; packet[17] = 0x01;
} }
static void __attribute__((unused)) frsky2way_data_frame() static void __attribute__((unused)) frsky2way_data_frame()
{//pachet[4] is telemetry user frame counter(hub) {//pachet[4] is telemetry user frame counter(hub)
//11 d7 2d 22 00 01 c9 c9 ca ca 88 88 ca ca c9 ca 88 88 //11 d7 2d 22 00 01 c9 c9 ca ca 88 88 ca ca c9 ca 88 88
@ -138,7 +135,11 @@ static void __attribute__((unused)) frsky2way_data_frame()
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] = counter;// packet[3] = counter;//
packet[4]=telemetry_counter; #if defined TELEMETRY
packet[4] = telemetry_counter;
#else
packet[4] = 0x00;
#endif
packet[5] = 0x01; packet[5] = 0x01;
// //

View File

@ -37,29 +37,16 @@ enum{
FLAG_MT_FLIP = 0x80, FLAG_MT_FLIP = 0x80,
}; };
enum{
// flags going to ?????? (Yi Zhan i6S)ROLL
BLABLA,
};
enum { enum {
MT99XX_INIT = 0, MT99XX_INIT = 0,
MT99XX_BIND, MT99XX_BIND,
MT99XX_DATA MT99XX_DATA
}; };
static uint8_t __attribute__((unused)) MT99XX_calcChecksum()
{
uint8_t result=checksum_offset;
for(uint8_t i=0; i<8; i++)
result += packet[i];
return result;
}
static void __attribute__((unused)) MT99XX_send_packet() static void __attribute__((unused)) MT99XX_send_packet()
{ {
static const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60}; const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
static const uint8_t mys_byte[] = { const uint8_t mys_byte[] = {
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10 0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10
}; };
@ -71,8 +58,8 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[1] = convert_channel_8b_scale(RUDDER ,0x00,0xE1); // rudder packet[1] = convert_channel_8b_scale(RUDDER ,0x00,0xE1); // rudder
packet[2] = convert_channel_8b_scale(AILERON ,0x00,0xE1); // aileron packet[2] = convert_channel_8b_scale(AILERON ,0x00,0xE1); // aileron
packet[3] = convert_channel_8b_scale(ELEVATOR,0x00,0xE1); // elevator packet[3] = convert_channel_8b_scale(ELEVATOR,0x00,0xE1); // elevator
packet[4] = convert_channel_8b_scale(AUX5,0x00,0x3F); // pitch trim (0x3f-0x20-0x00) packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
packet[5] = convert_channel_8b_scale(AUX6,0x00,0x3F); // roll trim (0x00-0x20-0x3f) packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
packet[6] = GET_FLAG( Servo_AUX1, FLAG_MT_FLIP ) packet[6] = GET_FLAG( Servo_AUX1, FLAG_MT_FLIP )
| GET_FLAG( Servo_AUX3, FLAG_MT_SNAPSHOT ) | GET_FLAG( Servo_AUX3, FLAG_MT_SNAPSHOT )
| GET_FLAG( Servo_AUX4, FLAG_MT_VIDEO ); | GET_FLAG( Servo_AUX4, FLAG_MT_VIDEO );
@ -84,7 +71,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
// low nibble: index in chan list ? // low nibble: index in chan list ?
// high nibble: 0->start from start of list, 1->start from end of list ? // high nibble: 0->start from start of list, 1->start from end of list ?
packet[7] = mys_byte[hopping_frequency_no]; packet[7] = mys_byte[hopping_frequency_no];
packet[8] = MT99XX_calcChecksum(); uint8_t result=checksum_offset;
for(uint8_t i=0; i<8; i++)
result += packet[i];
packet[8] = result;
} }
else else
{ // YZ { // YZ
@ -100,8 +90,12 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet_count=0; packet_count=0;
} }
packet[4] = yz_p4_seq[yz_seq_num]; packet[4] = yz_p4_seq[yz_seq_num];
packet[5] = 0x02; // expert ? (0=unarmed, 1=normal) packet[5] = 0x02 // expert ? (0=unarmed, 1=normal)
packet[6] = 0x80; | GET_FLAG(Servo_AUX4, 0x10) //VIDEO
| GET_FLAG(Servo_AUX1, 0x80) //FLIP
| GET_FLAG(Servo_AUX5, 0x04) //HEADLESS
| GET_FLAG(Servo_AUX3, 0x20); //SNAPSHOT
packet[6] = GET_FLAG(Servo_AUX2, 0x80); //LED
packet[7] = packet[0]; packet[7] = packet[0];
for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++) for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++)
packet[7] += packet[idx]; packet[7] += packet[idx];
@ -138,6 +132,9 @@ static void __attribute__((unused)) MT99XX_init()
else else
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower(); NRF24L01_SetPower();
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP) | (sub_protocol == YZ ? BV(XN297_UNSCRAMBLED):0) );
XN297_SetTXAddr((uint8_t *)"\0xCC\0xCC\0xCC\0xCC\0xCC", 5); XN297_SetTXAddr((uint8_t *)"\0xCC\0xCC\0xCC\0xCC\0xCC", 5);
} }
@ -210,8 +207,8 @@ uint16_t initMT99XX(void)
packet[2] = 0x05; packet[2] = 0x05;
packet[3] = 0x06; packet[3] = 0x06;
} }
packet[4] = rx_tx_addr[0]; // 1th byte for data state tx address packet[4] = rx_tx_addr[0]; // 1st byte for data state tx address
packet[5] = rx_tx_addr[1]; // 2th byte for data state tx address (always 0x00 on Yi Zhan ?) packet[5] = rx_tx_addr[1]; // 2nd byte for data state tx address (always 0x00 on Yi Zhan ?)
packet[6] = 0x00; // 3th byte for data state tx address (always 0x00 ?) packet[6] = 0x00; // 3th byte for data state tx address (always 0x00 ?)
packet[7] = checksum_offset; // checksum offset packet[7] = checksum_offset; // checksum offset
packet[8] = 0xAA; // fixed packet[8] = 0xAA; // fixed

View File

@ -47,7 +47,7 @@ uint8_t Servo_AUX;
// PPM variable // PPM variable
volatile uint16_t PPM_data[NUM_CHN]; volatile uint16_t PPM_data[NUM_CHN];
// NRF variables // Protocol variables
uint8_t rx_tx_addr[5]; uint8_t rx_tx_addr[5];
uint8_t phase; uint8_t phase;
uint16_t bind_counter; uint16_t bind_counter;
@ -64,6 +64,7 @@ uint8_t hopping_frequency_no=0;
uint8_t rf_ch_num; uint8_t rf_ch_num;
uint8_t throttle, rudder, elevator, aileron; uint8_t throttle, rudder, elevator, aileron;
uint8_t flags; uint8_t flags;
uint16_t crc;
// //
uint32_t state; uint32_t state;
uint8_t len; uint8_t len;
@ -91,13 +92,14 @@ uint8_t prev_protocol=0;
#define MAX_PKT 27 #define MAX_PKT 27
uint8_t pkt[MAX_PKT];//telemetry receiving packets uint8_t pkt[MAX_PKT];//telemetry receiving packets
#if defined(TELEMETRY) #if defined(TELEMETRY)
uint8_t pktt[MAX_PKT];//telemetry receiving packets uint8_t pktt[MAX_PKT];//telemetry receiving packets
volatile uint8_t tx_head; volatile uint8_t tx_head;
volatile uint8_t tx_tail; volatile uint8_t tx_tail;
uint8_t v_lipo; uint8_t v_lipo;
int16_t RSSI_dBm; int16_t RSSI_dBm;
//const uint8_t RSSI_offset=72;//69 71.72 values db //const uint8_t RSSI_offset=72;//69 71.72 values db
uint8_t telemetry_link=0; uint8_t telemetry_link=0;
uint8_t telemetry_counter=0;
#endif #endif
// Callback // Callback

View File

@ -257,6 +257,7 @@ uint8_t NRF24L01_packet_ack()
/////////////// ///////////////
// XN297 emulation layer // XN297 emulation layer
uint8_t xn297_scramble_enabled;
uint8_t xn297_addr_len; uint8_t xn297_addr_len;
uint8_t xn297_tx_addr[5]; uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5]; uint8_t xn297_rx_addr[5];
@ -269,9 +270,16 @@ static const uint8_t xn297_scramble[] = {
0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f, 0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f,
0x8e, 0xc5, 0x2f}; 0x8e, 0xc5, 0x2f};
static const uint16_t xn297_crc_xorout[] = { const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, // 1st entry is missing, probably never needed 0x0000, 0x3d5f, 0xa6f1, 0x3a23, 0xaa16, 0x1caf,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, // it's used for 3-byte address w/ 0 byte payload only 0x62b2, 0xe0eb, 0x0821, 0xbe07, 0x5f1a, 0xaf15,
0x4f0a, 0xad24, 0x5e48, 0xed34, 0x068c, 0xf2c9,
0x1852, 0xdf36, 0x129d, 0xb17c, 0xd5f5, 0x70d7,
0xb798, 0x5133, 0x67db, 0xd94e};
const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7, 0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
0x2138, 0x129F, 0xB3A0, 0x2988}; 0x2138, 0x129F, 0xB3A0, 0x2988};
@ -327,16 +335,21 @@ void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
memcpy(buf, addr, len); memcpy(buf, addr, len);
memcpy(xn297_rx_addr, addr, len); memcpy(xn297_rx_addr, addr, len);
for (uint8_t i = 0; i < xn297_addr_len; ++i) for (uint8_t i = 0; i < xn297_addr_len; ++i)
buf[i] = xn297_rx_addr[i] ^ xn297_scramble[xn297_addr_len-i-1]; {
buf[i] = xn297_rx_addr[i];
if(xn297_scramble_enabled)
buf[i] ^= xn297_scramble[xn297_addr_len-i-1];
}
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2); NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5); NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
} }
void XN297_Configure(uint8_t flags) void XN297_Configure(uint16_t flags)
{ {
xn297_scramble_enabled = !(flags & BV(XN297_UNSCRAMBLED));
xn297_crc = !!(flags & BV(NRF24L01_00_EN_CRC)); xn297_crc = !!(flags & BV(NRF24L01_00_EN_CRC));
flags &= ~(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)); flags &= ~(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags); NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
} }
void XN297_WritePayload(uint8_t* msg, uint8_t len) void XN297_WritePayload(uint8_t* msg, uint8_t len)
@ -352,12 +365,20 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
buf[last++] = 0x55; buf[last++] = 0x55;
} }
for (uint8_t i = 0; i < xn297_addr_len; ++i) for (uint8_t i = 0; i < xn297_addr_len; ++i)
buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i]; {
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
for (uint8_t i = 0; i < len; ++i) { if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[i];
last++;
}
for (uint8_t i = 0; i < len; ++i)
{
// bit-reverse bytes in packet // bit-reverse bytes in packet
uint8_t b_out = bit_reverse(msg[i]); uint8_t b_out = bit_reverse(msg[i]);
buf[last++] = b_out ^ xn297_scramble[xn297_addr_len+i]; buf[last] = b_out;
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[xn297_addr_len+i];
last++;
} }
if (xn297_crc) if (xn297_crc)
{ {
@ -365,7 +386,10 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
uint16_t crc = 0xb5d2; uint16_t crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i) for (uint8_t i = offset; i < last; ++i)
crc = crc16_update(crc, buf[i]); crc = crc16_update(crc, buf[i]);
crc ^= xn297_crc_xorout[xn297_addr_len - 3 + len]; if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
buf[last++] = crc >> 8; buf[last++] = crc >> 8;
buf[last++] = crc & 0xff; buf[last++] = crc & 0xff;
} }
@ -374,9 +398,14 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
void XN297_ReadPayload(uint8_t* msg, uint8_t len) void XN297_ReadPayload(uint8_t* msg, uint8_t len)
{ {
// TODO: if xn297_crc==1, check CRC before filling *msg
NRF24L01_ReadPayload(msg, len); NRF24L01_ReadPayload(msg, len);
for(uint8_t i=0; i<len; i++) for(uint8_t i=0; i<len; i++)
msg[i] = bit_reverse(msg[i]) ^ bit_reverse(xn297_scramble[i+xn297_addr_len]); {
msg[i] = bit_reverse(msg[i]);
if(xn297_scramble_enabled)
msg[i] ^= bit_reverse(xn297_scramble[i+xn297_addr_len]);
}
} }
// End of XN297 emulation // End of XN297 emulation

View File

@ -1,24 +1,39 @@
//************************************* //*************************************
// FrSky Telemetry serial code * // FrSky Telemetry serial code *
// By Midelic on RCG * // By Midelic on RCGroups *
//************************************* //*************************************
#if defined TELEMETRY #if defined TELEMETRY
#if defined FRSKYX_CC2500_INO
#define SPORT_TELEMETRY
#endif
#if defined FRSKY_CC2500_INO
#define HUB_TELEMETRY
#endif
#if defined SPORT_TELEMETRY
#define SPORT_TELEMETRY
#define SPORT_TIME 12000
uint32_t last=0;
uint8_t sport_counter=0;
uint8_t RxBt=0;
uint8_t rssi;
uint8_t ADC2;
#endif
#if defined HUB_TELEMETRY
#define MAX_PKTX 10
uint8_t pktx[MAX_PKTX];
uint8_t index;
uint8_t prev_index;
uint8_t pass = 0;
#endif
#define USER_MAX_BYTES 6
uint8_t frame[18];
#define USER_MAX_BYTES 6 void frskySendStuffed()
#define MAX_PKTX 10 {
uint8_t frame[18];
uint8_t pass = 0;
uint8_t index;
uint8_t prev_index;
uint8_t pktx[MAX_PKTX];
void frskySendStuffed()
{
Serial_write(0x7E); Serial_write(0x7E);
for (uint8_t i = 0; i < 9; i++) for (uint8_t i = 0; i < 9; i++)
{ {
if ((frame[i] == 0x7e) || (frame[i] == 0x7d)) if ((frame[i] == 0x7e) || (frame[i] == 0x7d))
{ {
Serial_write(0x7D); Serial_write(0x7D);
@ -27,18 +42,19 @@ void frskySendStuffed()
Serial_write(frame[i]); Serial_write(frame[i]);
} }
Serial_write(0x7E); Serial_write(0x7E);
} }
void compute_RSSIdbm(){
void compute_RSSIdbm(){
RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5); RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5);
if(pktt[len-2] >=128) if(pktt[len-2] >=128)
RSSI_dBm -= 82; RSSI_dBm -= 82;
else else
RSSI_dBm += 65; RSSI_dBm += 65;
} }
void frsky_check_telemetry(uint8_t *pkt,uint8_t len) void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
{ {
if(pkt[1] != rx_tx_addr[3] || pkt[2] != rx_tx_addr[2] || len != pkt[0] + 3) if(pkt[1] != rx_tx_addr[3] || pkt[2] != rx_tx_addr[2] || len != pkt[0] + 3)
{//only packets with the required id and packet length {//only packets with the required id and packet length
for(uint8_t i=3;i<6;i++) for(uint8_t i=3;i<6;i++)
@ -53,10 +69,10 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
if(pktt[6]>0) if(pktt[6]>0)
telemetry_counter=(telemetry_counter+1)%32; telemetry_counter=(telemetry_counter+1)%32;
} }
} }
void frsky_link_frame() void frsky_link_frame()
{ {
frame[0] = 0xFE; frame[0] = 0xFE;
if ((cur_protocol[0]&0x1F)==MODE_FRSKY) if ((cur_protocol[0]&0x1F)==MODE_FRSKY)
{ {
@ -76,11 +92,11 @@ void frsky_link_frame()
} }
frame[5] = frame[6] = frame[7] = frame[8] = 0; frame[5] = frame[6] = frame[7] = frame[8] = 0;
frskySendStuffed(); frskySendStuffed();
} }
#if defined HUB_TELEMETRY #if defined HUB_TELEMETRY
void frsky_user_frame() void frsky_user_frame()
{ {
uint8_t indexx = 0, c=0, j=8, n=0, i; uint8_t indexx = 0, c=0, j=8, n=0, i;
if(pktt[6]>0 && pktt[6]<=MAX_PKTX) if(pktt[6]>0 && pktt[6]<=MAX_PKTX)
@ -146,21 +162,176 @@ void frsky_user_frame()
} }
else else
pass=0; pass=0;
} }
#endif #endif
void frskyUpdate() #if defined SPORT_TELEMETRY
{
if(telemetry_link) /* SPORT details serial
100K 8E2 normal-multiprotocol
-every 12ms-
1 2 3 4 5 6 7 8 9 CRC DESCR
7E 98 10 05 F1 20 23 0F 00 A6 SWR_ID
7E 98 10 01 F1 33 00 00 00 C9 RSSI_ID
7E 98 10 04 F1 58 00 00 00 A1 BATT_ID
7E BA 10 03 F1 E2 00 00 00 18 ADC2_ID
7E BA 10 03 F1 E2 00 00 00 18 ADC2_ID
7E BA 10 03 F1 E2 00 00 00 18 ADC2_ID
7E BA 10 03 F1 E2 00 00 00 18 ADC2_ID
7E BA 10 03 F1 E2 00 00 00 18 ADC2_ID
7E BA 10 03 F1 E2 00 00 00 18 ADC2_ID
Telemetry frames(RF) SPORT info 15 bytes
SPORT frame 6+3 bytes
[00] PKLEN 0E 0E 0E 0E
[01] TXID1 DD DD DD DD
[02] TXID2 6D 6D 6D 6D
[03] CONST 02 02 02 02
[04] RS/RB 2C D0 2C CE //D0;CE=2*RSSI;....2C = RX battery voltage(5V from Bec)
[05] ????? 03 10 21 32 //TX/RX telemetry hand-shake bytes
[06] NO.BT 00 00 06 03 //No.of valid SPORT frame bytes in the frame
[07] STRM1 00 00 7E 00
[08] STRM2 00 00 1A 00
[09] STRM3 00 00 10 00
[10] STRM4 03 03 03 03
[11] STRM5 F1 F1 F1 F1
[12] STRM6 D1 D1 D0 D0
[13] CHKSUM1
[14] CHKSUM2
*/
void sportSend(uint8_t *p)
{
uint16_t crc_s = 0;
Serial_write(0x7e);//+9
for (uint8_t i = 0; i < 9; i++)
{
if (i == 8)
p[i] = 0xff - crc_s;
if ((p[i] == 0x7e) || (p[i] == 0x7d))
{
Serial_write(0x7d);
Serial_write(0x20 ^ p[i]);
}
else
Serial_write(p[i]);
if (i>0)
{
crc_s += p[i]; //0-1FF
crc_s += crc_s >> 8; //0-100
crc_s &= 0x00ff;
}
}
}
void sportIdle()
{
Serial_write(0x7e);
}
void sportSendFrame()
{
//at the moment only SWR RSSI,RxBt and A2.
sport_counter = (sport_counter + 1) %9;
for (uint8_t i=5;i<8;i++)
frame[i]=0;
switch (sport_counter)
{
case 0: // SWR
frame[0] = 0x98;
frame[1] = 0x10;
frame[2] = 0x05;
frame[3] = 0xf1;
frame[4] = 0x20;//dummy values if swr 20230f00
frame[5] = 0x23;
frame[6] = 0x0F;
frame[7] = 0x00;
break;
case 1: // RSSI
frame[0] = 0x98;
frame[1] = 0x10;
frame[2] = 0x01;
frame[3] = 0xf1;
frame[4] = rssi;
break;
case 2: //BATT
frame[0] = 0x98;
frame[1] = 0x10;
frame[2] = 0x04;
frame[3] = 0xf1;
frame[4] = RxBt;//a1;
break;
case 3: //ADC2(A2)
frame[0] = 0x1A;
frame[1] = 0x10;
frame[2] = 0x03;
frame[3] = 0xf1;
frame[4] = ADC2;//a2;;
break;
default:
sportIdle();
return;
}
sportSend(frame);
}
void process_sport_data()//only for ADC2
{
uint8_t j=7;
if(pktt[6]>0 && pktt[6]<=USER_MAX_BYTES)
{
for(uint8_t i=0;i<6;i++)
if(pktt[j++]==0x03)
if(pktt[j]==0xF1)
{
ADC2=pktt[j+1];
break;
}
pktt[6]=0;//new frame
}
}
#endif
void frskyUpdate()
{
if(telemetry_link && (cur_protocol[0]&0x1F) != MODE_FRSKYX )
{ {
frsky_link_frame(); frsky_link_frame();
telemetry_link=0; telemetry_link=0;
return; return;
} }
#if defined HUB_TELEMETRY #if defined HUB_TELEMETRY
if(!telemetry_link && (cur_protocol[0]&0x1F) != MODE_HUBSAN ) if(!telemetry_link && (cur_protocol[0]&0x1F) != MODE_HUBSAN && (cur_protocol[0]&0x1F) != MODE_FRSKYX)
{
frsky_user_frame(); frsky_user_frame();
return;
}
#endif #endif
} #if defined SPORT_TELEMETRY
if ((cur_protocol[0]&0x1F)==MODE_FRSKYX)
{
if(telemetry_link)
{
process_sport_data();
if(pktt[4]>0x36)
rssi=pktt[4]/2;
else
RxBt=pktt[4];
telemetry_link=0;
}
uint32_t now = micros();
if ((now - last) > SPORT_TIME)
{
sportSendFrame();
last = now;
}
}
#endif
}
#endif #endif

View File

@ -23,31 +23,40 @@
//Uncomment to enable telemetry //Uncomment to enable telemetry
#define TELEMETRY #define TELEMETRY
#define HUB_TELEMETRY
//Comment if a module is not installed
#define A7105_INSTALLED
#define CYRF6936_INSTALLED
#define CC2500_INSTALLED
#define NFR24L01_INSTALLED
//Comment a protocol to exclude it from compilation //Comment a protocol to exclude it from compilation
//A7105 protocols #ifdef A7105_INSTALLED
#define FLYSKY_A7105_INO #define FLYSKY_A7105_INO
#define HUBSAN_A7105_INO #define HUBSAN_A7105_INO
//CYRF6936 protocols #endif
#define DEVO_CYRF6936_INO #ifdef CYRF6936_INSTALLED
#define DSM2_CYRF6936_INO #define DEVO_CYRF6936_INO
//CC2500 protocols #define DSM2_CYRF6936_INO
#define FRSKY_CC2500_INO #endif
//#define FRSKYX_CC2500_INO #ifdef CC2500_INSTALLED
//NFR24L01 protocols #define FRSKY_CC2500_INO
#define BAYANG_NRF24L01_INO #define FRSKYX_CC2500_INO
#define CG023_NRF24L01_INO #endif
#define CX10_NRF24L01_INO #ifdef NFR24L01_INSTALLED
#define ESKY_NRF24L01_INO #define BAYANG_NRF24L01_INO
#define HISKY_NRF24L01_INO #define CG023_NRF24L01_INO
#define KN_NRF24L01_INO #define CX10_NRF24L01_INO
#define SLT_NRF24L01_INO #define ESKY_NRF24L01_INO
#define SYMAX_NRF24L01_INO #define HISKY_NRF24L01_INO
#define V2X2_NRF24L01_INO #define KN_NRF24L01_INO
#define YD717_NRF24L01_INO #define SLT_NRF24L01_INO
#define MT99XX_NRF24L01_INO #define SYMAX_NRF24L01_INO
#define MJXQ_NRF24L01_INO #define V2X2_NRF24L01_INO
#define YD717_NRF24L01_INO
#define MT99XX_NRF24L01_INO
#define MJXQ_NRF24L01_INO
#endif
//Update this table to set which protocol and all associated settings are called for the corresponding dial number //Update this table to set which protocol and all associated settings are called for the corresponding dial number
static const PPM_Parameters PPM_prot[15]= static const PPM_Parameters PPM_prot[15]=

View File

@ -102,18 +102,7 @@ enum {
#define REUSE_TX_PL 0xE3 #define REUSE_TX_PL 0xE3
//#define NOP 0xFF //#define NOP 0xFF
/* // XN297 emulation layer
void NRF24L01_Initialize(); #define XN297_UNSCRAMBLED 8
byte NRF24L01_WriteReg(byte reg, byte data);
byte NRF24L01_WriteRegisterMulti(byte reg, byte data[], byte length);
byte NRF24L01_WritePayload(byte *data, byte len);
byte NRF24L01_ReadReg(byte reg);
byte NRF24L01_ReadRegisterMulti(byte reg, byte data[], byte length);
byte NRF24L01_ReadPayload(byte *data, byte len);
byte NRF24L01_FlushTx();
byte NRF24L01_FlushRx();
byte NRF24L01_Activate(byte code);
*/
#endif #endif

View File

@ -387,7 +387,6 @@ const uint16_t PROGMEM CRCTable[]=
0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78
}; };
//**************************************** //****************************************
//*** MULTI protocol serial definition *** //*** MULTI protocol serial definition ***
//**************************************** //****************************************