Merge remote-tracking branch 'refs/remotes/pascallanger/master'

This commit is contained in:
Dennis
2017-03-14 13:40:26 -04:00
88 changed files with 65500 additions and 1616 deletions

View File

@@ -146,7 +146,11 @@ void A7105_SetPower()
{
uint8_t power=A7105_BIND_POWER;
if(IS_BIND_DONE_on)
power=IS_POWER_FLAG_on?A7105_HIGH_POWER:A7105_LOW_POWER;
#ifdef A7105_ENABLE_LOW_POWER
power=IS_POWER_FLAG_on?A7105_HIGH_POWER:A7105_LOW_POWER;
#else
power=A7105_HIGH_POWER;
#endif
if(IS_RANGE_FLAG_on)
power=A7105_RANGE_POWER;
if(prev_power != power)

View File

@@ -110,11 +110,11 @@ static void AFHDS2A_update_telemetry()
v_lipo1 = packet[index+2];
telemetry_link=1;
break;
/*case AFHDS2A_SENSOR_RX_ERR_RATE:
// packet[index+2];
break;*/
case AFHDS2A_SENSOR_RX_ERR_RATE:
RX_LQI=packet[index+2];
break;
case AFHDS2A_SENSOR_RX_RSSI:
RSSI_dBm = -packet[index+2];
RX_RSSI = -packet[index+2];
break;
case 0xff:
return;
@@ -260,7 +260,7 @@ uint16_t ReadAFHDS2A()
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetTxRxMode(RX_EN);
A7105_SetTxRxMode(TXRX_OFF); // Turn LNA off since we are in near range and we want to prevent swamping
A7105_Strobe(A7105_RX);
phase &= ~AFHDS2A_WAIT_WRITE;
phase++;
@@ -352,7 +352,7 @@ uint16_t initAFHDS2A()
}
hopping_frequency_no = 0;
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
init_hub_telemetry();
init_frskyd_link_telemetry();
#endif
return 50000;
}

View File

@@ -143,7 +143,7 @@ static void __attribute__((unused)) ASSAN_initialize_txid()
packet[20]=0x53; */
// Using packet[20..23] to store the ID1 and packet[24..27] to store the ID2
uint8_t freq=0,freq2;
for(uint8_t i=0;i<4;i++)
for(uint8_t i=0;i<ASSAN_ADDRESS_LENGTH;i++)
{
uint8_t temp=rx_tx_addr[i];
packet[i+20]=temp;

View File

@@ -150,7 +150,7 @@ static void __attribute__((unused)) check_rx(void)
// compensated battery volts*100/2
v_lipo2 = (packet[5]<<7) + (packet[6]>>2);
// reception in packets / sec
RSSI_dBm = packet[7];
RX_RSSI = packet[7];
//Flags
//uint8_t flags = packet[3] >> 3;
// battery low: flags & 1
@@ -252,7 +252,7 @@ uint16_t initBAYANG(void)
BAYANG_init();
packet_count=0;
#ifdef BAYANG_HUB_TELEMETRY
init_hub_telemetry();
init_frskyd_link_telemetry();
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
#endif
return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD;

View File

@@ -145,7 +145,11 @@ void CC2500_SetPower()
{
uint8_t power=CC2500_BIND_POWER;
if(IS_BIND_DONE_on)
power=IS_POWER_FLAG_on?CC2500_HIGH_POWER:CC2500_LOW_POWER;
#ifdef CC2500_ENABLE_LOW_POWER
power=IS_POWER_FLAG_on?CC2500_HIGH_POWER:CC2500_LOW_POWER;
#else
power=CC2500_HIGH_POWER;
#endif
if(IS_RANGE_FLAG_on)
power=CC2500_RANGE_POWER;
if(prev_power != power)

View File

@@ -133,7 +133,11 @@ void CYRF_SetPower(uint8_t val)
{
uint8_t power=CYRF_BIND_POWER;
if(IS_BIND_DONE_on)
power=IS_POWER_FLAG_on?CYRF_HIGH_POWER:CYRF_LOW_POWER;
#ifdef CYRF6936_ENABLE_LOW_POWER
power=IS_POWER_FLAG_on?CYRF_HIGH_POWER:CYRF_LOW_POWER;
#else
power=CYRF_HIGH_POWER;
#endif
if(IS_RANGE_FLAG_on)
power=CYRF_RANGE_POWER;
power|=val;

271
Multiprotocol/Common.ino Normal file
View File

@@ -0,0 +1,271 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
/************************/
/** Convert routines **/
/************************/
// Channel value is converted to 8bit values full scale
uint8_t convert_channel_8b(uint8_t num)
{
return (uint8_t) (map(limit_channel_100(num),servo_min_100,servo_max_100,0,255));
}
// Channel value is converted to 8bit values to provided values scale
uint8_t convert_channel_8b_scale(uint8_t num,uint8_t min,uint8_t max)
{
return (uint8_t) (map(limit_channel_100(num),servo_min_100,servo_max_100,min,max));
}
// Channel value is converted sign + magnitude 8bit values
uint8_t convert_channel_s8b(uint8_t num)
{
uint8_t ch;
ch = convert_channel_8b(num);
return (ch < 128 ? 127-ch : ch);
}
// Channel value is converted to 10bit values
uint16_t convert_channel_10b(uint8_t num)
{
return (uint16_t) (map(limit_channel_100(num),servo_min_100,servo_max_100,1,1023));
}
// Channel value is multiplied by 1.5
uint16_t convert_channel_frsky(uint8_t num)
{
return Servo_data[num] + Servo_data[num]/2;
}
// Channel value is converted for HK310
void convert_channel_HK310(uint8_t num, uint8_t *low, uint8_t *high)
{
uint16_t temp=0xFFFF-(4*Servo_data[num])/3;
*low=(uint8_t)(temp&0xFF);
*high=(uint8_t)(temp>>8);
}
// Channel value is converted to 16bit values
uint16_t convert_channel_16b(uint8_t num, int16_t out_min, int16_t out_max)
{
return (uint16_t) (map(limit_channel_100(num),servo_min_100,servo_max_100,out_min,out_max));
}
// Channel value is converted to 16bit values with no limit
uint16_t convert_channel_16b_nolim(uint8_t num, int16_t out_min, int16_t out_max)
{
return (uint16_t) (map(Servo_data[num],servo_min_100,servo_max_100,out_min,out_max));
}
// Channel value is limited to PPM_100
uint16_t limit_channel_100(uint8_t ch)
{
if(Servo_data[ch]>servo_max_100)
return servo_max_100;
else
if (Servo_data[ch]<servo_min_100)
return servo_min_100;
return Servo_data[ch];
}
/******************************/
/** FrSky D and X routines **/
/******************************/
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO)
enum {
FRSKY_BIND = 0,
FRSKY_BIND_DONE = 1000,
FRSKY_DATA1,
FRSKY_DATA2,
FRSKY_DATA3,
FRSKY_DATA4,
FRSKY_DATA5
};
void Frsky_init_hop(void)
{
uint8_t val;
uint8_t channel = rx_tx_addr[0]&0x07;
uint8_t channel_spacing = rx_tx_addr[1];
//Filter bad tables
if(channel_spacing<0x02) channel_spacing+=0x02;
if(channel_spacing>0xE9) channel_spacing-=0xE7;
if(channel_spacing%0x2F==0) channel_spacing++;
hopping_frequency[0]=channel;
for(uint8_t i=1;i<50;i++)
{
channel=(channel+channel_spacing) % 0xEB;
val=channel;
if((val==0x00) || (val==0x5A) || (val==0xDC))
val++;
hopping_frequency[i]=i>46?0:val;
}
}
#endif
/******************************/
/** FrSky V, D and X routines **/
/******************************/
#if defined(FRSKYV_CC2500_INO) || defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO)
const PROGMEM uint8_t FRSKY_common_startreg_cc2500_conf[]= {
CC2500_02_IOCFG0 ,
CC2500_00_IOCFG2 ,
CC2500_17_MCSM1 ,
CC2500_18_MCSM0 ,
CC2500_06_PKTLEN ,
CC2500_07_PKTCTRL1 ,
CC2500_08_PKTCTRL0 ,
CC2500_3E_PATABLE ,
CC2500_0B_FSCTRL1 ,
CC2500_0C_FSCTRL0 , // replaced by option value
CC2500_0D_FREQ2 ,
CC2500_0E_FREQ1 ,
CC2500_0F_FREQ0 ,
CC2500_10_MDMCFG4 ,
CC2500_11_MDMCFG3 ,
CC2500_12_MDMCFG2 ,
CC2500_13_MDMCFG1 ,
CC2500_14_MDMCFG0 ,
CC2500_15_DEVIATN };
#if defined(FRSKYV_CC2500_INO)
const PROGMEM uint8_t FRSKYV_cc2500_conf[]= {
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0xff ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x05 ,
/*3E_PATABLE*/ 0xfe ,
/*0B_FSCTRL1*/ 0x08 ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x58 ,
/*0F_FREQ0*/ 0x9d ,
/*10_MDMCFG4*/ 0xAA ,
/*11_MDMCFG3*/ 0x10 ,
/*12_MDMCFG2*/ 0x93 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x41 };
#endif
#if defined(FRSKYD_CC2500_INO)
const PROGMEM uint8_t FRSKYD_cc2500_conf[]= {
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x19 ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x05 ,
/*3E_PATABLE*/ 0xff ,
/*0B_FSCTRL1*/ 0x08 ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x76 ,
/*0F_FREQ0*/ 0x27 ,
/*10_MDMCFG4*/ 0xAA ,
/*11_MDMCFG3*/ 0x39 ,
/*12_MDMCFG2*/ 0x11 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x42 };
#endif
#if defined(FRSKYX_CC2500_INO)
const PROGMEM uint8_t FRSKYX_cc2500_conf[]= {
//FRSKYX
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x1E ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x01 ,
/*3E_PATABLE*/ 0xff ,
/*0B_FSCTRL1*/ 0x0A ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x76 ,
/*0F_FREQ0*/ 0x27 ,
/*10_MDMCFG4*/ 0x7B ,
/*11_MDMCFG3*/ 0x61 ,
/*12_MDMCFG2*/ 0x13 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x51 };
const PROGMEM uint8_t FRSKYXEU_cc2500_conf[]= {
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0E ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x23 ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x01 ,
/*3E_PATABLE*/ 0xff ,
/*0B_FSCTRL1*/ 0x08 ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x80 ,
/*0F_FREQ0*/ 0x00 ,
/*10_MDMCFG4*/ 0x7B ,
/*11_MDMCFG3*/ 0xF8 ,
/*12_MDMCFG2*/ 0x03 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x53 };
#endif
const PROGMEM uint8_t FRSKY_common_end_cc2500_conf[][2]= {
{ CC2500_19_FOCCFG, 0x16 },
{ CC2500_1A_BSCFG, 0x6c },
{ CC2500_1B_AGCCTRL2, 0x43 },
{ 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 } };
void FRSKY_init_cc2500(const uint8_t *ptr)
{
for(uint8_t i=0;i<19;i++)
{
uint8_t reg=pgm_read_byte_near(&FRSKY_common_startreg_cc2500_conf[i]);
uint8_t val=pgm_read_byte_near(&ptr[i]);
if(reg==CC2500_0C_FSCTRL0)
val=option;
CC2500_WriteReg(reg,val);
}
prev_option = option ; // Save option to monitor FSCTRL0 change
for(uint8_t i=0;i<17;i++)
{
uint8_t reg=pgm_read_byte_near(&FRSKY_common_end_cc2500_conf[i][0]);
uint8_t val=pgm_read_byte_near(&FRSKY_common_end_cc2500_conf[i][1]);
CC2500_WriteReg(reg,val);
}
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
CC2500_Strobe(CC2500_SIDLE); // Go to idle...
}
#endif

View File

@@ -1,68 +0,0 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
/************************/
/** Convert routines **/
/************************/
// Channel value is converted to 8bit values full scale
uint8_t convert_channel_8b(uint8_t num)
{
return (uint8_t) (map(limit_channel_100(num),servo_min_100,servo_max_100,0,255));
}
// Channel value is converted to 8bit values to provided values scale
uint8_t convert_channel_8b_scale(uint8_t num,uint8_t min,uint8_t max)
{
return (uint8_t) (map(limit_channel_100(num),servo_min_100,servo_max_100,min,max));
}
// Channel value is converted sign + magnitude 8bit values
uint8_t convert_channel_s8b(uint8_t num)
{
uint8_t ch;
ch = convert_channel_8b(num);
return (ch < 128 ? 127-ch : ch);
}
// Channel value is converted to 10bit values
uint16_t convert_channel_10b(uint8_t num)
{
return (uint16_t) (map(limit_channel_100(num),servo_min_100,servo_max_100,1,1023));
}
// Channel value is multiplied by 1.5
uint16_t convert_channel_frsky(uint8_t num)
{
return Servo_data[num] + Servo_data[num]/2;
}
// Channel value is converted for HK310
void convert_channel_HK310(uint8_t num, uint8_t *low, uint8_t *high)
{
uint16_t temp=0xFFFF-(4*Servo_data[num])/3;
*low=(uint8_t)(temp&0xFF);
*high=(uint8_t)(temp>>8);
}
// Channel value is limited to PPM_100
uint16_t limit_channel_100(uint8_t ch)
{
if(Servo_data[ch]>servo_max_100)
return servo_max_100;
else
if (Servo_data[ch]<servo_min_100)
return servo_min_100;
return Servo_data[ch];
}

View File

@@ -164,7 +164,7 @@ const uint8_t PROGMEM data_vals[][2] = {
{CYRF_1E_RX_OVERRIDE, 0x00}, // CRC16 enabled, no ACK
};
static void __attribute__((unused)) cyrf_config()
static void __attribute__((unused)) DSM_cyrf_config()
{
for(uint8_t i = 0; i < sizeof(init_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&init_vals[i][0]), pgm_read_byte_near(&init_vals[i][1]));
@@ -172,7 +172,7 @@ static void __attribute__((unused)) cyrf_config()
CYRF_ConfigRFChannel(0x61);
}
static void __attribute__((unused)) build_bind_packet()
static void __attribute__((unused)) DSM_build_bind_packet()
{
uint8_t i;
uint16_t sum = 384 - 0x10;//
@@ -211,21 +211,21 @@ static void __attribute__((unused)) build_bind_packet()
packet[15] = sum & 0xff;
}
static void __attribute__((unused)) initialize_bind_phase()
static void __attribute__((unused)) DSM_initialize_bind_phase()
{
CYRF_ConfigRFChannel(DSM_BIND_CHANNEL); //This seems to be random?
//64 SDR Mode is configured so only the 8 first values are needed but need to write 16 values...
CYRF_ConfigDataCode((const uint8_t*)"\xD7\xA1\x54\xB1\x5E\x89\xAE\x86\xc6\x94\x22\xfe\x48\xe6\x57\x4e", 16);
build_bind_packet();
DSM_build_bind_packet();
}
static void __attribute__((unused)) cyrf_configdata()
static void __attribute__((unused)) DSM_cyrf_configdata()
{
for(uint8_t i = 0; i < sizeof(data_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&data_vals[i][0]), pgm_read_byte_near(&data_vals[i][1]));
}
static void __attribute__((unused)) update_channels()
static void __attribute__((unused)) DSM_update_channels()
{
prev_option=option;
if(sub_protocol==DSM_AUTO)
@@ -243,13 +243,13 @@ static void __attribute__((unused)) update_channels()
ch_map[i]=pgm_read_byte_near(&ch_map_progmem[idx][i]);
}
static void __attribute__((unused)) build_data_packet(uint8_t upper)
static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
{
uint16_t max = 2047;
uint8_t bits = 11;
if(prev_option!=option)
update_channels();
DSM_update_channels();
if (sub_protocol==DSMX_11 || sub_protocol==DSMX_22 )
{
@@ -288,7 +288,7 @@ static void __attribute__((unused)) build_data_packet(uint8_t upper)
}
}
static void __attribute__((unused)) set_sop_data_crc()
static void __attribute__((unused)) DSM_set_sop_data_crc()
{
//The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1])
//The crc for channel '2' is (mfgid[0] << 8 + mfgid[1])
@@ -314,7 +314,7 @@ static void __attribute__((unused)) set_sop_data_crc()
hopping_frequency_no %=2;
}
static void __attribute__((unused)) calc_dsmx_channel()
static void __attribute__((unused)) DSM_calc_dsmx_channel()
{
uint8_t idx = 0;
uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0));
@@ -433,17 +433,17 @@ uint16_t ReadDsm()
#endif
case DSM_CHANSEL:
BIND_DONE;
cyrf_configdata();
DSM_cyrf_configdata();
CYRF_SetTxRxMode(TX_EN);
hopping_frequency_no = 0;
phase = DSM_CH1_WRITE_A; // in fact phase++
set_sop_data_crc();
DSM_set_sop_data_crc();
return 10000;
case DSM_CH1_WRITE_A:
case DSM_CH1_WRITE_B:
case DSM_CH2_WRITE_A:
case DSM_CH2_WRITE_B:
build_data_packet(phase == DSM_CH1_WRITE_B||phase == DSM_CH2_WRITE_B); // build lower or upper channels
DSM_build_data_packet(phase == DSM_CH1_WRITE_B||phase == DSM_CH2_WRITE_B); // build lower or upper channels
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
CYRF_WriteDataPacket(packet);
phase++; // change from WRITE to CHECK mode
@@ -463,12 +463,12 @@ uint16_t ReadDsm()
if (((CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x22) == 0x20) || (CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80))
{
CYRF_Reset();
cyrf_config();
cyrf_configdata();
DSM_cyrf_config();
DSM_cyrf_configdata();
CYRF_SetTxRxMode(TX_EN);
}
#endif
set_sop_data_crc();
DSM_set_sop_data_crc();
phase++; // change from CH1_CHECK to CH2_WRITE
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
}
@@ -510,11 +510,11 @@ uint16_t ReadDsm()
phase = DSM_CH1_WRITE_A; //Transmit lower
CYRF_SetTxRxMode(TX_EN); //TX mode
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); //Clear abort RX operation
set_sop_data_crc();
DSM_set_sop_data_crc();
return DSM_READ_DELAY;
#else
// No telemetry
set_sop_data_crc();
DSM_set_sop_data_crc();
if (phase == DSM_CH2_CHECK_A)
{
if(DSM_num_ch > 7 || sub_protocol==DSM2_11 || sub_protocol==DSMX_11)
@@ -548,7 +548,7 @@ uint16_t initDsm()
}
//Hopping frequencies
if (sub_protocol == DSMX_11 || sub_protocol == DSMX_22)
calc_dsmx_channel();
DSM_calc_dsmx_channel();
else
{
uint8_t tmpch[10];
@@ -565,15 +565,15 @@ uint16_t initDsm()
hopping_frequency[1] = tmpch[idx];
}
//
cyrf_config();
DSM_cyrf_config();
CYRF_SetTxRxMode(TX_EN);
//
update_channels();
DSM_update_channels();
//
if(IS_AUTOBIND_FLAG_on )
{
BIND_IN_PROGRESS;
initialize_bind_phase();
DSM_initialize_bind_phase();
phase = DSM_BIND_WRITE;
bind_counter=DSM_BIND_COUNT;
}

View File

@@ -134,7 +134,7 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
uint8_t sign = 0x0b;
for (uint8_t i = 0; i < 4; i++)
{
int16_t value=map(Servo_data[CH_EATR[ch_idx * 4 + i]],servo_min_125,servo_max_125,-1600,1600);//range -1600..+1600
int16_t value=map(Servo_data[CH_EATR[ch_idx * 4 + i]],servo_min_100,servo_max_100,-1600,1600);//range -1600..+1600
if(value < 0)
{
value = -value;

View File

@@ -60,9 +60,9 @@ static void __attribute__((unused)) ssv_pack_dpl(uint8_t addr[], uint8_t pid, ui
crc.val=0x3c18;
for (i = 0; i < 7; ++i)
crc.val=crc16_update(crc.val,header[i]);
crc.val=crc16_update(crc.val,header[i],8);
for (i = 0; i < *len; ++i)
crc.val=crc16_update(crc.val,payload[i]);
crc.val=crc16_update(crc.val,payload[i],8);
// encode payload and crc
// xor with this:

View File

@@ -19,26 +19,7 @@
static void __attribute__((unused)) frsky2way_init(uint8_t bind)
{
// Configure cc2500 for tx mode
//
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);
}
prev_option = option ;
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
CC2500_Strobe(CC2500_SIDLE);
FRSKY_init_cc2500(FRSKYD_cc2500_conf);
CC2500_WriteReg(CC2500_09_ADDR, bind ? 0x03 : rx_tx_addr[3]);
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05);
@@ -50,16 +31,6 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind)
//#######END INIT########
}
static uint8_t __attribute__((unused)) get_chan_num(uint16_t idx)
{
uint8_t ret = (idx * 0x1e) % 0xeb;
if(idx == 3 || idx == 23 || idx == 47)
ret++;
if(idx > 47)
return 0;
return ret;
}
static void __attribute__((unused)) frsky2way_build_bind_packet()
{
//11 03 01 d7 2d 00 00 1e 3c 5b 78 00 00 00 00 00 00 01
@@ -71,11 +42,11 @@ static void __attribute__((unused)) frsky2way_build_bind_packet()
packet[4] = rx_tx_addr[2];
uint16_t idx = ((state -FRSKY_BIND) % 10) * 5;
packet[5] = idx;
packet[6] = get_chan_num(idx++);
packet[7] = get_chan_num(idx++);
packet[8] = get_chan_num(idx++);
packet[9] = get_chan_num(idx++);
packet[10] = get_chan_num(idx++);
packet[6] = hopping_frequency[idx++];
packet[7] = hopping_frequency[idx++];
packet[8] = hopping_frequency[idx++];
packet[9] = hopping_frequency[idx++];
packet[10] = hopping_frequency[idx++];
packet[11] = 0x00;
packet[12] = 0x00;
packet[13] = 0x00;
@@ -124,6 +95,11 @@ static void __attribute__((unused)) frsky2way_data_frame()
uint16_t initFrSky_2way()
{
Frsky_init_hop();
packet_count=0;
#if defined TELEMETRY
init_frskyd_link_telemetry();
#endif
if(IS_AUTOBIND_FLAG_on)
{
frsky2way_init(1);
@@ -131,8 +107,7 @@ uint16_t initFrSky_2way()
}
else
{
frsky2way_init(0);
state = FRSKY_DATA2;
state = FRSKY_BIND_DONE;
}
return 10000;
}
@@ -147,7 +122,10 @@ uint16_t ReadFrSky_2way()
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
CC2500_Strobe(CC2500_SFRX);//0x3A
CC2500_WriteData(packet, packet[0]+1);
state++;
if(IS_BIND_DONE_on)
state = FRSKY_BIND_DONE;
else
state++;
return 9000;
}
if (state == FRSKY_BIND_DONE)
@@ -169,7 +147,7 @@ uint16_t ReadFrSky_2way()
{ //telemetry receive
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[counter % 47]);
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
state++;
return 1300;
@@ -179,19 +157,35 @@ uint16_t ReadFrSky_2way()
if (state == FRSKY_DATA1)
{
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && len<=MAX_PKT)//27 bytes
{
CC2500_ReadData(pkt, len); //received telemetry packets
if (len && len<=(0x11+3))// 20bytes
{
CC2500_ReadData(pkt, len); //received telemetry packets
#if defined(TELEMETRY)
//parse telemetry packet here
frsky_check_telemetry(pkt,len); //check if valid telemetry packets and buffer them.
#endif
}
if(pkt[len-1] & 0x80)
{//with valid crc
packet_count=0;
frsky_check_telemetry(pkt,len); //check if valid telemetry packets and buffer them.
}
#endif
}
else
{
packet_count++;
// restart sequence on missed packet - might need count or timeout instead of one missed
if(packet_count>100)
{//~1sec
packet_count=0;
#if defined TELEMETRY
telemetry_link=0;//no link frames
pkt[6]=0;//no user frames.
#endif
}
}
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower(); // Set tx_power
}
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[counter % 47]);
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack

View File

@@ -27,50 +27,6 @@ enum {
#include "iface_cc2500.h"
const PROGMEM uint8_t FRSKYV_cc2500_conf[][2]={
{ CC2500_17_MCSM1, 0x0c },
{ CC2500_18_MCSM0, 0x18 },
{ CC2500_06_PKTLEN, 0xff },
{ CC2500_07_PKTCTRL1, 0x04 },
{ CC2500_08_PKTCTRL0, 0x05 },
{ CC2500_3E_PATABLE, 0xfe },
{ CC2500_0B_FSCTRL1, 0x08 },
{ CC2500_0C_FSCTRL0, 0x00 },
{ CC2500_0D_FREQ2, 0x5c },
{ CC2500_0E_FREQ1, 0x58 },
{ CC2500_0F_FREQ0, 0x9d },
{ CC2500_10_MDMCFG4, 0xaa },
{ CC2500_11_MDMCFG3, 0x10 },
{ CC2500_12_MDMCFG2, 0x93 },
{ CC2500_13_MDMCFG1, 0x23 },
{ CC2500_14_MDMCFG0, 0x7a },
{ CC2500_15_DEVIATN, 0x41 }
};
static void __attribute__((unused)) FRSKYV_init()
{
for(uint8_t i=0;i<17;i++)
{
uint8_t reg=pgm_read_byte_near(&FRSKYV_cc2500_conf[i][0]);
uint8_t val=pgm_read_byte_near(&FRSKYV_cc2500_conf[i][1]);
if(reg==CC2500_0C_FSCTRL0)
val=option;
CC2500_WriteReg(reg,val);
}
prev_option = option ;
for(uint8_t i=19;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]);
CC2500_WriteReg(reg,val);
}
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
CC2500_Strobe(CC2500_SIDLE); // Go to idle...
}
static uint8_t __attribute__((unused)) FRSKYV_crc8(uint8_t result, uint8_t *data, uint8_t len)
{
for(uint8_t i = 0; i < len; i++)
@@ -199,7 +155,7 @@ uint16_t initFRSKYV()
rx_tx_addr[2]&=0x7F;
crc8 = FRSKYV_crc8_le(rx_tx_addr+2, 2);
FRSKYV_init();
FRSKY_init_cc2500(FRSKYV_cc2500_conf);
seed = 1;
binding_idx=0;
phase = FRSKYV_DATA1;

View File

@@ -21,85 +21,28 @@
#include "iface_cc2500.h"
uint8_t chanskip;
uint8_t counter_rst;
uint8_t ctr;
uint8_t seq_last_sent;
uint8_t seq_last_rcvd;
const PROGMEM uint8_t hop_data[]={
0x02, 0xD4, 0xBB, 0xA2, 0x89,
0x70, 0x57, 0x3E, 0x25, 0x0C,
0xDE, 0xC5, 0xAC, 0x93, 0x7A,
0x61, 0x48, 0x2F, 0x16, 0xE8,
0xCF, 0xB6, 0x9D, 0x84, 0x6B,
0x52, 0x39, 0x20, 0x07, 0xD9,
0xC0, 0xA7, 0x8E, 0x75, 0x5C,
0x43, 0x2A, 0x11, 0xE3, 0xCA,
0xB1, 0x98, 0x7F, 0x66, 0x4D,
0x34, 0x1B, 0x00, 0x1D, 0x03
};
static uint8_t __attribute__((unused)) hop(uint8_t byte)
{
return pgm_read_byte_near(&hop_data[byte]);
}
static void __attribute__((unused)) set_start(uint8_t ch )
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]);
CC2500_WriteReg(CC2500_0A_CHANNR, ch==47? 0:hop(ch));
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
}
static void __attribute__((unused)) frskyX_init()
{
for(uint8_t i=0;i<36;i++)
{
uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]);
uint8_t val=pgm_read_byte_near(&cc2500_conf[i][1]);
if(reg==CC2500_06_PKTLEN)
val=0x1E;
else
if(reg==CC2500_08_PKTCTRL0)
val=0x01;
else
if(reg==CC2500_0B_FSCTRL1)
val=0x0A;
else
if(reg==CC2500_10_MDMCFG4)
val=0x7B;
else
if(reg==CC2500_11_MDMCFG3)
val=0x61;
else
if(reg==CC2500_12_MDMCFG2)
val=0x13;
else
if(reg==CC2500_15_DEVIATN)
val=0x51;
CC2500_WriteReg(reg,val);
}
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x04);
prev_option = option ;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_Strobe(CC2500_SIDLE);
FRSKY_init_cc2500((sub_protocol&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC
//
for(uint8_t c=0;c < 47;c++)
for(uint8_t c=0;c < 48;c++)
{//calibrate hop channels
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR,hop(c));
CC2500_WriteReg(CC2500_0A_CHANNR,hopping_frequency[c]);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);//
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
}
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR,0x00);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
calData[47] = CC2500_ReadReg(CC2500_25_FSCAL1);
//#######END INIT########
}
@@ -140,27 +83,28 @@ static uint16_t __attribute__((unused)) scaleForPXX( uint8_t i )
static void __attribute__((unused)) frskyX_build_bind_packet()
{
packet[0] = 0x1D;
packet[1] = 0x03;
packet[2] = 0x01;
//
packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC
packet[1] = 0x03;
packet[2] = 0x01;
//
packet[3] = rx_tx_addr[3];
packet[4] = rx_tx_addr[2];
int idx = ((state -FRSKY_BIND) % 10) * 5;
packet[5] = idx;
packet[6] = hop(idx++);
packet[7] = hop(idx++);
packet[8] = hop(idx++);
packet[9] = hop(idx++);
packet[10] = hop(idx++);
packet[5] = idx;
packet[6] = hopping_frequency[idx++];
packet[7] = hopping_frequency[idx++];
packet[8] = hopping_frequency[idx++];
packet[9] = hopping_frequency[idx++];
packet[10] = hopping_frequency[idx++];
packet[11] = 0x02;
packet[12] = RX_num;
//
memset(&packet[13], 0, 15);
uint16_t lcrc = crc_x(&packet[3], 25);
uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ;
memset(&packet[13], 0, limit - 13);
uint16_t lcrc = crc_x(&packet[3], limit-3);
//
packet[28] = lcrc >> 8;
packet[29] = lcrc;
packet[limit++] = lcrc >> 8;
packet[limit] = lcrc;
//
}
@@ -173,13 +117,13 @@ static void __attribute__((unused)) frskyX_data_frame()
uint16_t chan_1 ;
uint8_t startChan = 0;
//
packet[0] = 0x1D;
packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = 0x02;
//
packet[4] = (ctr<<6)+hopping_frequency_no;
packet[5] = counter_rst;
packet[4] = (chanskip<<6)|hopping_frequency_no;
packet[5] = chanskip>>2;
packet[6] = RX_num;
//packet[7] = FLAGS 00 - standard packet
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
@@ -213,17 +157,18 @@ static void __attribute__((unused)) frskyX_data_frame()
else if (seq_last_rcvd == 0x00)
seq_last_sent = 1;
if(sub_protocol== CH_8 )// in X8 mode send only 8ch every 9ms
if(sub_protocol & 1 )// in X8 mode send only 8ch every 9ms
lpass = 0 ;
else
lpass += 1 ;
for (uint8_t i=22;i<28;i++)
uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ;
for (uint8_t i=22;i<limit;i++)
packet[i]=0;
uint16_t lcrc = crc_x(&packet[3], 25);
uint16_t lcrc = crc_x(&packet[3], limit-3);
packet[28]=lcrc>>8;//high byte
packet[29]=lcrc;//low byte
packet[limit++]=lcrc>>8;//high byte
packet[limit]=lcrc;//low byte
}
uint16_t ReadFrSkyX()
@@ -238,7 +183,10 @@ uint16_t ReadFrSkyX()
frskyX_build_bind_packet();
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteData(packet, packet[0]+1);
state++;
if(IS_BIND_DONE_on)
state = FRSKY_BIND_DONE;
else
state++;
return 9000;
case FRSKY_BIND_DONE:
initialize_data(0);
@@ -276,7 +224,7 @@ uint16_t ReadFrSkyX()
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
{
counter=0;
packet_count=0;
CC2500_ReadData(pkt, len);
#if defined TELEMETRY
frsky_check_telemetry(pkt,len); //check if valid telemetry packets
@@ -286,13 +234,13 @@ uint16_t ReadFrSkyX()
}
else
{
counter++;
packet_count++;
// restart sequence on missed packet - might need count or timeout instead of one missed
if(counter>100)
if(packet_count>100)
{//~1sec
seq_last_sent = 0;
seq_last_rcvd = 8;
counter=0;
packet_count=0;
#if defined TELEMETRY
telemetry_lost=1;
#endif
@@ -307,18 +255,17 @@ uint16_t ReadFrSkyX()
uint16_t initFrSkyX()
{
set_rx_tx_addr(MProtocol_id_master);
Frsky_init_hop();
packet_count=0;
while(!chanskip)
chanskip=random(0xfefefefe)%47;
while((chanskip-ctr)%4)
ctr=(ctr+1)%4;
counter_rst=(chanskip-ctr)>>2;
//for test***************
//rx_tx_addr[3]=0xB3;
//rx_tx_addr[2]=0xFD;
//************************
frskyX_init();
CC2500_SetTxRxMode(TX_EN);
//
if(IS_AUTOBIND_FLAG_on)
{

View File

@@ -0,0 +1,158 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// Compatible with Global Drone GW008 protocol.
// There are 3 versions of this small quad, this protocol is for the one with a XNS104 IC in the stock Tx and PAN159CY IC in the quad (SOCs with built-in xn297 compatible RF).
// The xn297 version is compatible with the CX10 protocol (green pcb).
// The LT8910 version is not supported yet.
#if defined(GW008_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define GW008_INITIAL_WAIT 500
#define GW008_PACKET_PERIOD 2400
#define GW008_RF_BIND_CHANNEL 2
#define GW008_PAYLOAD_SIZE 15
enum {
GW008_BIND1,
GW008_BIND2,
GW008_DATA
};
static void __attribute__((unused)) send_packet(uint8_t bind)
{
packet[0] = rx_tx_addr[0];
if(bind)
{
packet[1] = 0x55;
packet[2] = hopping_frequency[0];
packet[3] = hopping_frequency[1];
packet[4] = hopping_frequency[2];
packet[5] = hopping_frequency[3];
memset(&packet[6], 0, 7);
packet[13] = 0xaa;
}
else
{
packet[1] = 0x01 | GET_FLAG(AUX1, 0x40); // flip
packet[2] = convert_channel_8b_scale(AILERON , 200, 0); // aileron
packet[3] = convert_channel_8b_scale(ELEVATOR, 0, 200); // elevator
packet[4] = convert_channel_8b_scale(RUDDER , 200, 0); // rudder
packet[5] = convert_channel_8b_scale(THROTTLE, 0, 200); // throttle
packet[6] = 0xaa;
packet[7] = 0x02; // max rate
packet[8] = 0x00;
packet[9] = 0x00;
packet[10]= 0x00;
packet[11]= 0x00;
packet[12]= 0x00;
packet[13]= rx_tx_addr[2];
}
packet[14] = rx_tx_addr[1];
// Power on, TX mode, CRC enabled
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? GW008_RF_BIND_CHANNEL : hopping_frequency[(hopping_frequency_no++)/2]);
hopping_frequency_no %= 8;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WriteEnhancedPayload(packet, GW008_PAYLOAD_SIZE, 0, 0x3c7d);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) GW008_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
XN297_SetRXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
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_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, GW008_PAYLOAD_SIZE+2); // payload + 2 bytes for pcf
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_1M);
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits on
NRF24L01_Activate(0x73);
}
static void __attribute__((unused)) GW008_initialize_txid()
{
uint32_t lfsr = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16);
for(uint8_t i=0; i<4; i++)
hopping_frequency[i] = 0x10 + ((lfsr >> (i*8)) % 0x37);
}
uint16_t GW008_callback()
{
switch(phase)
{
case GW008_BIND1:
if((NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) && // RX fifo data ready
XN297_ReadEnhancedPayload(packet, GW008_PAYLOAD_SIZE) == GW008_PAYLOAD_SIZE && // check payload size
packet[0] == rx_tx_addr[0] && packet[14] == rx_tx_addr[1]) // check tx id
{
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
rx_tx_addr[2] = packet[13];
BIND_DONE;
phase = GW008_DATA;
}
else
{
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
send_packet(1);
phase = GW008_BIND2;
return 300;
}
break;
case GW008_BIND2:
// switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)
| _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
phase = GW008_BIND1;
return 5000;
break;
case GW008_DATA:
send_packet(0);
break;
}
return GW008_PACKET_PERIOD;
}
uint16_t initGW008()
{
BIND_IN_PROGRESS; // autobind protocol
GW008_initialize_txid();
phase = GW008_BIND1;
GW008_init();
hopping_frequency_no = 0;
return GW008_INITIAL_WAIT;
}
#endif

View File

@@ -352,7 +352,7 @@ uint16_t initHubsan() {
packet_count=0;
id_data=ID_NORMAL;
#ifdef HUBSAN_HUB_TELEMETRY
init_hub_telemetry();
init_frskyd_link_telemetry();
#endif
return 10000;
}

View File

@@ -261,7 +261,8 @@ uint16_t initMT99XX(void)
bind_counter = MT99XX_BIND_COUNT;
memcpy(hopping_frequency,"\x02\x48\x0C\x3e\x16\x34\x20\x2A\x2A\x20\x34\x16\x3e\x0c\x48\x02",16);
hopping_frequency_no=0;
MT99XX_initialize_txid();
MT99XX_init();

View File

@@ -598,7 +598,7 @@ clean_list :
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lss
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
$(REMOVE) $(CPPSRC:%.cpp=%.o)
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)

View File

@@ -12,7 +12,7 @@
12,CX10,GREEN,BLUE,DM007,---,J3015_1,J3015_2,MK33041
13,CG023,CG023,YD829,H8_3D
14,Bayang,Bayang,H8S3D
15,FrskyX,CH_16,CH_8
15,FrskyX,CH_16,CH_8,EU_16,EU_8
16,ESky
17,MT99xx,MT,H7,YZ,LS,FY805
18,MJXq,WLH08,X600,X800,H26D,E010,H26WH
@@ -26,4 +26,7 @@
26,HONTAI,HONTAI,JJRCX1,X5C1,FQ777_951
27,OpnLrs
28,AFHD2SA,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS
29,Q2X2,Q242,Q282
29,Q2X2,Q222,Q242,Q282
30,WK2x01,WK2801,WK2401,W6_5_1,W6_6_1,W6_HEL,W6_HEL_I
31,Q303,Q303,CX35,CX10D,CX10WD
32,GW008

View File

@@ -34,6 +34,8 @@ extern uint16_t DevoInit(void) ;
extern uint16_t devo_callback(void) ;
extern uint16_t initJ6Pro(void) ;
extern uint16_t ReadJ6Pro(void) ;
extern uint16_t WK_setup(void) ;
extern uint16_t WK_cb(void) ;
extern void randomSeed(unsigned int seed) ;
extern long random(long howbig) ;
@@ -46,7 +48,7 @@ extern void delayMilliseconds(unsigned long ms) ;
extern void init(void) ;
extern void modules_reset() ;
extern void Update_All() ;
extern uint8_t Update_All() ;
extern void tx_pause() ;
extern void tx_resume() ;
extern void TelemetryUpdate() ;
@@ -139,13 +141,14 @@ void init()
#include "Multiprotocol.ino"
#include "SPI.ino"
#include "Convert.ino"
#include "Common.ino"
#include "Arduino.ino"
#include "cyrf6936_SPI.ino"
#include "DSM_cyrf6936.ino"
#include "Devo_cyrf6936.ino"
#include "J6Pro_cyrf6936.ino"
#include "WK2x01_cyrf6936.ino"
#include "Telemetry.ino"

View File

@@ -17,9 +17,9 @@
// Version
//******************
#define VERSION_MAJOR 1
#define VERSION_MINOR 16
#define VERSION_PATCH_LEVEL 1
#define VERSION_MINOR 1
#define VERSION_REVISION 6
#define VERSION_PATCH_LEVEL 20
//******************
// Protocols
//******************
@@ -55,6 +55,9 @@ enum PROTOCOLS
MODE_OPENLRS = 27, // =>OpenLRS hardware
MODE_AFHDS2A = 28, // =>A7105
MODE_Q2X2 = 29, // =>NRF24L01, extension of CX-10 protocol
MODE_WK2x01 = 30, // =>CYRF6936
MODE_Q303 = 31, // =>NRF24L01
MODE_GW008 = 32, // =>NRF24L01
MODE_CABELL = 33, // =>NRF24L01
};
@@ -156,6 +159,8 @@ enum FRSKYX
{
CH_16 = 0,
CH_8 = 1,
EU_16 = 2,
EU_8 = 3,
};
enum HONTAI
{
@@ -174,6 +179,22 @@ enum FY326
FY326 = 0,
FY319 = 1,
};
enum WK2x01
{
WK2801 = 0,
WK2401 = 1,
W6_5_1 = 2,
W6_6_1 = 3,
W6_HEL = 4,
W6_HEL_I= 5,
};
enum Q303
{
Q303 = 0,
CX35 = 1,
CX10D = 2,
CX10WD = 3,
};
enum CABELL
{
CABELL_V3 = 0,
@@ -271,6 +292,17 @@ enum MultiPacketTypes {
#define INPUT_SIGNAL_on protocol_flags2 |= _BV(5)
#define IS_INPUT_SIGNAL_on ( ( protocol_flags2 & _BV(5) ) !=0 )
#define IS_INPUT_SIGNAL_off ( ( protocol_flags2 & _BV(5) ) ==0 )
//Bind from channel
#define BIND_CH_PREV_off protocol_flags2 &= ~_BV(6)
#define BIND_CH_PREV_on protocol_flags2 |= _BV(6)
#define IS_BIND_CH_PREV_on ( ( protocol_flags2 & _BV(6) ) !=0 )
#define IS_BIND_CH_PREV_off ( ( protocol_flags2 & _BV(6) ) ==0 )
//Wait for bind
#define WAIT_BIND_off protocol_flags2 &= ~_BV(7)
#define WAIT_BIND_on protocol_flags2 |= _BV(7)
#define IS_WAIT_BIND_on ( ( protocol_flags2 & _BV(7) ) !=0 )
#define IS_WAIT_BIND_off ( ( protocol_flags2 & _BV(7) ) ==0 )
//********************
//*** Blink timing ***
@@ -278,8 +310,11 @@ enum MultiPacketTypes {
#define BLINK_BIND_TIME 100
#define BLINK_SERIAL_TIME 500
#define BLINK_PPM_TIME 1000
#define BLINK_BAD_PROTO_TIME_LOW 1000
#define BLINK_BAD_PROTO_TIME_HIGH 50
#define BLINK_BAD_PROTO_TIME_LOW 1000
#define BLINK_WAIT_BIND_TIME_HIGH 1000
#define BLINK_WAIT_BIND_TIME_LOW 100
//*******************
//*** AUX flags ***
@@ -449,6 +484,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
OpenLRS 27
AFHDS2A 28
Q2X2 29
WK2x01 30
Q303 31
GW008 32
CABELL 33
BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No
@@ -521,6 +559,8 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
sub_protocol==FRSKYX
CH_16 0
CH_8 1
EU_16 2
EU_8 3
sub_protocol==HONTAI
FORMAT_HONTAI 0
FORMAT_JJRCX1 1
@@ -537,6 +577,18 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
sub_protocol==FY326
FY326 0
FY319 1
sub_protocol==WK2x01
WK2801 0
WK2401 1
W6_5_1 2
W6_6_1 3
W6_HEL 4
W6_HEL_I 5
sub_protocol==Q303
Q303 0
CX35 1
CX10D 2
CX10WD 3
sub_protocol==CABELL
CABELL_V3 0,
CABELL_SET_FAIL_SAFE 6,
@@ -544,7 +596,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
Power value => 0x80 0=High/1=Low
Stream[3] = option_protocol;
option_protocol value is -127..127
option_protocol value is -128..127
Stream[4] to [25] = Channels
16 Channels on 11 bits (0..2047)
0 -125%
@@ -555,18 +607,41 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
Channels bits are concatenated to fit in 22 bytes like in SBUS protocol
*/
/*
Multiprotocol telemetry definition
Multimodule Status
Based on #define MULTI_STATUS
Serial: 100000 Baud 8e2 (same as input)
Format: header (2 bytes) + data (variable)
[0] = 'M' (0x4d)
[1] Length (excluding the 2 header bytes)
[2-xx] data
Type = 0x01 Multimodule Status:
[2] Flags
0x01 = Input signal detected
0x02 = Serial mode enabled
0x04 = protocol is valid
0x08 = module is in binding mode
0x10 = module waits a bind event to load the protocol
[3] major
[4] minor
[5] revision
[6] patchlevel,
version of multi code, should be displayed as major.minor.revision.patchlevel
*/
/*
Multiprotocol telemetry definition for OpenTX
Based on #define MULTI_TELEMETRY enables OpenTX to get the multimodule status and select the correct telemetry type automatically.
Serial: 100000 Baud 8e2 (same as input)
TLV Protocol (type, length, value), allows a TX to ignore unknown messages
Format: header (4 byte) + data (variable)
[0] = 'M' (0x4d)
[1] = 'P' (0x50)
The first byte is deliberatly chosen to be different from other telemetry protocols
(e.g. 0xAA for DSM/Multi, 0xAA for FlySky and 0x7e for Frsky) to allow a TX to detect
the telemetry format of older versions
@@ -576,41 +651,41 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
[4-xx] data
Type = 0x01 Multimodule Status:
Type = 0x01 Multimodule Status:
[4] Flags
0x01 = Input signal detected
0x02 = Serial mode enabled
0x04 = protocol is valid
0x08 = module is in binding mode
0x10 = module waits a bind event to load the protocol
[5] major
[6] minor
[7-8] patchlevel
version of multi code, should be displayed as major.minor.patchlevel
[7] revision
[8] patchlevel,
version of multi code, should be displayed as major.minor.revision.patchlevel
more information can be added by specifing a longer length of the type, the TX will just ignore these bytes
Type 0x02 Frksy S.port telemetry
Type 0x03 Frsky Hub telemetry
Type 0x02 Frksy S.port telemetry
Type 0x03 Frsky Hub telemetry
*No* usual frsky byte stuffing and without start/stop byte (0x7e)
Type 0x04 Spektrum telemetry data
Type 0x04 Spektrum telemetry data
data[0] RSSI
data[1-15] telemetry data
Type 0x05 DSM bind data
Type 0x05 DSM bind data
data[0-16] DSM bind data
technically DSM bind data is only 10 bytes but multi send 16
like with telemtry, check length field)
Type 0x06 Flysky AFHDS2 telemetry data
Type 0x06 Flysky AFHDS2 telemetry data
length: 29
data[0] = RSSI value
data[1-28] telemetry data
*/
*/

View File

@@ -26,6 +26,9 @@
//Multiprotocol module configuration file
#include "_Config.h"
#ifdef __arm__
#define STM32_BOARD // Let's automatically select this board if arm is selected since this is the only one for now...
#endif
#include "Pins.h"
#include "TX_Def.h"
#include "Validate.h"
@@ -76,7 +79,7 @@ uint16_t packet_period;
uint8_t packet_count;
uint8_t packet_sent;
uint8_t packet_length;
uint8_t hopping_frequency[23];
uint8_t hopping_frequency[50];
uint8_t *hopping_frequency_ptr;
uint8_t hopping_frequency_no=0;
uint8_t rf_ch_num;
@@ -140,16 +143,29 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets
#endif
uint8_t pass = 0;
uint8_t pktt[MAX_PKT];//telemetry receiving packets
#ifndef BASH_SERIAL
#define TXBUFFER_SIZE 32
#ifdef BASH_SERIAL
// For bit-bashed serial output
#define TXBUFFER_SIZE 128
volatile struct t_serial_bash
{
uint8_t head ;
uint8_t tail ;
uint8_t data[TXBUFFER_SIZE] ;
uint8_t busy ;
uint8_t speed ;
} SerialControl ;
#else
#define TXBUFFER_SIZE 64
volatile uint8_t tx_buff[TXBUFFER_SIZE];
volatile uint8_t tx_head=0;
volatile uint8_t tx_tail=0;
#endif // BASH_SERIAL
uint8_t v_lipo1;
uint8_t v_lipo2;
int16_t RSSI_dBm;
uint8_t RX_RSSI;
uint8_t TX_RSSI;
uint8_t RX_LQI;
uint8_t TX_LQI;
uint8_t telemetry_link=0;
uint8_t telemetry_counter=0;
uint8_t telemetry_lost;
@@ -219,17 +235,17 @@ void setup()
// outputs
SDI_output;
SCLK_output;
#ifdef A7105_INSTALLED
#ifdef A7105_CSN_pin
A7105_CSN_output;
#endif
#ifdef CC2500_INSTALLED
#ifdef CC25_CSN_pin
CC25_CSN_output;
#endif
#ifdef CYRF6936_INSTALLED
#ifdef CYRF_CSN_pin
CYRF_RST_output;
CYRF_CSN_output;
#endif
#ifdef NRF24L01_INSTALLED
#ifdef NRF_CSN_pin
NRF_CSN_output;
#endif
PE1_output;
@@ -252,16 +268,16 @@ void setup()
#endif
// Set Chip selects
#ifdef A7105_INSTALLED
#ifdef A7105_CSN_pin
A7105_CSN_on;
#endif
#ifdef CC2500_INSTALLED
#ifdef CC25_CSN_pin
CC25_CSN_on;
#endif
#ifdef CYRF6936_INSTALLED
#ifdef CYRF_CSN_pin
CYRF_CSN_on;
#endif
#ifdef NRF24L01_INSTALLED
#ifdef NRF_CSN_pin
NRF_CSN_on;
#endif
// Set SPI lines
@@ -380,13 +396,13 @@ void loop()
while(1)
{
if(remote_callback==0 || diff>2*200)
if(remote_callback==0 || IS_WAIT_BIND_on || diff>2*200)
{
do
{
Update_All();
}
while(remote_callback==0);
while(remote_callback==0 || IS_WAIT_BIND_on);
}
#ifndef STM32_BOARD
if( (TIFR1 & OCF1A_bm) != 0)
@@ -411,7 +427,7 @@ void loop()
{
TX_MAIN_PAUSE_on;
tx_pause();
if(IS_INPUT_SIGNAL_on)
if(IS_INPUT_SIGNAL_on && remote_callback!=0)
next_callback=remote_callback();
else
next_callback=2000; // No PPM/serial signal check again in 2ms...
@@ -428,9 +444,11 @@ void loop()
TIMER2_BASE->SR &= ~TIMER_SR_CC1IF; //clear compare Flag
#endif
sei(); // enable global int
Update_All();
if(IS_CHANGE_PROTOCOL_FLAG_on)
break; // Protocol has been changed
if(Update_All()) // Protocol changed?
{
next_callback=0; // Launch new protocol ASAP
break;
}
#ifndef STM32_BOARD
while((TIFR1 & OCF1A_bm) == 0); // wait 2ms...
#else
@@ -454,18 +472,13 @@ void loop()
}
}
void Update_All()
uint8_t Update_All()
{
#ifdef ENABLE_SERIAL
if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received
{
update_serial_data(); // Update protocol and data
if(IS_CHANGE_PROTOCOL_FLAG_on)
{ // Protocol needs to be changed
LED_off; //led off during protocol init
modules_reset(); //reset all modules
protocol_init(); //init new protocol
}
update_channels_aux();
INPUT_SIGNAL_on; //valid signal received
last_signal=millis();
}
@@ -473,7 +486,7 @@ void Update_All()
#ifdef ENABLE_PPM
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++)
for(uint8_t i=0;i<MAX_PPM_CHANNELS;i++)
{ // update servo data without interrupts to prevent bad read in protocols
uint16_t temp_ppm ;
cli(); // disable global int
@@ -484,18 +497,42 @@ void Update_All()
Servo_data[i]= temp_ppm ;
}
PPM_FLAG_off; // wait for next frame before update
update_channels_aux();
INPUT_SIGNAL_on; //valid signal received
last_signal=millis();
}
#endif //ENABLE_PPM
update_channels_aux();
update_led_status();
#if defined(TELEMETRY)
#if !defined(MULTI_TELEMETRY)
#if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) )
if((protocol==MODE_FRSKYD) || (protocol==MODE_BAYANG) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_FRSKYX) || (protocol==MODE_DSM) )
#endif
TelemetryUpdate();
TelemetryUpdate();
#endif
update_led_status();
#ifdef ENABLE_BIND_CH
if(IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_off && Servo_data[BIND_CH-1]>PPM_MAX_COMMAND && Servo_data[THROTTLE]<(servo_min_100+25))
{ // Autobind is on and BIND_CH went up and Throttle is low
CHANGE_PROTOCOL_FLAG_on; //reload protocol to rebind
BIND_CH_PREV_on;
}
if(IS_BIND_CH_PREV_on && Servo_data[BIND_CH-1]<PPM_MIN_COMMAND)
{
BIND_CH_PREV_off;
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO)
if(protocol==MODE_FRSKYD || protocol==MODE_FRSKYX || protocol==MODE_FRSKYV)
BIND_DONE;
else
#endif
if(bind_counter>2)
bind_counter=2;
}
#endif //ENABLE_BIND_CH
if(IS_CHANGE_PROTOCOL_FLAG_on)
{ // Protocol needs to be changed or relaunched for bind
protocol_init(); //init new protocol
return 1;
}
return 0;
}
// Update channels direction and Servo_AUX flags based on servo AUX positions
@@ -546,9 +583,19 @@ static void update_led_status(void)
}
else
{
if(IS_BIND_DONE_on)
LED_off; //bind completed force led on
blink+=BLINK_BIND_TIME; //blink fastly during binding
if(IS_WAIT_BIND_on)
{
if(IS_LED_on) //flash to indicate WAIT_BIND
blink+=BLINK_WAIT_BIND_TIME_LOW;
else
blink+=BLINK_WAIT_BIND_TIME_HIGH;
}
else
{
if(IS_BIND_DONE_on)
LED_off; //bind completed force led on
blink+=BLINK_BIND_TIME; //blink fastly during binding
}
}
LED_toggle;
}
@@ -615,252 +662,312 @@ void start_timer2()
// Protocol start
static void protocol_init()
{
uint16_t next_callback=0; // Default is immediate call back
remote_callback = 0;
// reset telemetry
#ifdef TELEMETRY
tx_pause();
pass=0;
telemetry_link=0;
telemetry_lost=1;
#ifndef BASH_SERIAL
tx_tail=0;
tx_head=0;
#endif
TX_RX_PAUSE_off;
TX_MAIN_PAUSE_off;
#endif
//Set global ID and rx_tx_addr
MProtocol_id = RX_num + MProtocol_id_master;
set_rx_tx_addr(MProtocol_id);
blink=millis();
if(IS_BIND_BUTTON_FLAG_on)
AUTOBIND_FLAG_on;
if(IS_AUTOBIND_FLAG_on)
BIND_IN_PROGRESS; // Indicates bind in progress for blinking bind led
else
BIND_DONE;
PE1_on; //NRF24L01 antenna RF3 by default
PE2_off; //NRF24L01 antenna RF3 by default
switch(protocol) // Init the requested protocol
static uint16_t next_callback;
if(IS_WAIT_BIND_off)
{
#ifdef A7105_INSTALLED
#if defined(FLYSKY_A7105_INO)
case MODE_FLYSKY:
PE1_off; //antenna RF1
next_callback = initFlySky();
remote_callback = ReadFlySky;
break;
#endif
#if defined(AFHDS2A_A7105_INO)
case MODE_AFHDS2A:
PE1_off; //antenna RF1
next_callback = initAFHDS2A();
remote_callback = ReadAFHDS2A;
break;
#endif
#if defined(HUBSAN_A7105_INO)
case MODE_HUBSAN:
PE1_off; //antenna RF1
if(IS_BIND_BUTTON_FLAG_on) random_id(10,true); // Generate new ID if bind button is pressed.
next_callback = initHubsan();
remote_callback = ReadHubsan;
break;
remote_callback = 0; // No protocol
next_callback=0; // Default is immediate call back
LED_off; // Led off during protocol init
modules_reset(); // Reset all modules
// reset telemetry
#ifdef TELEMETRY
tx_pause();
pass=0;
telemetry_link=0;
telemetry_lost=1;
#ifdef BASH_SERIAL
TIMSK0 = 0 ; // Stop all timer 0 interrupts
#ifdef INVERT_SERIAL
SERIAL_TX_off;
#else
SERIAL_TX_on;
#endif
SerialControl.tail=0;
SerialControl.head=0;
SerialControl.busy=0;
#else
tx_tail=0;
tx_head=0;
#endif
TX_RX_PAUSE_off;
TX_MAIN_PAUSE_off;
#endif
#ifdef CC2500_INSTALLED
#if defined(FRSKYD_CC2500_INO)
case MODE_FRSKYD:
PE1_off; //antenna RF2
PE2_on;
next_callback = initFrSky_2way();
remote_callback = ReadFrSky_2way;
break;
//Set global ID and rx_tx_addr
MProtocol_id = RX_num + MProtocol_id_master;
set_rx_tx_addr(MProtocol_id);
blink=millis();
if(IS_BIND_BUTTON_FLAG_on)
AUTOBIND_FLAG_on;
if(IS_AUTOBIND_FLAG_on)
BIND_IN_PROGRESS; // Indicates bind in progress for blinking bind led
else
BIND_DONE;
PE1_on; //NRF24L01 antenna RF3 by default
PE2_off; //NRF24L01 antenna RF3 by default
switch(protocol) // Init the requested protocol
{
#ifdef A7105_INSTALLED
#if defined(FLYSKY_A7105_INO)
case MODE_FLYSKY:
PE1_off; //antenna RF1
next_callback = initFlySky();
remote_callback = ReadFlySky;
break;
#endif
#if defined(AFHDS2A_A7105_INO)
case MODE_AFHDS2A:
PE1_off; //antenna RF1
next_callback = initAFHDS2A();
remote_callback = ReadAFHDS2A;
break;
#endif
#if defined(HUBSAN_A7105_INO)
case MODE_HUBSAN:
PE1_off; //antenna RF1
if(IS_BIND_BUTTON_FLAG_on) random_id(10,true); // Generate new ID if bind button is pressed.
next_callback = initHubsan();
remote_callback = ReadHubsan;
break;
#endif
#endif
#if defined(FRSKYV_CC2500_INO)
case MODE_FRSKYV:
PE1_off; //antenna RF2
PE2_on;
next_callback = initFRSKYV();
remote_callback = ReadFRSKYV;
break;
#ifdef CC2500_INSTALLED
#if defined(FRSKYD_CC2500_INO)
case MODE_FRSKYD:
PE1_off; //antenna RF2
PE2_on;
next_callback = initFrSky_2way();
remote_callback = ReadFrSky_2way;
break;
#endif
#if defined(FRSKYV_CC2500_INO)
case MODE_FRSKYV:
PE1_off; //antenna RF2
PE2_on;
next_callback = initFRSKYV();
remote_callback = ReadFRSKYV;
break;
#endif
#if defined(FRSKYX_CC2500_INO)
case MODE_FRSKYX:
PE1_off; //antenna RF2
PE2_on;
next_callback = initFrSkyX();
remote_callback = ReadFrSkyX;
break;
#endif
#if defined(SFHSS_CC2500_INO)
case MODE_SFHSS:
PE1_off; //antenna RF2
PE2_on;
next_callback = initSFHSS();
remote_callback = ReadSFHSS;
break;
#endif
#endif
#if defined(FRSKYX_CC2500_INO)
case MODE_FRSKYX:
PE1_off; //antenna RF2
PE2_on;
next_callback = initFrSkyX();
remote_callback = ReadFrSkyX;
break;
#endif
#if defined(SFHSS_CC2500_INO)
case MODE_SFHSS:
PE1_off; //antenna RF2
PE2_on;
next_callback = initSFHSS();
remote_callback = ReadSFHSS;
break;
#endif
#endif
#ifdef CYRF6936_INSTALLED
#if defined(DSM_CYRF6936_INO)
case MODE_DSM:
PE2_on; //antenna RF4
next_callback = initDsm();
//Servo_data[2]=1500;//before binding
remote_callback = ReadDsm;
break;
#endif
#if defined(DEVO_CYRF6936_INO)
case MODE_DEVO:
#ifdef ENABLE_PPM
if(mode_select) //PPM mode
{
if(IS_BIND_BUTTON_FLAG_on)
#ifdef CYRF6936_INSTALLED
#if defined(DSM_CYRF6936_INO)
case MODE_DSM:
PE2_on; //antenna RF4
next_callback = initDsm();
//Servo_data[2]=1500;//before binding
remote_callback = ReadDsm;
break;
#endif
#if defined(DEVO_CYRF6936_INO)
case MODE_DEVO:
#ifdef ENABLE_PPM
if(mode_select) //PPM mode
{
eeprom_write_byte((EE_ADDR)(30+mode_select),0x00); // reset to autobind mode for the current model
option=0;
if(IS_BIND_BUTTON_FLAG_on)
{
eeprom_write_byte((EE_ADDR)(30+mode_select),0x00); // reset to autobind mode for the current model
option=0;
}
else
{
option=eeprom_read_byte((EE_ADDR)(30+mode_select)); // load previous mode: autobind or fixed id
if(option!=1) option=0; // if not fixed id mode then it should be autobind
}
}
else
{
option=eeprom_read_byte((EE_ADDR)(30+mode_select)); // load previous mode: autobind or fixed id
if(option!=1) option=0; // if not fixed id mode then it should be autobind
#endif //ENABLE_PPM
PE2_on; //antenna RF4
next_callback = DevoInit();
remote_callback = devo_callback;
break;
#endif
#if defined(WK2x01_CYRF6936_INO)
case MODE_WK2x01:
#ifdef ENABLE_PPM
if(mode_select) //PPM mode
{
if(IS_BIND_BUTTON_FLAG_on)
{
eeprom_write_byte((EE_ADDR)(30+mode_select),0x00); // reset to autobind mode for the current model
option=0;
}
else
{
option=eeprom_read_byte((EE_ADDR)(30+mode_select)); // load previous mode: autobind or fixed id
if(option!=1) option=0; // if not fixed id mode then it should be autobind
}
}
}
#endif //ENABLE_PPM
PE2_on; //antenna RF4
next_callback = DevoInit();
remote_callback = devo_callback;
break;
#endif //ENABLE_PPM
PE2_on; //antenna RF4
next_callback = WK_setup();
remote_callback = WK_cb;
break;
#endif
#if defined(J6PRO_CYRF6936_INO)
case MODE_J6PRO:
PE2_on; //antenna RF4
next_callback = initJ6Pro();
remote_callback = ReadJ6Pro;
break;
#endif
#endif
#if defined(J6PRO_CYRF6936_INO)
case MODE_J6PRO:
PE2_on; //antenna RF4
next_callback = initJ6Pro();
remote_callback = ReadJ6Pro;
break;
#ifdef NRF24L01_INSTALLED
#if defined(HISKY_NRF24L01_INO)
case MODE_HISKY:
next_callback=initHiSky();
remote_callback = hisky_cb;
break;
#endif
#if defined(V2X2_NRF24L01_INO)
case MODE_V2X2:
next_callback = initV2x2();
remote_callback = ReadV2x2;
break;
#endif
#if defined(YD717_NRF24L01_INO)
case MODE_YD717:
next_callback=initYD717();
remote_callback = yd717_callback;
break;
#endif
#if defined(KN_NRF24L01_INO)
case MODE_KN:
next_callback = initKN();
remote_callback = kn_callback;
break;
#endif
#if defined(SYMAX_NRF24L01_INO)
case MODE_SYMAX:
next_callback = initSymax();
remote_callback = symax_callback;
break;
#endif
#if defined(SLT_NRF24L01_INO)
case MODE_SLT:
next_callback=initSLT();
remote_callback = SLT_callback;
break;
#endif
#if defined(CX10_NRF24L01_INO)
case MODE_Q2X2:
sub_protocol|=0x08; // Increase the number of sub_protocols for CX-10
case MODE_CX10:
next_callback=initCX10();
remote_callback = CX10_callback;
break;
#endif
#if defined(CG023_NRF24L01_INO)
case MODE_CG023:
next_callback=initCG023();
remote_callback = CG023_callback;
break;
#endif
#if defined(BAYANG_NRF24L01_INO)
case MODE_BAYANG:
next_callback=initBAYANG();
remote_callback = BAYANG_callback;
break;
#endif
#if defined(ESKY_NRF24L01_INO)
case MODE_ESKY:
next_callback=initESKY();
remote_callback = ESKY_callback;
break;
#endif
#if defined(MT99XX_NRF24L01_INO)
case MODE_MT99XX:
next_callback=initMT99XX();
remote_callback = MT99XX_callback;
break;
#endif
#if defined(MJXQ_NRF24L01_INO)
case MODE_MJXQ:
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
#if defined(FY326_NRF24L01_INO)
case MODE_FY326:
next_callback=initFY326();
remote_callback = FY326_callback;
break;
#endif
#if defined(FQ777_NRF24L01_INO)
case MODE_FQ777:
next_callback=initFQ777();
remote_callback = FQ777_callback;
break;
#endif
#if defined(ASSAN_NRF24L01_INO)
case MODE_ASSAN:
next_callback=initASSAN();
remote_callback = ASSAN_callback;
break;
#endif
#if defined(HONTAI_NRF24L01_INO)
case MODE_HONTAI:
next_callback=initHONTAI();
remote_callback = HONTAI_callback;
break;
#endif
#if defined(Q303_NRF24L01_INO)
case MODE_Q303:
next_callback=initQ303();
remote_callback = Q303_callback;
break;
#endif
#if defined(GW008_NRF24L01_INO)
case MODE_GW008:
next_callback=initGW008();
remote_callback = GW008_callback;
break;
#endif
#if defined(CABELL_NRF24L01_INO)
case MODE_CABELL:
next_callback=initCABELL();
remote_callback = CABELL_callback;
break;
#endif
#endif
#endif
#ifdef NRF24L01_INSTALLED
#if defined(HISKY_NRF24L01_INO)
case MODE_HISKY:
next_callback=initHiSky();
remote_callback = hisky_cb;
break;
#endif
#if defined(V2X2_NRF24L01_INO)
case MODE_V2X2:
next_callback = initV2x2();
remote_callback = ReadV2x2;
break;
#endif
#if defined(YD717_NRF24L01_INO)
case MODE_YD717:
next_callback=initYD717();
remote_callback = yd717_callback;
break;
#endif
#if defined(KN_NRF24L01_INO)
case MODE_KN:
next_callback = initKN();
remote_callback = kn_callback;
break;
#endif
#if defined(SYMAX_NRF24L01_INO)
case MODE_SYMAX:
next_callback = initSymax();
remote_callback = symax_callback;
break;
#endif
#if defined(SLT_NRF24L01_INO)
case MODE_SLT:
next_callback=initSLT();
remote_callback = SLT_callback;
break;
#endif
#if defined(CX10_NRF24L01_INO)
case MODE_Q2X2:
sub_protocol|=0x08; // Increase the number of sub_protocols for CX-10
case MODE_CX10:
next_callback=initCX10();
remote_callback = CX10_callback;
break;
#endif
#if defined(CG023_NRF24L01_INO)
case MODE_CG023:
next_callback=initCG023();
remote_callback = CG023_callback;
break;
#endif
#if defined(BAYANG_NRF24L01_INO)
case MODE_BAYANG:
next_callback=initBAYANG();
remote_callback = BAYANG_callback;
break;
#endif
#if defined(ESKY_NRF24L01_INO)
case MODE_ESKY:
next_callback=initESKY();
remote_callback = ESKY_callback;
break;
#endif
#if defined(MT99XX_NRF24L01_INO)
case MODE_MT99XX:
next_callback=initMT99XX();
remote_callback = MT99XX_callback;
break;
#endif
#if defined(MJXQ_NRF24L01_INO)
case MODE_MJXQ:
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
#if defined(FY326_NRF24L01_INO)
case MODE_FY326:
next_callback=initFY326();
remote_callback = FY326_callback;
break;
#endif
#if defined(FQ777_NRF24L01_INO)
case MODE_FQ777:
next_callback=initFQ777();
remote_callback = FQ777_callback;
break;
#endif
#if defined(ASSAN_NRF24L01_INO)
case MODE_ASSAN:
next_callback=initASSAN();
remote_callback = ASSAN_callback;
break;
#endif
#if defined(HONTAI_NRF24L01_INO)
case MODE_HONTAI:
next_callback=initHONTAI();
remote_callback = HONTAI_callback;
break;
#endif
#if defined(CABELL_NRF24L01_INO)
case MODE_CABELL:
next_callback=initCABELL();
remote_callback = CABELL_callback;
break;
#endif
#endif
}
}
#if defined(WAIT_FOR_BIND) && defined(ENABLE_BIND_CH)
if( IS_AUTOBIND_FLAG_on && ! ( IS_BIND_CH_PREV_on || IS_BIND_BUTTON_FLAG_on || (cur_protocol[1]&0x80)!=0 ) )
{
WAIT_BIND_on;
return;
}
#endif
WAIT_BIND_off;
CHANGE_PROTOCOL_FLAG_off;
if(next_callback>32000)
{ // next_callback should not be more than 32767 so we will wait here...
uint16_t temp=(next_callback>>10)-2;
@@ -900,15 +1007,26 @@ void update_serial_data()
if( (rx_ok_buff[0] != cur_protocol[0]) || ((rx_ok_buff[1]&0x5F) != (cur_protocol[1]&0x5F)) || ( (rx_ok_buff[2]&0x7F) != (cur_protocol[2]&0x7F) ) )
{ // New model has been selected
CHANGE_PROTOCOL_FLAG_on; //change protocol
WAIT_BIND_off;
protocol=(rx_ok_buff[0]==0x55?0:32) + (rx_ok_buff[1]&0x1F); //protocol no (0-63) bits 4-6 of buff[1] and bit 0 of buf[0]
sub_protocol=(rx_ok_buff[2]>>4)& 0x07; //subprotocol no (0-7) bits 4-6
RX_num=rx_ok_buff[2]& 0x0F; // rx_num bits 0---3
}
else
if( ((rx_ok_buff[1]&0x80)!=0) && ((cur_protocol[1]&0x80)==0) ) // Bind flag has been set
if( ((rx_ok_buff[1]&0x80)!=0) && ((cur_protocol[1]&0x80)==0) ) // Bind flag has been set
CHANGE_PROTOCOL_FLAG_on; //restart protocol with bind
else
CHANGE_PROTOCOL_FLAG_off; //no need to restart
if( ((rx_ok_buff[1]&0x80)==0) && ((cur_protocol[1]&0x80)!=0) ) // Bind flag has been reset
{
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO)
if(protocol==MODE_FRSKYD || protocol==MODE_FRSKYX || protocol==MODE_FRSKYV)
BIND_DONE;
else
#endif
if(bind_counter>2)
bind_counter=2;
}
//store current protocol values
for(uint8_t i=0;i<3;i++)
cur_protocol[i] = rx_ok_buff[i];
@@ -1010,21 +1128,12 @@ void Mprotocol_serial_init()
#if defined(TELEMETRY)
void PPM_Telemetry_serial_init()
{
#ifdef MULTI_TELEMETRY
Mprotocol_serial_init();
#ifndef ORANGE_TX
#ifndef STM32_BOARD
UCSR0B &= ~(_BV(RXEN0)|_BV(RXCIE0));//rx disable and interrupt
#endif
#endif
#else
if( (protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_BAYANG) )
initTXSerial( SPEED_9600 ) ;
if(protocol==MODE_FRSKYX)
initTXSerial( SPEED_57600 ) ;
if(protocol==MODE_DSM)
initTXSerial( SPEED_125K ) ;
#endif
if( (protocol==MODE_FRSKYD) || (protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A) || (protocol==MODE_BAYANG) )
initTXSerial( SPEED_9600 ) ;
if(protocol==MODE_FRSKYX)
initTXSerial( SPEED_57600 ) ;
if(protocol==MODE_DSM)
initTXSerial( SPEED_125K ) ;
}
#endif
@@ -1070,7 +1179,13 @@ static uint32_t random_id(uint16_t adress, uint8_t create_new)
return id;
}
// Generate a random ID
id = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16);
#if defined STM32_BOARD
#define STM32_UUID ((uint32_t *)0x1FFFF7E8)
if (!create_new)
id = STM32_UUID[0] ^ STM32_UUID[1] ^ STM32_UUID[2];
#else
id = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16);
#endif
for(uint8_t i=0;i<4;i++)
{
eeprom_write_byte((EE_ADDR)adress+i,id);
@@ -1114,7 +1229,7 @@ static uint32_t random_id(uint16_t adress, uint8_t create_new)
else
if(Cur_TCNT1>4840)
{ //start of frame
if(chan>3)
if(chan>=MIN_PPM_CHANNELS)
PPM_FLAG_on; // good frame received if at least 4 channels have been seen
chan=0; // reset channel counter
bad_frame=0;
@@ -1123,7 +1238,7 @@ static uint32_t random_id(uint16_t adress, uint8_t create_new)
if(bad_frame==0) // need to wait for start of frame
{ //servo values between 500us and 2420us will end up here
PPM_data[chan]= Cur_TCNT1>>1;;
if(chan++>=NUM_CHN)
if(chan++>=MAX_PPM_CHANNELS)
bad_frame=1; // don't accept any new channels
}
Prev_TCNT1+=Cur_TCNT1;

View File

@@ -160,7 +160,11 @@ void NRF24L01_SetPower()
{
uint8_t power=NRF_BIND_POWER;
if(IS_BIND_DONE_on)
power=IS_POWER_FLAG_on?NRF_HIGH_POWER:NRF_LOW_POWER;
#ifdef NRF24L01_ENABLE_LOW_POWER
power=IS_POWER_FLAG_on?NRF_HIGH_POWER:NRF_LOW_POWER;
#else
power=NRF_HIGH_POWER;
#endif
if(IS_RANGE_FLAG_on)
power=NRF_POWER_0;
rf_setup = (rf_setup & 0xF9) | (power << 1);
@@ -278,10 +282,10 @@ static uint8_t bit_reverse(uint8_t b_in)
}
static const uint16_t polynomial = 0x1021;
static uint16_t crc16_update(uint16_t crc, uint8_t a)
static uint16_t crc16_update(uint16_t crc, uint8_t a, uint8_t bits)
{
crc ^= a << 8;
for (uint8_t i = 0; i < 8; ++i)
while(bits--)
if (crc & 0x8000)
crc = (crc << 1) ^ polynomial;
else
@@ -370,7 +374,7 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
uint16_t crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc = crc16_update(crc, buf[i]);
crc = crc16_update(crc, buf[i], 8);
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
@@ -381,6 +385,76 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
NRF24L01_WritePayload(buf, last);
}
void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack, uint16_t crc_xorout)
{
uint8_t packet[32];
uint8_t scramble_index=0;
uint8_t last = 0;
static uint8_t pid=0;
// address
if (xn297_addr_len < 4)
{
// If address length (which is defined by receive address length)
// is less than 4 the TX address can't fit the preamble, so the last
// byte goes here
packet[last++] = 0x55;
}
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
packet[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
last++;
}
// pcf
packet[last] = (len << 1) | (pid>>1);
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
last++;
packet[last] = (pid << 7) | (noack << 6);
// payload
packet[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
for (uint8_t i = 0; i < len-1; ++i)
{
last++;
packet[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
}
last++;
packet[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++] & 0xc0;
// crc
if (xn297_crc)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
uint16_t crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc = crc16_update(crc, packet[i], 8);
crc = crc16_update(crc, packet[last] & 0xc0, 2);
crc ^= crc_xorout;
packet[last++] |= (crc >> 8) >> 2;
packet[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
packet[last++] = (crc & 0xff) << 6;
}
NRF24L01_WritePayload(packet, last);
pid++;
if(pid>3)
pid=0;
}
void XN297_ReadPayload(uint8_t* msg, uint8_t len)
{
// TODO: if xn297_crc==1, check CRC before filling *msg
@@ -393,7 +467,26 @@ void XN297_ReadPayload(uint8_t* msg, uint8_t len)
}
}
// End of XN297 emulation
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
{
uint8_t buffer[32];
uint8_t pcf_size; // pcf payload size
NRF24L01_ReadPayload(buffer, len+2); // pcf + payload
pcf_size = buffer[0];
if(xn297_scramble_enabled)
pcf_size ^= xn297_scramble[xn297_addr_len];
pcf_size = pcf_size >> 1;
for(int i=0; i<len; i++)
{
msg[i] = bit_reverse((buffer[i+1] << 2) | (buffer[i+2] >> 6));
if(xn297_scramble_enabled)
msg[i] ^= bit_reverse((xn297_scramble[xn297_addr_len+i+1] << 2) |
(xn297_scramble[xn297_addr_len+i+2] >> 6));
}
return pcf_size;
}
// End of XN297 emulation
///////////////
// LT8900 emulation layer
@@ -527,14 +620,14 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
//Check len
if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN))
{
crc=crc16_update(crc,buffer[pos]);
crc=crc16_update(crc,buffer[pos],8);
if(bit_reverse(len)!=buffer[pos++])
return 0; // wrong len...
}
//Decode message
for(i=0;i<len;i++)
{
crc=crc16_update(crc,buffer[pos]);
crc=crc16_update(crc,buffer[pos],8);
msg[i]=bit_reverse(buffer[pos++]);
}
//Check CRC
@@ -556,14 +649,14 @@ void LT8900_WritePayload(uint8_t* msg, uint8_t len)
{
tmp=bit_reverse(len);
buffer[pos++]=tmp;
crc=crc16_update(crc,tmp);
crc=crc16_update(crc,tmp,8);
}
//Add payload
for(i=0;i<len;i++)
{
tmp=bit_reverse(msg[i]);
buffer[pos++]=tmp;
crc=crc16_update(crc,tmp);
crc=crc16_update(crc,tmp,8);
}
//Add CRC
if(LT8900_Flags&_BV(LT8900_CRC_ON))

View File

@@ -0,0 +1,409 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(Q303_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define Q303_BIND_COUNT 1500
#define Q303_INITIAL_WAIT 500
#define Q303_RF_BIND_CHANNEL 0x02
#define Q303_BTN_TAKEOFF 1
#define Q303_BTN_DESCEND 2
#define Q303_BTN_SNAPSHOT 4
#define Q303_BTN_VIDEO 8
#define Q303_BTN_RTH 16
#define Q303_BTN_VTX 32
static uint8_t __attribute__((unused)) cx10wd_getButtons()
{
#define CX10WD_FLAG_LAND 0x20
#define CX10D_FLAG_LAND 0x80
#define CX10WD_FLAG_TAKEOFF 0x40
static uint8_t BTN_state;
static uint8_t command;
// startup
if(packet_count < 50)
{
BTN_state = 0;
command = 0;
packet_count++;
}
// auto land
else if((Servo_data[AUX1] < PPM_MIN_COMMAND) && !(BTN_state & Q303_BTN_DESCEND))
{
BTN_state |= Q303_BTN_DESCEND;
BTN_state &= ~Q303_BTN_TAKEOFF;
switch(sub_protocol)
{
case CX10WD:
command ^= CX10WD_FLAG_LAND;
break;
case CX10D:
command ^= CX10D_FLAG_LAND;
break;
}
}
// auto take off
else if(Servo_AUX1 && !(BTN_state & Q303_BTN_TAKEOFF))
{
BTN_state |= Q303_BTN_TAKEOFF;
BTN_state &= ~Q303_BTN_DESCEND;
command ^= CX10WD_FLAG_TAKEOFF;
}
return command;
}
static uint8_t __attribute__((unused)) cx35_lastButton()
{
#define CX35_CMD_RATE 0x09
#define CX35_CMD_TAKEOFF 0x0e
#define CX35_CMD_DESCEND 0x0f
#define CX35_CMD_SNAPSHOT 0x0b
#define CX35_CMD_VIDEO 0x0c
#define CX35_CMD_RTH 0x11
#define CX35_CMD_VTX 0x10
static uint8_t BTN_state;
static uint8_t command;
// simulate 2 keypress on rate button just after bind
if(packet_count < 50)
{
BTN_state = 0;
packet_count++;
command = 0x00; // startup
}
else if(packet_count < 150)
{
packet_count++;
command = CX35_CMD_RATE; // 1st keypress
}
else if(packet_count < 250)
{
packet_count++;
command |= 0x20; // 2nd keypress
}
// descend
else if(!(GET_FLAG(Servo_AUX1, 1)) && !(BTN_state & Q303_BTN_DESCEND))
{
BTN_state |= Q303_BTN_DESCEND;
BTN_state &= ~Q303_BTN_TAKEOFF;
command = CX35_CMD_DESCEND;
}
// take off
else if(GET_FLAG(Servo_AUX1,1) && !(BTN_state & Q303_BTN_TAKEOFF))
{
BTN_state |= Q303_BTN_TAKEOFF;
BTN_state &= ~Q303_BTN_DESCEND;
command = CX35_CMD_TAKEOFF;
}
// RTH
else if(GET_FLAG(Servo_AUX6,1) && !(BTN_state & Q303_BTN_RTH))
{
BTN_state |= Q303_BTN_RTH;
if(command == CX35_CMD_RTH)
command |= 0x20;
else
command = CX35_CMD_RTH;
}
else if(!(GET_FLAG(Servo_AUX6,1)) && (BTN_state & Q303_BTN_RTH))
{
BTN_state &= ~Q303_BTN_RTH;
if(command == CX35_CMD_RTH)
command |= 0x20;
else
command = CX35_CMD_RTH;
}
// video
else if(GET_FLAG(Servo_AUX4,1) && !(BTN_state & Q303_BTN_VIDEO))
{
BTN_state |= Q303_BTN_VIDEO;
if(command == CX35_CMD_VIDEO)
command |= 0x20;
else
command = CX35_CMD_VIDEO;
}
else if(!(GET_FLAG(Servo_AUX4,1)) && (BTN_state & Q303_BTN_VIDEO))
{
BTN_state &= ~Q303_BTN_VIDEO;
if(command == CX35_CMD_VIDEO)
command |= 0x20;
else
command = CX35_CMD_VIDEO;
}
// snapshot
else if(GET_FLAG(Servo_AUX3,1) && !(BTN_state & Q303_BTN_SNAPSHOT))
{
BTN_state |= Q303_BTN_SNAPSHOT;
if(command == CX35_CMD_SNAPSHOT)
command |= 0x20;
else
command = CX35_CMD_SNAPSHOT;
}
// vtx channel
else if(GET_FLAG(Servo_AUX2,1) && !(BTN_state & Q303_BTN_VTX))
{
BTN_state |= Q303_BTN_VTX;
if(command == CX35_CMD_VTX)
command |= 0x20;
else
command = CX35_CMD_VTX;
}
if(!(GET_FLAG(Servo_AUX3,1)))
BTN_state &= ~Q303_BTN_SNAPSHOT;
if(!(GET_FLAG(Servo_AUX2,1)))
BTN_state &= ~Q303_BTN_VTX;
return command;
}
static void __attribute__((unused)) Q303_send_packet(uint8_t bind)
{
uint16_t aileron, elevator, throttle, rudder, slider;
if(bind)
{
packet[0] = 0xaa;
memcpy(&packet[1], rx_tx_addr + 1, 4);
memset(&packet[5], 0, packet_length-5);
}
else
{
packet[0] = 0x55;
// sticks
switch(sub_protocol)
{
case Q303:
case CX35:
aileron = convert_channel_16b(AILERON, 0, 1000);
elevator = convert_channel_16b(ELEVATOR, 1000, 0);
throttle = convert_channel_16b(THROTTLE, 0, 1000);
rudder = convert_channel_16b(RUDDER, 1000, 0);
if(sub_protocol == CX35)
aileron = 1000 - aileron;
packet[1] = aileron >> 2; // 8 bits
packet[2] = (aileron & 0x03) << 6 // 2 bits
| (elevator >> 4); // 6 bits
packet[3] = (elevator & 0x0f) << 4 // 4 bits
| (throttle >> 6); // 4 bits
packet[4] = (throttle & 0x3f) << 2 // 6 bits
| (rudder >> 8); // 2 bits
packet[5] = rudder & 0xff; // 8 bits
break;
case CX10D:
case CX10WD:
aileron = convert_channel_16b(AILERON, 2000, 1000);
elevator = convert_channel_16b(ELEVATOR, 2000, 1000);
throttle = convert_channel_16b(THROTTLE, 1000, 2000);
rudder = convert_channel_16b(RUDDER, 1000, 2000);
packet[1] = aileron & 0xff;
packet[2] = aileron >> 8;
packet[3] = elevator & 0xff;
packet[4] = elevator >> 8;
packet[5] = throttle & 0xff;
packet[6] = throttle >> 8;
packet[7] = rudder & 0xff;
packet[8] = rudder >> 8;
break;
}
// buttons
switch(sub_protocol)
{
case Q303:
packet[6] = 0x10; // trim(s) ?
packet[7] = 0x10; // trim(s) ?
packet[8] = 0x03 // high rate (0-3)
| GET_FLAG(Servo_AUX1, 0x40)
| GET_FLAG(Servo_AUX6, 0x80);
packet[9] = 0x40 // always set
| GET_FLAG(Servo_AUX5,0x08)
| GET_FLAG(Servo_AUX2, 0x80)
| GET_FLAG(Servo_AUX3,0x10)
| GET_FLAG(Servo_AUX4, 0x01);
if(Servo_data[AUX7] < PPM_MIN_COMMAND)
packet[9] |= 0x04; // gimbal down
else if(Servo_data[AUX7] > PPM_MAX_COMMAND)
packet[9] |= 0x20; // gimbal up
break;
case CX35:
slider = convert_channel_16b(AUX7, 731, 342);
packet[6] = slider >> 2;
packet[7] = ((slider & 3) << 6)
| 0x3e; // ?? 6 bit left (always 111110 ?)
packet[8] = 0x80; // always set
packet[9] = cx35_lastButton();
break;
case CX10D:
packet[8] |= GET_FLAG(Servo_AUX2, 0x10);
packet[9] = 0x02; // rate (0-2)
packet[10]= cx10wd_getButtons(); // auto land / take off management
break;
case CX10WD:
packet[8] |= GET_FLAG(Servo_AUX2, 0x10);
packet[9] = 0x02 // rate (0-2)
| cx10wd_getButtons(); // auto land / take off management
packet[10] = 0x00;
break;
}
}
// Power on, TX mode, CRC enabled
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? Q303_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no %= rf_ch_num;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, packet_length);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) Q303_init()
{
const uint8_t bind_address[] = {0xcc,0xcc,0xcc,0xcc,0xcc};
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
switch(sub_protocol)
{
case CX35:
case CX10D:
case CX10WD:
XN297_SetScrambledMode(XN297_SCRAMBLED);
NRF24L01_SetBitrate(NRF24L01_BR_1M);
break;
case Q303:
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
NRF24L01_SetBitrate(NRF24L01_BR_250K);
break;
}
XN297_SetTXAddr(bind_address, 5);
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_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits on
NRF24L01_Activate(0x73);
}
static void __attribute__((unused)) Q303_initialize_txid()
{
uint8_t i,offset;
rx_tx_addr[0] = 0x55;
switch(sub_protocol)
{
case Q303:
case CX10WD:
offset = rx_tx_addr[1] & 3;
for(i=0; i<4; i++)
hopping_frequency[i] = 0x46 + i*2 + offset;
break;
case CX35:
case CX10D:
// not thoroughly figured out rx_tx_addr/channels mapping yet
// for now 5 msb of rx_tx_addr[1] must be cleared
rx_tx_addr[1] &= 7;
offset = 6+(rx_tx_addr[1]*3);
hopping_frequency[0] = 0x14; // works only if rx_tx_addr[1] < 8
for(i=1; i<16; i++)
{
hopping_frequency[i] = hopping_frequency[i-1] + offset;
if(hopping_frequency[i] > 0x41)
hopping_frequency[i] -= 0x33;
if(hopping_frequency[i] < 0x14)
hopping_frequency[i] += offset;
}
// CX35 tx uses only 4 of those channels (#0,3,6,9)
if(sub_protocol == CX35)
for(i=0; i<4; i++)
hopping_frequency[i] = hopping_frequency[i*3];
break;
}
}
uint16_t Q303_callback()
{
if(IS_BIND_DONE_on)
Q303_send_packet(0);
else
{
if (bind_counter == 0)
{
XN297_SetTXAddr(rx_tx_addr, 5);
packet_count = 0;
BIND_DONE;
}
else
{
Q303_send_packet(1);
bind_counter--;
}
}
return packet_period;
}
uint16_t initQ303()
{
Q303_initialize_txid();
Q303_init();
bind_counter = Q303_BIND_COUNT;
switch(sub_protocol)
{
case Q303:
packet_period = 1500;
packet_length = 10;
rf_ch_num = 4;
break;
case CX35:
packet_period = 3000;
packet_length = 10;
rf_ch_num = 4;
break;
case CX10D:
packet_period = 3000;
packet_length = 11;
rf_ch_num = 16;
break;
case CX10WD:
packet_period = 3000;
packet_length = 11;
rf_ch_num = 4;
break;
}
hopping_frequency_no = 0;
BIND_IN_PROGRESS; // autobind protocol
return Q303_INITIAL_WAIT;
}
#endif

View File

@@ -122,22 +122,17 @@ static void __attribute__((unused)) SFHSS_calc_next_chan()
}
}
// Channel values are 10-bit values between 86 and 906, 496 is the middle.
// Values grow down and to the right, so we just revert every channel.
static uint16_t __attribute__((unused)) SFHSS_convert_channel(uint8_t num)
{
return (uint16_t) (map(limit_channel_100(num),servo_min_100,servo_max_100,906,86));
}
/*// Channel values are 10-bit values between 86 and 906, 496 is the middle.
// Values grow down and to the right.
static void __attribute__((unused)) SFHSS_build_data_packet()
{
#define spacer1 0x02 //0b10
#define spacer1 0x02
#define spacer2 (spacer1 << 4)
uint8_t ch_offset = phase == SFHSS_DATA1 ? 0 : 4;
uint16_t ch1 = SFHSS_convert_channel(CH_AETR[ch_offset+0]);
uint16_t ch2 = SFHSS_convert_channel(CH_AETR[ch_offset+1]);
uint16_t ch3 = SFHSS_convert_channel(CH_AETR[ch_offset+2]);
uint16_t ch4 = SFHSS_convert_channel(CH_AETR[ch_offset+3]);
uint16_t ch1 = convert_channel_16b_nolim(CH_AETR[ch_offset+0],86,906);
uint16_t ch2 = convert_channel_16b_nolim(CH_AETR[ch_offset+1],86,906);
uint16_t ch3 = convert_channel_16b_nolim(CH_AETR[ch_offset+2],86,906);
uint16_t ch4 = convert_channel_16b_nolim(CH_AETR[ch_offset+3],86,906);
packet[0] = 0x81; // can be 80 or 81 for Orange, only 81 for XK
packet[1] = rx_tx_addr[0];
@@ -146,13 +141,40 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
packet[4] = 0;
packet[5] = (rf_ch_num << 3) | spacer1 | ((ch1 >> 9) & 0x01);
packet[6] = (ch1 >> 1);
packet[7] = (ch1 << 7) | spacer2 | ((ch2 >> 5) & 0x1F /*0b11111*/);
packet[7] = (ch1 << 7) | spacer2 | ((ch2 >> 5) & 0x1F);
packet[8] = (ch2 << 3) | spacer1 | ((ch3 >> 9) & 0x01);
packet[9] = (ch3 >> 1);
packet[10] = (ch3 << 7) | spacer2 | ((ch4 >> 5) & 0x1F /*0b11111*/);
packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0x07 /*0b111 */);
packet[10] = (ch3 << 7) | spacer2 | ((ch4 >> 5) & 0x1F);
packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0x07);
packet[12] = (fhss_code << 6) | phase;
}
*/
// Channel values are 12-bit values between 1020 and 2020, 1520 is the middle.
// Futaba @140% is 2070...1520...970
// Values grow down and to the right.
static void __attribute__((unused)) SFHSS_build_data_packet()
{
uint8_t ch_offset = phase == SFHSS_DATA1 ? 0 : 4;
uint16_t ch1 = convert_channel_16b_nolim(CH_AETR[ch_offset+0],2020,1020);
uint16_t ch2 = convert_channel_16b_nolim(CH_AETR[ch_offset+1],2020,1020);
uint16_t ch3 = convert_channel_16b_nolim(CH_AETR[ch_offset+2],2020,1020);
uint16_t ch4 = convert_channel_16b_nolim(CH_AETR[ch_offset+3],2020,1020);
packet[0] = 0x81; // can be 80 or 81 for Orange, only 81 for XK
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
packet[3] = 0x0f; //10J
packet[4] = 0x09; //10J
packet[5] = (rf_ch_num << 3) | ((ch1 >> 9) & 0x07);
packet[6] = (ch1 >> 1);
packet[7] = (ch1 << 7) | ((ch2 >> 5) & 0x7F );
packet[8] = (ch2 << 3) | ((ch3 >> 9) & 0x07);
packet[9] = (ch3 >> 1);
packet[10] = (ch3 << 7) | ((ch4 >> 5) & 0x7F );
packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0x07 );
packet[12] = (fhss_code << 6) | phase;
}
static void __attribute__((unused)) SFHSS_send_packet()
{

View File

@@ -20,20 +20,15 @@
// For code readability
#define SLT_PAYLOADSIZE 7
#define SLT_VISTA_PAYLOADSIZE 11
#define SLT_NFREQCHANNELS 15
#define SLT_TXID_SIZE 4
enum {
// flags going to packet[6]
SLT_VISTA_FLAG_FLIP = 0x04,
SLT_VISTA_FLAG_MODE = 0x20
};
enum {
SLT_BIND=0,
SLT_BUILD,
SLT_DATA,
SLT_BUILD=0,
SLT_DATA1,
SLT_DATA2,
SLT_DATA3,
SLT_BIND
};
static void __attribute__((unused)) SLT_init()
@@ -108,37 +103,24 @@ static void __attribute__((unused)) SLT_send_data(uint8_t *data, uint8_t len)
static void __attribute__((unused)) SLT_build_packet()
{
// aileron, elevator, throttle, rudder, gear, pitch
// Set radio channel - once per packet batch
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
// aileron, elevator, throttle, rudder, gear, pitch
uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed
for (uint8_t i = 0; i < 4; ++i)
{
uint16_t v = convert_channel_10b(CH_AETR[i]);
if(sub_protocol==VISTA && CH_AETR[i]==THROTTLE)
v = (uint16_t) map(limit_channel_100(THROTTLE),servo_min_100,servo_max_100,850,150); // Throttel is between 850=0% and 150=100%
packet[i] = v;
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
}
// Extra bits for AETR
packet[4] = e;
if(sub_protocol==SLT)
{
// 8-bit channels
packet[5] = convert_channel_8b(AUX1);
packet[6] = convert_channel_8b(AUX2);
}
else
{ // VISTA
packet[5] = 0xA6;
packet[6] = 0x00;
if(Servo_AUX1)
packet[6] = SLT_VISTA_FLAG_FLIP;
if(Servo_AUX2)
packet[6] |= SLT_VISTA_FLAG_MODE;
packet[7] = 0x00;
packet[8] = 0x7F;
packet[9] = 0xAA;
packet[10] = 0x00;
}
// 8-bit channels
packet[5] = convert_channel_8b(AUX1);
packet[6] = convert_channel_8b(AUX2);
}
static void __attribute__((unused)) SLT_send_bind_packet()
@@ -162,83 +144,47 @@ uint16_t SLT_callback()
{
switch (phase)
{
case SLT_BIND:
bind_phase = 0;
SLT_send_bind_packet();
if(sub_protocol == VISTA)
case SLT_BUILD:
SLT_build_packet();
phase++;
return 1000;
case SLT_DATA1:
SLT_send_data(packet, SLT_PAYLOADSIZE);
phase++;
return 1000;
case SLT_DATA2:
SLT_send_data(packet, SLT_PAYLOADSIZE);
phase++;
return 1000;
case SLT_DATA3:
SLT_send_data(packet, SLT_PAYLOADSIZE);
if (++packet_count >= 100)
{
phase=SLT_DATA;
packet_count = 0;
phase++;
return 1000;
}
phase++; // SLT_BUILD
return 18000;
case SLT_BUILD:
if(sub_protocol==SLT)
{ // Set radio channel - once per packet batch
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
}
SLT_build_packet();
packet_count=0;
phase++; // SLT_DATA
return 1000;
case SLT_DATA:
if(sub_protocol==VISTA)
{ // Change radio channel every 9 packets
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
rf_ch_num++;
if(rf_ch_num>=9)
{
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
rf_ch_num=0;
}
}
SLT_send_data(packet, sub_protocol == VISTA?SLT_VISTA_PAYLOADSIZE:SLT_PAYLOADSIZE);
packet_count++;
if(packet_count >= (sub_protocol == VISTA?5:3))
{ // repeat the same data packet 3(SLT) or 5(VISTA) times
bind_phase++;
else
{
NRF24L01_SetPower(); // Set tx_power
phase = SLT_BUILD; // Refresh data
if(sub_protocol == VISTA)
return 1000;
else
if(bind_phase>=100)
{ //SLT sends bind packet every 2.2s
phase=SLT_BIND;
return 1000;
}
phase = SLT_BUILD;
return 19000;
}
if(sub_protocol == VISTA)
{ //VISTA sends bind packet every 1.5s
if(bind_phase>=150)
phase=SLT_BIND;
else
return 2000;
}
return 1000;
case SLT_BIND:
SLT_send_bind_packet();
phase = SLT_BUILD;
return 18000;
}
return 1000;
return 19000;
}
uint16_t initSLT()
{
packet_count = 0;
packet_sent = 0;
rf_ch_num=0;
hopping_frequency_no = 0;
if(sub_protocol == VISTA)
{
memcpy(rx_tx_addr,"\x00\x00\x23\x00",SLT_TXID_SIZE);
memcpy(hopping_frequency,"\x03\x0A\x11\x18\x1F\x26\x13\x0F\x0B\x10\x08\x16\x1D\x24\x06",15);
}
else
SLT_set_freq();
SLT_set_freq();
SLT_init();
SLT_build_packet();
phase = SLT_BIND;
return 50000;
}

View File

@@ -319,12 +319,12 @@ uint16_t symax_callback()
return SYMAX_FIRST_PACKET_DELAY;
break;
case SYMAX_BIND2:
counter = SYMAX_BIND_COUNT;
bind_counter = SYMAX_BIND_COUNT;
phase = SYMAX_BIND3;
SYMAX_send_packet(1);
break;
case SYMAX_BIND3:
if (counter == 0)
if (bind_counter == 0)
{
symax_init2();
phase = SYMAX_DATA;
@@ -333,7 +333,7 @@ uint16_t symax_callback()
else
{
SYMAX_send_packet(1);
counter--;
bind_counter--;
}
break;
case SYMAX_DATA:

View File

@@ -10,8 +10,8 @@
#if defined(TX_DEVO7)
#define PPM_MAX_100 1920 // 100%
#define PPM_MIN_100 1120 // 100%
#define PPM_MAX_125 2100 // 125%
#define PPM_MIN_125 900 // 125%
#define PPM_MAX_125 2120 // 125%
#define PPM_MIN_125 920 // 125%
#endif
// SPEKTRUM PPM and channels
@@ -24,10 +24,10 @@
// HISKY
#if defined(TX_HISKY)
#define PPM_MAX_100 1900 // 100%
#define PPM_MIN_100 1100 // 100%
#define PPM_MAX_125 2000 // 125%
#define PPM_MIN_125 1000 // 125%
#define PPM_MAX_100 1920 // 100%
#define PPM_MIN_100 1120 // 100%
#define PPM_MAX_125 2020 // 125%
#define PPM_MIN_125 1020 // 125%
#endif
// Multiplex MC2020
@@ -38,6 +38,14 @@
#define PPM_MIN_125 1150 // 125%
#endif
// Walkera PL0811-01H
#if defined(TX_WALKERA)
#define PPM_MAX_100 1800 // 100%
#define PPM_MIN_100 1000 // 100%
#define PPM_MAX_125 1900 // 125%
#define PPM_MIN_125 900 // 125%
#endif
//Serial MIN MAX values
#define SERIAL_MAX_100 2012 // 100%
#define SERIAL_MIN_100 988 // 100%

View File

@@ -17,8 +17,10 @@
//**************************
#if defined TELEMETRY
#if defined MULTI_TELEMETRY
#define MULTI_TIME 250 //in ms
uint8_t RetrySequence ;
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
#define MULTI_TIME 500 //in ms
uint32_t lastMulti = 0;
#endif
@@ -28,7 +30,6 @@
uint32_t last = 0;
uint8_t sport_counter=0;
uint8_t RxBt = 0;
uint8_t rssi;
uint8_t sport = 0;
#endif
#if defined HUB_TELEMETRY
@@ -45,32 +46,17 @@ uint8_t pktx1[MAX_PKTX];
uint8_t indx;
uint8_t frame[18];
#ifdef BASH_SERIAL
// For bit-bashed serial output
volatile struct t_serial_bash
{
uint8_t head ;
uint8_t tail ;
uint8_t data[64] ;
uint8_t busy ;
uint8_t speed ;
} SerialControl ;
#endif
#ifdef MULTI_TELEMETRY
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
static void multi_send_header(uint8_t type, uint8_t len)
{
Serial_write('M');
Serial_write('P');
Serial_write(type);
Serial_write(len);
}
static void multi_send_frskyhub()
{
multi_send_header(MULTI_TELEMETRY_HUB, 9);
for (uint8_t i = 0; i < 9; i++)
Serial_write(frame[i]);
Serial_write('M');
#ifdef MULTI_TELEMETRY
Serial_write('P');
Serial_write(type);
#else
(void)type;
#endif
Serial_write(len);
}
static void multi_send_status()
@@ -84,16 +70,21 @@ static void multi_send_status()
if (mode_select==MODE_SERIAL)
flags |= 0x02;
if (remote_callback != 0)
flags |= 0x04;
if (!IS_BIND_DONE_on)
flags |= 0x08;
{
flags |= 0x04;
if (IS_WAIT_BIND_on)
flags |= 0x10;
else
if (!IS_BIND_DONE_on)
flags |= 0x08;
}
Serial_write(flags);
// Version number example: 1.16.1
// Version number example: 1.1.6.1
Serial_write(VERSION_MAJOR);
Serial_write(VERSION_MINOR);
Serial_write(VERSION_REVISION);
Serial_write(VERSION_PATCH_LEVEL);
Serial_write(0);
}
#endif
@@ -101,22 +92,25 @@ static void multi_send_status()
#ifdef MULTI_TELEMETRY
void DSM_frame()
{
if (pkt[0] == 0x80) {
if (pkt[0] == 0x80)
{
multi_send_header(MULTI_TELEMETRY_DSMBIND, 10);
for (uint8_t i = 1; i < 11; i++) // 10 byte of DSM bind response
for (uint8_t i = 1; i < 11; i++) // 10 bytes of DSM bind response
Serial_write(pkt[i]);
} else {
}
else
{
multi_send_header(MULTI_TELEMETRY_DSM, 17);
for (uint8_t i = 0; i < 29; i++) // RSSI value followed by 4*7 bytes of telemetry data
for (uint8_t i = 0; i < 17; i++) // RSSI value followed by 16 bytes of telemetry data
Serial_write(pkt[i]);
}
}
#else
void DSM_frame()
{
Serial_write(0xAA); // Telemetry packet
for (uint8_t i = 0; i < 17; i++) // RSSI value followed by 16 bytes of telemetry data
Serial_write(0xAA); // Telemetry packet
for (uint8_t i = 0; i < 17; i++) // RSSI value followed by 16 bytes of telemetry data
Serial_write(pkt[i]);
}
#endif
@@ -128,13 +122,22 @@ static void multi_send_status()
#if defined MULTI_TELEMETRY
multi_send_header(MULTI_TELEMETRY_AFHDS2A, 29);
#else
Serial_write(0xAA); // Telemetry packet
Serial_write(0xAA); // Telemetry packet
#endif
for (uint8_t i = 0; i < 29; i++) // RSSI value followed by 4*7 bytes of telemetry data
for (uint8_t i = 0; i < 29; i++) // RSSI value followed by 4*7 bytes of telemetry data
Serial_write(pkt[i]);
}
#endif
#ifdef MULTI_TELEMETRY
static void multi_send_frskyhub()
{
multi_send_header(MULTI_TELEMETRY_HUB, 9);
for (uint8_t i = 0; i < 9; i++)
Serial_write(frame[i]);
}
#endif
void frskySendStuffed()
{
Serial_write(START_STOP);
@@ -150,25 +153,53 @@ void frskySendStuffed()
Serial_write(START_STOP);
}
void compute_RSSIdbm()
{
RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>4);
if(pktt[len-2] >=128)
RSSI_dBm -= 164;
else
RSSI_dBm += 130;
}
void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
{
if(pkt[1] == rx_tx_addr[3] && pkt[2] == rx_tx_addr[2] && len ==(pkt[0] + 3))
{
for (uint8_t i=3;i<len;i++)
pktt[i]=pkt[i];
telemetry_link=1;
if(pktt[6])
telemetry_counter=(telemetry_counter+1)%32;
telemetry_link|=1; // Telemetry data is available
/*previous version
RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>4);
if(pktt[len-2] >=128) RSSI_dBm -= 164;
else RSSI_dBm += 130;*/
TX_RSSI = pkt[len-2];
if(TX_RSSI >=128)
TX_RSSI -= 128;
else
TX_RSSI += 128;
TX_LQI = pkt[len-1]&0x7F;
for (uint8_t i=3;i<len-2;i++)
pktt[i]=pkt[i]; // Buffer telemetry values to be sent
if(pktt[6]>0 && pktt[6]<=10)
{
if (protocol==MODE_FRSKYD)
{
if ( ( pktt[7] & 0x1F ) == (telemetry_counter & 0x1F) )
{
uint8_t topBit = 0 ;
if ( telemetry_counter & 0x80 )
{
if ( ( telemetry_counter & 0x1F ) != RetrySequence )
{
topBit = 0x80 ;
}
}
telemetry_counter = ( (telemetry_counter+1)%32 ) | topBit ; // Request next telemetry frame
}
else
{
// incorrect sequence
RetrySequence = pktt[7] & 0x1F ;
telemetry_counter |= 0x80 ;
pktt[6]=0 ; // Discard current packet and wait for retransmit
}
}
}
else
{
pktt[6]=0; // Discard packet
}
//
#if defined SPORT_TELEMETRY && defined FRSKYX_CC2500_INO
telemetry_lost=0;
@@ -192,36 +223,41 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
}
}
void init_hub_telemetry()
void init_frskyd_link_telemetry()
{
telemetry_link=0;
telemetry_counter=0;
v_lipo1=0;
v_lipo2=0;
RSSI_dBm=0;
RX_RSSI=0;
TX_RSSI=0;
RX_LQI=0;
TX_LQI=0;
}
void frsky_link_frame()
{
frame[0] = 0xFE;
frame[0] = 0xFE; // Link frame
if (protocol==MODE_FRSKYD)
{
compute_RSSIdbm();
frame[1] = pktt[3];
frame[2] = pktt[4];
frame[3] = pktt[5];
frame[4] = (uint8_t)RSSI_dBm;
frame[1] = pktt[3]; // A1
frame[2] = pktt[4]; // A2
frame[3] = pktt[5]; // RX_RSSI
telemetry_link &= ~1 ; // Sent
telemetry_link |= 2 ; // Send hub if available
}
else
if (protocol==MODE_HUBSAN||protocol==MODE_AFHDS2A||protocol==MODE_BAYANG)
{
frame[1] = v_lipo1;
frame[2] = v_lipo2;
frame[3] = (uint8_t)RSSI_dBm;
frame[4] = TX_RSSI;
frame[3] = RX_RSSI;
telemetry_link=0;
}
frame[5] = frame[6] = frame[7] = frame[8] = 0;
frame[4] = TX_RSSI;
frame[5] = RX_LQI;
frame[6] = TX_LQI;
frame[7] = frame[8] = 0;
#if defined MULTI_TELEMETRY
multi_send_frskyhub();
#else
@@ -232,66 +268,26 @@ void frsky_link_frame()
#if defined HUB_TELEMETRY
void frsky_user_frame()
{
uint8_t indexx = 0, j=8, i;
//uint8_t c=0, n=0;
if(pktt[6]>0 && pktt[6]<=10)
{//only valid hub frames
frame[0] = 0xFD;
frame[2] = pktt[7];
switch(pass)
if(pktt[6])
{//only send valid hub frames
frame[0] = 0xFD; // user frame
if(pktt[6]>USER_MAX_BYTES)
{
case 0:
indexx=pktt[6];
for(i=0;i<indexx;i++)
{
// if(pktt[j]==0x5E)
// {
// if(c++)
// {
// c=0;
// n++;
// j++;
// }
// }
pktx[i]=pktt[j++];
}
// indexx = indexx-n;
pass=1;
case 1:
indx=indexx;
prev_index = indexx;
if(indx<USER_MAX_BYTES)
{
for(i=0;i<indx;i++)
frame[i+3]=pktx[i];
pktt[6]=0;
pass=0;
}
else
{
indx = USER_MAX_BYTES;
for(i=0;i<indx;i++)
frame[i+3]=pktx[i];
pass=2;
}
break;
case 2:
indx = prev_index - indx;
prev_index=0;
if(indx<=(MAX_PKTX-USER_MAX_BYTES)) //10-6=4
for(i=0;i<indx;i++)
frame[i+3]=pktx[USER_MAX_BYTES+i];
pass=0;
pktt[6]=0;
break;
default:
break;
frame[1]=USER_MAX_BYTES; // packet size
pktt[6]-=USER_MAX_BYTES;
telemetry_link |= 2 ; // 2 packets need to be sent
}
if(!indx)
return;
frame[1] = indx;
else
{
frame[1]=pktt[6]; // packet size
telemetry_link=0; // only 1 packet or processing second packet
}
frame[2] = pktt[7];
for(uint8_t i=0;i<USER_MAX_BYTES;i++)
frame[i+3]=pktt[i+8];
if(telemetry_link & 2) // prepare the content of second packet
for(uint8_t i=8;i<USER_MAX_BYTES+8;i++)
pktt[i]=pktt[i+USER_MAX_BYTES];
#if defined MULTI_TELEMETRY
multi_send_frskyhub();
#else
@@ -299,10 +295,8 @@ void frsky_user_frame()
#endif
}
else
pass=0;
telemetry_link=0;
}
#endif
/*
HuB RX packets.
pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
@@ -317,6 +311,8 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
0A 0F 5E 3A 06 00 5E 5E 3B 09 00 5E
05 10 5E 06 16 72 5E 5E 3A 06 00 5E
*/
#endif
#if defined SPORT_TELEMETRY
/* SPORT details serial
@@ -437,7 +433,7 @@ void sportSendFrame()
frame[0] = 0x98;
frame[1] = 0x10;
for (i=5;i<8;i++)
frame[i]=0;
frame[i]=0;
}
switch (sport_counter)
{
@@ -451,7 +447,10 @@ void sportSendFrame()
case 2: // RSSI
frame[2] = 0x01;
frame[3] = 0xf1;
frame[4] = rssi;
frame[4] = RX_RSSI;
frame[5] = TX_RSSI;
frame[6] = RX_LQI;
frame[7] = TX_LQI;
break;
case 4: //BATT
frame[2] = 0x04;
@@ -535,45 +534,33 @@ void TelemetryUpdate()
h = SerialControl.head ;
t = SerialControl.tail ;
if ( h >= t )
{
t += 64 - h ;
}
t += 128 - h ;
else
{
t -= h ;
}
if ( t < 32 )
{
if ( t < 64 )
return ;
}
#else
uint8_t h ;
uint8_t t ;
h = tx_head ;
t = tx_tail ;
if ( h >= t )
{
t += TXBUFFER_SIZE - h ;
}
else
{
t -= h ;
}
if ( t < 16 )
{
if ( t < 32 )
return ;
}
#endif
#if defined MULTI_TELEMETRY
{
uint32_t now = millis();
if ((now - lastMulti) > MULTI_TIME) {
multi_send_status();
lastMulti = now;
return;
}
}
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
{
uint32_t now = millis();
if ((now - lastMulti) > MULTI_TIME)
{
multi_send_status();
lastMulti = now;
return;
}
}
#endif
#if defined SPORT_TELEMETRY
@@ -582,10 +569,10 @@ void TelemetryUpdate()
if(telemetry_link)
{
if(pktt[4] & 0x80)
rssi=pktt[4] & 0x7F ;
RX_RSSI=pktt[4] & 0x7F ;
else
RxBt = (pktt[4]<<1) + 1 ;
if(pktt[6]<=6)
if(pktt[6] && pktt[6]<=6)
for (uint8_t i=0; i < pktt[6]; i++)
proces_sport_data(pktt[7+i]);
telemetry_link=0;
@@ -604,7 +591,7 @@ void TelemetryUpdate()
#endif
#if defined DSM_TELEMETRY
if(telemetry_link && protocol == MODE_DSM )
if(telemetry_link && protocol == MODE_DSM)
{ // DSM
DSM_frame();
telemetry_link=0;
@@ -616,17 +603,18 @@ void TelemetryUpdate()
{
AFHDSA_short_frame();
telemetry_link=0;
return;
}
#endif
if(telemetry_link && protocol != MODE_FRSKYX )
if((telemetry_link & 1 )&& protocol != MODE_FRSKYX)
{ // FrSkyD + Hubsan + AFHDS2A + Bayang
frsky_link_frame();
telemetry_link=0;
return;
}
#if defined HUB_TELEMETRY
if(!telemetry_link && protocol == MODE_FRSKYD)
{ // FrSky
if((telemetry_link & 2) && protocol == MODE_FRSKYD)
{ // FrSkyD
frsky_user_frame();
return;
}
@@ -846,7 +834,7 @@ void Serial_write( uint8_t byte )
#ifdef INVERT_SERIAL
byte |= 1 ; // Start bit
#endif
uint8_t next = (SerialControl.head + 2) & 0x3f ;
uint8_t next = (SerialControl.head + 2) & 0x7f ;
if ( next != SerialControl.tail )
{
SerialControl.data[SerialControl.head] = byte ;
@@ -940,7 +928,7 @@ ISR(TIMER0_COMPB_vect)
{
GPIOR0 = ptr->data[ptr->tail] ;
GPIOR2 = ptr->data[ptr->tail+1] ;
ptr->tail = ( ptr->tail + 2 ) & 0x3F ;
ptr->tail = ( ptr->tail + 2 ) & 0x7F ;
GPIOR1 = 8 ;
OCR0A = OCR0B + 40 ;
OCR0B = OCR0A + 8 * 20 ;
@@ -991,7 +979,7 @@ ISR(TIMER0_OVF_vect)
{
GPIOR0 = ptr->data[ptr->tail] ;
GPIOR2 = ptr->data[ptr->tail+1] ;
ptr->tail = ( ptr->tail + 2 ) & 0x3F ;
ptr->tail = ( ptr->tail + 2 ) & 0x7F ;
GPIOR1 = 10 ;
}
else

View File

@@ -252,19 +252,18 @@ uint16_t ReadV2x2()
return 150;
break;
case V202_BIND2:
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED) {
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED)
return V2X2_PACKET_CHKTIME;
}
V2X2_send_packet(1);
if (--counter == 0) {
if (--bind_counter == 0)
{
phase = V202_DATA;
BIND_DONE;
}
break;
case V202_DATA:
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED) {
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED)
return V2X2_PACKET_CHKTIME;
}
V2X2_send_packet(0);
break;
}
@@ -278,7 +277,7 @@ uint16_t initV2x2()
//
if (IS_AUTOBIND_FLAG_on)
{
counter = V2X2_BIND_COUNT;
bind_counter = V2X2_BIND_COUNT;
phase = V202_INIT2;
}
else

View File

@@ -22,8 +22,11 @@
#ifdef ORANGE_TX
#undef ENABLE_PPM // Disable PPM for OrangeTX module
#undef A7105_INSTALLED // Disable A7105 for OrangeTX module
#undef A7105_CSN_pin
#undef CC2500_INSTALLED // Disable CC2500 for OrangeTX module
#undef CC25_CSN_pin
#undef NRF24L01_INSTALLED // Disable NRF for OrangeTX module
#undef NRF_CSN_pin
#define TELEMETRY // Enable telemetry
#define INVERT_TELEMETRY // Enable invert telemetry
#define DSM_TELEMETRY // Enable DSM telemetry
@@ -39,6 +42,7 @@
#undef DEVO_CYRF6936_INO
#undef DSM_CYRF6936_INO
#undef J6PRO_CYRF6936_INO
#undef WK2x01_CYRF6936_INO
#endif
#ifndef CC2500_INSTALLED
#undef FRSKYD_CC2500_INO
@@ -64,6 +68,8 @@
#undef FQ777_NRF24L01_INO
#undef ASSAN_NRF24L01_INO
#undef HONTAI_NRF24L01_INO
#undef Q303_NRF24L01_INO
#undef GW008_NRF24L01_INO
#undef CABELL_NRF24L01_INO
#endif
@@ -77,8 +83,12 @@
#undef HUB_TELEMETRY
#undef SPORT_TELEMETRY
#undef DSM_TELEMETRY
#undef MULTI_STATUS
#undef MULTI_TELEMETRY
#else
#if defined MULTI_TELEMETRY && not defined INVERT_TELEMETRY
#warning MULTI_TELEMETRY has been defined but not INVERT_TELEMETRY. They should be both enabled for OpenTX telemetry and status to work.
#endif
#if not defined(BAYANG_NRF24L01_INO)
#undef BAYANG_HUB_TELEMETRY
#endif
@@ -98,7 +108,7 @@
#if not defined(DSM_CYRF6936_INO)
#undef DSM_TELEMETRY
#endif
#if not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY)
#if not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS)
#undef TELEMETRY
#undef INVERT_TELEMETRY
#endif
@@ -111,3 +121,25 @@
#if not defined(PPM_MAX_100) || not defined(PPM_MIN_100) || not defined(PPM_MAX_125) || not defined(PPM_MIN_125)
#error You must set correct TX end points.
#endif
#if defined(ENABLE_BIND_CH)
#if BIND_CH<4
#error BIND_CH must be above 4.
#endif
#if BIND_CH>16
#error BIND_CH must be below or equal to 16.
#endif
#endif
#if MIN_PPM_CHANNELS>16
#error MIN_PPM_CHANNELS must be below or equal to 16. The default for this value is 4.
#endif
#if MIN_PPM_CHANNELS<2
#error MIN_PPM_CHANNELS must be larger than 1. The default for this value is 4.
#endif
#if MAX_PPM_CHANNELS<MIN_PPM_CHANNELS
#error MAX_PPM_CHANNELS must be higher than MIN_PPM_CHANNELS. The default for this value is 16.
#endif
#if MAX_PPM_CHANNELS>16
#error MAX_PPM_CHANNELS must be below or equal to 16. The default for this value is 16.
#endif

View File

@@ -0,0 +1,491 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(WK2x01_CYRF6936_INO)
#include "iface_cyrf6936.h"
#define WK_BIND_COUNT 2980
#define WK_NUM_WAIT_LOOPS (100 / 5) //each loop is ~5us. Do not wait more than 100us
enum {
WK_BIND=0,
WK_BOUND_1,
WK_BOUND_2,
WK_BOUND_3,
WK_BOUND_4,
WK_BOUND_5,
WK_BOUND_6,
WK_BOUND_7,
WK_BOUND_8,
};
static const uint8_t WK_sopcodes[8] = {
/* Note these are in order transmitted (LSB 1st) */
0xDF,0xB1,0xC0,0x49,0x62,0xDF,0xC1,0x49 //0x49C1DF6249C0B1DF
};
static const uint8_t init_2801[] = {0xc5, 0x34, 0x60, 0x00, 0x25};
static const uint8_t init_2601[] = {0xb9, 0x45, 0xb0, 0xf1, 0x3a};
static const uint8_t init_2401[] = {0xa5, 0x23, 0xd0, 0xf0, 0x00};
uint8_t WK_last_beacon;
static void __attribute__((unused)) WK_add_pkt_crc(uint8_t init)
{
uint8_t add = init;
uint8_t xou = init;
for (uint8_t i = 0; i < 14; i++)
{
add += packet[i];
xou ^= packet[i];
}
packet[14] = xou;
packet[15] = add;
}
static void __attribute__((unused)) WK_build_bind_pkt(const uint8_t *init)
{
packet[0] = init[0];
packet[1] = init[1];
packet[2] = hopping_frequency[0];
packet[3] = hopping_frequency[1];
packet[4] = init[2];
packet[5] = hopping_frequency[2];
packet[6] = 0xff;
packet[7] = 0x00;
packet[8] = 0x00;
packet[9] = 0x32;
if (sub_protocol == WK2401)
packet[10] = 0x10 | (rx_tx_addr[0] & 0x0e);
else
packet[10] = rx_tx_addr[0];
packet[11] = rx_tx_addr[1];
packet[12] = rx_tx_addr[2] | packet_count;
packet[13] = init[3];
WK_add_pkt_crc(init[4]);
}
static int16_t __attribute__((unused)) WK_get_channel(uint8_t ch, int32_t scale, int16_t center, int16_t range)
{
int16_t value = map(Servo_data[CH_AETR[ch]],servo_min_100,servo_max_100,-scale,scale)+center;
if (value < center - range) value = center - range;
if (value > center + range) value = center + range;
return value;
}
static void __attribute__((unused)) WK_build_data_pkt_2401()
{
uint16_t msb = 0;
uint8_t offset = 0;
for (uint8_t i = 0; i < 4; i++)
{
if (i == 2)
offset = 1;
int16_t value = WK_get_channel(i, 0x800, 0, 0xA00); //12 bits, allow value to go to 125%
uint16_t base = abs(value) >> 2; //10 bits is the base value
uint16_t trim = abs(value) & 0x03; //lowest 2 bits represent trim
if (base >= 0x200)
{ //if value is > 100%, remainder goes to trim
trim = 4 *(base - 0x200);
base = 0x1ff;
}
base = (value >= 0) ? 0x200 + base : 0x200 - base;
trim = (value >= 0) ? 0x200 + trim : 0x200 - trim;
packet[2*i+offset] = base & 0xff;
packet[2*i+offset+1] = trim & 0xff;
msb = (msb << 4) | ((base >> 6) & 0x0c) | ((trim >> 8) & 0x03);
}
packet[4] = msb >> 8; //Ele/Ail MSB
packet[9] = msb & 0xff; //Thr/Rud MSB
packet[10] = 0xe0 | (rx_tx_addr[0] & 0x0e);
packet[11] = rx_tx_addr[1];
packet[12] = rx_tx_addr[2] | packet_count;
packet[13] = 0xf0; //FIXME - What is this?
WK_add_pkt_crc(0x00);
}
#define PCT(pct, max) (((int32_t)(max) * (int32_t)(pct) + 1L) / 1000L)
#define MAXTHR 426 //Measured to provide equal value at +/-0
static void __attribute__((unused)) WK_channels_6plus1_2601(uint8_t frame, int16_t *_v1, int16_t *_v2)
{
int16_t thr = WK_get_channel(2, 1000, 0, 1000);
int16_t v1;
uint8_t thr_rev = 0, pitch_rev = 0;
if(thr > 0)
{
if(thr >= 780)
{ //78%
v1 = 0; //thr = 60% * (x - 78%) / 22% + 40%
thr = PCT(1000-MAXTHR,512) * (thr-PCT(780,1000)) / PCT(220,1000) + PCT(MAXTHR,512);
}
else
{
v1 = 1023 - 1023 * thr / 780;
thr = PCT(MAXTHR, 512); //40%
}
}
else
{
thr = -thr;
thr_rev = 1;
if(thr >= 780)
{ //78%
v1 = 1023; //thr = 60% * (x - 78%) / 22% + 40%
thr = PCT(1000-MAXTHR,512) * (thr-PCT(780,1000)) / PCT(220,1000) + PCT(MAXTHR,512);
}
else
{
v1 = 1023 * thr / 780;
thr = PCT(MAXTHR, 512); //40%
}
}
if (thr >= 512)
thr = 511;
packet[2] = thr & 0xff;
packet[4] = (packet[4] & 0xF3) | ((thr >> 6) & 0x04);
int16_t pitch= WK_get_channel(5, 0x400, 0, 0x400);
if (pitch < 0)
{
pitch_rev = 1;
pitch = -pitch;
}
if (frame == 1)
{
//Pitch curve and range
if (thr > PCT(MAXTHR, 512))
*_v2 = pitch - pitch * 16 * (thr - PCT(MAXTHR, 512)) / PCT(1000 - MAXTHR, 512) / 100;
else
*_v2 = pitch;
*_v1 = 0;
}
else
if (frame == 2)
{
//Throttle curve & Expo
*_v1 = v1;
*_v2 = 512;
}
packet[7] = (thr_rev << 5) | (pitch_rev << 2); //reverse bits
packet[8] = 0;
}
static void __attribute__((unused)) WK_channels_5plus1_2601(uint8_t frame, int16_t *v1, int16_t *v2)
{
(void)v1;
//Zero out pitch, provide ail, ele, thr, rud, gyr + gear
if (frame == 1)
*v2 = 0; //Pitch curve and range
packet[7] = 0;
packet[8] = 0;
}
static void __attribute__((unused)) WK_channels_heli_2601(uint8_t frame, int16_t *v1, int16_t *v2)
{
//pitch is controlled by rx
//we can only control fmode, pit-reverse and pit/thr rate
uint8_t pit_rev = 0;
if (sub_protocol==W6_HEL_I)
pit_rev = 1;
int16_t pit_rate = WK_get_channel(5, 0x400, 0, 0x400);
uint8_t fmode = 1;
if (pit_rate < 0)
{
pit_rate = -pit_rate;
fmode = 0;
}
if (frame == 1)
{
//Pitch curve and range
*v1 = pit_rate;
*v2 = (int16_t)(option) * 0x400 / 100 + 0x400;
}
packet[7] = (pit_rev << 2); //reverse bits
packet[8] = fmode ? 0x02 : 0x00;
}
static void __attribute__((unused)) WK_build_data_pkt_2601()
{
uint8_t msb = 0;
uint8_t frame = (packet_count % 3);
for (uint8_t i = 0; i < 4; i++)
{
int16_t value = WK_get_channel(i, 0x190, 0, 0x1FF);
uint16_t mag = value < 0 ? -value : value;
packet[i] = mag & 0xff;
msb = (msb << 2) | ((mag >> 8) & 0x01) | (value < 0 ? 0x02 : 0x00);
}
packet[4] = msb;
int16_t v1 = 0x200, v2 = 0x200;
if (frame == 0)
{
//Gyro & Rudder mix
v1 = WK_get_channel(6, 0x200, 0x200, 0x200);
v2 = 0;
}
if (sub_protocol == W6_5_1)
WK_channels_5plus1_2601(frame, &v1, &v2);
else if (sub_protocol == W6_6_1)
WK_channels_6plus1_2601(frame, &v1, &v2);
else
WK_channels_heli_2601(frame, &v1, &v2);
if (v1 > 1023)
v1 = 1023;
if (v2 > 1023)
v2 = 1023;
packet[5] = v2 & 0xff;
packet[6] = v1 & 0xff;
//packet[7] handled by channel code
packet[8] |= (WK_get_channel(4, 0x190, 0, 0x1FF) > 0 ? 1 : 0);
packet[9] = ((v1 >> 4) & 0x30) | ((v2 >> 2) & 0xc0) | 0x04 | frame;
packet[10] = rx_tx_addr[0];
packet[11] = rx_tx_addr[1];
packet[12] = rx_tx_addr[2] | packet_count;
packet[13] = 0xff;
WK_add_pkt_crc(0x3A);
}
static void __attribute__((unused)) WK_build_data_pkt_2801()
{
uint16_t msb = 0;
uint8_t offset = 0;
uint8_t sign = 0;
for (uint8_t i = 0; i < 8; i++)
{
if (i == 4) { offset = 1; }
int16_t value = WK_get_channel(i, 0x1C2, 0, 0x3FF);
uint16_t mag = value < 0 ? -value : value;
packet[i+offset] = mag & 0xff;
msb = (msb << 2) | ((mag >> 8) & 0x03);
if (value < 0) { sign |= 1 << i; }
}
packet[4] = msb >> 8;
packet[9] = msb & 0xff;
packet[10] = rx_tx_addr[0];
packet[11] = rx_tx_addr[1];
packet[12] = rx_tx_addr[2] | packet_count;
packet[13] = sign;
WK_add_pkt_crc(0x25);
}
static void __attribute__((unused)) WK_build_beacon_pkt_2801()
{
WK_last_beacon ^= 1;
uint8_t en = 0;
uint8_t bind_state;
#ifdef ENABLE_PPM
if(mode_select && option==0 && IS_BIND_DONE_on) //PPM mode and option not already set and bind is finished
{
BIND_SET_INPUT;
BIND_SET_PULLUP; // set pullup
if(IS_BIND_BUTTON_on)
{
eeprom_write_byte((EE_ADDR)(30+mode_select),0x01); // Set fixed id mode for the current model
option=1;
}
BIND_SET_OUTPUT;
}
#endif //ENABLE_PPM
if(prev_option!=option && IS_BIND_DONE_on)
{
set_rx_tx_addr(MProtocol_id);
rx_tx_addr[2]=rx_tx_addr[3]<<4; // Make use of RX_Num
bind_counter = WK_BIND_COUNT / 8 + 1;
}
if (option)
{
if (bind_counter)
bind_state = 0xe4;
else
bind_state = 0x1b;
}
else
bind_state = 0x99;
for (uint8_t i = 0; i < 4; i++)
{ // failsafe info: WARNING All channels are set to 0 instead of midstick and 0 for throttle
packet[i+1] = 0;
}
packet[0] = en;
packet[5] = packet[4];
packet[4] = WK_last_beacon << 6;
packet[6] = hopping_frequency[0];
packet[7] = hopping_frequency[1];
packet[8] = hopping_frequency[2];
packet[9] = bind_state;
packet[10] = rx_tx_addr[0];
packet[11] = rx_tx_addr[1];
packet[12] = rx_tx_addr[2] | packet_count;
packet[13] = 0x00; //Does this matter? in the docs it is the same as the data packet
WK_add_pkt_crc(0x1C);
}
static void __attribute__((unused)) wk2x01_cyrf_init() {
/* Initialize CYRF chip */
CYRF_SetPower(0x28);
CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4A);
CYRF_WriteRegister(CYRF_0B_PWR_CTRL, 0x00);
CYRF_WriteRegister(CYRF_0C_XTAL_CTRL, 0xC0);
CYRF_WriteRegister(CYRF_0D_IO_CFG, 0x04);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x2C);
CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xEE);
CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, 0x55);
CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, 0x05);
CYRF_WriteRegister(CYRF_1D_MODE_OVERRIDE, 0x18);
CYRF_WriteRegister(CYRF_32_AUTO_CAL_TIME, 0x3C);
CYRF_WriteRegister(CYRF_35_AUTOCAL_OFFSET, 0x14);
CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x90);
CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00);
CYRF_WriteRegister(CYRF_01_TX_LENGTH, 0x10);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x2C);
CYRF_WriteRegister(CYRF_28_CLK_EN, 0x02);
CYRF_WriteRegister(CYRF_27_CLK_OVERRIDE, 0x02);
CYRF_ConfigSOPCode(WK_sopcodes);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x28);
CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x10);
CYRF_WriteRegister(CYRF_0E_GPIO_CTRL, 0x20);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x2C);
}
static void __attribute__((unused)) WK_BuildPacket_2801()
{
switch(phase) {
case WK_BIND:
bind_counter--;
WK_build_bind_pkt(init_2801);
if (bind_counter == 0)
{
BIND_DONE;
phase++;
}
break;
case WK_BOUND_1:
case WK_BOUND_2:
case WK_BOUND_3:
case WK_BOUND_4:
case WK_BOUND_5:
case WK_BOUND_6:
case WK_BOUND_7:
WK_build_data_pkt_2801();
phase++;
break;
case WK_BOUND_8:
WK_build_beacon_pkt_2801();
phase = WK_BOUND_1;
if (bind_counter)
{
bind_counter--;
if (bind_counter == 0)
BIND_DONE;
}
break;
}
}
static void __attribute__((unused)) WK_BuildPacket_2601()
{
if (bind_counter)
{
bind_counter--;
WK_build_bind_pkt(init_2601);
if (bind_counter == 0)
BIND_DONE;
}
else
WK_build_data_pkt_2601();
}
static void __attribute__((unused)) WK_BuildPacket_2401()
{
if (bind_counter)
{
bind_counter--;
WK_build_bind_pkt(init_2401);
if(bind_counter == 0)
BIND_DONE;
}
else
WK_build_data_pkt_2401();
}
uint16_t WK_cb()
{
if (packet_sent == 0)
{
packet_sent = 1;
if(sub_protocol == WK2801)
WK_BuildPacket_2801();
else if(sub_protocol == WK2401)
WK_BuildPacket_2401();
else
WK_BuildPacket_2601();
packet_count = (packet_count + 1) % 12;
CYRF_WriteDataPacket(packet);
return 1600;
}
packet_sent = 0;
uint8_t start=micros();
while ((uint8_t)micros()-start < 100) // Wait max 100µs
if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)
break;
if((packet_count & 0x03) == 0)
{
hopping_frequency_no++;
hopping_frequency_no%=3;
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
//Keep transmit power updated
CYRF_SetPower(0x28);
}
return 1200;
}
uint16_t WK_setup() {
wk2x01_cyrf_init();
CYRF_SetTxRxMode(TX_EN);
hopping_frequency_no=0;
CYRF_FindBestChannels(hopping_frequency, 3, 4, 4, 80);
CYRF_ConfigRFChannel(hopping_frequency[0]);
packet_count = 0;
packet_sent = 0;
WK_last_beacon = 0;
prev_option=option;
if(sub_protocol!=WK2801 || option==0)
{
CYRF_GetMfgData(cyrfmfg_id);
rx_tx_addr[2]=(hopping_frequency[0] ^ cyrfmfg_id[0] ^ cyrfmfg_id[3])<<4;
rx_tx_addr[1]=hopping_frequency[1] ^ cyrfmfg_id[1] ^ cyrfmfg_id[4];
rx_tx_addr[0]=hopping_frequency[2] ^ cyrfmfg_id[2] ^ cyrfmfg_id[5];
if(sub_protocol == WK2401)
rx_tx_addr[0] |= 0x01; //ID must be odd for 2401
bind_counter = WK_BIND_COUNT;
phase = WK_BIND;
BIND_IN_PROGRESS;
}
else
{
rx_tx_addr[2]=rx_tx_addr[3]<<4; // Make use of RX_Num
bind_counter = 0;
phase = WK_BOUND_1;
BIND_DONE;
}
return 2800;
}
#endif

View File

@@ -18,10 +18,9 @@
#include "iface_nrf24l01.h"
#define YD717_BIND_COUNT 60
#define YD717_BIND_COUNT 120
#define YD717_PACKET_PERIOD 8000 // Timeout for callback in uSec, 8ms=8000us for YD717
#define YD717_INITIAL_WAIT 50000 // Initial wait before starting callbacks
#define YD717_PACKET_CHKTIME 500 // Time to wait if packet not yet acknowledged or timed out
// Stock tx fixed frequency is 0x3C. Receiver only binds on this freq.
#define YD717_RF_CHANNEL 0x3C
@@ -125,32 +124,32 @@ static void __attribute__((unused)) yd717_init()
// CRC, radio on
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // Disable Acknoledgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00); // Disable all data pipes
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmit
NRF24L01_WriteReg(NRF24L01_05_RF_CH, YD717_RF_CHANNEL); // Channel 3C
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3F); // Enable Acknowledgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x1A); // 500uS retransmit t/o, 10 tries
NRF24L01_WriteReg(NRF24L01_05_RF_CH, YD717_RF_CHANNEL); // Channel 3C
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent and retransmit
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F); // Enable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Set feature bits on
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F); // Enable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Set feature bits on
NRF24L01_Activate(0x73);
// for bind packets set address to prearranged value known to receiver
uint8_t bind_rx_tx_addr[] = {0x65, 0x65, 0x65, 0x65, 0x65};
uint8_t bind_rx_tx_addr[5];
uint8_t offset=5;
if( sub_protocol==SYMAX4 )
for(uint8_t i=0; i < 5; i++)
bind_rx_tx_addr[i] = 0x60;
offset=0;
else
if( sub_protocol==NIHUI )
for(uint8_t i=0; i < 5; i++)
bind_rx_tx_addr[i] = 0x64;
offset=4;
for(uint8_t i=0; i < 5; i++)
bind_rx_tx_addr[i] = 0x60 + offset;
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_rx_tx_addr, 5);
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, bind_rx_tx_addr, 5);
}
uint16_t yd717_callback()
@@ -162,6 +161,7 @@ uint16_t yd717_callback()
if (bind_counter == 0)
{
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5); // set address
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
yd717_send_packet(0);
BIND_DONE; // bind complete
}

View File

@@ -17,16 +17,6 @@
/** Multiprotocol module configuration file ***/
/**********************************************/
/********************/
/*** BOARD TYPE ***/
/********************/
//Uncomment one of the line below if you have a different module not based on the original Multi Atmega328p design which includes the 4-in-1.
//If you don't know then leave them commented.
#ifdef __arm__
#define STM32_BOARD // Let's automatically select this board if arm is selected since this is the only one for now...
#endif
/*******************/
/*** TX SETTINGS ***/
/*******************/
@@ -42,9 +32,27 @@
//#define REVERSE_RUDDER
/**************************/
/*** RF CHIPS INSTALLED ***/
/**************************/
/*************************/
/*** BIND FROM CHANNEL ***/
/*************************/
//Bind from channel enables you to bind when a specified channel is giong from low to high. This feature is only active
// if you specify AUTOBIND in PPM mode or set AutoBind to YES for serial mode. It also requires that the throttle channel is low.
//Comment to globaly disable the bind feature from a channel.
#define ENABLE_BIND_CH
//Set the channel number used for bind. Default is 16.
#define BIND_CH 16
//Comment to disable the wait for bind feature. This feature will not activate the selected
// protocol unless a bind is requested using bind from channel or the GUI "Bind" button.
//The goal is to prevent binding other people's model when powering up the TX, changing model or scanning through protocols.
#define WAIT_FOR_BIND
/****************/
/*** RF CHIPS ***/
/****************/
//There are 4 RF components supported. If one of them is not installed you must comment it using "//".
//If a chip is not installed all associated protocols are disabled.
//4-in-1 modules have all RF chips installed
@@ -54,6 +62,14 @@
#define CC2500_INSTALLED
#define NRF24L01_INSTALLED
//Low power is reducing the transmit power of the multi module. This setting is configurable per model in PPM (table below) or Serial mode (radio GUI).
//It can be activated when flying indoor or small models since the distance is short or if a model is causing issues when flying closed to the TX.
//By default low power is completly disabled on all rf chips to prevent mistakes, but you can enable it by uncommenting the lines below:
//#define A7105_ENABLE_LOW_POWER
//#define CYRF6936_ENABLE_LOW_POWER
//#define CC2500_ENABLE_LOW_POWER
//#define NRF24L01_ENABLE_LOW_POWER
/****************************/
/*** PROTOCOLS TO INCLUDE ***/
@@ -71,10 +87,11 @@
#define DEVO_CYRF6936_INO
#define DSM_CYRF6936_INO
#define J6PRO_CYRF6936_INO
#define WK2x01_CYRF6936_INO
//The protocols below need a CC2500 to be installed
#define FRSKYD_CC2500_INO
#define FRSKYV_CC2500_INO
#define FRSKYD_CC2500_INO
#define FRSKYX_CC2500_INO
#define SFHSS_CC2500_INO
@@ -96,9 +113,10 @@
#define FQ777_NRF24L01_INO
#define ASSAN_NRF24L01_INO
#define HONTAI_NRF24L01_INO
#define Q303_NRF24L01_INO
#define GW008_NRF24L01_INO
#define CABELL_NRF24L01_INO
/**************************/
/*** TELEMETRY SETTINGS ***/
/**************************/
@@ -107,15 +125,23 @@
//If you do not plan using the telemetry comment this global setting using "//" and skip to the next section.
#define TELEMETRY
//Uncomment to invert the polarity of the telemetry serial signal.
//For ER9X and ERSKY9X it must be commented. For OpenTX it must be uncommented.
//Comment to invert the polarity of the output telemetry serial signal.
//This function takes quite some flash space and processor power on an atmega.
//For OpenTX it must be uncommented.
//On a 9XR_PRO running ersky9x both commented and uncommented will work depending on the radio setting Invert COM1 under the Telemetry menu.
//On other addon/replacement boards like the 9xtreme board or the Ar9x board running ersky9x, you need to uncomment the line below.
//For er9x it depends if you have an inveter mod or not on the telemetry pin. If you don't have an inverter comment this line.
//#define INVERT_TELEMETRY
//Uncomment to send also Multi status and wrap other telemetry to allow TX to autodetect the format
//Only for newest OpenTX version
//Comment if you don't want to send Multi status telemetry frames (Protocol available, Bind in progress, version...)
//Use with er9x/erksy9x, for OpenTX MULTI_TELEMETRY below is preferred instead
#define MULTI_STATUS
//Uncomment to send Multi status and allow OpenTX to autodetect the telemetry format
//Supported by OpenTX version 2.2 RC9 and newer. NOT supported by er9x/ersky9x use MULTI_STATUS instead.
//#define MULTI_TELEMETRY
//Comment a line to disable a protocol telemetry
//Comment a line to disable a specific protocol telemetry
#define DSM_TELEMETRY // Forward received telemetry packet directly to TX to be decoded
#define SPORT_TELEMETRY // Use FrSkyX SPORT format to send telemetry to TX
#define AFHDS2A_FW_TELEMETRY // Forward received telemetry packet directly to TX to be decoded
@@ -124,6 +150,7 @@
#define BAYANG_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define HUBSAN_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
/****************************/
/*** SERIAL MODE SETTINGS ***/
/****************************/
@@ -149,8 +176,9 @@
#define TX_ER9X //ER9X/ERSKY9X/OpenTX ( 988<->2012µs)
//#define TX_DEVO7 //DEVO (1120<->1920µs)
//#define TX_SPEKTRUM //Spektrum (1100<->1900µs)
//#define TX_HISKY //HISKY (1100<->1900µs)
//#define TX_HISKY //HISKY (1120<->1920µs)
//#define TX_MPX //Multiplex MC2020 (1250<->1950µs)
//#define TX_WALKERA //Walkera PL0811-01H (1000<->1800µs)
//#define TX_CUSTOM //Custom
// The lines below are used to set the end points in microseconds (µs) if you have selected TX_CUSTOM.
@@ -166,6 +194,13 @@
#define PPM_MIN_125 1000 // 125%
#endif
// The line below is used to set the minimum number of channels which the module should receive to consider a PPM frame valid.
// The default value is 4 to receive at least AETR for flying models but you could also connect the PPM from a car radio which has only 3 channels by changing this number to 3.
#define MIN_PPM_CHANNELS 4
// The line below is used to set the maximum number of channels which the module should work with. Any channels received above this number are discarded.
// The default value is 16 to receive all possible channels but you might want to filter some "bad" channels from the PPM frame like the ones above 6 on the Walkera PL0811.
#define MAX_PPM_CHANNELS 16
//The table below indicates which protocol to run when a specific position on the dial has been selected.
//All fields and values are explained below. Everything is configurable from here like in the Serial mode.
//Example: You can associate multiple times the same protocol to different dial positions to take advantage of the model match (RX_Num)
@@ -196,8 +231,15 @@ const PPM_Parameters PPM_prot[15]= {
CX20
MODE_HUBSAN
NONE
MODE_FRSKYV
NONE
MODE_FRSKYD
NONE
MODE_FRSKYX
CH_16
CH_8
EU_16
EU_8
MODE_HISKY
Hisky
HK310
@@ -246,9 +288,6 @@ const PPM_Parameters PPM_prot[15]= {
MODE_BAYANG
BAYANG
H8S3D
MODE_FRSKYX
CH_16
CH_8
MODE_ESKY
NONE
MODE_MT99XX
@@ -277,8 +316,6 @@ const PPM_Parameters PPM_prot[15]= {
NONE
MODE_ASSAN
NONE
MODE_FRSKYV
NONE
MODE_HONTAI
FORMAT_HONTAI
FORMAT_JJRCX1
@@ -289,6 +326,20 @@ const PPM_Parameters PPM_prot[15]= {
PPM_IBUS
PWM_SBUS
PPM_SBUS
MODE_WK2X01
WK2801
WK2401
W6_5_1
W6_6_1
W6_HEL
W6_HEL_I
MODE_Q303
Q303
CX35
CX10D
CX10WD
MODE_GW008
NONE
MODE_CABELL
CABELL_V3
CABELL_SET_FAIL_SAFE
@@ -304,6 +355,7 @@ const PPM_Parameters PPM_prot[15]= {
// Auto Bind AUTOBIND or NO_AUTOBIND
// For protocols which does not require binding at each power up (like Flysky, FrSky...), you might still want a bind to be initiated each time you power up the TX.
// As an example, it's usefull for the WLTOYS F929/F939/F949/F959 (all using the Flysky protocol) which requires a bind at each power up.
// It also enables the Bind from channel feature, allowing to execute a bind by toggling a designated channel.
// Option: the value is between -127 and +127.
// Option: the value is between -128 and +127.
// The option value is only valid for some protocols, read this page for more information: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/Protocols_Details.md

View File

@@ -16,16 +16,6 @@
#ifndef _IFACE_CC2500_H_
#define _IFACE_CC2500_H_
enum {
FRSKY_BIND = 0,
FRSKY_BIND_DONE = 1000,
FRSKY_DATA1,
FRSKY_DATA2,
FRSKY_DATA3,
FRSKY_DATA4,
FRSKY_DATA5
};
enum {
CC2500_00_IOCFG2 = 0x00, // GDO2 output pin configuration
CC2500_01_IOCFG1 = 0x01, // GDO1 output pin configuration
@@ -157,42 +147,4 @@ enum {
//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