Création

This commit is contained in:
tipouic 2016-09-30 13:36:12 +02:00
parent 89bea4c38b
commit 068b21cbb1
48 changed files with 7675 additions and 4271 deletions

View File

@ -30,12 +30,12 @@ void A7105_WriteData(uint8_t len, uint8_t channel)
A7105_Strobe(A7105_TX);
}
void A7105_ReadData() {
void A7105_ReadData(uint8_t len=16) {
uint8_t i;
A7105_Strobe(0xF0); //A7105_RST_RDPTR
A7105_CSN_off;
SPI_Write(0x45);
for (i=0;i<16;i++)
for (i=0;i<len;i++)
packet[i]=SPI_SDIO_Read();
A7105_CSN_on;
}
@ -159,16 +159,25 @@ const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00,
0x01, 0x0f, 0xff
};
const uint8_t AFHDS2A_regs[] = {
-1 , 0x42 | (1<<5), 0x00, 0x25, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c, 0x05, 0x00, 0x50, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x4f, 0x62, 0x80, -1, -1, 0x2a, 0x32, 0xc3, 0x1f, // 10 - 1f
0x1e, -1, 0x00, -1, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
#define ID_NORMAL 0x55201041
#define ID_PLUS 0xAA201041
void A7105_Init(uint8_t protocol)
{
void *A7105_Regs;
if(protocol==INIT_FLYSKY)
if(protocol==INIT_FLYSKY || protocol==INIT_FLYSKY_AFHDS2A)
{
A7105_WriteID(0x5475c52A);//0x2Ac57554
A7105_Regs=(void *)FLYSKY_A7105_regs;
if(protocol==INIT_FLYSKY_AFHDS2A)
A7105_Regs=(void *)AFHDS2A_regs;
else
A7105_Regs=(void *)FLYSKY_A7105_regs;
}
else
{
@ -187,7 +196,7 @@ void A7105_Init(uint8_t protocol)
// A7105_ReadReg(A7105_22_IF_CALIB_I);
// A7105_ReadReg(A7105_24_VCO_CURCAL);
if(protocol==INIT_FLYSKY)
if(protocol==INIT_FLYSKY || protocol==INIT_FLYSKY_AFHDS2A)
{
//VCO Current Calibration
A7105_WriteReg(A7105_24_VCO_CURCAL,0x13); //Recommended calibration from A7105 Datasheet
@ -210,6 +219,8 @@ void A7105_Init(uint8_t protocol)
//Reset VCO Band calibration
if(protocol==INIT_FLYSKY)
A7105_WriteReg(A7105_25_VCO_SBCAL_I,0x08);
if(protocol==INIT_FLYSKY_AFHDS2A)
A7105_WriteReg(A7105_25_VCO_SBCAL_I,0x0A);
A7105_SetTxRxMode(TX_EN);
A7105_SetPower();

View File

@ -109,9 +109,7 @@ static void joysway_build_packet()
static const int chmap[4] = {6, 7, 10, 11};
for (i = 0; i < 4; i++) {
// if (i >= Model.num_channels) { packet[chmap[i]] = 0x64; continue; }
uint32_t value = (uint32_t)Servo_data[i] * 0x66 / PPM_MAX + 0x66;
if (value < 0) { value = 0; }
if (value > 0xff) { value = 0xff; }
uint32_t value = map(limit_channel_100(i),servo_min_100,servo_max_100,0,204);
packet[chmap[i]] = value;
}
packet[8] = 0x64;

View File

@ -25,10 +25,6 @@
#define Q282_PACKET_SIZE 21
#define CX10_PACKET_PERIOD 1316 // Timeout for callback in uSec
#define CX10A_PACKET_PERIOD 6000
<<<<<<< HEAD
#define CX10A_BIND_COUNT 400 // 2 seconds
=======
>>>>>>> refs/remotes/pascallanger/master
#define CX10_INITIAL_WAIT 500
@ -201,30 +197,15 @@ uint16_t CX10_callback()
}
break;
case CX10_BIND2:
<<<<<<< HEAD
bind_counter--;
if(bind_counter==0)
{ // Needed for some CX-10A to properly finish the bind
CX10_init();
bind_counter=CX10A_BIND_COUNT;
}
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR))
=======
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
>>>>>>> refs/remotes/pascallanger/master
{ // RX fifo data ready
XN297_ReadPayload(packet, packet_length);
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
if(packet[9] == 1)
{
<<<<<<< HEAD
phase = CX10_BIND1;
bind_counter=0;
=======
BIND_DONE;
phase = CX10_DATA;
>>>>>>> refs/remotes/pascallanger/master
}
}
else
@ -234,11 +215,7 @@ uint16_t CX10_callback()
NRF24L01_FlushTx();
NRF24L01_SetTxRxMode(TX_EN);
CX10_Write_Packet(1);
<<<<<<< HEAD
delayMicroseconds(400); // 300µs in deviation but not working so using 400µs instead
=======
delayMicroseconds(400);
>>>>>>> refs/remotes/pascallanger/master
// switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
@ -288,10 +265,6 @@ uint16_t initCX10(void)
packet_period = CX10A_PACKET_PERIOD;
phase = CX10_BIND2;
<<<<<<< HEAD
bind_counter=CX10A_BIND_COUNT;
=======
>>>>>>> refs/remotes/pascallanger/master
for(uint8_t i=0; i<4; i++)
packet[5+i] = 0xff; // clear aircraft id

View File

@ -192,18 +192,11 @@ static void CYRF_StartReceive()
CYRF_ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, 0x10);
}
*/
<<<<<<< HEAD
static void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length)
=======
void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length)
>>>>>>> refs/remotes/pascallanger/master
{
CYRF_ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, length);
}
<<<<<<< HEAD
=======
>>>>>>> refs/remotes/pascallanger/master
static void CYRF_WriteDataPacketLen(const uint8_t dpbuffer[], uint8_t len)
{
CYRF_WriteRegister(CYRF_01_TX_LENGTH, len);

View File

@ -1,277 +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.
Deviation is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Deviation. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(J6PRO_CYRF6936_INO)
#include "iface_cyrf6936.h"
#define NUM_WAIT_LOOPS (100 / 5) //each loop is ~5us. Do not wait more than 100us
//For Debug
//#define NO_SCRAMBLE
enum J6ProState {
J6PRO_BIND,
J6PRO_BIND_01,
J6PRO_BIND_03_START,
J6PRO_BIND_03_CHECK,
J6PRO_BIND_05_1,
J6PRO_BIND_05_2,
J6PRO_BIND_05_3,
J6PRO_BIND_05_4,
J6PRO_BIND_05_5,
J6PRO_BIND_05_6,
J6PRO_CHANSEL,
J6PRO_CHAN_1,
J6PRO_CHAN_2,
J6PRO_CHAN_3,
J6PRO_CHAN_4,
};
static const uint8_t J6Pro_sopcodes[][8] = {
/* Note these are in order transmitted (LSB 1st) */
{0x3C, 0x37, 0xCC, 0x91, 0xE2, 0xF8, 0xCC, 0x91},
{0x9B, 0xC5, 0xA1, 0x0F, 0xAD, 0x39, 0xA2, 0x0F},
{0xEF, 0x64, 0xB0, 0x2A, 0xD2, 0x8F, 0xB1, 0x2A},
{0x66, 0xCD, 0x7C, 0x50, 0xDD, 0x26, 0x7C, 0x50},
{0x5C, 0xE1, 0xF6, 0x44, 0xAD, 0x16, 0xF6, 0x44},
{0x5A, 0xCC, 0xAE, 0x46, 0xB6, 0x31, 0xAE, 0x46},
{0xA1, 0x78, 0xDC, 0x3C, 0x9E, 0x82, 0xDC, 0x3C},
{0xB9, 0x8E, 0x19, 0x74, 0x6F, 0x65, 0x18, 0x74},
{0xDF, 0xB1, 0xC0, 0x49, 0x62, 0xDF, 0xC1, 0x49},
{0x97, 0xE5, 0x14, 0x72, 0x7F, 0x1A, 0x14, 0x72},
{0x82, 0xC7, 0x90, 0x36, 0x21, 0x03, 0xFF, 0x17},
{0xE2, 0xF8, 0xCC, 0x91, 0x3C, 0x37, 0xCC, 0x91}, //Note: the '03' was '9E' in the Cypress recommended table
{0xAD, 0x39, 0xA2, 0x0F, 0x9B, 0xC5, 0xA1, 0x0F}, //The following are the same as the 1st 8 above,
{0xD2, 0x8F, 0xB1, 0x2A, 0xEF, 0x64, 0xB0, 0x2A}, //but with the upper and lower word swapped
{0xDD, 0x26, 0x7C, 0x50, 0x66, 0xCD, 0x7C, 0x50},
{0xAD, 0x16, 0xF6, 0x44, 0x5C, 0xE1, 0xF6, 0x44},
{0xB6, 0x31, 0xAE, 0x46, 0x5A, 0xCC, 0xAE, 0x46},
{0x9E, 0x82, 0xDC, 0x3C, 0xA1, 0x78, 0xDC, 0x3C},
{0x6F, 0x65, 0x18, 0x74, 0xB9, 0x8E, 0x19, 0x74},
};
const uint8_t bind_sop_code[] = {0x62, 0xdf, 0xc1, 0x49, 0xdf, 0xb1, 0xc0, 0x49};
const uint8_t data_code[] = {0x02, 0xf9, 0x93, 0x97, 0x02, 0xfa, 0x5c, 0xe3, 0x01, 0x2b, 0xf1, 0xdb, 0x01, 0x32, 0xbe, 0x6f};
static uint8_t stateJ6P;
static uint8_t radio_ch[4];
static uint8_t num_channels;
void J6Pro_build_bind_packet()
{
packet[0] = 0x01; //Packet type
packet[1] = 0x01; //FIXME: What is this? Model number maybe?
packet[2] = 0x56; //FIXME: What is this?
packet[3] = cyrfmfg_id[0];
packet[4] = cyrfmfg_id[1];
packet[5] = cyrfmfg_id[2];
packet[6] = cyrfmfg_id[3];
packet[7] = cyrfmfg_id[4];
packet[8] = cyrfmfg_id[5];
}
void J6Pro_build_data_packet()
{
uint8_t i;
uint32_t upperbits = 0;
packet[0] = 0xaa; //FIXME what is this?
for (i = 0; i < 12; i++) {
if (i >= num_channels) {
packet[i+1] = 0xff;
continue;
}
uint32_t value = (uint32_t)Servo_data[i] * 0x200 / PPM_MAX + 0x200;
if (value < 0)
value = 0;
if (value > 0x3ff)
value = 0x3ff;
packet[i+1] = value & 0xff;
upperbits |= (value >> 8) << (i * 2);
}
packet[13] = upperbits & 0xff;
packet[14] = (upperbits >> 8) & 0xff;
packet[15] = (upperbits >> 16) & 0xff;
}
static void J6Pro_cyrf_init()
{
/* Initialise CYRF chip */
CYRF_WriteRegister(CYRF_28_CLK_EN, 0x02);
CYRF_WriteRegister(CYRF_32_AUTO_CAL_TIME, 0x3c);
CYRF_WriteRegister(CYRF_35_AUTOCAL_OFFSET, 0x14);
CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, 0x05);
CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, 0x55);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
CYRF_WriteRegister(CYRF_03_TX_CFG, 0x05 | CYRF_BIND_POWER);
CYRF_WriteRegister(CYRF_06_RX_CFG, 0x8a);
CYRF_WriteRegister(CYRF_03_TX_CFG, 0x28 | CYRF_BIND_POWER);
CYRF_WriteRegister(CYRF_12_DATA64_THOLD, 0x0e);
CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xee);
CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00);
CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x00);
CYRF_ConfigDataCode(data_code, 16);
CYRF_WritePreamble(0x023333);
}
static void J6Pro_cyrf_bindinit()
{
/* Use when binding */
//0.060470# 03 2f
CYRF_WriteRegister(CYRF_03_TX_CFG, 0x28 | 0x07); //Use max power for binding in case there is no telem module
CYRF_ConfigRFChannel(0x52);
CYRF_ConfigSOPCode(bind_sop_code);
CYRF_ConfigCRCSeed(0x0000);
CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a);
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83);
//0.061511# 13 20
CYRF_ConfigRFChannel(0x52);
//0.062684# 0f 05
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
//0.062792# 0f 05
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40);
J6Pro_build_bind_packet(); //01 01 e9 49 ec a9 c4 c1 ff
//CYRF_WriteDataPacketLen(packet, 0x09);
}
static void J6Pro_cyrf_datainit()
{
/* Use when already bound */
//0.094007# 0f 05
uint8_t sop_idx = (0xff & (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[5])) % 19;
uint16_t crc = (0xff & (cyrfmfg_id[1] - cyrfmfg_id[4] + cyrfmfg_id[5])) |
((0xff & (cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[4] + cyrfmfg_id[5])) << 8);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
CYRF_ConfigSOPCode(J6Pro_sopcodes[sop_idx]);
CYRF_ConfigCRCSeed(crc);
}
static void J6Pro_set_radio_channels()
{
//FIXME: Query free channels
//lowest channel is 0x08, upper channel is 0x4d?
CYRF_FindBestChannels(radio_ch, 3, 5, 8, 77);
radio_ch[3] = radio_ch[0];
}
static uint16_t j6pro_cb()
{
switch(stateJ6P) {
case J6PRO_BIND:
J6Pro_cyrf_bindinit();
stateJ6P = J6PRO_BIND_01;
//no break because we want to send the 1st bind packet now
case J6PRO_BIND_01:
CYRF_ConfigRFChannel(0x52);
CYRF_SetTxRxMode(TX_EN);
//0.062684# 0f 05
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
//0.062684# 0f 05
CYRF_WriteDataPacketLen(packet, 0x09);
stateJ6P = J6PRO_BIND_03_START;
return 3000; //3msec
case J6PRO_BIND_03_START:
{
int i = 0;
while (! (CYRF_ReadRegister(0x04) & 0x06))
if(++i > NUM_WAIT_LOOPS)
break;
}
CYRF_ConfigRFChannel(0x53);
CYRF_SetTxRxMode(RX_EN);
CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a);
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83);
stateJ6P = J6PRO_BIND_03_CHECK;
return 30000; //30msec
case J6PRO_BIND_03_CHECK:
{
uint8_t rx = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx & 0x1a) == 0x1a) {
rx = CYRF_ReadRegister(CYRF_0A_RX_LENGTH);
if(rx == 0x0f) {
rx = CYRF_ReadRegister(CYRF_09_RX_COUNT);
if(rx == 0x0f) {
//Expected and actual length are both 15
CYRF_ReadDataPacketLen(packet, rx);
if (packet[0] == 0x03 &&
packet[3] == cyrfmfg_id[0] &&
packet[4] == cyrfmfg_id[1] &&
packet[5] == cyrfmfg_id[2] &&
packet[6] == cyrfmfg_id[3] &&
packet[7] == cyrfmfg_id[4] &&
packet[8] == cyrfmfg_id[5])
{
//Send back Ack
packet[0] = 0x05;
CYRF_ConfigRFChannel(0x54);
CYRF_SetTxRxMode(TX_EN);
stateJ6P = J6PRO_BIND_05_1;
return 2000; //2msec
}
}
}
}
stateJ6P = J6PRO_BIND_01;
return 500;
}
case J6PRO_BIND_05_1:
case J6PRO_BIND_05_2:
case J6PRO_BIND_05_3:
case J6PRO_BIND_05_4:
case J6PRO_BIND_05_5:
case J6PRO_BIND_05_6:
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
CYRF_WriteDataPacketLen(packet, 0x0f);
stateJ6P = stateJ6P + 1;
return 4600; //4.6msec
case J6PRO_CHANSEL:
BIND_DONE;
J6Pro_set_radio_channels();
J6Pro_cyrf_datainit();
stateJ6P = J6PRO_CHAN_1;
case J6PRO_CHAN_1:
//Keep transmit power updated
CYRF_SetPower(CYRF_HIGH_POWER);
J6Pro_build_data_packet();
//return 3400;
case J6PRO_CHAN_2:
//return 3500;
case J6PRO_CHAN_3:
//return 3750
case J6PRO_CHAN_4:
CYRF_ConfigRFChannel(radio_ch[stateJ6P - J6PRO_CHAN_1]);
CYRF_SetTxRxMode(TX_EN);
CYRF_WriteDataPacket(packet);
if (stateJ6P == J6PRO_CHAN_4) {
stateJ6P = J6PRO_CHAN_1;
return 13900;
}
stateJ6P = stateJ6P + 1;
return 3550;
}
return 0;
}
static uint16_t j6pro_setup()
{
CYRF_Reset();
J6Pro_cyrf_init();
num_channels = 8;
if (IS_AUTOBIND_FLAG_on) {
stateJ6P = J6PRO_BIND;
BIND_IN_PROGRESS;
} else {
stateJ6P = J6PRO_CHANSEL;
}
return 2400;
}
#endif

View File

@ -37,53 +37,53 @@ enum {
static void skyartec_init() {
CC2500_Reset();
cc2500_writeReg(CC2500_16_MCSM2, 0x07);
cc2500_writeReg(CC2500_17_MCSM1, 0x30);
cc2500_writeReg(CC2500_1E_WOREVT1, 0x87);
cc2500_writeReg(CC2500_1F_WOREVT0, 0x6b);
cc2500_writeReg(CC2500_20_WORCTRL, 0xf8);
cc2500_writeReg(CC2500_2A_PTEST, 0x7f);
cc2500_writeReg(CC2500_2B_AGCTEST, 0x3f);
cc2500_writeReg(CC2500_0B_FSCTRL1, 0x09);
cc2500_writeReg(CC2500_0C_FSCTRL0, 0x00);
cc2500_writeReg(CC2500_0D_FREQ2, 0x5d);
cc2500_writeReg(CC2500_0E_FREQ1, 0x93);
cc2500_writeReg(CC2500_0F_FREQ0, 0xb1);
cc2500_writeReg(CC2500_10_MDMCFG4, 0x2d);
cc2500_writeReg(CC2500_11_MDMCFG3, 0x20);
cc2500_writeReg(CC2500_12_MDMCFG2, 0x73);
cc2500_writeReg(CC2500_13_MDMCFG1, 0x22);
cc2500_writeReg(CC2500_14_MDMCFG0, 0xf8);
cc2500_writeReg(CC2500_0A_CHANNR, 0xcd);
cc2500_writeReg(CC2500_15_DEVIATN, 0x50);
cc2500_writeReg(CC2500_21_FREND1, 0xb6);
cc2500_writeReg(CC2500_22_FREND0, 0x10);
cc2500_writeReg(CC2500_18_MCSM0, 0x18);
cc2500_writeReg(CC2500_19_FOCCFG, 0x1d);
cc2500_writeReg(CC2500_1A_BSCFG, 0x1c);
cc2500_writeReg(CC2500_1B_AGCCTRL2, 0xc7);
cc2500_writeReg(CC2500_1C_AGCCTRL1, 0x00);
cc2500_writeReg(CC2500_1D_AGCCTRL0, 0xb2);
cc2500_writeReg(CC2500_23_FSCAL3, 0xea);
cc2500_writeReg(CC2500_24_FSCAL2, 0x0a);
cc2500_writeReg(CC2500_25_FSCAL1, 0x00);
cc2500_writeReg(CC2500_26_FSCAL0, 0x11);
cc2500_writeReg(CC2500_29_FSTEST, 0x59);
cc2500_writeReg(CC2500_2C_TEST2, 0x88);
cc2500_writeReg(CC2500_2D_TEST1, 0x31);
cc2500_writeReg(CC2500_2E_TEST0, 0x0b);
cc2500_writeReg(CC2500_07_PKTCTRL1, 0x05);
cc2500_writeReg(CC2500_08_PKTCTRL0, 0x05);
cc2500_writeReg(CC2500_09_ADDR, 0x43);
cc2500_writeReg(CC2500_06_PKTLEN, 0xff);
cc2500_writeReg(CC2500_04_SYNC1, 0x13);
cc2500_writeReg(CC2500_05_SYNC0, 0x18);
CC2500_WriteReg(CC2500_16_MCSM2, 0x07);
CC2500_WriteReg(CC2500_17_MCSM1, 0x30);
CC2500_WriteReg(CC2500_1E_WOREVT1, 0x87);
CC2500_WriteReg(CC2500_1F_WOREVT0, 0x6b);
CC2500_WriteReg(CC2500_20_WORCTRL, 0xf8);
CC2500_WriteReg(CC2500_2A_PTEST, 0x7f);
CC2500_WriteReg(CC2500_2B_AGCTEST, 0x3f);
CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x09);
CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00);
CC2500_WriteReg(CC2500_0D_FREQ2, 0x5d);
CC2500_WriteReg(CC2500_0E_FREQ1, 0x93);
CC2500_WriteReg(CC2500_0F_FREQ0, 0xb1);
CC2500_WriteReg(CC2500_10_MDMCFG4, 0x2d);
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x20);
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x73);
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x22);
CC2500_WriteReg(CC2500_14_MDMCFG0, 0xf8);
CC2500_WriteReg(CC2500_0A_CHANNR, 0xcd);
CC2500_WriteReg(CC2500_15_DEVIATN, 0x50);
CC2500_WriteReg(CC2500_21_FREND1, 0xb6);
CC2500_WriteReg(CC2500_22_FREND0, 0x10);
CC2500_WriteReg(CC2500_18_MCSM0, 0x18);
CC2500_WriteReg(CC2500_19_FOCCFG, 0x1d);
CC2500_WriteReg(CC2500_1A_BSCFG, 0x1c);
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xc7);
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00);
CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xb2);
CC2500_WriteReg(CC2500_23_FSCAL3, 0xea);
CC2500_WriteReg(CC2500_24_FSCAL2, 0x0a);
CC2500_WriteReg(CC2500_25_FSCAL1, 0x00);
CC2500_WriteReg(CC2500_26_FSCAL0, 0x11);
CC2500_WriteReg(CC2500_29_FSTEST, 0x59);
CC2500_WriteReg(CC2500_2C_TEST2, 0x88);
CC2500_WriteReg(CC2500_2D_TEST1, 0x31);
CC2500_WriteReg(CC2500_2E_TEST0, 0x0b);
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05);
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05);
CC2500_WriteReg(CC2500_09_ADDR, 0x43);
CC2500_WriteReg(CC2500_06_PKTLEN, 0xff);
CC2500_WriteReg(CC2500_04_SYNC1, 0x13);
CC2500_WriteReg(CC2500_05_SYNC0, 0x18);
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
cc2500_strobe(CC2500_SFTX);
cc2500_strobe(CC2500_SFRX);
cc2500_strobe(CC2500_SXOFF);
cc2500_strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SFTX);
CC2500_Strobe(CC2500_SFRX);
CC2500_Strobe(CC2500_SXOFF);
CC2500_Strobe(CC2500_SIDLE);
}
static void add_pkt_suffix() {
@ -104,7 +104,7 @@ static void send_data_packet() {
packet[1] = TX_ADDR; //Tx Addr?
packet[2] = 0x01; //???
for(int i = 0; i < 7; i++) {
uint32_t value = (uint32_t)Servo_data[i] * 0x280 / PPM_MAX + 0x280;
uint32_t value = map(limit_channel_100(i),servo_min_100,servo_max_100,0,1280);
if(value < 0) { value = 0; }
if(value > 0x500) { value = 0x500; }
packet[3+2*i] = value >> 8;
@ -112,11 +112,11 @@ static void send_data_packet() {
}
add_pkt_suffix();
//for(int i = 0; i < 20; i++) printf("%02x ", packet[i]); printf("\n");
cc2500_writeReg(CC2500_04_SYNC1, ((binding_idx >> 0) & 0xff));
cc2500_writeReg(CC2500_05_SYNC0, ((binding_idx >> 8) & 0xff));
cc2500_writeReg(CC2500_09_ADDR, TX_ADDR);
cc2500_writeReg(CC2500_0A_CHANNR, TX_CHANNEL);
cc2500_writeFifo(packet, 20);
CC2500_WriteReg(CC2500_04_SYNC1, ((binding_idx >> 0) & 0xff));
CC2500_WriteReg(CC2500_05_SYNC0, ((binding_idx >> 8) & 0xff));
CC2500_WriteReg(CC2500_09_ADDR, TX_ADDR);
CC2500_WriteReg(CC2500_0A_CHANNR, TX_CHANNEL);
CC2500_WriteData(packet, 20);
}
static void send_bind_packet() {
@ -135,16 +135,16 @@ static void send_bind_packet() {
uint8_t xore = 0;
for(int i = 3; i < 11; i++) { xore ^= packet[i]; }
packet[11] = xore;
cc2500_writeReg(CC2500_04_SYNC1, 0x7d);
cc2500_writeReg(CC2500_05_SYNC0, 0x7d);
cc2500_writeReg(CC2500_09_ADDR, 0x7d);
cc2500_writeReg(CC2500_0A_CHANNR, 0x7d);
cc2500_writeFifo(packet, 12);
CC2500_WriteReg(CC2500_04_SYNC1, 0x7d);
CC2500_WriteReg(CC2500_05_SYNC0, 0x7d);
CC2500_WriteReg(CC2500_09_ADDR, 0x7d);
CC2500_WriteReg(CC2500_0A_CHANNR, 0x7d);
CC2500_WriteData(packet, 12);
}
static uint16_t skyartec_cb() {
if (state & 0x01) {
cc2500_strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SIDLE);
if (state == SKYARTEC_LAST) { CC2500_SetPower(); state = SKYARTEC_PKT1; }
else { state++; }
return 3000;

View File

@ -1,538 +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/>.
*/
#if defined(DSM2_CYRF6936_INO)
#include "iface_cyrf6936.h"
#define RANDOM_CHANNELS 0 // disabled
//#define RANDOM_CHANNELS 1 // enabled
#define BIND_CHANNEL 0x0d //13 This can be any odd channel
#define NUM_WAIT_LOOPS (100 / 5) //each loop is ~5us. Do not wait more than 100us
//During binding we will send BIND_COUNT/2 packets
//One packet each 10msec
#define BIND_COUNT1 600
enum {
DSM2_BIND = 0,
DSM2_CHANSEL = BIND_COUNT1 + 0,
DSM2_CH1_WRITE_A = BIND_COUNT1 + 1,
DSM2_CH1_CHECK_A = BIND_COUNT1 + 2,
DSM2_CH2_WRITE_A = BIND_COUNT1 + 3,
DSM2_CH2_CHECK_A = BIND_COUNT1 + 4,
DSM2_CH2_READ_A = BIND_COUNT1 + 5,
DSM2_CH1_WRITE_B = BIND_COUNT1 + 6,
DSM2_CH1_CHECK_B = BIND_COUNT1 + 7,
DSM2_CH2_WRITE_B = BIND_COUNT1 + 8,
DSM2_CH2_CHECK_B = BIND_COUNT1 + 9,
DSM2_CH2_READ_B = BIND_COUNT1 + 10,
};
const uint8_t PROGMEM pncodes[5][9][8] = {
/* Note these are in order transmitted (LSB 1st) */
{ /* Row 0 */
/* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8},
/* Col 1 */ {0x88, 0x17, 0x13, 0x3B, 0x2D, 0xBF, 0x06, 0xD6},
/* Col 2 */ {0xF1, 0x94, 0x30, 0x21, 0xA1, 0x1C, 0x88, 0xA9},
/* Col 3 */ {0xD0, 0xD2, 0x8E, 0xBC, 0x82, 0x2F, 0xE3, 0xB4},
/* Col 4 */ {0x8C, 0xFA, 0x47, 0x9B, 0x83, 0xA5, 0x66, 0xD0},
/* Col 5 */ {0x07, 0xBD, 0x9F, 0x26, 0xC8, 0x31, 0x0F, 0xB8},
/* Col 6 */ {0xEF, 0x03, 0x95, 0x89, 0xB4, 0x71, 0x61, 0x9D},
/* Col 7 */ {0x40, 0xBA, 0x97, 0xD5, 0x86, 0x4F, 0xCC, 0xD1},
/* Col 8 */ {0xD7, 0xA1, 0x54, 0xB1, 0x5E, 0x89, 0xAE, 0x86}
},
{ /* Row 1 */
/* Col 0 */ {0x83, 0xF7, 0xA8, 0x2D, 0x7A, 0x44, 0x64, 0xD3},
/* Col 1 */ {0x3F, 0x2C, 0x4E, 0xAA, 0x71, 0x48, 0x7A, 0xC9},
/* Col 2 */ {0x17, 0xFF, 0x9E, 0x21, 0x36, 0x90, 0xC7, 0x82},
/* Col 3 */ {0xBC, 0x5D, 0x9A, 0x5B, 0xEE, 0x7F, 0x42, 0xEB},
/* Col 4 */ {0x24, 0xF5, 0xDD, 0xF8, 0x7A, 0x77, 0x74, 0xE7},
/* Col 5 */ {0x3D, 0x70, 0x7C, 0x94, 0xDC, 0x84, 0xAD, 0x95},
/* Col 6 */ {0x1E, 0x6A, 0xF0, 0x37, 0x52, 0x7B, 0x11, 0xD4},
/* Col 7 */ {0x62, 0xF5, 0x2B, 0xAA, 0xFC, 0x33, 0xBF, 0xAF},
/* Col 8 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97}
},
{ /* Row 2 */
/* Col 0 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97},
/* Col 1 */ {0x8E, 0x4A, 0xD0, 0xA9, 0xA7, 0xFF, 0x20, 0xCA},
/* Col 2 */ {0x4C, 0x97, 0x9D, 0xBF, 0xB8, 0x3D, 0xB5, 0xBE},
/* Col 3 */ {0x0C, 0x5D, 0x24, 0x30, 0x9F, 0xCA, 0x6D, 0xBD},
/* Col 4 */ {0x50, 0x14, 0x33, 0xDE, 0xF1, 0x78, 0x95, 0xAD},
/* Col 5 */ {0x0C, 0x3C, 0xFA, 0xF9, 0xF0, 0xF2, 0x10, 0xC9},
/* Col 6 */ {0xF4, 0xDA, 0x06, 0xDB, 0xBF, 0x4E, 0x6F, 0xB3},
/* Col 7 */ {0x9E, 0x08, 0xD1, 0xAE, 0x59, 0x5E, 0xE8, 0xF0},
/* Col 8 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E}
},
{ /* Row 3 */
/* Col 0 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E},
/* Col 1 */ {0x80, 0x69, 0x26, 0x80, 0x08, 0xF8, 0x49, 0xE7},
/* Col 2 */ {0x7D, 0x2D, 0x49, 0x54, 0xD0, 0x80, 0x40, 0xC1},
/* Col 3 */ {0xB6, 0xF2, 0xE6, 0x1B, 0x80, 0x5A, 0x36, 0xB4},
/* Col 4 */ {0x42, 0xAE, 0x9C, 0x1C, 0xDA, 0x67, 0x05, 0xF6},
/* Col 5 */ {0x9B, 0x75, 0xF7, 0xE0, 0x14, 0x8D, 0xB5, 0x80},
/* Col 6 */ {0xBF, 0x54, 0x98, 0xB9, 0xB7, 0x30, 0x5A, 0x88},
/* Col 7 */ {0x35, 0xD1, 0xFC, 0x97, 0x23, 0xD4, 0xC9, 0x88},
/* Col 8 */ {0x88, 0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40}
},
{ /* Row 4 */
/* Col 0 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93},
/* Col 1 */ {0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C},
/* Col 2 */ {0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA},
/* Col 3 */ {0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC},
/* Col 4 */ {0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84},
/* Col 5 */ {0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7},
/* Col 6 */ {0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0},
/* Col 7 */ {0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1},
/* Col 8 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8}
},
};
static void __attribute__((unused)) read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
{
for(uint8_t i=0;i<len;i++)
buf[i]=pgm_read_byte_near( &pncodes[row][col][i] );
}
//
uint8_t chidx;
uint8_t sop_col;
uint8_t data_col;
uint16_t cyrf_state;
uint8_t crcidx;
uint8_t binding;
static void __attribute__((unused)) build_bind_packet()
{
uint8_t i;
uint16_t sum = 384 - 0x10;//
packet[0] = crc >> 8;
packet[1] = crc & 0xff;
packet[2] = 0xff ^ cyrfmfg_id[2];
packet[3] = (0xff ^ cyrfmfg_id[3]) + RX_num;
packet[4] = packet[0];
packet[5] = packet[1];
packet[6] = packet[2];
packet[7] = packet[3];
for(i = 0; i < 8; i++)
sum += packet[i];
packet[8] = sum >> 8;
packet[9] = sum & 0xff;
packet[10] = 0x01; //???
packet[11] = option>3?option:option+4;
if(sub_protocol==DSMX) //DSMX type
packet[12] = 0xb2; // Telemetry off: packet[12] = num_channels < 8 && Model.proto_opts[PROTOOPTS_TELEMETRY] == TELEM_OFF ? 0xa2 : 0xb2;
else
packet[12] = option<8?0x01:0x02;
packet[13] = 0x00; //???
for(i = 8; i < 14; i++)
sum += packet[i];
packet[14] = sum >> 8;
packet[15] = sum & 0xff;
}
static uint8_t __attribute__((unused)) PROTOCOL_SticksMoved(uint8_t init)
{
#define STICK_MOVEMENT 15*(PPM_MAX-PPM_MIN)/100 // defines when the bind dialog should be interrupted (stick movement STICK_MOVEMENT %)
static uint16_t ele_start, ail_start;
uint16_t ele = Servo_data[ELEVATOR];//CHAN_ReadInput(MIXER_MapChannel(INP_ELEVATOR));
uint16_t ail = Servo_data[AILERON];//CHAN_ReadInput(MIXER_MapChannel(INP_AILERON));
if(init) {
ele_start = ele;
ail_start = ail;
return 0;
}
uint16_t ele_diff = ele_start - ele;//abs(ele_start - ele);
uint16_t ail_diff = ail_start - ail;//abs(ail_start - ail);
return ((ele_diff + ail_diff) > STICK_MOVEMENT);//
}
static void __attribute__((unused)) build_data_packet(uint8_t upper)//
{
uint8_t i;
uint8_t bits;
uint8_t ch_map[] = {3, 2, 1, 5, 0, 4, 6, 7, 8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //9 Channels - DM9 TX
switch(option>3?option:option+4) // Create channel map based on number of channels
{
case 12:
ch_map[11]=11; // 12 channels
case 11:
ch_map[10]=10; // 11 channels
case 10:
ch_map[9]=9; // 10 channels
break;
case 8:
memcpy(ch_map,"\x01\x05\x02\x03\x06\xFF\xFF\x04\x00\x07",10); // 8 channels - DX8 TX
break;
case 7:
memcpy(ch_map,"\x01\x05\x02\x04\x03\x06\x00",7); // 7 channels - DX6i TX
break;
case 6:
memcpy(ch_map,"\x01\x05\x02\x03\x00\x04\xFF",7); // 6 channels - HP6DSM TX
break;
case 4:
case 5:
memcpy(ch_map,"\x00\x01\x02\x03\xFF\xFF\xFF",7); // 4 channels - Guess
if(option&0x01)
ch_map[4]=4; // 5 channels - Guess
break;
}
//
if( binding && PROTOCOL_SticksMoved(0) )
binding = 0;
if (sub_protocol==DSMX)
{
packet[0] = cyrfmfg_id[2];
packet[1] = cyrfmfg_id[3] + RX_num;
bits=11;
}
else
{
packet[0] = (0xff ^ cyrfmfg_id[2]);
packet[1] = (0xff ^ cyrfmfg_id[3]) + RX_num;
bits=10;
}
//
uint16_t max = 1 << bits;//max=2048 for DSMX & 1024 for DSM2 less than 8 ch and 2048 otherwise
//uint16_t pct_100 = (uint32_t)max * 100 / 150;//682 1024*100/150
//
for (i = 0; i < 7; i++)
{
uint8_t idx = ch_map[upper * 7 + i];//1,5,2,3,0,4
uint16_t value;
if (idx == 0xff)
value = 0xffff;
else
{
if (binding)
{ // Failsafe position during binding
value=max/2; //all channels to middle
if(idx==0)
value=1; //except throttle
}
else
{
switch(idx)
{
case 0:
value=Servo_data[THROTTLE];//85.75-938.25=125%//171-853=100%
break;
case 1:
value=Servo_data[AILERON];
break;
case 2:
value=Servo_data[ELEVATOR];
break;
case 3:
value=Servo_data[RUDDER];
break;
case 4:
value=Servo_data[AUX1];
break;
case 5:
value=Servo_data[AUX2];
break;
case 6:
value=Servo_data[AUX3];
break;
case 7:
value=Servo_data[AUX4];
break;
}
value=map(value,PPM_MIN,PPM_MAX,0,max-1);
}
value |= (upper && i == 0 ? 0x8000 : 0) | (idx << bits);
}
packet[i*2+2] = (value >> 8) & 0xff;
packet[i*2+3] = (value >> 0) & 0xff;
}
}
static uint8_t __attribute__((unused)) get_pn_row(uint8_t channel)
{
return (sub_protocol == DSMX ? (channel - 2) % 5 : channel % 5);
}
const uint8_t init_vals[][2] = {
{CYRF_02_TX_CTRL, 0x00},
{CYRF_05_RX_CTRL, 0x00},
{CYRF_28_CLK_EN, 0x02},
{CYRF_32_AUTO_CAL_TIME, 0x3c},
{CYRF_35_AUTOCAL_OFFSET, 0x14},
{CYRF_06_RX_CFG, 0x4A},
{CYRF_1B_TX_OFFSET_LSB, 0x55},
{CYRF_1C_TX_OFFSET_MSB, 0x05},
{CYRF_0F_XACT_CFG, 0x24}, // Force Idle
{CYRF_03_TX_CFG, 0x38 | CYRF_BIND_POWER}, //Set 64chip, SDR mode
{CYRF_12_DATA64_THOLD, 0x0a},
{CYRF_0F_XACT_CFG, 0x04}, // Idle
{CYRF_39_ANALOG_CTRL, 0x01},
{CYRF_0F_XACT_CFG, 0x24}, //Force IDLE
{CYRF_29_RX_ABORT, 0x00}, //Clear RX abort
{CYRF_12_DATA64_THOLD, 0x0a}, //set pn correlation threshold
{CYRF_10_FRAMING_CFG, 0x4a}, //set sop len and threshold
{CYRF_29_RX_ABORT, 0x0f}, //Clear RX abort?
{CYRF_03_TX_CFG, 0x38 | CYRF_BIND_POWER}, //Set 64chip, SDR mode
{CYRF_10_FRAMING_CFG, 0x4a}, //set sop len and threshold
{CYRF_1F_TX_OVERRIDE, 0x04}, //disable tx CRC
{CYRF_1E_RX_OVERRIDE, 0x14}, //disable rx crc
{CYRF_14_EOP_CTRL, 0x02}, //set EOP sync == 2
{CYRF_01_TX_LENGTH, 0x10}, //16byte packet
};
static void __attribute__((unused)) cyrf_config()
{
for(uint8_t i = 0; i < sizeof(init_vals) / 2; i++)
CYRF_WriteRegister(init_vals[i][0], init_vals[i][1]);
CYRF_WritePreamble(0x333304);
CYRF_ConfigRFChannel(0x61);
}
static void __attribute__((unused)) initialize_bind_state()
{
uint8_t code[32];
CYRF_ConfigRFChannel(BIND_CHANNEL); //This seems to be random?
uint8_t pn_row = get_pn_row(BIND_CHANNEL);
//printf("Ch: %d Row: %d SOP: %d Data: %d\n", BIND_CHANNEL, pn_row, sop_col, data_col);
CYRF_ConfigCRCSeed(crc);
read_code(code,pn_row,sop_col,8);
CYRF_ConfigSOPCode(code);
read_code(code,pn_row,data_col,16);
read_code(code+16,0,8,8);
memcpy(code + 24, "\xc6\x94\x22\xfe\x48\xe6\x57\x4e", 8);
CYRF_ConfigDataCode(code, 32);
build_bind_packet();
}
const uint8_t data_vals[][2] = {
{CYRF_05_RX_CTRL, 0x83}, //Initialize for reading RSSI
{CYRF_29_RX_ABORT, 0x20},
{CYRF_0F_XACT_CFG, 0x24},
{CYRF_29_RX_ABORT, 0x00},
{CYRF_03_TX_CFG, 0x08 | CYRF_HIGH_POWER},
{CYRF_10_FRAMING_CFG, 0xea},
{CYRF_1F_TX_OVERRIDE, 0x00},
{CYRF_1E_RX_OVERRIDE, 0x00},
{CYRF_03_TX_CFG, 0x28 | CYRF_HIGH_POWER},
{CYRF_12_DATA64_THOLD, 0x3f},
{CYRF_10_FRAMING_CFG, 0xff},
{CYRF_0F_XACT_CFG, 0x24}, //Switch from reading RSSI to Writing
{CYRF_29_RX_ABORT, 0x00},
{CYRF_12_DATA64_THOLD, 0x0a},
{CYRF_10_FRAMING_CFG, 0xea},
};
static void __attribute__((unused)) cyrf_configdata()
{
for(uint8_t i = 0; i < sizeof(data_vals) / 2; i++)
CYRF_WriteRegister(data_vals[i][0], data_vals[i][1]);
}
static void __attribute__((unused)) set_sop_data_crc()
{
uint8_t code[16];
uint8_t pn_row = get_pn_row(hopping_frequency[chidx]);
//printf("Ch: %d Row: %d SOP: %d Data: %d\n", ch[chidx], pn_row, sop_col, data_col);
CYRF_ConfigRFChannel(hopping_frequency[chidx]);
CYRF_ConfigCRCSeed(crcidx ? ~crc : crc);
read_code(code,pn_row,sop_col,8);
CYRF_ConfigSOPCode(code);
read_code(code,pn_row,data_col,16);
CYRF_ConfigDataCode(code, 16);
if(sub_protocol == DSMX)
chidx = (chidx + 1) % 23;
else
chidx = (chidx + 1) % 2;
crcidx = !crcidx;
}
static void __attribute__((unused)) 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));
uint32_t id_tmp = id;
while(idx < 23)
{
uint8_t i;
uint8_t count_3_27 = 0, count_28_51 = 0, count_52_76 = 0;
id_tmp = id_tmp * 0x0019660D + 0x3C6EF35F; // Randomization
uint8_t next_ch = ((id_tmp >> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3
if (((next_ch ^ id) & 0x01 )== 0)
continue;
for (i = 0; i < idx; i++)
{
if(hopping_frequency[i] == next_ch)
break;
if(hopping_frequency[i] <= 27)
count_3_27++;
else
if (hopping_frequency[i] <= 51)
count_28_51++;
else
count_52_76++;
}
if (i != idx)
continue;
if ((next_ch < 28 && count_3_27 < 8)
||(next_ch >= 28 && next_ch < 52 && count_28_51 < 7)
||(next_ch >= 52 && count_52_76 < 8))
hopping_frequency[idx++] = next_ch;
}
}
uint16_t ReadDsm2()
{
#define CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
#define WRITE_DELAY 1650 // 1550 original, Time after write to verify write complete
#define READ_DELAY 400 // Time before write to check read state, and switch channels
uint8_t i = 0;
switch(cyrf_state)
{
default:
//Binding
cyrf_state++;
if(cyrf_state & 1)
{
//Send packet on even states
//Note state has already incremented,
// so this is actually 'even' state
CYRF_WriteDataPacket(packet);
return 8500;
}
else
{
//Check status on odd states
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS);
return 1500;
}
case DSM2_CHANSEL:
BIND_DONE;
//Select channels and configure for writing data
//CYRF_FindBestChannels(ch, 2, 10, 1, 79);
cyrf_configdata();
CYRF_SetTxRxMode(TX_EN);
chidx = 0;
crcidx = 0;
cyrf_state = DSM2_CH1_WRITE_A; // in fact cyrf_state++
set_sop_data_crc();
return 10000;
case DSM2_CH1_WRITE_A:
case DSM2_CH1_WRITE_B:
build_data_packet(cyrf_state == DSM2_CH1_WRITE_B);//compare state and DSM2_CH1_WRITE_B return 0 or 1
case DSM2_CH2_WRITE_A:
case DSM2_CH2_WRITE_B:
CYRF_WriteDataPacket(packet);
cyrf_state++; // change from WRITE to CHECK mode
return WRITE_DELAY;
case DSM2_CH1_CHECK_A:
case DSM2_CH1_CHECK_B:
while (! (CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02))
if(++i > NUM_WAIT_LOOPS)
break;
set_sop_data_crc();
cyrf_state++; // change from CH1_CHECK to CH2_WRITE
return CH1_CH2_DELAY - WRITE_DELAY;
case DSM2_CH2_CHECK_A:
case DSM2_CH2_CHECK_B:
while (! (CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02))
if(++i > NUM_WAIT_LOOPS)
break;
if (cyrf_state == DSM2_CH2_CHECK_A)
CYRF_SetPower(0x28); //Keep transmit power in sync
// No telemetry...
set_sop_data_crc();
if (cyrf_state == DSM2_CH2_CHECK_A)
{
if(option < 8)
{
cyrf_state = DSM2_CH1_WRITE_A; // change from CH2_CHECK_A to CH1_WRITE_A (ie no upper)
if(option>3)
return 11000 - CH1_CH2_DELAY - WRITE_DELAY ; // force 11ms if option>3 ie 4,5,6,7 channels @11ms
else
return 22000 - CH1_CH2_DELAY - WRITE_DELAY ; // normal 22ms mode if option<=3 ie 4,5,6,7 channels @22ms
}
else
cyrf_state = DSM2_CH1_WRITE_B; // change from CH2_CHECK_A to CH1_WRITE_A (to transmit upper)
}
else
cyrf_state = DSM2_CH1_WRITE_A; // change from CH2_CHECK_B to CH1_WRITE_A (upper already transmitted so transmit lower)
return 11000 - CH1_CH2_DELAY - WRITE_DELAY;
}
return 0;
}
uint16_t initDsm2()
{
CYRF_Reset();
CYRF_GetMfgData(cyrfmfg_id);//
cyrf_config();
if (sub_protocol ==DSMX)
calc_dsmx_channel();
else
{
#if RANDOM_CHANNELS == 1
uint8_t tmpch[10];
CYRF_FindBestChannels(tmpch, 10, 5, 3, 75);
//
randomSeed((uint32_t)analogRead(A6)<<10|analogRead(A7));//seed
uint8_t idx = random(0xfefefefe) % 10;
hopping_frequency[0] = tmpch[idx];
while(1)
{
idx = random(0xfefefefe) % 10;
if (tmpch[idx] != hopping_frequency[0])
break;
}
hopping_frequency[1] = tmpch[idx];
#else
hopping_frequency[0] = (cyrfmfg_id[0] + cyrfmfg_id[2] + cyrfmfg_id[4]) % 39 + 1;
hopping_frequency[1] = (cyrfmfg_id[1] + cyrfmfg_id[3] + cyrfmfg_id[5]) % 40 + 40;
#endif
}
///}
crc = ~((cyrfmfg_id[0] << 8) + cyrfmfg_id[1]); //The crc for channel 'a' is NOT(mfgid[1] << 8 + mfgid[0])
crcidx = 0;//The crc for channel 'b' is (mfgid[1] << 8 + mfgid[0])
//
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;//Ok
data_col = 7 - sop_col;//ok
CYRF_SetTxRxMode(TX_EN);
//
if(IS_AUTOBIND_FLAG_on)
{
cyrf_state = DSM2_BIND;
PROTOCOL_SticksMoved(1); //Initialize Stick position
initialize_bind_state();
binding = 1;
}
else
{
cyrf_state = DSM2_CHANSEL;//
binding = 0;
}
return 10000;
}
#endif

View File

@ -43,31 +43,7 @@ enum {
DEVO_BOUND_10,
};
<<<<<<< HEAD
const uint8_t sopcodes[][8] = {
/* Note these are in order transmitted (LSB 1st) */
/* 0 */ {0x3C,0x37,0xCC,0x91,0xE2,0xF8,0xCC,0x91}, //0x91CCF8E291CC373C
/* 1 */ {0x9B,0xC5,0xA1,0x0F,0xAD,0x39,0xA2,0x0F}, //0x0FA239AD0FA1C59B
/* 2 */ {0xEF,0x64,0xB0,0x2A,0xD2,0x8F,0xB1,0x2A}, //0x2AB18FD22AB064EF
/* 3 */ {0x66,0xCD,0x7C,0x50,0xDD,0x26,0x7C,0x50}, //0x507C26DD507CCD66
/* 4 */ {0x5C,0xE1,0xF6,0x44,0xAD,0x16,0xF6,0x44}, //0x44F616AD44F6E15C
/* 5 */ {0x5A,0xCC,0xAE,0x46,0xB6,0x31,0xAE,0x46}, //0x46AE31B646AECC5A
/* 6 */ {0xA1,0x78,0xDC,0x3C,0x9E,0x82,0xDC,0x3C}, //0x3CDC829E3CDC78A1
/* 7 */ {0xB9,0x8E,0x19,0x74,0x6F,0x65,0x18,0x74}, //0x7418656F74198EB9
/* 8 */ {0xDF,0xB1,0xC0,0x49,0x62,0xDF,0xC1,0x49}, //0x49C1DF6249C0B1DF
/* 9 */ {0x97,0xE5,0x14,0x72,0x7F,0x1A,0x14,0x72}, //0x72141A7F7214E597
};
uint8_t txState;
uint8_t pkt_num;
uint8_t ch_idx;
uint8_t use_fixed_id;
uint8_t failsafe_pkt;
static void __attribute__((unused)) scramble_pkt()
=======
static void __attribute__((unused)) DEVO_scramble_pkt()
>>>>>>> refs/remotes/pascallanger/master
{
#ifdef NO_SCRAMBLE
return;
@ -77,11 +53,7 @@ static void __attribute__((unused)) DEVO_scramble_pkt()
#endif
}
<<<<<<< HEAD
static void __attribute__((unused)) add_pkt_suffix()
=======
static void __attribute__((unused)) DEVO_add_pkt_suffix()
>>>>>>> refs/remotes/pascallanger/master
{
uint8_t bind_state;
#ifdef ENABLE_PPM
@ -119,11 +91,7 @@ static void __attribute__((unused)) DEVO_add_pkt_suffix()
packet[15] = (MProtocol_id >> 16) & 0xff;
}
<<<<<<< HEAD
static void __attribute__((unused)) build_beacon_pkt(uint8_t upper)
=======
static void __attribute__((unused)) DEVO_build_beacon_pkt(uint8_t upper)
>>>>>>> refs/remotes/pascallanger/master
{
packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x07;
uint8_t max = 8;
@ -138,11 +106,7 @@ static void __attribute__((unused)) DEVO_build_beacon_pkt(uint8_t upper)
DEVO_add_pkt_suffix();
}
<<<<<<< HEAD
static void __attribute__((unused)) build_bind_pkt()
=======
static void __attribute__((unused)) DEVO_build_bind_pkt()
>>>>>>> refs/remotes/pascallanger/master
{
packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x0a;
packet[1] = bind_counter & 0xff;
@ -162,11 +126,7 @@ static void __attribute__((unused)) DEVO_build_bind_pkt()
packet[15] ^= cyrfmfg_id[2];
}
<<<<<<< HEAD
static void __attribute__((unused)) build_data_pkt()
=======
static void __attribute__((unused)) DEVO_build_data_pkt()
>>>>>>> refs/remotes/pascallanger/master
{
static uint8_t ch_idx=0;
@ -190,11 +150,7 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
DEVO_add_pkt_suffix();
}
<<<<<<< HEAD
static void __attribute__((unused)) cyrf_set_bound_sop_code()
=======
static void __attribute__((unused)) DEVO_cyrf_set_bound_sop_code()
>>>>>>> refs/remotes/pascallanger/master
{
/* crc == 0 isn't allowed, so use 1 if the math results in 0 */
uint8_t crc = (cyrfmfg_id[0] + (cyrfmfg_id[1] >> 6) + cyrfmfg_id[2]);
@ -207,9 +163,6 @@ static void __attribute__((unused)) DEVO_cyrf_set_bound_sop_code()
CYRF_SetPower(0x08);
}
<<<<<<< HEAD
static void __attribute__((unused)) cyrf_init()
=======
const uint8_t PROGMEM DEVO_init_vals[][2] = {
{ CYRF_1D_MODE_OVERRIDE, 0x38 },
{ CYRF_03_TX_CFG, 0x08 },
@ -233,18 +186,13 @@ const uint8_t PROGMEM DEVO_init_vals[][2] = {
};
static void __attribute__((unused)) DEVO_cyrf_init()
>>>>>>> refs/remotes/pascallanger/master
{
/* Initialise CYRF chip */
for(uint8_t i = 0; i < sizeof(DEVO_init_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte( &DEVO_init_vals[i][0]), pgm_read_byte( &DEVO_init_vals[i][1]) );
}
<<<<<<< HEAD
static void __attribute__((unused)) set_radio_channels()
=======
static void __attribute__((unused)) DEVO_set_radio_channels()
>>>>>>> refs/remotes/pascallanger/master
{
CYRF_FindBestChannels(hopping_frequency, 3, 4, 4, 80);
hopping_frequency[3] = hopping_frequency[0];
@ -337,35 +285,6 @@ uint16_t devo_callback()
return 1200;
}
<<<<<<< HEAD
/*static void __attribute__((unused)) devo_bind()
{
fixed_id = Model_fixed_id;
bind_counter = DEVO_BIND_COUNT;
use_fixed_id = 1;
//PROTOCOL_SetBindState(0x1388 * 2400 / 1000); //msecs 12000ms
}
static void __attribute__((unused)) generate_fixed_id_bind(){
if(BIND_0){
//randomSeed((uint32_t)analogRead(A6)<<10|analogRead(A7));//seed
uint8_t txid[4];
//Model_fixed_id = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16);
Model_fixed_id=0x332211;
txid[0]= (id &0xFF);
txid[1] = ((id >> 8) & 0xFF);
txid[2] = ((id >> 16) & 0xFF);
//txid[3] = ((id >> 24) & 0xFF);
eeprom_write_block((const void*)txid,(void*)40,3);
devo_bind();
}
}
*/
=======
>>>>>>> refs/remotes/pascallanger/master
uint16_t DevoInit()
{
DEVO_cyrf_init();

View File

@ -15,26 +15,17 @@
// Last sync with hexfet new_protocols/fy326_nrf24l01.c dated 2015-07-29
#if defined(FY326_NRF24L01_INO)
<<<<<<< HEAD
=======
>>>>>>> refs/remotes/pascallanger/master
#include "iface_nrf24l01.h"
#define FY326_INITIAL_WAIT 500
#define FY326_PACKET_PERIOD 1500
#define FY326_PACKET_CHKTIME 300
#define FY326_PACKET_SIZE 15
<<<<<<< HEAD
#define FY326_BIND_COUNT 16
=======
#define FY326_BIND_COUNT 16
>>>>>>> refs/remotes/pascallanger/master
#define FY326_RF_BIND_CHANNEL 0x17
#define FY326_NUM_RF_CHANNELS 5
enum {
<<<<<<< HEAD
FY326_INIT1 = 0,
FY326_BIND1,
FY326_BIND2,
@ -42,11 +33,6 @@ enum {
FY319_INIT1,
FY319_BIND1,
FY319_BIND2,
=======
FY326_BIND1=0,
FY326_BIND2,
FY326_DATA
>>>>>>> refs/remotes/pascallanger/master
};
#define rxid channel
@ -56,11 +42,7 @@ static void __attribute__((unused)) FY326_send_packet(uint8_t bind)
{
packet[0] = rx_tx_addr[3];
if(bind)
<<<<<<< HEAD
packet[1] = 0x55;
=======
packet[1] = 0x55;
>>>>>>> refs/remotes/pascallanger/master
else
packet[1] = GET_FLAG(Servo_AUX3, 0x80) // Headless
| GET_FLAG(Servo_AUX2, 0x40) // RTH
@ -71,11 +53,10 @@ static void __attribute__((unused)) FY326_send_packet(uint8_t bind)
packet[3] = convert_channel_8b_scale(ELEVATOR, 0, 200); // elevator
packet[4] = 200 - convert_channel_8b_scale(RUDDER, 0, 200); // rudder
packet[5] = convert_channel_8b_scale(THROTTLE, 0, 200); // throttle
<<<<<<< HEAD
if(sub_protocol == FY319) {
packet[6] = 255 - scale_channel(AILERON, 0, 255);
packet[7] = scale_channel(ELEVATOR, 0, 255);
packet[8] = 255 - scale_channel(RUDDER, 0, 255);
packet[6] = 255 - convert_channel_8b_scale(AILERON, 0, 255);
packet[7] = convert_channel_8b_scale(ELEVATOR, 0, 255);
packet[8] = 255 - convert_channel_8b_scale(RUDDER, 0, 255);
}
else {
packet[6] = rx_tx_addr[0];
@ -87,16 +68,6 @@ static void __attribute__((unused)) FY326_send_packet(uint8_t bind)
packet[11] = CHAN_TO_TRIM(packet[4]); // rudder_trim;
packet[12] = 0; // throttle_trim;
packet[13] = rxid;
=======
packet[6] = rx_tx_addr[0];
packet[7] = rx_tx_addr[1];
packet[8] = rx_tx_addr[2];
packet[9] = CHAN_TO_TRIM(packet[2]); // aileron_trim;
packet[10] = CHAN_TO_TRIM(packet[3]); // elevator_trim;
packet[11] = CHAN_TO_TRIM(packet[4]); // rudder_trim;
packet[12] = 0; // throttle_trim;
packet[13] = rxid;
>>>>>>> refs/remotes/pascallanger/master
packet[14] = rx_tx_addr[4];
if (bind)
@ -105,20 +76,12 @@ static void __attribute__((unused)) FY326_send_packet(uint8_t bind)
{
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no %= FY326_NUM_RF_CHANNELS;
<<<<<<< HEAD
}
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
=======
}
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_WritePayload(packet, FY326_PACKET_SIZE);
@ -127,18 +90,12 @@ static void __attribute__((unused)) FY326_send_packet(uint8_t bind)
static void __attribute__((unused)) FY326_init()
{
<<<<<<< HEAD
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
if(sub_protocol == FY319)
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // Five-byte rx/tx address
else
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // Three-byte rx/tx address
=======
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // Three-byte rx/tx address
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x15\x59\x23\xc6\x29", 5);
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x15\x59\x23\xc6\x29", 5);
NRF24L01_FlushTx();
@ -150,20 +107,14 @@ static void __attribute__((unused)) FY326_init()
NRF24L01_WriteReg(NRF24L01_05_RF_CH, FY326_RF_BIND_CHANNEL);
NRF24L01_SetBitrate(NRF24L01_BR_250K);
NRF24L01_SetPower();
<<<<<<< HEAD
NRF24L01_Activate(0x73);
=======
NRF24L01_Activate(0x73);
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f);
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
NRF24L01_Activate(0x73);
}
<<<<<<< HEAD
uint16_t fy326_callback()
uint16_t FY326_callback()
{
uint8_t i;
switch (phase) {
@ -171,19 +122,19 @@ uint16_t fy326_callback()
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_BIND_CHANNEL);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, FY326_RF_BIND_CHANNEL);
phase = FY319_BIND1;
BIND_IN_PROGRESS;
return FY326_CHKTIME;
return FY326_PACKET_CHKTIME;
break;
case FY319_BIND1:
if(NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR)) {
NRF24L01_ReadPayload(packet, FY326_SIZE);
if(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) {
NRF24L01_ReadPayload(packet, FY326_PACKET_SIZE);
rxid = packet[13];
packet[0] = txid[3];
packet[0] = rx_tx_addr[3];
packet[1] = 0x80;
packet[14]= txid[4];
packet[14]= rx_tx_addr[4];
bind_counter = FY326_BIND_COUNT;
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
@ -191,16 +142,16 @@ uint16_t fy326_callback()
NRF24L01_FlushTx();
bind_counter = 255;
for(i=2; i<6; i++)
packet[i] = rf_chans[0];
packet[i] = hopping_frequency[0];
phase = FY319_BIND2;
}
return FY326_CHKTIME;
return FY326_PACKET_CHKTIME;
break;
case FY319_BIND2:
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet, FY326_SIZE);
NRF24L01_WritePayload(packet, FY326_PACKET_SIZE);
if(bind_counter == 250)
packet[1] = 0x40;
if(--bind_counter == 0) {
@ -212,12 +163,12 @@ uint16_t fy326_callback()
case FY326_INIT1:
bind_counter = FY326_BIND_COUNT;
phase = FY326_BIND2;
send_packet(1);
return FY326_CHKTIME;
FY326_send_packet(1);
return FY326_PACKET_CHKTIME;
break;
case FY326_BIND1:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR))
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
NRF24L01_ReadPayload(packet, FY326_PACKET_SIZE);
rxid = packet[13];
@ -240,7 +191,7 @@ uint16_t fy326_callback()
break;
case FY326_BIND2:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_TX_DS))
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS))
{ // TX data sent -> switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
@ -255,55 +206,11 @@ uint16_t fy326_callback()
FY326_send_packet(0);
break;
}
=======
uint16_t FY326_callback()
{
switch (phase)
{
case FY326_BIND1:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
NRF24L01_ReadPayload(packet, FY326_PACKET_SIZE);
rxid = packet[13];
rx_tx_addr[0] = 0xAA;
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
BIND_DONE;
phase = FY326_DATA;
}
else
if (bind_counter-- == 0)
{
bind_counter = FY326_BIND_COUNT;
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
FY326_send_packet(1);
phase = FY326_BIND2;
return FY326_PACKET_CHKTIME;
}
break;
case FY326_BIND2:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS))
{ // TX data sent -> switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
phase = FY326_BIND1;
}
else
return FY326_PACKET_CHKTIME;
break;
case FY326_DATA:
FY326_send_packet(0);
break;
}
>>>>>>> refs/remotes/pascallanger/master
return FY326_PACKET_PERIOD;
}
static void __attribute__((unused)) FY326_initialize_txid()
{
<<<<<<< HEAD
if(sub_protocol == FY319) {
hopping_frequency[0] = (rx_tx_addr[0]&0x0f) & ~0x80;
hopping_frequency[1] = (rx_tx_addr[0] >> 4) & ~0x80;
@ -317,34 +224,19 @@ static void __attribute__((unused)) FY326_initialize_txid()
hopping_frequency[3] = 0x30 + (rx_tx_addr[1] >> 4);
hopping_frequency[4] = 0x40 + (rx_tx_addr[2] >> 4);
}
=======
hopping_frequency[0] = (rx_tx_addr[0]&0x0f);
hopping_frequency[1] = 0x10 + (rx_tx_addr[0] >> 4);
hopping_frequency[2] = 0x20 + (rx_tx_addr[1]&0x0f);
hopping_frequency[3] = 0x30 + (rx_tx_addr[1] >> 4);
hopping_frequency[4] = 0x40 + (rx_tx_addr[2] >> 4);
>>>>>>> refs/remotes/pascallanger/master
}
uint16_t initFY326(void)
{
BIND_IN_PROGRESS; // autobind protocol
<<<<<<< HEAD
rxid = 0xaa;
rxid = 0xAA;
bind_counter = 0;
FY326_initialize_txid();
fy326_init();
FY326_init();
if(sub_protocol == FY319)
phase = FY319_INIT1;
else
phase = FY326_INIT1;
=======
rxid = 0xAA;
bind_counter = 0;
FY326_initialize_txid();
FY326_init();
phase=FY326_BIND1;
>>>>>>> refs/remotes/pascallanger/master
return FY326_INITIAL_WAIT;
}

View File

@ -21,34 +21,6 @@
//FlySky constants & variables
#define FLYSKY_BIND_COUNT 2500
<<<<<<< HEAD
const uint8_t PROGMEM tx_channels[] = {
0x0a, 0x5a, 0x14, 0x64, 0x1e, 0x6e, 0x28, 0x78, 0x32, 0x82, 0x3c, 0x8c, 0x46, 0x96, 0x50, 0xa0,
0xa0, 0x50, 0x96, 0x46, 0x8c, 0x3c, 0x82, 0x32, 0x78, 0x28, 0x6e, 0x1e, 0x64, 0x14, 0x5a, 0x0a,
0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x46, 0x96, 0x1e, 0x6e, 0x3c, 0x8c, 0x28, 0x78, 0x32, 0x82,
0x82, 0x32, 0x78, 0x28, 0x8c, 0x3c, 0x6e, 0x1e, 0x96, 0x46, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a,
0x28, 0x78, 0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96,
0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a, 0x78, 0x28,
0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96, 0x14, 0x64,
0x64, 0x14, 0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50,
0x50, 0xa0, 0x46, 0x96, 0x3c, 0x8c, 0x28, 0x78, 0x0a, 0x5a, 0x32, 0x82, 0x1e, 0x6e, 0x14, 0x64,
0x64, 0x14, 0x6e, 0x1e, 0x82, 0x32, 0x5a, 0x0a, 0x78, 0x28, 0x8c, 0x3c, 0x96, 0x46, 0xa0, 0x50,
0x46, 0x96, 0x3c, 0x8c, 0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64,
0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50, 0x8c, 0x3c, 0x96, 0x46,
0x46, 0x96, 0x0a, 0x5a, 0x3c, 0x8c, 0x14, 0x64, 0x50, 0xa0, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82,
0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0xa0, 0x50, 0x64, 0x14, 0x8c, 0x3c, 0x5a, 0x0a, 0x96, 0x46,
0x46, 0x96, 0x0a, 0x5a, 0x50, 0xa0, 0x3c, 0x8c, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64,
0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0x8c, 0x3c, 0xa0, 0x50, 0x5a, 0x0a, 0x96, 0x46
};
enum {
// flags going to byte 10
FLAG_V9X9_VIDEO = 0x40,
FLAG_V9X9_CAMERA= 0x80,
// flags going to byte 12
FLAG_V9X9_FLIP = 0x10,
FLAG_V9X9_LED = 0x20,
=======
enum {
// flags going to byte 10
FLAG_V9X9_VIDEO = 0x40,
@ -56,27 +28,26 @@ enum {
// flags going to byte 12
FLAG_V9X9_FLIP = 0x10,
FLAG_V9X9_LED = 0x20,
>>>>>>> refs/remotes/pascallanger/master
};
enum {
// flags going to byte 13
FLAG_V6X6_HLESS1= 0x80,
// flags going to byte 14
FLAG_V6X6_VIDEO = 0x01,
FLAG_V6X6_YCAL = 0x02,
FLAG_V6X6_XCAL = 0x04,
FLAG_V6X6_RTH = 0x08,
FLAG_V6X6_CAMERA= 0x10,
FLAG_V6X6_HLESS2= 0x20,
FLAG_V6X6_LED = 0x40,
FLAG_V6X6_FLIP = 0x80,
// flags going to byte 13
FLAG_V6X6_HLESS1= 0x80,
// flags going to byte 14
FLAG_V6X6_VIDEO = 0x01,
FLAG_V6X6_YCAL = 0x02,
FLAG_V6X6_XCAL = 0x04,
FLAG_V6X6_RTH = 0x08,
FLAG_V6X6_CAMERA= 0x10,
FLAG_V6X6_HLESS2= 0x20,
FLAG_V6X6_LED = 0x40,
FLAG_V6X6_FLIP = 0x80,
};
enum {
// flags going to byte 14
FLAG_V912_TOPBTN= 0x40,
FLAG_V912_BTMBTN= 0x80,
// flags going to byte 14
FLAG_V912_TOPBTN= 0x40,
FLAG_V912_BTMBTN= 0x80,
};
const uint8_t PROGMEM V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, // sometime first byte is 0x15 ?
@ -84,79 +55,6 @@ const uint8_t PROGMEM V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, //
static void __attribute__((unused)) flysky_apply_extension_flags()
{
<<<<<<< HEAD
const uint8_t V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, // sometime first byte is 0x15 ?
0x49, 0x49, 0x49, 0x49, 0x49, };
static uint8_t seq_counter;
switch(sub_protocol)
{
case V9X9:
if(Servo_AUX1)
packet[12] |= FLAG_V9X9_FLIP;
if(Servo_AUX2)
packet[12] |= FLAG_V9X9_LED;
if(Servo_AUX3)
packet[10] |= FLAG_V9X9_CAMERA;
if(Servo_AUX4)
packet[10] |= FLAG_V9X9_VIDEO;
break;
case V6X6:
packet[13] = 0x03; // 3 = 100% rate (0=40%, 1=60%, 2=80%)
packet[14] = 0x00;
if(Servo_AUX1)
packet[14] |= FLAG_V6X6_FLIP;
if(Servo_AUX2)
packet[14] |= FLAG_V6X6_LED;
if(Servo_AUX3)
packet[14] |= FLAG_V6X6_CAMERA;
if(Servo_AUX4)
packet[14] |= FLAG_V6X6_VIDEO;
if(Servo_AUX5)
{
packet[13] |= FLAG_V6X6_HLESS1;
packet[14] |= FLAG_V6X6_HLESS2;
}
if(Servo_AUX6) //use option to manipulate these bytes
packet[14] |= FLAG_V6X6_RTH;
if(Servo_AUX7)
packet[14] |= FLAG_V6X6_XCAL;
if(Servo_AUX8)
packet[14] |= FLAG_V6X6_YCAL;
packet[15] = 0x10; // unknown
packet[16] = 0x10; // unknown
packet[17] = 0xAA; // unknown
packet[18] = 0xAA; // unknown
packet[19] = 0x60; // unknown, changes at irregular interval in stock TX
packet[20] = 0x02; // unknown
break;
case V912:
seq_counter++;
if( seq_counter > 9)
seq_counter = 0;
packet[12] |= 0x20; // bit 6 is always set ?
packet[13] = 0x00; // unknown
packet[14] = 0x00;
if(Servo_AUX1)
packet[14] = FLAG_V912_BTMBTN;
if(Servo_AUX2)
packet[14] |= FLAG_V912_TOPBTN;
packet[15] = 0x27; // [15] and [16] apparently hold an analog channel with a value lower than 1000
packet[16] = 0x03; // maybe it's there for a pitch channel for a CP copter ?
packet[17] = V912_X17_SEQ[seq_counter]; // not sure what [17] & [18] are for
if(seq_counter == 0) // V912 Rx does not even read those bytes... [17-20]
packet[18] = 0x02;
else
packet[18] = 0x00;
packet[19] = 0x00; // unknown
packet[20] = 0x00; // unknown
break;
default:
break;
}
=======
static uint8_t seq_counter;
switch(sub_protocol)
{
@ -226,78 +124,39 @@ static void __attribute__((unused)) flysky_apply_extension_flags()
default:
break;
}
>>>>>>> refs/remotes/pascallanger/master
}
static void __attribute__((unused)) flysky_build_packet(uint8_t init)
{
uint8_t i;
//servodata timing range for flysky.
////-100% =~ 0x03e8//=1000us(min)
//+100% =~ 0x07ca//=1994us(max)
//Center = 0x5d9//=1497us(center)
//channel order AIL;ELE;THR;RUD;AUX1;AUX2;AUX3;AUX4
//servodata timing range for flysky.
////-100% =~ 0x03e8//=1000us(min)
//+100% =~ 0x07ca//=1994us(max)
//Center = 0x5d9//=1497us(center)
//channel order AIL;ELE;THR;RUD;AUX1;AUX2;AUX3;AUX4
packet[0] = init ? 0xaa : 0x55;
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = rx_tx_addr[1];
packet[4] = rx_tx_addr[0];
<<<<<<< HEAD
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4};
for(i = 0; i < 8; i++)
{
packet[5+2*i]=lowByte(Servo_data[ch[i]]); //low byte of servo timing(1000-2000us)
packet[6+2*i]=highByte(Servo_data[ch[i]]); //high byte of servo timing(1000-2000us)
}
=======
for(i = 0; i < 8; i++)
{
packet[5 + i*2]=Servo_data[CH_AETR[i]]&0xFF; //low byte of servo timing(1000-2000us)
packet[6 + i*2]=(Servo_data[CH_AETR[i]]>>8)&0xFF; //high byte of servo timing(1000-2000us)
}
>>>>>>> refs/remotes/pascallanger/master
flysky_apply_extension_flags();
}
uint16_t ReadFlySky()
{
if (bind_counter)
{
{
flysky_build_packet(1);
A7105_WriteData(21, 1);
bind_counter--;
if (! bind_counter)
BIND_DONE;
}
<<<<<<< HEAD
else
{
flysky_build_packet(0);
A7105_WriteData(21, pgm_read_byte_near(&tx_channels[chanrow*16+chancol])-chanoffset);
chancol = (chancol + 1) % 16;
if (! chancol) //Keep transmit power updated
A7105_SetPower();
}
return 1460;
}
uint16_t initFlySky() {
//A7105_Reset();
A7105_Init(INIT_FLYSKY); //flysky_init();
if (rx_tx_addr[3] > 0x90) // limit offset to 9 as higher values don't work with some RX (ie V912)
rx_tx_addr[3] = rx_tx_addr[3] - 0x70;
chanrow=rx_tx_addr[3] % 16;
chancol=0;
chanoffset=rx_tx_addr[3] / 16;
if(IS_AUTOBIND_FLAG_on)
bind_counter = FLYSKY_BIND_COUNT;
else
bind_counter = 0;
return 2400;
=======
else
{
flysky_build_packet(0);
@ -352,7 +211,5 @@ uint16_t initFlySky()
else
bind_counter = 0;
return 2400;
>>>>>>> refs/remotes/pascallanger/master
}
#endif

View File

@ -0,0 +1,317 @@
// adaptation de https://github.com/goebish/deviation/blob/c5dd9fcc1441fc05fe9effa4c378886aeb3938d4/src/protocol/flysky_afhds2a_a7105.c
#ifdef AFHDS2A_A7105_INO
#define EEPROMadress 0 // rx ID 32bit
#define SERVO_HZ 0 //Frequency's servo 0=50 1=400 2=5
#define TXPACKET_SIZE 38
#define RXPACKET_SIZE 37
#define NUMFREQ 16
#define TXID_SIZE 4
#define RXID_SIZE 4
static uint8_t rxid[RXID_SIZE];
static uint8_t packet_type;
static uint8_t bind_reply;
enum{
PACKET_STICKS,
PACKET_SETTINGS,
PACKET_FAILSAFE,
};
enum{
BIND1,
BIND2,
BIND3,
BIND4,
DATA1,
};
enum {
PWM_IBUS = 0,
PPM_IBUS,
PWM_SBUS,
PPM_SBUS
};
static void build_packet(uint8_t type) {
switch(type) {
case PACKET_STICKS:
packet[0] = 0x58;
memcpy( &packet[1], rx_tx_addr, 4);
memcpy( &packet[5], rxid, 4);
for(uint8_t ch=0; ch<14; ch++) {
packet[9 + ch*2] = Servo_data[CH_AETR[ch]]&0xFF;
packet[10 + ch*2] = (Servo_data[CH_AETR[ch]]>>8)&0xFF;
}
packet[37] = 0x00;
break;
case PACKET_SETTINGS:
packet[0] = 0xaa;
memcpy( &packet[1], rx_tx_addr, 4);
memcpy( &packet[5], rxid, 4);
packet[9] = 0xfd;
packet[10]= 0xff;
packet[11]= SERVO_HZ & 0xff;
packet[12]= (SERVO_HZ >> 8) & 0xff;
if(option == PPM_IBUS || option == PPM_SBUS)
packet[13] = 0x01; // PPM output enabled
else
packet[13] = 0x00;
packet[14]= 0x00;
for(uint8_t i=15; i<37; i++)
packet[i] = 0xff;
packet[18] = 0x05; // ?
packet[19] = 0xdc; // ?
packet[20] = 0x05; // ?
if(option == PWM_SBUS || option == PPM_SBUS)
packet[21] = 0xdd; // SBUS output enabled
else
packet[21] = 0xde;
packet[37] = 0x00;
break;
case PACKET_FAILSAFE:
packet[0] = 0x56;
memcpy( &packet[1], rx_tx_addr, 4);
memcpy( &packet[5], rxid, 4);
for(uint8_t ch=0; ch<14; ch++) {
if(ch==0) {
// if(ch < Model.num_channels && (Model.limits[ch].flags & CH_FAILSAFE_EN)) {
uint32_t value = ((uint32_t)Servo_data[AUX11] + 100) * 5 + 1000;
packet[9 + ch*2] = value & 0xff;
packet[10+ ch*2] = (value >> 8) & 0xff;
}
else {
packet[9 + ch*2] = 0xff;
packet[10+ ch*2] = 0xff;
}
}
packet[37] = 0x00;
break;
}
}
#if defined(TELEMETRY)
// telemetry sensors ID
enum{
SENSOR_RX_VOLTAGE = 0x00,
SENSOR_RX_ERR_RATE = 0xfe,
SENSOR_RX_RSSI = 0xfc,
SENSOR_RX_NOISE = 0xfb,
SENSOR_RX_SNR = 0xfa,
};
static void update_telemetry() {
// AA | TXID | RXID | sensor id | sensor # | value 16 bit big endian | sensor id ......
// max 7 sensors per packet
for(uint8_t sensor=0; sensor<7; sensor++) {
uint8_t index = 9+(4*sensor);
switch(packet[index]) {
case SENSOR_RX_VOLTAGE:
v_lipo = packet[index+3]<<8 | packet[index+2];
telemetry_link=1;
break;
case SENSOR_RX_ERR_RATE:
// packet[index+2];
break;
case SENSOR_RX_RSSI:
RSSI_dBm = -packet[index+2];
break;
case 0xff:
return;
default:
// unknown sensor ID
break;
}
}
}
#endif
static void afhds2a_build_bind_packet() {
uint8_t ch;
memcpy( &packet[1], rx_tx_addr, 4);
memset( &packet[5], 0xff, 4);
packet[10]= 0x00;
for(ch=0; ch<16; ch++) {
packet[11+ch] = hopping_frequency[ch];
}
memset( &packet[27], 0xff, 10);
packet[37] = 0x00;
switch(phase) {
case BIND1:
packet[0] = 0xbb;
packet[9] = 0x01;
break;
case BIND2:
case BIND3:
case BIND4:
packet[0] = 0xbc;
if(phase == BIND4) {
memcpy( &packet[5], &rxid, 4);
memset( &packet[11], 0xff, 16);
}
packet[9] = phase-1;
if(packet[9] > 0x02)
packet[9] = 0x02;
packet[27]= 0x01;
packet[28]= 0x80;
break;
}
}
static void calc_afhds_channels(uint32_t seed) {
int idx = 0;
uint32_t rnd = seed;
while (idx < NUMFREQ) {
int i;
int count_1_42 = 0, count_43_85 = 0, count_86_128 = 0, count_129_168=0;
rnd = rnd * 0x0019660D + 0x3C6EF35F; // Randomization
uint8_t next_ch = ((rnd >> (idx%32)) % 0xa8) + 1;
// Keep the distance 2 between the channels - either odd or even
if (((next_ch ^ seed) & 0x01 )== 0)
continue;
// Check that it's not duplicate and spread uniformly
for (i = 0; i < idx; i++) {
if(hopping_frequency[i] == next_ch)
break;
if(hopping_frequency[i] <= 42)
count_1_42++;
else if (hopping_frequency[i] <= 85)
count_43_85++;
else if (hopping_frequency[i] <= 128)
count_86_128++;
else
count_129_168++;
}
if (i != idx)
continue;
if ((next_ch <= 42 && count_1_42 < 5)
||(next_ch >= 43 && next_ch <= 85 && count_43_85 < 5)
||(next_ch >= 86 && next_ch <=128 && count_86_128 < 5)
||(next_ch >= 129 && count_129_168 < 5))
{
hopping_frequency[idx++] = next_ch;
}
}
}
#define WAIT_WRITE 0x80
static uint16_t afhds2a_cb() {
switch(phase) {
case BIND1:
case BIND2:
case BIND3:
A7105_Strobe(A7105_STANDBY);
afhds2a_build_bind_packet();
A7105_WriteData(38, packet_count%2 ? 0x0d : 0x8c);
if(A7105_ReadReg(0) == 0x1b) { // todo: replace with check crc+fec
A7105_Strobe(A7105_RST_RDPTR);
A7105_ReadData(RXPACKET_SIZE);
if(packet[0] == 0xbc) {
for(uint8_t i=0; i<4; i++) {
rxid[i] = packet[5+i];
}
eeprom_write_block((const void*)rxid,(void*)EEPROMadress,4);
if(packet[9] == 0x01)
phase = BIND4;
}
}
packet_count++;
phase |= WAIT_WRITE;
return 1700;
case BIND1|WAIT_WRITE:
case BIND2|WAIT_WRITE:
case BIND3|WAIT_WRITE:
A7105_Strobe(A7105_RX);
phase &= ~WAIT_WRITE;
phase++;
if(phase > BIND3)
phase = BIND1;
return 2150;
case BIND4:
A7105_Strobe(A7105_STANDBY);
afhds2a_build_bind_packet();
A7105_WriteData(38, packet_count%2 ? 0x0d : 0x8c);
packet_count++;
bind_reply++;
if(bind_reply>=4) {
packet_count=0;
channel=1;
phase = DATA1;
BIND_DONE;
}
phase |= WAIT_WRITE;
return 1700;
case BIND4|WAIT_WRITE:
A7105_Strobe(A7105_RX);
phase &= ~WAIT_WRITE;
return 2150;
case DATA1:
A7105_Strobe(A7105_STANDBY);
build_packet(packet_type);
A7105_WriteData(38, hopping_frequency[channel++]);
if(channel >= 16)
channel = 0;
if(!(packet_count % 1313))
packet_type = PACKET_SETTINGS;
else if(!(packet_count % 1569))
packet_type = PACKET_FAILSAFE;
else
packet_type = PACKET_STICKS; // todo : check for settings changes
// got some data from RX ?
// we've no way to know if RX fifo has been filled
// as we can't poll GIO1 or GIO2 to check WTR
// we can't check A7105_MASK_TREN either as we know
// it's currently in transmit mode.
if(!(A7105_ReadReg(0) & (1<<5 | 1<<6))) { // FECF+CRCF Ok
A7105_Strobe(A7105_RST_RDPTR);
A7105_ReadData(1);
if(packet[0] == 0xaa) {
A7105_Strobe(A7105_RST_RDPTR);
A7105_ReadData(RXPACKET_SIZE);
if(packet[9] == 0xfc) { // rx is asking for settings
packet_type=PACKET_SETTINGS;
}
else {
#if defined(TELEMETRY)
update_telemetry();
#endif
}
}
}
packet_count++;
phase |= WAIT_WRITE;
return 1700;
case DATA1|WAIT_WRITE:
phase &= ~WAIT_WRITE;
A7105_Strobe(A7105_RX);
return 2150;
}
return 3850; // never reached, please the compiler
}
static uint16_t AFHDS2A_setup()
{
A7105_Init(INIT_FLYSKY_AFHDS2A); //flysky_init();
calc_afhds_channels(MProtocol_id);
packet_type = PACKET_STICKS;
packet_count = 0;
bind_reply = 0;
if(IS_AUTOBIND_FLAG_on) {
phase = BIND1;
BIND_IN_PROGRESS;
}
else {
phase = DATA1;
eeprom_read_block((void*)rxid,(const void*)EEPROMadress,4);
}
channel = 0;
return 50000;
}
#endif

View File

@ -17,297 +17,9 @@
*/
#if defined(FRSKYX_CC2500_INO)
#include "iface_cc2500.h"
uint8_t chanskip;
uint8_t calData[48][3];
uint8_t channr;
uint8_t pass_ = 1 ;
uint8_t counter_rst;
uint8_t ctr;
uint8_t FS_flag=0;
// uint8_t ptr[4]={0x01,0x12,0x23,0x30};
//uint8_t ptr[4]={0x00,0x11,0x22,0x33};
const PROGMEM uint8_t hop_data[]={
0x02, 0xD4, 0xBB, 0xA2, 0x89,
0x70, 0x57, 0x3E, 0x25, 0x0C,
0xDE, 0xC5, 0xAC, 0x93, 0x7A,
0x61, 0x48, 0x2F, 0x16, 0xE8,
0xCF, 0xB6, 0x9D, 0x84, 0x6B,
0x52, 0x39, 0x20, 0x07, 0xD9,
0xC0, 0xA7, 0x8E, 0x75, 0x5C,
0x43, 0x2A, 0x11, 0xE3, 0xCA,
0xB1, 0x98, 0x7F, 0x66, 0x4D,
0x34, 0x1B, 0x00, 0x1D, 0x03
};
static uint8_t __attribute__((unused)) hop(uint8_t byte)
{
return pgm_read_byte_near(&hop_data[byte]);
}
#include "iface_cc2500.h"
static void __attribute__((unused)) set_start(uint8_t ch )
{
cc2500_strobe(CC2500_SIDLE);
cc2500_writeReg(CC2500_23_FSCAL3, calData[ch][0]);
cc2500_writeReg(CC2500_24_FSCAL2, calData[ch][1]);
cc2500_writeReg(CC2500_25_FSCAL1, calData[ch][2]);
cc2500_writeReg(CC2500_0A_CHANNR, ch==47?0:pgm_read_word(&hop_data[ch]));
}
static void __attribute__((unused)) frskyX_init()
{
CC2500_Reset();
for(uint8_t i=0;i<36;i++)
{
uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]);
uint8_t val=pgm_read_byte_near(&cc2500_conf[i][1]);
if(reg==CC2500_06_PKTLEN)
val=0x1E;
else
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);
cc2500_writeReg(CC2500_0C_FSCTRL0, option);
cc2500_strobe(CC2500_SIDLE);
//
for(uint8_t c=0;c < 47;c++){//calibrate hop channels
cc2500_strobe(CC2500_SIDLE);
cc2500_writeReg(CC2500_0A_CHANNR,pgm_read_word(&hop_data[c]));
cc2500_strobe(CC2500_SCAL);
delayMicroseconds(900);//
calData[c][0] = cc2500_readReg(CC2500_23_FSCAL3);
calData[c][1] = cc2500_readReg(CC2500_24_FSCAL2);
calData[c][2] = cc2500_readReg(CC2500_25_FSCAL1);
}
cc2500_strobe(CC2500_SIDLE);
cc2500_writeReg(CC2500_0A_CHANNR,0x00);
cc2500_strobe(CC2500_SCAL);
delayMicroseconds(900);
calData[47][0] = cc2500_readReg(CC2500_23_FSCAL3);
calData[47][1] = cc2500_readReg(CC2500_24_FSCAL2);
calData[47][2] = cc2500_readReg(CC2500_25_FSCAL1);
//#######END INIT########
}
static void __attribute__((unused)) initialize_data(uint8_t adr)
{
cc2500_writeReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
cc2500_writeReg(CC2500_18_MCSM0, 0x8);
cc2500_writeReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]);
cc2500_writeReg(CC2500_07_PKTCTRL1,0x05);
}
static uint8_t __attribute__((unused)) crc_Byte( uint8_t byte )
{
crc = (crc<<8) ^ pgm_read_word(&CRCTable[((uint8_t)(crc>>8) ^ byte) & 0xFF]);
return byte;
}
static uint16_t __attribute__((unused)) scaleForPXX( uint8_t i )
{ //mapped 860,2140(125%) range to 64,1984(PXX values);
return (uint16_t)(((Servo_data[i]-PPM_MIN)*3)>>1)+64;
}
static void __attribute__((unused)) frskyX_build_bind_packet()
{
crc=0;
packet[0] = 0x1D;
packet[1] = 0x03;
packet[2] = 0x01;
//
packet[3] = crc_Byte(rx_tx_addr[3]);
packet[4] = crc_Byte(rx_tx_addr[2]);
int idx = ((state -FRSKY_BIND) % 10) * 5;
packet[5] = crc_Byte(idx);
packet[6] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[7] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[8] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[9] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[10] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[11] = crc_Byte(0x02);
packet[12] = crc_Byte(RX_num);
//
for(uint8_t i=13;i<28;i++)
packet[i]=crc_Byte(0);
//
packet[28]=highByte(crc);
packet[29]=lowByte(crc);
//
}
static void __attribute__((unused)) frskyX_data_frame()
{
//0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12
//
uint8_t lpass = pass_ ;
uint16_t chan_0 ;
uint16_t chan_1 ;
uint8_t flag2 = 0;
uint8_t startChan = 0;
crc = 0;
//static uint8_t p = 0;
//
packet[0] = 0x1D;
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = crc_Byte(0x02);
//
packet[4] = crc_Byte((ctr<<6)+channr); //*64
packet[5] = crc_Byte(counter_rst);
packet[6] = crc_Byte(RX_num);
// FLAGS 00 - standard packet
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
//20 - range check packet
packet[7] = crc_Byte(FS_flag);
packet[8] = crc_Byte(flag2);
//
if ( lpass & 1 )
startChan += 8 ;
for(uint8_t i = 0; i <12 ; i+=3)
{//12 bytes
chan_0 = scaleForPXX(startChan);
if(lpass & 1 )
chan_0+=2048;
packet[9+i] = crc_Byte(lowByte(chan_0));//3 bytes*4
startChan++;
chan_1 = scaleForPXX(startChan);
if(lpass & 1 )
chan_1+= 2048;
startChan++;
packet[9+i+1]=crc_Byte((((chan_0>>8) & 0x0F)|(chan_1 << 4)));
packet[9+i+2]=crc_Byte(chan_1>>4);
}
//packet[21]=crc_Byte(0x08);//first
packet[21]=crc_Byte(0x80);//??? when received first telemetry frame is changed to 0x80
//packet[21]=crc_Byte(ptr[p]);//???
//p=(p+1)%4;//repeating 4 bytes sequence pattern every 4th frame.
pass_=lpass+1;
for (uint8_t i=22;i<28;i++)
packet[i]=crc_Byte(0);
packet[28]=highByte(crc);
packet[29]=lowByte(crc);
}
<<<<<<< HEAD
uint16_t ReadFrSkyX()
{
switch(state)
{
default:
set_start(47);
CC2500_SetPower();
cc2500_strobe(CC2500_SFRX);
//
frskyX_build_bind_packet();
cc2500_strobe(CC2500_SIDLE);
cc2500_writeFifo(packet, packet[0]+1);
state++;
return 9000;
case FRSKY_BIND_DONE:
initialize_data(0);
channr=0;
BIND_DONE;
state++;
break;
case FRSKY_DATA1:
LED_ON;
CC2500_SetTxRxMode(TX_EN);
set_start(channr);
CC2500_SetPower();
cc2500_strobe(CC2500_SFRX);
channr = (channr+chanskip)%47;
cc2500_strobe(CC2500_SIDLE);
cc2500_writeFifo(packet, packet[0]+1);
//
frskyX_data_frame();
state++;
return 5500;
case FRSKY_DATA2:
CC2500_SetTxRxMode(RX_EN);
cc2500_strobe(CC2500_SIDLE);
state++;
return 200;
case FRSKY_DATA3:
cc2500_strobe(CC2500_SRX);
state++;
return 3000;
case FRSKY_DATA4:
len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len &&(len<MAX_PKT))
{
cc2500_readFifo(pkt, len);
#if defined TELEMETRY
frsky_check_telemetry(pkt,len); //check if valid telemetry packets
//parse telemetry packets here
//The same telemetry function used by FrSky(D8).
#endif
}
state = FRSKY_DATA1;
return 300;
}
return 1;
}
uint16_t initFrSkyX()
{
while(!chanskip)
{
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
chanskip=random(0xfefefefe)%47;
}
while((chanskip-ctr)%4)
ctr=(ctr+1)%4;
counter_rst=(chanskip-ctr)>>2;
//for test***************
//rx_tx_addr[3]=0xB3;
//rx_tx_addr[2]=0xFD;
//************************
frskyX_init();
//
if(IS_AUTOBIND_FLAG_on)
{
state = FRSKY_BIND;
initialize_data(1);
}
else
{
state = FRSKY_DATA1;
initialize_data(0);
}
return 10000;
}
=======
uint8_t chanskip;
uint8_t counter_rst;
uint8_t ctr;
@ -617,5 +329,4 @@ uint16_t initFrSkyX()
seq_last_rcvd = 8;
return 10000;
}
>>>>>>> refs/remotes/pascallanger/master
#endif

View File

@ -1,219 +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/>.
*/
#if defined(FRSKY_CC2500_INO)
#include "iface_cc2500.h"
//##########Variables########
//uint32_t state;
//uint8_t len;
/*
enum {
FRSKY_BIND = 0,
FRSKY_BIND_DONE = 1000,
FRSKY_DATA1,
FRSKY_DATA2,
FRSKY_DATA3,
FRSKY_DATA4,
FRSKY_DATA5
};
*/
static void __attribute__((unused)) frsky2way_init(uint8_t bind)
{
// Configure cc2500 for tx mode
CC2500_Reset();
//
for(uint8_t i=0;i<36;i++)
{
uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]);
uint8_t val=pgm_read_byte_near(&cc2500_conf[i][1]);
if(reg==CC2500_0C_FSCTRL0)
val=option;
else
if(reg==CC2500_1B_AGCCTRL2)
val=bind ? 0x43 : 0x03;
cc2500_writeReg(reg,val);
}
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
cc2500_strobe(CC2500_SIDLE);
cc2500_writeReg(CC2500_09_ADDR, bind ? 0x03 : rx_tx_addr[3]);
cc2500_writeReg(CC2500_07_PKTCTRL1, 0x05);
cc2500_strobe(CC2500_SIDLE); // Go to idle...
//
cc2500_writeReg(CC2500_0A_CHANNR, 0x00);
cc2500_writeReg(CC2500_23_FSCAL3, 0x89);
cc2500_strobe(CC2500_SFRX);
//#######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
//11 03 01 19 3e 00 02 8e 2f bb 5c 00 00 00 00 00 00 01
packet[0] = 0x11;
packet[1] = 0x03;
packet[2] = 0x01;
packet[3] = rx_tx_addr[3];
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[11] = 0x00;
packet[12] = 0x00;
packet[13] = 0x00;
packet[14] = 0x00;
packet[15] = 0x00;
packet[16] = 0x00;
packet[17] = 0x01;
}
static void __attribute__((unused)) frsky2way_data_frame()
{//pachet[4] is telemetry user frame counter(hub)
//11 d7 2d 22 00 01 c9 c9 ca ca 88 88 ca ca c9 ca 88 88
//11 57 12 00 00 01 f2 f2 f2 f2 06 06 ca ca ca ca 18 18
packet[0] = 0x11; //Length
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = counter;//
#if defined TELEMETRY
packet[4] = telemetry_counter;
#else
packet[4] = 0x00;
#endif
packet[5] = 0x01;
//
packet[10] = 0;
packet[11] = 0;
packet[16] = 0;
packet[17] = 0;
for(uint8_t i = 0; i < 8; i++)
{
uint16_t value;
value = convert_channel_frsky(i);
if(i < 4)
{
packet[6+i] = value & 0xff;
packet[10+(i>>1)] |= ((value >> 8) & 0x0f) << (4 *(i & 0x01));
}
else
{
packet[8+i] = value & 0xff;
packet[16+((i-4)>>1)] |= ((value >> 8) & 0x0f) << (4 * ((i-4) & 0x01));
}
}
}
uint16_t initFrSky_2way()
{
if(IS_AUTOBIND_FLAG_on)
{
frsky2way_init(1);
state = FRSKY_BIND;//
}
else
{
frsky2way_init(0);
state = FRSKY_DATA2;
}
return 10000;
}
uint16_t ReadFrSky_2way()
{
if (state < FRSKY_BIND_DONE)
{
frsky2way_build_bind_packet();
cc2500_strobe(CC2500_SIDLE);
cc2500_writeReg(CC2500_0A_CHANNR, 0x00);
cc2500_writeReg(CC2500_23_FSCAL3, 0x89);
cc2500_strobe(CC2500_SFRX);//0x3A
cc2500_writeFifo(packet, packet[0]+1);
state++;
return 9000;
}
if (state == FRSKY_BIND_DONE)
{
state = FRSKY_DATA2;
frsky2way_init(0);
counter = 0;
BIND_DONE;
}
else
if (state == FRSKY_DATA5)
{
cc2500_strobe(CC2500_SRX);//0x34 RX enable
state = FRSKY_DATA1;
return 9200;
}
counter = (counter + 1) % 188;
if (state == FRSKY_DATA4)
{ //telemetry receive
CC2500_SetTxRxMode(RX_EN);
cc2500_strobe(CC2500_SIDLE);
cc2500_writeReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
cc2500_writeReg(CC2500_23_FSCAL3, 0x89);
state++;
return 1300;
}
else
{
if (state == FRSKY_DATA1)
{
len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len<=MAX_PKT)//27 bytes
{
cc2500_readFifo(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
}
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_23_FSCAL3, 0x89);
cc2500_strobe(CC2500_SFRX);
frsky2way_data_frame();
cc2500_writeFifo(packet, packet[0]+1);
state++;
}
return state == FRSKY_DATA4 ? 7500 : 9000;
}
#endif

View File

@ -122,7 +122,7 @@ static void __attribute__((unused)) build_ch_data()
uint8_t i,j;
for (i = 0; i< 8; i++) {
j=CH_AETR[i];
temp=map(limit_channel_100(j),servo_min_100,servo_max_100,0,1000);
temp=map(limit_channel_100(j),servo_min_100,servo_max_100,0,1000);
if (j == THROTTLE) // It is clear that hisky's throttle stick is made reversely, so I adjust it here on purpose
temp = 1000 -temp;
if (j == AUX3)

View File

@ -70,6 +70,7 @@ static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
}
else
{
/*
if(sub_protocol == FORMAT_JJRCX1)
packet[0] = GET_FLAG(Servo_AUX2, 0x02); // Arm
else
@ -112,7 +113,60 @@ static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
packet[9] = convert_channel_8b_scale(ELEVATOR, 0, 63)-31; // Elevator trim
else
packet[9] = convert_channel_8b_scale(ELEVATOR, 0, 32)-16; // Elevator trim
*/
packet[1] = 0x00;
packet[2] = 0x00;
packet[3] = (convert_channel_8b_scale(THROTTLE, 0, 127) << 1); // Throttle
packet[4] = convert_channel_8b_scale(AILERON, 63, 0); // Aileron
packet[5] = convert_channel_8b_scale(ELEVATOR, 0, 63); // Elevator
packet[6] = convert_channel_8b_scale(RUDDER, 0, 63); // Rudder
if(sub_protocol == FORMAT_X5C1)
packet[7] = convert_channel_8b_scale(AILERON, 0, 63)-31; // Aileron trim
else
packet[7] = convert_channel_8b_scale(AILERON, 0, 32)-16; // Aileron trim
if (sub_protocol == FORMAT_X5C1)
packet[9] = convert_channel_8b_scale(ELEVATOR, 0, 63)-31; // Elevator trim
else
packet[9] = convert_channel_8b_scale(ELEVATOR, 0, 32)-16; // Elevator trim
switch(sub_protocol) {
case FORMAT_HONTAI:
packet[0] = 0x0b;
packet[3] |= GET_FLAG(Servo_AUX3, 0x01); // Picture
packet[4] |= GET_FLAG(Servo_AUX6, 0x80) // RTH
| GET_FLAG(Servo_AUX5, 0x40); // Headless
packet[5] |= GET_FLAG(Servo_AUX7, 0x80) // Calibrate
| GET_FLAG(Servo_AUX1, 0x40); // Flip
packet[6] |= GET_FLAG(Servo_AUX4, 0x80); // Video
packet[8] = convert_channel_8b_scale(RUDDER, 0, 32)-16; // Rudder trim
break;
case FORMAT_X5C1:
case FORMAT_JJRCX1:
packet[0] = GET_FLAG(Servo_AUX2, 0x02); //Arm
packet[3] |= GET_FLAG(Servo_AUX3, 0x01); // Picture
packet[4] |= 0x80; // unknown
if (sub_protocol == FORMAT_X5C1)
packet[4] |= GET_FLAG(Servo_AUX2, 0x40); // Lights (X5C1)
packet[5] |= GET_FLAG(Servo_AUX7, 0x80) // Calibrate
| GET_FLAG(Servo_AUX1, 0x40); // Flip
packet[6] |= GET_FLAG(Servo_AUX4, 0x80); // Video
packet[8] = 0xc0 // high rate, no rudder trim
| GET_FLAG(Servo_AUX6, 0x02) // RTH
| GET_FLAG(Servo_AUX5, 0x01); // Headless
break;
case FORMAT_FQ777:
// todo: add missing calibration flag
packet[0] = GET_FLAG(Servo_AUX3, 0x01) // Picture
| GET_FLAG(Servo_AUX4, 0x02); // Video
packet[3] |= GET_FLAG(Servo_AUX1, 0x01); // Flip
packet[4] |= 0xc0; // high rate (mid=0xa0, low=0x60)
packet[6] |= GET_FLAG(Servo_AUX5, 0x40); // Headless
if((packet[4] & 0x3f) > 0x3d && (packet[5] & 0x3f) < 3)
packet[5] |= 0x80; // accelerometer recalibration
break;
packet[8] = convert_channel_8b_scale(RUDDER, 0, 32)-16; // Rudder trim
}
packet_size=HONTAI_PACKET_SIZE;
}
crc16(packet, packet_size);
@ -172,7 +226,8 @@ static void __attribute__((unused)) HONTAI_init()
const uint8_t PROGMEM hopping_frequency_nonels[][3] = {
{0x05, 0x19, 0x28}, // Hontai
{0x0a, 0x1e, 0x2d}}; // JJRC X1
{0x0a, 0x1e, 0x2d}, // JJRC X1
{0x05, 0x19, 0x28}}; // FQ777-951
const uint8_t PROGMEM addr_vals[4][16] = {
{0x24, 0x26, 0x2a, 0x2c, 0x32, 0x34, 0x36, 0x4a, 0x4c, 0x4e, 0x54, 0x56, 0x5a, 0x64, 0x66, 0x6a},

View File

@ -18,24 +18,51 @@
#if defined(HUBSAN_A7105_INO)
#include "iface_a7105.h"
enum {
FORMAT_H107 = 0,
FORMAT_H301,
FORMAT_H501,
};
enum{
// flags going to packet[9] (Normal)
// flags going to packet[9] (H107 Normal)
HUBSAN_FLAG_VIDEO= 0x01, // record video
HUBSAN_FLAG_FLIP = 0x08, // enable flips
HUBSAN_FLAG_LED = 0x04 // enable LEDs
};
enum{
// flags going to packet[9] (Plus series)
// flags going to packet[9] (H107 Plus series)
HUBSAN_FLAG_HEADLESS = 0x08, // headless mode
};
enum{
// flags going to packet[13] (Plus series)
// flags going to packet[9] (H301)
FLAG_H301_VIDEO = 0x01,
FLAG_H301_STAB = 0x02,
FLAG_H301_LED = 0x10,
FLAG_H301_RTH = 0x40,
};
enum{
// flags going to packet[13] (H107 Plus series)
HUBSAN_FLAG_SNAPSHOT = 0x01,
HUBSAN_FLAG_FLIP_PLUS = 0x80,
};
enum{
// flags going to packet[9] (H501S)
FLAG_H501_VIDEO = 0x01,
FLAG_H501_LED = 0x04,
FLAG_H501_RTH = 0x20,
FLAG_H501_HEADLESS1 = 0x40,
FLAG_H501_GPS_HOLD = 0x80,
};
enum{
// flags going to packet[13] (H501S)
FLAG_H501_SNAPSHOT = 0x01,
FLAG_H501_HEADLESS2 = 0x02,
FLAG_H501_ALT_HOLD = 0x08,
};
uint32_t sessionid,id_data;
@ -76,7 +103,7 @@ static void __attribute__((unused)) hubsan_build_bind_packet(uint8_t bind_state)
packet[3] = (sessionid >> 16) & 0xFF;
packet[4] = (sessionid >> 8) & 0xFF;
packet[5] = (sessionid >> 0) & 0xFF;
if(id_data == ID_NORMAL)
if(id_data == ID_NORMAL && sub_protocol != FORMAT_H501)
{
packet[6] = 0x08;
packet[7] = 0xe4;
@ -89,7 +116,7 @@ static void __attribute__((unused)) hubsan_build_bind_packet(uint8_t bind_state)
packet[13] = 0x26;
packet[14] = 0x79;
}
else
else if(id_data == ID_PLUS || sub_protocol == FORMAT_H501)
{ //ID_PLUS
if(phase >= BIND_3)
{
@ -109,6 +136,7 @@ static void __attribute__((unused)) hubsan_build_bind_packet(uint8_t bind_state)
static void __attribute__((unused)) hubsan_build_packet()
{
static uint8_t vtx_freq = 0;
static uint32_t h501_packet = 0;
memset(packet, 0, 16);
if(vtx_freq != option || packet_count==100) // set vTX frequency (H107D)
{
@ -127,7 +155,7 @@ static void __attribute__((unused)) hubsan_build_packet()
packet[4] = 0xFF - convert_channel_8b(RUDDER); //Rudder is reversed
packet[6] = 0xFF - convert_channel_8b(ELEVATOR); //Elevator is reversed
packet[8] = convert_channel_8b(AILERON); //Aileron
if(id_data == ID_NORMAL)
if(id_data == ID_NORMAL && sub_protocol == FORMAT_H107) // H107/L/C/D, H102D
{
if( packet_count < 100)
{
@ -151,21 +179,50 @@ static void __attribute__((unused)) hubsan_build_packet()
packet[13] = 0x26;
packet[14] = 0x79;
}
else
{ //ID_PLUS
packet[3] = 0x64;
packet[5] = 0x64;
packet[7] = 0x64;
packet[9] = 0x06;
//FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
if(Servo_AUX4) packet[9] |= HUBSAN_FLAG_VIDEO;
if(Servo_AUX5) packet[9] |= HUBSAN_FLAG_HEADLESS;
packet[10]= 0x19;
packet[12]= 0x5C; // ghost channel ?
packet[13] = 0;
if(Servo_AUX3) packet[13] = HUBSAN_FLAG_SNAPSHOT;
if(Servo_AUX1) packet[13] |= HUBSAN_FLAG_FLIP_PLUS;
packet[14]= 0x49; // ghost channel ?
else if( sub_protocol == FORMAT_H301) {
if(packet_count < 100) {
packet[9] = FLAG_H301_STAB;
packet_count++;
} else {
packet[9] = 0;
if(Servo_AUX1) packet[9] |= FLAG_H301_LED;
if(Servo_AUX2) packet[9] |= FLAG_H301_STAB;
if(Servo_AUX3) packet[9] |= FLAG_H301_RTH;
if(Servo_AUX4) packet[9] |= FLAG_H301_VIDEO; // H102D
}
packet[10] = 0x18; // ?
packet[12] = 0x5c; // ?
packet[14] = 0xf6; // ?
} else
{ //ID_PLUS +FORMAT_H501
packet[3] = sub_protocol == FORMAT_H501 ? 0x00 : 0x64;
packet[5] = sub_protocol == FORMAT_H501 ? 0x00 : 0x64;
packet[7] = sub_protocol == FORMAT_H501 ? 0x00 : 0x64;
if( sub_protocol == FORMAT_H501) { // H501S
packet[9] = 0x02;
if(Servo_AUX1) packet[9] |= HUBSAN_FLAG_FLIP;
if(Servo_AUX2) packet[9] |= FLAG_H501_LED;
if(Servo_AUX3) packet[9] |= FLAG_H501_RTH;
if(Servo_AUX4) packet[9] |= FLAG_H501_VIDEO;
if(Servo_AUX5) packet[9] |= FLAG_H501_HEADLESS1;
if(Servo_AUX6) packet[9] |= FLAG_H501_GPS_HOLD;
packet[13] = 0;
if(Servo_AUX5) packet[9] |= FLAG_H501_HEADLESS2;
if(Servo_AUX7) packet[9] |= FLAG_H501_ALT_HOLD;
if(Servo_AUX8) packet[9] |= FLAG_H501_SNAPSHOT;
}
else { // H107P/C+/D+
packet[9] = 0x06;
//FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
if(Servo_AUX4) packet[9] |= HUBSAN_FLAG_VIDEO;
if(Servo_AUX5) packet[9] |= HUBSAN_FLAG_HEADLESS;
packet[10]= sub_protocol == FORMAT_H501 ? 0x1a : 0x19;
packet[12]= 0x5C; // ghost channel ?
packet[13] = 0;
if(Servo_AUX3) packet[13] = HUBSAN_FLAG_SNAPSHOT;
if(Servo_AUX1) packet[13] |= HUBSAN_FLAG_FLIP_PLUS;
packet[14]= 0x49; // ghost channel ?
}
if(packet_count < 100)
{ // set channels to neutral for first 100 packets
packet[2] = 0x80; // throttle neutral is at mid stick on plus series
@ -176,6 +233,18 @@ static void __attribute__((unused)) hubsan_build_packet()
packet[13]= 0x00;
packet_count++;
}
if(sub_protocol == FORMAT_H501) {
h501_packet++;
if(h501_packet == 10) {
memset(packet, 0, 16);
packet[0] = 0xe8;
}
else if(h501_packet == 20) {
memset(packet, 0, 16);
packet[0] = 0xe9;
}
if(h501_packet >= 20) h501_packet = 0;
}
}
hubsan_update_crc();
}
@ -205,7 +274,7 @@ uint16_t ReadHubsan()
switch(phase) {
case BIND_1:
bind_count++;
if(bind_count >= 20)
if(bind_count >= 20 && sub_protocol != FORMAT_H501)
{
if(id_data == ID_NORMAL)
id_data = ID_PLUS;
@ -287,7 +356,15 @@ uint16_t ReadHubsan()
A7105_SetPower(); //Keep transmit power in sync
hubsan_build_packet();
A7105_Strobe(A7105_STANDBY);
A7105_WriteData(16, phase == DATA_5 && id_data == ID_NORMAL ? channel + 0x23 : channel);
u8 ch;
if((phase == DATA_5 && id_data == ID_NORMAL) && sub_protocol == FORMAT_H107) {
ch = channel + 0x23;
}
else {
ch = channel;
}
A7105_WriteData( 16, ch);
// A7105_WriteData(16, phase == DATA_5 && id_data == ID_NORMAL ? channel + 0x23 : channel);
if (phase == DATA_5)
phase = DATA_1;
else

View File

@ -246,11 +246,7 @@ static void __attribute__((unused)) kn_init()
NRF24L01_Initialize();
<<<<<<< HEAD
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
=======
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
@ -263,11 +259,7 @@ static void __attribute__((unused)) kn_init()
NRF24L01_Activate(0x73);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
// Enable: Dynamic Payload Length to enable PCF
<<<<<<< HEAD
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, BV(NRF2401_1D_EN_DPL));
=======
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, _BV(NRF2401_1D_EN_DPL));
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_SetPower();

File diff suppressed because it is too large Load Diff

View File

@ -12,11 +12,7 @@
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
<<<<<<< HEAD
// compatible with MJX WLH08, X600, X800, H26D
=======
// compatible with MJX WLH08, X600, X800, H26D, Eachine E010
>>>>>>> refs/remotes/pascallanger/master
// Last sync with hexfet new_protocols/mjxq_nrf24l01.c dated 2016-01-17
#if defined(MJXQ_NRF24L01_INO)
@ -30,8 +26,6 @@
#define MJXQ_RF_NUM_CHANNELS 4
#define MJXQ_ADDRESS_LENGTH 5
<<<<<<< HEAD
=======
// haven't figured out txid<-->rf channel mapping for MJX models
const uint8_t PROGMEM MJXQ_map_rfchan[][4] = {
{0x0A, 0x46, 0x3A, 0x42},
@ -43,7 +37,6 @@ const uint8_t PROGMEM MJXQ_map_txid[][3] = {
{0x48, 0x6A, 0x40} };
>>>>>>> refs/remotes/pascallanger/master
#define MJXQ_PAN_TILT_COUNT 16 // for H26D - match stock tx timing
#define MJXQ_PAN_DOWN 0x08
#define MJXQ_PAN_UP 0x04
@ -57,16 +50,6 @@ static uint8_t __attribute__((unused)) MJXQ_pan_tilt_value()
packet_count++;
if(packet_count & MJXQ_PAN_TILT_COUNT)
{
<<<<<<< HEAD
if(Servo_AUX8)
pan=MJXQ_PAN_UP;
if(Servo_data[AUX8]<PPM_MIN_COMMAND)
pan=MJXQ_PAN_DOWN;
if(Servo_data[AUX9]>PPM_MIN_COMMAND)
pan=MJXQ_TILT_UP;
if(Servo_data[AUX9]<PPM_MIN_COMMAND)
pan=MJXQ_TILT_DOWN;
=======
if(Servo_data[AUX8]>PPM_MAX_COMMAND)
pan=MJXQ_PAN_UP;
if(Servo_data[AUX8]<PPM_MIN_COMMAND)
@ -75,7 +58,6 @@ static uint8_t __attribute__((unused)) MJXQ_pan_tilt_value()
pan+=MJXQ_TILT_UP;
if(Servo_data[AUX9]<PPM_MIN_COMMAND)
pan+=MJXQ_TILT_DOWN;
>>>>>>> refs/remotes/pascallanger/master
}
return pan;
}
@ -86,17 +68,10 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
packet[0] = convert_channel_8b(THROTTLE);
packet[1] = convert_channel_s8b(RUDDER);
packet[4] = 0x40; // rudder does not work well with dyntrim
<<<<<<< HEAD
packet[2] = convert_channel_s8b(ELEVATOR);
packet[5] = MJXQ_CHAN2TRIM(packet[2]); // trim elevator
packet[3] = convert_channel_s8b(AILERON);
packet[6] = MJXQ_CHAN2TRIM(packet[3]); // trim aileron
=======
packet[2] = 0x80 ^ convert_channel_s8b(ELEVATOR);
packet[5] = GET_FLAG(Servo_AUX5, 1) ? 0x40 : MJXQ_CHAN2TRIM(packet[2]); // trim elevator
packet[3] = convert_channel_s8b(AILERON);
packet[6] = GET_FLAG(Servo_AUX5, 1) ? 0x40 : MJXQ_CHAN2TRIM(packet[3]); // trim aileron
>>>>>>> refs/remotes/pascallanger/master
packet[7] = rx_tx_addr[0];
packet[8] = rx_tx_addr[1];
packet[9] = rx_tx_addr[2];
@ -121,10 +96,7 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
packet[10]=MJXQ_pan_tilt_value();
// fall through on purpose - no break
case WLH08:
<<<<<<< HEAD
=======
case E010:
>>>>>>> refs/remotes/pascallanger/master
packet[10] += GET_FLAG(Servo_AUX6, 0x02) //RTH
| GET_FLAG(Servo_AUX5, 0x01); //HEADLESS
if (!bind)
@ -137,14 +109,6 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
}
break;
case X600:
<<<<<<< HEAD
if(Servo_AUX5) //HEADLESS
{ // driven trims cause issues when headless is enabled
packet[5] = 0x40;
packet[6] = 0x40;
}
=======
>>>>>>> refs/remotes/pascallanger/master
packet[10] = GET_FLAG(!Servo_AUX2, 0x02); //LED
packet[11] = GET_FLAG(Servo_AUX6, 0x01); //RTH
if (!bind)
@ -178,11 +142,7 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
if (sub_protocol == H26D)
NRF24L01_SetTxRxMode(TX_EN);
else
<<<<<<< HEAD
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
=======
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++ / 2]);
hopping_frequency_no %= 2 * MJXQ_RF_NUM_CHANNELS; // channels repeated
@ -205,20 +165,12 @@ static void __attribute__((unused)) MJXQ_init()
if (sub_protocol == WLH08)
memcpy(hopping_frequency, "\x12\x22\x32\x42", MJXQ_RF_NUM_CHANNELS);
else
<<<<<<< HEAD
if (sub_protocol == H26D)
=======
if (sub_protocol == H26D || sub_protocol == E010)
>>>>>>> refs/remotes/pascallanger/master
memcpy(hopping_frequency, "\x36\x3e\x46\x2e", MJXQ_RF_NUM_CHANNELS);
else
{
memcpy(hopping_frequency, "\x0a\x35\x42\x3d", MJXQ_RF_NUM_CHANNELS);
<<<<<<< HEAD
memcpy(addr, "\x6d\x6a\x73\x73\x73", MJXQ_RF_NUM_CHANNELS);
=======
memcpy(addr, "\x6d\x6a\x73\x73\x73", MJXQ_ADDRESS_LENGTH);
>>>>>>> refs/remotes/pascallanger/master
}
@ -237,53 +189,25 @@ static void __attribute__((unused)) MJXQ_init()
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, MJXQ_PACKET_SIZE); // rx pipe 0 (used only for blue board)
<<<<<<< HEAD
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
=======
if (sub_protocol == E010)
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250K
else
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_SetPower();
}
static void __attribute__((unused)) MJXQ_init2()
{
<<<<<<< HEAD
// haven't figured out txid<-->rf channel mapping for MJX models
static const uint8_t rf_map[][4] = {
{0x0A, 0x46, 0x3A, 0x42},
{0x0A, 0x3C, 0x36, 0x3F},
{0x0A, 0x43, 0x36, 0x3F} };
if (sub_protocol == H26D)
memcpy(hopping_frequency, "\x32\x3e\x42\x4e", MJXQ_RF_NUM_CHANNELS);
else
if (sub_protocol == WLH08)
memcpy(hopping_frequency, rf_map[rx_tx_addr[0]%3], MJXQ_RF_NUM_CHANNELS);
=======
if (sub_protocol == H26D)
memcpy(hopping_frequency, "\x32\x3e\x42\x4e", MJXQ_RF_NUM_CHANNELS);
else
if (sub_protocol != WLH08 && sub_protocol != E010)
for(uint8_t i=0;i<MJXQ_RF_NUM_CHANNELS;i++)
hopping_frequency[i]=pgm_read_byte_near( &MJXQ_map_rfchan[rx_tx_addr[4]%3][i] );
>>>>>>> refs/remotes/pascallanger/master
}
static void __attribute__((unused)) MJXQ_initialize_txid()
{
<<<<<<< HEAD
// haven't figured out txid<-->rf channel mapping for MJX models
static const uint8_t tx_map[][3]={
{0xF8, 0x4F, 0x1C},
{0xC8, 0x6E, 0x02},
{0x48, 0x6A, 0x40} };
if (sub_protocol == WLH08)
rx_tx_addr[0]&=0xF8; // txid must be multiple of 8
else
memcpy(rx_tx_addr,tx_map[rx_tx_addr[0]%3],3);
=======
rx_tx_addr[0]&=0xF8;
if (sub_protocol == E010)
{
@ -293,7 +217,6 @@ static void __attribute__((unused)) MJXQ_initialize_txid()
else
for(uint8_t i=0;i<3;i++)
rx_tx_addr[i]=pgm_read_byte_near( &MJXQ_map_txid[rx_tx_addr[4]%3][i] );
>>>>>>> refs/remotes/pascallanger/master
}
uint16_t MJXQ_callback()

View File

@ -12,11 +12,7 @@
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
<<<<<<< HEAD
// compatible with MT99xx, Eachine H7, Yi Zhan i6S
=======
// compatible with MT99xx, Eachine H7, Yi Zhan i6S and LS114/124
>>>>>>> refs/remotes/pascallanger/master
// Last sync with Goebish mt99xx_nrf24l01.c dated 2016-01-29
#if defined(MT99XX_NRF24L01_INO)
@ -41,8 +37,6 @@ enum{
FLAG_MT_FLIP = 0x80,
};
<<<<<<< HEAD
=======
enum{
// flags going to packet[6] (LS)
FLAG_LS_INVERT = 0x01,
@ -53,43 +47,12 @@ enum{
FLAG_LS_FLIP = 0x80,
};
>>>>>>> refs/remotes/pascallanger/master
enum {
MT99XX_INIT = 0,
MT99XX_BIND,
MT99XX_DATA
};
<<<<<<< HEAD
static void __attribute__((unused)) MT99XX_send_packet()
{
const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
const uint8_t mys_byte[] = {
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10
};
static uint8_t yz_seq_num=0;
if(sub_protocol != YZ)
{ // MT99XX & H7
packet[0] = convert_channel_8b_scale(THROTTLE,0x00,0xE1); // throttle
packet[1] = convert_channel_8b_scale(RUDDER ,0x00,0xE1); // rudder
packet[2] = convert_channel_8b_scale(AILERON ,0x00,0xE1); // aileron
packet[3] = convert_channel_8b_scale(ELEVATOR,0x00,0xE1); // elevator
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
packet[6] = GET_FLAG( Servo_AUX1, FLAG_MT_FLIP )
| GET_FLAG( Servo_AUX3, FLAG_MT_SNAPSHOT )
| GET_FLAG( Servo_AUX4, FLAG_MT_VIDEO );
if(sub_protocol==MT99)
packet[6] |= 0x40 | FLAG_MT_RATE2;
else
packet[6] |= FLAG_MT_RATE1; // max rate on H7
// todo: mys_byte = next channel index ?
// low nibble: index in chan list ?
// high nibble: 0->start from start of list, 1->start from end of list ?
packet[7] = mys_byte[hopping_frequency_no];
=======
const uint8_t h7_mys_byte[] = {
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10
@ -138,7 +101,6 @@ static void __attribute__((unused)) MT99XX_send_packet()
ls_counter=0;
}
>>>>>>> refs/remotes/pascallanger/master
uint8_t result=checksum_offset;
for(uint8_t i=0; i<8; i++)
result += packet[i];
@ -147,15 +109,9 @@ static void __attribute__((unused)) MT99XX_send_packet()
else
{ // YZ
packet[0] = convert_channel_8b_scale(THROTTLE,0x00,0x64); // throttle
<<<<<<< HEAD
packet[1] = convert_channel_8b_scale(RUDDER ,0x00,0x64); // rudder
packet[2] = convert_channel_8b_scale(ELEVATOR,0x00,0x64); // elevator
packet[3] = convert_channel_8b_scale(AILERON ,0x00,0x64); // aileron
=======
packet[1] = convert_channel_8b_scale(RUDDER ,0x64,0x00); // rudder
packet[2] = convert_channel_8b_scale(ELEVATOR,0x00,0x64); // elevator
packet[3] = convert_channel_8b_scale(AILERON ,0x64,0x00); // aileron
>>>>>>> refs/remotes/pascallanger/master
if(packet_count++ >= 23)
{
yz_seq_num ++;
@ -176,14 +132,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[8] = 0xff;
}
<<<<<<< HEAD
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no] + channel_offset);
=======
if(sub_protocol == LS)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel
else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no] + channel_offset);
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
@ -201,16 +153,11 @@ static void __attribute__((unused)) MT99XX_send_packet()
static void __attribute__((unused)) MT99XX_init()
{
NRF24L01_Initialize();
<<<<<<< HEAD
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
=======
if(sub_protocol == YZ)
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
XN297_SetTXAddr((uint8_t *)"\xCC\xCC\xCC\xCC\xCC", 5);
>>>>>>> refs/remotes/pascallanger/master
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); // Enable data pipe 0 only
@ -222,31 +169,18 @@ static void __attribute__((unused)) MT99XX_init()
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
<<<<<<< HEAD
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP) | (sub_protocol == YZ ? BV(XN297_UNSCRAMBLED):0) );
XN297_SetTXAddr((uint8_t *)"\xCC\xCC\xCC\xCC\xCC", 5);
=======
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) );
>>>>>>> refs/remotes/pascallanger/master
}
static void __attribute__((unused)) MT99XX_initialize_txid()
{
<<<<<<< HEAD
=======
rx_tx_addr[3] = 0xCC;
rx_tx_addr[4] = 0xCC;
>>>>>>> refs/remotes/pascallanger/master
if(sub_protocol == YZ)
{
rx_tx_addr[0] = 0x53; // test (SB id)
rx_tx_addr[1] = 0x00;
<<<<<<< HEAD
}
checksum_offset = (rx_tx_addr[0] + rx_tx_addr[1]) & 0xff;
=======
rx_tx_addr[2] = 0x00;
}
else
@ -255,7 +189,6 @@ static void __attribute__((unused)) MT99XX_initialize_txid()
else //MT99 & H7
rx_tx_addr[2] = 0x00;
checksum_offset = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2];
>>>>>>> refs/remotes/pascallanger/master
channel_offset = (((checksum_offset & 0xf0)>>4) + (checksum_offset & 0x0f)) % 8;
}
@ -267,26 +200,16 @@ uint16_t MT99XX_callback()
{
if (bind_counter == 0)
{
<<<<<<< HEAD
rx_tx_addr[2] = 0x00;
rx_tx_addr[3] = 0xCC;
rx_tx_addr[4] = 0xCC;
=======
>>>>>>> refs/remotes/pascallanger/master
// set tx address for data packets
XN297_SetTXAddr(rx_tx_addr, 5);
BIND_DONE;
}
else
{
<<<<<<< HEAD
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
=======
if(sub_protocol == LS)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel
else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, MT99XX_PACKET_SIZE); // bind packet
@ -313,25 +236,6 @@ uint16_t initMT99XX(void)
MT99XX_init();
packet[0] = 0x20;
<<<<<<< HEAD
if(sub_protocol!=YZ)
{ // MT99 & H7
packet_period = MT99XX_PACKET_PERIOD_MT;
packet[1] = 0x14;
packet[2] = 0x03;
packet[3] = 0x25;
}
else
{ // YZ
packet_period = MT99XX_PACKET_PERIOD_YZ;
packet[1] = 0x15;
packet[2] = 0x05;
packet[3] = 0x06;
}
packet[4] = rx_tx_addr[0]; // 1st byte for data state tx address
packet[5] = rx_tx_addr[1]; // 2nd byte for data state tx address (always 0x00 on Yi Zhan ?)
packet[6] = 0x00; // 3rd byte for data state tx address (always 0x00 ?)
=======
packet_period = MT99XX_PACKET_PERIOD_MT;
switch(sub_protocol)
{ // MT99 & H7
@ -356,7 +260,6 @@ uint16_t initMT99XX(void)
packet[4] = rx_tx_addr[0];
packet[5] = rx_tx_addr[1];
packet[6] = rx_tx_addr[2];
>>>>>>> refs/remotes/pascallanger/master
packet[7] = checksum_offset; // checksum offset
packet[8] = 0xAA; // fixed
packet_count=0;

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -94,6 +94,14 @@ static void NRF24L01_ReadPayload(uint8_t * data, uint8_t length)
data[i] = SPI_Read();
NRF_CSN_on;
}
static uint8_t NRF24L01_GetDynamicPayloadSize(void)
{
NRF_CSN_off;
SPI_Write(R_RX_PL_WID);
uint8_t res = SPI_Read();
NRF_CSN_on;
return res;
}
static void NRF24L01_Strobe(uint8_t state)
{
@ -234,11 +242,7 @@ uint8_t NRF24L01_packet_ack()
///////////////
// XN297 emulation layer
<<<<<<< HEAD
uint8_t xn297_scramble_enabled;
=======
uint8_t xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
>>>>>>> refs/remotes/pascallanger/master
uint8_t xn297_addr_len;
uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5];
@ -251,16 +255,6 @@ static const uint8_t xn297_scramble[] = {
0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f,
0x8e, 0xc5, 0x2f};
<<<<<<< HEAD
const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3d5f, 0xa6f1, 0x3a23, 0xaa16, 0x1caf,
0x62b2, 0xe0eb, 0x0821, 0xbe07, 0x5f1a, 0xaf15,
0x4f0a, 0xad24, 0x5e48, 0xed34, 0x068c, 0xf2c9,
0x1852, 0xdf36, 0x129d, 0xb17c, 0xd5f5, 0x70d7,
0xb798, 0x5133, 0x67db, 0xd94e};
=======
>>>>>>> refs/remotes/pascallanger/master
const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
@ -334,14 +328,8 @@ void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
}
void XN297_Configure(uint16_t flags)
void XN297_Configure(uint8_t flags)
{
<<<<<<< HEAD
xn297_scramble_enabled = !(flags & BV(XN297_UNSCRAMBLED));
xn297_crc = !!(flags & BV(NRF24L01_00_EN_CRC));
flags &= ~(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
=======
xn297_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
@ -350,7 +338,6 @@ void XN297_Configure(uint16_t flags)
void XN297_SetScrambledMode(const u8 mode)
{
xn297_scramble_enabled = mode;
>>>>>>> refs/remotes/pascallanger/master
}
void XN297_WritePayload(uint8_t* msg, uint8_t len)
@ -412,32 +399,6 @@ void XN297_ReadPayload(uint8_t* msg, uint8_t len)
// End of XN297 emulation
///////////////
<<<<<<< HEAD
// LT8910 emulation layer
uint8_t LT8910_buffer[64];
uint8_t LT8910_buffer_start;
uint16_t LT8910_buffer_overhead_bits;
uint8_t LT8910_addr[8];
uint8_t LT8910_addr_size;
uint8_t LT8910_Preamble_Len;
uint8_t LT8910_Tailer_Len;
uint8_t LT8910_CRC_Initial_Data;
uint8_t LT8910_Flags;
#define LT8910_CRC_ON 6
#define LT8910_SCRAMBLE_ON 5
#define LT8910_PACKET_LENGTH_EN 4
#define LT8910_DATA_PACKET_TYPE_1 3
#define LT8910_DATA_PACKET_TYPE_0 2
#define LT8910_FEC_TYPE_1 1
#define LT8910_FEC_TYPE_0 0
void LT8910_Config(uint8_t preamble_len, uint8_t trailer_len, uint8_t flags, uint8_t crc_init)
{
//Preamble 1 to 8 bytes
LT8910_Preamble_Len=preamble_len;
//Trailer 4 to 18 bits
LT8910_Tailer_Len=trailer_len;
=======
// LT8900 emulation layer
uint8_t LT8900_buffer[64];
uint8_t LT8900_buffer_start;
@ -462,37 +423,23 @@ void LT8900_Config(uint8_t preamble_len, uint8_t trailer_len, uint8_t flags, uin
LT8900_Preamble_Len=preamble_len;
//Trailer 4 to 18 bits
LT8900_Tailer_Len=trailer_len;
>>>>>>> refs/remotes/pascallanger/master
//Flags
// CRC_ON: 1 on, 0 off
// SCRAMBLE_ON: 1 on, 0 off
// PACKET_LENGTH_EN: 1 1st byte of payload is payload size
// DATA_PACKET_TYPE: 00 NRZ, 01 Manchester, 10 8bit/10bit line code, 11 interleave data type
// FEC_TYPE: 00 No FEC, 01 FEC13, 10 FEC23, 11 reserved
<<<<<<< HEAD
LT8910_Flags=flags;
//CRC init constant
LT8910_CRC_Initial_Data=crc_init;
}
void LT8910_SetChannel(uint8_t channel)
=======
LT8900_Flags=flags;
//CRC init constant
LT8900_CRC_Initial_Data=crc_init;
}
void LT8900_SetChannel(uint8_t channel)
>>>>>>> refs/remotes/pascallanger/master
{
NRF24L01_WriteReg(NRF24L01_05_RF_CH, channel +2); //NRF24L01 is 2400+channel but LT8900 is 2402+channel
}
<<<<<<< HEAD
void LT8910_SetTxRxMode(enum TXRX_State mode)
=======
void LT8900_SetTxRxMode(enum TXRX_State mode)
>>>>>>> refs/remotes/pascallanger/master
{
if(mode == TX_EN)
{
@ -518,35 +465,12 @@ void LT8900_SetTxRxMode(enum TXRX_State mode)
NRF24L01_SetTxRxMode(TXRX_OFF);
}
<<<<<<< HEAD
void LT8910_BuildOverhead()
=======
void LT8900_BuildOverhead()
>>>>>>> refs/remotes/pascallanger/master
{
uint8_t pos;
//Build overhead
//preamble
<<<<<<< HEAD
memset(LT8910_buffer,LT8910_addr[0]&0x01?0xAA:0x55,LT8910_Preamble_Len-1);
pos=LT8910_Preamble_Len-1;
//address
for(uint8_t i=0;i<LT8910_addr_size;i++)
{
LT8910_buffer[pos]=bit_reverse(LT8910_addr[i]);
pos++;
}
//trailer
memset(LT8910_buffer+pos,(LT8910_buffer[pos-1]&0x01)==0?0xAA:0x55,3);
LT8910_buffer_overhead_bits=pos*8+LT8910_Tailer_Len;
//nrf address length max is 5
pos+=LT8910_Tailer_Len/8;
LT8910_buffer_start=pos>5?5:pos;
}
void LT8910_SetAddress(uint8_t *address,uint8_t addr_size)
=======
memset(LT8900_buffer,LT8900_addr[0]&0x01?0xAA:0x55,LT8900_Preamble_Len-1);
pos=LT8900_Preamble_Len-1;
//address
@ -564,33 +488,10 @@ void LT8910_SetAddress(uint8_t *address,uint8_t addr_size)
}
void LT8900_SetAddress(uint8_t *address,uint8_t addr_size)
>>>>>>> refs/remotes/pascallanger/master
{
uint8_t addr[5];
//Address size (SyncWord) 2 to 8 bytes, 16/32/48/64 bits
<<<<<<< HEAD
LT8910_addr_size=addr_size;
memcpy(LT8910_addr,address,LT8910_addr_size);
//Build overhead
LT8910_BuildOverhead();
//Set NRF RX&TX address based on overhead content
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, LT8910_buffer_start-2);
for(uint8_t i=0;i<LT8910_buffer_start;i++) // reverse bytes order
addr[i]=LT8910_buffer[LT8910_buffer_start-i-1];
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, addr,LT8910_buffer_start);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr,LT8910_buffer_start);
}
uint8_t LT8910_ReadPayload(uint8_t* msg, uint8_t len)
{
uint8_t i,pos=0,shift,end,buffer[32];
unsigned int crc=LT8910_CRC_Initial_Data,a;
pos=LT8910_buffer_overhead_bits/8-LT8910_buffer_start;
end=pos+len+(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN)?1:0)+(LT8910_Flags&_BV(LT8910_CRC_ON)?2:0);
=======
LT8900_addr_size=addr_size;
for (uint8_t i = 0; i < addr_size; i++)
LT8900_addr[i] = address[addr_size-1-i];
@ -612,22 +513,14 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
unsigned int crc=LT8900_CRC_Initial_Data,a;
pos=LT8900_buffer_overhead_bits/8-LT8900_buffer_start;
end=pos+len+(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN)?1:0)+(LT8900_Flags&_BV(LT8900_CRC_ON)?2:0);
>>>>>>> refs/remotes/pascallanger/master
//Read payload
NRF24L01_ReadPayload(buffer,end+1);
//Check address + trail
for(i=0;i<pos;i++)
<<<<<<< HEAD
if(LT8910_buffer[LT8910_buffer_start+i]!=buffer[i])
return 0; // wrong address...
//Shift buffer to remove trail bits
shift=LT8910_buffer_overhead_bits&0x7;
=======
if(LT8900_buffer[LT8900_buffer_start+i]!=buffer[i])
return 0; // wrong address...
//Shift buffer to remove trail bits
shift=LT8900_buffer_overhead_bits&0x7;
>>>>>>> refs/remotes/pascallanger/master
for(i=pos;i<end;i++)
{
a=(buffer[i]<<8)+buffer[i+1];
@ -635,11 +528,7 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
buffer[i]=(a>>8)&0xFF;
}
//Check len
<<<<<<< HEAD
if(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN))
=======
if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN))
>>>>>>> refs/remotes/pascallanger/master
{
crc=crc16_update(crc,buffer[pos]);
if(bit_reverse(len)!=buffer[pos++])
@ -652,11 +541,7 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
msg[i]=bit_reverse(buffer[pos++]);
}
//Check CRC
<<<<<<< HEAD
if(LT8910_Flags&_BV(LT8910_CRC_ON))
=======
if(LT8900_Flags&_BV(LT8900_CRC_ON))
>>>>>>> refs/remotes/pascallanger/master
{
if(buffer[pos++]!=((crc>>8)&0xFF)) return 0; // wrong CRC...
if(buffer[pos]!=(crc&0xFF)) return 0; // wrong CRC...
@ -665,21 +550,12 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
return 1;
}
<<<<<<< HEAD
void LT8910_WritePayload(uint8_t* msg, uint8_t len)
{
unsigned int crc=LT8910_CRC_Initial_Data,a,mask;
uint8_t i, pos=0,tmp, buffer[64], pos_final,shift;
//Add packet len
if(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN))
=======
void LT8900_WritePayload(uint8_t* msg, uint8_t len)
{
unsigned int crc=LT8900_CRC_Initial_Data,a,mask;
uint8_t i, pos=0,tmp, buffer[64], pos_final,shift;
//Add packet len
if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN))
>>>>>>> refs/remotes/pascallanger/master
{
tmp=bit_reverse(len);
buffer[pos++]=tmp;
@ -693,27 +569,12 @@ void LT8900_WritePayload(uint8_t* msg, uint8_t len)
crc=crc16_update(crc,tmp);
}
//Add CRC
<<<<<<< HEAD
if(LT8910_Flags&_BV(LT8910_CRC_ON))
=======
if(LT8900_Flags&_BV(LT8900_CRC_ON))
>>>>>>> refs/remotes/pascallanger/master
{
buffer[pos++]=crc>>8;
buffer[pos++]=crc;
}
//Shift everything to fit behind the trailer (4 to 18 bits)
<<<<<<< HEAD
shift=LT8910_buffer_overhead_bits&0x7;
pos_final=LT8910_buffer_overhead_bits/8;
mask=~(0xFF<<(8-shift));
LT8910_buffer[pos_final+pos]=0xFF;
for(i=pos-1;i!=0xFF;i--)
{
a=buffer[i]<<(8-shift);
LT8910_buffer[pos_final+i]=(LT8910_buffer[pos_final+i]&mask>>8)|a>>8;
LT8910_buffer[pos_final+i+1]=(LT8910_buffer[pos_final+i+1]&mask)|a;
=======
shift=LT8900_buffer_overhead_bits&0x7;
pos_final=LT8900_buffer_overhead_bits/8;
mask=~(0xFF<<(8-shift));
@ -723,17 +584,10 @@ void LT8900_WritePayload(uint8_t* msg, uint8_t len)
a=buffer[i]<<(8-shift);
LT8900_buffer[pos_final+i]=(LT8900_buffer[pos_final+i]&mask>>8)|a>>8;
LT8900_buffer[pos_final+i+1]=(LT8900_buffer[pos_final+i+1]&mask)|a;
>>>>>>> refs/remotes/pascallanger/master
}
if(shift)
pos++;
//Send everything
<<<<<<< HEAD
NRF24L01_WritePayload(LT8910_buffer+LT8910_buffer_start,pos_final+pos-LT8910_buffer_start);
}
// End of LT8910 emulation
=======
NRF24L01_WritePayload(LT8900_buffer+LT8900_buffer_start,pos_final+pos-LT8900_buffer_start);
}
// End of LT8900 emulation
>>>>>>> refs/remotes/pascallanger/master

View File

@ -51,7 +51,7 @@ static void bluefly_init() {
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81); // binding packet must be set in channel 81
// 2-bytes CRC, radio on
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
NRF24L01_SetBitrate(NRF24L01_BR_250K); // BlueFly - 250kbps
NRF24L01_SetPower();
@ -63,7 +63,7 @@ static void bluefly_ch_data() {
uint32_t temp;
int i;
for (i = 0; i< 8; ++i) {
temp = (uint32_t)Servo_data[ch[i]] * 300/PPM_MAX + 500; // 200-800 range
temp = map(limit_channel_100(i),servo_min_100,servo_max_100,200,800); // 200-800 range
if (temp < 0)
ch_data_bluefly[i] = 0;
else if (temp > 1000)
@ -140,6 +140,7 @@ static uint16_t bluefly_cb() {
}
static uint16_t BlueFly_setup() {
MProtocol_id = (MProtocol_id | ((uint32_t)txid[3]<<32));
hopping_frequency_start = ((MProtocol_id >> 8) % 47) + 2;
bluefly_binding_packet();
bluefly_init();

View File

@ -13,12 +13,6 @@
along with Deviation. If not, see <http://www.gnu.org/licenses/>.
*/
/* NB: Not implemented
Uncomment define below to enable telemetry. Also add CFlie protocol to TELEMETRY_SetTypeByProtocol to set type to DSM.
#define CFLIE_TELEMETRY
*/
#if defined(CFlie_NRF24L01_INO)
#include "iface_nrf24l01.h"
@ -59,30 +53,15 @@ enum {
CFLIE_DATA
};
#ifdef CFLIE_TELEMETRY
static const char * const cflie_opts[] = {
_tr_noop("Telemetry"), _tr_noop("Off"), _tr_noop("On"), NULL,
NULL
};
enum {
PROTOOPTS_TELEMETRY = 0,
LAST_PROTO_OPT,
};
ctassert(LAST_PROTO_OPT <= NUM_PROTO_OPTS, too_many_protocol_opts);
#define TELEM_OFF 0
#define TELEM_ON 1
#endif
#define PACKET_CHKTIME 500 // time to wait if packet not yet acknowledged or timed out
#define PACKET_CFLIE_CHKTIME 500 // time to wait if packet not yet acknowledged or timed out
static uint16_t dbg_cnt = 0;
static uint8_t packet_ack() {
if (++dbg_cnt > 50) { dbg_cnt = 0; }
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) {
case BV(NRF24L01_07_TX_DS):
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (_BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT))) {
case _BV(NRF24L01_07_TX_DS):
return PKT_ACKED;
case BV(NRF24L01_07_MAX_RT):
case _BV(NRF24L01_07_MAX_RT):
return PKT_TIMEOUT;
}
return PKT_PENDING;
@ -97,7 +76,7 @@ static void send_search_packet() {
uint8_t buf[1];
buf[0] = 0xff;
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT)));
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)));
NRF24L01_FlushTx();
if (rf_channel++ > 125) {
@ -119,7 +98,7 @@ static void send_search_packet() {
NRF24L01_WritePayload(buf, sizeof(buf));
++packet_counter;
++packet_count;
}
// Frac 16.16
@ -151,33 +130,39 @@ static void send_cmd_packet() {
// Channels in AETR order
// Roll, aka aileron, float +- 50.0 in degrees
// float roll = -(float) Servo_data[AILERON]*50.0/10000;
uint32_t f_roll = -Servo_data[AILERON] * FRAC_SCALE / (10000 / 50);
uint32_t f_roll = -map(limit_channel_100(AILERON),servo_min_100,servo_max_100,-50,50);
// Pitch, aka elevator, float +- 50.0 degrees
//float pitch = -(float) Servo_data[ELEVATOR]*50.0/10000;
uint32_t f_pitch = -Servo_data[ELEVATOR] * FRAC_SCALE / (10000 / 50);
uint32_t f_pitch = -map(limit_channel_100(ELEVATOR),servo_min_100,servo_max_100,-50,50);
// Thrust, aka throttle 0..65535, working range 5535..65535
// No space for overshoot here, hard limit Channel3 by -10000..10000
uint32_t ch = Servo_data[THROTTLE];
if (ch < PPM_MIN) {
ch = PPM_MIN;
} else if (ch > PPM_MAX) {
ch = PPM_MAX;
if (ch < servo_min_125) {
ch = servo_min_125;
} else if (ch > servo_max_125) {
ch = servo_max_125;
}
uint16_t thrust = ch*3L + 35535L;
// Yaw, aka rudder, float +- 400.0 deg/s
// float yaw = -(float) Servo_data[RUDDER]*400.0/10000;
uint32_t f_yaw = - Servo_data[RUDDER] * FRAC_SCALE / (10000 / 400);
uint32_t f_yaw = - map(limit_channel_100(RUDDER),servo_min_100,servo_max_100,-40,40);
frac2float(f_yaw, &yaw);
// Convert + to X. 181 / 256 = 0.70703125 ~= sqrt(2) / 2
uint32_t f_x_roll = (f_roll + f_pitch) * 181 / 256;
frac2float(f_x_roll, &x_roll);
uint32_t f_x_pitch = (f_pitch - f_roll) * 181 / 256;
frac2float(f_x_pitch, &x_pitch);
// Switch on/off?
if(Servo_AUX1)
{
frac2float(f_roll, &x_roll);
frac2float(f_pitch, &x_pitch);
}
else
{
// Convert + to X. 181 / 256 = 0.70703125 ~= sqrt(2) / 2
uint32_t f_x_roll = (f_roll + f_pitch) * 181 / 256;
frac2float(f_x_roll, &x_roll);
uint32_t f_x_pitch = (f_pitch - f_roll) * 181 / 256;
frac2float(f_x_pitch, &x_pitch);
}
int bufptr = 0;
buf[bufptr++] = 0x30; // Commander packet to channel 0
@ -188,12 +173,12 @@ static void send_cmd_packet() {
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT)));
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)));
NRF24L01_FlushTx();
NRF24L01_WritePayload(buf, sizeof(buf));
++packet_counter;
++packet_count;
NRF24L01_SetPower();
}
@ -203,7 +188,7 @@ static int cflie_init() {
// CRC, radio on
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
// NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x01); // Auto Acknowledgement for data pipe 0
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
@ -236,21 +221,6 @@ static int cflie_init() {
return 50000;
}
#ifdef CFLIE_TELEMETRY
static void update_telemetry() {
static uint8_t frameloss = 0;
frameloss += NRF24L01_ReadReg(NRF24L01_08_OBSERVE_TX) >> 4;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_channel); // reset packet loss counter
Telemetry.p.dsm.flog.frameloss = frameloss;
// Telemetry.p.dsm.flog.volt[0] = read battery voltage from ack payload
TELEMETRY_SetUpdated(TELEM_DSM_FLOG_FRAMELOSS);
}
#endif
static uint16_t cflie_callback() {
switch (phase) {
case CFLIE_INIT_SEARCH:
@ -264,7 +234,7 @@ static uint16_t cflie_callback() {
case CFLIE_SEARCH:
switch (packet_ack()) {
case PKT_PENDING:
return PACKET_CHKTIME; // packet send not yet complete
return PACKET_CFLIE_CHKTIME; // packet send not yet complete
case PKT_ACKED:
phase = CFLIE_DATA;
BIND_DONE;
@ -275,11 +245,8 @@ static uint16_t cflie_callback() {
}
break;
case CFLIE_DATA:
#ifdef CFLIE_TELEMETRY
update_telemetry();
#endif
if (packet_ack() == PKT_PENDING)
return PACKET_CHKTIME; // packet send not yet complete
return PACKET_CFLIE_CHKTIME; // packet send not yet complete
send_cmd_packet();
break;
}
@ -287,31 +254,21 @@ static uint16_t cflie_callback() {
}
// Generate address to use from TX id and manufacturer id (STM32 unique id)
static uint8_t initialize_rx_tx_addr() {
static uint16_t Cflie_setup() {
rx_tx_addr[0] =
rx_tx_addr[1] =
rx_tx_addr[2] =
rx_tx_addr[3] =
rx_tx_addr[4] = 0xE7; // CFlie uses fixed address
data_rate = NRF24L01_BR_250K;
rf_channel = 0;
return CFLIE_INIT_SEARCH;
// return CFLIE_INIT_DATA;
}
static uint16_t Cflie_setup() {
phase = initialize_rx_tx_addr();
packet_counter = 0;
data_rate = NRF24L01_BR_250K;
rf_channel = 0;
packet_count = 0;
int delay = cflie_init();
#ifdef CFLIE_TELEMETRY
memset(&Telemetry, 0, sizeof(Telemetry));
TELEMETRY_SetType(TELEM_DSM);
#endif
if (phase == CFLIE_INIT_SEARCH) { BIND_IN_PROGRESS; }
phase = CFLIE_INIT_SEARCH;
BIND_IN_PROGRESS;
return delay;
}

View File

@ -32,15 +32,15 @@ enum {
static uint8_t esky150_packet_ack() {
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) {
case BV(NRF24L01_07_TX_DS): return PKT_ACKED;
case BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT;
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (_BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT))) {
case _BV(NRF24L01_07_TX_DS): return PKT_ACKED;
case _BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT;
}
return PKT_PENDING;
}
// 2-bytes CRC
#define CRC_CONFIG (BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO))
#define CRC_CONFIG (_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO))
static uint16_t esky150_init() {
uint8_t rx_addr[ADDR_esky150_SIZE] = { 0x73, 0x73, 0x74, 0x63 };
uint8_t tx_addr[ADDR_esky150_SIZE] = { 0x71, 0x0A, 0x31, 0xF4 };
@ -64,7 +64,7 @@ static uint16_t esky150_init() {
NRF24L01_Activate(0x73);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
// Enable: Dynamic Payload Length, Payload with ACK , W_TX_PAYLOAD_NOACK
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, BV(NRF2401_1D_EN_DPL) | BV(NRF2401_1D_EN_ACK_PAY) | BV(NRF2401_1D_EN_DYN_ACK));
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, _BV(NRF2401_1D_EN_DPL) | _BV(NRF2401_1D_EN_ACK_PAY) | _BV(NRF2401_1D_EN_DYN_ACK));
// Delay 50 ms
return 50000;
@ -80,51 +80,26 @@ static uint16_t esky150_init2() {
// Turn radio power on
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, CRC_CONFIG | BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, CRC_CONFIG | _BV(NRF24L01_00_PWR_UP));
// delayMicroseconds(150);
return 150;
}
static void calc_fh_channels(uint32_t seed) {
// Use channels 2..79
uint8_t first = seed % 37 + 2;
uint8_t second = first + 40;
hopping_frequency[0] = first; // 0x22;
hopping_frequency[1] = second; // 0x4a;
}
static uint8_t convert_channel(uint8_t num) {
uint32_t ch = Servo_data[num];
if (ch < PPM_MIN) { ch = PPM_MIN; }
else if (ch > PPM_MAX) { ch = PPM_MAX; }
return (uint8_t) ((ch * 500 / PPM_MAX) + 1500);
}
static void read_controls(uint8_t* throttle, uint8_t* aileron, uint8_t* elevator, uint8_t* rudder) {
*throttle = convert_channel(THROTTLE);
*aileron = convert_channel(AILERON);
*elevator = convert_channel(ELEVATOR);
*rudder = convert_channel(RUDDER);
}
static void esky150_send_packet() {
uint8_t rf_ch = hopping_frequency[rf_ch_num];
rf_ch_num = 1 - rf_ch_num;
read_controls(&throttle, &aileron, &elevator, &rudder);
packet[0] = hopping_frequency[0];
packet[1] = hopping_frequency[1];
packet[2] = (throttle >> 8) & 0xFF;
packet[3] = throttle & 0xFF;
packet[4] = (aileron >> 8) & 0xFF;
packet[5] = aileron & 0xFF;
packet[6] = (elevator >> 8) & 0xFF;
packet[7] = elevator & 0xFF;
packet[8] = (rudder >> 8) & 0xFF;
packet[9] = rudder & 0xFF;
packet[2] = highByte(Servo_data[THROTTLE]);
packet[3] = lowByte(Servo_data[THROTTLE]);
packet[4] = highByte(Servo_data[AILERON]);
packet[5] = lowByte(Servo_data[AILERON]);
packet[6] = highByte(Servo_data[ELEVATOR]);
packet[7] = lowByte(Servo_data[ELEVATOR]);
packet[8] = highByte(Servo_data[RUDDER]);
packet[9] = lowByte(Servo_data[RUDDER]);
// Constant values 00 d8 18 f8
packet[10] = 0x00;
packet[11] = 0xd8;
@ -166,6 +141,12 @@ static uint16_t esky150_callback() {
static uint16_t esky150_setup() {
total_packets = 0;
uint16_t timeout = esky150_init();
// Use channels 2..79
uint8_t first = MProtocol_id % 37 + 2;
uint8_t second = first + 40;
hopping_frequency[0] = first; // 0x22;
hopping_frequency[1] = second; // 0x4a;
return timeout;
}

View File

@ -93,7 +93,7 @@ static void config_nrf24l01() {
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // 0:No Auto Acknoledgement; 1:Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length); // fbl100/v922's packet size = 10, hp100 = 12
// 2-bytes CRC, radio off
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
NRF24L01_SetBitrate(sub_protocol == HP100? NRF24L01_BR_250K:NRF24L01_BR_1M); //hp100:250kbps; fbl100: 1Mbps
NRF24L01_SetPower();
@ -108,7 +108,7 @@ static void fbl100_build_ch_data() {
uint32_t temp;
uint8_t i;
for (i = 0; i< 8; i++) {
temp = (uint32_t)Servo_data[i] * 500/PPM_MAX + 500;
temp = (uint32_t)Servo_data[i] -1000;
if (i == 2) { temp = 1000 -temp; } // It is clear that fbl100's thro stick is made reversely,so I adjust it here on purposely
if (temp < 0) { fbl_data[i] = 0; }
else if (temp > 1000) { fbl_data[i] = 1000; }
@ -131,11 +131,12 @@ static void hp100_build_ch_data() {
uint32_t temp;
uint8_t i;
for (i = 0; i< 8; i++) {
temp = (uint32_t)Servo_data[i] * 300/PPM_MAX + 500;
temp=map(limit_channel_100(i),servo_min_100,servo_max_100,200,800);
/* temp = (uint32_t)Servo_data[i] * 300/PPM_MAX + 500;
if (temp < 0) { temp = 0; }
else if (temp > 1000) { temp = 1000; }
if (i == 3 || i == 5) { temp = 1000 -temp; } // hp100's rudd and pit channel are made reversely,so I adjust them on purposely
*/
fbl_data[i] = (unsigned int)temp;
packet[i] = (uint8_t)fbl_data[i];
}

View File

@ -90,7 +90,7 @@ static void h377_init() {
// 2-bytes CRC, radio off
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
NRF24L01_SetBitrate(0); // 1Mbps
NRF24L01_SetPower();
@ -100,10 +100,11 @@ static void h377_init() {
// H377 channel sequence: AILE ELEV THRO RUDD GEAR PITH, channel data value is from 0 to 1000
static void h377_ch_data() {
uint32_t temp;
uint8_t i;
uint8_t i,j;
for (i = 0; i< 8; i++) {
temp = (uint32_t)Servo_data[i] * 450/PPM_MAX + 500; // max/min servo range is +-125%
if (i == 2) // It is clear that h377's thro stick is made reversely, so I adjust it here on purpose
j=CH_AETR[i];
temp=map(limit_channel_100(j),servo_min_100,servo_max_100,0,1000); // max/min servo range is +-125%
if (j == THROTTLE) // It is clear that h377's thro stick is made reversely, so I adjust it here on purpose
temp = 1000 -temp;
//if (i == 0) // It is clear that h377's thro stick is made reversely, so I adjust it here on purpose
// temp = 1000 -temp;

View File

@ -76,7 +76,7 @@ static uint8_t count;
static uint8_t rf_ch[] = {0x08, 0x35, 0x12, 0x3f, 0x1c, 0x49, 0x26};
static uint8_t bind_addr[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xc2};
static uint8_t crc8(uint32_t result, uint8_t *data, int len) {
static uint8_t HM830_crc8(uint32_t result, uint8_t *data, int len) {
int polynomial = 0x01;
for(int i = 0; i < len; i++) {
result = result ^ data[i];
@ -114,26 +114,26 @@ static void HM830_init() {
static void build_bind_packet_hm830() {
for(int i = 0; i < 6; i++) { packet[i] = rx_tx_addr[i]; }
packet[6] = crc8(0xa5, packet, 6);
packet[6] = HM830_crc8(0xa5, packet, 6);
}
static void build_data_packet() {
uint8_t ail_sign = 0, trim_sign = 0;
throttle = (uint32_t)Servo_data[THROTTLE] * 50 / PPM_MAX + 50;
throttle = (uint32_t)map(limit_channel_100(THROTTLE),servo_min_100,servo_max_100,0,100);
if (throttle < 0) { throttle = 0; }
aileron = (uint32_t)Servo_data[AILERON] * 8 / PPM_MAX;
aileron = (uint32_t)map(limit_channel_100(AILERON),servo_min_100,servo_max_100,-8,8);
if (aileron < 0) { aileron = -aileron; ail_sign = 1; }
if (aileron > 7) { aileron = 7; }
uint8_t turbo = (uint32_t)Servo_data[ELEVATOR] > 0 ? 1 : 0;
uint8_t turbo = Servo_data[ELEVATOR] > PPM_SWITCH ? 1 : 0;
uint8_t trim = ((uint32_t)Servo_data[RUDDER] * 0x1f / PPM_MAX);
uint8_t trim = map(limit_channel_100(RUDDER),servo_min_100,servo_max_100,-31,31);
if (trim < 0) { trim = -trim; trim_sign = 1; }
if (trim > 0x1f) { trim = 0x1f; }
uint8_t rbutton = (uint32_t)Servo_data[4] > 0 ? 1 : 0;
uint8_t rbutton = Servo_data[4] > PPM_SWITCH ? 1 : 0;
packet[0] = throttle;
packet[1] = aileron;
if (ail_sign) { packet[1] |= 0x20; }
@ -141,7 +141,7 @@ static void build_data_packet() {
if (rbutton) { packet[1] |= 0x80; }
packet[5] = trim;
if (trim_sign) { packet[5] |= 0x20;}
packet[6] = crc8(0xa5, packet, 6);
packet[6] = HM830_crc8(0xa5, packet, 6);
}
static void send_packet_hm830() {

View File

@ -1,272 +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.
Deviation is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Deviation. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(HonTai_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define BIND_HT_COUNT 80
#define PACKET_HT_PERIOD 13500 // Timeout for callback in uSec
//printf inside an interrupt handler is really dangerous
//this shouldn't be enabled even in debug builds without explicitly
//turning it on
#define dbgprintf if(0) printf
#define INITIAL_HT_WAIT 500
#define BIND_HT_PACKET_SIZE 10
#define PACKET_HT_SIZE 12
#define RF_BIND_HT_CHANNEL 0
enum {
FORMAT_HONTAI = 0,
FORMAT_JJRCX1,
};
#define CHANNEL_LED AUX1
#define CHANNEL_ARM AUX1 // for JJRC X1
#define CHANNEL_FLIP AUX2
#define CHANNEL_PICTURE AUX3
#define CHANNEL_VIDEO AUX4
#define CHANNEL_HEADLESS AUX5
#define CHANNEL_RTH AUX6
#define CHANNEL_CALIBRATE AUX7
enum {
HonTai_INIT1 = 0,
HonTai_BIND2,
HonTai_DATA
};
static uint8_t ht_txid[5];
static uint8_t rf_chan = 0;
static uint8_t rf_channels[][3] = {{0x05, 0x19, 0x28}, // Hontai
{0x0a, 0x1e, 0x2d}}; // JJRC X1
static uint8_t rx_tx_ht_addr[] = {0xd2, 0xb5, 0x99, 0xb3, 0x4a};
static uint8_t addr_vals[4][16] = {
{0x24, 0x26, 0x2a, 0x2c, 0x32, 0x34, 0x36, 0x4a, 0x4c, 0x4e, 0x54, 0x56, 0x5a, 0x64, 0x66, 0x6a},
{0x92, 0x94, 0x96, 0x9a, 0xa4, 0xa6, 0xac, 0xb2, 0xb4, 0xb6, 0xca, 0xcc, 0xd2, 0xd4, 0xd6, 0xda},
{0x93, 0x95, 0x99, 0x9b, 0xa5, 0xa9, 0xab, 0xad, 0xb3, 0xb5, 0xc9, 0xcb, 0xcd, 0xd3, 0xd5, 0xd9},
{0x25, 0x29, 0x2b, 0x2d, 0x33, 0x35, 0x49, 0x4b, 0x4d, 0x59, 0x5b, 0x65, 0x69, 0x6b, 0x6d, 0x6e}};
// proudly swiped from http://www.drdobbs.com/implementing-the-ccitt-cyclical-redundan/199904926
#define POLY 0x8408
static uint16_t crc16(uint8_t *data_p, uint32_t length)
{
uint8_t i;
uint32_t data;
uint32_t crc;
crc = 0xffff;
if (length == 0) return (~crc);
length -= 2;
do {
for (i = 0, data = (uint8_t)0xff & *data_p++;
i < 8;
i++, data >>= 1) {
if ((crc & 0x0001) ^ (data & 0x0001))
crc = (crc >> 1) ^ POLY;
else
crc >>= 1;
}
} while (--length);
crc = ~crc;
data = crc;
crc = (crc << 8) | (data >> 8 & 0xFF);
*data_p++ = crc >> 8;
*data_p = crc & 0xff;
return crc;
}
#define CHAN_RANGE (PPM_MAX - PPM_MIN)
static uint8_t scale_HT_channel(uint8_t ch, uint8_t start, uint8_t end)
{
uint32_t range = end - start;
uint32_t chanval = Servo_data[ch];
if (chanval < PPM_MIN) chanval = PPM_MIN;
else if (chanval > PPM_MAX) chanval = PPM_MAX;
uint32_t round = range < 0 ? 0 : CHAN_RANGE / range; // channels round up
if (start < 0) round = CHAN_RANGE / range / 2; // trims zero centered around zero
return (range * (chanval - PPM_MIN + round)) / CHAN_RANGE + start;
}
#define GET_FLAG(ch, mask) (Servo_data[ch] > 0 ? mask : 0)
static void send_HT_packet(uint8_t bind)
{
if (bind) {
memcpy(packet, ht_txid, 5);
memset(&packet[5], 0, 3);
} else {
if (sub_protocol == FORMAT_HONTAI) {
packet[0] = 0x0b;
} else {
packet[0] = GET_FLAG(CHANNEL_ARM, 0x02);
}
packet[1] = 0x00;
packet[2] = 0x00;
packet[3] = (scale_HT_channel(THROTTLE, 0, 127) << 1) // throttle
| GET_FLAG(CHANNEL_PICTURE, 0x01);
packet[4] = scale_HT_channel(AILERON, 63, 0); // aileron
if (sub_protocol == FORMAT_HONTAI) {
packet[4] |= GET_FLAG(CHANNEL_RTH, 0x80)
| GET_FLAG(CHANNEL_HEADLESS, 0x40);
} else {
packet[4] |= 0x80; // not sure what this bit does
}
packet[5] = scale_channel(CHANNEL2, 0, 63) // elevator
| GET_FLAG(CHANNEL_CALIBRATE, 0x80)
| GET_FLAG(CHANNEL_FLIP, 0x40);
packet[6] = scale_HT_channel(RUDDER, 0, 63) // rudder
| GET_FLAG(CHANNEL_VIDEO, 0x80);
packet[7] = scale_HT_channel(AILERON, -16, 16); // aileron trim
if (sub_protocol == FORMAT_HONTAI) {
packet[8] = scale_HT_channel(RUDDER, -16, 16); // rudder trim
} else {
packet[8] = 0xc0 // always in expert mode
| GET_FLAG(CHANNEL_RTH, 0x02)
| GET_FLAG(CHANNEL_HEADLESS, 0x01);
}
packet[9] = scale_HT_channel(ELEVATOR, -16, 16); // elevator trim
}
crc16(packet, bind ? BIND_HT_PACKET_SIZE : PACKET_HT_SIZE);
// Power on, TX mode, 2byte CRC
if (sub_protocol == FORMAT_HONTAI) {
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP));
} else {
NRF24L01_SetTxRxMode(TX_EN);
}
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? RF_BIND_HT_CHANNEL : rf_channels[sub_protocol][rf_chan++]);
rf_chan %= sizeof(rf_channels);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
if (sub_protocol == FORMAT_HONTAI) {
XN297_WritePayload(packet, bind ? BIND_HT_PACKET_SIZE : PACKET_HT_SIZE);
} else {
NRF24L01_WritePayload(packet, bind ? BIND_HT_PACKET_SIZE : PACKET_HT_SIZE);
}
NRF24L01_SetPower();
}
static void ht_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
// SPI trace of stock TX has these writes to registers that don't appear in
// nRF24L01 or Beken 2421 datasheets. Uncomment if you have an XN297 chip?
// NRF24L01_WriteRegisterMulti(0x3f, "\x4c\x84\x67,\x9c,\x20", 5);
// NRF24L01_WriteRegisterMulti(0x3e, "\xc9\x9a\xb0,\x61,\xbb,\xab,\x9c", 7);
// NRF24L01_WriteRegisterMulti(0x39, "\x0b\xdf\xc4,\xa7,\x03,\xab,\x9c", 7);
if (sub_protocol == FORMAT_HONTAI) {
XN297_SetTXAddr(rx_tx_ht_addr, sizeof(rx_tx_ht_addr));
} else {
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_ht_addr, sizeof(rx_tx_ht_addr));
}
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
if (sub_protocol == FORMAT_HONTAI) {
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00);
NRF24L01_Activate(0x73); // Deactivate feature register
} else {
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xff); // JJRC uses dynamic payload length
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // match other stock settings even though AA disabled...
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
}
}
static void ht_init2()
{
uint8_t data_tx_addr[] = {0x2a, 0xda, 0xa5, 0x25, 0x24};
data_tx_addr[0] = addr_vals[0][ ht_txid[3] & 0x0f];
data_tx_addr[1] = addr_vals[1][(ht_txid[3] >> 4) & 0x0f];
data_tx_addr[2] = addr_vals[2][ ht_txid[4] & 0x0f];
data_tx_addr[3] = addr_vals[3][(ht_txid[4] >> 4) & 0x0f];
if (sub_protocol == FORMAT_HONTAI) {
XN297_SetTXAddr(data_tx_addr, sizeof(data_tx_addr));
} else {
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, data_tx_addr, sizeof(data_tx_addr));
}
}
static uint16_t ht_callback()
{
switch (phase) {
case HonTai_INIT1:
phase = HonTai_BIND2;
break;
case HonTai_BIND2:
if (counter == 0) {
ht_init2();
phase = HonTai_DATA;
BIND_DONE;
} else {
send_HT_packet(1);
counter -= 1;
}
break;
case HonTai_DATA:
send_HT_packet(0);
break;
}
return PACKET_HT_PERIOD;
}
static uint16_t ht_setup()
{
counter = BIND_HT_COUNT;
if (sub_protocol == FORMAT_HONTAI) {
ht_txid[0] = 0x4c; // first three bytes some kind of model id? - set same as stock tx
ht_txid[1] = 0x4b;
ht_txid[2] = 0x3a;
} else {
ht_txid[0] = 0x4b; // JJRC X1
ht_txid[1] = 0x59;
ht_txid[2] = 0x3a;
}
ht_txid[3] = (MProtocol_id >> 8 ) & 0xff;
ht_txid[4] = MProtocol_id & 0xff;
ht_init();
phase = HonTai_INIT1;
return INITIAL_HT_WAIT;
}
#endif

View File

@ -0,0 +1,733 @@
/***
* iNav Protocol
*
* Data rate is 250Kbps - lower data rate for better reliability and range
*
* Uses auto acknowledgment and dynamic payload size
* ACK payload is used for handshaking in bind phase and telemetry in data phase
*
* Bind payload size is 16 bytes
* Data payload size is 16 bytes dependent on variant of protocol, (small payload is read more quickly (marginal benefit))
*
* Bind and data payloads are whitened (XORed with a pseudo-random bitstream) to remove strings of 0s or 1s in transmission
* packet. This improves reception by helping keep the TX and RX clocks in sync.
*
* Bind Phase
* uses address {0x4b,0x5c,0x6d,0x7e,0x8f}
* uses channel 0x4c (76)
*
* Data Phase
* 1) Uses the address received in bind packet
*
* 2) Hops between RF channels generated from the address received in bind packet.
* The number of RF hopping channels is set during bind handshaking:
* the transmitter requests a number of hopping channels in payload[7]
* the receiver sets ackPayload[7] with the number of hopping channels actually allocated - the transmitter must
* use this value.
*
* 3) There are 16 channels: eight 10-bit analog channels, two 8-bit analog channels, and six digital channels as follows:
* Channels 0 to 3, are the AETR channels, values 1000 to 2000 with resolution of 1 (10-bit channels)
* Channel AUX1 by deviation convention is used for rate, values 1000, 1500, 2000
* Channels AUX2 to AUX6 are binary channels, values 1000 or 2000,
* by deviation convention these channels are used for: flip, picture, video, headless, and return to home
* Channels AUX7 to AUX10 are analog channels, values 1000 to 2000 with resolution of 1 (10-bit channels)
* Channels AUX11 and AUX12 are analog channels, values 1000 to 2000 with resolution of 4 (8-bit channels)
***/
// debug build flags
//#define NO_RF_CHANNEL_HOPPING
#define USE_AUTO_ACKKNOWLEDGEMENT
#define USE_WHITENING
#define INAV_TELEMETRY
//#define INAV_TELEMETRY_DEBUG
#define UNUSED(x) (void)(x)
#ifdef INAV_NRF24L01_INO
static uint8_t INAV_setup() { return 1000; }
static uint16_t inav_cb() {}
#endif
#if 0
/*
*/
#include "iface_nrf24l01.h"
#define BIND_COUNT 345 // 1.5 seconds
#define FIRST_PACKET_DELAY 12000
#define PACKET_PERIOD 4000 // Timeout for callback in uSec
#define INITIAL_WAIT 500
// For code readability
enum {
CHANNEL1 = 0,
CHANNEL2,
CHANNEL3,
CHANNEL4,
CHANNEL5,
CHANNEL6,
CHANNEL7,
CHANNEL8,
CHANNEL9,
CHANNEL10,
CHANNEL11,
CHANNEL12,
CHANNEL13,
CHANNEL14,
CHANNEL15,
CHANNEL16,
};
// Deviation transmitter channels
#define DEVIATION_CHANNEL_COUNT 12 // Max supported by Devo 7e
//#define CHANNEL_LED CHANNEL5
#define CHANNEL_RATE CHANNEL5
#define CHANNEL_FLIP CHANNEL6
#define CHANNEL_PICTURE CHANNEL7
#define CHANNEL_VIDEO CHANNEL8
#define CHANNEL_HEADLESS CHANNEL9
#define CHANNEL_RTH CHANNEL10
#define CHANNEL_XCAL CHANNEL11
#define CHANNEL_YCAL CHANNEL12
// #define GET_FLAG(ch, mask) (Channels[ch] > 0 ? mask : 0)
enum {
RATE_LOW = 0,
RATE_MID = 1,
RATE_HIGH = 2,
};
enum {
FLAG_FLIP = 0x01,
FLAG_PICTURE = 0x02,
FLAG_VIDEO = 0x04,
FLAG_RTH = 0x08,
FLAG_HEADLESS = 0x10,
};
typedef enum {
PHASE_INAV_INIT = 0,
PHASE_INAV_BIND,
PHASE_INAV_DATA
};
typedef enum {
DATA_PACKET = 0,
BIND_PACKET = 1,
};
static const char * const inav_opts[] = {
#ifdef INAV_TELEMETRY
_tr_noop("Telemetry"), _tr_noop("On"), _tr_noop("Off"), NULL,
#endif
"RxTx Addr1", "-32768", "32767", "1", NULL, // todo: store that elsewhere
"RxTx Addr2", "-32768", "32767", "1", NULL, // ^^^^^^^^^^^^^^^^^^^^^^^^^^
NULL
};
enum {
#ifdef INAV_TELEMETRY
PROTOOPTS_TELEMETRY,
#endif
PROTOOPTS_RX_TX_ADDR1, // todo: store that elsewhere
PROTOOPTS_RX_TX_ADDR2, // ^^^^^^^^^^^^^^^^^^^^^^^^^^
LAST_PROTO_OPT
};
enum {
OPTS_6_CHANNELS = 0,
OPTS_12_CHANNELS
};
enum {
TELEM_ON = 0,
TELEM_OFF,
};
// Bit vector from bit position
#define BV(bit) (1 << bit)
// Bit position mnemonics
enum {
NRF24L01_1D_EN_DYN_ACK = 0,
NRF24L01_1D_EN_ACK_PAY = 1,
NRF24L01_1D_EN_DPL = 2,
};
// Pre-shifted and combined bits
enum {
NRF24L01_03_SETUP_AW_5BYTES = 0x03,
};
enum {
NRF24L01_MAX_PAYLOAD_SIZE = 32,
};
#define INAV_PROTOCOL_PAYLOAD_SIZE_MIN 8
#define INAV_PROTOCOL_PAYLOAD_SIZE_DEFAULT 16
#define INAV_PROTOCOL_PAYLOAD_SIZE_MAX 16
static uint32_t lost_packet_counter;
#define RC_CHANNEL_COUNT_MIN 6
#define RC_CHANNEL_COUNT_DEFAULT 16
#define RC_CHANNEL_COUNT_MAX 18
static uint8_t rc_channel_count;
static uint8_t tx_power;
#define RX_TX_ADDR_LEN 5
static const uint8_t rx_tx_addr_bind[RX_TX_ADDR_LEN] = {0x4b,0x5c,0x6d,0x7e,0x8f};
static uint8_t rx_tx_addr[RX_TX_ADDR_LEN];
#define RX_TX_ADDR_4 0xD2 // rxTxAddr[4] always set to this value
#define BIND_PAYLOAD0 0xad // 10101101
#define BIND_PAYLOAD1 0xc9 // 11001001
#define BIND_ACK_PAYLOAD0 0x95 // 10010101
#define BIND_ACK_PAYLOAD1 0xa9 // 10101001
#define TELEMETRY_ACK_PAYLOAD0 0x5a // 01011010
// TELEMETRY_ACK_PAYLOAD1 is sequence count
#define DATA_PAYLOAD0 0x00
#define DATA_PAYLOAD1 0x00
#ifdef USE_AUTO_ACKKNOWLEDGEMENT
static uint8_t ackPayloadSize;
static uint8_t ackPayload[NRF24L01_MAX_PAYLOAD_SIZE];
#endif
// frequency channel management
#define RF_CHANNEL_COUNT_DEFAULT 4
#define RF_CHANNEL_COUNT_MAX 4
#define RF_CHANNEL_BIND 0x4c
static uint8_t rf_channel_index;
static uint8_t rf_channels[RF_CHANNEL_COUNT_MAX];
static uint8_t rf_channel_count;
static protocol_phase_t phase;
#ifndef TELEM_LTM
// use DSM telemetry until LTM telemetry is implemented
#define TELEM_LTM TELEM_DSM
// repurpose the DSM FADESL, FADESR and HOLDS fields to display roll, pitch and yaw
#define TELEM_LTM_ATTITUDE_PITCH TELEM_DSM_FLOG_FADESL
#define TELEM_LTM_ATTITUDE_ROLL TELEM_DSM_FLOG_FADESR
#define TELEM_LTM_ATTITUDE_YAW TELEM_DSM_FLOG_HOLDS
// use DSM VOLT2, AMPS1 and AIRSPEED fields
#define TELEM_LTM_STATUS_VBAT TELEM_DSM_FLOG_VOLT2
#define TELEM_LTM_STATUS_CURRENT TELEM_DSM_AMPS1
#define TELEM_LTM_STATUS_RSSI TELEM_DSM_FLOG_FRAMELOSS
#define TELEM_LTM_STATUS_AIRSPEED TELEM_DSM_AIRSPEED
/*
currently unused LTM telemetry fields
TELEM_LTM_STATUS_ARMED
TELEM_LTM_STATUS_FAILSAFE
TELEM_LTM_STATUS_FLIGHTMODE
TELEM_LTM_NAVIGATION_GPS_MODE
TELEM_LTM_NAVIGATION_NAV_MODE
TELEM_LTM_NAVIGATION_ACTION
TELEM_LTM_NAVIGATION_WAYPOINT_NUMBER
TELEM_LTM_NAVIGATION_ERROR
TELEM_LTM_NAVIGATION_FLAGS
TELEM_LTM_GPSX_HDOP
TELEM_LTM_TUNING_P_ROLL
TELEM_LTM_TUNING_I_ROLL
TELEM_LTM_TUNING_D_ROLL
TELEM_LTM_TUNING_P_PITCH
TELEM_LTM_TUNING_I_PITCH
TELEM_LTM_TUNING_D_PITCH
TELEM_LTM_TUNING_P_YAW
TELEM_LTM_TUNING_I_YAW
TELEM_LTM_TUNING_D_YAW
TELEM_LTM_TUNING_RATES_ROLL
TELEM_LTM_TUNING_RATES_PITCH
TELEM_LTM_TUNING_RATES_YAW
*/
#endif
/*
uint8_t convert_channel_8b(uint8_t channel)
{
return (uint8_t)(convert_channel(channel) >> 2);
}
*/
static void whiten_payload(uint8_t *payload, uint8_t len)
{
#ifdef USE_WHITENING
uint8_t whitenCoeff = 0x6b; // 01101011
while (len--) {
for (uint8_t m = 1; m; m <<= 1) {
if (whitenCoeff & 0x80) {
whitenCoeff ^= 0x11;
(*payload) ^= m;
}
whitenCoeff <<= 1;
}
payload++;
}
#else
UNUSED(payload);
UNUSED(len);
#endif
}
static void build_bind_packet(void)
{
memset(packet, 0, INAV_PROTOCOL_PAYLOAD_SIZE_MAX);
packet[0] = BIND_PAYLOAD0;
packet[1] = BIND_PAYLOAD1;
packet[2] = rx_tx_addr[0];
packet[3] = rx_tx_addr[1];
packet[4] = rx_tx_addr[2];
packet[5] = rx_tx_addr[3];
packet[6] = rx_tx_addr[4];
packet[7] = rf_channel_count;
packet[8] = packet_length;
packet[9] = rc_channel_count;
}
static void build_data_packet(void)
{
packet[0] = 0;
packet[1] = 0;
// AETR channels have 10 bit resolution
const uint16_t aileron = convert_channel_10b(AILERON);
const uint16_t elevator = convert_channel_10b(ELEVATOR);
const uint16_t throttle = convert_channel_10b(THROTTLE);
const uint16_t rudder = convert_channel_10b(RUDDER);
packet[2] = aileron >> 2;
packet[3] = elevator >> 2;
packet[4] = throttle >> 2;
packet[5] = rudder >> 2;
// pack the AETR low bits
packet[6] = (aileron & 0x03) | ((elevator & 0x03) << 2) | ((throttle & 0x03) << 4) | ((rudder & 0x03) << 6);
uint8_t rate = RATE_LOW;
if (Channels[CHANNEL_RATE] > 0) {
rate = RATE_HIGH;
} else if (Channels[CHANNEL_RATE] == 0) {
rate = RATE_MID;
}
packet[7] = rate; // rate, deviation channel 5, is mapped to AUX1
const uint8_t flags = GET_FLAG(CHANNEL_FLIP, FLAG_FLIP)
| GET_FLAG(CHANNEL_PICTURE, FLAG_PICTURE)
| GET_FLAG(CHANNEL_VIDEO, FLAG_VIDEO)
| GET_FLAG(CHANNEL_RTH, FLAG_RTH)
| GET_FLAG(CHANNEL_HEADLESS, FLAG_HEADLESS);
packet[8] = flags; // flags, deviation channels 6-10 are mapped to AUX2 t0 AUX6
// map deviation channels 9-12 to RC channels AUX7-AUX10, use 10 bit resolution
// deviation CHANNEL9 (headless) and CHANNEL10 (RTH) are mapped for a second time
// duplicate mapping makes maximum use of deviation's 12 channels
const uint16_t channel9 = convert_channel_10b(CHANNEL9);
const uint16_t channel10 = convert_channel_10b(CHANNEL10);
const uint16_t channel11 = convert_channel_10b(CHANNEL11);
const uint16_t channel12 = convert_channel_10b(CHANNEL12);
packet[9] = channel9 >> 2;
packet[10] = channel10 >> 2;
packet[11] = channel11 >> 2;
packet[12] = channel12 >> 2;
packet[13] = (channel9 & 0x03) | ((channel10 & 0x03) << 2) | ((channel11 & 0x03) << 4) | ((channel12 & 0x03) << 6);
// map deviation channels 7 and 8 to RC channels AUX11 and AUX12, use 10 bit resolution
// deviation channels 7 (picture) and 8 (video) are mapped for a second time
packet[14] = convert_channel_8b(CHANNEL7);
packet[15] = convert_channel_8b(CHANNEL8);
}
static uint8_t packet_ack(void)
{
#ifdef USE_AUTO_ACKKNOWLEDGEMENT
const uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
if (status & BV(NRF24L01_07_TX_DS)) { // NRF24L01_07_TX_DS asserted when ack payload received
// ack payload recieved
ackPayloadSize = NRF24L01_GetDynamicPayloadSize();
if (ackPayloadSize > NRF24L01_MAX_PAYLOAD_SIZE) {
ackPayloadSize = 0;
NRF24L01_FlushRx();
return PKT_PENDING;
}
NRF24L01_ReadPayload(ackPayload, ackPayloadSize);
whiten_payload(ackPayload, ackPayloadSize);
NRF24L01_WriteReg(NRF24L01_07_STATUS, BV(NRF24L01_07_TX_DS)); // clear TX_DS interrupt
return PKT_ACKED;
}
if (status & BV(NRF24L01_07_MAX_RT)) {
// max retries exceeded
// clear MAX_RT interrupt to allow further transmission
NRF24L01_WriteReg(NRF24L01_07_STATUS, BV(NRF24L01_07_MAX_RT));
NRF24L01_FlushTx(); // payload wasn't successfully transmitted, so remove it from TX FIFO
return PKT_TIMEOUT;
}
return PKT_PENDING;
#else
return PKT_TIMEOUT; // if not using AUTO ACK just return a timeout
#endif
}
void transmit_packet(void)
{
// clear packet MAX_RT status bit so that transmission is not blocked
NRF24L01_WriteReg(NRF24L01_07_STATUS, BV(NRF24L01_07_MAX_RT));
// set NRF24L01_00_MASK_TX_DS and clear NRF24L01_00_PRIM_RX to initiate transmit
// NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_PWR_UP) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_MASK_TX_DS) | BV(NRF24L01_00_MASK_MAX_RT));
whiten_payload(packet, packet_length);
NRF24L01_WritePayload(packet, packet_length);// asynchronous call
}
static void hop_to_next_channel(void)
{
#ifndef NO_RF_CHANNEL_HOPPING
if (phase == PHASE_INAV_BIND) {
return;
}
++rf_channel_index;
if (rf_channel_index >= rf_channel_count) {
rf_channel_index = 0;
}
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_channels[rf_channel_index]);
#endif
}
static void send_packet(uint8_t packet_type)
{
if (packet_type == DATA_PACKET) {
build_data_packet();
} else {
build_bind_packet();
}
transmit_packet();
hop_to_next_channel();
++packet_count;
// Check and adjust transmission power. We do this after
// transmission to not bother with timeout after power
// settings change - we have plenty of time until next
// packet.
if (tx_power != Model.tx_power) {
//Keep transmit power updated
tx_power = Model.tx_power;
NRF24L01_SetPower(tx_power);
}
}
static void set_data_phase(void)
{
packet_count = 0;
lost_packet_counter = 0;
phase = PHASE_INAV_DATA;
rf_channel_index = 0;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_channels[0]);
// RX_ADDR_P0 must equal TX_ADDR for auto ACK
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, RX_TX_ADDR_LEN);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, RX_TX_ADDR_LEN);
}
static void init_nrf24l01(void)
{
NRF24L01_Initialize();
// sets PWR_UP, EN_CRC, CRCO - 2 byte CRC
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_PWR_UP) | BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
#ifdef USE_AUTO_ACKKNOWLEDGEMENT
// Note that for some cheap NFR24L01 clones the NO_ACK bit in the packet control field is inverted,
// see https://ncrmnt.org/2015/03/13/how-do-i-cost-optimize-nrf24l01/
// (see section 7.3.3, p28 of nRF24L01+ Product Specification for descripton of packet control field).
// This means AUTO_ACK will no work between them and genuine NRF24L01 modules, although AUTO_ACK
// between these clones should work.
NRF24L01_WriteReg(NRF24L01_01_EN_AA, BV(NRF24L01_01_ENAA_P0)); // auto acknowledgment on P0
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, BV(NRF24L01_02_ERX_P0)); // Enable RX on P0 for Auto Ack
#else
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00);
#endif
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, NRF24L01_03_SETUP_AW_5BYTES); // 5-byte RX/TX address
// ARD of 1500us is minimum required for 32 byte ACK payload in 250kbps mode (section 7.4.2, p33 of nRF24L01+ Product Specification)
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, NRF24L01_04_ARD_2500us | NRF24L01_04_ARC_1); // 1 retry after 1500us
NRF24L01_WriteReg(NRF24L01_05_RF_CH, RF_CHANNEL_BIND);
// bitrate and power are set using regigister NRF24L01_06_RF_SETUP
NRF24L01_SetBitrate(NRF24L01_BR_250K);
NRF24L01_SetPower(Model.tx_power);
// Writing to the STATUS register clears the specified interrupt bits
NRF24L01_WriteReg(NRF24L01_07_STATUS, BV(NRF24L01_07_RX_DR) | BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT));
// NRF24L01_08_OBSERVE_TX is read only register
// NRF24L01_09_RPD is read only register (called RPD for NRF24L01+, CD for NRF24L01)
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr_bind, RX_TX_ADDR_LEN); // RX_ADDR_P0 must equal TX_ADDR for auto ACK
// RX_ADDR for pipes P1-P5 (registers 0B to 0F) aret left at default values
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr_bind, RX_TX_ADDR_LEN);
// Payload Widths for P0-P5 (registers 11 to 16) aret left at default values
// NRF24L01_17_FIFO_STATUS is read only register for all non-reserved bits
// No registers with values 18 to 1B
#ifdef USE_AUTO_ACKKNOWLEDGEMENT
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
NRF24L01_Activate(0x73); // Activate feature register, needed for NRF24L01 (harmless for NRF24L01+)
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, BV(NRF24L01_1C_DYNPD_P0)); // dynamic payload length on pipes P0
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, BV(NRF24L01_1D_EN_ACK_PAY) | BV(NRF24L01_1D_EN_DPL));
#endif
NRF24L01_Activate(0x53); // switch bank back
NRF24L01_SetTxRxMode(TX_EN); // enter transmit mode, sets up NRF24L01_00_CONFIG register
}
// Generate address to use from TX id and manufacturer id (STM32 unique id)
static void initialize_rx_tx_addr(void)
{
uint32_t lfsr = 0xb2c54a2ful;
#ifndef USE_FIXED_MFGID
uint8_t var[12];
MCU_SerialNumber(var, 12);
for (int i = 0; i < 12; ++i) {
rand32_r(&lfsr, var[i]);
}
#endif
if (Model.fixed_id) {
for (uint8_t i = 0, j = 0; i < sizeof(Model.fixed_id); ++i, j += 8)
rand32_r(&lfsr, (Model.fixed_id >> j) & 0xff);
}
// Pump zero bytes for LFSR to diverge more
for (uint8_t i = 0; i < sizeof(lfsr); ++i) rand32_r(&lfsr, 0);
for (uint8_t i = 0; i < sizeof(rx_tx_addr)-1; ++i) {
rx_tx_addr[i] = lfsr & 0xff;
rand32_r(&lfsr, i);
}
rx_tx_addr[1] &= 0x7f; // clear top bit so saved Model.proto_opts value is positive
rx_tx_addr[3] &= 0x7f; // clear top bit so saved Model.proto_opts value is positive
rx_tx_addr[4] = RX_TX_ADDR_4; // set to constant, so variable part of rx_tx_addr can be stored in 32-bit value
}
// The hopping channels are determined by the value of rx_tx_addr[0]
static void set_hopping_channels(void)
{
rf_channel_index = 0;
const uint8_t addr = rx_tx_addr[0];
uint8_t ch = 0x10 + (addr & 0x07);
for (int i = 0; i < rf_channel_count; ++i) {
rf_channels[i] = ch;
ch += 0x0c;
}
}
static void update_telemetry(void)
{
#ifdef INAV_TELEMETRY
const uint8_t observeTx = NRF24L01_ReadReg(NRF24L01_08_OBSERVE_TX);
const uint8_t lostPacketCount = (observeTx & NRF24L01_08_PLOS_CNT_MASK) >> 4;
// const uint8_t autoRetryCount = observeTx & NRF24L01_08_ARC_CNT_MASK;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_channels[rf_channel_index]); // reset packet loss counter
lost_packet_counter += lostPacketCount;
Telemetry.value[TELEM_LTM_STATUS_RSSI] = 100 - 100 * lost_packet_counter / packet_count;
TELEMETRY_SetUpdated(TELEM_LTM_STATUS_RSSI);
// ackPayload contains telemetry in LTM format.
// See https://github.com/stronnag/mwptools/blob/master/docs/ltm-definition.txt
// ackPayload[0] is a sequence count, LTM begins at ackPayload[2]
const uint8_t *ltm = &ackPayload[2];
switch (ltm[0]) { // frame type
case 'G': // GPS frame
{
// LTM lat/long: int32 decimal degrees * 10,000,000 (1E7)
// LTM 1 degree = 1,000,000
// Deviation longitude: +/-180degrees = +/- 180*60*60*1000; W if value<0, E if value>=0; -180degrees = 180degrees
// Deviation latitude: +/-90degrees = +/- 90*60*60*1000; S if value<0, N if value>=0
// Deviation 1 degree = 3,600,000
// Scale factor = 36/10 = 18/5
uint32_t latitude;
memcpy(&latitude, &ltm[1], sizeof(uint32_t));
Telemetry.gps.latitude = latitude * 18 / 5;
TELEMETRY_SetUpdated(TELEM_GPS_LAT);
uint32_t longitude;
memcpy(&longitude, &ltm[5], sizeof(uint32_t));
Telemetry.gps.longitude = longitude * 18 / 5;
TELEMETRY_SetUpdated(TELEM_GPS_LONG);
Telemetry.gps.velocity = ltm[9] * 1000; // LTM m/s; DEV mm/s
TELEMETRY_SetUpdated(TELEM_GPS_SPEED);
uint32_t altitude;
memcpy(&altitude, &ltm[10], sizeof(uint32_t));
Telemetry.gps.altitude = altitude * 10; // LTM:cm; DEV:mm
TELEMETRY_SetUpdated(TELEM_GPS_ALT);
Telemetry.gps.satcount = ltm[14] >> 2;
TELEMETRY_SetUpdated(TELEM_GPS_SATCOUNT);
}
break;
case 'A': // Attitude frame
{
const uint16_t heading = ltm[5] | (ltm[6] << 8);
Telemetry.gps.heading = heading;
TELEMETRY_SetUpdated(TELEM_GPS_HEADING);
const s16 pitch = ltm[1] | (ltm[2] << 8);
Telemetry.value[TELEM_LTM_ATTITUDE_PITCH] = pitch; // LTM:degrees [-180,180]
TELEMETRY_SetUpdated(TELEM_LTM_ATTITUDE_PITCH);
const s16 roll = ltm[3] | (ltm[4] << 8);
Telemetry.value[TELEM_LTM_ATTITUDE_ROLL] = roll; // LTM:degrees [-180,180]
TELEMETRY_SetUpdated(TELEM_LTM_ATTITUDE_ROLL);
Telemetry.value[TELEM_LTM_ATTITUDE_YAW] = heading;
TELEMETRY_SetUpdated(TELEM_LTM_ATTITUDE_YAW);
}
break;
case 'S': // Status frame
{
const uint16_t vBat = ltm[1] | (ltm[2] << 8);
Telemetry.value[TELEM_LTM_STATUS_VBAT] = (uint32_t)(vBat); // LTM:mV; DEV:V/10
TELEMETRY_SetUpdated(TELEM_LTM_STATUS_VBAT);
const uint16_t amps = ltm[3] | (ltm[4] << 8);
Telemetry.value[TELEM_LTM_STATUS_CURRENT] = (uint32_t)(amps); // LTM:mA; DEV:A/10
TELEMETRY_SetUpdated(TELEM_LTM_STATUS_CURRENT);
Telemetry.value[TELEM_LTM_STATUS_AIRSPEED] = ltm[6];
TELEMETRY_SetUpdated(TELEM_LTM_STATUS_AIRSPEED);
}
break;
default:
break;
}
#endif
}
void save_rx_tx_addr(void)
{
Model.proto_opts[PROTOOPTS_RX_TX_ADDR1] = rx_tx_addr[0] | ((uint16_t)rx_tx_addr[1] << 8);
Model.proto_opts[PROTOOPTS_RX_TX_ADDR2] = rx_tx_addr[2] | ((uint16_t)rx_tx_addr[3] << 8);
}
void load_rx_tx_addr(void)
{
rx_tx_addr[0] = (Model.proto_opts[PROTOOPTS_RX_TX_ADDR1]) & 0xff;
rx_tx_addr[1] = (Model.proto_opts[PROTOOPTS_RX_TX_ADDR1] >> 8) & 0xff;
rx_tx_addr[2] = (Model.proto_opts[PROTOOPTS_RX_TX_ADDR2]) & 0xff;
rx_tx_addr[3] = (Model.proto_opts[PROTOOPTS_RX_TX_ADDR2] >> 8) & 0xff;
rx_tx_addr[4] = RX_TX_ADDR_4; // set to constant, so variable part of rx_tx_addr can be stored in 32-bit value
}
static void inav_init()
{
// check options before proceeding with initialiasation
packet_length = INAV_PROTOCOL_PAYLOAD_SIZE_DEFAULT;
rc_channel_count = RC_CHANNEL_COUNT_DEFAULT;
rf_channel_count = RF_CHANNEL_COUNT_DEFAULT;
if(IS_AUTOBIND_FLAG_on) {
initialize_rx_tx_addr();
save_rx_tx_addr();
} else {
load_rx_tx_addr();
}
packet_count = 0;
set_hopping_channels();
}
static uint16_t inav_cb()
{
static uint16_t bind_counter;
static uint8_t bind_acked;
switch (phase) {
case PHASE_INAV_INIT:
phase = PHASE_INAV_BIND;
bind_counter = BIND_COUNT;
bind_acked = 0;
return FIRST_PACKET_DELAY;
break;
case PHASE_INAV_BIND:
if (bind_counter == 0) {
set_data_phase();
BIND_DONE;
} else {
if (packet_ack() == PKT_ACKED) {
bind_acked = 1;
}
if (bind_acked == 1) {
// bind packet acked, so set bind_counter to zero to enter data phase on next callback
bind_counter = 0;
return PACKET_PERIOD;
}
send_packet(BIND_PACKET);
--bind_counter;
}
break;
case PHASE_INAV_DATA:
update_telemetry();
/*#define PACKET_CHKTIME 500 // time to wait if packet not yet acknowledged or timed out
if (packet_ack() == PKT_PENDING) {
return PACKET_CHKTIME; // packet send not yet complete
}*/
packet_ack();
send_packet(DATA_PACKET);
break;
}
return PACKET_PERIOD;
}
static uint8_t INAV_setup()
{
CLOCK_StopTimer();
tx_power = Model.tx_power;
ackPayloadSize = 0;
memset(ackPayload, 0, NRF24L01_MAX_PAYLOAD_SIZE);
inav_init(bind);
init_nrf24l01();
#ifdef INAV_TELEMETRY
memset(&Telemetry, 0, sizeof(Telemetry));
TELEMETRY_SetType(TELEM_LTM);
#endif
if(IS_AUTOBIND_FLAG_on) {
phase = PHASE_INAV_INIT;
// PROTOCOL_SetBindState(BIND_COUNT * PACKET_PERIOD / 1000);
} else {
set_data_phase();
// BIND_DONE;
}
return INITIAL_WAIT;
}
/*
const void *INAV_Cmds(enum ProtoCmds cmd)
{
switch(cmd) {
case PROTOCMD_INIT: initialize(INIT_BIND); return 0;
case PROTOCMD_DEINIT:
case PROTOCMD_RESET:
CLOCK_StopTimer();
return (void *)(NRF24L01_Reset() ? 1L : -1L);
//case PROTOCMD_CHECK_AUTOBIND: return 0;
case PROTOCMD_CHECK_AUTOBIND: return (void *)1L; // always Autobind
case PROTOCMD_BIND: initialize(INIT_BIND); return 0;
case PROTOCMD_NUMCHAN: return (void *)((long)rc_channel_count);
case PROTOCMD_DEFAULT_NUMCHAN: return (void *)((long)RC_CHANNEL_COUNT_DEFAULT);
case PROTOCMD_CURRENT_ID: return 0;
case PROTOCMD_GETOPTIONS: return inav_opts;
#ifdef INAV_TELEMETRY
case PROTOCMD_TELEMETRYSTATE: return (void *)(long)(Model.proto_opts[PROTOOPTS_TELEMETRY] == TELEM_ON ? PROTO_TELEM_ON : PROTO_TELEM_OFF);
#else
case PROTOCMD_TELEMETRYSTATE: return (void *)(long)PROTO_TELEM_UNSUPPORTED;
#endif
default: break;
}
return 0;
}
*/
#endif

View File

@ -189,9 +189,9 @@ static void ne260_init() {
NRF24L01_WriteReg(NRF24L01_07_STATUS, vRX_DR | vTX_DS | vMAX_RT); // reset the IRQ flags
}
static void send_data_packet() {
static void send_ne_data_packet() {
for(int i = 0; i < 4; i++) {
uint32_t value = (uint32_t)Servo_data[NE_ch[i]] * 0x40 / PPM_MAX + 0x40;
uint32_t value = (uint32_t)map(limit_channel_100(NE_ch[i]),servo_min_100,servo_max_100,0,80);
if (value > 0x7f)
value = 0x7f;
else if(value < 0)
@ -210,7 +210,7 @@ static void send_data_packet() {
NRF24L01_WritePayload((uint8_t*) packet, PACKET_NE_LENGTH);
}
static void send_bind_packet() {
static void send_ne_bind_packet() {
packet[0] = 0xAA; //throttle
packet[1] = 0xAA; //rudder
packet[2] = 0xAA; //elevator
@ -243,7 +243,7 @@ static uint16_t ne260_cb() {
}
}
NRF24L01_SetTxRxMode(TX_EN);
send_bind_packet();
send_ne_bind_packet();
state = NE260_BINDRX;
return 500;
} else if (state == NE260_BINDRX) {
@ -259,7 +259,7 @@ static uint16_t ne260_cb() {
else if (state == NE260_DATA1) { neChannel = 10; state = NE260_DATA2; }
else if (state == NE260_DATA2) { neChannel = 30; state = NE260_DATA3; }
else if (state == NE260_DATA3) { neChannel = 50; state = NE260_DATA1; }
send_data_packet();
send_ne_data_packet();
return 2500;
}

View File

@ -112,9 +112,9 @@ static const uint8_t * rf_udi_channels = NULL;
static uint8_t packet_udi_ack()
{
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) {
case BV(NRF24L01_07_TX_DS): return PKT_ACKED;
case BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT;
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (_BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT))) {
case _BV(NRF24L01_07_TX_DS): return PKT_ACKED;
case _BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT;
}
return PKT_PENDING;
}
@ -207,7 +207,7 @@ static void UDI_init2()
// Turn radio power on
NRF24L01_SetTxRxMode(TX_EN);
uint8_t config = BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP);
uint8_t config = _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, config);
// Implicit delay in callback
// delayMicroseconds(150);
@ -239,15 +239,11 @@ static void add_pkt_checksum()
static uint8_t convert_channel(uint8_t num, uint8_t chn_max, uint8_t sign_ofs)
{
uint32_t ch = Servo_data[num];
if (ch < PPM_MIN) {
ch = PPM_MIN;
} else if (ch > PPM_MAX) {
ch = PPM_MAX;
}
uint32_t ch = map(limit_channel_100(num),servo_min_100,servo_max_100,-1000, 1000);
uint32_t chn_val;
if (sign_ofs) chn_val = (((ch * chn_max / PPM_MAX) + sign_ofs) >> 1);
else chn_val = (ch * chn_max / PPM_MAX);
if (sign_ofs) chn_val = (((ch * chn_max / servo_max_100) + sign_ofs) >> 1);
else chn_val = (ch * chn_max / servo_max_100);
if (chn_val < 0) chn_val = 0;
else if (chn_val > chn_max) chn_val = chn_max;
return (uint8_t) chn_val;
@ -260,8 +256,8 @@ static void read_controls(uint8_t* throttle, uint8_t* rudder, uint8_t* elevator,
// Protocol is registered AETRG, that is
// Aileron is channel 0, Elevator - 1, Throttle - 2, Rudder - 3
// Sometimes due to imperfect calibration or mixer settings
// throttle can be less than PPM_MIN or larger than
// PPM_MAX. As we have no space here, we hard-limit
// throttle can be less than servo_min_100 or larger than
// servo_max_100. As we have no space here, we hard-limit
// channels values by min..max range
// Channel 3: throttle is 0-100
@ -277,28 +273,28 @@ static void read_controls(uint8_t* throttle, uint8_t* rudder, uint8_t* elevator,
*aileron = convert_channel(AILERON, 0x3f, 0x20);
// Channel 5
if (Servo_data[AUX1] <= 0) *flags &= ~UDI_FLIP360;
else *flags |= UDI_FLIP360;
if (Servo_AUX1) *flags |= UDI_FLIP360;
else *flags &= ~UDI_FLIP360;
// Channel 6
if (Servo_data[AUX2] <= 0) *flags &= ~UDI_FLIP;
else *flags |= UDI_FLIP;
if (Servo_AUX2) *flags |= UDI_FLIP;
else *flags &= ~UDI_FLIP;
// Channel 7
if (Servo_data[AUX3] <= 0) *flags &= ~UDI_CAMERA;
else *flags |= UDI_CAMERA;
if (Servo_AUX3) *flags |= UDI_CAMERA;
else *flags &= ~UDI_CAMERA;
// Channel 8
if (Servo_data[AUX4] <= 0) *flags &= ~UDI_VIDEO;
else *flags |= UDI_VIDEO;
if (Servo_AUX4) *flags |= UDI_VIDEO;
else *flags &= ~UDI_VIDEO;
// Channel 9
if (Servo_data[AUX5] <= 0) *flags &= ~UDI_LIGHTS;
else *flags |= UDI_LIGHTS;
if (Servo_AUX5) *flags |= UDI_LIGHTS;
else *flags &= ~UDI_LIGHTS;
// Channel 10
if (Servo_data[AUX6] <= 0) *flags &= ~UDI_MODE2;
else *flags |= UDI_MODE2;
if (Servo_AUX6) *flags |= UDI_MODE2;
else *flags &= ~UDI_MODE2;
}
static void send_udi_packet(uint8_t bind)
@ -325,7 +321,7 @@ static void send_udi_packet(uint8_t bind)
packet[5] = randoms[1];
packet[6] = randoms[2];
if (sub_protocol == U839_2014) {
packet[7] = (packet_counter < 4) ? 0x3f : 0x04; // first four packets use 0x3f here, then 0x04
packet[7] = (packet_count < 4) ? 0x3f : 0x04; // first four packets use 0x3f here, then 0x04
}
} else if (bind == 2) {
// Bind phase 2
@ -374,7 +370,7 @@ static void send_udi_packet(uint8_t bind)
uint8_t status = NRF24L01_ReadReg(NRF24L01_07_STATUS);
NRF24L01_WriteReg(NRF24L01_07_STATUS,status);
if (packet_sent && bind && (status & BV(NRF24L01_07_TX_DS))) {
if (packet_sent && bind && (status & _BV(NRF24L01_07_TX_DS))) {
bind_step_success = 1;
}
@ -396,7 +392,7 @@ static void send_udi_packet(uint8_t bind)
}
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet, payload_size);
++packet_counter;
++packet_count;
packet_sent = 1;
}
@ -433,7 +429,7 @@ static uint16_t UDI_callback() {
break;
case UDI_BIND1_RX:
// Check if data has been received
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR) ) {
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR) ) {
uint8_t data[UDI_PAYLOADSIZE];
NRF24L01_ReadPayload(data, payload_size);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x4E); // On original TX this is done on LAST packet check only !
@ -514,7 +510,7 @@ static uint16_t UDI_callback() {
case UDI_BIND2_RX:
// Check if data has been received
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR) ) {
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR) ) {
uint8_t data[UDI_PAYLOADSIZE];
NRF24L01_ReadPayload(data, payload_size);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x4E);
@ -570,7 +566,7 @@ static uint16_t UDI_callback() {
static uint16_t UDI_setup()
{
packet_counter = 0;
packet_count = 0;
UDI_init();
phase = UDI_INIT2;

230
Multiprotocol/README.md Normal file
View File

@ -0,0 +1,230 @@
# DIY-Multiprotocol-TX-Module
![Screenshot](http://static.rcgroups.net/forums/attachments/4/0/8/5/8/3/t7952733-114-thumb-P4100002.JPG?d=1433910155) ![Screenshot](http://static.rcgroups.net/forums/attachments/4/0/8/5/8/3/t7952734-189-thumb-P4100003.JPG?d=1433910159)
Fork du projet https://github.com/pascallanger/DIY-Multiprotocol-TX-Module
Afin d'ajouter :
- Un rebind hardware en PPM
- La radio TARANIS (TAERB, B = rebind ;-) ) et redéclaration des radios
Programme des évolutions :
- Ajout du futur protocole INAV
#Schematic
![Screenshot](http://static.rcgroups.net/forums/attachments/4/0/8/5/8/3/a8443844-119-multiprotocol_diagram_rotary_serial_2.jpg)
Notes:
- Attention: All modules are 3.3V only, never power them with 5V.
#Protocoles ajoutés mais non testés (Issue de Deviation)
##Other
###OPENLRS
Empty protocol
##CYRF6936 RF Module
###J6PRO
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
###WK2x01
Autobind
####Sub_protocol WK2401
CH1|CH2|CH3|CH4
---|---|---|---
CH1|CH2|CH3|CH4
####Sub_protocol WK2601
Option:
0 = 5+1
2 = 6+1
..1 = Hélicoptère (. = autres options pour ce mode)
.01 = Hélicoptère normal
.11 = Hélicoptère avec pit inversé
0.1 = Pitch curve -100
1.1 = Pitch curve 100
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|???|CONF|Gyro & Rudder mix
CONF: Option 1 = Rate Throtle
Option 2 = Pitch
####Sub_protocol WK2801
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
##A7105 RF Module
###Flysky AFHDS2A
Telemetry enabled for battery voltage and TX RSSI
Option= 0-PWM_IBUS 1-PPM_IBUS 2-PWM_SBUS 3-PPM_SBUS
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
T|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|Failsave T
###HUBSAN
Models: Hubsan H102D, H107/L/C/D and Hubsan H107P/C+/D+
Autobind protocol
Telemetry enabled for battery voltage and TX RSSI
Option=vTX frequency (H107D) 5645 - 5900 MHz
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
####Sub_protocol H301
CH5|CH6|CH7|CH8
---|---|---|---
LED|STAB|RTH|VIDEO
####Sub_protocol H501
CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|---|---|---
FLIP|LIGHT|RTH|VIDEO|HEADLESS|GPS_HOLD|ALT_HOLD|SNAPSHOT
###Joysway
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
##CC2500 RF Module
###SKYARTEC
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
? | ? | ? | ? | ? | ? | ?
##NRF24L01 RF Module
###BLUEFLY
Autobind
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|GEAR|PITCH
###CFLIE
Modele: CrazyFlie Nano quad
Autobind
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
###ESKY150
Autobind
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
###FBL100
Autobind
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
? | ? | ? | ? | ? | ? | ? | ?
####Sub_protocol HP100
Same channels assignement as above.
###Fy326
Autobind
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|HEADLESS|RTH|Calibrate|Expert
####Sub_protocol FY319
Same channels assignement as above.
###H377
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
###HM830
Modele: HM Hobby HM830 RC Paper Airplane
Autobind
CH1|CH2|CH3|CH4|CH5
---|---|---|---
A|Turbo|T|Trim|Bouton
###HONTAI
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|CAL
####Sub_protocol HONTAI
####Sub_protocol JJRCX1
CH6|
---|
ARM|
####Sub_protocol X5C1
X5C1 clone
CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|----|----
FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|CAL
####Sub_protocol FQ777
Format FQ777-951C
CH6|CH7|CH8|CH9
---|---|---|---
FLIP|SNAPSHOT|VIDEO|HEADLESS
###INAV
En cours de passage
###NE260
Modele: Nine Eagles SoloPro
Autobind
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
###UDI
Modele: Known UDI 2.4GHz protocol variants, all using BK2421
* UDI U819 coaxial 3ch helicoper
* UDI U816/817/818 quadcopters
- "V1" with orange LED on TX, U816 RX labeled '' , U817/U818 RX labeled 'UD-U817B'
- "V2" with red LEDs on TX, U816 RX labeled '', U817/U818 RX labeled 'UD-U817OG'
- "V3" with green LEDs on TX. Did not get my hands on yet.
* U830 mini quadcopter with tilt steering ("Protocol 2014")
* U839 nano quadcopter ("Protocol 2014")
Autobind
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP 360|FLIP|VIDEO|LED|MODE 2
####Sub_protocol U816_V1 (orange)
####Sub_protocol U816_V2 (red)
####Sub_protocol U839_2014
Same channels assignement as above.
###D'autres à venir

View File

@ -1,5 +1,3 @@
<<<<<<< HEAD
=======
/*
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
@ -15,7 +13,6 @@
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
>>>>>>> refs/remotes/pascallanger/master
#if defined(SHENQI_NRF24L01_INO)
#include "iface_nrf24l01.h"
@ -42,17 +39,10 @@ void SHENQI_init()
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5 bytes rx/tx address
<<<<<<< HEAD
LT8910_Config(4, 8, _BV(LT8910_CRC_ON)|_BV(LT8910_PACKET_LENGTH_EN), 0xAA);
LT8910_SetChannel(2);
LT8910_SetAddress((uint8_t *)"\x9A\x9A\x9A\x9A",4);
LT8910_SetTxRxMode(RX_EN);
=======
LT8900_Config(4, 8, _BV(LT8900_CRC_ON)|_BV(LT8900_PACKET_LENGTH_EN), 0xAA);
LT8900_SetChannel(2);
LT8900_SetAddress((uint8_t *)"\x9A\x9A\x9A\x9A",4);
LT8900_SetTxRxMode(RX_EN);
>>>>>>> refs/remotes/pascallanger/master
}
void SHENQI_send_packet()
@ -61,16 +51,6 @@ void SHENQI_send_packet()
if(packet_count==0)
{
uint8_t bind_addr[4];
<<<<<<< HEAD
bind_addr[0]=0x9A;
bind_addr[1]=0x9A;
bind_addr[2]=rx_tx_addr[2];
bind_addr[3]=rx_tx_addr[3];
LT8910_SetAddress(bind_addr,4);
LT8910_SetChannel(2);
packet[1]=rx_tx_addr[1];
packet[2]=rx_tx_addr[0];
=======
bind_addr[0]=rx_tx_addr[0];
bind_addr[1]=rx_tx_addr[1];
bind_addr[2]=0x9A;
@ -79,39 +59,24 @@ void SHENQI_send_packet()
LT8900_SetChannel(2);
packet[1]=rx_tx_addr[2];
packet[2]=rx_tx_addr[3];
>>>>>>> refs/remotes/pascallanger/master
packet_period=2508;
}
else
{
<<<<<<< HEAD
LT8910_SetAddress(rx_tx_addr,4);
packet[1]=255-convert_channel_8b(RUDDER);
packet[2]=255-convert_channel_8b_scale(THROTTLE,0x60,0xA0);
uint8_t freq=pgm_read_byte_near(&SHENQI_Freq[hopping_frequency_no])+(rx_tx_addr[1]&0x0F);
LT8910_SetChannel(freq);
=======
LT8900_SetAddress(rx_tx_addr,4);
packet[1]=255-convert_channel_8b(RUDDER);
packet[2]=255-convert_channel_8b_scale(THROTTLE,0x60,0xA0);
uint8_t freq=pgm_read_byte_near(&SHENQI_Freq[hopping_frequency_no])+(rx_tx_addr[2]&0x0F);
LT8900_SetChannel(freq);
>>>>>>> refs/remotes/pascallanger/master
hopping_frequency_no++;
if(hopping_frequency_no==60)
hopping_frequency_no=0;
packet_period=1750;
}
// Send packet + 1 retransmit - not sure why but needed (not present on original TX...)
<<<<<<< HEAD
LT8910_WritePayload(packet,3);
while(NRF24L01_packet_ack()!=PKT_ACKED);
LT8910_WritePayload(packet,3);
=======
LT8900_WritePayload(packet,3);
while(NRF24L01_packet_ack()!=PKT_ACKED);
LT8900_WritePayload(packet,3);
>>>>>>> refs/remotes/pascallanger/master
packet_count++;
if(packet_count==7)
@ -129,16 +94,6 @@ uint16_t SHENQI_callback()
SHENQI_send_packet();
else
{
<<<<<<< HEAD
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR))
{
if(LT8910_ReadPayload(packet, 3))
{
BIND_DONE;
rx_tx_addr[3]=packet[1];
rx_tx_addr[2]=packet[2];
LT8910_SetTxRxMode(TX_EN);
=======
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{
if(LT8900_ReadPayload(packet, 3))
@ -147,7 +102,6 @@ uint16_t SHENQI_callback()
rx_tx_addr[0]=packet[1];
rx_tx_addr[1]=packet[2];
LT8900_SetTxRxMode(TX_EN);
>>>>>>> refs/remotes/pascallanger/master
packet_period=14000;
}
NRF24L01_FlushRx();
@ -162,11 +116,7 @@ uint16_t initSHENQI()
SHENQI_init();
hopping_frequency_no = 0;
packet_count=0;
<<<<<<< HEAD
packet_period=100;
=======
packet_period=500;
>>>>>>> refs/remotes/pascallanger/master
return 1000;
}

View File

@ -22,6 +22,16 @@
#define PPM_MIN_125 1000 // 125%
#endif
// TAARANIS PPM and channels
#if defined(TX_TARANIS)
#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 INVERT_TELEMETRY
#endif
// HISKY
#if defined(TX_HISKY)
#define PPM_MAX_100 1900 // 100%
@ -37,7 +47,6 @@
#define PPM_MAX_125 2050 // 125%
#define PPM_MIN_125 1150 // 125%
#endif
//Serial MIN MAX values
#define SERIAL_MAX_100 2012 // 100%
#define SERIAL_MIN_100 988 // 100%

View File

@ -1,178 +1,3 @@
<<<<<<< HEAD
//*************************************
// FrSky Telemetry serial code *
// By Midelic on RCGroups *
//*************************************
#if defined TELEMETRY
#if defined FRSKYX_CC2500_INO
#define SPORT_TELEMETRY
#endif
#if defined FRSKY_CC2500_INO
#define HUB_TELEMETRY
#endif
#if defined SPORT_TELEMETRY
#define SPORT_TELEMETRY
#define SPORT_TIME 12000
uint32_t last=0;
uint8_t sport_counter=0;
uint8_t RxBt=0;
uint8_t rssi;
uint8_t ADC2;
#endif
#if defined HUB_TELEMETRY
#define MAX_PKTX 10
uint8_t pktx[MAX_PKTX];
uint8_t index;
uint8_t prev_index;
uint8_t pass = 0;
#endif
#define USER_MAX_BYTES 6
uint8_t frame[18];
void frskySendStuffed()
{
Serial_write(0x7E);
for (uint8_t i = 0; i < 9; i++)
{
if ((frame[i] == 0x7e) || (frame[i] == 0x7d))
{
Serial_write(0x7D);
frame[i] ^= 0x20;
}
Serial_write(frame[i]);
}
Serial_write(0x7E);
}
void compute_RSSIdbm(){
RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5);
if(pktt[len-2] >=128)
RSSI_dBm -= 82;
else
RSSI_dBm += 65;
}
void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
{
if(pkt[1] != rx_tx_addr[3] || pkt[2] != rx_tx_addr[2] || len != pkt[0] + 3)
{//only packets with the required id and packet length
for(uint8_t i=3;i<6;i++)
pktt[i]=0;
return;
}
else
{
for (uint8_t i=3;i<len;i++)
pktt[i]=pkt[i];
telemetry_link=1;
if(pktt[6]>0)
telemetry_counter=(telemetry_counter+1)%32;
}
}
void frsky_link_frame()
{
frame[0] = 0xFE;
if ((cur_protocol[0]&0x1F)==MODE_FRSKY)
{
compute_RSSIdbm();
frame[1] = pktt[3];
frame[2] = pktt[4];
frame[3] = (uint8_t)RSSI_dBm;
frame[4] = pktt[5]*2;
}
else
if ((cur_protocol[0]&0x1F)==MODE_HUBSAN)
{
frame[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V
frame[2] = frame[1];
frame[3] = 0x00;
frame[4] = (uint8_t)RSSI_dBm;
}
frame[5] = frame[6] = frame[7] = frame[8] = 0;
frskySendStuffed();
}
#if defined HUB_TELEMETRY
void frsky_user_frame()
{
uint8_t indexx = 0, c=0, j=8, n=0, i;
if(pktt[6]>0 && pktt[6]<=MAX_PKTX)
{//only valid hub frames
frame[0] = 0xFD;
frame[1] = 0;
frame[2] = pktt[7];
switch(pass)
{
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:
index=indexx;
prev_index = indexx;
if(index<USER_MAX_BYTES)
{
for(i=0;i<index;i++)
frame[i+3]=pktx[i];
pktt[6]=0;
pass=0;
}
else
{
index = USER_MAX_BYTES;
for(i=0;i<index;i++)
frame[i+3]=pktx[i];
pass=2;
}
break;
case 2:
index = prev_index - index;
prev_index=0;
if(index<MAX_PKTX-USER_MAX_BYTES) //10-6=4
for(i=0;i<index;i++)
frame[i+3]=pktx[USER_MAX_BYTES+i];
pass=0;
pktt[6]=0;
break;
default:
break;
}
if(!index)
return;
frame[1] = index;
frskySendStuffed();
}
else
pass=0;
}
#endif
#if defined SPORT_TELEMETRY
/* SPORT details serial
100K 8E2 normal-multiprotocol
-every 12ms-
1 2 3 4 5 6 7 8 9 CRC DESCR
=======
/*
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
@ -190,6 +15,7 @@
//**************************
// Telemetry serial code *
//**************************
#if defined TELEMETRY
#if defined SPORT_TELEMETRY
@ -304,7 +130,7 @@ void frsky_link_frame()
frame[4] = (uint8_t)RSSI_dBm;
}
else
if (protocol==MODE_HUBSAN)
if ((protocol==MODE_HUBSAN) || (protocol==MODE_AFHDS2A))
{
frame[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V
frame[2] = frame[1];
@ -405,7 +231,6 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
100K 8E2 normal-multiprotocol
-every 12ms-or multiple of 12; %36
1 2 3 4 5 6 7 8 9 CRC DESCR
>>>>>>> refs/remotes/pascallanger/master
7E 98 10 05 F1 20 23 0F 00 A6 SWR_ID
7E 98 10 01 F1 33 00 00 00 C9 RSSI_ID
7E 98 10 04 F1 58 00 00 00 A1 BATT_ID
@ -417,24 +242,15 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
7E BA 10 03 F1 E2 00 00 00 18 ADC2_ID
<<<<<<< HEAD
Telemetry frames(RF) SPORT info 15 bytes
SPORT frame 6+3 bytes
=======
Telemetry frames(RF) SPORT info
15 bytes payload
SPORT frame valid 6+3 bytes
>>>>>>> refs/remotes/pascallanger/master
[00] PKLEN 0E 0E 0E 0E
[01] TXID1 DD DD DD DD
[02] TXID2 6D 6D 6D 6D
[03] CONST 02 02 02 02
[04] RS/RB 2C D0 2C CE //D0;CE=2*RSSI;....2C = RX battery voltage(5V from Bec)
<<<<<<< HEAD
[05] ????? 03 10 21 32 //TX/RX telemetry hand-shake bytes
=======
[05] HD-SK 03 10 21 32 //TX/RX telemetry hand-shake bytes
>>>>>>> refs/remotes/pascallanger/master
[06] NO.BT 00 00 06 03 //No.of valid SPORT frame bytes in the frame
[07] STRM1 00 00 7E 00
[08] STRM2 00 00 1A 00
@ -442,146 +258,6 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
[10] STRM4 03 03 03 03
[11] STRM5 F1 F1 F1 F1
[12] STRM6 D1 D1 D0 D0
<<<<<<< HEAD
[13] CHKSUM1
[14] CHKSUM2
*/
void sportSend(uint8_t *p)
{
uint16_t crc_s = 0;
Serial_write(0x7e);//+9
for (uint8_t i = 0; i < 9; i++)
{
if (i == 8)
p[i] = 0xff - crc_s;
if ((p[i] == 0x7e) || (p[i] == 0x7d))
{
Serial_write(0x7d);
Serial_write(0x20 ^ p[i]);
}
else
Serial_write(p[i]);
if (i>0)
{
crc_s += p[i]; //0-1FF
crc_s += crc_s >> 8; //0-100
crc_s &= 0x00ff;
}
}
}
void sportIdle()
{
Serial_write(0x7e);
}
void sportSendFrame()
{
//at the moment only SWR RSSI,RxBt and A2.
sport_counter = (sport_counter + 1) %9;
for (uint8_t i=5;i<8;i++)
frame[i]=0;
switch (sport_counter)
{
case 0: // SWR
frame[0] = 0x98;
frame[1] = 0x10;
frame[2] = 0x05;
frame[3] = 0xf1;
frame[4] = 0x20;//dummy values if swr 20230f00
frame[5] = 0x23;
frame[6] = 0x0F;
frame[7] = 0x00;
break;
case 1: // RSSI
frame[0] = 0x98;
frame[1] = 0x10;
frame[2] = 0x01;
frame[3] = 0xf1;
frame[4] = rssi;
break;
case 2: //BATT
frame[0] = 0x98;
frame[1] = 0x10;
frame[2] = 0x04;
frame[3] = 0xf1;
frame[4] = RxBt;//a1;
break;
case 3: //ADC2(A2)
frame[0] = 0x1A;
frame[1] = 0x10;
frame[2] = 0x03;
frame[3] = 0xf1;
frame[4] = ADC2;//a2;;
break;
default:
sportIdle();
return;
}
sportSend(frame);
}
void process_sport_data()//only for ADC2
{
uint8_t j=7;
if(pktt[6]>0 && pktt[6]<=USER_MAX_BYTES)
{
for(uint8_t i=0;i<6;i++)
if(pktt[j++]==0x03)
if(pktt[j]==0xF1)
{
ADC2=pktt[j+1];
break;
}
pktt[6]=0;//new frame
}
}
#endif
void frskyUpdate()
{
if(telemetry_link && (cur_protocol[0]&0x1F) != MODE_FRSKYX )
{
frsky_link_frame();
telemetry_link=0;
return;
}
#if defined HUB_TELEMETRY
if(!telemetry_link && (cur_protocol[0]&0x1F) != MODE_HUBSAN && (cur_protocol[0]&0x1F) != MODE_FRSKYX)
{
frsky_user_frame();
return;
}
#endif
#if defined SPORT_TELEMETRY
if ((cur_protocol[0]&0x1F)==MODE_FRSKYX)
{
if(telemetry_link)
{
process_sport_data();
if(pktt[4]>0x36)
rssi=pktt[4]/2;
else
RxBt=pktt[4];
telemetry_link=0;
}
uint32_t now = micros();
if ((now - last) > SPORT_TIME)
{
sportSendFrame();
last = now;
}
}
#endif
}
#endif
=======
[13] CHKSUM1 --|2 CRC bytes sent by RX (calculated on RX side crc16/table)
[14] CHKSUM2 --|
+2 appended bytes automatically RSSI and LQI/CRC bytes(len=0x0E+3);
@ -732,92 +408,92 @@ void proces_sport_data(uint8_t data)
void TelemetryUpdate()
{
#if defined SPORT_TELEMETRY
if (protocol==MODE_FRSKYX)
{ // FrSkyX
if(telemetry_link)
{
if(pktt[4] & 0x80)
rssi=pktt[4] & 0x7F ;
else
RxBt = (pktt[4]<<1) + 1 ;
for (uint8_t i=0; i < pktt[6]; i++)
proces_sport_data(pktt[7+i]);
telemetry_link=0;
#if defined SPORT_TELEMETRY
if (protocol==MODE_FRSKYX)
{ // FrSkyX
if(telemetry_link)
{
if(pktt[4] & 0x80)
rssi=pktt[4] & 0x7F ;
else
RxBt = (pktt[4]<<1) + 1 ;
for (uint8_t i=0; i < pktt[6]; i++)
proces_sport_data(pktt[7+i]);
telemetry_link=0;
}
}
}
#endif
#endif
// check for space in tx buffer
#ifdef BASH_SERIAL
uint8_t h ;
uint8_t t ;
h = SerialControl.head ;
t = SerialControl.tail ;
if ( h >= t )
{
t += 64 - h ;
}
else
{
t -= h ;
}
if ( t < 32 )
{
return ;
}
#ifdef BASH_SERIAL
uint8_t h ;
uint8_t t ;
h = SerialControl.head ;
t = SerialControl.tail ;
if ( h >= t )
{
t += 64 - h ;
}
else
{
t -= h ;
}
if ( t < 32 )
{
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 )
{
return ;
}
#endif
#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 )
{
return ;
}
#endif
#if defined DSM_TELEMETRY
if(telemetry_link && protocol == MODE_DSM )
{ // DSM
DSM_frame();
telemetry_link=0;
return;
}
if(telemetry_link && protocol == MODE_DSM )
{ // DSM
DSM_frame();
telemetry_link=0;
return;
}
#endif
if(telemetry_link && protocol != MODE_FRSKYX )
{ // FrSky + Hubsan
{ // FrSky + Hubsan + Flysky AFHDS2A
frsky_link_frame();
telemetry_link=0;
return;
}
#if defined HUB_TELEMETRY
if(!telemetry_link && protocol == MODE_FRSKYD)
{ // FrSky
frsky_user_frame();
return;
}
if(!telemetry_link && protocol == MODE_FRSKYD)
{ // FrSky
frsky_user_frame();
return;
}
#endif
#if defined SPORT_TELEMETRY
if (protocol==MODE_FRSKYX)
{ // FrSkyX
uint32_t now = micros();
if ((now - last) > SPORT_TIME)
{
sportSendFrame();
last += SPORT_TIME ;
if (protocol==MODE_FRSKYX)
{ // FrSkyX
uint32_t now = micros();
if ((now - last) > SPORT_TIME)
{
sportSendFrame();
last += SPORT_TIME ;
}
}
}
#endif
}
@ -846,19 +522,19 @@ void initTXSerial( uint8_t speed)
#ifdef ENABLE_PPM
if(speed==SPEED_9600)
{ // 9600
#ifdef XMEGA
USARTC0.BAUDCTRLA = 207 ;
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
USARTC0.CTRLC = 0x03 ;
#else
//9600 bauds
UBRR0H = 0x00;
UBRR0L = 0x67;
UCSR0A = 0 ; // Clear X2 bit
//Set frame format to 8 data bits, none, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
#ifdef XMEGA
USARTC0.BAUDCTRLA = 207 ;
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
USARTC0.CTRLC = 0x03 ;
#else
//9600 bauds
UBRR0H = 0x00;
UBRR0L = 0x67;
UCSR0A = 0 ; // Clear X2 bit
//Set frame format to 8 data bits, none, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
#endif
}
else if(speed==SPEED_57600)
@ -951,20 +627,20 @@ void Serial_write( uint8_t byte )
uint8_t temp1 ;
uint8_t byteLo ;
#ifdef INVERT_SERIAL
byte = ~byte ;
#endif
#ifdef INVERT_SERIAL
byte = ~byte ;
#endif
byteLo = byte ;
byteLo >>= 7 ; // Top bit
if ( SerialControl.speed == SPEED_100K )
{
#ifdef INVERT_SERIAL
byteLo |= 0x02 ; // Parity bit
#else
byteLo |= 0xFC ; // Stop bits
#endif
// calc parity
#ifdef INVERT_SERIAL
byteLo |= 0x02 ; // Parity bit
#else
byteLo |= 0xFC ; // Stop bits
#endif
// calc parity
temp = byte ;
temp >>= 4 ;
temp = byte ^ temp ;
@ -975,21 +651,21 @@ void Serial_write( uint8_t byte )
temp1 <<= 1 ;
temp ^= temp1 ;
temp &= 0x02 ;
#ifdef INVERT_SERIAL
byteLo ^= temp ;
#else
byteLo |= temp ;
#endif
#ifdef INVERT_SERIAL
byteLo ^= temp ;
#else
byteLo |= temp ;
#endif
}
else
{
byteLo |= 0xFE ; // Stop bit
}
byte <<= 1 ;
#ifdef INVERT_SERIAL
byte |= 1 ; // Start bit
#endif
uint8_t next = (SerialControl.head + 2) & 0x3f ;
#ifdef INVERT_SERIAL
byte |= 1 ; // Start bit
#endif
uint8_t next = (SerialControl.head + 2) & 0x3f ;
if ( next != SerialControl.tail )
{
SerialControl.data[SerialControl.head] = byte ;
@ -1007,11 +683,11 @@ void resumeBashSerial()
{
sei() ;
// Start the transmission here
#ifdef INVERT_SERIAL
GPIOR2 = 0 ;
#else
GPIOR2 = 0x01 ;
#endif
#ifdef INVERT_SERIAL
GPIOR2 = 0 ;
#else
GPIOR2 = 0x01 ;
#endif
if ( SerialControl.speed == SPEED_100K )
{
GPIOR1 = 1 ;
@ -1149,4 +825,4 @@ ISR(TIMER0_OVF_vect)
#endif // BASH_SERIAL
#endif // TELEMETRY
>>>>>>> refs/remotes/pascallanger/master

View File

@ -34,16 +34,6 @@
#define YD717_PAYLOADSIZE 8 // receive data pipes set to this size, but unused
<<<<<<< HEAD
enum {
YD717_INIT1 = 0,
YD717_BIND2,
YD717_BIND3,
YD717_DATA
};
=======
>>>>>>> refs/remotes/pascallanger/master
static void __attribute__((unused)) yd717_send_packet(uint8_t bind)
{
uint8_t rudder_trim, elevator_trim, aileron_trim;
@ -149,11 +139,6 @@ static void __attribute__((unused)) yd717_init()
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Set feature bits on
NRF24L01_Activate(0x73);
<<<<<<< HEAD
static void __attribute__((unused)) YD717_init1()
{
=======
>>>>>>> refs/remotes/pascallanger/master
// for bind packets set address to prearranged value known to receiver
uint8_t bind_rx_tx_addr[] = {0x65, 0x65, 0x65, 0x65, 0x65};
@ -168,16 +153,6 @@ static void __attribute__((unused)) YD717_init1()
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_rx_tx_addr, 5);
}
<<<<<<< HEAD
static void __attribute__((unused)) YD717_init2()
{
// set rx/tx address for data phase
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
}
=======
>>>>>>> refs/remotes/pascallanger/master
uint16_t yd717_callback()
{
if(IS_BIND_DONE_on)

View File

@ -13,85 +13,6 @@
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
<<<<<<< HEAD
/** Multiprotocol module configuration file ***/
//Uncomment your TX type
#define TARANIS //TARANIS TAER (1100<->1900µs)
//#define TX_ER9X //ER9X AETR (988<->2012µs)
//#define TX_DEVO7 //DEVO7 EATR (1120<->1920µs)
//#define TX_SPEKTRUM //Spektrum TAER (1100<->1900µs)
//#define TX_HISKY //HISKY AETR (1100<->1900µs)
//Uncomment to enable telemetry
#define TELEMETRY
//Comment if a module is not installed
#define A7105_INSTALLED
#define CYRF6936_INSTALLED
//#define CC2500_INSTALLED
#define NFR24L01_INSTALLED
//Comment a protocol to exclude it from compilation
#ifdef A7105_INSTALLED
#define JOYSWAY_A7105_INO
#define FLYSKY_A7105_INO
#define HUBSAN_A7105_INO
#endif
#ifdef CYRF6936_INSTALLED
#define J6PRO_CYRF6936_INO
#define WK2x01_CYRF6936_INO
#define DEVO_CYRF6936_INO
#define DSM2_CYRF6936_INO
#endif
#ifdef CC2500_INSTALLED
#define SKYARTEC_CC2500_INO
#define FRSKY_CC2500_INO
#define FRSKYX_CC2500_INO
#endif
#ifdef NFR24L01_INSTALLED
#define HM830_NRF24L01_INO
#define CFlie_NRF24L01_INO
#define H377_NRF24L01_INO
#define ESKY150_NRF24L01_INO
#define HonTai_NRF24L01_INO
#define UDI_NRF24L01_INO
#define NE260_NRF24L01_INO
#define BlueFly_NRF24L01_INO //probleme gene id
#define FBL100_NRF24L01_INO // finir id
#define BAYANG_NRF24L01_INO
#define CG023_NRF24L01_INO
#define CX10_NRF24L01_INO
#define ESKY_NRF24L01_INO
#define HISKY_NRF24L01_INO
#define KN_NRF24L01_INO
#define SLT_NRF24L01_INO
#define SYMAX_NRF24L01_INO
#define V2X2_NRF24L01_INO
#define YD717_NRF24L01_INO
#define MT99XX_NRF24L01_INO
#define MJXQ_NRF24L01_INO
#define SHENQI_NRF24L01_INO
#define FY326_NRF24L01_INO
#endif
//Update this table to set which protocol and all associated settings are called for the corresponding dial number
const PPM_Parameters PPM_prot[15]= {
// Dial Protocol Sub protocol RX_Num Power Auto Bind Option
/* 1 */ {MODE_FLYSKY, Flysky , 0 , P_HIGH , AUTOBIND , 0 },
/* 2 */ {MODE_HUBSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 3 */ {MODE_FRSKY , 0 , 0 , P_HIGH , NO_AUTOBIND , 0xD7 }, // D7 fine tuning
/* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 5 */ {MODE_V2X2 , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 6 */ {MODE_DSM2 , DSM2 , 0 , P_HIGH , NO_AUTOBIND , 6 }, // 6 channels @ 11ms
/* 7 */ {MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 8 */ {MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 9 */ {MODE_KN , FEILUN , 0 , P_HIGH , AUTOBIND , 0 },
=======
/**********************************************/
/** Multiprotocol module configuration file ***/
/**********************************************/
@ -102,7 +23,7 @@ const PPM_Parameters PPM_prot[15]= {
//Modify the channel order based on your TX: AETR, TAER, RETA...
//Examples: Flysky & DEVO is AETR, JR/Spektrum radio is TAER, Multiplex is AERT...
//Default is AETR.
#define AETR
#define EATR
/**************************/
@ -112,10 +33,10 @@ const PPM_Parameters PPM_prot[15]= {
//If a chip is not installed all associated protocols are disabled.
//4-in-1 modules have all RF chips installed
//!!!If a RF chip is present it MUST be marked as installed!!! or weird things will happen you have been warned.
#define A7105_INSTALLED
#define CYRF6936_INSTALLED
#define CC2500_INSTALLED
#define NRF24L01_INSTALLED
#define A7105_INSTALLED
#define CYRF6936_INSTALLED
// #define CC2500_INSTALLED
#define NRF24L01_INSTALLED
/****************************/
@ -126,39 +47,55 @@ const PPM_Parameters PPM_prot[15]= {
//Comment the protocols you are not using with "//" to save Flash space.
//The protocols below need an A7105 to be installed
#define FLYSKY_A7105_INO
#define HUBSAN_A7105_INO
#define AFHDS2A_A7105_INO
// #define JOYSWAY_A7105_INO
#define FLYSKY_A7105_INO
#define HUBSAN_A7105_INO
//The protocols below need a CYRF6936 to be installed
#define DEVO_CYRF6936_INO
#define DSM_CYRF6936_INO
#define J6PRO_CYRF6936_INO
// #define WK2x01_CYRF6936_INO //!\\ //pb voie
#define DEVO_CYRF6936_INO
#define DSM_CYRF6936_INO
// #define J6PRO_CYRF6936_INO
//The protocols below need a CC2500 to be installed
#define FRSKYD_CC2500_INO
#define FRSKYV_CC2500_INO
#define FRSKYX_CC2500_INO
#define SFHSS_CC2500_INO
#define SKYARTEC_CC2500_INO
#define FRSKYD_CC2500_INO
#define FRSKYV_CC2500_INO
#define FRSKYX_CC2500_INO
#define SFHSS_CC2500_INO
//The protocols below need a NRF24L01 to be installed
#define BAYANG_NRF24L01_INO
#define CG023_NRF24L01_INO
#define CX10_NRF24L01_INO
#define ESKY_NRF24L01_INO
#define HISKY_NRF24L01_INO
#define KN_NRF24L01_INO
#define SLT_NRF24L01_INO
#define SYMAX_NRF24L01_INO
#define V2X2_NRF24L01_INO
#define YD717_NRF24L01_INO
#define MT99XX_NRF24L01_INO
#define MJXQ_NRF24L01_INO
#define SHENQI_NRF24L01_INO
#define FY326_NRF24L01_INO
#define FQ777_NRF24L01_INO
#define ASSAN_NRF24L01_INO
#define HONTAI_NRF24L01_INO
#define HM830_NRF24L01_INO
// #define CFlie_NRF24L01_INO //!\\ //pb voie gaz
// #define H377_NRF24L01_INO
// #define ESKY150_NRF24L01_INO
// #define HonTai_NRF24L01_INO
// #define UDI_NRF24L01_INO
// #define NE260_NRF24L01_INO
// #define BlueFly_NRF24L01_INO //probleme gene id
// #define FBL100_NRF24L01_INO // finir id //!\\ //pb voie ???
#define INAV_NRF24L01_INO
#define BAYANG_NRF24L01_INO
#define CG023_NRF24L01_INO
#define CX10_NRF24L01_INO
#define ESKY_NRF24L01_INO
// #define HISKY_NRF24L01_INO
#define KN_NRF24L01_INO
#define SLT_NRF24L01_INO
#define SYMAX_NRF24L01_INO
#define V2X2_NRF24L01_INO
#define YD717_NRF24L01_INO
// #define MT99XX_NRF24L01_INO
// #define MJXQ_NRF24L01_INO
// #define SHENQI_NRF24L01_INO
// #define FY326_NRF24L01_INO
// #define FQ777_NRF24L01_INO
// #define ASSAN_NRF24L01_INO
// #define HONTAI_NRF24L01_INO
/**************************/
/*** TELEMETRY SETTINGS ***/
@ -173,9 +110,9 @@ const PPM_Parameters PPM_prot[15]= {
//#define INVERT_TELEMETRY
//Comment a line to disable a protocol telemetry
#define DSM_TELEMETRY
#define SPORT_TELEMETRY
#define HUB_TELEMETRY
#define DSM_TELEMETRY
#define SPORT_TELEMETRY
#define HUB_TELEMETRY
/****************************/
@ -200,7 +137,8 @@ const PPM_Parameters PPM_prot[15]= {
//It is important for the module to know the endpoints of your radio.
//Below are some standard transmitters already preconfigured.
//Uncomment only the one which matches your transmitter.
#define TX_ER9X //ER9X/ERSKY9X/OpenTX ( 988<->2012µs)
//#define TX_ER9X //ER9X/ERSKY9X/OpenTX ( 988<->2012µs)
#define TX_TARANIS //TARANIS TAER (1100<->1900µs)
//#define TX_DEVO7 //DEVO (1120<->1920µs)
//#define TX_SPEKTRUM //Spektrum (1100<->1900µs)
//#define TX_HISKY //HISKY (1100<->1900µs)
@ -225,7 +163,7 @@ const PPM_Parameters PPM_prot[15]= {
//Example: You can associate multiple times the same protocol to different dial positions to take advantage of the model match (RX_Num)
const PPM_Parameters PPM_prot[15]= {
// Dial Protocol Sub protocol RX_Num Power Auto Bind Option
/* 1 */ {MODE_FLYSKY, Flysky , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 1 */ {MODE_FLYSKY, Flysky , 0 , P_HIGH , AUTOBIND , 0 },
/* 2 */ {MODE_HUBSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 3 */ {MODE_FRSKYD, 0 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
@ -234,7 +172,6 @@ const PPM_Parameters PPM_prot[15]= {
/* 7 */ {MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 8 */ {MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 9 */ {MODE_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 },
>>>>>>> refs/remotes/pascallanger/master
/* 10 */ {MODE_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 11 */ {MODE_SLT , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 12 */ {MODE_CX10 , CX10_BLUE , 0 , P_HIGH , NO_AUTOBIND , 0 },
@ -242,11 +179,7 @@ const PPM_Parameters PPM_prot[15]= {
/* 14 */ {MODE_BAYANG, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 15 */ {MODE_SYMAX , SYMAX5C , 0 , P_HIGH , NO_AUTOBIND , 0 }
};
<<<<<<< HEAD
/* Available protocols and associated sub protocols:
=======
/* Available protocols and associated sub protocols to pick and choose from
>>>>>>> refs/remotes/pascallanger/master
MODE_FLYSKY
Flysky
V9X9
@ -254,28 +187,18 @@ const PPM_Parameters PPM_prot[15]= {
V912
MODE_HUBSAN
NONE
<<<<<<< HEAD
MODE_FRSKY
=======
MODE_FRSKYD
>>>>>>> refs/remotes/pascallanger/master
NONE
MODE_HISKY
Hisky
HK310
MODE_V2X2
NONE
<<<<<<< HEAD
MODE_DSM2
DSM2
DSMX
=======
MODE_DSM
DSM2_22
DSM2_11
DSMX_22
DSMX_11
>>>>>>> refs/remotes/pascallanger/master
MODE_DEVO
NONE
MODE_YD717
@ -308,142 +231,26 @@ const PPM_Parameters PPM_prot[15]= {
MODE_BAYANG
NONE
MODE_FRSKYX
<<<<<<< HEAD
NONE
=======
CH_16
CH_8
>>>>>>> refs/remotes/pascallanger/master
MODE_ESKY
NONE
MODE_MT99XX
MT99
H7
YZ
<<<<<<< HEAD
=======
LS
>>>>>>> refs/remotes/pascallanger/master
MODE_MJXQ
WLH08
X600
X800
H26D
<<<<<<< HEAD
E010
MODE_SHENQI
NONE
MODE_FY326
FY326
FY319
RX_Num value between 0 and 15
Power P_HIGH or P_LOW
Auto Bind AUTOBIND or NO_AUTOBIND
Option value between 0 and 255. 0xD7 or 0x00 for Frsky fine tuning.
*/
//******************
//TX definitions with timing endpoints and channels order
// Turnigy PPM and channels
#if defined(TX_ER9X)
#define PPM_MAX 2140
#define PPM_MIN 860
#define PPM_MAX_100 2012
#define PPM_MIN_100 988
#define AETR
#endif
// Devo PPM and channels
#if defined(TX_DEVO7)
#define PPM_MAX 2100
#define PPM_MIN 900
#define PPM_MAX_100 1920
#define PPM_MIN_100 1120
#define EATR
#endif
// SPEKTRUM PPM and channels
#if defined(TX_SPEKTRUM)
#define PPM_MAX 2000
#define PPM_MIN 1000
#define PPM_MAX_100 1900
#define PPM_MIN_100 1100
#define TAER
#endif
// TARANIS PPM and channels
#if defined(TARANIS)
#define PPM_MAX 2000
#define PPM_MIN 1000
#define PPM_MAX_100 1900
#define PPM_MIN_100 1100
#define EATR
#endif
// HISKY
#if defined(TX_HISKY)
#define PPM_MAX 2000
#define PPM_MIN 1000
#define PPM_MAX_100 1900
#define PPM_MIN_100 1100
#define AETR
#endif
#if defined(EATR)
enum chan_order{
ELEVATOR=0,
AILERON,
THROTTLE,
RUDDER,
};
#endif
#if defined(TAER)
enum chan_order{
THROTTLE=0,
AILERON,
ELEVATOR,
RUDDER,
};
#endif
#if defined(AETR)
enum chan_order{
AILERON =0,
ELEVATOR,
THROTTLE,
RUDDER,
};
#endif
enum chan_orders{
AUX1 =4,
AUX2,
AUX3,
AUX4,
AUX5,
AUX6,
AUX7,
AUX8,
AUX9
};
#define PPM_MIN_COMMAND 1250
#define PPM_SWITCH 1550
#define PPM_MAX_COMMAND 1750
//Uncoment the desired serial speed
#define BAUD 100000
//#define BAUD 125000
=======
E010
MODE_SHENQI
NONE
MODE_FY326
NONE
MODE_SFHSS
NONE
MODE_J6PRO
@ -458,6 +265,7 @@ enum chan_orders{
FORMAT_HONTAI
FORMAT_JJRCX1
FORMAT_X5C1
FQ777-951
*/
// RX_Num is used for model match. Using RX_Num values different for each receiver will prevent starting a model with the false config loaded...
@ -471,5 +279,4 @@ enum chan_orders{
// As an exxample, it's usefull for the WLTOYS F929/F939/F949/F959 (all using the Flysky protocol) which requires a bind at each power up.
// Option: the value is between -127 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
>>>>>>> refs/remotes/pascallanger/master
// 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

@ -0,0 +1,4 @@
0-4 rx Flysky afhds2a
10+ 0-4 tx id
+10 réf gene id
30+6 devo reset Autobind auto

Binary file not shown.

View File

@ -89,6 +89,7 @@ enum A7105_MASK {
enum {
INIT_FLYSKY,
INIT_FLYSKY_AFHDS2A,
INIT_HUBSAN
};

View File

@ -103,13 +103,8 @@ enum {
//#define NOP 0xFF
// XN297 emulation layer
<<<<<<< HEAD
#define XN297_UNSCRAMBLED 8
=======
enum {
XN297_UNSCRAMBLED = 0,
XN297_SCRAMBLED
};
>>>>>>> refs/remotes/pascallanger/master
#endif

View File

@ -1,94 +0,0 @@
-- Multiprotocole Midelic et Pascallanger
local debut = 0
local tps = 0
local tpsact = 1024
local mix, mixe
local channel
local inp = {
{ "Protocole", VALUE, 1, 26, 2 },
{ "Switch", SOURCE }
}
-- 6 7 8 15 16 17 24 25 26
-- 4 5 12 13 14 21 22 23
-- 1 2 3 9 10 11 18 19 20
local out = { "Bind", "Gaz", "Aile", "Prof", "Dir" }
local function run_func(proto, sw)
-- test mixage lua
if debut == 0 then
-- passage en lua
for channel = 0, 3, 1 do
local mix = model.getMix(channel, 0)
mix_source = mix["source"]
if mix_source < 33 or 1 then
model.deleteMix(channel, 0)
mix["source"] = channel + 34
mix["name"] = "Lua "
model.insertMix(channel, 0, mix)
end
end
end
-- inter install
channel = 4
mix = { name="Raz Bind", source=33, weight=100, switch=0, multiplex=REPLACE }
count = model.getMixesCount(channel + 0)
if count == 0 and inter == 1 then
model.insertMix(channel + 0, 0, mix)
elseif count == 1 and inter == 0 then
mixe = model.getMix(channel, 0)
if mixe["name"] == mix["name"] then
model.deleteMix(channel, 0)
end
end
-- delais init
if proto ~= debut then
tps = getTime() + 250 -- delai pour mini 12 cycle PPM
tpsact = 1024
debut = proto
end
local gaz = 1024
local ail = 0
local dir = 0
local pro = 0
if tpsact == 0 and sw < 100 then
-- reprise valeur input
pro = getValue(1)
ail = getValue(2)
gaz = getValue(3)
dir = getValue(4)
elseif tpsact ~= 0 then
-- decallage pour position memo (centre)
if proto > 4 then proto = proto + 1 end
-- calcul position
-- decallage pour > 18
if proto > 18 then
ail = 1024
proto = proto - 18
end
-- decallage pour > 9
if proto > 9 then
ail = -1024
proto = proto - 9
end
if proto < 4 then pro = -1024 end
if proto > 6 then pro = 1024 end
if proto % 3 == 1 then dir = -1024 end
if proto % 3 == 0 then dir = 1024 end
if tps < getTime() then
tpsact = tpsact - 512
if tpsact>-20 then tps = getTime() + 250 end
end
sw = tpsact
end
return sw, gaz, ail, pro, dir
end
return { run=run_func, input=inp, output=out}

View File

@ -16,7 +16,7 @@
// Check selected board type
#ifndef XMEGA
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO)
#error You must select the board type "Arduino Pro or Pro Mini" or "Arduino Mini"
// #error You must select the board type "Arduino Pro or Pro Mini" or "Arduino Mini"
#endif
#if F_CPU != 16000000L || not defined(__AVR_ATmega328P__)
#error You must select the processor type "ATmega328(5V, 16MHz)"
@ -24,10 +24,27 @@
#endif
//******************
// Protocols
// Protocols max 31 x2
//******************
enum PROTOCOLS
{
MODE_JOYSWAY = 40, // =>A7105
MODE_WK2x01 = 41, // =>CYRF6936
MODE_SKYARTEC = 42, // =>CC2500
MODE_UDI = 44, // =>NRF24L01
MODE_FBL100 = 45, // =>NRF24L01
MODE_HM830 = 50, // =>NRF24L01
MODE_CFLIE = 51, // =>NRF24L01
MODE_H377 = 52, // =>NRF24L01
MODE_ESKY150 = 53, // =>NRF24L01
MODE_BlueFly = 54, // =>NRF24L01
MODE_NE260 = 55, // =>NRF24L01
MODE_AFHDS2A = 31, // =>A7105
MODE_INAV = 57, // =>NRF24L01
MODE_SERIAL = 0, // Serial commands
MODE_FLYSKY = 1, // =>A7105
MODE_HUBSAN = 2, // =>A7105
@ -57,18 +74,17 @@ enum PROTOCOLS
MODE_HONTAI = 26, // =>NRF24L01
MODE_OPENLRS = 27, // =>OpenLRS hardware
};
enum Flysky
{
Flysky = 0,
V9X9 = 1,
V6X6 = 2,
V912 = 3
Flysky=0,
V9X9=1,
V6X6=2,
V912=3
};
enum Hisky
{
Hisky = 0,
HK310 = 1
Hisky=0,
HK310=1
};
enum DSM
{
@ -80,38 +96,38 @@ enum DSM
};
enum YD717
{
YD717 = 0,
SKYWLKR = 1,
SYMAX4 = 2,
XINXUN = 3,
NIHUI = 4
YD717=0,
SKYWLKR=1,
SYMAX4=2,
XINXUN=3,
NIHUI=4
};
enum KN
{
WLTOYS = 0,
FEILUN = 1
WLTOYS=0,
FEILUN=1
};
enum SYMAX
{
SYMAX = 0,
SYMAX5C = 1
SYMAX=0,
SYMAX5C=1
};
enum CX10
{
CX10_GREEN = 0,
CX10_BLUE = 1, // also compatible with CX10-A, CX12
DM007 = 2,
Q282 = 3,
JC3015_1 = 4,
JC3015_2 = 5,
MK33041 = 6,
Q242 = 7
CX10_GREEN = 0,
CX10_BLUE=1, // also compatible with CX10-A, CX12
DM007=2,
Q282=3,
JC3015_1=4,
JC3015_2=5,
MK33041=6,
Q242=7
};
enum CG023
{
CG023 = 0,
YD829 = 1,
H8_3D = 2
CG023 = 0,
YD829 = 1,
H8_3D = 2
};
enum MT99XX
{
@ -135,9 +151,41 @@ enum FRSKYX
};
enum HONTAI
{
FORMAT_HONTAI = 0,
FORMAT_HONTAI = 0,
FORMAT_JJRCX1 = 1,
FORMAT_X5C1 = 2
FORMAT_X5C1 = 2,
FORMAT_FQ777 = 3
};
enum HUBSAN
{
H107 = 0,
H301 = 1,
H501 = 2
};
enum FY326
{
FY326 = 0,
FY319 = 1
};
enum WK2X01
{
WK2801 = 0,
WK2601 = 1,
WK2401 = 2
};
enum UDI
{
U816_V1 = 0,
U816_V2 = 1,
U839_2014 = 2
};
enum FBL100
{
FBL100 = 0,
HP100 = 1
};
#define NONE 0
@ -188,7 +236,7 @@ struct PPM_Parameters
#define IS_RX_FLAG_on ( ( protocol_flags & _BV(0) ) !=0 )
//
#define CHANGE_PROTOCOL_FLAG_on protocol_flags |= _BV(1)
#define CHANGE_PROTOCOL_FLAG_off protocol_flags &= ~_BV(1)
#define CHANGE_PROTOCOL_FLAG_off protocol_flags &= ~_BV(1)
#define IS_CHANGE_PROTOCOL_FLAG_on ( ( protocol_flags & _BV(1) ) !=0 )
//
#define POWER_FLAG_on protocol_flags |= _BV(2)
@ -206,8 +254,9 @@ struct PPM_Parameters
#define BIND_BUTTON_FLAG_on protocol_flags |= _BV(5)
#define BIND_BUTTON_FLAG_off protocol_flags &= ~_BV(5)
#define IS_BIND_BUTTON_FLAG_on ( ( protocol_flags & _BV(5) ) !=0 )
//PPM RX OK
#define PPM_FLAG_off protocol_flags &= ~_BV(6)
#define PPM_FLAG_off protocol_flags &= ~_BV(6)
#define PPM_FLAG_on protocol_flags |= _BV(6)
#define IS_PPM_FLAG_on ( ( protocol_flags & _BV(6) ) !=0 )
//Bind flag
@ -227,19 +276,21 @@ struct PPM_Parameters
#define RX_MISSED_BUFF_on protocol_flags2 |= _BV(2)
#define IS_RX_MISSED_BUFF_on ( ( protocol_flags2 & _BV(2) ) !=0 )
//TX Pause
#define TX_MAIN_PAUSE_off protocol_flags2 &= ~_BV(3)
#define TX_MAIN_PAUSE_on protocol_flags2 |= _BV(3)
#define IS_TX_MAIN_PAUSE_on ( ( protocol_flags2 & _BV(3) ) !=0 )
#define TX_MAIN_PAUSE_off protocol_flags2 &= ~_BV(3)
#define TX_MAIN_PAUSE_on protocol_flags2 |= _BV(3)
#define IS_TX_MAIN_PAUSE_on ( ( protocol_flags2 & _BV(3) ) !=0 )
#define TX_RX_PAUSE_off protocol_flags2 &= ~_BV(4)
#define TX_RX_PAUSE_on protocol_flags2 |= _BV(4)
#define IS_TX_RX_PAUSE_on ( ( protocol_flags2 & _BV(4) ) !=0 )
#define TX_RX_PAUSE_on protocol_flags2 |= _BV(4)
#define IS_TX_RX_PAUSE_on ( ( protocol_flags2 & _BV(4) ) !=0 )
#define IS_TX_PAUSE_on ( ( protocol_flags2 & (_BV(4)|_BV(3)) ) !=0 )
//********************
//*** Blink timing ***
//********************
#define BLINK_BIND_TIME 100
#define BLINK_SERIAL_TIME 500
#define BLINK_BIND_TIME 100
#define BLINK_SERIAL_TIME 500
#define BLINK_BAD_PROTO_TIME_LOW 1000
#define BLINK_BAD_PROTO_TIME_HIGH 50
@ -416,30 +467,30 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
RxNum value is 0..15 (bits 0..3)
Type is 0..7 <<4 (bit 4..6)
sub_protocol==Flysky
Flysky 0
V9x9 1
V6x6 2
V912 3
Flysky 0
V9x9 1
V6x6 2
V912 3
sub_protocol==Hisky
Hisky 0
HK310 1
Hisky 0
HK310 1
sub_protocol==DSM
DSM2_22 0
DSM2_11 1
DSMX_22 2
DSMX_11 3
sub_protocol==YD717
YD717 0
SKYWLKR 1
SYMAX4 2
XINXUN 3
NIHUI 4
YD717 0
SKYWLKR 1
SYMAX4 2
XINXUN 3
NIHUI 4
sub_protocol==KN
WLTOYS 0
FEILUN 1
WLTOYS 0
FEILUN 1
sub_protocol==SYMAX
SYMAX 0
SYMAX5C 1
SYMAX 0
SYMAX5C 1
sub_protocol==CX10
CX10_GREEN 0
CX10_BLUE 1 // also compatible with CX10-A, CX12
@ -464,14 +515,18 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
X800 2
H26D 3
E010 4
sub_protocol==FY326
FY326 0
FY319 1
sub_protocol==FRSKYX
CH_16 0
CH_8 1
sub_protocol==HONTAI
FORMAT_HONTAI 0
FORMAT_JJRCX1 1
FORMAT_X5C1 2
Power value => 0x80 0=High/1=Low
HONTAI 0
JJRCX1 1
X5C1 2
FQ777-521 3
Power value => 0x80 0=High/1=Low
Stream[3] = option_protocol;
option_protocol value is -127..127
Stream[4] to [25] = Channels
@ -483,3 +538,4 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
2047 +125%
Channels bits are concatenated to fit in 22 bytes like in SBUS protocol
*/

Binary file not shown.

BIN
Multiprotocol/sync.ffs_db Normal file

Binary file not shown.