mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-07-03 03:57:51 +00:00
Ajout de 5 protocoles
This commit is contained in:
parent
bdb8eec3ea
commit
f6b4db1618
@ -191,10 +191,16 @@ const uint8_t PROGMEM HUBSAN_A7105_regs[] = {
|
||||
0xFF, 0xFF, 0xFF
|
||||
};
|
||||
const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
|
||||
/*
|
||||
0xff, 0x42, 0x00, 0x14, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50,
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f,
|
||||
0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00,
|
||||
0x01, 0x0f, 0xff
|
||||
*/
|
||||
-1, 0x42, 0x00, 0x14, 0x00, -1 , -1 , 0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50,
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f,
|
||||
0x13, 0xc3, 0x00, -1, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00,
|
||||
0x01, 0x0f, -1
|
||||
};
|
||||
#define ID_NORMAL 0x55201041
|
||||
#define ID_PLUS 0xAA201041
|
||||
|
@ -114,14 +114,6 @@ uint8_t data_col;
|
||||
uint16_t cyrf_state;
|
||||
uint8_t crcidx;
|
||||
uint8_t binding;
|
||||
/*
|
||||
#ifdef USE_FIXED_MFGID
|
||||
const uint8_t cyrfmfg_id[6] = {0x5e, 0x28, 0xa3, 0x1b, 0x00, 0x00}; //dx8
|
||||
const uint8_t cyrfmfg_id[6] = {0xd4, 0x62, 0xd6, 0xad, 0xd3, 0xff}; //dx6i
|
||||
#else
|
||||
//uint8_t cyrfmfg_id[6];
|
||||
#endif
|
||||
*/
|
||||
|
||||
static void __attribute__((unused)) build_bind_packet()
|
||||
{
|
||||
|
@ -117,7 +117,6 @@ static void __attribute__((unused)) ESKY_send_packet(uint8_t bind)
|
||||
// For arithmetic simplicity, channels are repeated in rf_channels array
|
||||
if (hopping_frequency_no == 0)
|
||||
{
|
||||
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2};
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
{
|
||||
packet[i*2] = Servo_data[ch[i]]>>8; //high byte of servo timing(1000-2000us)
|
||||
|
@ -45,7 +45,7 @@ enum {
|
||||
FLAG_V9X9_VIDEO = 0x40,
|
||||
FLAG_V9X9_CAMERA= 0x80,
|
||||
// flags going to byte 12
|
||||
FLAG_V9X9_UNK = 0x10, // undocumented ?
|
||||
FLAG_V9X9_FLIP = 0x10,
|
||||
FLAG_V9X9_LED = 0x20,
|
||||
};
|
||||
|
||||
@ -82,7 +82,7 @@ static void __attribute__((unused)) flysky_apply_extension_flags()
|
||||
{
|
||||
case V9X9:
|
||||
if(Servo_AUX1)
|
||||
packet[12] |= FLAG_V9X9_UNK;
|
||||
packet[12] |= FLAG_V9X9_FLIP;
|
||||
if(Servo_AUX2)
|
||||
packet[12] |= FLAG_V9X9_LED;
|
||||
if(Servo_AUX3)
|
||||
@ -210,3 +210,4 @@ uint16_t initFlySky() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -43,39 +43,179 @@
|
||||
0x34, 0x1B, 0x00, 0x1D, 0x03
|
||||
};
|
||||
|
||||
uint8_t hop(uint8_t byte)
|
||||
static uint8_t __attribute__((unused)) hop(uint8_t byte)
|
||||
{
|
||||
return pgm_read_byte_near(&hop_data[byte]);
|
||||
}
|
||||
|
||||
uint16_t initFrSkyX()
|
||||
static void __attribute__((unused)) set_start(uint8_t ch )
|
||||
{
|
||||
while(!chanskip)
|
||||
{
|
||||
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
|
||||
chanskip=random(0xfefefefe)%47;
|
||||
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]));
|
||||
}
|
||||
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)
|
||||
static void __attribute__((unused)) frskyX_init()
|
||||
{
|
||||
state = FRSKY_BIND;
|
||||
initialize_data(1);
|
||||
}
|
||||
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
|
||||
{
|
||||
state = FRSKY_DATA1;
|
||||
initialize_data(0);
|
||||
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);
|
||||
}
|
||||
return 10000;
|
||||
|
||||
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()
|
||||
@ -137,179 +277,33 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
void set_start(uint8_t ch )
|
||||
uint16_t initFrSkyX()
|
||||
{
|
||||
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()
|
||||
while(!chanskip)
|
||||
{
|
||||
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########
|
||||
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
|
||||
chanskip=random(0xfefefefe)%47;
|
||||
}
|
||||
while((chanskip-ctr)%4)
|
||||
ctr=(ctr+1)%4;
|
||||
|
||||
void initialize_data(uint8_t adr)
|
||||
counter_rst=(chanskip-ctr)>>2;
|
||||
//for test***************
|
||||
//rx_tx_addr[3]=0xB3;
|
||||
//rx_tx_addr[2]=0xFD;
|
||||
//************************
|
||||
frskyX_init();
|
||||
//
|
||||
if(IS_AUTOBIND_FLAG_on)
|
||||
{
|
||||
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);
|
||||
state = FRSKY_BIND;
|
||||
initialize_data(1);
|
||||
}
|
||||
|
||||
void frskyX_build_bind_packet()
|
||||
else
|
||||
{
|
||||
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);
|
||||
//
|
||||
state = FRSKY_DATA1;
|
||||
initialize_data(0);
|
||||
}
|
||||
|
||||
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;
|
||||
return 10000;
|
||||
}
|
||||
#endif
|
@ -38,45 +38,19 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind)
|
||||
// Configure cc2500 for tx mode
|
||||
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, 0x19);
|
||||
cc2500_writeReg(CC2500_07_PKTCTRL1, 0x04);
|
||||
cc2500_writeReg(CC2500_08_PKTCTRL0, 0x05);
|
||||
cc2500_writeReg(CC2500_3E_PATABLE, 0xff);
|
||||
cc2500_writeReg(CC2500_0B_FSCTRL1, 0x08);
|
||||
cc2500_writeReg(CC2500_0C_FSCTRL0, option);
|
||||
//base freq FREQ = 0x5C7627 (F = 2404MHz)
|
||||
cc2500_writeReg(CC2500_0D_FREQ2, 0x5c);
|
||||
cc2500_writeReg(CC2500_0E_FREQ1, 0x76);
|
||||
cc2500_writeReg(CC2500_0F_FREQ0, 0x27);
|
||||
//
|
||||
cc2500_writeReg(CC2500_10_MDMCFG4, 0xAA);
|
||||
cc2500_writeReg(CC2500_11_MDMCFG3, 0x39);
|
||||
cc2500_writeReg(CC2500_12_MDMCFG2, 0x11);
|
||||
cc2500_writeReg(CC2500_13_MDMCFG1, 0x23);
|
||||
cc2500_writeReg(CC2500_14_MDMCFG0, 0x7a);
|
||||
cc2500_writeReg(CC2500_15_DEVIATN, 0x42);
|
||||
cc2500_writeReg(CC2500_19_FOCCFG, 0x16);
|
||||
cc2500_writeReg(CC2500_1A_BSCFG, 0x6c);
|
||||
cc2500_writeReg(CC2500_1B_AGCCTRL2, bind ? 0x43 : 0x03);
|
||||
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);
|
||||
//
|
||||
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_0C_FSCTRL0)
|
||||
val=option;
|
||||
else
|
||||
if(reg==CC2500_1B_AGCCTRL2)
|
||||
val=bind ? 0x43 : 0x03;
|
||||
cc2500_writeReg(reg,val);
|
||||
}
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
CC2500_SetPower();
|
||||
|
||||
|
@ -45,8 +45,7 @@ uint8_t packet[40];
|
||||
// Servo data
|
||||
uint16_t Servo_data[NUM_CHN];
|
||||
uint8_t Servo_AUX;
|
||||
// PPM variable
|
||||
volatile uint16_t PPM_data[NUM_CHN];
|
||||
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4};
|
||||
|
||||
// Protocol variables
|
||||
uint8_t rx_tx_addr[5];
|
||||
@ -73,9 +72,11 @@ uint8_t RX_num;
|
||||
|
||||
// Mode_select variables
|
||||
uint8_t mode_select;
|
||||
uint8_t ppm_select=0, flag_decal=0;
|
||||
uint8_t protocol_flags=0,protocol_flags2=0;
|
||||
|
||||
// PPM variable
|
||||
volatile uint16_t PPM_data[NUM_CHN];
|
||||
|
||||
// Serial variables
|
||||
#define RXBUFFER_SIZE 25
|
||||
#define TXBUFFER_SIZE 12
|
||||
@ -158,25 +159,24 @@ void setup()
|
||||
MProtocol_id_master=random_id(10,false);
|
||||
|
||||
//Init RF modules
|
||||
#ifdef CC2500_INSTALLED
|
||||
CC2500_Reset();
|
||||
#endif
|
||||
|
||||
//Protocol and interrupts initialization
|
||||
#if !defined(POTAR_SELECT)
|
||||
if(mode_select == MODE_SERIAL)
|
||||
{ // Serial
|
||||
cur_protocol[0]=0;
|
||||
cur_protocol[1]=0;
|
||||
prev_protocol=0;
|
||||
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
||||
}
|
||||
else
|
||||
#else
|
||||
if(mode_select==MODE_SERIAL) { flag_decal=1; } else { flag_decal=0;}
|
||||
#endif
|
||||
if(mode_select != MODE_SERIAL)
|
||||
{ // PPM
|
||||
prev_protocol=0;
|
||||
CHANGE_PROTOCOL_FLAG_on;
|
||||
update_ppm_data();
|
||||
mode_select--;
|
||||
cur_protocol[0] = PPM_prot[mode_select].protocol;
|
||||
sub_protocol = PPM_prot[mode_select].sub_proto;
|
||||
RX_num = PPM_prot[mode_select].rx_num;
|
||||
MProtocol_id = RX_num + MProtocol_id_master;
|
||||
option = PPM_prot[mode_select].option;
|
||||
if(PPM_prot[mode_select].power) POWER_FLAG_on;
|
||||
if(PPM_prot[mode_select].autobind) AUTOBIND_FLAG_on;
|
||||
mode_select++;
|
||||
|
||||
protocol_init();
|
||||
|
||||
//Configure PPM interrupt
|
||||
EICRA |=(1<<ISC11); // The rising edge of INT1 pin D3 generates an interrupt request
|
||||
@ -185,32 +185,41 @@ void setup()
|
||||
PPM_Telemetry_serial_init(); // Configure serial for telemetry
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{ // Serial
|
||||
cur_protocol[0]=0;
|
||||
cur_protocol[1]=0;
|
||||
prev_protocol=0;
|
||||
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
||||
}
|
||||
}
|
||||
|
||||
// Main
|
||||
void loop()
|
||||
{
|
||||
#if !defined(POTAR_SELECT)
|
||||
if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received
|
||||
{
|
||||
update_serial_data(); // Update protocol and data
|
||||
update_aux_flags();
|
||||
}
|
||||
if(mode_select!=MODE_SERIAL && IS_PPM_FLAG_on) // PPM mode and a full frame has been received
|
||||
#else
|
||||
if(IS_PPM_FLAG_on) // PPM mode and a full frame has been received
|
||||
#endif
|
||||
{
|
||||
update_PPM_servo();
|
||||
update_aux_flags();
|
||||
update_ppm_data();
|
||||
}
|
||||
if(IS_CHANGE_PROTOCOL_FLAG_on) { // Protocol needs to be changed
|
||||
if(IS_CHANGE_PROTOCOL_FLAG_on)
|
||||
{ // Protocol needs to be changed
|
||||
LED_OFF; //led off during protocol init
|
||||
module_reset(); //reset previous module
|
||||
protocol_init(); //init new protocol
|
||||
CHANGE_PROTOCOL_FLAG_off; //done
|
||||
}
|
||||
}
|
||||
if(mode_select!=MODE_SERIAL && IS_PPM_FLAG_on) // PPM mode and a full frame has been received
|
||||
{
|
||||
for(uint8_t i=0;i<NUM_CHN;i++)
|
||||
{ // update servo data without interrupts to prevent bad read in protocols
|
||||
cli(); // disable global int
|
||||
Servo_data[i]=PPM_data[i];
|
||||
sei(); // enable global int
|
||||
}
|
||||
update_aux_flags();
|
||||
PPM_FLAG_off; // wait for next frame before update
|
||||
}
|
||||
update_led_status();
|
||||
#if defined(TELEMETRY)
|
||||
if( ((cur_protocol[0]&0x1F)==MODE_FRSKY) || ((cur_protocol[0]&0x1F)==MODE_HUBSAN) || ((cur_protocol[0]&0x1F)==MODE_FRSKYX) )
|
||||
@ -220,20 +229,12 @@ void loop()
|
||||
CheckTimer(remote_callback);
|
||||
}
|
||||
|
||||
static void update_PPM_servo(void) {
|
||||
for(uint8_t i=0;i<NUM_CHN;i++) { // update servo data without interrupts to prevent bad read in protocols
|
||||
cli(); // disable global int
|
||||
Servo_data[i]=PPM_data[i];
|
||||
sei(); // enable global int
|
||||
}
|
||||
PPM_FLAG_off; // wait for next frame before update
|
||||
}
|
||||
// Update Servo_AUX flags based on servo AUX positions
|
||||
static void update_aux_flags(void)
|
||||
{
|
||||
Servo_AUX=0;
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
if(Servo_data[AUX1+i+flag_decal]>PPM_SWITCH)
|
||||
if(Servo_data[AUX1+i]>PPM_SWITCH)
|
||||
Servo_AUX|=1<<i;
|
||||
}
|
||||
|
||||
@ -357,6 +358,36 @@ static void protocol_init()
|
||||
remote_callback = fy326_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(ESKY150_NRF24L01_INO)
|
||||
case MODE_ESKY150:
|
||||
next_callback=esky150_setup();
|
||||
remote_callback = esky150_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(BlueFly_NRF24L01_INO)
|
||||
case MODE_BlueFly:
|
||||
next_callback=BlueFly_setup();
|
||||
remote_callback = bluefly_cb;
|
||||
break;
|
||||
#endif
|
||||
#if defined(HonTai_NRF24L01_INO)
|
||||
case MODE_BlueFly:
|
||||
next_callback=ht_setup();
|
||||
remote_callback = ht_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(UDI_NRF24L01_INO)
|
||||
case MODE_UDI:
|
||||
next_callback=UDI_setup();
|
||||
remote_callback = UDI_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(NE260_NRF24L01_INO)
|
||||
case MODE_NE260:
|
||||
next_callback=NE260_setup();
|
||||
remote_callback = ne260_cb;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(FLYSKY_A7105_INO)
|
||||
case MODE_FLYSKY:
|
||||
@ -475,6 +506,12 @@ static void protocol_init()
|
||||
next_callback=initMJXQ();
|
||||
remote_callback = MJXQ_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SHENQI_NRF24L01_INO)
|
||||
case MODE_SHENQI:
|
||||
next_callback=initSHENQI();
|
||||
remote_callback = SHENQI_callback;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -490,59 +527,6 @@ static void protocol_init()
|
||||
BIND_BUTTON_FLAG_off; // do not bind/reset id anymore even if protocol change
|
||||
}
|
||||
|
||||
static void update_ppm_data() {
|
||||
#if defined(POTAR_SELECT)
|
||||
if(Servo_data[AUX1]>PPM_SWITCH) {
|
||||
CHANGE_PROTOCOL_FLAG_on;
|
||||
tone(BUZZER, BUZZER_HTZ);
|
||||
delay(BUZZER_TPS);
|
||||
noTone(BUZZER);
|
||||
}
|
||||
#endif
|
||||
if(IS_CHANGE_PROTOCOL_FLAG_on) {
|
||||
ppm_select = 10;
|
||||
|
||||
if(mode_select == 0) {
|
||||
while(ppm_select) {
|
||||
while(!IS_PPM_FLAG_on) {} // wait
|
||||
update_PPM_servo();
|
||||
if(Servo_data[AUX1] < PPM_MAX_100) { ppm_select--; }
|
||||
} // attente de la d<>activation du rebind
|
||||
}
|
||||
prev_protocol = ppm_select;
|
||||
|
||||
// protocol selection
|
||||
ppm_select = 0;
|
||||
if(Servo_data[POTAR_SELECT_M] > PPM_MAX_COMMAND) { ppm_select += 18; } // THROTTLE up
|
||||
else if(Servo_data[POTAR_SELECT_M] < PPM_MIN_COMMAND) { ppm_select += 9; } // THROTTLE down
|
||||
else { ppm_select += 0; } // THROTTLE middle
|
||||
|
||||
|
||||
if(Servo_data[POTAR_SELECT_V] > PPM_MAX_COMMAND) { ppm_select += 7; } // Elevator up
|
||||
else if(Servo_data[POTAR_SELECT_V] < PPM_MIN_COMMAND) { ppm_select += 1; } // Elevator down
|
||||
else { ppm_select += 4; } // Elevator middle
|
||||
|
||||
if(Servo_data[POTAR_SELECT_H] > PPM_MAX_COMMAND) { ppm_select += 2; } // Aileron right
|
||||
else if(Servo_data[POTAR_SELECT_H] < PPM_MIN_COMMAND) { ppm_select += 0; } // Aileron left
|
||||
else { ppm_select += 1; } // Aileron middle
|
||||
|
||||
// if(ppm_select == 5) { ppm_select = eeprom_read_byte(30); } else { eeprom_update_byte(30, ppm_select); }
|
||||
|
||||
if(ppm_select != 5) {
|
||||
if(ppm_select > 5) { ppm_select--; }
|
||||
ppm_select--;
|
||||
cur_protocol[0] = PPM_prot[ppm_select].protocol;
|
||||
sub_protocol = PPM_prot[ppm_select].sub_proto;
|
||||
MProtocol_id = PPM_prot[ppm_select].rx_num + MProtocol_id_master;
|
||||
option = PPM_prot[ppm_select].option;
|
||||
if(PPM_prot[ppm_select].power) POWER_FLAG_on;
|
||||
if(PPM_prot[ppm_select].autobind) AUTOBIND_FLAG_on;
|
||||
ppm_select++;
|
||||
}
|
||||
|
||||
while(Servo_data[THROTTLE] > PPM_MIN_100) { delay(100); update_PPM_servo(); } // attente de la remise des gaz <20> z<>ro (pouss<73> <20> fond avec le script lua)
|
||||
}
|
||||
}
|
||||
static void update_serial_data()
|
||||
{
|
||||
if(rx_ok_buff[0]&0x20) //check range
|
||||
@ -610,7 +594,7 @@ static void module_reset()
|
||||
case MODE_DEVO:
|
||||
CYRF_Reset();
|
||||
break;
|
||||
default: // MODE_HISKY, MODE_V2X2, MODE_YD717, MODE_KN, MODE_SYMAX, MODE_SLT, MODE_CX10, MODE_CG023, MODE_BAYANG, MODE_ESKY, MODE_MT99XX, MODE_MJXQ
|
||||
default: // MODE_HISKY, MODE_V2X2, MODE_YD717, MODE_KN, MODE_SYMAX, MODE_SLT, MODE_CX10, MODE_CG023, MODE_BAYANG, MODE_ESKY, MODE_MT99XX, MODE_MJXQ, MODE_SHENQI
|
||||
NRF24L01_Reset();
|
||||
break;
|
||||
}
|
||||
@ -682,7 +666,6 @@ void Serial_write(uint8_t data)
|
||||
|
||||
static void Mprotocol_serial_init()
|
||||
{
|
||||
#define BAUD 100000
|
||||
#include <util/setbaud.h>
|
||||
UBRR0H = UBRRH_VALUE;
|
||||
UBRR0L = UBRRL_VALUE;
|
||||
@ -778,7 +761,6 @@ ISR(INT1_vect)
|
||||
}
|
||||
|
||||
//Serial RX
|
||||
#if !defined(POTAR_SELECT)
|
||||
ISR(USART_RX_vect)
|
||||
{ // RX interrupt
|
||||
if((UCSR0A&0x1C)==0) // Check frame error, data overrun and parity error
|
||||
@ -815,7 +797,6 @@ ISR(USART_RX_vect)
|
||||
idx=0; // Error encountered discard full frame...
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//Serial timer
|
||||
ISR(TIMER1_COMPB_vect)
|
||||
|
@ -154,7 +154,7 @@ void NRF24L01_SetBitrate(uint8_t bitrate)
|
||||
// Note that bitrate 250kbps (and bit RF_DR_LOW) is valid only
|
||||
// for nRF24L01+. There is no way to programmatically tell it from
|
||||
// older version, nRF24L01, but the older is practically phased out
|
||||
// by Nordic, so we assume that we deal with with modern version.
|
||||
// by Nordic, so we assume that we deal with modern version.
|
||||
|
||||
// Bit 0 goes to RF_DR_HIGH, bit 1 - to RF_DR_LOW
|
||||
rf_setup = (rf_setup & 0xD7) | ((bitrate & 0x02) << 4) | ((bitrate & 0x01) << 3);
|
||||
@ -409,3 +409,196 @@ void XN297_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
}
|
||||
|
||||
// End of XN297 emulation
|
||||
|
||||
///////////////
|
||||
// LT8910 emulation layer
|
||||
uint8_t LT8910_buffer[64];
|
||||
uint8_t LT8910_buffer_start;
|
||||
uint16_t LT8910_buffer_overhead_bits;
|
||||
uint8_t LT8910_addr[8];
|
||||
uint8_t LT8910_addr_size;
|
||||
uint8_t LT8910_Preamble_Len;
|
||||
uint8_t LT8910_Tailer_Len;
|
||||
uint8_t LT8910_CRC_Initial_Data;
|
||||
uint8_t LT8910_Flags;
|
||||
#define LT8910_CRC_ON 6
|
||||
#define LT8910_SCRAMBLE_ON 5
|
||||
#define LT8910_PACKET_LENGTH_EN 4
|
||||
#define LT8910_DATA_PACKET_TYPE_1 3
|
||||
#define LT8910_DATA_PACKET_TYPE_0 2
|
||||
#define LT8910_FEC_TYPE_1 1
|
||||
#define LT8910_FEC_TYPE_0 0
|
||||
|
||||
void LT8910_Config(uint8_t preamble_len, uint8_t trailer_len, uint8_t flags, uint8_t crc_init)
|
||||
{
|
||||
//Preamble 1 to 8 bytes
|
||||
LT8910_Preamble_Len=preamble_len;
|
||||
//Trailer 4 to 18 bits
|
||||
LT8910_Tailer_Len=trailer_len;
|
||||
//Flags
|
||||
// CRC_ON: 1 on, 0 off
|
||||
// SCRAMBLE_ON: 1 on, 0 off
|
||||
// PACKET_LENGTH_EN: 1 1st byte of payload is payload size
|
||||
// DATA_PACKET_TYPE: 00 NRZ, 01 Manchester, 10 8bit/10bit line code, 11 interleave data type
|
||||
// FEC_TYPE: 00 No FEC, 01 FEC13, 10 FEC23, 11 reserved
|
||||
LT8910_Flags=flags;
|
||||
//CRC init constant
|
||||
LT8910_CRC_Initial_Data=crc_init;
|
||||
}
|
||||
|
||||
void LT8910_SetChannel(uint8_t channel)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, channel +2); //NRF24L01 is 2400+channel but LT8900 is 2402+channel
|
||||
}
|
||||
|
||||
void LT8910_SetTxRxMode(enum TXRX_State mode)
|
||||
{
|
||||
if(mode == TX_EN)
|
||||
{
|
||||
//Switch to TX
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
//Disable CRC
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_PWR_UP));
|
||||
}
|
||||
else
|
||||
if (mode == RX_EN)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 32);
|
||||
//Switch to RX
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
// Disable CRC
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_PWR_UP) | (1 << NRF24L01_00_PRIM_RX) );
|
||||
}
|
||||
else
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
}
|
||||
|
||||
void LT8910_BuildOverhead()
|
||||
{
|
||||
uint8_t pos;
|
||||
|
||||
//Build overhead
|
||||
//preamble
|
||||
memset(LT8910_buffer,LT8910_addr[0]&0x01?0xAA:0x55,LT8910_Preamble_Len-1);
|
||||
pos=LT8910_Preamble_Len-1;
|
||||
//address
|
||||
for(uint8_t i=0;i<LT8910_addr_size;i++)
|
||||
{
|
||||
LT8910_buffer[pos]=bit_reverse(LT8910_addr[i]);
|
||||
pos++;
|
||||
}
|
||||
//trailer
|
||||
memset(LT8910_buffer+pos,(LT8910_buffer[pos-1]&0x01)==0?0xAA:0x55,3);
|
||||
LT8910_buffer_overhead_bits=pos*8+LT8910_Tailer_Len;
|
||||
//nrf address length max is 5
|
||||
pos+=LT8910_Tailer_Len/8;
|
||||
LT8910_buffer_start=pos>5?5:pos;
|
||||
}
|
||||
|
||||
void LT8910_SetAddress(uint8_t *address,uint8_t addr_size)
|
||||
{
|
||||
uint8_t addr[5];
|
||||
|
||||
//Address size (SyncWord) 2 to 8 bytes, 16/32/48/64 bits
|
||||
LT8910_addr_size=addr_size;
|
||||
memcpy(LT8910_addr,address,LT8910_addr_size);
|
||||
|
||||
//Build overhead
|
||||
LT8910_BuildOverhead();
|
||||
|
||||
//Set NRF RX&TX address based on overhead content
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, LT8910_buffer_start-2);
|
||||
for(uint8_t i=0;i<LT8910_buffer_start;i++) // reverse bytes order
|
||||
addr[i]=LT8910_buffer[LT8910_buffer_start-i-1];
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, addr,LT8910_buffer_start);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr,LT8910_buffer_start);
|
||||
}
|
||||
|
||||
uint8_t LT8910_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
uint8_t i,pos=0,shift,end,buffer[32];
|
||||
unsigned int crc=LT8910_CRC_Initial_Data,a;
|
||||
pos=LT8910_buffer_overhead_bits/8-LT8910_buffer_start;
|
||||
end=pos+len+(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN)?1:0)+(LT8910_Flags&_BV(LT8910_CRC_ON)?2:0);
|
||||
//Read payload
|
||||
NRF24L01_ReadPayload(buffer,end+1);
|
||||
//Check address + trail
|
||||
for(i=0;i<pos;i++)
|
||||
if(LT8910_buffer[LT8910_buffer_start+i]!=buffer[i])
|
||||
return 0; // wrong address...
|
||||
//Shift buffer to remove trail bits
|
||||
shift=LT8910_buffer_overhead_bits&0x7;
|
||||
for(i=pos;i<end;i++)
|
||||
{
|
||||
a=(buffer[i]<<8)+buffer[i+1];
|
||||
a<<=shift;
|
||||
buffer[i]=(a>>8)&0xFF;
|
||||
}
|
||||
//Check len
|
||||
if(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN))
|
||||
{
|
||||
crc=crc16_update(crc,buffer[pos]);
|
||||
if(bit_reverse(len)!=buffer[pos++])
|
||||
return 0; // wrong len...
|
||||
}
|
||||
//Decode message
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
crc=crc16_update(crc,buffer[pos]);
|
||||
msg[i]=bit_reverse(buffer[pos++]);
|
||||
}
|
||||
//Check CRC
|
||||
if(LT8910_Flags&_BV(LT8910_CRC_ON))
|
||||
{
|
||||
if(buffer[pos++]!=((crc>>8)&0xFF)) return 0; // wrong CRC...
|
||||
if(buffer[pos]!=(crc&0xFF)) return 0; // wrong CRC...
|
||||
}
|
||||
//Everything ok
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LT8910_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
unsigned int crc=LT8910_CRC_Initial_Data,a,mask;
|
||||
uint8_t i, pos=0,tmp, buffer[64], pos_final,shift;
|
||||
//Add packet len
|
||||
if(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN))
|
||||
{
|
||||
tmp=bit_reverse(len);
|
||||
buffer[pos++]=tmp;
|
||||
crc=crc16_update(crc,tmp);
|
||||
}
|
||||
//Add payload
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
tmp=bit_reverse(msg[i]);
|
||||
buffer[pos++]=tmp;
|
||||
crc=crc16_update(crc,tmp);
|
||||
}
|
||||
//Add CRC
|
||||
if(LT8910_Flags&_BV(LT8910_CRC_ON))
|
||||
{
|
||||
buffer[pos++]=crc>>8;
|
||||
buffer[pos++]=crc;
|
||||
}
|
||||
//Shift everything to fit behind the trailer (4 to 18 bits)
|
||||
shift=LT8910_buffer_overhead_bits&0x7;
|
||||
pos_final=LT8910_buffer_overhead_bits/8;
|
||||
mask=~(0xFF<<(8-shift));
|
||||
LT8910_buffer[pos_final+pos]=0xFF;
|
||||
for(i=pos-1;i!=0xFF;i--)
|
||||
{
|
||||
a=buffer[i]<<(8-shift);
|
||||
LT8910_buffer[pos_final+i]=(LT8910_buffer[pos_final+i]&mask>>8)|a>>8;
|
||||
LT8910_buffer[pos_final+i+1]=(LT8910_buffer[pos_final+i+1]&mask)|a;
|
||||
}
|
||||
if(shift)
|
||||
pos++;
|
||||
//Send everything
|
||||
NRF24L01_WritePayload(LT8910_buffer+LT8910_buffer_start,pos_final+pos-LT8910_buffer_start);
|
||||
}
|
||||
// End of LT8910 emulation
|
||||
|
183
Multiprotocol/Nrf24l01_bluefly.ino
Normal file
183
Multiprotocol/Nrf24l01_bluefly.ino
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(BlueFly_NRF24L01_INO)
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define BIND_BlueFly_COUNT 800
|
||||
|
||||
#define TXID_BlueFly_SIZE 5
|
||||
|
||||
#define PAYLOAD_BlueFly_SIZE 12
|
||||
// available frequency must be in between 2402 and 2477
|
||||
static uint8_t hopping_frequency_start;
|
||||
|
||||
static uint8_t bluefly_binding_adr_rf[TXID_BlueFly_SIZE]={0x32,0xaa,0x45,0x45,0x78}; // fixed binding ids for all planes
|
||||
// bluefly_rf_adr_buf can be used for fixed id
|
||||
static uint8_t bluefly_rf_adr_buf[TXID_BlueFly_SIZE]; // ={0x13,0x88,0x46,0x57,0x76};
|
||||
|
||||
static uint8_t bind_payload[PAYLOAD_BlueFly_SIZE];
|
||||
|
||||
static unsigned int ch_data_bluefly[8];
|
||||
|
||||
|
||||
static void bluefly_binding_packet(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TXID_BlueFly_SIZE; ++i)
|
||||
bind_payload[i] = bluefly_rf_adr_buf[i];
|
||||
bind_payload[i++] = hopping_frequency_start;
|
||||
for (; i < PAYLOAD_BlueFly_SIZE; ++i) bind_payload[i] = 0x55;
|
||||
}
|
||||
|
||||
static void bluefly_init() {
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable p0 rx
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bluefly_rf_adr_buf, 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, bluefly_rf_adr_buf, 5);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, PAYLOAD_BlueFly_SIZE); // payload size = 12
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81); // binding packet must be set in channel 81
|
||||
|
||||
// 2-bytes CRC, radio on
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // BlueFly - 250kbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
}
|
||||
|
||||
// HiSky channel sequence: AILE ELEV THRO RUDD GEAR PITCH, channel data value is from 0 to 1000
|
||||
static void bluefly_ch_data() {
|
||||
uint32_t temp;
|
||||
int i;
|
||||
for (i = 0; i< 8; ++i) {
|
||||
temp = (uint32_t)Servo_data[ch[i]] * 300/PPM_MAX + 500; // 200-800 range
|
||||
if (temp < 0)
|
||||
ch_data_bluefly[i] = 0;
|
||||
else if (temp > 1000)
|
||||
ch_data_bluefly[i] = 1000;
|
||||
else
|
||||
ch_data_bluefly[i] = (unsigned int)temp;
|
||||
|
||||
packet[i] = (uint8_t)ch_data_bluefly[i];
|
||||
}
|
||||
|
||||
packet[8] = (uint8_t)((ch_data_bluefly[0]>>8)&0x0003);
|
||||
packet[8] |= (uint8_t)((ch_data_bluefly[1]>>6)&0x000c);
|
||||
packet[8] |= (uint8_t)((ch_data_bluefly[2]>>4)&0x0030);
|
||||
packet[8] |= (uint8_t)((ch_data_bluefly[3]>>2)&0x00c0);
|
||||
|
||||
packet[9] = (uint8_t)((ch_data_bluefly[4]>>8)&0x0003);
|
||||
packet[9] |= (uint8_t)((ch_data_bluefly[5]>>6)&0x000c);
|
||||
packet[9] |= (uint8_t)((ch_data_bluefly[6]>>4)&0x0030);
|
||||
packet[9] |= (uint8_t)((ch_data_bluefly[7]>>2)&0x00c0);
|
||||
|
||||
unsigned char l, h, t;
|
||||
l = h = 0xff;
|
||||
for (int i=0; i<10; ++i) {
|
||||
h ^= packet[i];
|
||||
h ^= h >> 4;
|
||||
t = h;
|
||||
h = l;
|
||||
l = t;
|
||||
t = (l<<4) | (l>>4);
|
||||
h ^= ((t<<2) | (t>>6)) & 0x1f;
|
||||
h ^= t & 0xf0;
|
||||
l ^= ((t<<1) | (t>>7)) & 0xe0;
|
||||
}
|
||||
// Checksum
|
||||
packet[10] = h;
|
||||
packet[11] = l;
|
||||
}
|
||||
|
||||
static uint16_t bluefly_cb() {
|
||||
switch(phase++) {
|
||||
case 0:
|
||||
bluefly_ch_data();
|
||||
break;
|
||||
case 1:
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bluefly_rf_adr_buf, 5);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_start + hopping_frequency_no*2);
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no %= 15;
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, PAYLOAD_BlueFly_SIZE);
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
if (counter>0) {
|
||||
counter--;
|
||||
if (! counter) { BIND_DONE; }
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bluefly_binding_adr_rf, 5);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(bind_payload, PAYLOAD_BlueFly_SIZE);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
NRF24L01_SetPower();
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
phase = 0;
|
||||
break;
|
||||
}
|
||||
return 1000; // send 1 binding packet and 1 data packet per 9ms
|
||||
}
|
||||
|
||||
// Generate internal id from TX id and manufacturer id (STM32 unique id)
|
||||
static void initialize_tx_id() {
|
||||
uint32_t lfsr = 0x7649eca9ul;
|
||||
|
||||
if (Model.fixed_id) {
|
||||
for (uint8_t i = 0, j = 0; i < sizeof(Model.fixed_id); ++i, j += 8)
|
||||
rand32_r(&lfsr, (Model.fixed_id >> j) & 0xff);
|
||||
}
|
||||
// Pump zero bytes for LFSR to diverge more
|
||||
for (int i = 0; i < TXID_BlueFly_SIZE; ++i) rand32_r(&lfsr, 0);
|
||||
|
||||
for (uint8_t i = 0; i < TXID_BlueFly_SIZE; ++i) {
|
||||
bluefly_rf_adr_buf[i] = lfsr & 0xff;
|
||||
rand32_r(&lfsr, i);
|
||||
}
|
||||
|
||||
printf("Effective id: %02X%02X%02X%02X%02X\r\n", bluefly_rf_adr_buf[0], bluefly_rf_adr_buf[1], bluefly_rf_adr_buf[2], bluefly_rf_adr_buf[3], bluefly_rf_adr_buf[4]);
|
||||
|
||||
// Use LFSR to seed frequency hopping sequence after another
|
||||
// divergence round
|
||||
for (uint8_t i = 0; i < sizeof(lfsr); ++i) rand32_r(&lfsr, 0);
|
||||
hopping_frequency_start = ((lfsr >> 8) % 47) + 2;
|
||||
bluefly_binding_packet();
|
||||
}
|
||||
|
||||
static uint16_t BlueFly_setup() {
|
||||
initialize_tx_id();
|
||||
|
||||
bluefly_init();
|
||||
|
||||
if(IS_AUTOBIND_FLAG_on) {
|
||||
counter = BIND_BlueFly_COUNT;
|
||||
// PROTOCOL_SetBindState(BIND_BlueFly_COUNT * 10); //8 seconds binding time
|
||||
} else {
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
return 1000;
|
||||
}
|
||||
#endif
|
172
Multiprotocol/Nrf24l01_esky150.ino
Normal file
172
Multiprotocol/Nrf24l01_esky150.ino
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(ESKY150_NRF24L01_INO)
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
|
||||
// Timeout for callback in uSec, 4.8ms=4800us for ESky150
|
||||
#define ESKY150_PERIOD 4800
|
||||
#define ESKY150_CHKTIME 100 // Time to wait for packet to be sent (no ACK, so very short)
|
||||
|
||||
#define esky150_PAYLOADSIZE 15
|
||||
#define ADDR_esky150_SIZE 4
|
||||
|
||||
static uint32_t total_packets;
|
||||
enum {
|
||||
ESKY150_INIT2 = 0,
|
||||
ESKY150_DATA
|
||||
};
|
||||
|
||||
|
||||
static uint8_t esky150_packet_ack() {
|
||||
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) {
|
||||
case BV(NRF24L01_07_TX_DS): return PKT_ACKED;
|
||||
case BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT;
|
||||
}
|
||||
return PKT_PENDING;
|
||||
}
|
||||
|
||||
// 2-bytes CRC
|
||||
#define CRC_CONFIG (BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO))
|
||||
static uint16_t esky150_init() {
|
||||
uint8_t rx_addr[ADDR_esky150_SIZE] = { 0x73, 0x73, 0x74, 0x63 };
|
||||
uint8_t tx_addr[ADDR_esky150_SIZE] = { 0x71, 0x0A, 0x31, 0xF4 };
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, CRC_CONFIG);
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, ADDR_esky150_SIZE-2); // 4-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // Disable retransmit
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_2M);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_addr, ADDR_esky150_SIZE);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, tx_addr, ADDR_esky150_SIZE);
|
||||
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, esky150_PAYLOADSIZE); // bytes of data payload for pipe 0
|
||||
|
||||
|
||||
NRF24L01_Activate(0x73);
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
|
||||
// Enable: Dynamic Payload Length, Payload with ACK , W_TX_PAYLOAD_NOACK
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, BV(NRF2401_1D_EN_DPL) | BV(NRF2401_1D_EN_ACK_PAY) | BV(NRF2401_1D_EN_DYN_ACK));
|
||||
|
||||
// Delay 50 ms
|
||||
return 50000;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t esky150_init2() {
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
packet_sent = 0;
|
||||
packet_count = 0;
|
||||
rf_ch_num = 0;
|
||||
|
||||
// Turn radio power on
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, CRC_CONFIG | BV(NRF24L01_00_PWR_UP));
|
||||
// delayMicroseconds(150);
|
||||
return 150;
|
||||
}
|
||||
|
||||
|
||||
static void calc_fh_channels(uint32_t seed) {
|
||||
// Use channels 2..79
|
||||
uint8_t first = seed % 37 + 2;
|
||||
uint8_t second = first + 40;
|
||||
hopping_frequency[0] = first; // 0x22;
|
||||
hopping_frequency[1] = second; // 0x4a;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t convert_channel(uint8_t num) {
|
||||
uint32_t ch = Servo_data[num];
|
||||
if (ch < PPM_MIN) { ch = PPM_MIN; }
|
||||
else if (ch > PPM_MAX) { ch = PPM_MAX; }
|
||||
return (uint8_t) ((ch * 500 / PPM_MAX) + 1500);
|
||||
}
|
||||
static void read_controls(uint8_t* throttle, uint8_t* aileron, uint8_t* elevator, uint8_t* rudder) {
|
||||
*throttle = convert_channel(THROTTLE);
|
||||
*aileron = convert_channel(AILERON);
|
||||
*elevator = convert_channel(ELEVATOR);
|
||||
*rudder = convert_channel(RUDDER);
|
||||
}
|
||||
|
||||
|
||||
static void esky150_send_packet() {
|
||||
uint8_t rf_ch = hopping_frequency[rf_ch_num];
|
||||
rf_ch_num = 1 - rf_ch_num;
|
||||
|
||||
read_controls(&throttle, &aileron, &elevator, &rudder);
|
||||
|
||||
packet[0] = hopping_frequency[0];
|
||||
packet[1] = hopping_frequency[1];
|
||||
packet[2] = (throttle >> 8) & 0xFF;
|
||||
packet[3] = throttle & 0xFF;
|
||||
packet[4] = (aileron >> 8) & 0xFF;
|
||||
packet[5] = aileron & 0xFF;
|
||||
packet[6] = (elevator >> 8) & 0xFF;
|
||||
packet[7] = elevator & 0xFF;
|
||||
packet[8] = (rudder >> 8) & 0xFF;
|
||||
packet[9] = rudder & 0xFF;
|
||||
// Constant values 00 d8 18 f8
|
||||
packet[10] = 0x00;
|
||||
packet[11] = 0xd8;
|
||||
packet[12] = 0x18;
|
||||
packet[13] = 0xf8;
|
||||
uint8_t sum = 0;
|
||||
for (int i = 0; i < 14; ++i) sum += packet[i];
|
||||
packet[14] = sum;
|
||||
|
||||
packet_sent = 0;
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, sizeof(packet));
|
||||
++total_packets;
|
||||
packet_sent = 1;
|
||||
}
|
||||
|
||||
static uint16_t esky150_callback() {
|
||||
uint16_t timeout = ESKY150_PERIOD;
|
||||
switch (phase) {
|
||||
case ESKY150_INIT2:
|
||||
timeout = esky150_init2();
|
||||
phase = ESKY150_DATA;
|
||||
break;
|
||||
case ESKY150_DATA:
|
||||
if (packet_count == 4)
|
||||
packet_count = 0;
|
||||
else {
|
||||
if (packet_sent && esky150_packet_ack() != PKT_ACKED) {
|
||||
return ESKY150_CHKTIME;
|
||||
}
|
||||
esky150_send_packet();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return timeout;
|
||||
}
|
||||
|
||||
static uint16_t esky150_setup() {
|
||||
total_packets = 0;
|
||||
uint16_t timeout = esky150_init();
|
||||
|
||||
return timeout;
|
||||
}
|
||||
#endif
|
@ -75,14 +75,14 @@ static void send_packet(uint8_t bind)
|
||||
| GET_FLAG(CHANNEL_CALIBRATE, 0x01)
|
||||
| GET_FLAG(CHANNEL_EXPERT, 4);
|
||||
}
|
||||
packet[2] = 200 - scale_channel(AILERON, 0, 200); // aileron
|
||||
packet[3] = scale_channel(ELEVATOR, 0, 200); // elevator
|
||||
packet[4] = 200 - scale_channel(RUDDER, 0, 200); // rudder
|
||||
packet[5] = scale_channel(THROTTLE, 0, 200); // throttle
|
||||
packet[2] = 200 - scale_channel(AILERON, 0, 200); // aileron 1
|
||||
packet[3] = scale_channel(ELEVATOR, 0, 200); // elevator 2
|
||||
packet[4] = 200 - scale_channel(RUDDER, 0, 200); // rudder 4
|
||||
packet[5] = scale_channel(THROTTLE, 0, 200); // throttle 3
|
||||
if(sub_protocol == FY319) {
|
||||
packet[6] = 255 - scale_channel(CHANNEL1, 0, 255);
|
||||
packet[7] = scale_channel(CHANNEL2, 0, 255);
|
||||
packet[8] = 255 - scale_channel(CHANNEL4, 0, 255);
|
||||
packet[6] = 255 - scale_channel(AILERON, 0, 255);
|
||||
packet[7] = scale_channel(ELEVATOR, 0, 255);
|
||||
packet[8] = 255 - scale_channel(RUDDER, 0, 255);
|
||||
}
|
||||
else {
|
||||
packet[6] = txid[0];
|
||||
@ -148,7 +148,7 @@ static uint16_t fy326_callback()
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_BIND_CHANNEL);
|
||||
phase = FY319_BIND1;
|
||||
BIND_IN_PROGRESS;
|
||||
return PACKET_CHKTIME;
|
||||
return FY326_CHKTIME;
|
||||
break;
|
||||
|
||||
case FY319_BIND1:
|
||||
@ -158,7 +158,7 @@ static uint16_t fy326_callback()
|
||||
packet[0] = txid[3];
|
||||
packet[1] = 0x80;
|
||||
packet[14]= txid[4];
|
||||
bind_counter = BIND_COUNT;
|
||||
bind_counter = FY326_BIND_COUNT;
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
@ -168,7 +168,7 @@ static uint16_t fy326_callback()
|
||||
packet[i] = rf_chans[0];
|
||||
phase = FY319_BIND2;
|
||||
}
|
||||
return PACKET_CHKTIME;
|
||||
return FY326_CHKTIME;
|
||||
break;
|
||||
|
||||
case FY319_BIND2:
|
||||
@ -264,3 +264,4 @@ static uint16_t FY326_setup()
|
||||
return INITIAL_WAIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
272
Multiprotocol/Nrf24l01_hontai.ino
Normal file
272
Multiprotocol/Nrf24l01_hontai.ino
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#if defined(HonTai_NRF24L01_INO)
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define BIND_HT_COUNT 80
|
||||
#define PACKET_HT_PERIOD 13500 // Timeout for callback in uSec
|
||||
//printf inside an interrupt handler is really dangerous
|
||||
//this shouldn't be enabled even in debug builds without explicitly
|
||||
//turning it on
|
||||
#define dbgprintf if(0) printf
|
||||
|
||||
#define INITIAL_HT_WAIT 500
|
||||
#define BIND_HT_PACKET_SIZE 10
|
||||
#define PACKET_HT_SIZE 12
|
||||
#define RF_BIND_HT_CHANNEL 0
|
||||
|
||||
enum {
|
||||
FORMAT_HONTAI = 0,
|
||||
FORMAT_JJRCX1,
|
||||
};
|
||||
|
||||
|
||||
#define CHANNEL_LED AUX1
|
||||
#define CHANNEL_ARM AUX1 // for JJRC X1
|
||||
#define CHANNEL_FLIP AUX2
|
||||
#define CHANNEL_PICTURE AUX3
|
||||
#define CHANNEL_VIDEO AUX4
|
||||
#define CHANNEL_HEADLESS AUX5
|
||||
#define CHANNEL_RTH AUX6
|
||||
#define CHANNEL_CALIBRATE AUX7
|
||||
|
||||
enum {
|
||||
HonTai_INIT1 = 0,
|
||||
HonTai_BIND2,
|
||||
HonTai_DATA
|
||||
};
|
||||
|
||||
static uint8_t ht_txid[5];
|
||||
|
||||
static uint8_t rf_chan = 0;
|
||||
static uint8_t rf_channels[][3] = {{0x05, 0x19, 0x28}, // Hontai
|
||||
{0x0a, 0x1e, 0x2d}}; // JJRC X1
|
||||
static uint8_t rx_tx_ht_addr[] = {0xd2, 0xb5, 0x99, 0xb3, 0x4a};
|
||||
static uint8_t addr_vals[4][16] = {
|
||||
{0x24, 0x26, 0x2a, 0x2c, 0x32, 0x34, 0x36, 0x4a, 0x4c, 0x4e, 0x54, 0x56, 0x5a, 0x64, 0x66, 0x6a},
|
||||
{0x92, 0x94, 0x96, 0x9a, 0xa4, 0xa6, 0xac, 0xb2, 0xb4, 0xb6, 0xca, 0xcc, 0xd2, 0xd4, 0xd6, 0xda},
|
||||
{0x93, 0x95, 0x99, 0x9b, 0xa5, 0xa9, 0xab, 0xad, 0xb3, 0xb5, 0xc9, 0xcb, 0xcd, 0xd3, 0xd5, 0xd9},
|
||||
{0x25, 0x29, 0x2b, 0x2d, 0x33, 0x35, 0x49, 0x4b, 0x4d, 0x59, 0x5b, 0x65, 0x69, 0x6b, 0x6d, 0x6e}};
|
||||
|
||||
// proudly swiped from http://www.drdobbs.com/implementing-the-ccitt-cyclical-redundan/199904926
|
||||
#define POLY 0x8408
|
||||
static uint16_t crc16(uint8_t *data_p, uint32_t length)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t data;
|
||||
uint32_t crc;
|
||||
|
||||
crc = 0xffff;
|
||||
|
||||
if (length == 0) return (~crc);
|
||||
|
||||
length -= 2;
|
||||
do {
|
||||
for (i = 0, data = (uint8_t)0xff & *data_p++;
|
||||
i < 8;
|
||||
i++, data >>= 1) {
|
||||
if ((crc & 0x0001) ^ (data & 0x0001))
|
||||
crc = (crc >> 1) ^ POLY;
|
||||
else
|
||||
crc >>= 1;
|
||||
}
|
||||
} while (--length);
|
||||
|
||||
crc = ~crc;
|
||||
data = crc;
|
||||
crc = (crc << 8) | (data >> 8 & 0xFF);
|
||||
*data_p++ = crc >> 8;
|
||||
*data_p = crc & 0xff;
|
||||
return crc;
|
||||
}
|
||||
|
||||
#define CHAN_RANGE (PPM_MAX - PPM_MIN)
|
||||
static uint8_t scale_HT_channel(uint8_t ch, uint8_t start, uint8_t end)
|
||||
{
|
||||
uint32_t range = end - start;
|
||||
uint32_t chanval = Servo_data[ch];
|
||||
|
||||
if (chanval < PPM_MIN) chanval = PPM_MIN;
|
||||
else if (chanval > PPM_MAX) chanval = PPM_MAX;
|
||||
|
||||
uint32_t round = range < 0 ? 0 : CHAN_RANGE / range; // channels round up
|
||||
if (start < 0) round = CHAN_RANGE / range / 2; // trims zero centered around zero
|
||||
return (range * (chanval - PPM_MIN + round)) / CHAN_RANGE + start;
|
||||
}
|
||||
|
||||
#define GET_FLAG(ch, mask) (Servo_data[ch] > 0 ? mask : 0)
|
||||
static void send_HT_packet(uint8_t bind)
|
||||
{
|
||||
if (bind) {
|
||||
memcpy(packet, ht_txid, 5);
|
||||
memset(&packet[5], 0, 3);
|
||||
} else {
|
||||
if (sub_protocol == FORMAT_HONTAI) {
|
||||
packet[0] = 0x0b;
|
||||
} else {
|
||||
packet[0] = GET_FLAG(CHANNEL_ARM, 0x02);
|
||||
}
|
||||
packet[1] = 0x00;
|
||||
packet[2] = 0x00;
|
||||
packet[3] = (scale_HT_channel(THROTTLE, 0, 127) << 1) // throttle
|
||||
| GET_FLAG(CHANNEL_PICTURE, 0x01);
|
||||
packet[4] = scale_HT_channel(AILERON, 63, 0); // aileron
|
||||
if (sub_protocol == FORMAT_HONTAI) {
|
||||
packet[4] |= GET_FLAG(CHANNEL_RTH, 0x80)
|
||||
| GET_FLAG(CHANNEL_HEADLESS, 0x40);
|
||||
} else {
|
||||
packet[4] |= 0x80; // not sure what this bit does
|
||||
}
|
||||
packet[5] = scale_channel(CHANNEL2, 0, 63) // elevator
|
||||
| GET_FLAG(CHANNEL_CALIBRATE, 0x80)
|
||||
| GET_FLAG(CHANNEL_FLIP, 0x40);
|
||||
packet[6] = scale_HT_channel(RUDDER, 0, 63) // rudder
|
||||
| GET_FLAG(CHANNEL_VIDEO, 0x80);
|
||||
packet[7] = scale_HT_channel(AILERON, -16, 16); // aileron trim
|
||||
if (sub_protocol == FORMAT_HONTAI) {
|
||||
packet[8] = scale_HT_channel(RUDDER, -16, 16); // rudder trim
|
||||
} else {
|
||||
packet[8] = 0xc0 // always in expert mode
|
||||
| GET_FLAG(CHANNEL_RTH, 0x02)
|
||||
| GET_FLAG(CHANNEL_HEADLESS, 0x01);
|
||||
}
|
||||
packet[9] = scale_HT_channel(ELEVATOR, -16, 16); // elevator trim
|
||||
}
|
||||
crc16(packet, bind ? BIND_HT_PACKET_SIZE : PACKET_HT_SIZE);
|
||||
|
||||
// Power on, TX mode, 2byte CRC
|
||||
if (sub_protocol == FORMAT_HONTAI) {
|
||||
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
|
||||
} else {
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
}
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? RF_BIND_HT_CHANNEL : rf_channels[sub_protocol][rf_chan++]);
|
||||
rf_chan %= sizeof(rf_channels);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
|
||||
if (sub_protocol == FORMAT_HONTAI) {
|
||||
XN297_WritePayload(packet, bind ? BIND_HT_PACKET_SIZE : PACKET_HT_SIZE);
|
||||
} else {
|
||||
NRF24L01_WritePayload(packet, bind ? BIND_HT_PACKET_SIZE : PACKET_HT_SIZE);
|
||||
}
|
||||
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void ht_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
// SPI trace of stock TX has these writes to registers that don't appear in
|
||||
// nRF24L01 or Beken 2421 datasheets. Uncomment if you have an XN297 chip?
|
||||
// NRF24L01_WriteRegisterMulti(0x3f, "\x4c\x84\x67,\x9c,\x20", 5);
|
||||
// NRF24L01_WriteRegisterMulti(0x3e, "\xc9\x9a\xb0,\x61,\xbb,\xab,\x9c", 7);
|
||||
// NRF24L01_WriteRegisterMulti(0x39, "\x0b\xdf\xc4,\xa7,\x03,\xab,\x9c", 7);
|
||||
|
||||
if (sub_protocol == FORMAT_HONTAI) {
|
||||
XN297_SetTXAddr(rx_tx_ht_addr, sizeof(rx_tx_ht_addr));
|
||||
} else {
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_ht_addr, sizeof(rx_tx_ht_addr));
|
||||
}
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
if (sub_protocol == FORMAT_HONTAI) {
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00);
|
||||
NRF24L01_Activate(0x73); // Deactivate feature register
|
||||
} else {
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xff); // JJRC uses dynamic payload length
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // match other stock settings even though AA disabled...
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
|
||||
}
|
||||
}
|
||||
|
||||
static void ht_init2()
|
||||
{
|
||||
uint8_t data_tx_addr[] = {0x2a, 0xda, 0xa5, 0x25, 0x24};
|
||||
|
||||
data_tx_addr[0] = addr_vals[0][ ht_txid[3] & 0x0f];
|
||||
data_tx_addr[1] = addr_vals[1][(ht_txid[3] >> 4) & 0x0f];
|
||||
data_tx_addr[2] = addr_vals[2][ ht_txid[4] & 0x0f];
|
||||
data_tx_addr[3] = addr_vals[3][(ht_txid[4] >> 4) & 0x0f];
|
||||
|
||||
if (sub_protocol == FORMAT_HONTAI) {
|
||||
XN297_SetTXAddr(data_tx_addr, sizeof(data_tx_addr));
|
||||
} else {
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, data_tx_addr, sizeof(data_tx_addr));
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t ht_callback()
|
||||
{
|
||||
switch (phase) {
|
||||
case HonTai_INIT1:
|
||||
phase = HonTai_BIND2;
|
||||
break;
|
||||
case HonTai_BIND2:
|
||||
if (counter == 0) {
|
||||
ht_init2();
|
||||
phase = HonTai_DATA;
|
||||
BIND_DONE;
|
||||
} else {
|
||||
send_HT_packet(1);
|
||||
counter -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case HonTai_DATA:
|
||||
send_HT_packet(0);
|
||||
break;
|
||||
}
|
||||
return PACKET_HT_PERIOD;
|
||||
}
|
||||
|
||||
static uint16_t ht_setup()
|
||||
{
|
||||
counter = BIND_HT_COUNT;
|
||||
|
||||
if (sub_protocol == FORMAT_HONTAI) {
|
||||
ht_txid[0] = 0x4c; // first three bytes some kind of model id? - set same as stock tx
|
||||
ht_txid[1] = 0x4b;
|
||||
ht_txid[2] = 0x3a;
|
||||
} else {
|
||||
ht_txid[0] = 0x4b; // JJRC X1
|
||||
ht_txid[1] = 0x59;
|
||||
ht_txid[2] = 0x3a;
|
||||
}
|
||||
ht_txid[3] = (MProtocol_id >> 8 ) & 0xff;
|
||||
ht_txid[4] = MProtocol_id & 0xff;
|
||||
|
||||
ht_init();
|
||||
phase = HonTai_INIT1;
|
||||
|
||||
return INITIAL_HT_WAIT;
|
||||
}
|
||||
#endif
|
||||
|
274
Multiprotocol/Nrf24l01_ne260.ino
Normal file
274
Multiprotocol/Nrf24l01_ne260.ino
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* This code is based upon code from:
|
||||
http://www.rcgroups.com/forums/showthread.php?t=1564343
|
||||
Author : Ferenc Szili (kile at the rcgroups.net forum)
|
||||
*/
|
||||
|
||||
|
||||
#if defined(NE260_NRF24L01_INO)
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
///////////////////////
|
||||
// register bits
|
||||
///////////////////////
|
||||
|
||||
// CONFIG
|
||||
#define MASK_RX_DR 6
|
||||
#define MASK_TX_DS 5
|
||||
#define MASK_MAX_RT 4
|
||||
#define EN_CRC 3
|
||||
#define CRCO 2
|
||||
#define PWR_UP 1
|
||||
#define PRIM_RX 0
|
||||
|
||||
// EN_AA
|
||||
#define ENAA_P5 5
|
||||
#define ENAA_P4 4
|
||||
#define ENAA_P3 3
|
||||
#define ENAA_P2 2
|
||||
#define ENAA_P1 1
|
||||
#define ENAA_P0 0
|
||||
|
||||
// EN_RXADDR
|
||||
#define ERX_P5 5
|
||||
#define ERX_P4 4
|
||||
#define ERX_P3 3
|
||||
#define ERX_P2 2
|
||||
#define ERX_P1 1
|
||||
#define ERX_P0 0
|
||||
|
||||
// RF_SETUP
|
||||
#define CONT_WAVE 7
|
||||
#define RF_DR_LOW 5
|
||||
#define PLL_LOCK 4
|
||||
#define RF_DR_HIGH 3
|
||||
#define RF_PWR_HIGH 2
|
||||
#define RF_PWR_LOW 1
|
||||
#define LNA_HCURR 0 // obsolete in nRF24L01+
|
||||
|
||||
// STATUS
|
||||
#define RX_DR 6
|
||||
#define TX_DS 5
|
||||
#define MAX_RT 4
|
||||
#define TX_FULL 0
|
||||
|
||||
// FIFO_STATUS
|
||||
#define TX_REUSE 6
|
||||
#define FIFO_TX_FULL 5
|
||||
#define TX_EMPTY 4
|
||||
#define RX_FULL 1
|
||||
#define RX_EMPTY 0
|
||||
|
||||
///////////////////////
|
||||
// register bit values
|
||||
///////////////////////
|
||||
|
||||
// CONFIG
|
||||
#define vMASK_RX_DR (1<<(MASK_RX_DR))
|
||||
#define vMASK_TX_DS (1<<(MASK_TX_DS))
|
||||
#define vMASK_MAX_RT (1<<(MASK_MAX_RT))
|
||||
#define vEN_CRC (1<<(EN_CRC))
|
||||
#define vCRCO (1<<(CRCO))
|
||||
#define vPWR_UP (1<<(PWR_UP))
|
||||
#define vPRIM_RX (1<<(PRIM_RX))
|
||||
|
||||
// EN_AA
|
||||
#define vENAA_P5 (1<<(ENAA_P5))
|
||||
#define vENAA_P4 (1<<(ENAA_P4))
|
||||
#define vENAA_P3 (1<<(ENAA_P3))
|
||||
#define vENAA_P2 (1<<(ENAA_P2))
|
||||
#define vENAA_P1 (1<<(ENAA_P1))
|
||||
#define vENAA_P0 (1<<(ENAA_P0))
|
||||
|
||||
// EN_RXADDR
|
||||
#define vERX_P5 (1<<(ERX_P5))
|
||||
#define vERX_P4 (1<<(ERX_P4))
|
||||
#define vERX_P3 (1<<(ERX_P3))
|
||||
#define vERX_P2 (1<<(ERX_P2))
|
||||
#define vERX_P1 (1<<(ERX_P1))
|
||||
#define vERX_P0 (1<<(ERX_P0))
|
||||
|
||||
// SETUP_AW -- address widths in bytes
|
||||
#define vAW_3 1
|
||||
#define vAW_4 2
|
||||
#define vAW_5 3
|
||||
|
||||
// RF_SETUP
|
||||
#define vCONT_WAVE (1<<(CONT_WAVE))
|
||||
#define vRF_DR_LOW (1<<(RF_DR_LOW))
|
||||
#define vPLL_LOCK (1<<(PLL_LOCK))
|
||||
#define vRF_DR_HIGH (1<<(RF_DR_HIGH))
|
||||
#define vRF_PWR_HIGH (1<<(RF_PWR_HIGH))
|
||||
#define vRF_PWR_LOW (1<<(RF_PWR_LOW))
|
||||
#define vLNA_HCURR (1<<(LNA_HCURR)) // obsolete in nRF24L01+
|
||||
|
||||
#define vRF_DR_1MBPS 0
|
||||
#define vRF_DR_2MBPS (1<<(RF_DR_HIGH))
|
||||
#define vRF_DR_250KBPS (1<<(RF_DR_LOW))
|
||||
|
||||
#define vRF_PWR_M18DBM 0x00
|
||||
#define vRF_PWR_M12DBM 0x02
|
||||
#define vRF_PWR_M6DBM 0x04
|
||||
#define vRF_PWR_0DBM 0x06
|
||||
|
||||
#define vARD_250us 0x00
|
||||
#define vARD_500us 0x10
|
||||
#define vARD_750us 0x20
|
||||
#define vARD_1000us 0x30
|
||||
#define vARD_1250us 0x40
|
||||
#define vARD_1500us 0x50
|
||||
#define vARD_1750us 0x60
|
||||
#define vARD_2000us 0x70
|
||||
#define vARD_2250us 0x80
|
||||
#define vARD_2500us 0x90
|
||||
#define vARD_2750us 0xA0
|
||||
#define vARD_3000us 0xB0
|
||||
#define vARD_3250us 0xC0
|
||||
#define vARD_3500us 0xD0
|
||||
#define vARD_3750us 0xE0
|
||||
#define vARD_4000us 0xF0
|
||||
|
||||
// STATUS
|
||||
#define vRX_DR (1<<(RX_DR))
|
||||
#define vTX_DS (1<<(TX_DS))
|
||||
#define vMAX_RT (1<<(MAX_RT))
|
||||
#define vTX_FULL (1<<(TX_FULL))
|
||||
|
||||
#define RX_P_NO(stat) ((stat >> 1) & 7)
|
||||
#define HAS_RX_PAYLOAD(stat) ((stat & 0b1110) < 0b1100)
|
||||
|
||||
// FIFO_STATUS
|
||||
#define vTX_REUSE (1<<(TX_REUSE))
|
||||
#define vTX_FULL (1<<(TX_FULL))
|
||||
#define vTX_EMPTY (1<<(TX_EMPTY))
|
||||
#define vRX_FULL (1<<(RX_FULL))
|
||||
#define vRX_EMPTY (1<<(RX_EMPTY))
|
||||
////////////////////////////////////////////////////////////
|
||||
uint8_t neChannel = 10;
|
||||
uint8_t neChannelOffset = 0;
|
||||
#define PACKET_NE_LENGTH 7
|
||||
|
||||
static u32 bind_count;
|
||||
static uint16_t model_id = 0xA04A;
|
||||
|
||||
uint8_t NE_ch[]={THROTTLE, RUDDER, ELEVATOR, AILERON, AUX1};
|
||||
uint8_t NEAddr[] = {0x34, 0x43, 0x10, 0x10, 0x01};
|
||||
enum {
|
||||
NE260_BINDTX,
|
||||
NE260_BINDRX,
|
||||
NE260_DATA1,
|
||||
NE260_DATA2,
|
||||
NE260_DATA3,
|
||||
};
|
||||
|
||||
|
||||
static void ne260_init() {
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, NEAddr, 5); // write the address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, NEAddr, 5);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, vENAA_P0); // enable auto acknoledge
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, vARD_500us); // ARD=500us, ARC=disabled
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, vRF_DR_250KBPS | vLNA_HCURR | vRF_PWR_0DBM); // data rate, output power and noise cancel
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, PACKET_NE_LENGTH); // RX payload length
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, vERX_P0); // enable RX address
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, vRX_DR | vTX_DS | vMAX_RT); // reset the IRQ flags
|
||||
}
|
||||
|
||||
static void send_data_packet() {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
uint32_t value = (uint32_t)Servo_data[NE_ch[i]] * 0x40 / PPM_MAX + 0x40;
|
||||
if (value > 0x7f)
|
||||
value = 0x7f;
|
||||
else if(value < 0)
|
||||
value = 0;
|
||||
packet[i] = value;
|
||||
}
|
||||
packet[4] = 0x55;
|
||||
packet[5] = model_id & 0xff;
|
||||
packet[6] = (model_id >> 8) & 0xff;
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, vMAX_RT);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, neChannel + neChannelOffset);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, vEN_CRC | vCRCO | vPWR_UP);
|
||||
// send a fresh packet to the nRF
|
||||
NRF24L01_WritePayload((uint8_t*) packet, PACKET_NE_LENGTH);
|
||||
}
|
||||
|
||||
static void send_bind_packet() {
|
||||
packet[0] = 0xAA; //throttle
|
||||
packet[1] = 0xAA; //rudder
|
||||
packet[2] = 0xAA; //elevator
|
||||
packet[3] = 0xAA; //aileron
|
||||
packet[4] = 0xAA; //command
|
||||
packet[5] = model_id & 0xff;
|
||||
packet[6] = (model_id >> 8) & 0xff;
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, vRX_DR | vTX_DS | vMAX_RT); // reset the status flags
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, neChannel + neChannelOffset);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload((uint8_t*) &packet, PACKET_NE_LENGTH); // send the bind packet
|
||||
}
|
||||
|
||||
static uint16_t ne260_cb() {
|
||||
if (state == NE260_BINDTX) {
|
||||
// do we have a packet?
|
||||
if ((NRF24L01_ReadReg(NRF24L01_07_STATUS) & vRX_DR) != 0) {
|
||||
// read the packet contents
|
||||
NRF24L01_ReadPayload(packet, PACKET_NE_LENGTH);
|
||||
|
||||
// is this the bind response packet?
|
||||
if (strncmp("\x55\x55\x55\x55\x55", (char*) (packet + 1), 5) == 0 && *((uint16_t*)(packet + 6)) == model_id) {
|
||||
// exit the bind loop
|
||||
state = NE260_DATA1;
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
return 2000;
|
||||
}
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
send_bind_packet();
|
||||
state = NE260_BINDRX;
|
||||
return 500;
|
||||
} else if (state == NE260_BINDRX) {
|
||||
// switch to RX mode
|
||||
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & (vMAX_RT | vTX_DS))) ;
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, vTX_DS);
|
||||
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
state = NE260_BINDTX;
|
||||
return 2000;
|
||||
}
|
||||
else if (state == NE260_DATA1) { neChannel = 10; state = NE260_DATA2; }
|
||||
else if (state == NE260_DATA2) { neChannel = 30; state = NE260_DATA3; }
|
||||
else if (state == NE260_DATA3) { neChannel = 50; state = NE260_DATA1; }
|
||||
send_data_packet();
|
||||
return 2500;
|
||||
}
|
||||
|
||||
static uint16_t NE260_setup() {
|
||||
ne260_init();
|
||||
bind_count = 10000;
|
||||
state = NE260_BINDTX;
|
||||
|
||||
return 10000;
|
||||
}
|
||||
#endif
|
583
Multiprotocol/Nrf24l01_udi.ino
Normal file
583
Multiprotocol/Nrf24l01_udi.ino
Normal file
@ -0,0 +1,583 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Known UDI 2.4GHz protocol variants, all using BK2421
|
||||
// * UDI U819 coaxial 3ch helicoper
|
||||
// * UDI U816/817/818 quadcopters
|
||||
// - "V1" with orange LED on TX, U816 RX labeled '' , U817/U818 RX labeled 'UD-U817B'
|
||||
// - "V2" with red LEDs on TX, U816 RX labeled '', U817/U818 RX labeled 'UD-U817OG'
|
||||
// - "V3" with green LEDs on TX. Did not get my hands on yet.
|
||||
// * U830 mini quadcopter with tilt steering ("Protocol 2014")
|
||||
// * U839 nano quadcopter ("Protocol 2014")
|
||||
|
||||
#if defined(UDI_NRF24L01_INO)
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define BIND_UDI_COUNT 1000
|
||||
|
||||
// Timeout for callback in uSec, 4ms=4000us for UDI
|
||||
// ???
|
||||
//#define PACKET_UDI_PERIOD 4000
|
||||
|
||||
#define BIND_PACKET_UDI_PERIOD 5000
|
||||
#define PACKET_UDI_PERIOD 15000
|
||||
|
||||
#define BIND_PACKETS_UDI_PER_CHANNEL 11
|
||||
#define PACKETS_UDI_PER_CHANNEL 11
|
||||
|
||||
#define NUM_UDI_RF_CHANNELS 16
|
||||
|
||||
|
||||
#define INITIAL_UDI_WAIT 50000
|
||||
|
||||
#define PACKET_UDI_CHKTIME 100
|
||||
|
||||
// For readability
|
||||
enum {
|
||||
UDI_CAMERA = 1,
|
||||
UDI_VIDEO = 2,
|
||||
UDI_MODE2 = 4,
|
||||
UDI_FLIP360 = 8,
|
||||
UDI_FLIP =16,
|
||||
UDI_LIGHTS =32
|
||||
};
|
||||
|
||||
// This is maximum payload size used in UDI protocols
|
||||
#define UDI_PAYLOADSIZE 16
|
||||
|
||||
|
||||
|
||||
static uint8_t payload_size; // Bytes in payload for selected variant
|
||||
static uint8_t bind_channel;
|
||||
static uint8_t packets_to_hop;
|
||||
static uint8_t packets_to_check; // BIND_RX phase needs to receive/auto-ack more than one packet for RX to switch to next phase, it seems
|
||||
static uint8_t packets_to_send; // Number of packets to send / check for in current bind phase
|
||||
static uint8_t bind_step_success; // Indicates successfull transmission / receive of bind reply during current bind phase
|
||||
static uint8_t tx_id[3];
|
||||
static uint8_t rx_id[3];
|
||||
static uint8_t randoms[3]; // 3 random bytes choosen by TX, sent in BIND packets. Lower nibble of first byte sets index in RF CH table to use for BIND2
|
||||
|
||||
|
||||
//
|
||||
enum {
|
||||
UDI_INIT2 = 0,
|
||||
UDI_INIT2_NO_BIND,
|
||||
UDI_BIND1_TX,
|
||||
UDI_BIND1_RX,
|
||||
UDI_BIND2_TX,
|
||||
UDI_BIND2_RX,
|
||||
UDI_DATA
|
||||
};
|
||||
|
||||
enum {
|
||||
PROTOOPTS_FORMAT = 0,
|
||||
PROTOOPTS_STARTBIND,
|
||||
};
|
||||
enum {
|
||||
STARTBIND_NO = 0,
|
||||
STARTBIND_YES = 1,
|
||||
};
|
||||
|
||||
// This are frequency hopping tables for UDI protocols
|
||||
|
||||
// uint8_t16 V1 (Orange LED) Bind CH 0x07
|
||||
// TX ID 0x57, 0x5A, 0x2D
|
||||
static const uint8_t freq_hopping_uint8_t16_v1[NUM_UDI_RF_CHANNELS] = {
|
||||
0x07, 0x21, 0x49, 0x0B, 0x39, 0x10, 0x25, 0x42,
|
||||
0x1D, 0x31, 0x35, 0x14, 0x28, 0x3D, 0x18, 0x2D
|
||||
};
|
||||
|
||||
// Protocol 2014 (uint8_t30,uint8_t39,...) BIND CH 0x23 (second entry)
|
||||
// DATA: hops ~ every 0.361s (0.350 ... 0.372)
|
||||
static const uint8_t freq_hopping_uint8_t39[NUM_UDI_RF_CHANNELS] = {
|
||||
0x08, 0x23, 0x48, 0x0D, 0x3B, 0x12, 0x27, 0x44,
|
||||
0x1F, 0x33, 0x37, 0x16, 0x2A, 0x3F, 0x1A, 0x2F
|
||||
};
|
||||
|
||||
// Points to proper table
|
||||
static const uint8_t * rf_udi_channels = NULL;
|
||||
|
||||
|
||||
static uint8_t packet_udi_ack()
|
||||
{
|
||||
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) {
|
||||
case BV(NRF24L01_07_TX_DS): return PKT_ACKED;
|
||||
case BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT;
|
||||
}
|
||||
return PKT_PENDING;
|
||||
}
|
||||
|
||||
static void UDI_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
//NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
switch (sub_protocol) {
|
||||
case U816_V1:
|
||||
rf_udi_channels = freq_hopping_uint8_t16_v1;
|
||||
payload_size = 8;
|
||||
break;
|
||||
|
||||
case U816_V2:
|
||||
rf_udi_channels = NULL; // NO HOPPING !
|
||||
payload_size = 7;
|
||||
break;
|
||||
|
||||
case U839_2014:
|
||||
// UDI 2014 Protocol (uint8_t30, uint8_t39, all other new products ?)
|
||||
rf_udi_channels = freq_hopping_uint8_t39;
|
||||
payload_size = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, payload_size);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x07); // Clear status bits
|
||||
|
||||
if ((sub_protocol == U816_V1) || (sub_protocol == U816_V2)) {
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x27); //
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x3A); //
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3 byte address
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3F); // Auto-acknowledge on all data pipers, same as YD
|
||||
if (sub_protocol == U816_V1) {
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7F); //
|
||||
} else {
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7A); //
|
||||
}
|
||||
} else
|
||||
if (sub_protocol == U839_2014) {
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x0F); // 2Mbps air rate, 5dBm RF output power, high LNA gain
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x1A); // 500uS retransmit t/o, 10 tries (same as YD)
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3 byte address
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3F); // Auto-acknowledge on all data pipers, same as YD
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // Enable CRC, 2 byte CRC, PWR UP, PRIMARY RX
|
||||
}
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, status);
|
||||
|
||||
status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||
NRF24L01_FlushTx();
|
||||
status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, status);
|
||||
|
||||
// Implicit delay in callback
|
||||
// delayMicroseconds(120)
|
||||
}
|
||||
|
||||
static void UDI_init2()
|
||||
{
|
||||
NRF24L01_FlushTx();
|
||||
bind_step_success = 0;
|
||||
packet_sent = 0;
|
||||
|
||||
switch (sub_protocol) {
|
||||
case U816_V1:
|
||||
rf_ch_num = 0;
|
||||
bind_channel = rf_udi_channels[rf_ch_num++];
|
||||
break;
|
||||
case U816_V2:
|
||||
rf_ch_num = 0x07; // This is actual channel. No hopping here
|
||||
bind_channel = 0;
|
||||
break;
|
||||
case U839_2014:
|
||||
rf_ch_num = 1;
|
||||
bind_channel = rf_udi_channels[rf_ch_num++];
|
||||
break;
|
||||
}
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind_channel);
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *) "\xe7\x7e\xe7", 3);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *) "\xe7\x7e\xe7", 3);
|
||||
|
||||
// Turn radio power on
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
uint8_t config = BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, config);
|
||||
// Implicit delay in callback
|
||||
// delayMicroseconds(150);
|
||||
}
|
||||
|
||||
static void set_tx_id(uint32_t id)
|
||||
{
|
||||
tx_id[0] = (id >> 16) & 0xFF;
|
||||
tx_id[1] = (id >> 8) & 0xFF;
|
||||
tx_id[2] = (id >> 0) & 0xFF;
|
||||
|
||||
/*
|
||||
uint32_t val = rand32(); randoms[0] = val & 0xff; randoms[1] = (val >> 8 ) & 0xff; randoms[2] = (val >> 16 ) & 0xff;
|
||||
*/
|
||||
// FIXME
|
||||
// This one has been observed, leads to RF CH 0x1F (#08) used for BIND2
|
||||
randoms[0] = 0x98; randoms[1] = 0x80; randoms[2] = 0x5B;
|
||||
}
|
||||
|
||||
static void add_pkt_checksum()
|
||||
{
|
||||
// CHECKSUM was introduced with 2014 protocol
|
||||
if (sub_protocol < U839_2014) return;
|
||||
uint8_t sum = 0;
|
||||
for (uint8_t i = 0; i < payload_size-1; ++i) sum += packet[i];
|
||||
packet[payload_size-1] = sum & 0x3f; // *sick*
|
||||
}
|
||||
|
||||
|
||||
static uint8_t convert_channel(uint8_t num, uint8_t chn_max, uint8_t sign_ofs)
|
||||
{
|
||||
uint32_t ch = Servo_data[num];
|
||||
if (ch < PPM_MIN) {
|
||||
ch = PPM_MIN;
|
||||
} else if (ch > PPM_MAX) {
|
||||
ch = PPM_MAX;
|
||||
}
|
||||
uint32_t chn_val;
|
||||
if (sign_ofs) chn_val = (((ch * chn_max / PPM_MAX) + sign_ofs) >> 1);
|
||||
else chn_val = (ch * chn_max / PPM_MAX);
|
||||
if (chn_val < 0) chn_val = 0;
|
||||
else if (chn_val > chn_max) chn_val = chn_max;
|
||||
return (uint8_t) chn_val;
|
||||
}
|
||||
|
||||
|
||||
static void read_controls(uint8_t* throttle, uint8_t* rudder, uint8_t* elevator, uint8_t* aileron,
|
||||
uint8_t* flags)
|
||||
{
|
||||
// Protocol is registered AETRG, that is
|
||||
// Aileron is channel 0, Elevator - 1, Throttle - 2, Rudder - 3
|
||||
// Sometimes due to imperfect calibration or mixer settings
|
||||
// throttle can be less than PPM_MIN or larger than
|
||||
// PPM_MAX. As we have no space here, we hard-limit
|
||||
// channels values by min..max range
|
||||
|
||||
// Channel 3: throttle is 0-100
|
||||
*throttle = convert_channel(THROTTLE, 0x64, 0);
|
||||
|
||||
// Channel 4
|
||||
*rudder = convert_channel(RUDDER, 0x3f, 0x20);
|
||||
|
||||
// Channel 2
|
||||
*elevator = convert_channel(ELEVATOR, 0x3f, 0x20);
|
||||
|
||||
// Channel 1
|
||||
*aileron = convert_channel(AILERON, 0x3f, 0x20);
|
||||
|
||||
// Channel 5
|
||||
if (Servo_data[AUX1] <= 0) *flags &= ~UDI_FLIP360;
|
||||
else *flags |= UDI_FLIP360;
|
||||
|
||||
// Channel 6
|
||||
if (Servo_data[AUX2] <= 0) *flags &= ~UDI_FLIP;
|
||||
else *flags |= UDI_FLIP;
|
||||
|
||||
// Channel 7
|
||||
if (Servo_data[AUX3] <= 0) *flags &= ~UDI_CAMERA;
|
||||
else *flags |= UDI_CAMERA;
|
||||
|
||||
// Channel 8
|
||||
if (Servo_data[AUX4] <= 0) *flags &= ~UDI_VIDEO;
|
||||
else *flags |= UDI_VIDEO;
|
||||
|
||||
// Channel 9
|
||||
if (Servo_data[AUX5] <= 0) *flags &= ~UDI_LIGHTS;
|
||||
else *flags |= UDI_LIGHTS;
|
||||
|
||||
// Channel 10
|
||||
if (Servo_data[AUX6] <= 0) *flags &= ~UDI_MODE2;
|
||||
else *flags |= UDI_MODE2;
|
||||
}
|
||||
|
||||
static void send_udi_packet(uint8_t bind)
|
||||
{
|
||||
packet[7] = 0x4A;
|
||||
if (bind == 1) {
|
||||
// Bind phase 1
|
||||
// MAGIC
|
||||
packet[0] = 0x5A; // NOTE: Also 0xF3, when RX does not ACK packets (uint8_t39, only TX on) ...
|
||||
// Current Address / TX ID
|
||||
if (sub_protocol == U839_2014) {
|
||||
// uint8_t39: Current RX/TX Addr
|
||||
packet[1] = 0xE7;
|
||||
packet[2] = 0x7E;
|
||||
packet[3] = 0xE7;
|
||||
} else {
|
||||
// uint8_t16: ID Fixed per TX
|
||||
packet[1] = tx_id[0];
|
||||
packet[2] = tx_id[1];
|
||||
packet[3] = tx_id[2];
|
||||
}
|
||||
// Pseudo random values (lower nibble of packet[4] determines index of RF CH used in BIND2)
|
||||
packet[4] = randoms[0];
|
||||
packet[5] = randoms[1];
|
||||
packet[6] = randoms[2];
|
||||
if (sub_protocol == U839_2014) {
|
||||
packet[7] = (packet_counter < 4) ? 0x3f : 0x04; // first four packets use 0x3f here, then 0x04
|
||||
}
|
||||
} else if (bind == 2) {
|
||||
// Bind phase 2
|
||||
// MAGIC
|
||||
packet[0] = 0xAA;
|
||||
// Current Address (RX "ID", pseudorandom again)
|
||||
packet[1] = rx_id[0];
|
||||
packet[2] = rx_id[1];
|
||||
packet[3] = rx_id[2];
|
||||
// Pseudo random values
|
||||
packet[4] = randoms[0];
|
||||
packet[5] = randoms[1];
|
||||
packet[6] = randoms[2];
|
||||
if (sub_protocol == U839_2014) {
|
||||
packet[7] = 0x04;
|
||||
}
|
||||
} else {
|
||||
// regular packet
|
||||
// Read channels (converts to required ranges)
|
||||
read_controls(&throttle, &rudder, &elevator, &aileron, &flags);
|
||||
// MAGIC
|
||||
packet[0] = 0x55;
|
||||
packet[1] = throttle; // throttle is 0-0x64
|
||||
// 3 Channels packed into 2 bytes (5bit per channel)
|
||||
uint16_t encoded = (rudder << 11) | (elevator << 6) | (aileron << 1);
|
||||
packet[2] = (encoded >> 8) & 0xff;
|
||||
packet[3] = encoded & 0xff;
|
||||
// Trims and flags (0x20 = center)
|
||||
packet[4] = 0x20; // rudder trim 6bit
|
||||
packet[5] = 0x20; // elev trim 6bit
|
||||
packet[6] = 0x20; // ail trim 6bit
|
||||
|
||||
if (flags & UDI_FLIP) packet[4] |= 0x80; // "Directional" flip
|
||||
if (flags & UDI_LIGHTS) packet[4] |= 0x40; // Light on/off
|
||||
|
||||
if (flags & UDI_MODE2) packet[5] |= 0x80; // High rate ("Mode2")
|
||||
if (flags & UDI_FLIP360) packet[5] |= 0x40; // 360 degree flip
|
||||
|
||||
if (flags & UDI_VIDEO) packet[6] |= 0x80; // Video recording on/off
|
||||
if (flags & UDI_CAMERA) packet[6] |= 0x40; // Take picture
|
||||
|
||||
// NOTE: Only newer protocols have this (handled by routine)
|
||||
add_pkt_checksum();
|
||||
}
|
||||
|
||||
uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS,status);
|
||||
|
||||
if (packet_sent && bind && (status & BV(NRF24L01_07_TX_DS))) {
|
||||
bind_step_success = 1;
|
||||
}
|
||||
|
||||
packet_sent = 0;
|
||||
|
||||
// Check if its time to change channel
|
||||
// This seems to be done by measuring time,
|
||||
// not by counting packets, on UDI transmitters
|
||||
// NOTE: Seems even in bind phase channels are changed
|
||||
|
||||
// NOTE: Only hop in TX mode ???
|
||||
if (rf_udi_channels && (bind == 0) && (packets_to_hop-- == 0)) {
|
||||
uint8_t rf_ch = rf_udi_channels[rf_ch_num];
|
||||
rf_ch_num++;
|
||||
rf_ch_num %= NUM_UDI_RF_CHANNELS;
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
|
||||
|
||||
packets_to_hop = bind ? BIND_PACKETS_UDI_PER_CHANNEL : PACKETS_UDI_PER_CHANNEL;
|
||||
}
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, payload_size);
|
||||
++packet_counter;
|
||||
packet_sent = 1;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t UDI_callback() {
|
||||
switch (phase) {
|
||||
case UDI_INIT2:
|
||||
UDI_init2();
|
||||
phase = UDI_BIND1_TX;
|
||||
return 120;
|
||||
break;
|
||||
case UDI_INIT2_NO_BIND:
|
||||
// Do nothing (stay forever)
|
||||
// Cannot re-bind on UDI protocol since IDs are random
|
||||
return 10000; // 10ms
|
||||
break;
|
||||
case UDI_BIND1_TX:
|
||||
if (packet_sent && packet_udi_ack() == PKT_ACKED) { bind_step_success = 1; }
|
||||
if (bind_step_success) {
|
||||
// All fine, wait for reply of receiver
|
||||
phase = UDI_BIND1_RX;
|
||||
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);
|
||||
bind_step_success = 0;
|
||||
//packets_to_check = 12; // according to SPI traces on uint8_t17B RX it receives 12 packets (and answers with 5)
|
||||
packets_to_check = 3;
|
||||
} else {
|
||||
send_udi_packet(1);
|
||||
}
|
||||
return BIND_PACKET_UDI_PERIOD;
|
||||
break;
|
||||
case UDI_BIND1_RX:
|
||||
// Check if data has been received
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR) ) {
|
||||
uint8_t data[UDI_PAYLOADSIZE];
|
||||
NRF24L01_ReadPayload(data, payload_size);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x4E); // On original TX this is done on LAST packet check only !
|
||||
NRF24L01_FlushRx();
|
||||
|
||||
// Verify MAGIC and Random ID
|
||||
// (may be reply to bind packet from other TX)
|
||||
if ((data[0] == 0xA5) &&
|
||||
(data[4] == randoms[0]) &&
|
||||
(data[5] == randoms[1]) &&
|
||||
(data[6] == randoms[2]) &&
|
||||
(data[7] == randoms[2])) {
|
||||
rx_id[0] = data[1];
|
||||
rx_id[1] = data[2];
|
||||
rx_id[2] = data[3];
|
||||
if (sub_protocol != U816_V2) {
|
||||
rf_ch_num = randoms[0] & 0x0f;
|
||||
}
|
||||
bind_step_success = 1;
|
||||
}
|
||||
}
|
||||
// RX seems to need more than one ACK
|
||||
if (packets_to_check) packets_to_check--;
|
||||
//NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);
|
||||
if (bind_step_success && !packets_to_check) {
|
||||
// All fine, switch address and RF channel,
|
||||
// send bind packets with channel hopping now
|
||||
phase = UDI_BIND2_TX;
|
||||
|
||||
packet_sent = 0;
|
||||
packets_to_send = 4;
|
||||
bind_step_success = 0;
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_id, 3);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_id, 3);
|
||||
|
||||
if (sub_protocol != U816_V2) {
|
||||
// Switch RF channel
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_udi_channels[rf_ch_num++]);
|
||||
rf_ch_num %= NUM_UDI_RF_CHANNELS;
|
||||
}
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x7E);
|
||||
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
//NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0E)
|
||||
|
||||
return 10; // 10 µs (start sending immediately)
|
||||
}
|
||||
return BIND_PACKET_UDI_PERIOD;
|
||||
break;
|
||||
|
||||
case UDI_BIND2_TX:
|
||||
if (packet_sent && packet_udi_ack() == PKT_ACKED) {
|
||||
bind_step_success = 1;
|
||||
}
|
||||
send_udi_packet(2);
|
||||
if (packets_to_send) --packets_to_send;
|
||||
if (bind_step_success || !packets_to_send) {
|
||||
// Seems the original TX ignores AACK, too !
|
||||
// U816 V1: 3 packets send, U839: 4 packets send
|
||||
// All fine, wait for reply of receiver
|
||||
phase = UDI_BIND2_RX;
|
||||
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);
|
||||
bind_step_success = 0;
|
||||
packets_to_check = 14; // ???
|
||||
}
|
||||
return bind_step_success ? 4000 : 12000; // 4ms if no packed acked yet, 12ms afterwards
|
||||
// return 120; // FIXME: Varies for first three packets !!!
|
||||
|
||||
break;
|
||||
|
||||
case UDI_BIND2_RX:
|
||||
// Check if data has been received
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR) ) {
|
||||
uint8_t data[UDI_PAYLOADSIZE];
|
||||
NRF24L01_ReadPayload(data, payload_size);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x4E);
|
||||
NRF24L01_FlushRx();
|
||||
|
||||
// Verify MAGIC, RX Addr, Random ID
|
||||
// (may be reply to bind packet from other TX)
|
||||
if ((data[0] == 0xDD) &&
|
||||
(data[1] == rx_id[0]) &&
|
||||
(data[2] == rx_id[1]) &&
|
||||
(data[3] == rx_id[2]) &&
|
||||
(data[4] == randoms[0]) &&
|
||||
(data[5] == randoms[1]) &&
|
||||
(data[6] == randoms[2]) &&
|
||||
(data[7] == randoms[2])) {
|
||||
bind_step_success = 1;
|
||||
}
|
||||
}
|
||||
// RX seems to need more than one ACK
|
||||
if (packets_to_check) packets_to_check--;
|
||||
//NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F);
|
||||
if (bind_step_success && !packets_to_check) {
|
||||
phase = UDI_DATA;
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x7E);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0E);
|
||||
NRF24L01_FlushTx();
|
||||
|
||||
// Switch RF channel
|
||||
if (sub_protocol == U816_V2) {
|
||||
// FIXED RF Channel
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num);
|
||||
} else {
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_udi_channels[rf_ch_num++]);
|
||||
rf_ch_num %= NUM_UDI_RF_CHANNELS;
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
BIND_DONE;
|
||||
}
|
||||
return BIND_PACKET_UDI_PERIOD;
|
||||
break;
|
||||
case UDI_DATA:
|
||||
if (packet_sent && packet_udi_ack() != PKT_ACKED) {
|
||||
return PACKET_UDI_CHKTIME;
|
||||
}
|
||||
send_udi_packet(0);
|
||||
break;
|
||||
}
|
||||
// Packet every 15ms
|
||||
return PACKET_UDI_PERIOD;
|
||||
}
|
||||
|
||||
static uint16_t UDI_setup()
|
||||
{
|
||||
packet_counter = 0;
|
||||
UDI_init();
|
||||
phase = UDI_INIT2;
|
||||
counter = BIND_UDI_COUNT;
|
||||
|
||||
// observed on U839 TX
|
||||
set_tx_id(0x457C27);
|
||||
|
||||
return INITIAL_UDI_WAIT;
|
||||
}
|
||||
#endif
|
108
Multiprotocol/SHENQI_nrf24l01.ino
Normal file
108
Multiprotocol/SHENQI_nrf24l01.ino
Normal file
@ -0,0 +1,108 @@
|
||||
#if defined(SHENQI_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
const uint8_t PROGMEM SHENQI_Freq[] = {
|
||||
50,50,20,60,30,40,
|
||||
10,30,40,20,60,10,
|
||||
50,20,50,40,10,60,
|
||||
30,30,60,10,40,50,
|
||||
20,10,60,20,50,30,
|
||||
40,40,30,50,20,60,
|
||||
10,10,20,30,40,50,
|
||||
60,60,50,40,30,20,
|
||||
10,60,10,50,30,40,
|
||||
20,10,40,30,60,20 };
|
||||
|
||||
void SHENQI_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5 bytes rx/tx address
|
||||
|
||||
LT8910_Config(4, 8, _BV(LT8910_CRC_ON)|_BV(LT8910_PACKET_LENGTH_EN), 0xAA);
|
||||
LT8910_SetChannel(2);
|
||||
LT8910_SetAddress((uint8_t *)"\x9A\x9A\x9A\x9A",4);
|
||||
LT8910_SetTxRxMode(RX_EN);
|
||||
}
|
||||
|
||||
void SHENQI_send_packet()
|
||||
{
|
||||
packet[0]=0x00;
|
||||
if(packet_count==0)
|
||||
{
|
||||
uint8_t bind_addr[4];
|
||||
bind_addr[0]=0x9A;
|
||||
bind_addr[1]=0x9A;
|
||||
bind_addr[2]=rx_tx_addr[2];
|
||||
bind_addr[3]=rx_tx_addr[3];
|
||||
LT8910_SetAddress(bind_addr,4);
|
||||
LT8910_SetChannel(2);
|
||||
packet[1]=rx_tx_addr[1];
|
||||
packet[2]=rx_tx_addr[0];
|
||||
packet_period=2508;
|
||||
}
|
||||
else
|
||||
{
|
||||
LT8910_SetAddress(rx_tx_addr,4);
|
||||
packet[1]=255-convert_channel_8b(RUDDER);
|
||||
packet[2]=255-convert_channel_8b_scale(THROTTLE,0x60,0xA0);
|
||||
uint8_t freq=pgm_read_byte_near(&SHENQI_Freq[hopping_frequency_no])+(rx_tx_addr[1]&0x0F);
|
||||
LT8910_SetChannel(freq);
|
||||
hopping_frequency_no++;
|
||||
if(hopping_frequency_no==60)
|
||||
hopping_frequency_no=0;
|
||||
packet_period=1750;
|
||||
}
|
||||
// Send packet + 1 retransmit - not sure why but needed (not present on original TX...)
|
||||
LT8910_WritePayload(packet,3);
|
||||
while(NRF24L01_packet_ack()!=PKT_ACKED);
|
||||
LT8910_WritePayload(packet,3);
|
||||
|
||||
packet_count++;
|
||||
if(packet_count==7)
|
||||
{
|
||||
packet_count=0;
|
||||
packet_period=3000;
|
||||
}
|
||||
// Set power
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
uint16_t SHENQI_callback()
|
||||
{
|
||||
if(IS_BIND_DONE_on)
|
||||
SHENQI_send_packet();
|
||||
else
|
||||
{
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR))
|
||||
{
|
||||
if(LT8910_ReadPayload(packet, 3))
|
||||
{
|
||||
BIND_DONE;
|
||||
rx_tx_addr[3]=packet[1];
|
||||
rx_tx_addr[2]=packet[2];
|
||||
LT8910_SetTxRxMode(TX_EN);
|
||||
packet_period=14000;
|
||||
}
|
||||
NRF24L01_FlushRx();
|
||||
}
|
||||
}
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initSHENQI()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
SHENQI_init();
|
||||
hopping_frequency_no = 0;
|
||||
packet_count=0;
|
||||
packet_period=100;
|
||||
return 1000;
|
||||
}
|
||||
|
||||
#endif
|
@ -25,14 +25,6 @@
|
||||
//Uncomment to enable telemetry
|
||||
#define TELEMETRY
|
||||
|
||||
|
||||
//Uncomment to enable potar select
|
||||
#define POTAR_SELECT
|
||||
#define POTAR_SELECT_V ELEVATOR
|
||||
#define POTAR_SELECT_H RUDDER
|
||||
#define POTAR_SELECT_M AILERON
|
||||
|
||||
|
||||
//Comment if a module is not installed
|
||||
#define A7105_INSTALLED
|
||||
#define CYRF6936_INSTALLED
|
||||
@ -62,6 +54,11 @@
|
||||
#define CFlie_NRF24L01_INO
|
||||
#define H377_NRF24L01_INO
|
||||
#define FY326_NRF24L01_INO
|
||||
#define ESKY150_NRF24L01_INO
|
||||
// #define BlueFly_NRF24L01_INO //probleme gene id
|
||||
#define HonTai_NRF24L01_INO
|
||||
#define UDI_NRF24L01_INO
|
||||
#define NE260_NRF24L01_INO
|
||||
|
||||
#define BAYANG_NRF24L01_INO
|
||||
#define CG023_NRF24L01_INO
|
||||
@ -75,27 +72,27 @@
|
||||
#define YD717_NRF24L01_INO
|
||||
#define MT99XX_NRF24L01_INO
|
||||
#define MJXQ_NRF24L01_INO
|
||||
// #define SHENQI_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]=
|
||||
{
|
||||
// Protocol Sub protocol RX_Num Power Auto Bind Option
|
||||
{MODE_FLYSKY, Flysky , 0 , P_HIGH , AUTOBIND , 0 }, //Dial=1
|
||||
{MODE_HUBSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=2
|
||||
{MODE_FRSKY , 0 , 0 , P_HIGH , NO_AUTOBIND , 0xD7 }, //Dial=3
|
||||
{MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=4
|
||||
{MODE_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=5
|
||||
{MODE_DSM2 , DSM2 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=6
|
||||
{MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=7
|
||||
{MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=8
|
||||
{MODE_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=9
|
||||
{MODE_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=10
|
||||
{MODE_SLT , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=11
|
||||
{MODE_CX10 , CX10_BLUE , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=12
|
||||
{MODE_CG023 , CG023 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=13
|
||||
{MODE_BAYANG, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, //Dial=14
|
||||
{MODE_SYMAX , SYMAX5C , 0 , P_HIGH , NO_AUTOBIND , 0 } //Dial=15
|
||||
const PPM_Parameters PPM_prot[15]= {
|
||||
// Dial Protocol Sub protocol RX_Num Power Auto Bind Option
|
||||
/* 1 */ {MODE_FLYSKY, Flysky , 0 , P_HIGH , AUTOBIND , 0 },
|
||||
/* 2 */ {MODE_HUBSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 3 */ {MODE_FRSKY , 0 , 0 , P_HIGH , NO_AUTOBIND , 0xD7 },
|
||||
/* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 5 */ {MODE_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 6 */ {MODE_DSM2 , DSM2 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 7 */ {MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 8 */ {MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 9 */ {MODE_KN , FEILUN , 0 , P_HIGH , AUTOBIND , 0 },
|
||||
/* 10 */ {MODE_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 11 */ {MODE_SLT , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 12 */ {MODE_CX10 , CX10_BLUE , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 13 */ {MODE_CG023 , CG023 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 14 */ {MODE_BAYANG, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
|
||||
/* 15 */ {MODE_SYMAX , SYMAX5C , 0 , P_HIGH , NO_AUTOBIND , 0 }
|
||||
};
|
||||
/* Available protocols and associated sub protocols:
|
||||
MODE_FLYSKY
|
||||
@ -159,6 +156,8 @@ static const PPM_Parameters PPM_prot[15]=
|
||||
X600
|
||||
X800
|
||||
H26D
|
||||
MODE_SHENQI
|
||||
NONE
|
||||
|
||||
RX_Num value between 0 and 15
|
||||
|
||||
@ -191,7 +190,7 @@ Option value between 0 and 255. 0xD7 or 0x00 for Frsky fine tuning.
|
||||
#endif
|
||||
|
||||
// SPEKTRUM PPM and channels
|
||||
#if defined(TX_SPEKTRUM) | defined(TARANIS)
|
||||
#if defined(TX_SPEKTRUM)
|
||||
#define PPM_MAX 2000
|
||||
#define PPM_MIN 1000
|
||||
#define PPM_MAX_100 1900
|
||||
@ -199,6 +198,15 @@ Option value between 0 and 255. 0xD7 or 0x00 for Frsky fine tuning.
|
||||
#define TAER
|
||||
#endif
|
||||
|
||||
// TARANIS PPM and channels
|
||||
#if defined(TARANIS)
|
||||
#define PPM_MAX 2000
|
||||
#define PPM_MIN 1000
|
||||
#define PPM_MAX_100 1900
|
||||
#define PPM_MIN_100 1100
|
||||
#define EATR
|
||||
#endif
|
||||
|
||||
// HISKY
|
||||
#if defined(TX_HISKY)
|
||||
#define PPM_MAX 2000
|
||||
@ -249,3 +257,7 @@ enum chan_orders{
|
||||
#define PPM_MIN_COMMAND 1250
|
||||
#define PPM_SWITCH 1550
|
||||
#define PPM_MAX_COMMAND 1750
|
||||
|
||||
//Uncoment the desired serial speed
|
||||
#define BAUD 100000
|
||||
//#define BAUD 125000
|
||||
|
@ -156,4 +156,43 @@ enum {
|
||||
//void CC2500_WriteData(u8 *packet, u8 length);
|
||||
//void CC2500_ReadData(u8 *dpbuffer, int len);
|
||||
//void CC2500_SetTxRxMode(enum TXRX_State);
|
||||
|
||||
const PROGMEM uint8_t cc2500_conf[][2]={
|
||||
{ CC2500_02_IOCFG0, 0x06 },
|
||||
{ CC2500_00_IOCFG2, 0x06 },
|
||||
{ CC2500_17_MCSM1, 0x0c },
|
||||
{ CC2500_18_MCSM0, 0x18 },
|
||||
{ CC2500_06_PKTLEN, 0x19 },
|
||||
{ CC2500_07_PKTCTRL1, 0x04 },
|
||||
{ CC2500_08_PKTCTRL0, 0x05 },
|
||||
{ CC2500_3E_PATABLE, 0xff },
|
||||
{ CC2500_0B_FSCTRL1, 0x08 },
|
||||
{ CC2500_0C_FSCTRL0, 0x00 }, // option
|
||||
{ CC2500_0D_FREQ2, 0x5c },
|
||||
{ CC2500_0E_FREQ1, 0x76 },
|
||||
{ CC2500_0F_FREQ0, 0x27 },
|
||||
{ CC2500_10_MDMCFG4, 0xAA },
|
||||
{ CC2500_11_MDMCFG3, 0x39 },
|
||||
{ CC2500_12_MDMCFG2, 0x11 },
|
||||
{ CC2500_13_MDMCFG1, 0x23 },
|
||||
{ CC2500_14_MDMCFG0, 0x7a },
|
||||
{ CC2500_15_DEVIATN, 0x42 },
|
||||
{ CC2500_19_FOCCFG, 0x16 },
|
||||
{ CC2500_1A_BSCFG, 0x6c },
|
||||
{ CC2500_1B_AGCCTRL2, 0x43 }, // bind ? 0x43 : 0x03
|
||||
{ CC2500_1C_AGCCTRL1,0x40 },
|
||||
{ CC2500_1D_AGCCTRL0,0x91 },
|
||||
{ CC2500_21_FREND1, 0x56 },
|
||||
{ CC2500_22_FREND0, 0x10 },
|
||||
{ CC2500_23_FSCAL3, 0xa9 },
|
||||
{ CC2500_24_FSCAL2, 0x0A },
|
||||
{ CC2500_25_FSCAL1, 0x00 },
|
||||
{ CC2500_26_FSCAL0, 0x11 },
|
||||
{ CC2500_29_FSTEST, 0x59 },
|
||||
{ CC2500_2C_TEST2, 0x88 },
|
||||
{ CC2500_2D_TEST1, 0x31 },
|
||||
{ CC2500_2E_TEST0, 0x0B },
|
||||
{ CC2500_03_FIFOTHR, 0x07 },
|
||||
{ CC2500_09_ADDR, 0x00 }
|
||||
};
|
||||
#endif
|
||||
|
@ -30,6 +30,11 @@ enum PROTOCOLS
|
||||
MODE_H377=44, // =>NRF24L01
|
||||
MODE_WK2x01 = 45, // =>CYRF6936
|
||||
MODE_FY326=46, // =>NRF24L01
|
||||
MODE_ESKY150=47, // =>NRF24L01
|
||||
MODE_BlueFly=48, // =>NRF24L01
|
||||
MODE_HonTai=49, // =>NRF24L01
|
||||
MODE_UDI=50, // =>NRF24L01
|
||||
MODE_NE260=51, // =>NRF24L01
|
||||
|
||||
MODE_SERIAL = 0, // Serial commands
|
||||
MODE_FLYSKY = 1, // =>A7105
|
||||
@ -49,7 +54,8 @@ enum PROTOCOLS
|
||||
MODE_FRSKYX = 15, // =>CC2500
|
||||
MODE_ESKY = 16, // =>NRF24L01
|
||||
MODE_MT99XX=17, // =>NRF24L01
|
||||
MODE_MJXQ=18 // =>NRF24L01
|
||||
MODE_MJXQ=18, // =>NRF24L01
|
||||
MODE_SHENQI=19 // =>NRF24L01
|
||||
};
|
||||
enum Flysky
|
||||
{
|
||||
@ -127,6 +133,12 @@ enum FY326
|
||||
FY326 = 0,
|
||||
FY319 = 1
|
||||
};
|
||||
enum UDI
|
||||
{
|
||||
U816_V1 = 0,
|
||||
U816_V2,
|
||||
U839_2014
|
||||
};
|
||||
|
||||
#define NONE 0
|
||||
#define P_HIGH 1
|
||||
@ -147,10 +159,6 @@ struct PPM_Parameters
|
||||
//*******************
|
||||
//*** Pinouts ***
|
||||
//*******************
|
||||
#define BUZZER 19 //A5
|
||||
#define BUZZER_HTZ 440 // La clé de sol
|
||||
#define BUZZER_TPS 300
|
||||
|
||||
//#define BIND_pin 13
|
||||
#define LED_pin 13 //Promini original led on B5
|
||||
//
|
||||
@ -440,6 +448,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
ESky 16
|
||||
MT99XX 17
|
||||
MJXQ 18
|
||||
SHENQI 19
|
||||
BindBit=> 0x80 1=Bind/0=No
|
||||
AutoBindBit=> 0x40 1=Yes /0=No
|
||||
RangeCheck=> 0x20 1=Yes /0=No
|
||||
|
63
README.md
63
README.md
@ -60,6 +60,7 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7
|
||||
CH1|CH2|CH3|CH4|???|CONF|Gyro & Rudder mix
|
||||
|
||||
CONF: Option 1 = Rate Throtle
|
||||
|
||||
Option 2 = Pitch
|
||||
|
||||
|
||||
@ -76,6 +77,13 @@ CH1|CH2|CH3|CH4
|
||||
A|E|T|R
|
||||
|
||||
##NRF24L01 RF Module
|
||||
###BLUEFLY
|
||||
Autobind
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6
|
||||
---|---|---|---|---|---
|
||||
A|E|T|R|GEAR|PITCH
|
||||
|
||||
###CFLIE
|
||||
Modele: CrazyFlie Nano quad
|
||||
|
||||
@ -85,6 +93,14 @@ CH1|CH2|CH3|CH4
|
||||
---|---|---|---
|
||||
A|E|T|R
|
||||
|
||||
###ESKY150
|
||||
|
||||
Autobind
|
||||
|
||||
CH1|CH2|CH3|CH4
|
||||
---|---|---|---
|
||||
A|E|T|R
|
||||
|
||||
###Fy326
|
||||
Autobind
|
||||
|
||||
@ -107,6 +123,51 @@ Autobind
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5
|
||||
---|---|---|---
|
||||
A|Turbo|T|Trim|Bouton ???
|
||||
A|Turbo|T|Trim|Bouton
|
||||
|
||||
###HONTAI
|
||||
Autobind
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
||||
---|---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|LED|FLIP|PICTURE|VIDEO|HEADLESS|RTH|Calibrate
|
||||
|
||||
####Sub_protocol JJRCX1
|
||||
Modele: JJRC X1
|
||||
|
||||
CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
||||
---|---|---|---|---|---|---|---|---|---|---
|
||||
ARM|FLIP|PICTURE|VIDEO|HEADLESS|RTH|Calibrate
|
||||
|
||||
###NE260
|
||||
Modele: Nine Eagles SoloPro
|
||||
|
||||
Autobind
|
||||
|
||||
CH1|CH2|CH3|CH4
|
||||
---|---|---|---
|
||||
A|E|T|R
|
||||
|
||||
###UDI
|
||||
Modele: Known UDI 2.4GHz protocol variants, all using BK2421
|
||||
* UDI U819 coaxial 3ch helicoper
|
||||
* UDI U816/817/818 quadcopters
|
||||
- "V1" with orange LED on TX, U816 RX labeled '' , U817/U818 RX labeled 'UD-U817B'
|
||||
- "V2" with red LEDs on TX, U816 RX labeled '', U817/U818 RX labeled 'UD-U817OG'
|
||||
- "V3" with green LEDs on TX. Did not get my hands on yet.
|
||||
* U830 mini quadcopter with tilt steering ("Protocol 2014")
|
||||
* U839 nano quadcopter ("Protocol 2014")
|
||||
|
||||
Autobind
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
|
||||
---|---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|FLIP 360|FLIP|VIDEO|LED|MODE 2
|
||||
|
||||
####Sub_protocol U816 V1 (orange)
|
||||
####Sub_protocol U816 V2 (red)
|
||||
####Sub_protocol U816 (2014)
|
||||
Same channels assignement as above.
|
||||
|
||||
|
||||
###D'autres à venir
|
Loading…
x
Reference in New Issue
Block a user