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,
};
const uint8_t pncodes[5][9][8] = {
const uint8_t PROGMEM pncodes[5][9][8] = {
/* Note these are in order transmitted (LSB 1st) */
{ /* Row 0 */
/* 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 sop_col;
@ -109,8 +114,6 @@ uint8_t data_col;
uint16_t cyrf_state;
uint8_t crcidx;
uint8_t binding;
uint16_t crc;
/*
#ifdef USE_FIXED_MFGID
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()
{
const uint8_t pn_bind[] = { 0xc6,0x94,0x22,0xfe,0x48,0xe6,0x57,0x4e };
uint8_t data_code[32];
uint8_t code[32];
CYRF_ConfigRFChannel(BIND_CHANNEL); //This seems to be random?
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);
CYRF_ConfigCRCSeed(crc);
CYRF_ConfigSOPCode(pncodes[pn_row][sop_col]);
memcpy(data_code, pncodes[pn_row][data_col], 16);
memcpy(data_code + 16, pncodes[0][8], 8);
memcpy(data_code + 24, pn_bind, 8);
CYRF_ConfigDataCode(data_code, 32);
read_code(code,pn_row,sop_col,8);
CYRF_ConfigSOPCode(code);
read_code(code,pn_row,data_col,16);
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();
}
@ -349,12 +355,17 @@ static void __attribute__((unused)) cyrf_configdata()
static void __attribute__((unused)) set_sop_data_crc()
{
uint8_t code[16];
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);
CYRF_ConfigRFChannel(hopping_frequency[chidx]);
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)
chidx = (chidx + 1) % 23;
else

View File

@ -1,4 +1,7 @@
/*
/* **************************
* 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
@ -11,11 +14,302 @@
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(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

View File

@ -20,7 +20,6 @@
//##########Variables########
//uint32_t state;
//uint8_t len;
uint8_t telemetry_counter=0;
/*
enum {
@ -128,8 +127,6 @@ static void __attribute__((unused)) frsky2way_build_bind_packet()
packet[17] = 0x01;
}
static void __attribute__((unused)) frsky2way_data_frame()
{//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
@ -138,7 +135,11 @@ static void __attribute__((unused)) frsky2way_data_frame()
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = counter;//
packet[4]=telemetry_counter;
#if defined TELEMETRY
packet[4] = telemetry_counter;
#else
packet[4] = 0x00;
#endif
packet[5] = 0x01;
//

View File

@ -37,29 +37,16 @@ enum{
FLAG_MT_FLIP = 0x80,
};
enum{
// flags going to ?????? (Yi Zhan i6S)ROLL
BLABLA,
};
enum {
MT99XX_INIT = 0,
MT99XX_BIND,
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 const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
static const uint8_t mys_byte[] = {
const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
const uint8_t mys_byte[] = {
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
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[2] = convert_channel_8b_scale(AILERON ,0x00,0xE1); // aileron
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[5] = convert_channel_8b_scale(AUX6,0x00,0x3F); // roll trim (0x00-0x20-0x3f)
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
packet[6] = GET_FLAG( Servo_AUX1, FLAG_MT_FLIP )
| GET_FLAG( Servo_AUX3, FLAG_MT_SNAPSHOT )
| GET_FLAG( Servo_AUX4, FLAG_MT_VIDEO );
@ -84,7 +71,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
// low nibble: index in chan list ?
// high nibble: 0->start from start of list, 1->start from end of list ?
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
{ // YZ
@ -100,8 +90,12 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet_count=0;
}
packet[4] = yz_p4_seq[yz_seq_num];
packet[5] = 0x02; // expert ? (0=unarmed, 1=normal)
packet[6] = 0x80;
packet[5] = 0x02 // expert ? (0=unarmed, 1=normal)
| 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];
for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++)
packet[7] += packet[idx];
@ -138,6 +132,9 @@ static void __attribute__((unused)) MT99XX_init()
else
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
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);
}
@ -210,8 +207,8 @@ uint16_t initMT99XX(void)
packet[2] = 0x05;
packet[3] = 0x06;
}
packet[4] = rx_tx_addr[0]; // 1th 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[4] = rx_tx_addr[0]; // 1st byte for data state tx address
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[7] = checksum_offset; // checksum offset
packet[8] = 0xAA; // fixed

View File

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

View File

@ -257,6 +257,7 @@ uint8_t NRF24L01_packet_ack()
///////////////
// XN297 emulation layer
uint8_t xn297_scramble_enabled;
uint8_t xn297_addr_len;
uint8_t xn297_tx_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,
0x8e, 0xc5, 0x2f};
static const uint16_t xn297_crc_xorout[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, // 1st entry is missing, probably never needed
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, // it's used for 3-byte address w/ 0 byte payload only
const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3d5f, 0xa6f1, 0x3a23, 0xaa16, 0x1caf,
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,
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
0x2138, 0x129F, 0xB3A0, 0x2988};
@ -327,16 +335,21 @@ void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
memcpy(buf, addr, len);
memcpy(xn297_rx_addr, addr, len);
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_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));
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)
@ -352,12 +365,20 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
buf[last++] = 0x55;
}
for (uint8_t i = 0; i < xn297_addr_len; ++i)
buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i];
for (uint8_t i = 0; i < len; ++i) {
{
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[i];
last++;
}
for (uint8_t i = 0; i < len; ++i)
{
// bit-reverse bytes in packet
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)
{
@ -365,7 +386,10 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
uint16_t crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++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 & 0xff;
}
@ -374,9 +398,14 @@ void XN297_WritePayload(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);
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

View File

@ -1,24 +1,39 @@
//*************************************
// FrSky Telemetry serial code *
// By Midelic on RCG *
// By Midelic on RCGroups *
//*************************************
#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
#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()
{
void frskySendStuffed()
{
Serial_write(0x7E);
for (uint8_t i = 0; i < 9; i++)
{
if ((frame[i] == 0x7e) || (frame[i] == 0x7d))
{
Serial_write(0x7D);
@ -27,18 +42,19 @@ void frskySendStuffed()
Serial_write(frame[i]);
}
Serial_write(0x7E);
}
}
void compute_RSSIdbm(){
void compute_RSSIdbm(){
RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5);
if(pktt[len-2] >=128)
RSSI_dBm -= 82;
else
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)
{//only packets with the required id and packet length
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)
telemetry_counter=(telemetry_counter+1)%32;
}
}
}
void frsky_link_frame()
{
void frsky_link_frame()
{
frame[0] = 0xFE;
if ((cur_protocol[0]&0x1F)==MODE_FRSKY)
{
@ -76,11 +92,11 @@ void frsky_link_frame()
}
frame[5] = frame[6] = frame[7] = frame[8] = 0;
frskySendStuffed();
}
}
#if defined HUB_TELEMETRY
void frsky_user_frame()
{
#if defined HUB_TELEMETRY
void frsky_user_frame()
{
uint8_t indexx = 0, c=0, j=8, n=0, i;
if(pktt[6]>0 && pktt[6]<=MAX_PKTX)
@ -146,21 +162,176 @@ void frsky_user_frame()
}
else
pass=0;
}
#endif
}
#endif
void frskyUpdate()
{
if(telemetry_link)
#if defined SPORT_TELEMETRY
/* 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();
telemetry_link=0;
return;
}
#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();
return;
}
#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

View File

@ -23,31 +23,40 @@
//Uncomment to enable 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
//A7105 protocols
#define FLYSKY_A7105_INO
#define HUBSAN_A7105_INO
//CYRF6936 protocols
#define DEVO_CYRF6936_INO
#define DSM2_CYRF6936_INO
//CC2500 protocols
#define FRSKY_CC2500_INO
//#define FRSKYX_CC2500_INO
//NFR24L01 protocols
#define BAYANG_NRF24L01_INO
#define CG023_NRF24L01_INO
#define CX10_NRF24L01_INO
#define ESKY_NRF24L01_INO
#define HISKY_NRF24L01_INO
#define KN_NRF24L01_INO
#define SLT_NRF24L01_INO
#define SYMAX_NRF24L01_INO
#define V2X2_NRF24L01_INO
#define YD717_NRF24L01_INO
#define MT99XX_NRF24L01_INO
#define MJXQ_NRF24L01_INO
#ifdef A7105_INSTALLED
#define FLYSKY_A7105_INO
#define HUBSAN_A7105_INO
#endif
#ifdef CYRF6936_INSTALLED
#define DEVO_CYRF6936_INO
#define DSM2_CYRF6936_INO
#endif
#ifdef CC2500_INSTALLED
#define FRSKY_CC2500_INO
#define FRSKYX_CC2500_INO
#endif
#ifdef NFR24L01_INSTALLED
#define BAYANG_NRF24L01_INO
#define CG023_NRF24L01_INO
#define CX10_NRF24L01_INO
#define ESKY_NRF24L01_INO
#define HISKY_NRF24L01_INO
#define KN_NRF24L01_INO
#define SLT_NRF24L01_INO
#define SYMAX_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
static const PPM_Parameters PPM_prot[15]=

View File

@ -102,18 +102,7 @@ enum {
#define REUSE_TX_PL 0xE3
//#define NOP 0xFF
/*
void NRF24L01_Initialize();
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);
// XN297 emulation layer
#define XN297_UNSCRAMBLED 8
byte NRF24L01_FlushTx();
byte NRF24L01_FlushRx();
byte NRF24L01_Activate(byte code);
*/
#endif

View File

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