Merge pull request #1 from tipouic/flysky_afhds2a

Flysky afhds2a
This commit is contained in:
tipouic 2016-12-01 07:05:13 +01:00 committed by GitHub
commit a06e8f945a
67 changed files with 10392 additions and 5231 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.ffs_db
*.ffs_db
*.ffs_db
*.hc
*.ffs_db

View File

@ -15,6 +15,7 @@
/********************/ /********************/
/** A7105 routines **/ /** A7105 routines **/
/********************/ /********************/
#ifdef A7105_INSTALLED
#include "iface_a7105.h" #include "iface_a7105.h"
void A7105_WriteData(uint8_t len, uint8_t channel) void A7105_WriteData(uint8_t len, uint8_t channel)
@ -22,21 +23,27 @@ void A7105_WriteData(uint8_t len, uint8_t channel)
uint8_t i; uint8_t i;
A7105_CSN_off; A7105_CSN_off;
SPI_Write(A7105_RST_WRPTR); SPI_Write(A7105_RST_WRPTR);
SPI_Write(0x05); SPI_Write(A7105_05_FIFO_DATA);
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
SPI_Write(packet[i]); SPI_Write(packet[i]);
A7105_CSN_on; A7105_CSN_on;
A7105_WriteReg(0x0F, channel); if(protocol!=MODE_FLYSKY)
{
A7105_Strobe(A7105_STANDBY); //Force standby mode, ie cancel any TX or RX...
A7105_SetTxRxMode(TX_EN); //Switch to PA
}
A7105_WriteReg(A7105_0F_PLL_I, channel);
A7105_Strobe(A7105_TX); A7105_Strobe(A7105_TX);
} }
void A7105_ReadData() { void A7105_ReadData(uint8_t len)
{
uint8_t i; uint8_t i;
A7105_Strobe(0xF0); //A7105_RST_RDPTR A7105_Strobe(A7105_RST_RDPTR);
A7105_CSN_off; A7105_CSN_off;
SPI_Write(0x45); SPI_Write(0x40 | A7105_05_FIFO_DATA); //bit 6 =1 for reading
for (i=0;i<16;i++) for (i=0;i<len;i++)
packet[i]=SPI_SDIO_Read(); packet[i]=SPI_SDI_Read();
A7105_CSN_on; A7105_CSN_on;
} }
@ -48,11 +55,12 @@ void A7105_WriteReg(uint8_t address, uint8_t data) {
A7105_CSN_on; A7105_CSN_on;
} }
uint8_t A7105_ReadReg(uint8_t address) { uint8_t A7105_ReadReg(uint8_t address)
{
uint8_t result; uint8_t result;
A7105_CSN_off; A7105_CSN_off;
SPI_Write(address |=0x40); //bit 6 =1 for reading SPI_Write(address |=0x40); //bit 6 =1 for reading
result = SPI_SDIO_Read(); result = SPI_SDI_Read();
A7105_CSN_on; A7105_CSN_on;
return(result); return(result);
} }
@ -60,13 +68,19 @@ uint8_t A7105_ReadReg(uint8_t address) {
//------------------------ //------------------------
void A7105_SetTxRxMode(uint8_t mode) void A7105_SetTxRxMode(uint8_t mode)
{ {
if(mode == TX_EN) { if(mode == TX_EN)
{
A7105_WriteReg(A7105_0B_GPIO1_PIN1, 0x33); A7105_WriteReg(A7105_0B_GPIO1_PIN1, 0x33);
A7105_WriteReg(A7105_0C_GPIO2_PIN_II, 0x31); A7105_WriteReg(A7105_0C_GPIO2_PIN_II, 0x31);
} else if (mode == RX_EN) { }
else
if (mode == RX_EN)
{
A7105_WriteReg(A7105_0B_GPIO1_PIN1, 0x31); A7105_WriteReg(A7105_0B_GPIO1_PIN1, 0x31);
A7105_WriteReg(A7105_0C_GPIO2_PIN_II, 0x33); A7105_WriteReg(A7105_0C_GPIO2_PIN_II, 0x33);
} else { }
else
{
//The A7105 seems to some with a cross-wired power-amp (A7700) //The A7105 seems to some with a cross-wired power-amp (A7700)
//On the XL7105-D03, TX_EN -> RXSW and RX_EN -> TXSW //On the XL7105-D03, TX_EN -> RXSW and RX_EN -> TXSW
//This means that sleep mode is wired as RX_EN = 1 and TX_EN = 1 //This means that sleep mode is wired as RX_EN = 1 and TX_EN = 1
@ -81,21 +95,22 @@ uint8_t A7105_Reset()
{ {
uint8_t result; uint8_t result;
A7105_WriteReg(0x00, 0x00); A7105_WriteReg(A7105_00_MODE, 0x00);
delayMilliseconds(1); delayMilliseconds(1);
A7105_SetTxRxMode(TXRX_OFF); //Set both GPIO as output and low A7105_SetTxRxMode(TXRX_OFF); //Set both GPIO as output and low
result=A7105_ReadReg(0x10) == 0x9E; //check if is reset. result=A7105_ReadReg(A7105_10_PLL_II) == 0x9E; //check if is reset.
A7105_Strobe(A7105_STANDBY); A7105_Strobe(A7105_STANDBY);
return result; return result;
} }
void A7105_WriteID(uint32_t ida) { void A7105_WriteID(uint32_t ida)
{
A7105_CSN_off; A7105_CSN_off;
SPI_Write(0x06);//ex id=0x5475c52a ;txid3txid2txid1txid0 SPI_Write(A7105_06_ID_DATA); //ex id=0x5475c52a ;txid3txid2txid1txid0
SPI_Write((ida>>24)&0xff);//53 SPI_Write((ida>>24)&0xff); //53
SPI_Write((ida>>16)&0xff);//75 SPI_Write((ida>>16)&0xff); //75
SPI_Write((ida>>8)&0xff);//c5 SPI_Write((ida>>8)&0xff); //c5
SPI_Write((ida>>0)&0xff);//2a SPI_Write((ida>>0)&0xff); //2a
A7105_CSN_on; A7105_CSN_on;
} }
@ -136,7 +151,7 @@ void A7105_SetPower()
power=A7105_RANGE_POWER; power=A7105_RANGE_POWER;
if(prev_power != power) if(prev_power != power)
{ {
A7105_WriteReg(0x28, power); A7105_WriteReg(A7105_28_TX_TEST, power);
prev_power=power; prev_power=power;
} }
} }
@ -146,53 +161,79 @@ void A7105_Strobe(uint8_t address) {
SPI_Write(address); SPI_Write(address);
A7105_CSN_on; A7105_CSN_on;
} }
#ifdef HUBSAN_A7105_INO
const uint8_t PROGMEM HUBSAN_A7105_regs[] = { const uint8_t PROGMEM HUBSAN_A7105_regs[] = {
0xFF, 0x63, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x04, 0xFF, 0xFF, 0x63, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x04, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2B, 0xFF, 0xFF, 0x62, 0x80, 0xFF, 0xFF, 0x0A, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2B, 0xFF, 0xFF, 0x62, 0x80, 0xFF, 0xFF, 0x0A, 0xFF, 0xFF, 0x07,
0x17, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x17, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF 0xFF, 0xFF
}; };
#endif
#ifdef FLYSKY_A7105_INO
const uint8_t PROGMEM FLYSKY_A7105_regs[] = { const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
0xff, 0x42, 0x00, 0x14, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50, 0xff, 0x42, 0x00, 0x14, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50,
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f, 0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f,
0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, 0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00,
0x01, 0x0f, 0xff 0x01, 0x0f
}; };
#endif
#ifdef AFHDS2A_A7105_INO
const uint8_t PROGMEM AFHDS2A_A7105_regs[] = {
0xFF, 0x42 | (1<<5), 0x00, 0x25, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c, 0x05, 0x00, 0x50, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x4f, 0x62, 0x80, 0xFF, 0xFF, 0x2a, 0x32, 0xc3, 0x1f, // 10 - 1f
0x1e, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
#endif
#define ID_NORMAL 0x55201041 #define ID_NORMAL 0x55201041
#define ID_PLUS 0xAA201041 #define ID_PLUS 0xAA201041
void A7105_Init(uint8_t protocol) void A7105_Init(void)
{ {
void *A7105_Regs; uint8_t *A7105_Regs=0;
if(protocol==INIT_FLYSKY) #ifdef HUBSAN_A7105_INO
if(protocol==MODE_HUBSAN)
{
A7105_WriteID(ID_NORMAL);
A7105_Regs=(uint8_t*)HUBSAN_A7105_regs;
}
else
#endif
{
A7105_WriteID(0x5475c52A);//0x2Ac57554
#ifdef FLYSKY_A7105_INO
if(protocol==MODE_FLYSKY)
A7105_Regs=(uint8_t*)FLYSKY_A7105_regs;
else
#endif
{
#ifdef AFHDS2A_A7105_INO
A7105_Regs=(uint8_t*)AFHDS2A_A7105_regs;
#endif
}
}
for (uint8_t i = 0; i < 0x32; i++)
{ {
A7105_WriteID(0x5475c52A);//0x2Ac57554 uint8_t val=pgm_read_byte_near(&A7105_Regs[i]);
A7105_Regs=(void *)FLYSKY_A7105_regs; if( val != 0xFF)
} A7105_WriteReg(i, val);
else
{
A7105_WriteID(ID_NORMAL);
A7105_Regs=(void *)HUBSAN_A7105_regs;
}
for (uint8_t i = 0; i < 0x33; i++){
if( pgm_read_byte_near((uint16_t)(A7105_Regs)+i) != 0xFF)
A7105_WriteReg(i, pgm_read_byte_near((uint16_t)(A7105_Regs)+i));
} }
A7105_Strobe(A7105_STANDBY); A7105_Strobe(A7105_STANDBY);
//IF Filter Bank Calibration //IF Filter Bank Calibration
A7105_WriteReg(A7105_02_CALC,1); A7105_WriteReg(A7105_02_CALC,1);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
// A7105_ReadReg(A7105_22_IF_CALIB_I); // A7105_ReadReg(A7105_22_IF_CALIB_I);
// A7105_ReadReg(A7105_24_VCO_CURCAL); // A7105_ReadReg(A7105_24_VCO_CURCAL);
if(protocol==INIT_FLYSKY) if(protocol!=MODE_HUBSAN)
{ {
//VCO Current Calibration //VCO Current Calibration
A7105_WriteReg(A7105_24_VCO_CURCAL,0x13); //Recommended calibration from A7105 Datasheet A7105_WriteReg(A7105_24_VCO_CURCAL,0x13); //Recommended calibration from A7105 Datasheet
//VCO Bank Calibration //VCO Bank Calibration
A7105_WriteReg(A7105_26_VCO_SBCAL_II,0x3b); //Recommended calibration from A7105 Datasheet A7105_WriteReg(A7105_26_VCO_SBCAL_II,0x3b); //Recommended calibration from A7105 Datasheet
} }
//VCO Bank Calibrate channel 0 //VCO Bank Calibrate channel 0
@ -208,11 +249,12 @@ void A7105_Init(uint8_t protocol)
// A7105_ReadReg(A7105_25_VCO_SBCAL_I); // A7105_ReadReg(A7105_25_VCO_SBCAL_I);
//Reset VCO Band calibration //Reset VCO Band calibration
if(protocol==INIT_FLYSKY) if(protocol!=MODE_HUBSAN)
A7105_WriteReg(A7105_25_VCO_SBCAL_I,0x08); A7105_WriteReg(A7105_25_VCO_SBCAL_I,protocol==MODE_FLYSKY?0x08:0x0A);
A7105_SetTxRxMode(TX_EN); A7105_SetTxRxMode(TX_EN);
A7105_SetPower(); A7105_SetPower();
A7105_Strobe(A7105_STANDBY); A7105_Strobe(A7105_STANDBY);
} }
#endif

View File

@ -19,146 +19,107 @@
#define EVEN_ODD 0x00 #define EVEN_ODD 0x00
//#define EVEN_ODD 0x01 //#define EVEN_ODD 0x01
static const uint8_t A7105_regs[] = {
0x00, 0x62, -1, 0x0f, 0x00, -1 , -1 , 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0xf5, 0x00, 0x15, const uint8_t PROGMEM JOYSWAY_A7105_regs[] = {
0x00, 0x62, 0xFF, 0x0f, 0x00, 0xFF , 0xFF , 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0xf5, 0x00, 0x15,
0x9e, 0x4b, 0x00, 0x03, 0x56, 0x2b, 0x12, 0x4a, 0x02, 0x80, 0x80, 0x00, 0x0e, 0x91, 0x03, 0x0f, 0x9e, 0x4b, 0x00, 0x03, 0x56, 0x2b, 0x12, 0x4a, 0x02, 0x80, 0x80, 0x00, 0x0e, 0x91, 0x03, 0x0f,
0x16, 0x2a, 0x00, -1, -1, -1, 0x3a, 0x06, 0x1f, 0x47, 0x80, 0x01, 0x05, 0x45, 0x18, 0x00, 0x16, 0x2a, 0x00, 0xFF, 0xFF, 0xFF, 0x3a, 0x06, 0x1f, 0x47, 0x80, 0x01, 0x05, 0x45, 0x18, 0x00,
0x01, 0x0f, 0x00 0x01, 0x0f, 0x00
}; };
static void joysway_build_packet() {
static uint8_t next_ch; int i;
//-100% =~ 0x03e8
static int joysway_init() //+100% =~ 0x07ca
{ //Calculate:
int i; //Center = 0x5d9
uint8_t if_calibration1; //1 % = 5
//uint8_t vco_calibration0; packet[0] = phase == 0 ? 0xdd : 0xff;
//uint8_t vco_calibration1; packet[1] = (MProtocol_id >> 24) & 0xff;
packet[2] = (MProtocol_id >> 16) & 0xff;
phase = 0; packet[3] = (MProtocol_id >> 8) & 0xff;
next_ch = 0x30; packet[4] = (MProtocol_id >> 0) & 0xff;
packet[5] = 0x00;
for (i = 0; i < 0x33; i++) static const int chmap[4] = {6, 7, 10, 11};
if((uint8_t)A7105_regs[i] != -1) for (i = 0; i < 4; i++) {
A7105_WriteReg(i, A7105_regs[i]); // if (i >= Model.num_channels) { packet[chmap[i]] = 0x64; continue; }
A7105_WriteID(0x5475c52a); packet[chmap[i]] = map(limit_channel_100(i),servo_min_100,servo_max_100,0,204);
}
A7105_Strobe(A7105_PLL); packet[8] = 0x64;
packet[9] = 0x64;
//IF Filter Bank Calibration packet[12] = 0x64;
A7105_WriteReg(0x02, 1); packet[13] = 0x64;
A7105_ReadReg(0x02); packet[14] = phase == 0 ? 0x30 : 0xaa;
uint32_t ms = micros(); uint8_t value = 0;
while(micros() - ms < 500) { for (int i = 0; i < 15; i++) { value += packet[i]; }
if(! A7105_ReadReg(0x02)) packet[15] = value;
break;
}
if (micros() - ms >= 500)
return 0;
A7105_Strobe(A7105_STANDBY);
if_calibration1 = A7105_ReadReg(0x22);
if(if_calibration1 & A7105_MASK_FBCF) {
//Calibration failed...what do we do?
return 0;
}
//VCO Current Calibration
A7105_WriteReg(0x24, 0x13); //Recomended calibration from A7105 Datasheet
A7105_WriteReg(0x25, 0x09); //Recomended calibration from A7105 Datasheet
A7105_WriteID(MProtocol_id_master);
A7105_Strobe(A7105_PLL);
A7105_WriteReg(0x02, 1);
ms = micros();
while(micros() - ms < 500) {
if(! A7105_ReadReg(0x02))
break;
}
if (micros() - ms >= 500)
return 0;
A7105_Strobe(A7105_STANDBY);
if_calibration1 = A7105_ReadReg(0x22);
if(if_calibration1 & A7105_MASK_FBCF) {
//Calibration failed...what do we do?
return 0;
}
A7105_WriteReg(0x24, 0x13); //Recomended calibration from A7105 Datasheet
A7105_WriteReg(0x25, 0x09); //Recomended calibration from A7105 Datasheet
A7105_SetTxRxMode(TX_EN);
A7105_SetPower();
A7105_Strobe(A7105_STANDBY);
return 1;
} }
static void joysway_build_packet() static uint16_t joysway_cb() {
{ if (phase == 254) {
int i; phase = 0;
//-100% =~ 0x03e8 A7105_WriteID(0x5475c52a);
//+100% =~ 0x07ca hopping_frequency_no = 0x0a;
//Calculate: } else if (phase == 2) {
//Center = 0x5d9 A7105_WriteID(MProtocol_id);
//1 % = 5 hopping_frequency_no = 0x30;
packet[0] = phase == 0 ? 0xdd : 0xff; } else {
packet[1] = (MProtocol_id_master >> 24) & 0xff; if ((phase & 0x01) ^ EVEN_ODD) {
packet[2] = (MProtocol_id_master >> 16) & 0xff; hopping_frequency_no = 0x30;
packet[3] = (MProtocol_id_master >> 8) & 0xff; } else {
packet[4] = (MProtocol_id_master >> 0) & 0xff; hopping_frequency_no = rf_ch_num;
packet[5] = 0x00; }
static const int chmap[4] = {6, 7, 10, 11}; }
for (i = 0; i < 4; i++) { if (! ((phase & 0x01) ^ EVEN_ODD)) {
// if (i >= Model.num_channels) { packet[chmap[i]] = 0x64; continue; } rf_ch_num++;
uint32_t value = (uint32_t)Servo_data[i] * 0x66 / PPM_MAX + 0x66; if (rf_ch_num == 0x45)
if (value < 0) { value = 0; } rf_ch_num = 0x30;
if (value > 0xff) { value = 0xff; } }
packet[chmap[i]] = value; joysway_build_packet();
} A7105_Strobe(A7105_STANDBY);
packet[8] = 0x64; A7105_WriteData(16, hopping_frequency_no);
packet[9] = 0x64; phase++;
packet[12] = 0x64; return 6000;
packet[13] = 0x64;
packet[14] = phase == 0 ? 0x30 : 0xaa;
uint8_t value = 0;
for (int i = 0; i < 15; i++) { value += packet[i]; }
packet[15] = value;
}
static uint16_t joysway_cb()
{
uint8_t ch;
if (phase == 254) {
phase = 0;
A7105_WriteID(0x5475c52a);
ch = 0x0a;
} else if (phase == 2) {
A7105_WriteID(MProtocol_id_master);
ch = 0x30;
} else {
if ((phase & 0x01) ^ EVEN_ODD) {
ch = 0x30;
} else {
ch = next_ch;
}
}
if (! ((phase & 0x01) ^ EVEN_ODD)) {
next_ch++;
if (next_ch == 0x45)
next_ch = 0x30;
}
joysway_build_packet();
A7105_Strobe(A7105_STANDBY);
A7105_WriteData(16, ch);
phase++;
return 6000;
} }
static uint16_t JOYSWAY_Setup() { static uint16_t JOYSWAY_Setup() {
while(1) { int i;
A7105_Reset(); u8 if_calibration1;
if (joysway_init()) //u8 vco_calibration0;
break; //u8 vco_calibration1;
counter = 0;
// next_ch = 0x30;
for (i = 0; i < 0x33; i++) {
uint8_t val=pgm_read_byte_near(&JOYSWAY_A7105_regs[i]);
if( val != 0xFF)
A7105_WriteReg(i, val);
} }
A7105_WriteID(0x5475c52a);
A7105_Strobe(A7105_PLL);
//IF Filter Bank Calibration
A7105_WriteReg(0x02, 1);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
A7105_Strobe(A7105_STANDBY);
//VCO Current Calibration
A7105_WriteReg(0x24, 0x13); //Recomended calibration from A7105 Datasheet
A7105_WriteReg(0x25, 0x09); //Recomended calibration from A7105 Datasheet
A7105_WriteID(MProtocol_id);
A7105_Strobe(A7105_PLL);
A7105_WriteReg(0x02, 1);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
A7105_Strobe(A7105_STANDBY);
A7105_WriteReg(0x24, 0x13); //Recomended calibration from A7105 Datasheet
A7105_WriteReg(0x25, 0x09); //Recomended calibration from A7105 Datasheet
A7105_SetTxRxMode(TX_EN);
A7105_SetPower();
A7105_Strobe(A7105_STANDBY);
return 2400; return 2400;
} }
#endif #endif

View File

@ -0,0 +1,351 @@
/*
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/>.
*/
// Last sync with hexfet new_protocols/flysky_a7105.c dated 2015-09-28
#ifdef AFHDS2A_A7105_INO
#define AFHDS2A_TXPACKET_SIZE 38
#define AFHDS2A_RXPACKET_SIZE 37
#define AFHDS2A_NUMFREQ 16
enum{
AFHDS2A_PACKET_STICKS,
AFHDS2A_PACKET_SETTINGS,
AFHDS2A_PACKET_FAILSAFE,
};
enum{
AFHDS2A_BIND1,
AFHDS2A_BIND2,
AFHDS2A_BIND3,
AFHDS2A_BIND4,
AFHDS2A_DATA,
};
static void AFHDS2A_calc_channels()
{
uint8_t idx = 0;
uint32_t rnd = MProtocol_id;
while (idx < AFHDS2A_NUMFREQ)
{
uint8_t i;
uint8_t 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 ^ MProtocol_id) & 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;
}
}
#if defined(TELEMETRY)
// telemetry sensors ID
enum{
AFHDS2A_SENSOR_RX_VOLTAGE = 0x00,
AFHDS2A_SENSOR_RX_ERR_RATE = 0xfe,
AFHDS2A_SENSOR_RX_RSSI = 0xfc,
AFHDS2A_SENSOR_RX_NOISE = 0xfb,
AFHDS2A_SENSOR_RX_SNR = 0xfa,
};
static void AFHDS2A_update_telemetry()
{
// AA | TXID | rx_id | sensor id | sensor # | value 16 bit big endian | sensor id ......
// max 7 sensors per packet
#if defined AFHDS2A_TELEMETRY
if (option & 0x80) {
// forward telemetry to TX, skip rx and tx id to save space
pkt[0]= TX_RSSI;
for(int i=9;i < AFHDS2A_RXPACKET_SIZE; i++)
pkt[i-8]=packet[i];
telemetry_link=2;
return;
}
#endif
for(uint8_t sensor=0; sensor<7; sensor++)
{
uint8_t index = 9+(4*sensor);
switch(packet[index])
{
case AFHDS2A_SENSOR_RX_VOLTAGE:
v_lipo = packet[index+3]<<8 | packet[index+2];
telemetry_link=1;
break;
/*case AFHDS2A_SENSOR_RX_ERR_RATE:
// packet[index+2];
break;*/
case AFHDS2A_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<AFHDS2A_NUMFREQ; ch++)
packet[11+ch] = hopping_frequency[ch];
memset( &packet[27], 0xff, 10);
packet[37] = 0x00;
switch(phase)
{
case AFHDS2A_BIND1:
packet[0] = 0xbb;
packet[9] = 0x01;
break;
case AFHDS2A_BIND2:
case AFHDS2A_BIND3:
case AFHDS2A_BIND4:
packet[0] = 0xbc;
if(phase == AFHDS2A_BIND4)
{
memcpy( &packet[5], &rx_id, 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 AFHDS2A_build_packet(uint8_t type)
{
memcpy( &packet[1], rx_tx_addr, 4);
memcpy( &packet[5], rx_id, 4);
switch(type)
{
case AFHDS2A_PACKET_STICKS:
packet[0] = 0x58;
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;
}
break;
case AFHDS2A_PACKET_FAILSAFE:
packet[0] = 0x56;
for(uint8_t ch=0; ch<14; ch++)
{
/*if((Model.limits[ch].flags & CH_FAILSAFE_EN))
{
packet[9 + ch*2] = Servo_data[CH_AETR[ch]] & 0xff;
packet[10+ ch*2] = (Servo_data[CH_AETR[ch]] >> 8) & 0xff;
}
else*/
{
packet[9 + ch*2] = 0xff;
packet[10+ ch*2] = 0xff;
}
}
break;
case AFHDS2A_PACKET_SETTINGS:
packet[0] = 0xaa;
packet[9] = 0xfd;
packet[10]= 0xff;
uint16_t val_hz=5*(option & 0x7f)+50; // option value should be between 0 and 70 which gives a value between 50 and 400Hz
if(val_hz<50 || val_hz>400) val_hz=50; // default is 50Hz
packet[11]= val_hz;
packet[12]= val_hz >> 8;
if(sub_protocol == PPM_IBUS || sub_protocol == 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(sub_protocol == PWM_SBUS || sub_protocol == PPM_SBUS)
packet[21] = 0xdd; // SBUS output enabled
else
packet[21] = 0xde; // IBUS
break;
}
packet[37] = 0x00;
}
#define AFHDS2A_WAIT_WRITE 0x80
uint16_t ReadAFHDS2A()
{
static uint8_t packet_type = AFHDS2A_PACKET_STICKS;
static uint16_t packet_counter=0;
uint8_t data_rx;
uint16_t start;
switch(phase)
{
case AFHDS2A_BIND1:
case AFHDS2A_BIND2:
case AFHDS2A_BIND3:
AFHDS2A_build_bind_packet();
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, packet_count%2 ? 0x0d : 0x8c);
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5 | 1<<6)))
{ // FECF+CRCF Ok
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
if(packet[0] == 0xbc && packet[9] == 0x01)
{
uint8_t temp=50+RX_num*4;
uint8_t i;
for(i=0; i<4; i++)
{
rx_id[i] = packet[5+i];
eeprom_write_byte((EE_ADDR)(temp+i),rx_id[i]);
}
phase = AFHDS2A_BIND4;
packet_count++;
return 3850;
}
}
packet_count++;
phase |= AFHDS2A_WAIT_WRITE;
return 1700;
case AFHDS2A_BIND1|AFHDS2A_WAIT_WRITE:
case AFHDS2A_BIND2|AFHDS2A_WAIT_WRITE:
case AFHDS2A_BIND3|AFHDS2A_WAIT_WRITE:
//Wait for TX completion
start=micros();
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetTxRxMode(RX_EN);
A7105_Strobe(A7105_RX);
phase &= ~AFHDS2A_WAIT_WRITE;
phase++;
if(phase > AFHDS2A_BIND3)
phase = AFHDS2A_BIND1;
return 2150;
case AFHDS2A_BIND4:
AFHDS2A_build_bind_packet();
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, packet_count%2 ? 0x0d : 0x8c);
packet_count++;
bind_phase++;
if(bind_phase>=4)
{
packet_counter=0;
packet_type = AFHDS2A_PACKET_STICKS;
hopping_frequency_no=1;
phase = AFHDS2A_DATA;
BIND_DONE;
}
return 3850;
case AFHDS2A_DATA:
AFHDS2A_build_packet(packet_type);
if((A7105_ReadReg(A7105_00_MODE) & 0x01)) // Check if something has been received...
data_rx=0;
else
data_rx=1; // Yes
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, hopping_frequency[hopping_frequency_no++]);
if(hopping_frequency_no >= AFHDS2A_NUMFREQ)
hopping_frequency_no = 0;
if(!(packet_counter % 1313))
packet_type = AFHDS2A_PACKET_SETTINGS;
else if(!(packet_counter % 1569))
packet_type = AFHDS2A_PACKET_FAILSAFE;
else
packet_type = AFHDS2A_PACKET_STICKS; // todo : check for settings changes
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5 | 1<<6)) && data_rx==1)
{ // RX+FECF+CRCF Ok
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
if(packet[0] == 0xaa)
{
if(packet[9] == 0xfc)
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
#if defined(TELEMETRY)
else
{
// Read TX RSSI
int16_t temp=256-(A7105_ReadReg(A7105_1D_RSSI_THOLD)*8)/5; // value from A7105 is between 8 for maximum signal strength to 160 or less
if(temp<0) temp=0;
else if(temp>255) temp=255;
TX_RSSI=temp;
AFHDS2A_update_telemetry();
}
#endif
}
}
packet_counter++;
phase |= AFHDS2A_WAIT_WRITE;
return 1700;
case AFHDS2A_DATA|AFHDS2A_WAIT_WRITE:
//Wait for TX completion
start=micros();
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetTxRxMode(RX_EN);
A7105_Strobe(A7105_RX);
phase &= ~AFHDS2A_WAIT_WRITE;
return 2150;
}
return 3850; // never reached, please the compiler
}
uint16_t initAFHDS2A()
{
A7105_Init();
AFHDS2A_calc_channels();
packet_count = 0;
bind_phase = 0;
if(IS_AUTOBIND_FLAG_on)
phase = AFHDS2A_BIND1;
else
{
phase = AFHDS2A_DATA;
//Read RX ID from EEPROM based on RX_num, RX_num must be uniq for each RX
uint8_t temp=50+RX_num*4;
for(uint8_t i=0;i<4;i++)
rx_id[i]=eeprom_read_byte((EE_ADDR)(temp+i));
}
hopping_frequency_no = 0;
return 50000;
}
#endif

View File

@ -12,9 +12,23 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef STM32_BOARD
/************************************/
/************************************/ /************************************/
/** Arduino replacement routines **/ /** Arduino replacement routines **/
/************************************/ /************************************/
// replacement map()
int16_t map( int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max)
{
// return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
long y ;
x -= in_min ;
y = out_max - out_min ;
y *= x ;
x = y / (in_max - in_min) ;
return x + out_min ;
}
// replacement millis() and micros() // replacement millis() and micros()
// These work polled, no interrupts // These work polled, no interrupts
// micros() MUST be called at least once every 32 milliseconds // micros() MUST be called at least once every 32 milliseconds
@ -106,7 +120,7 @@ void delayMicroseconds(unsigned int us)
return; return;
us <<= 2; // * 4 us <<= 2; // * 4
us -= 2; // - 2 us -= 2; // - 2
#ifdef XMEGA #ifdef ORANGE_TX
__asm__ __volatile__ ( __asm__ __volatile__ (
"1: sbiw %0,1" "\n\t" // 2 cycles "1: sbiw %0,1" "\n\t" // 2 cycles
"nop \n" "nop \n"
@ -123,11 +137,12 @@ void delayMicroseconds(unsigned int us)
#endif #endif
} }
#ifndef XMEGA #ifndef ORANGE_TX
void init() void init()
{ {
// this needs to be called before setup() or some functions won't work there // this needs to be called before setup() or some functions won't work there
sei(); sei();
} }
#endif //XMEGA #endif //ORANGE_TX
#endif //STM32_BOARD

View File

@ -0,0 +1,20 @@
@echo off
if "%AVR32_HOME%"=="" (
echo.
echo You must install winavr to compile Multi for OrangeTX: https://sourceforge.net/projects/winavr/
echo.
pause
exit /b
)
if exist MultiOrange.cpp.orangetx ren *.orangetx *.
if exist .dep (make clean)
md .dep
make
if exist MultiOrange.hex (
objcopy -I ihex MultiOrange.hex -O binary MultiOrange.bin
echo.
echo Compilation OK.
echo Use MultiOrange.hex to program your OrangeTX module.
echo.
)
pause

View File

@ -1,3 +1,4 @@
/* /*
This project is free software: you can redistribute it and/or modify This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -17,6 +18,7 @@
//CC2500 SPI routines //CC2500 SPI routines
//------------------------------- //-------------------------------
//------------------------------- //-------------------------------
#ifdef CC2500_INSTALLED
#include "iface_cc2500.h" #include "iface_cc2500.h"
//---------------------------- //----------------------------
@ -152,4 +154,4 @@ void CC2500_SetPower()
prev_power=power; prev_power=power;
} }
} }
#endif

View File

@ -56,18 +56,23 @@ enum YD829_FLAGS {
}; };
enum H8_3D_FLAGS { enum H8_3D_FLAGS {
// flags going to packet[17] // flags going to packet[17]
H8_3D_FLAG_FLIP = 0x01, H8_3D_FLAG_FLIP = 0x01,
H8_3D_FLAG_RATE_MID = 0x02, H8_3D_FLAG_RATE_MID = 0x02,
H8_3D_FLAG_RATE_HIGH = 0x04, H8_3D_FLAG_RATE_HIGH = 0x04,
H8_3D_FLAG_LIGTH = 0x08, // Light on H22 H8_3D_FLAG_LIGTH = 0x08, // Light on H22
H8_3D_FLAG_HEADLESS = 0x10, // RTH + headless on H8, headless on JJRC H20, RTH on H22 H8_3D_FLAG_HEADLESS = 0x10, // RTH + headless on H8, headless on JJRC H20, RTH on H22
H8_3D_FLAG_RTH = 0x20, // 360 flip mode on H8 3D and H22, RTH on JJRC H20 H8_3D_FLAG_RTH = 0x20, // 360 flip mode on H8 3D and H22, RTH on JJRC H20
}; };
enum H8_3D_FLAGS_2 { enum H8_3D_FLAGS_2 {
// flags going to packet[18] // flags going to packet[18]
H8_3D_FLAG_CALIBRATE = 0x20, // accelerometer calibration H8_3D_FLAG_CAM_UP = 0x04,
H8_3D_FLAG_CAM_DOWN = 0x08,
H8_3D_FLAG_CALIBRATE2 = 0x10, // acc calib. (H11D, H20)
H8_3D_FLAG_CALIBRATE = 0x20, // acc calib. (H8 3D), headless calib (H20)
H8_3D_FLAG_SNAPSHOT = 0x40,
H8_3D_FLAG_VIDEO = 0x80,
}; };
static void __attribute__((unused)) CG023_send_packet(uint8_t bind) static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
@ -119,8 +124,10 @@ static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
| GET_FLAG(Servo_AUX2,H8_3D_FLAG_LIGTH) //H22 light | GET_FLAG(Servo_AUX2,H8_3D_FLAG_LIGTH) //H22 light
| GET_FLAG(Servo_AUX3,H8_3D_FLAG_HEADLESS) | GET_FLAG(Servo_AUX3,H8_3D_FLAG_HEADLESS)
| GET_FLAG(Servo_AUX4,H8_3D_FLAG_RTH); // 180/360 flip mode on H8 3D | GET_FLAG(Servo_AUX4,H8_3D_FLAG_RTH); // 180/360 flip mode on H8 3D
if(Servo_AUX5) packet[18] = GET_FLAG(Servo_AUX5,H8_3D_FLAG_CALIBRATE)
packet[18] = H8_3D_FLAG_CALIBRATE; | GET_FLAG(Servo_AUX5,H8_3D_FLAG_CALIBRATE2)
| GET_FLAG(Servo_AUX6,H8_3D_FLAG_SNAPSHOT)
| GET_FLAG(Servo_AUX7,H8_3D_FLAG_VIDEO);
} }
uint8_t sum = packet[9]; uint8_t sum = packet[9];
for (uint8_t i=10; i < H8_3D_PACKET_SIZE-1; i++) for (uint8_t i=10; i < H8_3D_PACKET_SIZE-1; i++)

View File

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

View File

@ -12,9 +12,9 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef CYRF6936_INSTALLED
#include "iface_cyrf6936.h" #include "iface_cyrf6936.h"
void CYRF_WriteRegister(uint8_t address, uint8_t data) void CYRF_WriteRegister(uint8_t address, uint8_t data)
{ {
CYRF_CSN_off; CYRF_CSN_off;
@ -182,28 +182,16 @@ void CYRF_WritePreamble(uint32_t preamble)
/* /*
* *
*/ */
static void CYRF_StartReceive()
{
CYRF_WriteRegister(CYRF_05_RX_CTRL,0x87);
}
/*static void CYRF_ReadDataPacket(uint8_t dpbuffer[]) /*static void CYRF_ReadDataPacket(uint8_t dpbuffer[])
{ {
CYRF_ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, 0x10); 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) void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length)
>>>>>>> refs/remotes/pascallanger/master
{ {
CYRF_ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, length); CYRF_ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, length);
} }
<<<<<<< HEAD
=======
>>>>>>> refs/remotes/pascallanger/master
static void CYRF_WriteDataPacketLen(const uint8_t dpbuffer[], uint8_t len) static void CYRF_WriteDataPacketLen(const uint8_t dpbuffer[], uint8_t len)
{ {
CYRF_WriteRegister(CYRF_01_TX_LENGTH, len); CYRF_WriteRegister(CYRF_01_TX_LENGTH, len);
@ -250,10 +238,14 @@ void CYRF_FindBestChannels(uint8_t *channels, uint8_t len, uint8_t minspace, uin
for(i = 0; i < NUM_FREQ; i++) for(i = 0; i < NUM_FREQ; i++)
{ {
CYRF_ConfigRFChannel(i); CYRF_ConfigRFChannel(i);
CYRF_ReadRegister(CYRF_13_RSSI); delayMicroseconds(270); //slow channel require 270usec for synthesizer to settle
CYRF_StartReceive(); if( !(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80)) {
delayMicroseconds(10); CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x80); //Prepare to receive
rssi[i] = CYRF_ReadRegister(CYRF_13_RSSI); delayMicroseconds(15);
CYRF_ReadRegister(CYRF_13_RSSI); //dummy read
delayMicroseconds(15); //The conversion can occur as often as once every 12us
}
rssi[i] = CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;
} }
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
@ -269,7 +261,9 @@ void CYRF_FindBestChannels(uint8_t *channels, uint8_t len, uint8_t minspace, uin
rssi[j] = 0xff; rssi[j] = 0xff;
} }
} }
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
CYRF_SetTxRxMode(TX_EN); CYRF_SetTxRxMode(TX_EN);
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Clear abort RX
} }
#if defined(DEVO_CYRF6936_INO) || defined(J6PRO_CYRF6936_INO) #if defined(DEVO_CYRF6936_INO) || defined(J6PRO_CYRF6936_INO)
@ -304,4 +298,5 @@ static void __attribute__((unused)) CYRF_PROGMEM_ConfigSOPCode(const uint8_t *da
for(uint8_t i=0;i<8;i++) for(uint8_t i=0;i<8;i++)
code[i]=pgm_read_byte_near(&data[i]); code[i]=pgm_read_byte_near(&data[i]);
CYRF_ConfigSOPCode(code); CYRF_ConfigSOPCode(code);
} }
#endif

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

View File

@ -15,17 +15,6 @@
/************************/ /************************/
/** Convert routines **/ /** Convert routines **/
/************************/ /************************/
int16_t map( int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max)
{
// return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
long y ;
x -= in_min ;
y = out_max - out_min ;
y *= x ;
x = y / (in_max - in_min) ;
return x + out_min ;
}
// Channel value is converted to 8bit values full scale // Channel value is converted to 8bit values full scale
uint8_t convert_channel_8b(uint8_t num) uint8_t convert_channel_8b(uint8_t num)
{ {

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

@ -135,8 +135,7 @@ static uint8_t __attribute__((unused)) get_pn_row(uint8_t channel)
} }
const uint8_t PROGMEM init_vals[][2] = { const uint8_t PROGMEM init_vals[][2] = {
{CYRF_02_TX_CTRL, 0x03}, // TX interrupt complete and error enabled {CYRF_02_TX_CTRL, 0x00}, // All TX interrupt disabled
//0x00 in deviation but needed to know when transmit is over
{CYRF_05_RX_CTRL, 0x00}, // All RX interrupt disabled {CYRF_05_RX_CTRL, 0x00}, // All RX interrupt disabled
{CYRF_28_CLK_EN, 0x02}, // Force receive clock enable {CYRF_28_CLK_EN, 0x02}, // Force receive clock enable
{CYRF_32_AUTO_CAL_TIME, 0x3c}, // Default init value {CYRF_32_AUTO_CAL_TIME, 0x3c}, // Default init value
@ -369,13 +368,13 @@ static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
uint16_t ReadDsm() uint16_t ReadDsm()
{ {
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2 #define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
#define DSM_WRITE_DELAY 1550 // Time after write to verify write complete #define DSM_WRITE_DELAY 1950 // Time after write to verify write complete
#define DSM_READ_DELAY 600 // Time before write to check read phase, and switch channels. Was 400 but 600 seems what the 328p needs to read a packet #define DSM_READ_DELAY 600 // Time before write to check read phase, and switch channels. Was 400 but 600 seems what the 328p needs to read a packet
uint16_t start;
#if defined DSM_TELEMETRY #if defined DSM_TELEMETRY
uint8_t rx_phase; uint8_t rx_phase;
uint8_t len; uint8_t len;
#endif #endif
uint8_t start;
switch(phase) switch(phase)
{ {
@ -451,19 +450,28 @@ uint16_t ReadDsm()
return DSM_WRITE_DELAY; return DSM_WRITE_DELAY;
case DSM_CH1_CHECK_A: case DSM_CH1_CHECK_A:
case DSM_CH1_CHECK_B: case DSM_CH1_CHECK_B:
start=micros();
while ((uint16_t)micros()-start < 500) // Wait max 500µs
if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)
break;
set_sop_data_crc();
phase++; // change from CH1_CHECK to CH2_WRITE
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
case DSM_CH2_CHECK_A: case DSM_CH2_CHECK_A:
case DSM_CH2_CHECK_B: case DSM_CH2_CHECK_B:
start=micros(); start=micros();
while ((uint16_t)micros()-start < 500) // Wait max 500µs while ((uint8_t)micros()-start < 100) // Wait max 100µs, max I've seen is 50µs
if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02) if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)
break; break;
if(phase==DSM_CH1_CHECK_A || phase==DSM_CH1_CHECK_B)
{
#if defined DSM_TELEMETRY
// reset cyrf6936 if freezed after switching from TX to RX
if (((CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x22) == 0x20) || (CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80))
{
CYRF_Reset();
cyrf_config();
cyrf_configdata();
CYRF_SetTxRxMode(TX_EN);
}
#endif
set_sop_data_crc();
phase++; // change from CH1_CHECK to CH2_WRITE
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
}
if (phase == DSM_CH2_CHECK_A) if (phase == DSM_CH2_CHECK_A)
CYRF_SetPower(0x28); //Keep transmit power in sync CYRF_SetPower(0x28); //Keep transmit power in sync
#if defined DSM_TELEMETRY #if defined DSM_TELEMETRY

View File

@ -43,31 +43,7 @@ enum {
DEVO_BOUND_10, 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() static void __attribute__((unused)) DEVO_scramble_pkt()
>>>>>>> refs/remotes/pascallanger/master
{ {
#ifdef NO_SCRAMBLE #ifdef NO_SCRAMBLE
return; return;
@ -77,11 +53,7 @@ static void __attribute__((unused)) DEVO_scramble_pkt()
#endif #endif
} }
<<<<<<< HEAD
static void __attribute__((unused)) add_pkt_suffix()
=======
static void __attribute__((unused)) DEVO_add_pkt_suffix() static void __attribute__((unused)) DEVO_add_pkt_suffix()
>>>>>>> refs/remotes/pascallanger/master
{ {
uint8_t bind_state; uint8_t bind_state;
#ifdef ENABLE_PPM #ifdef ENABLE_PPM
@ -91,7 +63,7 @@ static void __attribute__((unused)) DEVO_add_pkt_suffix()
BIND_SET_PULLUP; // set pullup BIND_SET_PULLUP; // set pullup
if(IS_BIND_BUTTON_on) if(IS_BIND_BUTTON_on)
{ {
eeprom_write_byte((uint8_t*)(30+mode_select),0x01); // Set fixed id mode for the current model eeprom_write_byte((EE_ADDR)(30+mode_select),0x01); // Set fixed id mode for the current model
option=1; option=1;
} }
BIND_SET_OUTPUT; BIND_SET_OUTPUT;
@ -119,11 +91,7 @@ static void __attribute__((unused)) DEVO_add_pkt_suffix()
packet[15] = (MProtocol_id >> 16) & 0xff; 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) static void __attribute__((unused)) DEVO_build_beacon_pkt(uint8_t upper)
>>>>>>> refs/remotes/pascallanger/master
{ {
packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x07; packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x07;
uint8_t max = 8; uint8_t max = 8;
@ -138,11 +106,7 @@ static void __attribute__((unused)) DEVO_build_beacon_pkt(uint8_t upper)
DEVO_add_pkt_suffix(); DEVO_add_pkt_suffix();
} }
<<<<<<< HEAD
static void __attribute__((unused)) build_bind_pkt()
=======
static void __attribute__((unused)) DEVO_build_bind_pkt() static void __attribute__((unused)) DEVO_build_bind_pkt()
>>>>>>> refs/remotes/pascallanger/master
{ {
packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x0a; packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x0a;
packet[1] = bind_counter & 0xff; packet[1] = bind_counter & 0xff;
@ -162,11 +126,7 @@ static void __attribute__((unused)) DEVO_build_bind_pkt()
packet[15] ^= cyrfmfg_id[2]; packet[15] ^= cyrfmfg_id[2];
} }
<<<<<<< HEAD
static void __attribute__((unused)) build_data_pkt()
=======
static void __attribute__((unused)) DEVO_build_data_pkt() static void __attribute__((unused)) DEVO_build_data_pkt()
>>>>>>> refs/remotes/pascallanger/master
{ {
static uint8_t ch_idx=0; static uint8_t ch_idx=0;
@ -190,11 +150,7 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
DEVO_add_pkt_suffix(); DEVO_add_pkt_suffix();
} }
<<<<<<< HEAD
static void __attribute__((unused)) cyrf_set_bound_sop_code()
=======
static void __attribute__((unused)) DEVO_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 */ /* 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]); 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); CYRF_SetPower(0x08);
} }
<<<<<<< HEAD
static void __attribute__((unused)) cyrf_init()
=======
const uint8_t PROGMEM DEVO_init_vals[][2] = { const uint8_t PROGMEM DEVO_init_vals[][2] = {
{ CYRF_1D_MODE_OVERRIDE, 0x38 }, { CYRF_1D_MODE_OVERRIDE, 0x38 },
{ CYRF_03_TX_CFG, 0x08 }, { CYRF_03_TX_CFG, 0x08 },
@ -233,18 +186,13 @@ const uint8_t PROGMEM DEVO_init_vals[][2] = {
}; };
static void __attribute__((unused)) DEVO_cyrf_init() static void __attribute__((unused)) DEVO_cyrf_init()
>>>>>>> refs/remotes/pascallanger/master
{ {
/* Initialise CYRF chip */ /* Initialise CYRF chip */
for(uint8_t i = 0; i < sizeof(DEVO_init_vals) / 2; i++) 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]) ); 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() static void __attribute__((unused)) DEVO_set_radio_channels()
>>>>>>> refs/remotes/pascallanger/master
{ {
CYRF_FindBestChannels(hopping_frequency, 3, 4, 4, 80); CYRF_FindBestChannels(hopping_frequency, 3, 4, 4, 80);
hopping_frequency[3] = hopping_frequency[0]; hopping_frequency[3] = hopping_frequency[0];
@ -337,35 +285,6 @@ uint16_t devo_callback()
return 1200; 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() uint16_t DevoInit()
{ {
DEVO_cyrf_init(); DEVO_cyrf_init();

View File

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

View File

@ -21,34 +21,6 @@
//FlySky constants & variables //FlySky constants & variables
#define FLYSKY_BIND_COUNT 2500 #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 { enum {
// flags going to byte 10 // flags going to byte 10
FLAG_V9X9_VIDEO = 0x40, FLAG_V9X9_VIDEO = 0x40,
@ -56,27 +28,26 @@ enum {
// flags going to byte 12 // flags going to byte 12
FLAG_V9X9_FLIP = 0x10, FLAG_V9X9_FLIP = 0x10,
FLAG_V9X9_LED = 0x20, FLAG_V9X9_LED = 0x20,
>>>>>>> refs/remotes/pascallanger/master
}; };
enum { enum {
// flags going to byte 13 // flags going to byte 13
FLAG_V6X6_HLESS1= 0x80, FLAG_V6X6_HLESS1= 0x80,
// flags going to byte 14 // flags going to byte 14
FLAG_V6X6_VIDEO = 0x01, FLAG_V6X6_VIDEO = 0x01,
FLAG_V6X6_YCAL = 0x02, FLAG_V6X6_YCAL = 0x02,
FLAG_V6X6_XCAL = 0x04, FLAG_V6X6_XCAL = 0x04,
FLAG_V6X6_RTH = 0x08, FLAG_V6X6_RTH = 0x08,
FLAG_V6X6_CAMERA= 0x10, FLAG_V6X6_CAMERA= 0x10,
FLAG_V6X6_HLESS2= 0x20, FLAG_V6X6_HLESS2= 0x20,
FLAG_V6X6_LED = 0x40, FLAG_V6X6_LED = 0x40,
FLAG_V6X6_FLIP = 0x80, FLAG_V6X6_FLIP = 0x80,
}; };
enum { enum {
// flags going to byte 14 // flags going to byte 14
FLAG_V912_TOPBTN= 0x40, FLAG_V912_TOPBTN= 0x40,
FLAG_V912_BTMBTN= 0x80, FLAG_V912_BTMBTN= 0x80,
}; };
const uint8_t PROGMEM V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, // sometime first byte is 0x15 ? 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() 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; static uint8_t seq_counter;
switch(sub_protocol) switch(sub_protocol)
{ {
@ -226,78 +124,39 @@ static void __attribute__((unused)) flysky_apply_extension_flags()
default: default:
break; break;
} }
>>>>>>> refs/remotes/pascallanger/master
} }
static void __attribute__((unused)) flysky_build_packet(uint8_t init) static void __attribute__((unused)) flysky_build_packet(uint8_t init)
{ {
uint8_t i; uint8_t i;
//servodata timing range for flysky. //servodata timing range for flysky.
////-100% =~ 0x03e8//=1000us(min) ////-100% =~ 0x03e8//=1000us(min)
//+100% =~ 0x07ca//=1994us(max) //+100% =~ 0x07ca//=1994us(max)
//Center = 0x5d9//=1497us(center) //Center = 0x5d9//=1497us(center)
//channel order AIL;ELE;THR;RUD;AUX1;AUX2;AUX3;AUX4 //channel order AIL;ELE;THR;RUD;AUX1;AUX2;AUX3;AUX4
packet[0] = init ? 0xaa : 0x55; packet[0] = init ? 0xaa : 0x55;
packet[1] = rx_tx_addr[3]; packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2]; packet[2] = rx_tx_addr[2];
packet[3] = rx_tx_addr[1]; packet[3] = rx_tx_addr[1];
packet[4] = rx_tx_addr[0]; 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++) for(i = 0; i < 8; i++)
{ {
packet[5 + i*2]=Servo_data[CH_AETR[i]]&0xFF; //low byte of servo timing(1000-2000us) 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) 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(); flysky_apply_extension_flags();
} }
uint16_t ReadFlySky() uint16_t ReadFlySky()
{ {
if (bind_counter) if (bind_counter)
{ {
flysky_build_packet(1); flysky_build_packet(1);
A7105_WriteData(21, 1); A7105_WriteData(21, 1);
bind_counter--; bind_counter--;
if (! bind_counter) if (! bind_counter)
BIND_DONE; 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 else
{ {
flysky_build_packet(0); flysky_build_packet(0);
@ -325,7 +184,7 @@ uint16_t initFlySky()
uint8_t chanoffset; uint8_t chanoffset;
uint8_t temp; uint8_t temp;
A7105_Init(INIT_FLYSKY); //flysky_init(); A7105_Init();
if ((rx_tx_addr[3]&0xF0) > 0x90) // limit offset to 9 as higher values don't work with some RX (ie V912) if ((rx_tx_addr[3]&0xF0) > 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; rx_tx_addr[3]=rx_tx_addr[3]-0x70;
@ -352,7 +211,5 @@ uint16_t initFlySky()
else else
bind_counter = 0; bind_counter = 0;
return 2400; return 2400;
>>>>>>> refs/remotes/pascallanger/master
} }
#endif #endif

View File

@ -17,297 +17,9 @@
*/ */
#if defined(FRSKYX_CC2500_INO) #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) #include "iface_cc2500.h"
{
return pgm_read_byte_near(&hop_data[byte]);
}
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 chanskip;
uint8_t counter_rst; uint8_t counter_rst;
uint8_t ctr; uint8_t ctr;
@ -562,13 +274,14 @@ uint16_t ReadFrSkyX()
return 3000; return 3000;
case FRSKY_DATA4: case FRSKY_DATA4:
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && (len<MAX_PKT)) if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
{ {
counter=0;
CC2500_ReadData(pkt, len); CC2500_ReadData(pkt, len);
#if defined TELEMETRY #if defined TELEMETRY
frsky_check_telemetry(pkt,len); //check if valid telemetry packets frsky_check_telemetry(pkt,len); //check if valid telemetry packets
//parse telemetry packets here //parse telemetry packets here
//The same telemetry function used by FrSky(D8). //The same telemetry function used by FrSky(D8).
#endif #endif
} }
else else
@ -580,7 +293,11 @@ uint16_t ReadFrSkyX()
seq_last_sent = 0; seq_last_sent = 0;
seq_last_rcvd = 8; seq_last_rcvd = 8;
counter=0; counter=0;
#if defined TELEMETRY
telemetry_lost=1;
#endif
} }
CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO
} }
state = FRSKY_DATA1; state = FRSKY_DATA1;
return 300; return 300;
@ -617,5 +334,4 @@ uint16_t initFrSkyX()
seq_last_rcvd = 8; seq_last_rcvd = 8;
return 10000; return 10000;
} }
>>>>>>> refs/remotes/pascallanger/master
#endif #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; uint8_t i,j;
for (i = 0; i< 8; i++) { for (i = 0; i< 8; i++) {
j=CH_AETR[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 if (j == THROTTLE) // It is clear that hisky's throttle stick is made reversely, so I adjust it here on purpose
temp = 1000 -temp; temp = 1000 -temp;
if (j == AUX3) if (j == AUX3)

View File

@ -70,6 +70,7 @@ static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
} }
else else
{ {
/*
if(sub_protocol == FORMAT_JJRCX1) if(sub_protocol == FORMAT_JJRCX1)
packet[0] = GET_FLAG(Servo_AUX2, 0x02); // Arm packet[0] = GET_FLAG(Servo_AUX2, 0x02); // Arm
else 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 packet[9] = convert_channel_8b_scale(ELEVATOR, 0, 63)-31; // Elevator trim
else else
packet[9] = convert_channel_8b_scale(ELEVATOR, 0, 32)-16; // Elevator trim 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; packet_size=HONTAI_PACKET_SIZE;
} }
crc16(packet, packet_size); crc16(packet, packet_size);
@ -172,7 +226,8 @@ static void __attribute__((unused)) HONTAI_init()
const uint8_t PROGMEM hopping_frequency_nonels[][3] = { const uint8_t PROGMEM hopping_frequency_nonels[][3] = {
{0x05, 0x19, 0x28}, // Hontai {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] = { const uint8_t PROGMEM addr_vals[4][16] = {
{0x24, 0x26, 0x2a, 0x2c, 0x32, 0x34, 0x36, 0x4a, 0x4c, 0x4e, 0x54, 0x56, 0x5a, 0x64, 0x66, 0x6a}, {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) #if defined(HUBSAN_A7105_INO)
#include "iface_a7105.h" #include "iface_a7105.h"
enum {
FORMAT_H107 = 0,
FORMAT_H301,
FORMAT_H501,
};
enum{ enum{
// flags going to packet[9] (Normal) // flags going to packet[9] (H107 Normal)
HUBSAN_FLAG_VIDEO= 0x01, // record video HUBSAN_FLAG_VIDEO= 0x01, // record video
HUBSAN_FLAG_FLIP = 0x08, // enable flips HUBSAN_FLAG_FLIP = 0x08, // enable flips
HUBSAN_FLAG_LED = 0x04 // enable LEDs HUBSAN_FLAG_LED = 0x04 // enable LEDs
}; };
enum{ enum{
// flags going to packet[9] (Plus series) // flags going to packet[9] (H107 Plus series)
HUBSAN_FLAG_HEADLESS = 0x08, // headless mode HUBSAN_FLAG_HEADLESS = 0x08, // headless mode
}; };
enum{ 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_SNAPSHOT = 0x01,
HUBSAN_FLAG_FLIP_PLUS = 0x80, 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; 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[3] = (sessionid >> 16) & 0xFF;
packet[4] = (sessionid >> 8) & 0xFF; packet[4] = (sessionid >> 8) & 0xFF;
packet[5] = (sessionid >> 0) & 0xFF; packet[5] = (sessionid >> 0) & 0xFF;
if(id_data == ID_NORMAL) if(id_data == ID_NORMAL && sub_protocol != FORMAT_H501)
{ {
packet[6] = 0x08; packet[6] = 0x08;
packet[7] = 0xe4; packet[7] = 0xe4;
@ -89,7 +116,7 @@ static void __attribute__((unused)) hubsan_build_bind_packet(uint8_t bind_state)
packet[13] = 0x26; packet[13] = 0x26;
packet[14] = 0x79; packet[14] = 0x79;
} }
else else if(id_data == ID_PLUS || sub_protocol == FORMAT_H501)
{ //ID_PLUS { //ID_PLUS
if(phase >= BIND_3) 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 void __attribute__((unused)) hubsan_build_packet()
{ {
static uint8_t vtx_freq = 0; static uint8_t vtx_freq = 0;
static uint32_t h501_packet = 0;
memset(packet, 0, 16); memset(packet, 0, 16);
if(vtx_freq != option || packet_count==100) // set vTX frequency (H107D) 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[4] = 0xFF - convert_channel_8b(RUDDER); //Rudder is reversed
packet[6] = 0xFF - convert_channel_8b(ELEVATOR); //Elevator is reversed packet[6] = 0xFF - convert_channel_8b(ELEVATOR); //Elevator is reversed
packet[8] = convert_channel_8b(AILERON); //Aileron 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) if( packet_count < 100)
{ {
@ -151,21 +179,50 @@ static void __attribute__((unused)) hubsan_build_packet()
packet[13] = 0x26; packet[13] = 0x26;
packet[14] = 0x79; packet[14] = 0x79;
} }
else else if( sub_protocol == FORMAT_H301) {
{ //ID_PLUS if(packet_count < 100) {
packet[3] = 0x64; packet[9] = FLAG_H301_STAB;
packet[5] = 0x64; packet_count++;
packet[7] = 0x64; } else {
packet[9] = 0x06; packet[9] = 0;
//FLIP|LIGHT|PICTURE|VIDEO|HEADLESS if(Servo_AUX1) packet[9] |= FLAG_H301_LED;
if(Servo_AUX4) packet[9] |= HUBSAN_FLAG_VIDEO; if(Servo_AUX2) packet[9] |= FLAG_H301_STAB;
if(Servo_AUX5) packet[9] |= HUBSAN_FLAG_HEADLESS; if(Servo_AUX3) packet[9] |= FLAG_H301_RTH;
packet[10]= 0x19; if(Servo_AUX4) packet[9] |= FLAG_H301_VIDEO; // H102D
packet[12]= 0x5C; // ghost channel ? }
packet[13] = 0; packet[10] = 0x18; // ?
if(Servo_AUX3) packet[13] = HUBSAN_FLAG_SNAPSHOT; packet[12] = 0x5c; // ?
if(Servo_AUX1) packet[13] |= HUBSAN_FLAG_FLIP_PLUS; packet[14] = 0xf6; // ?
packet[14]= 0x49; // ghost channel ? } 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) if(packet_count < 100)
{ // set channels to neutral for first 100 packets { // set channels to neutral for first 100 packets
packet[2] = 0x80; // throttle neutral is at mid stick on plus series 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[13]= 0x00;
packet_count++; 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(); hubsan_update_crc();
} }
@ -205,7 +274,7 @@ uint16_t ReadHubsan()
switch(phase) { switch(phase) {
case BIND_1: case BIND_1:
bind_count++; bind_count++;
if(bind_count >= 20) if(bind_count >= 20 && sub_protocol != FORMAT_H501)
{ {
if(id_data == ID_NORMAL) if(id_data == ID_NORMAL)
id_data = ID_PLUS; id_data = ID_PLUS;
@ -218,7 +287,6 @@ uint16_t ReadHubsan()
case BIND_5: case BIND_5:
case BIND_7: case BIND_7:
hubsan_build_bind_packet(phase == BIND_7 ? 9 : (phase == BIND_5 ? 1 : phase + 1 - BIND_1)); hubsan_build_bind_packet(phase == BIND_7 ? 9 : (phase == BIND_5 ? 1 : phase + 1 - BIND_1));
A7105_Strobe(A7105_STANDBY);
A7105_WriteData(16, channel); A7105_WriteData(16, channel);
phase |= WAIT_WRITE; phase |= WAIT_WRITE;
return 3000; return 3000;
@ -253,7 +321,7 @@ uint16_t ReadHubsan()
phase = BIND_1; phase = BIND_1;
return 4500; //No signal, restart binding procedure. 12msec elapsed since last write return 4500; //No signal, restart binding procedure. 12msec elapsed since last write
} }
A7105_ReadData(); A7105_ReadData(16);
phase++; phase++;
if (phase == BIND_5) if (phase == BIND_5)
A7105_WriteID(((uint32_t)packet[2] << 24) | ((uint32_t)packet[3] << 16) | ((uint32_t)packet[4] << 8) | packet[5]); A7105_WriteID(((uint32_t)packet[2] << 24) | ((uint32_t)packet[3] << 16) | ((uint32_t)packet[4] << 8) | packet[5]);
@ -264,7 +332,7 @@ uint16_t ReadHubsan()
phase = BIND_7; phase = BIND_7;
return 15000; //22.5msec elapsed since last write return 15000; //22.5msec elapsed since last write
} }
A7105_ReadData(); A7105_ReadData(16);
if(packet[1] == 9 && id_data == ID_NORMAL) { if(packet[1] == 9 && id_data == ID_NORMAL) {
phase = DATA_1; phase = DATA_1;
A7105_WriteReg(A7105_1F_CODE_I, 0x0F); A7105_WriteReg(A7105_1F_CODE_I, 0x0F);
@ -286,8 +354,15 @@ uint16_t ReadHubsan()
if( phase == DATA_1) if( phase == DATA_1)
A7105_SetPower(); //Keep transmit power in sync A7105_SetPower(); //Keep transmit power in sync
hubsan_build_packet(); hubsan_build_packet();
A7105_Strobe(A7105_STANDBY); u8 ch;
A7105_WriteData(16, phase == DATA_5 && id_data == ID_NORMAL ? channel + 0x23 : channel); 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) if (phase == DATA_5)
phase = DATA_1; phase = DATA_1;
else else
@ -314,7 +389,7 @@ uint16_t ReadHubsan()
{ {
if( !(A7105_ReadReg(A7105_00_MODE) & 0x01)) if( !(A7105_ReadReg(A7105_00_MODE) & 0x01))
{ // data received { // data received
A7105_ReadData(); A7105_ReadData(16);
if( hubsan_check_integrity() ) if( hubsan_check_integrity() )
{ {
v_lipo=packet[13];// hubsan lipo voltage 8bits the real value is h_lipo/10(0x2A=42 -> 4.2V) v_lipo=packet[13];// hubsan lipo voltage 8bits the real value is h_lipo/10(0x2A=42 -> 4.2V)
@ -322,9 +397,10 @@ uint16_t ReadHubsan()
} }
A7105_Strobe(A7105_RX); A7105_Strobe(A7105_RX);
// Read TX RSSI // Read TX RSSI
RSSI_dBm=256-(A7105_ReadReg(A7105_1D_RSSI_THOLD)*8)/5; // value from A7105 is between 8 for maximum signal strength to 160 or less int16_t temp=256-(A7105_ReadReg(A7105_1D_RSSI_THOLD)*8)/5; // value from A7105 is between 8 for maximum signal strength to 160 or less
if(RSSI_dBm<0) RSSI_dBm=0; if(temp<0) temp=0;
else if(RSSI_dBm>255) RSSI_dBm=255; else if(temp>255) temp=255;
TX_RSSI=temp;
break; break;
} }
} }
@ -343,7 +419,7 @@ uint16_t ReadHubsan()
uint16_t initHubsan() { uint16_t initHubsan() {
const uint8_t allowed_ch[] = {0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82}; const uint8_t allowed_ch[] = {0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82};
A7105_Init(INIT_HUBSAN); //hubsan_init(); A7105_Init();
sessionid = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16); sessionid = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16);
channel = allowed_ch[random(0xfefefefe) % sizeof(allowed_ch)]; channel = allowed_ch[random(0xfefefefe) % sizeof(allowed_ch)];

View File

@ -55,10 +55,10 @@ static void __attribute__((unused)) j6pro_build_data_packet()
{ {
uint8_t i; uint8_t i;
uint32_t upperbits = 0; uint32_t upperbits = 0;
uint16_t value; uint16_t value;
packet[0] = 0xaa; //FIXME what is this? packet[0] = 0xaa; //FIXME what is this?
for (i = 0; i < 12; i++) for (i = 0; i < 12; i++)
{ {
value = convert_channel_10b(CH_AETR[i]); value = convert_channel_10b(CH_AETR[i]);
packet[i+1] = value & 0xff; packet[i+1] = value & 0xff;
upperbits |= (value >> 8) << (i * 2); upperbits |= (value >> 8) << (i * 2);
@ -76,16 +76,16 @@ static void __attribute__((unused)) j6pro_cyrf_init()
CYRF_WriteRegister(CYRF_35_AUTOCAL_OFFSET, 0x14); CYRF_WriteRegister(CYRF_35_AUTOCAL_OFFSET, 0x14);
CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, 0x05); CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, 0x05);
CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, 0x55); CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, 0x55);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25); //CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24);
CYRF_SetPower(0x05); //CYRF_SetPower(0x05);
CYRF_WriteRegister(CYRF_06_RX_CFG, 0x8a); CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a);
CYRF_SetPower(0x28); CYRF_SetPower(0x28);
CYRF_WriteRegister(CYRF_12_DATA64_THOLD, 0x0e); CYRF_WriteRegister(CYRF_12_DATA64_THOLD, 0x0e);
CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xee); CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xee);
CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00); CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00);
CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x00); CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x00);
CYRF_ConfigDataCode(j6pro_data_code, 16); CYRF_ConfigDataCode(j6pro_data_code, 16);
CYRF_WritePreamble(0x023333); CYRF_WritePreamble(0x333302);
CYRF_GetMfgData(cyrfmfg_id); CYRF_GetMfgData(cyrfmfg_id);
//Model match //Model match
@ -94,36 +94,28 @@ static void __attribute__((unused)) j6pro_cyrf_init()
static void __attribute__((unused)) cyrf_bindinit() static void __attribute__((unused)) cyrf_bindinit()
{ {
/* Use when binding */ /* Use when binding */
//0.060470# 03 2f CYRF_SetPower(0x28); //Deviation using max power, replaced by bind power...
CYRF_SetPower(0x28); //Deviation using max power, replaced by bind power... //CYRF_ConfigRFChannel(0x52);
CYRF_PROGMEM_ConfigSOPCode(j6pro_bind_sop_code);
CYRF_ConfigRFChannel(0x52); CYRF_ConfigCRCSeed(0x0000);
CYRF_PROGMEM_ConfigSOPCode(j6pro_bind_sop_code); //CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a);
CYRF_ConfigCRCSeed(0x0000); //CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x80);
CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a); //CYRF_ConfigRFChannel(0x52);
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); //CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24);
//0.061511# 13 20 //CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40);
j6pro_build_bind_packet();
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 __attribute__((unused)) cyrf_datainit() static void __attribute__((unused)) cyrf_datainit()
{ {
/* Use when already bound */ /* 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;
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])) |
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);
((0xff & (cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[4] + cyrfmfg_id[5])) << 8); //CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25); CYRF_PROGMEM_ConfigSOPCode(DEVO_j6pro_sopcodes[sop_idx]);
CYRF_PROGMEM_ConfigSOPCode(DEVO_j6pro_sopcodes[sop_idx]); CYRF_ConfigCRCSeed(crc);
CYRF_ConfigCRCSeed(crc);
} }
static void __attribute__((unused)) j6pro_set_radio_channels() static void __attribute__((unused)) j6pro_set_radio_channels()
@ -136,10 +128,10 @@ static void __attribute__((unused)) j6pro_set_radio_channels()
uint16_t ReadJ6Pro() uint16_t ReadJ6Pro()
{ {
uint32_t start; uint32_t start;
switch(phase) switch(phase)
{ {
case J6PRO_BIND: case J6PRO_BIND:
cyrf_bindinit(); cyrf_bindinit();
phase = J6PRO_BIND_01; phase = J6PRO_BIND_01;
@ -147,9 +139,7 @@ uint16_t ReadJ6Pro()
case J6PRO_BIND_01: case J6PRO_BIND_01:
CYRF_ConfigRFChannel(0x52); CYRF_ConfigRFChannel(0x52);
CYRF_SetTxRxMode(TX_EN); CYRF_SetTxRxMode(TX_EN);
//0.062684# 0f 05 //CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
//0.062684# 0f 05
CYRF_WriteDataPacketLen(packet, 0x09); CYRF_WriteDataPacketLen(packet, 0x09);
phase = J6PRO_BIND_03_START; phase = J6PRO_BIND_03_START;
return 3000; //3msec return 3000; //3msec
@ -160,8 +150,8 @@ uint16_t ReadJ6Pro()
break; break;
CYRF_ConfigRFChannel(0x53); CYRF_ConfigRFChannel(0x53);
CYRF_SetTxRxMode(RX_EN); CYRF_SetTxRxMode(RX_EN);
CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a); //CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a);
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x80);
phase = J6PRO_BIND_03_CHECK; phase = J6PRO_BIND_03_CHECK;
return 30000; //30msec return 30000; //30msec
case J6PRO_BIND_03_CHECK: case J6PRO_BIND_03_CHECK:
@ -201,7 +191,7 @@ uint16_t ReadJ6Pro()
case J6PRO_BIND_05_4: case J6PRO_BIND_05_4:
case J6PRO_BIND_05_5: case J6PRO_BIND_05_5:
case J6PRO_BIND_05_6: case J6PRO_BIND_05_6:
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25); //CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24);
CYRF_WriteDataPacketLen(packet, 0x0f); CYRF_WriteDataPacketLen(packet, 0x0f);
phase = phase + 1; phase = phase + 1;
return 4600; //4.6msec return 4600; //4.6msec
@ -212,7 +202,7 @@ uint16_t ReadJ6Pro()
phase = J6PRO_CHAN_1; phase = J6PRO_CHAN_1;
case J6PRO_CHAN_1: case J6PRO_CHAN_1:
//Keep transmit power updated //Keep transmit power updated
CYRF_SetPower(0); CYRF_SetPower(0x28);
j6pro_build_data_packet(); j6pro_build_data_packet();
//return 3400; //return 3400;
case J6PRO_CHAN_2: case J6PRO_CHAN_2:
@ -237,12 +227,10 @@ uint16_t initJ6Pro()
{ {
j6pro_cyrf_init(); j6pro_cyrf_init();
if(IS_AUTOBIND_FLAG_on) { if(IS_AUTOBIND_FLAG_on)
phase = J6PRO_BIND; phase = J6PRO_BIND;
} else
else {
phase = J6PRO_CHANSEL; phase = J6PRO_CHANSEL;
}
return 2400; return 2400;
} }

View File

@ -246,11 +246,7 @@ static void __attribute__((unused)) kn_init()
NRF24L01_Initialize(); 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)); 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_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address 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_Activate(0x73);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0 NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
// Enable: Dynamic Payload Length to enable PCF // 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)); NRF24L01_WriteReg(NRF24L01_1D_FEATURE, _BV(NRF2401_1D_EN_DPL));
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_SetPower(); 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 You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
<<<<<<< HEAD
// compatible with MJX WLH08, X600, X800, H26D
=======
// compatible with MJX WLH08, X600, X800, H26D, Eachine E010 // 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 // Last sync with hexfet new_protocols/mjxq_nrf24l01.c dated 2016-01-17
#if defined(MJXQ_NRF24L01_INO) #if defined(MJXQ_NRF24L01_INO)
@ -30,20 +26,17 @@
#define MJXQ_RF_NUM_CHANNELS 4 #define MJXQ_RF_NUM_CHANNELS 4
#define MJXQ_ADDRESS_LENGTH 5 #define MJXQ_ADDRESS_LENGTH 5
<<<<<<< HEAD
=======
// haven't figured out txid<-->rf channel mapping for MJX models // haven't figured out txid<-->rf channel mapping for MJX models
const uint8_t PROGMEM MJXQ_map_rfchan[][4] = {
{0x0A, 0x46, 0x3A, 0x42},
{0x0A, 0x3C, 0x36, 0x3F},
{0x0A, 0x43, 0x36, 0x3F} };
const uint8_t PROGMEM MJXQ_map_txid[][3] = { const uint8_t PROGMEM MJXQ_map_txid[][3] = {
{0xF8, 0x4F, 0x1C}, {0xF8, 0x4F, 0x1C},
{0xC8, 0x6E, 0x02}, {0xC8, 0x6E, 0x02},
{0x48, 0x6A, 0x40} }; {0x48, 0x6A, 0x40} };
const uint8_t PROGMEM MJXQ_map_rfchan[][4] = {
{0x0A, 0x46, 0x3A, 0x42},
{0x0A, 0x3C, 0x36, 0x3F},
{0x0A, 0x43, 0x36, 0x3F} };
>>>>>>> refs/remotes/pascallanger/master
#define MJXQ_PAN_TILT_COUNT 16 // for H26D - match stock tx timing #define MJXQ_PAN_TILT_COUNT 16 // for H26D - match stock tx timing
#define MJXQ_PAN_DOWN 0x08 #define MJXQ_PAN_DOWN 0x08
#define MJXQ_PAN_UP 0x04 #define MJXQ_PAN_UP 0x04
@ -57,16 +50,6 @@ static uint8_t __attribute__((unused)) MJXQ_pan_tilt_value()
packet_count++; packet_count++;
if(packet_count & MJXQ_PAN_TILT_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) if(Servo_data[AUX8]>PPM_MAX_COMMAND)
pan=MJXQ_PAN_UP; pan=MJXQ_PAN_UP;
if(Servo_data[AUX8]<PPM_MIN_COMMAND) if(Servo_data[AUX8]<PPM_MIN_COMMAND)
@ -75,7 +58,6 @@ static uint8_t __attribute__((unused)) MJXQ_pan_tilt_value()
pan+=MJXQ_TILT_UP; pan+=MJXQ_TILT_UP;
if(Servo_data[AUX9]<PPM_MIN_COMMAND) if(Servo_data[AUX9]<PPM_MIN_COMMAND)
pan+=MJXQ_TILT_DOWN; pan+=MJXQ_TILT_DOWN;
>>>>>>> refs/remotes/pascallanger/master
} }
return pan; return pan;
} }
@ -86,17 +68,10 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
packet[0] = convert_channel_8b(THROTTLE); packet[0] = convert_channel_8b(THROTTLE);
packet[1] = convert_channel_s8b(RUDDER); packet[1] = convert_channel_s8b(RUDDER);
packet[4] = 0x40; // rudder does not work well with dyntrim 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[2] = 0x80 ^ convert_channel_s8b(ELEVATOR);
packet[5] = GET_FLAG(Servo_AUX5, 1) ? 0x40 : MJXQ_CHAN2TRIM(packet[2]); // trim elevator packet[5] = GET_FLAG(Servo_AUX5, 1) ? 0x40 : MJXQ_CHAN2TRIM(packet[2]); // trim elevator
packet[3] = convert_channel_s8b(AILERON); packet[3] = convert_channel_s8b(AILERON);
packet[6] = GET_FLAG(Servo_AUX5, 1) ? 0x40 : MJXQ_CHAN2TRIM(packet[3]); // trim 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[7] = rx_tx_addr[0];
packet[8] = rx_tx_addr[1]; packet[8] = rx_tx_addr[1];
packet[9] = rx_tx_addr[2]; packet[9] = rx_tx_addr[2];
@ -115,16 +90,15 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
// Servo_AUX5 HEADLESS // Servo_AUX5 HEADLESS
// Servo_AUX6 RTH // Servo_AUX6 RTH
// Servo_AUX7 AUTOFLIP // X800, X600 // Servo_AUX7 AUTOFLIP // X800, X600
// Servo_AUX8 ARM // H26WH
switch(sub_protocol) switch(sub_protocol)
{ {
case H26D: case H26D:
case H26WH:
packet[10]=MJXQ_pan_tilt_value(); packet[10]=MJXQ_pan_tilt_value();
// fall through on purpose - no break // fall through on purpose - no break
case WLH08: case WLH08:
<<<<<<< HEAD
=======
case E010: case E010:
>>>>>>> refs/remotes/pascallanger/master
packet[10] += GET_FLAG(Servo_AUX6, 0x02) //RTH packet[10] += GET_FLAG(Servo_AUX6, 0x02) //RTH
| GET_FLAG(Servo_AUX5, 0x01); //HEADLESS | GET_FLAG(Servo_AUX5, 0x01); //HEADLESS
if (!bind) if (!bind)
@ -135,16 +109,13 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
| GET_FLAG(Servo_AUX4, 0x10) //VIDEO | GET_FLAG(Servo_AUX4, 0x10) //VIDEO
| GET_FLAG(!Servo_AUX2, 0x20); // air/ground mode | GET_FLAG(!Servo_AUX2, 0x20); // air/ground mode
} }
if (sub_protocol == H26WH) {
packet[10] &= ~0x40;
packet[14] &= ~0x24;
packet[14] |= GET_FLAG(Servo_AUX2, 0x04);
}
break; break;
case X600: 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[10] = GET_FLAG(!Servo_AUX2, 0x02); //LED
packet[11] = GET_FLAG(Servo_AUX6, 0x01); //RTH packet[11] = GET_FLAG(Servo_AUX6, 0x01); //RTH
if (!bind) if (!bind)
@ -175,14 +146,15 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
packet[15] = sum; packet[15] = sum;
// Power on, TX mode, 2byte CRC // Power on, TX mode, 2byte CRC
if (sub_protocol == H26D) switch (Model.proto_opts[PROTOOPTS_FORMAT]) {
NRF24L01_SetTxRxMode(TX_EN); case H26D:
else case H26WH:
<<<<<<< HEAD NRF24L01_SetTxRxMode(TX_EN);
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); break;
======= default:
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 break;
}
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++ / 2]); NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++ / 2]);
hopping_frequency_no %= 2 * MJXQ_RF_NUM_CHANNELS; // channels repeated hopping_frequency_no %= 2 * MJXQ_RF_NUM_CHANNELS; // channels repeated
@ -190,10 +162,15 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx(); NRF24L01_FlushTx();
if (sub_protocol == H26D) switch (Model.proto_opts[PROTOOPTS_FORMAT]) {
NRF24L01_WritePayload(packet, MJXQ_PACKET_SIZE); case H26D:
else case H26WH:
XN297_WritePayload(packet, MJXQ_PACKET_SIZE); NRF24L01_WritePayload(packet, MJXQ_PACKET_SIZE);
break;
default:
XN297_WritePayload(packet, MJXQ_PACKET_SIZE);
break;
}
NRF24L01_SetPower(); NRF24L01_SetPower();
} }
@ -202,31 +179,26 @@ static void __attribute__((unused)) MJXQ_init()
{ {
uint8_t addr[MJXQ_ADDRESS_LENGTH]; uint8_t addr[MJXQ_ADDRESS_LENGTH];
memcpy(addr, "\x6d\x6a\x77\x77\x77", MJXQ_ADDRESS_LENGTH); memcpy(addr, "\x6d\x6a\x77\x77\x77", MJXQ_ADDRESS_LENGTH);
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
if (sub_protocol == WLH08) if (sub_protocol == WLH08)
memcpy(hopping_frequency, "\x12\x22\x32\x42", MJXQ_RF_NUM_CHANNELS); memcpy(hopping_frequency, "\x12\x22\x32\x42", MJXQ_RF_NUM_CHANNELS);
else else
<<<<<<< HEAD if (sub_protocol == H26D || sub_protocol == H26WH || sub_protocol == E010)
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); memcpy(hopping_frequency, "\x36\x3e\x46\x2e", MJXQ_RF_NUM_CHANNELS);
else else
{ {
memcpy(hopping_frequency, "\x0a\x35\x42\x3d", MJXQ_RF_NUM_CHANNELS); 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); memcpy(addr, "\x6d\x6a\x73\x73\x73", MJXQ_ADDRESS_LENGTH);
>>>>>>> refs/remotes/pascallanger/master
} }
NRF24L01_Initialize(); if (sub_protocol == H26D || sub_protocol == H26WH)
NRF24L01_SetTxRxMode(TX_EN); {
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
if (sub_protocol == H26D)
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, MJXQ_ADDRESS_LENGTH); NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, MJXQ_ADDRESS_LENGTH);
}
else else
XN297_SetTXAddr(addr, MJXQ_ADDRESS_LENGTH); XN297_SetTXAddr(addr, MJXQ_ADDRESS_LENGTH);
@ -237,63 +209,39 @@ static void __attribute__((unused)) MJXQ_init()
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits 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) 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) if (sub_protocol == E010)
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250K NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250K
else else
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_SetPower(); NRF24L01_SetPower();
} }
static void __attribute__((unused)) MJXQ_init2() 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) if (sub_protocol == H26D)
memcpy(hopping_frequency, "\x32\x3e\x42\x4e", MJXQ_RF_NUM_CHANNELS); memcpy(hopping_frequency, "\x32\x3e\x42\x4e", MJXQ_RF_NUM_CHANNELS);
else else
if (sub_protocol != WLH08 && sub_protocol != E010) if (sub_protocol != WLH08 && sub_protocol != E010)
for(uint8_t i=0;i<MJXQ_RF_NUM_CHANNELS;i++) 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] ); hopping_frequency[i]=pgm_read_byte_near( &MJXQ_map_rfchan[rx_tx_addr[3]%3][i] );
>>>>>>> refs/remotes/pascallanger/master
} }
static void __attribute__((unused)) MJXQ_initialize_txid() 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; rx_tx_addr[0]&=0xF8;
if (sub_protocol == E010) rx_tx_addr[2]=rx_tx_addr[3]; // Make use of RX_Num
if (sub_protocol == H26WH)
{
memcpy(txid, "\xa4\x03\x00", sizeof(txid));
}
else if (sub_protocol == E010)
{ {
rx_tx_addr[1]=(rx_tx_addr[1]&0xF0)|0x0C; rx_tx_addr[1]=(rx_tx_addr[1]&0xF0)|0x0C;
rx_tx_addr[2]&=0xF0; rx_tx_addr[2]<<=4; // Make use of RX_Num
} }
else else
for(uint8_t i=0;i<3;i++) 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] ); rx_tx_addr[i]=pgm_read_byte_near( &MJXQ_map_txid[rx_tx_addr[3]%3][i] );
>>>>>>> refs/remotes/pascallanger/master
} }
uint16_t MJXQ_callback() uint16_t MJXQ_callback()

View File

@ -12,11 +12,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
<<<<<<< HEAD
// compatible with MT99xx, Eachine H7, Yi Zhan i6S
=======
// compatible with MT99xx, Eachine H7, Yi Zhan i6S and LS114/124 // 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 // Last sync with Goebish mt99xx_nrf24l01.c dated 2016-01-29
#if defined(MT99XX_NRF24L01_INO) #if defined(MT99XX_NRF24L01_INO)
@ -41,8 +37,6 @@ enum{
FLAG_MT_FLIP = 0x80, FLAG_MT_FLIP = 0x80,
}; };
<<<<<<< HEAD
=======
enum{ enum{
// flags going to packet[6] (LS) // flags going to packet[6] (LS)
FLAG_LS_INVERT = 0x01, FLAG_LS_INVERT = 0x01,
@ -53,49 +47,18 @@ enum{
FLAG_LS_FLIP = 0x80, FLAG_LS_FLIP = 0x80,
}; };
>>>>>>> refs/remotes/pascallanger/master
enum { enum {
MT99XX_INIT = 0, MT99XX_INIT = 0,
MT99XX_BIND, MT99XX_BIND,
MT99XX_DATA 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[] = { const uint8_t h7_mys_byte[] = {
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10 0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10
}; };
static const u8 ls_mys_byte[] = { static const uint8_t ls_mys_byte[] = {
0x05, 0x15, 0x25, 0x06, 0x16, 0x26, 0x05, 0x15, 0x25, 0x06, 0x16, 0x26,
0x07, 0x17, 0x27, 0x00, 0x10, 0x20, 0x07, 0x17, 0x27, 0x00, 0x10, 0x20,
0x01, 0x11, 0x21, 0x02, 0x12, 0x22, 0x01, 0x11, 0x21, 0x02, 0x12, 0x22,
@ -138,7 +101,6 @@ static void __attribute__((unused)) MT99XX_send_packet()
ls_counter=0; ls_counter=0;
} }
>>>>>>> refs/remotes/pascallanger/master
uint8_t result=checksum_offset; uint8_t result=checksum_offset;
for(uint8_t i=0; i<8; i++) for(uint8_t i=0; i<8; i++)
result += packet[i]; result += packet[i];
@ -147,15 +109,9 @@ static void __attribute__((unused)) MT99XX_send_packet()
else else
{ // YZ { // YZ
packet[0] = convert_channel_8b_scale(THROTTLE,0x00,0x64); // throttle 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[1] = convert_channel_8b_scale(RUDDER ,0x64,0x00); // rudder
packet[2] = convert_channel_8b_scale(ELEVATOR,0x00,0x64); // elevator packet[2] = convert_channel_8b_scale(ELEVATOR,0x00,0x64); // elevator
packet[3] = convert_channel_8b_scale(AILERON ,0x64,0x00); // aileron packet[3] = convert_channel_8b_scale(AILERON ,0x64,0x00); // aileron
>>>>>>> refs/remotes/pascallanger/master
if(packet_count++ >= 23) if(packet_count++ >= 23)
{ {
yz_seq_num ++; yz_seq_num ++;
@ -176,14 +132,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[8] = 0xff; packet[8] = 0xff;
} }
<<<<<<< HEAD
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no] + channel_offset);
=======
if(sub_protocol == LS) if(sub_protocol == LS)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel
else else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no] + channel_offset); NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no] + channel_offset);
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx(); NRF24L01_FlushTx();
XN297_WritePayload(packet, MT99XX_PACKET_SIZE); XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
@ -201,16 +153,11 @@ static void __attribute__((unused)) MT99XX_send_packet()
static void __attribute__((unused)) MT99XX_init() static void __attribute__((unused)) MT99XX_init()
{ {
NRF24L01_Initialize(); NRF24L01_Initialize();
<<<<<<< HEAD
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
=======
if(sub_protocol == YZ) if(sub_protocol == YZ)
XN297_SetScrambledMode(XN297_UNSCRAMBLED); XN297_SetScrambledMode(XN297_UNSCRAMBLED);
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx(); NRF24L01_FlushTx();
XN297_SetTXAddr((uint8_t *)"\xCC\xCC\xCC\xCC\xCC", 5); 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_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_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only 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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower(); 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) ); 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() static void __attribute__((unused)) MT99XX_initialize_txid()
{ {
<<<<<<< HEAD
=======
rx_tx_addr[3] = 0xCC; rx_tx_addr[3] = 0xCC;
rx_tx_addr[4] = 0xCC; rx_tx_addr[4] = 0xCC;
>>>>>>> refs/remotes/pascallanger/master
if(sub_protocol == YZ) if(sub_protocol == YZ)
{ {
rx_tx_addr[0] = 0x53; // test (SB id) rx_tx_addr[0] = 0x53; // test (SB id)
rx_tx_addr[1] = 0x00; rx_tx_addr[1] = 0x00;
<<<<<<< HEAD
}
checksum_offset = (rx_tx_addr[0] + rx_tx_addr[1]) & 0xff;
=======
rx_tx_addr[2] = 0x00; rx_tx_addr[2] = 0x00;
} }
else else
@ -255,7 +189,6 @@ static void __attribute__((unused)) MT99XX_initialize_txid()
else //MT99 & H7 else //MT99 & H7
rx_tx_addr[2] = 0x00; rx_tx_addr[2] = 0x00;
checksum_offset = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2]; 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; channel_offset = (((checksum_offset & 0xf0)>>4) + (checksum_offset & 0x0f)) % 8;
} }
@ -267,26 +200,16 @@ uint16_t MT99XX_callback()
{ {
if (bind_counter == 0) 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 // set tx address for data packets
XN297_SetTXAddr(rx_tx_addr, 5); XN297_SetTXAddr(rx_tx_addr, 5);
BIND_DONE; BIND_DONE;
} }
else else
{ {
<<<<<<< HEAD
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
=======
if(sub_protocol == LS) if(sub_protocol == LS)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel
else else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]); NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
>>>>>>> refs/remotes/pascallanger/master
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx(); NRF24L01_FlushTx();
XN297_WritePayload(packet, MT99XX_PACKET_SIZE); // bind packet XN297_WritePayload(packet, MT99XX_PACKET_SIZE); // bind packet
@ -313,25 +236,6 @@ uint16_t initMT99XX(void)
MT99XX_init(); MT99XX_init();
packet[0] = 0x20; 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; packet_period = MT99XX_PACKET_PERIOD_MT;
switch(sub_protocol) switch(sub_protocol)
{ // MT99 & H7 { // MT99 & H7
@ -356,7 +260,6 @@ uint16_t initMT99XX(void)
packet[4] = rx_tx_addr[0]; packet[4] = rx_tx_addr[0];
packet[5] = rx_tx_addr[1]; packet[5] = rx_tx_addr[1];
packet[6] = rx_tx_addr[2]; packet[6] = rx_tx_addr[2];
>>>>>>> refs/remotes/pascallanger/master
packet[7] = checksum_offset; // checksum offset packet[7] = checksum_offset; // checksum offset
packet[8] = 0xAA; // fixed packet[8] = 0xAA; // fixed
packet_count=0; packet_count=0;

View File

@ -1,7 +1,7 @@
#define ARDUINO_AVR_PRO 1 #define ARDUINO_AVR_PRO 1
//#define __AVR_ATmega328P__ 1 //#define __AVR_ATmega328P__ 1
#define XMEGA 1 #define ORANGE_TX 1
// For BLUE module use: // For BLUE module use:
//#define DSM_BLUE //#define DSM_BLUE

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -14,9 +14,7 @@
*/ */
//--------------------------- #ifdef NRF24L01_INSTALLED
// AVR nrf chip bitbang SPI functions
//---------------------------
#include "iface_nrf24l01.h" #include "iface_nrf24l01.h"
@ -94,6 +92,14 @@ static void NRF24L01_ReadPayload(uint8_t * data, uint8_t length)
data[i] = SPI_Read(); data[i] = SPI_Read();
NRF_CSN_on; 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) static void NRF24L01_Strobe(uint8_t state)
{ {
@ -181,7 +187,8 @@ void NRF24L01_SetTxRxMode(enum TXRX_State mode)
NRF_CE_on; NRF_CE_on;
} }
else else
if (mode == RX_EN) { if (mode == RX_EN)
{
NRF_CE_off; NRF_CE_off;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // reset the flag(s) NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // reset the flag(s)
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // switch to RX mode NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // switch to RX mode
@ -234,11 +241,7 @@ uint8_t NRF24L01_packet_ack()
/////////////// ///////////////
// XN297 emulation layer // XN297 emulation layer
<<<<<<< HEAD
uint8_t xn297_scramble_enabled;
=======
uint8_t xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default uint8_t xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
>>>>>>> refs/remotes/pascallanger/master
uint8_t xn297_addr_len; uint8_t xn297_addr_len;
uint8_t xn297_tx_addr[5]; uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5]; uint8_t xn297_rx_addr[5];
@ -251,16 +254,6 @@ static const uint8_t xn297_scramble[] = {
0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f, 0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f,
0x8e, 0xc5, 0x2f}; 0x8e, 0xc5, 0x2f};
<<<<<<< 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[] = { const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
@ -334,23 +327,16 @@ void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5); 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)); xn297_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)); flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF); NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
} }
void XN297_SetScrambledMode(const u8 mode) void XN297_SetScrambledMode(const uint8_t mode)
{ {
xn297_scramble_enabled = mode; xn297_scramble_enabled = mode;
>>>>>>> refs/remotes/pascallanger/master
} }
void XN297_WritePayload(uint8_t* msg, uint8_t len) void XN297_WritePayload(uint8_t* msg, uint8_t len)
@ -412,32 +398,6 @@ void XN297_ReadPayload(uint8_t* msg, uint8_t len)
// End of XN297 emulation // 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 // LT8900 emulation layer
uint8_t LT8900_buffer[64]; uint8_t LT8900_buffer[64];
uint8_t LT8900_buffer_start; uint8_t LT8900_buffer_start;
@ -462,37 +422,23 @@ void LT8900_Config(uint8_t preamble_len, uint8_t trailer_len, uint8_t flags, uin
LT8900_Preamble_Len=preamble_len; LT8900_Preamble_Len=preamble_len;
//Trailer 4 to 18 bits //Trailer 4 to 18 bits
LT8900_Tailer_Len=trailer_len; LT8900_Tailer_Len=trailer_len;
>>>>>>> refs/remotes/pascallanger/master
//Flags //Flags
// CRC_ON: 1 on, 0 off // CRC_ON: 1 on, 0 off
// SCRAMBLE_ON: 1 on, 0 off // SCRAMBLE_ON: 1 on, 0 off
// PACKET_LENGTH_EN: 1 1st byte of payload is payload size // 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 // 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 // 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; LT8900_Flags=flags;
//CRC init constant //CRC init constant
LT8900_CRC_Initial_Data=crc_init; LT8900_CRC_Initial_Data=crc_init;
} }
void LT8900_SetChannel(uint8_t channel) 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 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) void LT8900_SetTxRxMode(enum TXRX_State mode)
>>>>>>> refs/remotes/pascallanger/master
{ {
if(mode == TX_EN) if(mode == TX_EN)
{ {
@ -518,35 +464,12 @@ void LT8900_SetTxRxMode(enum TXRX_State mode)
NRF24L01_SetTxRxMode(TXRX_OFF); NRF24L01_SetTxRxMode(TXRX_OFF);
} }
<<<<<<< HEAD
void LT8910_BuildOverhead()
=======
void LT8900_BuildOverhead() void LT8900_BuildOverhead()
>>>>>>> refs/remotes/pascallanger/master
{ {
uint8_t pos; uint8_t pos;
//Build overhead //Build overhead
//preamble //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); memset(LT8900_buffer,LT8900_addr[0]&0x01?0xAA:0x55,LT8900_Preamble_Len-1);
pos=LT8900_Preamble_Len-1; pos=LT8900_Preamble_Len-1;
//address //address
@ -564,33 +487,10 @@ void LT8910_SetAddress(uint8_t *address,uint8_t addr_size)
} }
void LT8900_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]; uint8_t addr[5];
//Address size (SyncWord) 2 to 8 bytes, 16/32/48/64 bits //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; LT8900_addr_size=addr_size;
for (uint8_t i = 0; i < addr_size; i++) for (uint8_t i = 0; i < addr_size; i++)
LT8900_addr[i] = address[addr_size-1-i]; LT8900_addr[i] = address[addr_size-1-i];
@ -612,22 +512,14 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
unsigned int crc=LT8900_CRC_Initial_Data,a; unsigned int crc=LT8900_CRC_Initial_Data,a;
pos=LT8900_buffer_overhead_bits/8-LT8900_buffer_start; 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); 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 //Read payload
NRF24L01_ReadPayload(buffer,end+1); NRF24L01_ReadPayload(buffer,end+1);
//Check address + trail //Check address + trail
for(i=0;i<pos;i++) 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]) if(LT8900_buffer[LT8900_buffer_start+i]!=buffer[i])
return 0; // wrong address... return 0; // wrong address...
//Shift buffer to remove trail bits //Shift buffer to remove trail bits
shift=LT8900_buffer_overhead_bits&0x7; shift=LT8900_buffer_overhead_bits&0x7;
>>>>>>> refs/remotes/pascallanger/master
for(i=pos;i<end;i++) for(i=pos;i<end;i++)
{ {
a=(buffer[i]<<8)+buffer[i+1]; a=(buffer[i]<<8)+buffer[i+1];
@ -635,11 +527,7 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
buffer[i]=(a>>8)&0xFF; buffer[i]=(a>>8)&0xFF;
} }
//Check len //Check len
<<<<<<< HEAD
if(LT8910_Flags&_BV(LT8910_PACKET_LENGTH_EN))
=======
if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN)) if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN))
>>>>>>> refs/remotes/pascallanger/master
{ {
crc=crc16_update(crc,buffer[pos]); crc=crc16_update(crc,buffer[pos]);
if(bit_reverse(len)!=buffer[pos++]) if(bit_reverse(len)!=buffer[pos++])
@ -652,11 +540,7 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
msg[i]=bit_reverse(buffer[pos++]); msg[i]=bit_reverse(buffer[pos++]);
} }
//Check CRC //Check CRC
<<<<<<< HEAD
if(LT8910_Flags&_BV(LT8910_CRC_ON))
=======
if(LT8900_Flags&_BV(LT8900_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>>8)&0xFF)) return 0; // wrong CRC...
if(buffer[pos]!=(crc&0xFF)) return 0; // wrong CRC... if(buffer[pos]!=(crc&0xFF)) return 0; // wrong CRC...
@ -665,21 +549,12 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
return 1; 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) void LT8900_WritePayload(uint8_t* msg, uint8_t len)
{ {
unsigned int crc=LT8900_CRC_Initial_Data,a,mask; unsigned int crc=LT8900_CRC_Initial_Data,a,mask;
uint8_t i, pos=0,tmp, buffer[64], pos_final,shift; uint8_t i, pos=0,tmp, buffer[64], pos_final,shift;
//Add packet len //Add packet len
if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN)) if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN))
>>>>>>> refs/remotes/pascallanger/master
{ {
tmp=bit_reverse(len); tmp=bit_reverse(len);
buffer[pos++]=tmp; buffer[pos++]=tmp;
@ -693,27 +568,12 @@ void LT8900_WritePayload(uint8_t* msg, uint8_t len)
crc=crc16_update(crc,tmp); crc=crc16_update(crc,tmp);
} }
//Add CRC //Add CRC
<<<<<<< HEAD
if(LT8910_Flags&_BV(LT8910_CRC_ON))
=======
if(LT8900_Flags&_BV(LT8900_CRC_ON)) if(LT8900_Flags&_BV(LT8900_CRC_ON))
>>>>>>> refs/remotes/pascallanger/master
{ {
buffer[pos++]=crc>>8; buffer[pos++]=crc>>8;
buffer[pos++]=crc; buffer[pos++]=crc;
} }
//Shift everything to fit behind the trailer (4 to 18 bits) //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; shift=LT8900_buffer_overhead_bits&0x7;
pos_final=LT8900_buffer_overhead_bits/8; pos_final=LT8900_buffer_overhead_bits/8;
mask=~(0xFF<<(8-shift)); mask=~(0xFF<<(8-shift));
@ -723,17 +583,11 @@ void LT8900_WritePayload(uint8_t* msg, uint8_t len)
a=buffer[i]<<(8-shift); a=buffer[i]<<(8-shift);
LT8900_buffer[pos_final+i]=(LT8900_buffer[pos_final+i]&mask>>8)|a>>8; 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; LT8900_buffer[pos_final+i+1]=(LT8900_buffer[pos_final+i+1]&mask)|a;
>>>>>>> refs/remotes/pascallanger/master
} }
if(shift) if(shift)
pos++; pos++;
//Send everything //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); NRF24L01_WritePayload(LT8900_buffer+LT8900_buffer_start,pos_final+pos-LT8900_buffer_start);
} }
// End of LT8900 emulation // End of LT8900 emulation
>>>>>>> refs/remotes/pascallanger/master #endif

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 NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81); // binding packet must be set in channel 81
// 2-bytes CRC, radio on // 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_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
NRF24L01_SetBitrate(NRF24L01_BR_250K); // BlueFly - 250kbps NRF24L01_SetBitrate(NRF24L01_BR_250K); // BlueFly - 250kbps
NRF24L01_SetPower(); NRF24L01_SetPower();
@ -63,7 +63,7 @@ static void bluefly_ch_data() {
uint32_t temp; uint32_t temp;
int i; int i;
for (i = 0; i< 8; ++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) if (temp < 0)
ch_data_bluefly[i] = 0; ch_data_bluefly[i] = 0;
else if (temp > 1000) else if (temp > 1000)
@ -140,6 +140,7 @@ static uint16_t bluefly_cb() {
} }
static uint16_t BlueFly_setup() { static uint16_t BlueFly_setup() {
MProtocol_id = (MProtocol_id | ((uint32_t)txid[3]<<32));
hopping_frequency_start = ((MProtocol_id >> 8) % 47) + 2; hopping_frequency_start = ((MProtocol_id >> 8) % 47) + 2;
bluefly_binding_packet(); bluefly_binding_packet();
bluefly_init(); bluefly_init();

View File

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

View File

@ -32,15 +32,15 @@ enum {
static uint8_t esky150_packet_ack() { static uint8_t esky150_packet_ack() {
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) { 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_TX_DS): return PKT_ACKED;
case BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT; case _BV(NRF24L01_07_MAX_RT): return PKT_TIMEOUT;
} }
return PKT_PENDING; return PKT_PENDING;
} }
// 2-bytes CRC // 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() { static uint16_t esky150_init() {
uint8_t rx_addr[ADDR_esky150_SIZE] = { 0x73, 0x73, 0x74, 0x63 }; uint8_t rx_addr[ADDR_esky150_SIZE] = { 0x73, 0x73, 0x74, 0x63 };
uint8_t tx_addr[ADDR_esky150_SIZE] = { 0x71, 0x0A, 0x31, 0xF4 }; uint8_t tx_addr[ADDR_esky150_SIZE] = { 0x71, 0x0A, 0x31, 0xF4 };
@ -64,7 +64,7 @@ static uint16_t esky150_init() {
NRF24L01_Activate(0x73); NRF24L01_Activate(0x73);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0 NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
// Enable: Dynamic Payload Length, Payload with ACK , W_TX_PAYLOAD_NOACK // 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 // Delay 50 ms
return 50000; return 50000;
@ -80,51 +80,26 @@ static uint16_t esky150_init2() {
// Turn radio power on // Turn radio power on
NRF24L01_SetTxRxMode(TX_EN); 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); // delayMicroseconds(150);
return 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() { static void esky150_send_packet() {
uint8_t rf_ch = hopping_frequency[rf_ch_num]; uint8_t rf_ch = hopping_frequency[rf_ch_num];
rf_ch_num = 1 - rf_ch_num; rf_ch_num = 1 - rf_ch_num;
read_controls(&throttle, &aileron, &elevator, &rudder);
packet[0] = hopping_frequency[0]; packet[0] = hopping_frequency[0];
packet[1] = hopping_frequency[1]; packet[1] = hopping_frequency[1];
packet[2] = (throttle >> 8) & 0xFF; packet[2] = highByte(Servo_data[THROTTLE]);
packet[3] = throttle & 0xFF; packet[3] = lowByte(Servo_data[THROTTLE]);
packet[4] = (aileron >> 8) & 0xFF; packet[4] = highByte(Servo_data[AILERON]);
packet[5] = aileron & 0xFF; packet[5] = lowByte(Servo_data[AILERON]);
packet[6] = (elevator >> 8) & 0xFF; packet[6] = highByte(Servo_data[ELEVATOR]);
packet[7] = elevator & 0xFF; packet[7] = lowByte(Servo_data[ELEVATOR]);
packet[8] = (rudder >> 8) & 0xFF; packet[8] = highByte(Servo_data[RUDDER]);
packet[9] = rudder & 0xFF; packet[9] = lowByte(Servo_data[RUDDER]);
// Constant values 00 d8 18 f8 // Constant values 00 d8 18 f8
packet[10] = 0x00; packet[10] = 0x00;
packet[11] = 0xd8; packet[11] = 0xd8;
@ -166,6 +141,12 @@ static uint16_t esky150_callback() {
static uint16_t esky150_setup() { static uint16_t esky150_setup() {
total_packets = 0; total_packets = 0;
uint16_t timeout = esky150_init(); 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; 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_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 NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length); // fbl100/v922's packet size = 10, hp100 = 12
// 2-bytes CRC, radio off // 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_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_SetBitrate(sub_protocol == HP100? NRF24L01_BR_250K:NRF24L01_BR_1M); //hp100:250kbps; fbl100: 1Mbps
NRF24L01_SetPower(); NRF24L01_SetPower();
@ -108,7 +108,7 @@ static void fbl100_build_ch_data() {
uint32_t temp; uint32_t temp;
uint8_t i; uint8_t i;
for (i = 0; i< 8; 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 (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; } if (temp < 0) { fbl_data[i] = 0; }
else if (temp > 1000) { fbl_data[i] = 1000; } else if (temp > 1000) { fbl_data[i] = 1000; }
@ -131,11 +131,12 @@ static void hp100_build_ch_data() {
uint32_t temp; uint32_t temp;
uint8_t i; uint8_t i;
for (i = 0; i< 8; 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; } if (temp < 0) { temp = 0; }
else if (temp > 1000) { temp = 1000; } 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 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; fbl_data[i] = (unsigned int)temp;
packet[i] = (uint8_t)fbl_data[i]; packet[i] = (uint8_t)fbl_data[i];
} }

View File

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

View File

@ -1,10 +1,11 @@
/* /*
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. 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. 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/>. You should have received a copy of the GNU General Public License along with Deviation. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* This protocol is for the HM Hobby HM830 RC Paper Airplane /*
This protocol is for the HM Hobby HM830 RC Paper Airplane
Protocol spec: Protocol spec:
Channel data: Channel data:
AA BB CC DD EE FF GG AA BB CC DD EE FF GG
@ -76,7 +77,7 @@ static uint8_t count;
static uint8_t rf_ch[] = {0x08, 0x35, 0x12, 0x3f, 0x1c, 0x49, 0x26}; 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 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; int polynomial = 0x01;
for(int i = 0; i < len; i++) { for(int i = 0; i < len; i++) {
result = result ^ data[i]; result = result ^ data[i];
@ -114,26 +115,26 @@ static void HM830_init() {
static void build_bind_packet_hm830() { static void build_bind_packet_hm830() {
for(int i = 0; i < 6; i++) { packet[i] = rx_tx_addr[i]; } 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() { static void build_data_packet() {
uint8_t ail_sign = 0, trim_sign = 0; 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; } 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 < 0) { aileron = -aileron; ail_sign = 1; }
if (aileron > 7) { aileron = 7; } 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 < 0) { trim = -trim; trim_sign = 1; }
if (trim > 0x1f) { trim = 0x1f; } 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[0] = throttle;
packet[1] = aileron; packet[1] = aileron;
if (ail_sign) { packet[1] |= 0x20; } if (ail_sign) { packet[1] |= 0x20; }
@ -141,7 +142,7 @@ static void build_data_packet() {
if (rbutton) { packet[1] |= 0x80; } if (rbutton) { packet[1] |= 0x80; }
packet[5] = trim; packet[5] = trim;
if (trim_sign) { packet[5] |= 0x20;} if (trim_sign) { packet[5] |= 0x20;}
packet[6] = crc8(0xa5, packet, 6); packet[6] = HM830_crc8(0xa5, packet, 6);
} }
static void send_packet_hm830() { 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 INAV_BIND_COUNT 345 // 1.5 seconds
#define FIRST_INAV_PACKET_DELAY 12000
#define INAV_PACKET_PERIOD 4000 // Timeout for callback in uSec
#define INAV_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 {
INAV_RATE_LOW = 0,
INAV_RATE_MID = 1,
INAV_RATE_HIGH = 2,
};
enum {
INAV_FLAG_FLIP = 0x01,
INAV_FLAG_PICTURE = 0x02,
INAV_FLAG_VIDEO = 0x04,
INAV_FLAG_RTH = 0x08,
INAV_FLAG_HEADLESS = 0x10,
};
typedef enum {
PHASE_INIT = 0,
PHASE_INAV_BIND,
PHASE_INAV_DATA
};
typedef enum {
DATA_INAV_PACKET = 0,
BIND_INAV_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 = INAV_RATE_LOW;
if (Channels[CHANNEL_RATE] > 0) {
rate = INAV_RATE_HIGH;
} else if (Channels[CHANNEL_RATE] == 0) {
rate = INAV_RATE_MID;
}
packet[7] = rate; // rate, deviation channel 5, is mapped to AUX1
const uint8_t flags = GET_FLAG(CHANNEL_FLIP, INAV_FLAG_FLIP)
| GET_FLAG(CHANNEL_PICTURE, INAV_FLAG_PICTURE)
| GET_FLAG(CHANNEL_VIDEO, INAV_FLAG_VIDEO)
| GET_FLAG(CHANNEL_RTH, INAV_FLAG_RTH)
| GET_FLAG(CHANNEL_HEADLESS, INAV_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_INAV_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 = INAV_BIND_COUNT;
bind_acked = 0;
return FIRST_INAV_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 INAV_PACKET_PERIOD;
}
send_packet(BIND_INAV_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_INAV_PACKET);
break;
}
return INAV_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(INAV_BIND_COUNT * INAV_PACKET_PERIOD / 1000);
} else {
set_data_phase();
// BIND_DONE;
}
return INAV_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 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++) { 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) if (value > 0x7f)
value = 0x7f; value = 0x7f;
else if(value < 0) else if(value < 0)
@ -210,7 +210,7 @@ static void send_data_packet() {
NRF24L01_WritePayload((uint8_t*) packet, PACKET_NE_LENGTH); NRF24L01_WritePayload((uint8_t*) packet, PACKET_NE_LENGTH);
} }
static void send_bind_packet() { static void send_ne_bind_packet() {
packet[0] = 0xAA; //throttle packet[0] = 0xAA; //throttle
packet[1] = 0xAA; //rudder packet[1] = 0xAA; //rudder
packet[2] = 0xAA; //elevator packet[2] = 0xAA; //elevator
@ -243,7 +243,7 @@ static uint16_t ne260_cb() {
} }
} }
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
send_bind_packet(); send_ne_bind_packet();
state = NE260_BINDRX; state = NE260_BINDRX;
return 500; return 500;
} else if (state == NE260_BINDRX) { } 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_DATA1) { neChannel = 10; state = NE260_DATA2; }
else if (state == NE260_DATA2) { neChannel = 30; state = NE260_DATA3; } else if (state == NE260_DATA2) { neChannel = 30; state = NE260_DATA3; }
else if (state == NE260_DATA3) { neChannel = 50; state = NE260_DATA1; } else if (state == NE260_DATA3) { neChannel = 50; state = NE260_DATA1; }
send_data_packet(); send_ne_data_packet();
return 2500; return 2500;
} }

View File

@ -0,0 +1,152 @@
#ifdef Q303_NRF24L01_INO
#include "iface_nrf24l01.h"
#define Q303_BIND_COUNT 1200
#define Q303_PACKET_SIZE 10
#define Q303_PACKET_PERIOD 1500 // Timeout for callback in uSec
#define Q303_INITIAL_WAIT 500
#define Q303_RF_BIND_CHANNEL 0x02
#define Q303_NUM_RF_CHANNELS 4
static uint8_t tx_addr[5];
static uint8_t current_chan;
uint8_t txid[4] = {0xAE, 0x89, 0x97, 0x87};
static uint8_t rf_chans[4] = {0x4A, 0x4C, 0x4E, 0x48};
// haven't figured out txid<-->rf channel mapping yet
// static const struct { uint8_t txid[sizeof(txid)]; uint8_t rfchan[Q303_NUM_RF_CHANNELS]; } q303_tx_rf_map[] = {{{0xAE, 0x89, 0x97, 0x87}, {0x4A, 0x4C, 0x4E, 0x48}}};
enum {
Q303_BIND,
Q303_DATA
};
// flags going to packet[8]
#define Q303_FLAG_HIGHRATE 0x03
#define Q303_FLAG_AHOLD 0x40
#define Q303_FLAG_RTH 0x80
// flags going to packet[9]
#define Q303_FLAG_GIMBAL_DN 0x04
#define Q303_FLAG_GIMBAL_UP 0x20
#define Q303_FLAG_HEADLESS 0x08
#define Q303_FLAG_FLIP 0x80
#define Q303_FLAG_SNAPSHOT 0x10
#define Q303_FLAG_VIDEO 0x01
static void send_packet(uint8_t bind)
{
if(bind) {
packet[0] = 0xaa;
memcpy(&packet[1], txid, 4);
memset(&packet[5], 0, 5);
}
else {
aileron = map(Servo_data[AILERON], 1000, 2000, 0, 1000);
elevator = 1000 - map(Servo_data[ELEVATOR], 1000, 2000, 0, 1000);
throttle = map(Servo_data[THROTTLE], 1000, 2000, 0, 1000);
rudder = 1000 - map(Servo_data[RUDDER], 1000, 2000, 0, 1000);
packet[0] = 0x55;
packet[1] = aileron >> 2 ; // 8 bits
packet[2] = (aileron & 0x03) << 6 // 2 bits
| (elevator >> 4); // 6 bits
packet[3] = (elevator & 0x0f) << 4 // 4 bits
| (throttle >> 6); // 4 bits
packet[4] = (throttle & 0x3f) << 2 // 6 bits
| (rudder >> 8); // 2 bits
packet[5] = rudder & 0xff; // 8 bits
packet[6] = 0x10; // trim(s) ?
packet[7] = 0x10; // trim(s) ?
packet[8] = 0x03 // high rate (0-3)
| GET_FLAG(Servo_AUX1, Q303_FLAG_AHOLD)
| GET_FLAG(Servo_AUX6, Q303_FLAG_RTH);
packet[9] = 0x40 // always set
| GET_FLAG(Servo_AUX5, Q303_FLAG_HEADLESS)
| GET_FLAG(Servo_AUX2, Q303_FLAG_FLIP)
| GET_FLAG(Servo_AUX3, Q303_FLAG_SNAPSHOT)
| GET_FLAG(Servo_AUX4, Q303_FLAG_VIDEO);
if(Servo_data[AUX7] < (servo_max_100-PPM_SWITCH))
packet[9] |= Q303_FLAG_GIMBAL_DN;
else if(Servo_data[AUX7] > PPM_SWITCH)
packet[9] |= Q303_FLAG_GIMBAL_UP;
// set low rate for first packets
if(bind_counter != 0) {
packet[8] &= ~0x03;
bind_counter--;
}
}
// Power on, TX mode, CRC enabled
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (bind) {
NRF24L01_WriteReg(NRF24L01_05_RF_CH, Q303_RF_BIND_CHANNEL);
} else {
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_chans[current_chan++]);
current_chan %= Q303_NUM_RF_CHANNELS;
}
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, Q303_PACKET_SIZE);
}
static uint16_t q303_callback()
{
switch (phase) {
case Q303_BIND:
if (bind_counter == 0) {
tx_addr[0] = 0x55;
memcpy(&tx_addr[1], txid, 4);
XN297_SetTXAddr(tx_addr, 5);
phase = Q303_DATA;
bind_counter = Q303_BIND_COUNT;
BIND_DONE;
} else {
send_packet(1);
bind_counter--;
}
break;
case Q303_DATA:
send_packet(0);
break;
}
return Q303_PACKET_PERIOD;
}
static uint16_t q303_init()
{
// memcpy(txid, q303_tx_rf_map[MProtocol_id % (sizeof(q303_tx_rf_map)/sizeof(q303_tx_rf_map[0]))].txid, sizeof(txid));
// memcpy(rf_chans, q303_tx_rf_map[MProtocol_id % (sizeof(q303_tx_rf_map)/sizeof(q303_tx_rf_map[0]))].rfchan, sizeof(rf_chans));
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *) "\xCC\xCC\xCC\xCC\xCC", 5);
NRF24L01_FlushTx();
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_05_RF_CH, Q303_RF_BIND_CHANNEL);
NRF24L01_SetBitrate(NRF24L01_BR_250K);
NRF24L01_SetPower();
// this sequence necessary for module from stock tx
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00); // Set feature bits on
NRF24L01_Activate(0x53); // switch bank back
BIND_IN_PROGRESS;
bind_counter = Q303_BIND_COUNT;
current_chan = 0;
// PROTOCOL_SetBindState(Q303_BIND_COUNT * Q303_PACKET_PERIOD / 1000);
phase = Q303_BIND;
return Q303_INITIAL_WAIT;
}
#endif

View File

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

View File

@ -0,0 +1,89 @@
#define PPM_TEST 3 //test voie valeur
#define PPM_MIN_COMMAND 1250
#define PPM_SWITCH 1550
#define PPM_MAX_COMMAND 1750
#define isterie 10
#define PPM_Pin 3 //this must be 2 or 3
int ppm[18]; //array for storing up to 16 servo signals
int maxi = 0, mini = 3000, decal, moy, a,r, val;
void setup() {
Serial.begin(115200); Serial.println("ready");
pinMode(PPM_Pin, INPUT); attachInterrupt(PPM_Pin - 2, read_ppm, CHANGE);
TCCR1A = 0; //reset timer1
TCCR1B = 0;
TCCR1B |= (1 << CS11); //set timer1 to increment every 0,5 us
}
void loop() {
//You can delete everithing inside loop() and put your own code here
int count;
if(ppm[PPM_TEST]<mini || ppm[PPM_TEST]>maxi) {
maxi = max( maxi, ppm[PPM_TEST]);
mini = min( mini, ppm[PPM_TEST]);
moy = (maxi + mini)/2;
decal = (maxi - moy) / 125 * 100;
a = moy + decal;
r = moy - decal;
}
Serial.print(a); Serial.print(" ");
Serial.print(r); Serial.print(" ");
Serial.print(maxi); Serial.print(" ");
Serial.print(mini); Serial.print(" ");
Serial.print(moy); Serial.print(" ");
if((PPM_SWITCH - isterie) < moy < (PPM_SWITCH + isterie)) {
Serial.print(" . Pb istérie PPM middel ");
Serial.print(PPM_SWITCH);
}
else {
Serial.print(" . ");
count = 0;
Serial.print(ppm[count]); Serial.print(" "); count++;
Serial.print(ppm[count]); Serial.print(" "); count++;
Serial.print(ppm[count]); Serial.print(" "); count++;
Serial.print(ppm[count]); Serial.print(" "); count++;
for( ;count<17;count++) {
val=ppm[count];
if((moy-2*isterie) < val < (moy+2*isterie)) { Serial.print("2"); }
else if(PPM_MAX_COMMAND < val < 2200) { Serial.print("3"); }
else if(PPM_MAX_COMMAND < val) { Serial.print("+"); }
else if(800 < val < PPM_MIN_COMMAND) { Serial.print("1"); }
else { Serial.print("."); }
}
/*
while(ppm[count] != 0){ //print out the servo values
Serial.print(count); Serial.print(" ");
Serial.print(ppm[count]); Serial.print(" ");
count++;
}
*/
}
Serial.println("");
delay(100); //you can even use delays!!!
}
void read_ppm(){ //leave this alone
#if F_CPU == 16000000
#define PPM_SCALE 1L
#elif F_CPU == 8000000
#define PPM_SCALE 0L
#else
#error // 8 or 16MHz only !
#endif
static unsigned int pulse;
static unsigned long counter;
static byte channel;
counter = TCNT1;
TCNT1 = 0;
if(counter < 510 << PPM_SCALE){ pulse = counter; } //must be a pulse if less than 510us
else if(counter > 1910 << PPM_SCALE){ channel = 0; } //sync pulses over 1910us
else{ ppm[channel] = (counter + pulse) >> PPM_SCALE; channel++; } //servo values between 510us and 2420us will end up here
}

View File

@ -15,195 +15,323 @@
//******************* //*******************
//*** Pinouts *** //*** Pinouts ***
//******************* //*******************
#ifndef STM32_BOARD
// TX
#define SERIAL_TX_pin 1 //PD1
#define SERIAL_TX_port PORTD
#define SERIAL_TX_ddr DDRD
#define SERIAL_TX_output SERIAL_TX_ddr |= _BV(SERIAL_TX_pin)
#define SERIAL_TX_on SERIAL_TX_port |= _BV(SERIAL_TX_pin)
#define SERIAL_TX_off SERIAL_TX_port &= ~_BV(SERIAL_TX_pin)
#ifdef DEBUG_TX
#define DEBUG_TX_on SERIAL_TX_on
#define DEBUG_TX_off SERIAL_TX_off
#define DEBUG_TX_toggle SERIAL_TX_port ^= _BV(SERIAL_TX_pin)
#else
#define DEBUG_TX_on
#define DEBUG_TX_off
#define DEBUG_TX_toggle
#endif
// TX // Dial
#define SERIAL_TX_pin 1 //PD1 #define MODE_DIAL1_pin 2
#define SERIAL_TX_port PORTD #define MODE_DIAL1_port PORTB
#define SERIAL_TX_ddr DDRD #define MODE_DIAL1_ipr PINB
#define SERIAL_TX_output SERIAL_TX_ddr |= _BV(SERIAL_TX_pin) #define MODE_DIAL2_pin 3
#define SERIAL_TX_on SERIAL_TX_port |= _BV(SERIAL_TX_pin) #define MODE_DIAL2_port PORTB
#define SERIAL_TX_off SERIAL_TX_port &= ~_BV(SERIAL_TX_pin) #define MODE_DIAL2_ipr PINB
#ifdef DEBUG_TX #define MODE_DIAL3_pin 4
#define DEBUG_TX_on SERIAL_TX_ON #define MODE_DIAL3_port PORTB
#define DEBUG_TX_off SERIAL_TX_OFF #define MODE_DIAL3_ipr PINB
#define DEBUG_TX_toggle SERIAL_TX_port ^= _BV(SERIAL_TX_pin) #define MODE_DIAL4_pin 0
#else #define MODE_DIAL4_port PORTC
#define DEBUG_TX_on #define MODE_DIAL4_ipr PINC
#define DEBUG_TX_off
#define DEBUG_TX_toggle // PPM
#define PPM_pin 3 //D3 = PD3
#define PPM_port PORTD
// SDIO
#define SDI_pin 5 //D5 = PD5
#define SDI_port PORTD
#define SDI_ipr PIND
#define SDI_ddr DDRD
#ifdef ORANGE_TX
#define SDI_on SDI_port.OUTSET = _BV(SDI_pin)
#define SDI_off SDI_port.OUTCLR = _BV(SDI_pin)
#else
#define SDI_on SDI_port |= _BV(SDI_pin)
#define SDI_off SDI_port &= ~_BV(SDI_pin)
#define SDI_1 (SDI_ipr & _BV(SDI_pin))
#define SDI_0 (SDI_ipr & _BV(SDI_pin)) == 0x00
#endif
#define SDI_input SDI_ddr &= ~_BV(SDI_pin)
#define SDI_output SDI_ddr |= _BV(SDI_pin)
//SDO
#define SDO_pin 6 //D6 = PD6
#define SDO_port PORTD
#define SDO_ipr PIND
#ifdef ORANGE_TX
#define SDO_1 (SDO_port.IN & _BV(SDO_pin))
#define SDO_0 (SDO_port.IN & _BV(SDO_pin)) == 0x00
#else
#define SDO_1 (SDO_ipr & _BV(SDO_pin))
#define SDO_0 (SDO_ipr & _BV(SDO_pin)) == 0x00
#endif
// SCLK
#define SCLK_port PORTD
#define SCLK_ddr DDRD
#ifdef ORANGE_TX
#define SCLK_pin 7 //PD7
#define SCLK_on SCLK_port.OUTSET = _BV(SCLK_pin)
#define SCLK_off SCLK_port.OUTCLR = _BV(SCLK_pin)
#else
#define SCLK_pin 4 //D4 = PD4
#define SCLK_output SCLK_ddr |= _BV(SCLK_pin)
#define SCLK_on SCLK_port |= _BV(SCLK_pin)
#define SCLK_off SCLK_port &= ~_BV(SCLK_pin)
#endif
// A7105
#define A7105_CSN_pin 2 //D2 = PD2
#define A7105_CSN_port PORTD
#define A7105_CSN_ddr DDRD
#define A7105_CSN_output A7105_CSN_ddr |= _BV(A7105_CSN_pin)
#define A7105_CSN_on A7105_CSN_port |= _BV(A7105_CSN_pin)
#define A7105_CSN_off A7105_CSN_port &= ~_BV(A7105_CSN_pin)
// CC2500
#define CC25_CSN_pin 7 //D7 = PD7
#define CC25_CSN_port PORTD
#define CC25_CSN_ddr DDRD
#define CC25_CSN_output CC25_CSN_ddr |= _BV(CC25_CSN_pin)
#define CC25_CSN_on CC25_CSN_port |= _BV(CC25_CSN_pin)
#define CC25_CSN_off CC25_CSN_port &= ~_BV(CC25_CSN_pin)
// NRF24L01
#define NRF_CSN_pin 0 //D8 = PB0
#define NRF_CSN_port PORTB
#define NRF_CSN_ddr DDRB
#define NRF_CSN_output NRF_CSN_ddr |= _BV(NRF_CSN_pin)
#define NRF_CSN_on NRF_CSN_port |= _BV(NRF_CSN_pin)
#define NRF_CSN_off NRF_CSN_port &= ~_BV(NRF_CSN_pin)
#define NRF_CE_on
#define NRF_CE_off
// CYRF6936
#ifdef ORANGE_TX
#define CYRF_CSN_pin 4 //PD4
#define CYRF_CSN_port PORTD
#define CYRF_CSN_ddr DDRD
#define CYRF_CSN_on CYRF_CSN_port.OUTSET = _BV(CYRF_CSN_pin)
#define CYRF_CSN_off CYRF_CSN_port.OUTCLR = _BV(CYRF_CSN_pin)
#define CYRF_RST_pin 0 //PE0
#define CYRF_RST_port PORTE
#define CYRF_RST_ddr DDRE
#define CYRF_RST_HI CYRF_RST_port.OUTSET = _BV(CYRF_RST_pin)
#define CYRF_RST_LO CYRF_RST_port.OUTCLR = _BV(CYRF_RST_pin)
#else
#define CYRF_CSN_pin 1 //D9 = PB1
#define CYRF_CSN_port PORTB
#define CYRF_CSN_ddr DDRB
#define CYRF_CSN_output CYRF_CSN_ddr |= _BV(CYRF_CSN_pin)
#define CYRF_CSN_on CYRF_CSN_port |= _BV(CYRF_CSN_pin)
#define CYRF_CSN_off CYRF_CSN_port &= ~_BV(CYRF_CSN_pin)
#define CYRF_RST_pin 5 //A5 = PC5
#define CYRF_RST_port PORTC
#define CYRF_RST_ddr DDRC
#define CYRF_RST_output CYRF_RST_ddr |= _BV(CYRF_RST_pin)
#define CYRF_RST_HI CYRF_RST_port |= _BV(CYRF_RST_pin)
#define CYRF_RST_LO CYRF_RST_port &= ~_BV(CYRF_RST_pin)
#endif
//RF Switch
#ifdef ORANGE_TX
#define PE1_on
#define PE1_off
#define PE2_on
#define PE2_off
#else
#define PE1_pin 1 //A1 = PC1
#define PE1_port PORTC
#define PE1_ddr DDRC
#define PE1_output PE1_ddr |= _BV(PE1_pin)
#define PE1_on PE1_port |= _BV(PE1_pin)
#define PE1_off PE1_port &= ~_BV(PE1_pin)
#define PE2_pin 2 //A2 = PC2
#define PE2_port PORTC
#define PE2_ddr DDRC
#define PE2_output PE2_ddr |= _BV(PE2_pin)
#define PE2_on PE2_port |= _BV(PE2_pin)
#define PE2_off PE2_port &= ~_BV(PE2_pin)
#endif
// LED
#ifdef ORANGE_TX
#define LED_pin 1 //PD1
#define LED_port PORTD
#define LED_ddr DDRD
#define LED_on LED_port.OUTCLR = _BV(LED_pin)
#define LED_off LED_port.OUTSET = _BV(LED_pin)
#define LED_toggle LED_port.OUTTGL = _BV(LED_pin)
#define LED_output LED_port.DIRSET = _BV(LED_pin)
#define IS_LED_on (LED_port.OUT & _BV(LED_pin))
#else
#define LED_pin 5 //D13 = PB5
#define LED_port PORTB
#define LED_ddr DDRB
#define LED_on LED_port |= _BV(LED_pin)
#define LED_off LED_port &= ~_BV(LED_pin)
#define LED_toggle LED_port ^= _BV(LED_pin)
#define LED_output LED_ddr |= _BV(LED_pin)
#define IS_LED_on (LED_port & _BV(LED_pin))
#endif
//BIND
#ifdef ORANGE_TX
#define BIND_pin 2 //PD2
#define BIND_port PORTD
#define IS_BIND_BUTTON_on ( (BIND_port.IN & _BV(BIND_pin)) == 0x00 )
#else
#define BIND_pin 5 //D13 = PB5
#define BIND_port PORTB
#define BIND_ipr PINB
#define BIND_ddr DDRB
#define BIND_SET_INPUT BIND_ddr &= ~_BV(BIND_pin)
#define BIND_SET_OUTPUT BIND_ddr |= _BV(BIND_pin)
#define BIND_SET_PULLUP BIND_port |= _BV(BIND_pin)
#define IS_BIND_BUTTON_on ( (BIND_ipr & _BV(BIND_pin)) == 0x00 )
#endif
#else //STM32_BOARD
#define BIND_pin PA0
#define LED_pin PA1
//
#define PPM_pin PA8 //PPM 5V tolerant
//
#define S1_pin PA4 //Dial switch pins
#define S2_pin PA5
#define S3_pin PA6
#define S4_pin PA7
//
#define PE1_pin PB4 //PE1
#define PE2_pin PB5 //PE2
//CS pins
#define CC25_CSN_pin PB6 //CC2500
#define NRF_CSN_pin PB7 //NRF24L01
#define CYRF_RST_pin PB8 //CYRF RESET
#define A7105_CSN_pin PB9 //A7105
#define CYRF_CSN_pin PB12 //CYRF CSN
//SPI pins
#define SCK_pin PB13 //SCK
#define SDO_pin PB14 //MISO
#define SDI_pin PB15 //MOSI
//
#define TX_INV_pin PB3
#define RX_INV_pin PB1
//
#define PE1_on digitalWrite(PE1_pin,HIGH)
#define PE1_off digitalWrite(PE1_pin,LOW)
//
#define PE2_on digitalWrite(PE2_pin,HIGH)
#define PE2_off digitalWrite(PE2_pin,LOW)
#define A7105_CSN_on digitalWrite(A7105_CSN_pin,HIGH)
#define A7105_CSN_off digitalWrite(A7105_CSN_pin,LOW)
#define NRF_CE_on
#define NRF_CE_off
#define SCK_on digitalWrite(SCK_pin,HIGH)
#define SCK_off digitalWrite(SCK_pin,LOW)
#define SDI_on digitalWrite(SDI_pin,HIGH)
#define SDI_off digitalWrite(SDI_pin,LOW)
#define SDI_1 (digitalRead(SDI_pin)==HIGH)
#define SDI_0 (digitalRead(SDI_pin)==LOW)
#define CC25_CSN_on digitalWrite(CC25_CSN_pin,HIGH)
#define CC25_CSN_off digitalWrite(CC25_CSN_pin,LOW)
#define NRF_CSN_on digitalWrite(NRF_CSN_pin,HIGH)
#define NRF_CSN_off digitalWrite(NRF_CSN_pin,LOW)
#define CYRF_CSN_on digitalWrite(CYRF_CSN_pin,HIGH)
#define CYRF_CSN_off digitalWrite(CYRF_CSN_pin,LOW)
#define CYRF_RST_HI digitalWrite(CYRF_RST_pin,HIGH) //reset cyrf
#define CYRF_RST_LO digitalWrite(CYRF_RST_pin,LOW) //
#define SDO_1 (digitalRead(SDO_pin)==HIGH)
#define SDO_0 (digitalRead(SDO_pin)==LOW)
#define TX_INV_on digitalWrite(TX_INV_pin,HIGH)
#define TX_INV_off digitalWrite(TX_INV_pin,LOW)
#define RX_INV_on digitalWrite(RX_INV_pin,HIGH)
#define RX_INV_off digitalWrite(RX_INV_pin,LOW)
#define LED_on digitalWrite(LED_pin,HIGH)
#define LED_off digitalWrite(LED_pin,LOW)
#define LED_toggle digitalWrite(LED_pin ,!digitalRead(LED_pin))
#define LED_output pinMode(LED_pin,OUTPUT)
#define IS_LED_on ( digitalRead(LED_pin)==HIGH)
#define BIND_SET_INPUT pinMode(BIND_pin,INPUT)
#define BIND_SET_PULLUP digitalWrite(BIND_pin,HIGH)
#define BIND_SET_OUTPUT pinMode(BIND_pin,OUTPUT)
#define IS_BIND_BUTTON_on (digitalRead(BIND_pin)==LOW)
#define cli() noInterrupts()
#define sei() interrupts()
#define delayMilliseconds(x) delay(x)
#endif #endif
// Dial //*******************
#define MODE_DIAL1_pin 2 //*** Timer ***
#define MODE_DIAL1_port PORTB //*******************
#define MODE_DIAL1_ipr PINB #ifdef ORANGE_TX
#define MODE_DIAL2_pin 3 #define TIFR1 TCC1.INTFLAGS
#define MODE_DIAL2_port PORTB #define OCF1A_bm TC1_CCAIF_bm
#define MODE_DIAL2_ipr PINB #define OCR1A TCC1.CCA
#define MODE_DIAL3_pin 4 #define TCNT1 TCC1.CNT
#define MODE_DIAL3_port PORTB #define UDR0 USARTC0.DATA
#define MODE_DIAL3_ipr PINB #define OCF1B_bm TC1_CCBIF_bm
#define MODE_DIAL4_pin 0 #define OCR1B TCC1.CCB
#define MODE_DIAL4_port PORTC #define TIMSK1 TCC1.INTCTRLB
#define MODE_DIAL4_ipr PINC #define SET_TIMSK1_OCIE1B TIMSK1 = (TIMSK1 & 0xF3) | 0x04
#define CLR_TIMSK1_OCIE1B TIMSK1 &= 0xF3
// PPM
#define PPM_pin 3 //D3 = PD3
#define PPM_port PORTD
// SDIO
#define SDI_pin 5 //D5 = PD5
#define SDI_port PORTD
#define SDI_ipr PIND
#define SDI_ddr DDRD
#ifdef XMEGA
#define SDI_on SDI_port.OUTSET = _BV(SDI_pin)
#define SDI_off SDI_port.OUTCLR = _BV(SDI_pin)
#else #else
#define SDI_on SDI_port |= _BV(SDI_pin) #ifdef STM32_BOARD
#define SDI_off SDI_port &= ~_BV(SDI_pin) #define OCR1A TIMER2_BASE->CCR1
#define SDI_1 (SDI_ipr & _BV(SDI_pin)) #define TCNT1 TIMER2_BASE->CNT
#define SDI_0 (SDI_ipr & _BV(SDI_pin)) == 0x00 #define UDR0 USART2_BASE->DR
#endif #define TIFR1 TIMER2_BASE->SR
#define SDI_input SDI_ddr &= ~_BV(SDI_pin) #define OCF1A_bm TIMER_SR_CC1IF
#define SDI_output SDI_ddr |= _BV(SDI_pin) #define UCSR0B USART2_BASE->CR1
#define RXCIE0 USART_CR1_RXNEIE_BIT
//SDO #define TXCIE0 USART_CR1_TXEIE_BIT
#define SDO_pin 6 //D6 = PD6 //#define TIFR1 TIMER2_BASE->SR
#define SDO_port PORTD #else
#define SDO_ipr PIND #define OCF1A_bm _BV(OCF1A)
#ifdef XMEGA #define OCF1B_bm _BV(OCF1B)
#define SDO_1 (SDO_port.IN & _BV(SDO_pin)) #define SET_TIMSK1_OCIE1B TIMSK1 |= _BV(OCIE1B)
#define SDO_0 (SDO_port.IN & _BV(SDO_pin)) == 0x00 #define CLR_TIMSK1_OCIE1B TIMSK1 &=~_BV(OCIE1B)
#else #endif
#define SDO_1 (SDO_ipr & _BV(SDO_pin))
#define SDO_0 (SDO_ipr & _BV(SDO_pin)) == 0x00
#endif #endif
// SCLK //*******************
#define SCLK_port PORTD //*** EEPROM ***
#define SCLK_ddr DDRD //*******************
#ifdef XMEGA #ifdef STM32_BOARD
#define SCLK_pin 7 //PD7 #define EE_ADDR uint16
#define SCLK_on SCLK_port.OUTSET = _BV(SCLK_pin) #define eeprom_write_byte EEPROM.write
#define SCLK_off SCLK_port.OUTCLR = _BV(SCLK_pin) #define eeprom_read_byte EEPROM.read
#else #else
#define SCLK_pin 4 //D4 = PD4 #define EE_ADDR uint8_t*
#define SCLK_output SCLK_ddr |= _BV(SCLK_pin)
#define SCLK_on SCLK_port |= _BV(SCLK_pin)
#define SCLK_off SCLK_port &= ~_BV(SCLK_pin)
#endif
// A7105
#define A7105_CSN_pin 2 //D2 = PD2
#define A7105_CSN_port PORTD
#define A7105_CSN_ddr DDRD
#define A7105_CSN_output A7105_CSN_ddr |= _BV(A7105_CSN_pin)
#define A7105_CSN_on A7105_CSN_port |= _BV(A7105_CSN_pin)
#define A7105_CSN_off A7105_CSN_port &= ~_BV(A7105_CSN_pin)
// CC2500
#define CC25_CSN_pin 7 //D7 = PD7
#define CC25_CSN_port PORTD
#define CC25_CSN_ddr DDRD
#define CC25_CSN_output CC25_CSN_ddr |= _BV(CC25_CSN_pin)
#define CC25_CSN_on CC25_CSN_port |= _BV(CC25_CSN_pin)
#define CC25_CSN_off CC25_CSN_port &= ~_BV(CC25_CSN_pin)
// NRF24L01
#define NRF_CSN_pin 0 //D8 = PB0
#define NRF_CSN_port PORTB
#define NRF_CSN_ddr DDRB
#define NRF_CSN_output NRF_CSN_ddr |= _BV(NRF_CSN_pin)
#define NRF_CSN_on NRF_CSN_port |= _BV(NRF_CSN_pin)
#define NRF_CSN_off NRF_CSN_port &= ~_BV(NRF_CSN_pin)
#define NRF_CE_on
#define NRF_CE_off
// CYRF6936
#ifdef XMEGA
#define CYRF_CSN_pin 4 //PD4
#define CYRF_CSN_port PORTD
#define CYRF_CSN_ddr DDRD
#define CYRF_CSN_on CYRF_CSN_port.OUTSET = _BV(CYRF_CSN_pin)
#define CYRF_CSN_off CYRF_CSN_port.OUTCLR = _BV(CYRF_CSN_pin)
#define CYRF_RST_pin 0 //PE0
#define CYRF_RST_port PORTE
#define CYRF_RST_ddr DDRE
#define CYRF_RST_HI CYRF_RST_port.OUTSET = _BV(CYRF_RST_pin)
#define CYRF_RST_LO CYRF_RST_port.OUTCLR = _BV(CYRF_RST_pin)
#else
#define CYRF_CSN_pin 1 //D9 = PB1
#define CYRF_CSN_port PORTB
#define CYRF_CSN_ddr DDRB
#define CYRF_CSN_output CYRF_CSN_ddr |= _BV(CYRF_CSN_pin)
#define CYRF_CSN_on CYRF_CSN_port |= _BV(CYRF_CSN_pin)
#define CYRF_CSN_off CYRF_CSN_port &= ~_BV(CYRF_CSN_pin)
#define CYRF_RST_pin 5 //A5 = PC5
#define CYRF_RST_port PORTC
#define CYRF_RST_ddr DDRC
#define CYRF_RST_output CYRF_RST_ddr |= _BV(CYRF_RST_pin)
#define CYRF_RST_HI CYRF_RST_port |= _BV(CYRF_RST_pin)
#define CYRF_RST_LO CYRF_RST_port &= ~_BV(CYRF_RST_pin)
#endif
//RF Switch
#ifdef XMEGA
#define PE1_on
#define PE1_off
#define PE2_on
#define PE2_off
#else
#define PE1_pin 1 //A1 = PC1
#define PE1_port PORTC
#define PE1_ddr DDRC
#define PE1_output PE1_ddr |= _BV(PE1_pin)
#define PE1_on PE1_port |= _BV(PE1_pin)
#define PE1_off PE1_port &= ~_BV(PE1_pin)
#define PE2_pin 2 //A2 = PC2
#define PE2_port PORTC
#define PE2_ddr DDRC
#define PE2_output PE2_ddr |= _BV(PE2_pin)
#define PE2_on PE2_port |= _BV(PE2_pin)
#define PE2_off PE2_port &= ~_BV(PE2_pin)
#endif
// LED
#ifdef XMEGA
#define LED_pin 1 //PD1
#define LED_port PORTD
#define LED_ddr DDRD
#define LED_on LED_port.OUTCLR = _BV(LED_pin)
#define LED_off LED_port.OUTSET = _BV(LED_pin)
#define LED_toggle LED_port.OUTTGL = _BV(LED_pin)
#define LED_output LED_port.DIRSET = _BV(LED_pin)
#define IS_LED_on (LED_port.OUT & _BV(LED_pin))
#else
#define LED_pin 5 //D13 = PB5
#define LED_port PORTB
#define LED_ddr DDRB
#define LED_on LED_port |= _BV(LED_pin)
#define LED_off LED_port &= ~_BV(LED_pin)
#define LED_toggle LED_port ^= _BV(LED_pin)
#define LED_output LED_ddr |= _BV(LED_pin)
#define IS_LED_on (LED_port & _BV(LED_pin))
#endif
//BIND
#ifdef XMEGA
#define BIND_pin 2 //PD2
#define BIND_port PORTD
#define IS_BIND_BUTTON_on ( (BIND_port.IN & _BV(BIND_pin)) == 0x00 )
#else
#define BIND_pin 5 //D13 = PB5
#define BIND_port PORTB
#define BIND_ipr PINB
#define BIND_ddr DDRB
#define BIND_SET_INPUT BIND_ddr &= ~_BV(BIND_pin)
#define BIND_SET_OUTPUT BIND_ddr |= _BV(BIND_pin)
#define BIND_SET_PULLUP BIND_port |= _BV(BIND_pin)
#define IS_BIND_BUTTON_on ( (BIND_ipr & _BV(BIND_pin)) == 0x00 )
#endif #endif

275
Multiprotocol/README.md Normal file
View File

@ -0,0 +1,275 @@
# 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
###CG023
###Sub_protocol H8_3D
Models: EAchine H8 mini 3D, JJRC H20/H22, JJRC H11D
CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---
FLIP|LIGTH|OPT1|OPT2|CAL|SNAPSHOT|VIDEO
JJRC H20: OPT1=Headless, OPT2=RTH
JJRC H22: OPT1=RTH, OPT2=180/360° flip mode
H8 3D: OPT1=RTH then press a direction to enter headless mode (like stock TX), OPT2=switch 180/360° flip mode
CAL: calibrate accelerometers
###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
###HISKY
####Sub_protocol HK310
###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
###MJX
####Sub_protocol H26WH
###NE260
Modele: Nine Eagles SoloPro
Autobind
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
###Q303
Autobind
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|AHOLD|FLIP|SNAPSHOT|VIDEO|HEADLESS|RTH|GIMBAL
###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.
###V2X2
####Sub_protocol V2X2
Models: WLToys V202/252/272, JXD 385/388, JJRC H6C, Yizhan Tarantula X6 ...
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS|MAG_CAL_X|MAG_CAL_Y
PICTURE: also automatic Missile Launcher and Hoist in one direction
VIDEO: also Sprayer, Bubbler, Missile Launcher(1), and Hoist in the other dir
####Sub_protocol JXD-506
CH10|CH11|CH12
----|----|----
ARM|EMERGENCY|PAN CAMERA
###D'autres à venir

View File

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

View File

@ -12,7 +12,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
// Last sync with hexfet new_protocols/slt_nrf24l01.c dated 2015-02-13 // Last sync with deviation main github branch
#if defined(SLT_NRF24L01_INO) #if defined(SLT_NRF24L01_INO)
@ -24,11 +24,11 @@
#define SLT_TXID_SIZE 4 #define SLT_TXID_SIZE 4
enum { enum {
SLT_INIT2 = 0, SLT_BUILD=0,
SLT_BIND,
SLT_DATA1, SLT_DATA1,
SLT_DATA2, SLT_DATA2,
SLT_DATA3 SLT_DATA3,
SLT_BIND
}; };
static void __attribute__((unused)) SLT_init() static void __attribute__((unused)) SLT_init()
@ -45,24 +45,18 @@ static void __attribute__((unused)) SLT_init()
NRF24L01_SetPower(); NRF24L01_SetPower();
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xC3\xC3\xAA\x55", 4); NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xC3\xC3\xAA\x55", 4);
NRF24L01_FlushRx(); NRF24L01_FlushRx();
} NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE);
static void __attribute__((unused)) SLT_init2()
{
NRF24L01_FlushTx(); NRF24L01_FlushTx();
packet_sent = 0;
hopping_frequency_no = 0;
// Turn radio power on // Turn radio power on
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
} }
static void __attribute__((unused)) SLT_set_tx_id(void) static void __attribute__((unused)) SLT_set_freq(void)
{ {
// Frequency hopping sequence generation // Frequency hopping sequence generation
for (uint8_t i = 0; i < 4; ++i) for (uint8_t i = 0; i < SLT_TXID_SIZE; ++i)
{ {
uint8_t next_i = (i+1) % 4; // is & 3 better than % 4 ? uint8_t next_i = (i+1) % SLT_TXID_SIZE; // is & 3 better than % 4 ?
uint8_t base = i < 2 ? 0x03 : 0x10; uint8_t base = i < 2 ? 0x03 : 0x10;
hopping_frequency[i*4 + 0] = (rx_tx_addr[i] & 0x3f) + base; hopping_frequency[i*4 + 0] = (rx_tx_addr[i] & 0x3f) + base;
hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base; hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base;
@ -72,8 +66,9 @@ static void __attribute__((unused)) SLT_set_tx_id(void)
} }
// unique // unique
uint8_t done = 0;
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i) for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
{
uint8_t done = 0;
while (!done) while (!done)
{ {
done = 1; done = 1;
@ -86,14 +81,13 @@ static void __attribute__((unused)) SLT_set_tx_id(void)
hopping_frequency[i] = hopping_frequency[i] - 0x50 + 0x03; hopping_frequency[i] = hopping_frequency[i] - 0x50 + 0x03;
} }
} }
}
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4);
} }
static void __attribute__((unused)) SLT_wait_radio() static void __attribute__((unused)) SLT_wait_radio()
{ {
if (packet_sent) if (packet_sent)
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS))) ; while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)));
packet_sent = 0; packet_sent = 0;
} }
@ -109,9 +103,15 @@ static void __attribute__((unused)) SLT_send_data(uint8_t *data, uint8_t len)
static void __attribute__((unused)) SLT_build_packet() static void __attribute__((unused)) SLT_build_packet()
{ {
// aileron, elevator, throttle, rudder, gear, pitch // Set radio channel - once per packet batch
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
// aileron, elevator, throttle, rudder, gear, pitch
uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed
for (uint8_t i = 0; i < 4; ++i) { for (uint8_t i = 0; i < 4; ++i)
{
uint16_t v = convert_channel_10b(CH_AETR[i]); uint16_t v = convert_channel_10b(CH_AETR[i]);
packet[i] = v; packet[i] = v;
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0); e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
@ -121,81 +121,71 @@ static void __attribute__((unused)) SLT_build_packet()
// 8-bit channels // 8-bit channels
packet[5] = convert_channel_8b(AUX1); packet[5] = convert_channel_8b(AUX1);
packet[6] = convert_channel_8b(AUX2); packet[6] = convert_channel_8b(AUX2);
// Set radio channel - once per packet batch
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
} }
static void __attribute__((unused)) SLT_send_bind_packet() static void __attribute__((unused)) SLT_send_bind_packet()
{ {
SLT_wait_radio(); SLT_wait_radio();
BIND_IN_PROGRESS; // autobind protocol BIND_IN_PROGRESS; //Limit TX power to bind level
NRF24L01_SetPower(); NRF24L01_SetPower();
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x7E\xB8\x63\xA9", 4); BIND_DONE;
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x50); NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x50);
SLT_send_data(rx_tx_addr, 4); SLT_send_data(rx_tx_addr, SLT_TXID_SIZE);
// NB: we should wait until the packet's sent before changing TX address! SLT_wait_radio(); //Wait until the packet's sent before changing TX address!
SLT_wait_radio();
BIND_DONE; NRF24L01_SetPower(); //Change power back to normal level
NRF24L01_SetPower(); NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4);
} }
uint16_t SLT_callback() uint16_t SLT_callback()
{ {
uint16_t delay_us = 20000; // 3 packets with 1ms intervals every 22ms
switch (phase) switch (phase)
{ {
case SLT_INIT2: case SLT_BUILD:
SLT_init2();
phase = SLT_BIND;
delay_us = 150;
break;
case SLT_BIND:
SLT_send_bind_packet();
phase = SLT_DATA1;
delay_us = 19000;
break;
case SLT_DATA1:
SLT_build_packet(); SLT_build_packet();
SLT_send_data(packet, 7); phase++;
phase = SLT_DATA2; return 1000;
delay_us = 1000; case SLT_DATA1:
break; SLT_send_data(packet, SLT_PAYLOADSIZE);
phase++;
return 1000;
case SLT_DATA2: case SLT_DATA2:
SLT_send_data(packet, 7); SLT_send_data(packet, SLT_PAYLOADSIZE);
phase = SLT_DATA3; phase++;
delay_us = 1000; return 1000;
break;
case SLT_DATA3: case SLT_DATA3:
SLT_send_data(packet, 7); SLT_send_data(packet, SLT_PAYLOADSIZE);
if (++counter >= 100) if (++packet_count >= 100)
{ {
counter = 0; packet_count = 0;
phase = SLT_BIND; phase++;
delay_us = 1000; return 1000;
} }
else else
{ {
NRF24L01_SetPower(); // Set tx_power NRF24L01_SetPower(); // Set tx_power
phase = SLT_DATA1; phase = SLT_BUILD;
return 19000;
} }
break; case SLT_BIND:
SLT_send_bind_packet();
phase = SLT_BUILD;
return 18000;
} }
return delay_us; return 19000;
} }
uint16_t initSLT() uint16_t initSLT()
{ {
counter = 0; packet_count = 0;
packet_sent = 0;
hopping_frequency_no = 0;
SLT_set_freq();
SLT_init(); SLT_init();
phase = SLT_INIT2; phase = SLT_BIND;
SLT_set_tx_id();
return 50000; return 50000;
} }

View File

@ -15,72 +15,145 @@
/********************/ /********************/
/** SPI routines **/ /** SPI routines **/
/********************/ /********************/
#ifdef XMEGA #ifdef STM32_BOARD
#define XNOP() NOP()
SPIClass SPI_2(2); //Create an instance of the SPI Class called SPI_2 that uses the 2nd SPI Port
void initSPI2()
{
//SPI_DISABLE();
SPI_2.end();
SPI2_BASE->CR1 &= ~SPI_CR1_DFF_8_BIT; //8 bits format This bit should be written only when SPI is disabled (SPE = ?0?) for correct operation.
SPI_2.begin(); //Initialize the SPI_2 port.
SPI_2.setBitOrder(MSBFIRST); // Set the SPI_2 bit order
SPI_2.setDataMode(SPI_MODE0); // Set the SPI_2 data mode 0
SPI_2.setClockDivider(SPI_CLOCK_DIV8); // Set the speed (36 / 8 = 4.5 MHz SPI_2 speed)
}
void SPI_Write(uint8_t command)
{//working OK
SPI2_BASE->DR = command; //Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag).
while (!(SPI2_BASE->SR & SPI_SR_RXNE));
command = SPI2_BASE->DR; // ... and read the last received data.
}
uint8_t SPI_Read(void)
{
SPI_Write(0x00);
return SPI2_BASE->DR;
}
uint8_t SPI_SDI_Read()
{
uint8_t rx=0;
cli(); //Fix Hubsan droputs??
while(!(SPI2_BASE->SR & SPI_SR_TXE));
while((SPI2_BASE->SR & SPI_SR_BSY));
//
SPI_DISABLE();
SPI_SET_BIDIRECTIONAL();
volatile uint8_t x = SPI2_BASE->DR;
(void)x;
SPI_ENABLE();
//
SPI_DISABLE();
while(!(SPI2_BASE->SR& SPI_SR_RXNE));
rx=SPI2_BASE->DR;
SPI_SET_UNIDIRECTIONAL();
SPI_ENABLE();
sei();//fix Hubsan dropouts??
return rx;
}
void SPI_ENABLE()
{
SPI2_BASE->CR1 |= SPI_CR1_SPE;
}
void SPI_DISABLE()
{
SPI2_BASE->CR1 &= ~SPI_CR1_SPE;
}
void SPI_SET_BIDIRECTIONAL()
{
SPI2_BASE->CR1 |= SPI_CR1_BIDIMODE;
SPI2_BASE->CR1 &= ~ SPI_CR1_BIDIOE;//receive only
}
void SPI_SET_UNIDIRECTIONAL()
{
SPI2_BASE->CR1 &= ~SPI_CR1_BIDIMODE;
}
#else #else
#define XNOP() #ifdef ORANGE_TX
#endif #define XNOP() NOP()
#else
#define XNOP()
#endif
void SPI_Write(uint8_t command) void SPI_Write(uint8_t command)
{
uint8_t n=8;
SCLK_off;//SCK start low
XNOP();
SDI_off;
XNOP();
do
{ {
if(command&0x80) uint8_t n=8;
SDI_on;
else
SDI_off;
XNOP();
SCLK_on;
XNOP();
XNOP();
command = command << 1;
SCLK_off;
XNOP();
}
while(--n) ;
SDI_on;
}
uint8_t SPI_Read(void) SCLK_off;//SCK start low
{ XNOP();
uint8_t result=0,i; SDI_off;
for(i=0;i<8;i++) XNOP();
do
{
if(command&0x80)
SDI_on;
else
SDI_off;
XNOP();
SCLK_on;
XNOP();
XNOP();
command = command << 1;
SCLK_off;
XNOP();
}
while(--n) ;
SDI_on;
}
uint8_t SPI_Read(void)
{ {
result=result<<1; uint8_t result=0,i;
if(SDO_1) for(i=0;i<8;i++)
result |= 0x01; {
SCLK_on; result=result<<1;
XNOP(); if(SDO_1)
XNOP(); result |= 0x01;
NOP(); SCLK_on;
SCLK_off; XNOP();
XNOP(); XNOP();
XNOP(); NOP();
SCLK_off;
XNOP();
XNOP();
}
return result;
} }
return result;
}
#ifdef A7105_INSTALLED #ifdef A7105_INSTALLED
uint8_t SPI_SDIO_Read(void) uint8_t SPI_SDI_Read(void)
{ {
uint8_t result=0; uint8_t result=0;
SDI_input; SDI_input;
for(uint8_t i=0;i<8;i++) for(uint8_t i=0;i<8;i++)
{ {
result=result<<1; result=result<<1;
if(SDI_1) ///if SDIO =1 if(SDI_1) ///if SDIO =1
result |= 0x01; result |= 0x01;
SCLK_on; SCLK_on;
NOP(); NOP();
SCLK_off; SCLK_off;
}
SDI_output;
return result;
} }
SDI_output; #endif
return result; #endif//STM32_BOARD
}
#endif

View File

@ -22,6 +22,16 @@
#define PPM_MIN_125 1000 // 125% #define PPM_MIN_125 1000 // 125%
#endif #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 // HISKY
#if defined(TX_HISKY) #if defined(TX_HISKY)
#define PPM_MAX_100 1900 // 100% #define PPM_MAX_100 1900 // 100%
@ -37,7 +47,6 @@
#define PPM_MAX_125 2050 // 125% #define PPM_MAX_125 2050 // 125%
#define PPM_MIN_125 1150 // 125% #define PPM_MIN_125 1150 // 125%
#endif #endif
//Serial MIN MAX values //Serial MIN MAX values
#define SERIAL_MAX_100 2012 // 100% #define SERIAL_MAX_100 2012 // 100%
#define SERIAL_MIN_100 988 // 100% #define SERIAL_MIN_100 988 // 100%
@ -47,203 +56,156 @@
//PPM values used to compare //PPM values used to compare
#define PPM_MIN_COMMAND 1250 #define PPM_MIN_COMMAND 1250
#define PPM_SWITCH 1550 #define PPM_SWITCH 1550
#define PPM_SWITCH_B 1450
#define PPM_MAX_COMMAND 1750 #define PPM_MAX_COMMAND 1750
//Channel definitions //Channel definitions
#ifdef AETR #ifdef AETR
enum { #define AILERON 0
AILERON =0, #define ELEVATOR 1
ELEVATOR, #define THROTTLE 2
THROTTLE, #define RUDDER 3
RUDDER,
};
#endif #endif
#ifdef AERT #ifdef AERT
enum { #define AILERON 0
AILERON =0, #define ELEVATOR 1
ELEVATOR, #define THROTTLE 3
RUDDER, #define RUDDER 2
THROTTLE,
};
#endif #endif
#ifdef ARET #ifdef ARET
enum { #define AILERON 0
AILERON =0, #define ELEVATOR 2
RUDDER, #define THROTTLE 3
ELEVATOR, #define RUDDER 1
THROTTLE,
};
#endif #endif
#ifdef ARTE #ifdef ARTE
enum { #define AILERON 0
AILERON =0, #define ELEVATOR 3
RUDDER, #define THROTTLE 2
THROTTLE, #define RUDDER 1
ELEVATOR,
};
#endif #endif
#ifdef ATRE #ifdef ATRE
enum { #define AILERON 0
AILERON =0, #define ELEVATOR 3
THROTTLE, #define THROTTLE 1
RUDDER, #define RUDDER 2
ELEVATOR,
};
#endif #endif
#ifdef ATER #ifdef ATER
enum { #define AILERON 0
AILERON =0, #define ELEVATOR 2
THROTTLE, #define THROTTLE 1
ELEVATOR, #define RUDDER 3
RUDDER,
};
#endif #endif
#ifdef EATR #ifdef EATR
enum { #define AILERON 1
ELEVATOR =0, #define ELEVATOR 0
AILERON, #define THROTTLE 2
THROTTLE, #define RUDDER 3
RUDDER,
};
#endif #endif
#ifdef EART #ifdef EART
enum { #define AILERON 1
ELEVATOR =0, #define ELEVATOR 0
AILERON, #define THROTTLE 3
RUDDER, #define RUDDER 2
THROTTLE,
};
#endif #endif
#ifdef ERAT #ifdef ERAT
enum { #define AILERON 2
ELEVATOR =0, #define ELEVATOR 0
RUDDER, #define THROTTLE 3
AILERON, #define RUDDER 1
THROTTLE,
};
#endif #endif
#ifdef ERTA #ifdef ERTA
enum { #define AILERON 3
ELEVATOR =0, #define ELEVATOR 0
RUDDER, #define THROTTLE 2
THROTTLE, #define RUDDER 1
AILERON,
};
#endif #endif
#ifdef ETRA #ifdef ETRA
enum { #define AILERON 3
ELEVATOR =0, #define ELEVATOR 0
THROTTLE, #define THROTTLE 1
RUDDER, #define RUDDER 2
AILERON,
};
#endif #endif
#ifdef ETAR #ifdef ETAR
enum { #define AILERON 2
ELEVATOR =0, #define ELEVATOR 0
THROTTLE, #define THROTTLE 1
AILERON, #define RUDDER 3
RUDDER,
};
#endif #endif
#ifdef TEAR #ifdef TEAR
enum { #define AILERON 2
THROTTLE =0, #define ELEVATOR 1
ELEVATOR, #define THROTTLE 0
AILERON, #define RUDDER 3
RUDDER,
};
#endif #endif
#ifdef TERA #ifdef TERA
enum { #define AILERON 3
THROTTLE =0, #define ELEVATOR 1
ELEVATOR, #define THROTTLE 0
RUDDER, #define RUDDER 2
AILERON,
};
#endif #endif
#ifdef TREA #ifdef TREA
enum { #define AILERON 3
THROTTLE =0, #define ELEVATOR 2
RUDDER, #define THROTTLE 0
ELEVATOR, #define RUDDER 1
AILERON,
};
#endif #endif
#ifdef TRAE #ifdef TRAE
enum { #define AILERON 2
THROTTLE =0, #define ELEVATOR 3
RUDDER, #define THROTTLE 0
AILERON, #define RUDDER 1
ELEVATOR,
};
#endif #endif
#ifdef TARE #ifdef TARE
enum { #define AILERON 1
THROTTLE =0, #define ELEVATOR 3
AILERON, #define THROTTLE 0
RUDDER, #define RUDDER 2
ELEVATOR,
};
#endif #endif
#ifdef TAER #ifdef TAER
enum { #define AILERON 1
THROTTLE =0, #define ELEVATOR 2
AILERON, #define THROTTLE 0
ELEVATOR, #define RUDDER 3
RUDDER,
};
#endif #endif
#ifdef RETA #ifdef RETA
enum { #define AILERON 3
RUDDER =0, #define ELEVATOR 1
ELEVATOR, #define THROTTLE 2
THROTTLE, #define RUDDER 0
AILERON,
};
#endif #endif
#ifdef REAT #ifdef REAT
enum { #define AILERON 2
RUDDER =0, #define ELEVATOR 1
ELEVATOR, #define THROTTLE 3
AILERON, #define RUDDER 0
THROTTLE,
};
#endif #endif
#ifdef RAET #ifdef RAET
enum { #define AILERON 1
RUDDER =0, #define ELEVATOR 2
AILERON, #define THROTTLE 3
ELEVATOR, #define RUDDER 0
THROTTLE,
};
#endif #endif
#ifdef RATE #ifdef RATE
enum { #define AILERON 1
RUDDER =0, #define ELEVATOR 3
AILERON, #define THROTTLE 2
THROTTLE, #define RUDDER 0
ELEVATOR,
};
#endif #endif
#ifdef RTAE #ifdef RTAE
enum { #define AILERON 2
RUDDER =0, #define ELEVATOR 3
THROTTLE, #define THROTTLE 1
AILERON, #define RUDDER 0
ELEVATOR,
};
#endif #endif
#ifdef RTEA #ifdef RTEA
enum { #define AILERON 3
RUDDER =0, #define ELEVATOR 2
THROTTLE, #define THROTTLE 1
ELEVATOR, #define RUDDER 0
AILERON,
};
#endif #endif
#define AUX1 4 #define AUX1 4

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 This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -212,7 +37,7 @@
#define MAX_PKTX 10 #define MAX_PKTX 10
uint8_t pktx[MAX_PKTX]; uint8_t pktx[MAX_PKTX];
uint8_t pktx1[MAX_PKTX]; uint8_t pktx1[MAX_PKTX];
uint8_t index; uint8_t indx;
uint8_t frame[18]; uint8_t frame[18];
#ifdef BASH_SERIAL #ifdef BASH_SERIAL
@ -236,6 +61,15 @@ void DSM_frame()
} }
#endif #endif
#if defined AFHDS2A_TELEMETRY
void AFHDSA_short_frame()
{
Serial_write(0xAA); // Telemetry packet
for (uint8_t i = 0; i < 29; i++) // RSSI value followed by 4*7 bytes of telemetry data
Serial_write(pkt[i]);
}
#endif
void frskySendStuffed() void frskySendStuffed()
{ {
Serial_write(START_STOP); Serial_write(START_STOP);
@ -272,6 +106,7 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
telemetry_counter=(telemetry_counter+1)%32; telemetry_counter=(telemetry_counter+1)%32;
// //
#if defined SPORT_TELEMETRY && defined FRSKYX_CC2500_INO #if defined SPORT_TELEMETRY && defined FRSKYX_CC2500_INO
telemetry_lost=0;
if (protocol==MODE_FRSKYX) if (protocol==MODE_FRSKYX)
{ {
if ((pktt[5] >> 4 & 0x0f) == 0x08) if ((pktt[5] >> 4 & 0x0f) == 0x08)
@ -304,12 +139,12 @@ void frsky_link_frame()
frame[4] = (uint8_t)RSSI_dBm; frame[4] = (uint8_t)RSSI_dBm;
} }
else 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[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V
frame[2] = frame[1]; frame[2] = frame[1];
frame[3] = 0x00; frame[3] = protocol==MODE_HUBSAN?0x00:(uint8_t)RSSI_dBm;
frame[4] = (uint8_t)RSSI_dBm; frame[4] = TX_RSSI;
} }
frame[5] = frame[6] = frame[7] = frame[8] = 0; frame[5] = frame[6] = frame[7] = frame[8] = 0;
frskySendStuffed(); frskySendStuffed();
@ -346,28 +181,28 @@ void frsky_user_frame()
pass=1; pass=1;
case 1: case 1:
index=indexx; indx=indexx;
prev_index = indexx; prev_index = indexx;
if(index<USER_MAX_BYTES) if(indx<USER_MAX_BYTES)
{ {
for(i=0;i<index;i++) for(i=0;i<indx;i++)
frame[i+3]=pktx[i]; frame[i+3]=pktx[i];
pktt[6]=0; pktt[6]=0;
pass=0; pass=0;
} }
else else
{ {
index = USER_MAX_BYTES; indx = USER_MAX_BYTES;
for(i=0;i<index;i++) for(i=0;i<indx;i++)
frame[i+3]=pktx[i]; frame[i+3]=pktx[i];
pass=2; pass=2;
} }
break; break;
case 2: case 2:
index = prev_index - index; indx = prev_index - indx;
prev_index=0; prev_index=0;
if(index<=(MAX_PKTX-USER_MAX_BYTES)) //10-6=4 if(indx<=(MAX_PKTX-USER_MAX_BYTES)) //10-6=4
for(i=0;i<index;i++) for(i=0;i<indx;i++)
frame[i+3]=pktx[USER_MAX_BYTES+i]; frame[i+3]=pktx[USER_MAX_BYTES+i];
pass=0; pass=0;
pktt[6]=0; pktt[6]=0;
@ -375,9 +210,9 @@ void frsky_user_frame()
default: default:
break; break;
} }
if(!index) if(!indx)
return; return;
frame[1] = index; frame[1] = indx;
frskySendStuffed(); frskySendStuffed();
} }
else else
@ -405,7 +240,6 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
100K 8E2 normal-multiprotocol 100K 8E2 normal-multiprotocol
-every 12ms-or multiple of 12; %36 -every 12ms-or multiple of 12; %36
1 2 3 4 5 6 7 8 9 CRC DESCR 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 05 F1 20 23 0F 00 A6 SWR_ID
7E 98 10 01 F1 33 00 00 00 C9 RSSI_ID 7E 98 10 01 F1 33 00 00 00 C9 RSSI_ID
7E 98 10 04 F1 58 00 00 00 A1 BATT_ID 7E 98 10 04 F1 58 00 00 00 A1 BATT_ID
@ -417,24 +251,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 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 Telemetry frames(RF) SPORT info
15 bytes payload 15 bytes payload
SPORT frame valid 6+3 bytes SPORT frame valid 6+3 bytes
>>>>>>> refs/remotes/pascallanger/master
[00] PKLEN 0E 0E 0E 0E [00] PKLEN 0E 0E 0E 0E
[01] TXID1 DD DD DD DD [01] TXID1 DD DD DD DD
[02] TXID2 6D 6D 6D 6D [02] TXID2 6D 6D 6D 6D
[03] CONST 02 02 02 02 [03] CONST 02 02 02 02
[04] RS/RB 2C D0 2C CE //D0;CE=2*RSSI;....2C = RX battery voltage(5V from Bec) [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 [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 [06] NO.BT 00 00 06 03 //No.of valid SPORT frame bytes in the frame
[07] STRM1 00 00 7E 00 [07] STRM1 00 00 7E 00
[08] STRM2 00 00 1A 00 [08] STRM2 00 00 1A 00
@ -442,146 +267,6 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
[10] STRM4 03 03 03 03 [10] STRM4 03 03 03 03
[11] STRM5 F1 F1 F1 F1 [11] STRM5 F1 F1 F1 F1
[12] STRM6 D1 D1 D0 D0 [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) [13] CHKSUM1 --|2 CRC bytes sent by RX (calculated on RX side crc16/table)
[14] CHKSUM2 --| [14] CHKSUM2 --|
+2 appended bytes automatically RSSI and LQI/CRC bytes(len=0x0E+3); +2 appended bytes automatically RSSI and LQI/CRC bytes(len=0x0E+3);
@ -635,7 +320,11 @@ void sportSendFrame()
{ {
uint8_t i; uint8_t i;
sport_counter = (sport_counter + 1) %36; sport_counter = (sport_counter + 1) %36;
if(telemetry_lost)
{
sportIdle();
return;
}
if(sport_counter<6) if(sport_counter<6)
{ {
frame[0] = 0x98; frame[0] = 0x98;
@ -686,30 +375,30 @@ void proces_sport_data(uint8_t data)
case 0: case 0:
if (data == START_STOP) if (data == START_STOP)
{//waiting for 0x7e {//waiting for 0x7e
index = 0; indx = 0;
pass = 1; pass = 1;
} }
break; break;
case 1: case 1:
if (data == START_STOP) // Happens if missed packet if (data == START_STOP) // Happens if missed packet
{//waiting for 0x7e {//waiting for 0x7e
index = 0; indx = 0;
pass = 1; pass = 1;
break; break;
} }
if(data == BYTESTUFF)//if they are stuffed if(data == BYTESTUFF)//if they are stuffed
pass=2; pass=2;
else else
if (index < MAX_PKTX) if (indx < MAX_PKTX)
pktx[index++] = data; pktx[indx++] = data;
break; break;
case 2: case 2:
if (index < MAX_PKTX) if (indx < MAX_PKTX)
pktx[index++] = data ^ STUFF_MASK; //unstuff bytes pktx[indx++] = data ^ STUFF_MASK; //unstuff bytes
pass=1; pass=1;
break; break;
} // end switch } // end switch
if (index >= FRSKY_SPORT_PACKET_SIZE) if (indx >= FRSKY_SPORT_PACKET_SIZE)
{//8 bytes no crc {//8 bytes no crc
if ( sport ) if ( sport )
{ {
@ -732,93 +421,99 @@ void proces_sport_data(uint8_t data)
void TelemetryUpdate() 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;
}
}
#endif
// check for space in tx buffer // check for space in tx buffer
#ifdef BASH_SERIAL
#ifdef BASH_SERIAL uint8_t h ;
uint8_t h ; uint8_t t ;
uint8_t t ; h = SerialControl.head ;
h = SerialControl.head ; t = SerialControl.tail ;
t = SerialControl.tail ; if ( h >= t )
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
#if defined DSM_TELEMETRY
if(telemetry_link && protocol == MODE_DSM )
{ // DSM
DSM_frame();
telemetry_link=0;
return;
}
#endif
if(telemetry_link && protocol != MODE_FRSKYX )
{ // FrSky + Hubsan
frsky_link_frame();
telemetry_link=0;
return;
}
#if defined HUB_TELEMETRY
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(); t += 64 - h ;
last += SPORT_TIME ; }
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
#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 ;
if(pktt[6]<=6)
for (uint8_t i=0; i < pktt[6]; i++)
proces_sport_data(pktt[7+i]);
telemetry_link=0;
}
uint32_t now = micros();
if ((now - last) > SPORT_TIME)
{
sportSendFrame();
#ifdef STM32_BOARD
last=now;
#else
last += SPORT_TIME ;
#endif
}
} }
}
#endif #endif
#if defined DSM_TELEMETRY
if(telemetry_link && protocol == MODE_DSM )
{ // DSM
DSM_frame();
telemetry_link=0;
return;
}
#endif
#if defined AFHDS2A_TELEMETRY
if(telemetry_link == 2 && protocol == MODE_AFHDS2A)
{
AFHDSA_short_frame();
telemetry_link=0;
}
#endif
if(telemetry_link && protocol != MODE_FRSKYX )
{ // FrSkyD + Hubsan + AFHDS2A
frsky_link_frame();
telemetry_link=0;
return;
}
#if defined HUB_TELEMETRY
if(!telemetry_link && protocol == MODE_FRSKYD)
{ // FrSky
frsky_user_frame();
return;
}
#endif
} }
@ -829,94 +524,139 @@ void TelemetryUpdate()
/**************************/ /**************************/
#ifndef BASH_SERIAL #ifndef BASH_SERIAL
// Routines for normal serial output // Routines for normal serial output
void Serial_write(uint8_t data) void Serial_write(uint8_t data)
{
uint8_t nextHead ;
nextHead = tx_head + 1 ;
if ( nextHead >= TXBUFFER_SIZE )
nextHead = 0 ;
tx_buff[nextHead]=data;
tx_head = nextHead ;
tx_resume();
}
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);
#endif
}
else if(speed==SPEED_57600)
{ // 57600
#ifdef XMEGA
/*USARTC0.BAUDCTRLA = 207 ;
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
USARTC0.CTRLC = 0x03 ;*/
#else
//57600 bauds
UBRR0H = 0x00;
UBRR0L = 0x22;
UCSR0A = 0x02 ; // Set X2 bit
//Set frame format to 8 data bits, none, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
#endif
}
else if(speed==SPEED_125K)
{ // 125000
#ifdef XMEGA
/*USARTC0.BAUDCTRLA = 207 ;
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
USARTC0.CTRLC = 0x03 ;*/
#else
//125000 bauds
UBRR0H = 0x00;
UBRR0L = 0x07;
UCSR0A = 0x00 ; // Clear X2 bit
//Set frame format to 8 data bits, none, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
#endif
}
#endif
#ifndef XMEGA
UCSR0B |= (1<<TXEN0);//tx enable
#endif
}
#ifdef XMEGA
ISR(USARTC0_DRE_vect)
#else
ISR(USART_UDRE_vect)
#endif
{ // Transmit interrupt
if(tx_head!=tx_tail)
{ {
if(++tx_tail>=TXBUFFER_SIZE)//head uint8_t nextHead ;
tx_tail=0; nextHead = tx_head + 1 ;
UDR0=tx_buff[tx_tail]; if ( nextHead >= TXBUFFER_SIZE )
nextHead = 0 ;
tx_buff[nextHead]=data;
tx_head = nextHead ;
tx_resume();
} }
if (tx_tail == tx_head)
tx_pause(); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt
}
void initTXSerial( uint8_t speed)
{
#ifdef ENABLE_PPM
if(speed==SPEED_9600)
{ // 9600
#ifdef ORANGE_TX
USARTC0.BAUDCTRLA = 207 ;
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
USARTC0.CTRLC = 0x03 ;
#else
#ifdef STM32_BOARD
usart3_begin(9600,SERIAL_8N1); //USART3
USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable RX leave TX enabled
#else
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
#endif
}
else if(speed==SPEED_57600)
{ // 57600
#ifdef ORANGE_TX
/*USARTC0.BAUDCTRLA = 207 ;
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
USARTC0.CTRLC = 0x03 ;*/
#else
#ifdef STM32_BOARD
usart3_begin(57600,SERIAL_8N1); //USART3
USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable RX leave TX enabled
#else
UBRR0H = 0x00;
UBRR0L = 0x22;
UCSR0A = 0x02 ; // Set X2 bit
//Set frame format to 8 data bits, none, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
#endif
#endif
}
else if(speed==SPEED_125K)
{ // 125000
#ifdef ORANGE_TX
/*USARTC0.BAUDCTRLA = 207 ;
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
USARTC0.CTRLC = 0x03 ;*/
#else
#ifdef STM32_BOARD
usart3_begin(125000,SERIAL_8N1); //USART3
USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable RX leave TX enabled
#else
UBRR0H = 0x00;
UBRR0L = 0x07;
UCSR0A = 0x00 ; // Clear X2 bit
//Set frame format to 8 data bits, none, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
#endif
#endif
}
#endif
#ifndef ORANGE_TX
#ifndef STM32_BOARD
UCSR0B |= (1<<TXEN0);//tx enable
#endif
#endif
}
//Serial TX
#ifdef ORANGE_TX
ISR(USARTC0_DRE_vect)
#else
#ifdef STM32_BOARD
void __irq_usart3()
#else
ISR(USART_UDRE_vect)
#endif
#endif
{ // Transmit interrupt
#ifdef STM32_BOARD
if(USART3_BASE->SR & USART_SR_TXE)
{
#endif
if(tx_head!=tx_tail)
{
if(++tx_tail>=TXBUFFER_SIZE)//head
tx_tail=0;
#ifdef STM32_BOARD
USART3_BASE->DR=tx_buff[tx_tail];//clears TXE bit
#else
UDR0=tx_buff[tx_tail];
#endif
}
if (tx_tail == tx_head)
tx_pause(); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt
#ifdef STM32_BOARD
}
#endif
}
#ifdef STM32_BOARD
void usart2_begin(uint32_t baud,uint32_t config )
{
usart_init(USART2);
usart_config_gpios_async(USART2,GPIOA,PIN_MAP[PA3].gpio_bit,GPIOA,PIN_MAP[PA2].gpio_bit,config);
usart_set_baud_rate(USART2, STM32_PCLK1, baud);//
usart_enable(USART2);
}
void usart3_begin(uint32_t baud,uint32_t config )
{
usart_init(USART3);
usart_config_gpios_async(USART3,GPIOB,PIN_MAP[PB11].gpio_bit,GPIOB,PIN_MAP[PB10].gpio_bit,config);
usart_set_baud_rate(USART3, STM32_PCLK1, baud);
usart_enable(USART3);
}
#endif
#else //BASH_SERIAL #else //BASH_SERIAL
// Routines for bit-bashed serial output // Routines for bit-bashed serial output
@ -1149,4 +889,3 @@ ISR(TIMER0_OVF_vect)
#endif // BASH_SERIAL #endif // BASH_SERIAL
#endif // TELEMETRY #endif // TELEMETRY
>>>>>>> refs/remotes/pascallanger/master

View File

@ -15,6 +15,8 @@
// compatible with WLToys V2x2, JXD JD38x, JD39x, JJRC H6C, Yizhan Tarantula X6 ... // compatible with WLToys V2x2, JXD JD38x, JD39x, JJRC H6C, Yizhan Tarantula X6 ...
// Last sync with hexfet new_protocols/v202_nrf24l01.c dated 2015-03-15 // Last sync with hexfet new_protocols/v202_nrf24l01.c dated 2015-03-15
// ajout jdx506 : https://github.com/DeviationTX/deviation/compare/master...goebish:protocol_jxd_506
#if defined(V2X2_NRF24L01_INO) #if defined(V2X2_NRF24L01_INO)
@ -40,7 +42,12 @@ enum {
// flags going to byte 10 // flags going to byte 10
V2X2_FLAG_HEADLESS = 0x02, V2X2_FLAG_HEADLESS = 0x02,
V2X2_FLAG_MAG_CAL_X = 0x08, V2X2_FLAG_MAG_CAL_X = 0x08,
V2X2_FLAG_MAG_CAL_Y = 0x20 V2X2_FLAG_MAG_CAL_Y = 0x20,
//
JXD_FLAG_START_STOP= 0x40, // arm / disarm JXD-506
JXD_FLAG_EMERGENCY = 0x80, // JXD-506
JXD_FLAG_CAMERA_UP = 0x01, // JXD-506
JXD_FLAG_CAMERA_DN = 0x02, // JXD-506
}; };
// //
@ -182,12 +189,26 @@ static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
// Channel 9 // Channel 9
if (Servo_AUX5) if (Servo_AUX5)
flags2 = V2X2_FLAG_HEADLESS; flags2 = V2X2_FLAG_HEADLESS;
// Channel 10
if (Servo_AUX6) if(sub_protocol == FORMAT_JXD506) {
flags2 |= V2X2_FLAG_MAG_CAL_X; // Channel 10
// Channel 11 if (Servo_AUX6) flags2 |= JXD_FLAG_START_STOP;
if (Servo_AUX7) // Channel 11
flags2 |= V2X2_FLAG_MAG_CAL_Y; if (Servo_AUX7) flags2 |= JXD_FLAG_EMERGENCY;
// Channel 12 down
if (Servo_data[AUX8] < PPM_SWITCH_B) flags2 |= JXD_FLAG_CAMERA_DN;
// Channel 12 up
if (Servo_data[AUX8] > PPM_SWITCH) flags2 |= JXD_FLAG_CAMERA_UP;
} else {
// Channel 10
if (Servo_AUX6)
flags2 |= V2X2_FLAG_MAG_CAL_X;
// Channel 11
if (Servo_AUX7)
flags2 |= V2X2_FLAG_MAG_CAL_Y;
}
} }
// TX id // TX id
packet[7] = rx_tx_addr[1]; packet[7] = rx_tx_addr[1];

101
Multiprotocol/Validate.h Normal file
View File

@ -0,0 +1,101 @@
// Check selected board type
#if defined (STM32_BOARD) && defined (ORANGE_TX)
#error You must comment the board type STM32_BOARD in _Config.h to compile ORANGE_TX
#endif
#if not defined (ORANGE_TX) && not defined (STM32_BOARD)
//Atmega328p
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO)
#error You must select one of these boards: "Multi 4-in-1", "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)"
#endif
#endif
#if defined (STM32_BOARD) && not defined (ORANGE_TX)
//STM32
#ifndef ARDUINO_GENERIC_STM32F103C
#error You must select the board type "Generic STM32F103C series"
#endif
#endif
//Change/Force configuration if OrangeTX
#ifdef ORANGE_TX
#undef ENABLE_PPM // Disable PPM for OrangeTX module
#undef A7105_INSTALLED // Disable A7105 for OrangeTX module
#undef CC2500_INSTALLED // Disable CC2500 for OrangeTX module
#undef NRF24L01_INSTALLED // Disable NRF for OrangeTX module
#define TELEMETRY // Enable telemetry
#define INVERT_TELEMETRY // Enable invert telemetry
#define DSM_TELEMETRY // Enable DSM telemetry
#endif
//Make sure protocols are selected correctly
#ifndef A7105_INSTALLED
#undef FLYSKY_A7105_INO
#undef HUBSAN_A7105_INO
#undef AFHDS2A_A7105_INO
#endif
#ifndef CYRF6936_INSTALLED
#undef DEVO_CYRF6936_INO
#undef DSM_CYRF6936_INO
#undef J6PRO_CYRF6936_INO
#endif
#ifndef CC2500_INSTALLED
#undef FRSKYD_CC2500_INO
#undef FRSKYV_CC2500_INO
#undef FRSKYX_CC2500_INO
#undef SFHSS_CC2500_INO
#endif
#ifndef NRF24L01_INSTALLED
#undef BAYANG_NRF24L01_INO
#undef CG023_NRF24L01_INO
#undef CX10_NRF24L01_INO
#undef ESKY_NRF24L01_INO
#undef HISKY_NRF24L01_INO
#undef KN_NRF24L01_INO
#undef SLT_NRF24L01_INO
#undef SYMAX_NRF24L01_INO
#undef V2X2_NRF24L01_INO
#undef YD717_NRF24L01_INO
#undef MT99XX_NRF24L01_INO
#undef MJXQ_NRF24L01_INO
#undef SHENQI_NRF24L01_INO
#undef FY326_NRF24L01_INO
#undef FQ777_NRF24L01_INO
#undef ASSAN_NRF24L01_INO
#undef HONTAI_NRF24L01_INO
#endif
//Make sure telemetry is selected correctly
#ifndef TELEMETRY
#undef INVERT_TELEMETRY
#undef DSM_TELEMETRY
#undef SPORT_TELEMETRY
#undef HUB_TELEMETRY
#undef AFHDS2A_TELEMETRY
#else
#if not defined(DSM_CYRF6936_INO)
#undef DSM_TELEMETRY
#endif
#if not defined(FRSKYD_CC2500_INO) && not defined(HUBSAN_A7105_INO) && not defined(AFHDS2A_A7105_INO)
#undef HUB_TELEMETRY
#endif
#if not defined(FRSKYX_CC2500_INO)
#undef SPORT_TELEMETRY
#endif
#if not defined(AFHDS2A_A7105_INO)
#undef AFHDS2A_TELEMETRY
#endif
#if not defined(DSM_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(AFHDS2A_TELEMETRY)
#undef TELEMETRY
#undef INVERT_TELEMETRY
#endif
#endif
//Make sure TX is defined correctly
#ifndef AILERON
#error You must select a correct channel order.
#endif
#if not defined(PPM_MAX_100) || not defined(PPM_MIN_100) || not defined(PPM_MAX_125) || not defined(PPM_MIN_125)
#error You must set correct TX end points.
#endif

View File

@ -34,16 +34,6 @@
#define YD717_PAYLOADSIZE 8 // receive data pipes set to this size, but unused #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) static void __attribute__((unused)) yd717_send_packet(uint8_t bind)
{ {
uint8_t rudder_trim, elevator_trim, aileron_trim; 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_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Set feature bits on
NRF24L01_Activate(0x73); 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 // for bind packets set address to prearranged value known to receiver
uint8_t bind_rx_tx_addr[] = {0x65, 0x65, 0x65, 0x65, 0x65}; uint8_t bind_rx_tx_addr[] = {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); 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() uint16_t yd717_callback()
{ {
if(IS_BIND_DONE_on) if(IS_BIND_DONE_on)

View File

@ -13,98 +13,32 @@
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. 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 ***/ /** Multiprotocol module configuration file ***/
/**********************************************/ /**********************************************/
/********************/
/*** BOARD TYPE ***/
/********************/
//Uncomment one of the line below if you have a different module not based on the original Multi Atmega328p design which includes the 4-in-1.
//If you don't know then leave them commented.
#ifdef __arm__
#define STM32_BOARD // Let's automatically select this board if arm is selected since this is the only one for now...
#endif
/*******************/ /*******************/
/*** TX SETTINGS ***/ /*** TX SETTINGS ***/
/*******************/ /*******************/
//Modify the channel order based on your TX: AETR, TAER, RETA... //Modify the channel order based on your TX: AETR, TAER, RETA...
//Examples: Flysky & DEVO is AETR, JR/Spektrum radio is TAER, Multiplex is AERT... //Examples: Flysky & DEVO is AETR, JR/Spektrum radio is TAER, Multiplex is AERT...
//Default is AETR. //Default is AETR.
#define AETR #define EATR
//Modify the channel for a software reset modul: AUX...(channel number - 4)
//Default is AUX10 (channel 14).
#define SWITCH_RESET 14
/**************************/ /**************************/
/*** RF CHIPS INSTALLED ***/ /*** RF CHIPS INSTALLED ***/
/**************************/ /**************************/
@ -112,53 +46,70 @@ const PPM_Parameters PPM_prot[15]= {
//If a chip is not installed all associated protocols are disabled. //If a chip is not installed all associated protocols are disabled.
//4-in-1 modules have all RF chips installed //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. //!!!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 A7105_INSTALLED
#define CYRF6936_INSTALLED #define CYRF6936_INSTALLED
#define CC2500_INSTALLED // #define CC2500_INSTALLED
#define NRF24L01_INSTALLED #define NRF24L01_INSTALLED
/****************************/ /****************************/
/*** PROTOCOLS TO INCLUDE ***/ /*** PROTOCOLS TO INCLUDE ***/
/****************************/ /****************************/
//In this section select the protocols you want to be accessible when using the module. //In this section select the protocols you want to be accessible when using the module.
//All the protocols will not fit in the module so you need to pick and choose. //All the protocols will not fit in the Atmega328p module so you need to pick and choose.
//Comment the protocols you are not using with "//" to save Flash space. //Comment the protocols you are not using with "//" to save Flash space.
//The protocols below need an A7105 to be installed //The protocols below need an A7105 to be installed
#define FLYSKY_A7105_INO #define JOYSWAY_A7105_INO
#define HUBSAN_A7105_INO
#define FLYSKY_A7105_INO
#define HUBSAN_A7105_INO
#define AFHDS2A_A7105_INO
//The protocols below need a CYRF6936 to be installed //The protocols below need a CYRF6936 to be installed
#define DEVO_CYRF6936_INO // #define WK2x01_CYRF6936_INO //!\\ //pb voie
#define DSM_CYRF6936_INO
#define J6PRO_CYRF6936_INO #define DEVO_CYRF6936_INO
#define DSM_CYRF6936_INO
// #define J6PRO_CYRF6936_INO
//The protocols below need a CC2500 to be installed //The protocols below need a CC2500 to be installed
#define FRSKYD_CC2500_INO #define SKYARTEC_CC2500_INO
#define FRSKYV_CC2500_INO
#define FRSKYX_CC2500_INO #define FRSKYD_CC2500_INO
#define SFHSS_CC2500_INO #define FRSKYV_CC2500_INO
#define FRSKYX_CC2500_INO
#define SFHSS_CC2500_INO
//The protocols below need a NRF24L01 to be installed //The protocols below need a NRF24L01 to be installed
#define BAYANG_NRF24L01_INO #define HM830_NRF24L01_INO
#define CG023_NRF24L01_INO // #define CFlie_NRF24L01_INO //!\\ //pb voie gaz
#define CX10_NRF24L01_INO // #define H377_NRF24L01_INO
#define ESKY_NRF24L01_INO // #define ESKY150_NRF24L01_INO
#define HISKY_NRF24L01_INO // #define HonTai_NRF24L01_INO
#define KN_NRF24L01_INO // #define UDI_NRF24L01_INO
#define SLT_NRF24L01_INO // #define NE260_NRF24L01_INO
#define SYMAX_NRF24L01_INO // #define BlueFly_NRF24L01_INO //probleme gene id
#define V2X2_NRF24L01_INO // #define FBL100_NRF24L01_INO // finir id //!\\ //pb voie ???
#define YD717_NRF24L01_INO // #define INAV_NRF24L01_INO // a faire
#define MT99XX_NRF24L01_INO #define Q303_NRF24L01_INO
#define MJXQ_NRF24L01_INO
#define SHENQI_NRF24L01_INO #define BAYANG_NRF24L01_INO
#define FY326_NRF24L01_INO #define CG023_NRF24L01_INO
#define FQ777_NRF24L01_INO #define CX10_NRF24L01_INO
#define ASSAN_NRF24L01_INO #define ESKY_NRF24L01_INO
#define HONTAI_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 ***/ /*** TELEMETRY SETTINGS ***/
@ -173,10 +124,10 @@ const PPM_Parameters PPM_prot[15]= {
//#define INVERT_TELEMETRY //#define INVERT_TELEMETRY
//Comment a line to disable a protocol telemetry //Comment a line to disable a protocol telemetry
#define DSM_TELEMETRY #define DSM_TELEMETRY
#define SPORT_TELEMETRY #define SPORT_TELEMETRY
#define HUB_TELEMETRY #define HUB_TELEMETRY
#define AFHDS2A_TELEMETRY
/****************************/ /****************************/
/*** SERIAL MODE SETTINGS ***/ /*** SERIAL MODE SETTINGS ***/
@ -200,17 +151,18 @@ const PPM_Parameters PPM_prot[15]= {
//It is important for the module to know the endpoints of your radio. //It is important for the module to know the endpoints of your radio.
//Below are some standard transmitters already preconfigured. //Below are some standard transmitters already preconfigured.
//Uncomment only the one which matches your transmitter. //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_DEVO7 //DEVO (1120<->1920µs) #define TX_TARANIS //TARANIS AETR (1100<->1900µs)
//#define TX_SPEKTRUM //Spektrum (1100<->1900µs) //#define TX_DEVO7 //DEVO (1120<->1920µs)
//#define TX_HISKY //HISKY (1100<->1900µs) //#define TX_SPEKTRUM //Spektrum (1100<->1900µs)
//#define TX_MPX //Multiplex MC2020 (1250<->1950µs) //#define TX_HISKY //HISKY (1100<->1900µs)
//#define TX_CUSTOM //Custom //#define TX_MPX //Multiplex MC2020 (1250<->1950µs)
//#define TX_CUSTOM //Custom
// The lines below are used to set the end points in microseconds (µs) if you have selected TX_CUSTOM. // The lines below are used to set the end points in microseconds (µs) if you have selected TX_CUSTOM.
// A few things to considered: // A few things to consider:
// - If you put too big values compared to your TX you won't be able to reach the extremes which is bad for throttle as an example // - If you put too big values compared to your TX you won't be able to reach the extremes which is bad for throttle as an example
// - If you put too low values you won't be able to use your full stick range, it will be maxed out before reaching the end // - If you put too low values you won't be able to use your full stick range, it will be maxed out before reaching the ends
// - Centered stick value is usually 1500. It should match the middle between MIN and MAX, ie Center=(MAX-MIN)/2+MIN. If your TX is not centered you can adjust the value MIN or MAX. // - Centered stick value is usually 1500. It should match the middle between MIN and MAX, ie Center=(MAX-MIN)/2+MIN. If your TX is not centered you can adjust the value MIN or MAX.
// - 100% is the value when the model is by default, 125% is the value when you extend the servo travel which is only used by some protocols // - 100% is the value when the model is by default, 125% is the value when you extend the servo travel which is only used by some protocols
#if defined(TX_CUSTOM) #if defined(TX_CUSTOM)
@ -225,7 +177,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) //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]= { const PPM_Parameters PPM_prot[15]= {
// Dial Protocol Sub protocol RX_Num Power Auto Bind Option // 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 }, /* 2 */ {MODE_HUBSAN, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 3 */ {MODE_FRSKYD, 0 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning /* 3 */ {MODE_FRSKYD, 0 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 }, /* 4 */ {MODE_HISKY , Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
@ -234,7 +186,6 @@ const PPM_Parameters PPM_prot[15]= {
/* 7 */ {MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, /* 7 */ {MODE_DEVO , 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 8 */ {MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 }, /* 8 */ {MODE_YD717 , YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 9 */ {MODE_KN , WLTOYS , 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 }, /* 10 */ {MODE_SYMAX , SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 11 */ {MODE_SLT , 0 , 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 }, /* 12 */ {MODE_CX10 , CX10_BLUE , 0 , P_HIGH , NO_AUTOBIND , 0 },
@ -242,11 +193,7 @@ const PPM_Parameters PPM_prot[15]= {
/* 14 */ {MODE_BAYANG, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 }, /* 14 */ {MODE_BAYANG, 0 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 15 */ {MODE_SYMAX , SYMAX5C , 0 , P_HIGH , NO_AUTOBIND , 0 } /* 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 /* Available protocols and associated sub protocols to pick and choose from
>>>>>>> refs/remotes/pascallanger/master
MODE_FLYSKY MODE_FLYSKY
Flysky Flysky
V9X9 V9X9
@ -254,28 +201,18 @@ const PPM_Parameters PPM_prot[15]= {
V912 V912
MODE_HUBSAN MODE_HUBSAN
NONE NONE
<<<<<<< HEAD
MODE_FRSKY
=======
MODE_FRSKYD MODE_FRSKYD
>>>>>>> refs/remotes/pascallanger/master
NONE NONE
MODE_HISKY MODE_HISKY
Hisky Hisky
HK310 HK310
MODE_V2X2 MODE_V2X2
NONE NONE
<<<<<<< HEAD
MODE_DSM2
DSM2
DSMX
=======
MODE_DSM MODE_DSM
DSM2_22 DSM2_22
DSM2_11 DSM2_11
DSMX_22 DSMX_22
DSMX_11 DSMX_11
>>>>>>> refs/remotes/pascallanger/master
MODE_DEVO MODE_DEVO
NONE NONE
MODE_YD717 MODE_YD717
@ -308,142 +245,26 @@ const PPM_Parameters PPM_prot[15]= {
MODE_BAYANG MODE_BAYANG
NONE NONE
MODE_FRSKYX MODE_FRSKYX
<<<<<<< HEAD
NONE
=======
CH_16 CH_16
CH_8 CH_8
>>>>>>> refs/remotes/pascallanger/master
MODE_ESKY MODE_ESKY
NONE NONE
MODE_MT99XX MODE_MT99XX
MT99 MT99
H7 H7
YZ YZ
<<<<<<< HEAD
=======
LS LS
>>>>>>> refs/remotes/pascallanger/master
MODE_MJXQ MODE_MJXQ
WLH08 WLH08
X600 X600
X800 X800
H26D H26D
<<<<<<< HEAD E010
MODE_SHENQI MODE_SHENQI
NONE NONE
MODE_FY326 MODE_FY326
FY326 FY326
FY319 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 MODE_SFHSS
NONE NONE
MODE_J6PRO MODE_J6PRO
@ -458,6 +279,9 @@ enum chan_orders{
FORMAT_HONTAI FORMAT_HONTAI
FORMAT_JJRCX1 FORMAT_JJRCX1
FORMAT_X5C1 FORMAT_X5C1
FQ777-951
MODE_AFHDS2A
NONE
*/ */
// 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... // 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...
@ -468,8 +292,7 @@ enum chan_orders{
// Auto Bind AUTOBIND or NO_AUTOBIND // Auto Bind AUTOBIND or NO_AUTOBIND
// For protocols which does not require binding at each power up (like Flysky, FrSky...), you might still want a bind to be initiated each time you power up the TX. // For protocols which does not require binding at each power up (like Flysky, FrSky...), you might still want a bind to be initiated each time you power up the TX.
// As an exxample, it's usefull for the WLTOYS F929/F939/F949/F959 (all using the Flysky protocol) which requires a bind at each power up. // As an example, it's usefull for the WLTOYS F929/F939/F949/F959 (all using the Flysky protocol) which requires a bind at each power up.
// Option: the value is between -127 and +127. // 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 // 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

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

890
Multiprotocol/boards.txt Normal file
View File

@ -0,0 +1,890 @@
# See: http://code.google.com/p/arduino/wiki/Platforms
menu.cpu=Processor
##############################################################
yun.name=Arduino Yún
yun.upload.via_ssh=true
yun.vid.0=0x2341
yun.pid.0=0x0041
yun.vid.1=0x2341
yun.pid.1=0x8041
yun.vid.2=0x2A03
yun.pid.2=0x0041
yun.vid.3=0x2A03
yun.pid.3=0x8041
yun.upload.tool=avrdude
yun.upload.protocol=avr109
yun.upload.maximum_size=28672
yun.upload.maximum_data_size=2560
yun.upload.speed=57600
yun.upload.disable_flushing=true
yun.upload.use_1200bps_touch=true
yun.upload.wait_for_upload_port=true
yun.bootloader.tool=avrdude
yun.bootloader.low_fuses=0xff
yun.bootloader.high_fuses=0xd8
yun.bootloader.extended_fuses=0xfb
yun.bootloader.file=caterina/Caterina-Yun.hex
yun.bootloader.unlock_bits=0x3F
yun.bootloader.lock_bits=0x2F
yun.build.mcu=atmega32u4
yun.build.f_cpu=16000000L
yun.build.vid=0x2341
yun.build.pid=0x8041
yun.build.usb_product="Arduino Yun"
yun.build.board=AVR_YUN
yun.build.core=arduino
yun.build.variant=yun
yun.build.extra_flags={build.usb_flags}
##############################################################
uno.name=Arduino/Genuino Uno
uno.vid.0=0x2341
uno.pid.0=0x0043
uno.vid.1=0x2341
uno.pid.1=0x0001
uno.vid.2=0x2A03
uno.pid.2=0x0043
uno.vid.3=0x2341
uno.pid.3=0x0243
uno.upload.tool=avrdude
uno.upload.protocol=arduino
uno.upload.maximum_size=32256
uno.upload.maximum_data_size=2048
uno.upload.speed=115200
uno.bootloader.tool=avrdude
uno.bootloader.low_fuses=0xFF
uno.bootloader.high_fuses=0xDE
uno.bootloader.extended_fuses=0x05
uno.bootloader.unlock_bits=0x3F
uno.bootloader.lock_bits=0x0F
uno.bootloader.file=optiboot/optiboot_atmega328.hex
uno.build.mcu=atmega328p
uno.build.f_cpu=16000000L
uno.build.board=AVR_UNO
uno.build.core=arduino
uno.build.variant=standard
##############################################################
diecimila.name=Arduino Duemilanove or Diecimila
diecimila.upload.tool=avrdude
diecimila.upload.protocol=arduino
diecimila.bootloader.tool=avrdude
diecimila.bootloader.low_fuses=0xFF
diecimila.bootloader.unlock_bits=0x3F
diecimila.bootloader.lock_bits=0x0F
diecimila.build.f_cpu=16000000L
diecimila.build.board=AVR_DUEMILANOVE
diecimila.build.core=arduino
diecimila.build.variant=standard
## Arduino Duemilanove or Diecimila w/ ATmega328
## ---------------------------------------------
diecimila.menu.cpu.atmega328=ATmega328
diecimila.menu.cpu.atmega328.upload.maximum_size=30720
diecimila.menu.cpu.atmega328.upload.maximum_data_size=2048
diecimila.menu.cpu.atmega328.upload.speed=57600
diecimila.menu.cpu.atmega328.bootloader.high_fuses=0xDA
diecimila.menu.cpu.atmega328.bootloader.extended_fuses=0x05
diecimila.menu.cpu.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
diecimila.menu.cpu.atmega328.build.mcu=atmega328p
## Arduino Duemilanove or Diecimila w/ ATmega168
## ---------------------------------------------
diecimila.menu.cpu.atmega168=ATmega168
diecimila.menu.cpu.atmega168.upload.maximum_size=14336
diecimila.menu.cpu.atmega168.upload.maximum_data_size=1024
diecimila.menu.cpu.atmega168.upload.speed=19200
diecimila.menu.cpu.atmega168.bootloader.high_fuses=0xdd
diecimila.menu.cpu.atmega168.bootloader.extended_fuses=0x00
diecimila.menu.cpu.atmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex
diecimila.menu.cpu.atmega168.build.mcu=atmega168
##############################################################
nano.name=Arduino Nano
nano.upload.tool=avrdude
nano.upload.protocol=arduino
nano.bootloader.tool=avrdude
nano.bootloader.unlock_bits=0x3F
nano.bootloader.lock_bits=0x0F
nano.build.f_cpu=16000000L
nano.build.board=AVR_NANO
nano.build.core=arduino
nano.build.variant=eightanaloginputs
## Arduino Nano w/ ATmega328
## -------------------------
nano.menu.cpu.atmega328=ATmega328
nano.menu.cpu.atmega328.upload.maximum_size=30720
nano.menu.cpu.atmega328.upload.maximum_data_size=2048
nano.menu.cpu.atmega328.upload.speed=57600
nano.menu.cpu.atmega328.bootloader.low_fuses=0xFF
nano.menu.cpu.atmega328.bootloader.high_fuses=0xDA
nano.menu.cpu.atmega328.bootloader.extended_fuses=0x05
nano.menu.cpu.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
nano.menu.cpu.atmega328.build.mcu=atmega328p
## Arduino Nano w/ ATmega168
## -------------------------
nano.menu.cpu.atmega168=ATmega168
nano.menu.cpu.atmega168.upload.maximum_size=14336
nano.menu.cpu.atmega168.upload.maximum_data_size=1024
nano.menu.cpu.atmega168.upload.speed=19200
nano.menu.cpu.atmega168.bootloader.low_fuses=0xff
nano.menu.cpu.atmega168.bootloader.high_fuses=0xdd
nano.menu.cpu.atmega168.bootloader.extended_fuses=0x00
nano.menu.cpu.atmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex
nano.menu.cpu.atmega168.build.mcu=atmega168
##############################################################
mega.name=Arduino/Genuino Mega or Mega 2560
mega.vid.0=0x2341
mega.pid.0=0x0010
mega.vid.1=0x2341
mega.pid.1=0x0042
mega.vid.2=0x2A03
mega.pid.2=0x0010
mega.vid.3=0x2A03
mega.pid.3=0x0042
mega.vid.4=0x2341
mega.pid.4=0x0210
mega.vid.5=0x2341
mega.pid.5=0x0242
mega.upload.tool=avrdude
mega.upload.maximum_data_size=8192
mega.bootloader.tool=avrdude
mega.bootloader.low_fuses=0xFF
mega.bootloader.unlock_bits=0x3F
mega.bootloader.lock_bits=0x0F
mega.build.f_cpu=16000000L
mega.build.core=arduino
mega.build.variant=mega
# default board may be overridden by the cpu menu
mega.build.board=AVR_MEGA2560
## Arduino/Genuino Mega w/ ATmega2560
## -------------------------
mega.menu.cpu.atmega2560=ATmega2560 (Mega 2560)
mega.menu.cpu.atmega2560.upload.protocol=wiring
mega.menu.cpu.atmega2560.upload.maximum_size=253952
mega.menu.cpu.atmega2560.upload.speed=115200
mega.menu.cpu.atmega2560.bootloader.high_fuses=0xD8
mega.menu.cpu.atmega2560.bootloader.extended_fuses=0xFD
mega.menu.cpu.atmega2560.bootloader.file=stk500v2/stk500boot_v2_mega2560.hex
mega.menu.cpu.atmega2560.build.mcu=atmega2560
mega.menu.cpu.atmega2560.build.board=AVR_MEGA2560
## Arduino Mega w/ ATmega1280
## -------------------------
mega.menu.cpu.atmega1280=ATmega1280
mega.menu.cpu.atmega1280.upload.protocol=arduino
mega.menu.cpu.atmega1280.upload.maximum_size=126976
mega.menu.cpu.atmega1280.upload.speed=57600
mega.menu.cpu.atmega1280.bootloader.high_fuses=0xDA
mega.menu.cpu.atmega1280.bootloader.extended_fuses=0xF5
mega.menu.cpu.atmega1280.bootloader.file=atmega/ATmegaBOOT_168_atmega1280.hex
mega.menu.cpu.atmega1280.build.mcu=atmega1280
mega.menu.cpu.atmega1280.build.board=AVR_MEGA
##############################################################
megaADK.name=Arduino Mega ADK
megaADK.vid.0=0x2341
megaADK.pid.0=0x003f
megaADK.vid.1=0x2341
megaADK.pid.1=0x0044
megaADK.vid.2=0x2A03
megaADK.pid.2=0x003f
megaADK.vid.3=0x2A03
megaADK.pid.3=0x0044
megaADK.upload.tool=avrdude
megaADK.upload.protocol=wiring
megaADK.upload.maximum_size=253952
megaADK.upload.maximum_data_size=8192
megaADK.upload.speed=115200
megaADK.bootloader.tool=avrdude
megaADK.bootloader.low_fuses=0xFF
megaADK.bootloader.high_fuses=0xD8
megaADK.bootloader.extended_fuses=0xFD
megaADK.bootloader.file=stk500v2/stk500boot_v2_mega2560.hex
megaADK.bootloader.unlock_bits=0x3F
megaADK.bootloader.lock_bits=0x0F
megaADK.build.mcu=atmega2560
megaADK.build.f_cpu=16000000L
megaADK.build.board=AVR_ADK
megaADK.build.core=arduino
megaADK.build.variant=mega
##############################################################
leonardo.name=Arduino Leonardo
leonardo.vid.0=0x2341
leonardo.pid.0=0x0036
leonardo.vid.1=0x2341
leonardo.pid.1=0x8036
leonardo.vid.2=0x2A03
leonardo.pid.2=0x0036
leonardo.vid.3=0x2A03
leonardo.pid.3=0x8036
leonardo.upload.tool=avrdude
leonardo.upload.protocol=avr109
leonardo.upload.maximum_size=28672
leonardo.upload.maximum_data_size=2560
leonardo.upload.speed=57600
leonardo.upload.disable_flushing=true
leonardo.upload.use_1200bps_touch=true
leonardo.upload.wait_for_upload_port=true
leonardo.bootloader.tool=avrdude
leonardo.bootloader.low_fuses=0xff
leonardo.bootloader.high_fuses=0xd8
leonardo.bootloader.extended_fuses=0xcb
leonardo.bootloader.file=caterina/Caterina-Leonardo.hex
leonardo.bootloader.unlock_bits=0x3F
leonardo.bootloader.lock_bits=0x2F
leonardo.build.mcu=atmega32u4
leonardo.build.f_cpu=16000000L
leonardo.build.vid=0x2341
leonardo.build.pid=0x8036
leonardo.build.usb_product="Arduino Leonardo"
leonardo.build.board=AVR_LEONARDO
leonardo.build.core=arduino
leonardo.build.variant=leonardo
leonardo.build.extra_flags={build.usb_flags}
##############################################################
micro.name=Arduino/Genuino Micro
micro.vid.0=0x2341
micro.pid.0=0x0037
micro.vid.1=0x2341
micro.pid.1=0x8037
micro.vid.2=0x2A03
micro.pid.2=0x0037
micro.vid.3=0x2A03
micro.pid.3=0x8037
micro.vid.4=0x2341
micro.pid.4=0x0237
# If the board is a 2341:0237 use 2341:8237 for build and set
# other parameters as well
micro.vid.4.build.vid=0x2341
micro.vid.4.build.pid=0x8237
micro.vid.4.build.usb_product="Genuino Micro"
micro.vid.4.bootloader.file=caterina/Caterina-Genuino-Micro.hex
micro.vid.5=0x2341
micro.pid.5=0x8237
# If the board is a 2341:8237 use 2341:8237 for build and set
# other paramters as well
micro.vid.5.build.vid=0x2341
micro.vid.5.build.pid=0x8237
micro.vid.5.build.usb_product="Genuino Micro"
micro.vid.5.bootloader.file=caterina/Caterina-Genuino-Micro.hex
micro.upload.tool=avrdude
micro.upload.protocol=avr109
micro.upload.maximum_size=28672
micro.upload.maximum_data_size=2560
micro.upload.speed=57600
micro.upload.disable_flushing=true
micro.upload.use_1200bps_touch=true
micro.upload.wait_for_upload_port=true
micro.bootloader.tool=avrdude
micro.bootloader.low_fuses=0xff
micro.bootloader.high_fuses=0xd8
micro.bootloader.extended_fuses=0xcb
micro.bootloader.file=caterina/Caterina-Micro.hex
micro.bootloader.unlock_bits=0x3F
micro.bootloader.lock_bits=0x2F
micro.build.mcu=atmega32u4
micro.build.f_cpu=16000000L
micro.build.vid=0x2341
micro.build.pid=0x8037
micro.build.usb_product="Arduino Micro"
micro.build.board=AVR_MICRO
micro.build.core=arduino
micro.build.variant=micro
micro.build.extra_flags={build.usb_flags}
##############################################################
esplora.name=Arduino Esplora
esplora.vid.0=0x2341
esplora.pid.0=0x003C
esplora.vid.1=0x2341
esplora.pid.1=0x803C
esplora.vid.2=0x2A03
esplora.pid.2=0x003C
esplora.vid.3=0x2A03
esplora.pid.3=0x803C
esplora.upload.tool=avrdude
esplora.upload.protocol=avr109
esplora.upload.maximum_size=28672
esplora.upload.maximum_data_size=2560
esplora.upload.speed=57600
esplora.upload.disable_flushing=true
esplora.upload.use_1200bps_touch=true
esplora.upload.wait_for_upload_port=true
esplora.bootloader.tool=avrdude
esplora.bootloader.low_fuses=0xff
esplora.bootloader.high_fuses=0xd8
esplora.bootloader.extended_fuses=0xcb
esplora.bootloader.file=caterina/Caterina-Esplora.hex
esplora.bootloader.unlock_bits=0x3F
esplora.bootloader.lock_bits=0x2F
esplora.build.mcu=atmega32u4
esplora.build.f_cpu=16000000L
esplora.build.vid=0x2341
esplora.build.pid=0x803c
esplora.build.usb_product="Arduino Esplora"
esplora.build.board=AVR_ESPLORA
esplora.build.core=arduino
esplora.build.variant=leonardo
esplora.build.extra_flags={build.usb_flags}
##############################################################
mini.name=Arduino Mini
mini.upload.tool=avrdude
mini.upload.protocol=arduino
mini.bootloader.tool=avrdude
mini.bootloader.low_fuses=0xff
mini.bootloader.unlock_bits=0x3F
mini.bootloader.lock_bits=0x0F
mini.build.f_cpu=16000000L
mini.build.board=AVR_MINI
mini.build.core=arduino
mini.build.variant=eightanaloginputs
## Arduino Mini w/ ATmega328
## -------------------------
mini.menu.cpu.atmega328=ATmega328
mini.menu.cpu.atmega328.upload.maximum_size=28672
mini.menu.cpu.atmega328.upload.maximum_data_size=2048
mini.menu.cpu.atmega328.upload.speed=115200
mini.menu.cpu.atmega328.bootloader.high_fuses=0xd8
mini.menu.cpu.atmega328.bootloader.extended_fuses=0x05
mini.menu.cpu.atmega328.bootloader.file=optiboot/optiboot_atmega328-Mini.hex
mini.menu.cpu.atmega328.build.mcu=atmega328p
## Arduino Mini w/ ATmega168
## -------------------------
mini.menu.cpu.atmega168=ATmega168
mini.menu.cpu.atmega168.upload.maximum_size=14336
mini.menu.cpu.atmega168.upload.maximum_data_size=1024
mini.menu.cpu.atmega168.upload.speed=19200
mini.menu.cpu.atmega168.bootloader.high_fuses=0xdd
mini.menu.cpu.atmega168.bootloader.extended_fuses=0x00
mini.menu.cpu.atmega168.bootloader.file=atmega/ATmegaBOOT_168_ng.hex
mini.menu.cpu.atmega168.build.mcu=atmega168
##############################################################
ethernet.name=Arduino Ethernet
ethernet.upload.tool=avrdude
ethernet.upload.protocol=arduino
ethernet.upload.maximum_size=32256
ethernet.upload.maximum_data_size=2048
ethernet.upload.speed=115200
ethernet.bootloader.tool=avrdude
ethernet.bootloader.low_fuses=0xff
ethernet.bootloader.high_fuses=0xde
ethernet.bootloader.extended_fuses=0x05
ethernet.bootloader.file=optiboot/optiboot_atmega328.hex
ethernet.bootloader.unlock_bits=0x3F
ethernet.bootloader.lock_bits=0x0F
ethernet.build.variant=ethernet
ethernet.build.mcu=atmega328p
ethernet.build.f_cpu=16000000L
ethernet.build.board=AVR_ETHERNET
ethernet.build.core=arduino
##############################################################
fio.name=Arduino Fio
fio.upload.tool=avrdude
fio.upload.protocol=arduino
fio.upload.maximum_size=30720
fio.upload.maximum_data_size=2048
fio.upload.speed=57600
fio.bootloader.tool=avrdude
fio.bootloader.low_fuses=0xFF
fio.bootloader.high_fuses=0xDA
fio.bootloader.extended_fuses=0x05
fio.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex
fio.bootloader.unlock_bits=0x3F
fio.bootloader.lock_bits=0x0F
fio.build.mcu=atmega328p
fio.build.f_cpu=8000000L
fio.build.board=AVR_FIO
fio.build.core=arduino
fio.build.variant=eightanaloginputs
##############################################################
bt.name=Arduino BT
bt.upload.tool=avrdude
bt.upload.protocol=arduino
bt.upload.speed=19200
bt.upload.disable_flushing=true
bt.bootloader.tool=avrdude
bt.bootloader.low_fuses=0xff
bt.bootloader.unlock_bits=0x3F
bt.bootloader.lock_bits=0x0F
bt.build.f_cpu=16000000L
bt.build.board=AVR_BT
bt.build.core=arduino
bt.build.variant=eightanaloginputs
## Arduino BT w/ ATmega328
## -----------------------
bt.menu.cpu.atmega328=ATmega328
bt.menu.cpu.atmega328.upload.maximum_size=28672
bt.menu.cpu.atmega328.upload.maximum_data_size=2048
bt.menu.cpu.atmega328.bootloader.high_fuses=0xd8
bt.menu.cpu.atmega328.bootloader.extended_fuses=0x05
bt.menu.cpu.atmega328.bootloader.file=bt/ATmegaBOOT_168_atmega328_bt.hex
bt.menu.cpu.atmega328.build.mcu=atmega328p
## Arduino BT w/ ATmega168
## -----------------------
bt.menu.cpu.atmega168=ATmega168
bt.menu.cpu.atmega168.upload.maximum_size=14336
bt.menu.cpu.atmega168.upload.maximum_data_size=1024
bt.menu.cpu.atmega168.bootloader.high_fuses=0xdd
bt.menu.cpu.atmega168.bootloader.extended_fuses=0x00
bt.menu.cpu.atmega168.bootloader.file=bt/ATmegaBOOT_168.hex
bt.menu.cpu.atmega168.build.mcu=atmega168
##############################################################
LilyPadUSB.name=LilyPad Arduino USB
LilyPadUSB.vid.0=0x1B4F
LilyPadUSB.pid.0=0x9207
LilyPadUSB.vid.1=0x1B4F
LilyPadUSB.pid.1=0x9208
LilyPadUSB.upload.tool=avrdude
LilyPadUSB.upload.protocol=avr109
LilyPadUSB.upload.maximum_size=28672
LilyPadUSB.upload.maximum_data_size=2560
LilyPadUSB.upload.speed=57600
LilyPadUSB.upload.disable_flushing=true
LilyPadUSB.upload.use_1200bps_touch=true
LilyPadUSB.upload.wait_for_upload_port=true
LilyPadUSB.bootloader.tool=avrdude
LilyPadUSB.bootloader.low_fuses=0xff
LilyPadUSB.bootloader.high_fuses=0xd8
LilyPadUSB.bootloader.extended_fuses=0xce
LilyPadUSB.bootloader.file=caterina-LilyPadUSB/Caterina-LilyPadUSB.hex
LilyPadUSB.bootloader.unlock_bits=0x3F
LilyPadUSB.bootloader.lock_bits=0x2F
LilyPadUSB.build.mcu=atmega32u4
LilyPadUSB.build.f_cpu=8000000L
LilyPadUSB.build.vid=0x1B4F
LilyPadUSB.build.pid=0x9208
LilyPadUSB.build.usb_product="LilyPad USB"
LilyPadUSB.build.board=AVR_LILYPAD_USB
LilyPadUSB.build.core=arduino
LilyPadUSB.build.variant=leonardo
LilyPadUSB.build.extra_flags={build.usb_flags}
##############################################################
lilypad.name=LilyPad Arduino
lilypad.upload.tool=avrdude
lilypad.upload.protocol=arduino
lilypad.bootloader.tool=avrdude
lilypad.bootloader.unlock_bits=0x3F
lilypad.bootloader.lock_bits=0x0F
lilypad.build.f_cpu=8000000L
lilypad.build.board=AVR_LILYPAD
lilypad.build.core=arduino
lilypad.build.variant=standard
## LilyPad Arduino w/ ATmega328
## ----------------------------
lilypad.menu.cpu.atmega328=ATmega328
lilypad.menu.cpu.atmega328.upload.maximum_size=30720
lilypad.menu.cpu.atmega328.upload.maximum_data_size=2048
lilypad.menu.cpu.atmega328.upload.speed=57600
lilypad.menu.cpu.atmega328.bootloader.low_fuses=0xFF
lilypad.menu.cpu.atmega328.bootloader.high_fuses=0xDA
lilypad.menu.cpu.atmega328.bootloader.extended_fuses=0x05
lilypad.menu.cpu.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex
lilypad.menu.cpu.atmega328.build.mcu=atmega328p
## LilyPad Arduino w/ ATmega168
## ----------------------------
lilypad.menu.cpu.atmega168=ATmega168
lilypad.menu.cpu.atmega168.upload.maximum_size=14336
lilypad.menu.cpu.atmega168.upload.maximum_data_size=1024
lilypad.menu.cpu.atmega168.upload.speed=19200
lilypad.menu.cpu.atmega168.bootloader.low_fuses=0xe2
lilypad.menu.cpu.atmega168.bootloader.high_fuses=0xdd
lilypad.menu.cpu.atmega168.bootloader.extended_fuses=0x00
lilypad.menu.cpu.atmega168.bootloader.file=lilypad/LilyPadBOOT_168.hex
lilypad.menu.cpu.atmega168.build.mcu=atmega168
##############################################################
pro.name=Arduino Pro or Pro Mini
pro.upload.tool=avrdude
pro.upload.protocol=arduino
pro.bootloader.tool=avrdude
pro.bootloader.unlock_bits=0x3F
pro.bootloader.lock_bits=0x0F
pro.build.board=AVR_PRO
pro.build.core=arduino
pro.build.variant=eightanaloginputs
## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328
## -------------------------------------------------
pro.menu.cpu.16MHzatmega328=ATmega328 (5V, 16 MHz)
pro.menu.cpu.16MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.16MHzatmega328.upload.speed=57600
pro.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0x05
pro.menu.cpu.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
pro.menu.cpu.16MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.16MHzatmega328.build.f_cpu=16000000L
## Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328
## --------------------------------------------------
pro.menu.cpu.8MHzatmega328=ATmega328 (3.3V, 8 MHz)
pro.menu.cpu.8MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.8MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.8MHzatmega328.upload.speed=57600
pro.menu.cpu.8MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.8MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.8MHzatmega328.bootloader.extended_fuses=0x05
pro.menu.cpu.8MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex
pro.menu.cpu.8MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.8MHzatmega328.build.f_cpu=8000000L
## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega168
## -------------------------------------------------
pro.menu.cpu.16MHzatmega168=ATmega168 (5V, 16 MHz)
pro.menu.cpu.16MHzatmega168.upload.maximum_size=14336
pro.menu.cpu.16MHzatmega168.upload.maximum_data_size=1024
pro.menu.cpu.16MHzatmega168.upload.speed=19200
pro.menu.cpu.16MHzatmega168.bootloader.low_fuses=0xff
pro.menu.cpu.16MHzatmega168.bootloader.high_fuses=0xdd
pro.menu.cpu.16MHzatmega168.bootloader.extended_fuses=0x00
pro.menu.cpu.16MHzatmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex
pro.menu.cpu.16MHzatmega168.build.mcu=atmega168
pro.menu.cpu.16MHzatmega168.build.f_cpu=16000000L
## Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega168
## --------------------------------------------------
pro.menu.cpu.8MHzatmega168=ATmega168 (3.3V, 8 MHz)
pro.menu.cpu.8MHzatmega168.upload.maximum_size=14336
pro.menu.cpu.8MHzatmega168.upload.maximum_data_size=1024
pro.menu.cpu.8MHzatmega168.upload.speed=19200
pro.menu.cpu.8MHzatmega168.bootloader.low_fuses=0xc6
pro.menu.cpu.8MHzatmega168.bootloader.high_fuses=0xdd
pro.menu.cpu.8MHzatmega168.bootloader.extended_fuses=0x00
pro.menu.cpu.8MHzatmega168.bootloader.file=atmega/ATmegaBOOT_168_pro_8MHz.hex
pro.menu.cpu.8MHzatmega168.build.mcu=atmega168
pro.menu.cpu.8MHzatmega168.build.f_cpu=8000000L
##############################################################
atmegang.name=Arduino NG or older
atmegang.upload.tool=avrdude
atmegang.upload.protocol=arduino
atmegang.upload.speed=19200
atmegang.bootloader.tool=avrdude
atmegang.bootloader.unlock_bits=0x3F
atmegang.bootloader.lock_bits=0x0F
atmegang.build.mcu=atmegang
atmegang.build.f_cpu=16000000L
atmegang.build.board=AVR_NG
atmegang.build.core=arduino
atmegang.build.variant=standard
## Arduino NG or older w/ ATmega168
## --------------------------------
atmegang.menu.cpu.atmega168=ATmega168
atmegang.menu.cpu.atmega168.upload.maximum_size=14336
atmegang.menu.cpu.atmega168.upload.maximum_data_size=1024
atmegang.menu.cpu.atmega168.bootloader.low_fuses=0xff
atmegang.menu.cpu.atmega168.bootloader.high_fuses=0xdd
atmegang.menu.cpu.atmega168.bootloader.extended_fuses=0x00
atmegang.menu.cpu.atmega168.bootloader.file=atmega/ATmegaBOOT_168_ng.hex
atmegang.menu.cpu.atmega168.build.mcu=atmega168
## Arduino NG or older w/ ATmega8
## ------------------------------
atmegang.menu.cpu.atmega8=ATmega8
atmegang.menu.cpu.atmega8.upload.maximum_size=7168
atmegang.menu.cpu.atmega8.upload.maximum_data_size=1024
atmegang.menu.cpu.atmega8.bootloader.low_fuses=0xdf
atmegang.menu.cpu.atmega8.bootloader.high_fuses=0xca
atmegang.menu.cpu.atmega8.bootloader.file=atmega8/ATmegaBOOT-prod-firmware-2009-11-07.hex
atmegang.menu.cpu.atmega8.build.mcu=atmega8
##############################################################
robotControl.name=Arduino Robot Control
robotControl.vid.0=0x2341
robotControl.pid.0=0x0038
robotControl.vid.1=0x2341
robotControl.pid.1=0x8038
robotControl.vid.2=0x2A03
robotControl.pid.2=0x0038
robotControl.vid.3=0x2A03
robotControl.pid.3=0x8038
robotControl.upload.tool=avrdude
robotControl.upload.protocol=avr109
robotControl.upload.maximum_size=28672
robotControl.upload.maximum_data_size=2560
robotControl.upload.speed=57600
robotControl.upload.disable_flushing=true
robotControl.upload.use_1200bps_touch=true
robotControl.upload.wait_for_upload_port=true
robotControl.bootloader.tool=avrdude
robotControl.bootloader.low_fuses=0xff
robotControl.bootloader.high_fuses=0xd8
robotControl.bootloader.extended_fuses=0xcb
robotControl.bootloader.file=caterina-Arduino_Robot/Caterina-Robot-Control.hex
robotControl.bootloader.unlock_bits=0x3F
robotControl.bootloader.lock_bits=0x2F
robotControl.build.mcu=atmega32u4
robotControl.build.f_cpu=16000000L
robotControl.build.vid=0x2341
robotControl.build.pid=0x8038
robotControl.build.usb_product="Robot Control"
robotControl.build.board=AVR_ROBOT_CONTROL
robotControl.build.core=arduino
robotControl.build.variant=robot_control
robotControl.build.extra_flags={build.usb_flags}
##############################################################
robotMotor.name=Arduino Robot Motor
robotMotor.vid.0=0x2341
robotMotor.pid.0=0x0039
robotMotor.vid.1=0x2341
robotMotor.pid.1=0x8039
robotMotor.vid.2=0x2A03
robotMotor.pid.2=0x0039
robotMotor.vid.3=0x2A03
robotMotor.pid.3=0x8039
robotMotor.upload.tool=avrdude
robotMotor.upload.protocol=avr109
robotMotor.upload.maximum_size=28672
robotMotor.upload.maximum_data_size=2560
robotMotor.upload.speed=57600
robotMotor.upload.disable_flushing=true
robotMotor.upload.use_1200bps_touch=true
robotMotor.upload.wait_for_upload_port=true
robotMotor.bootloader.tool=avrdude
robotMotor.bootloader.low_fuses=0xff
robotMotor.bootloader.high_fuses=0xd8
robotMotor.bootloader.extended_fuses=0xcb
robotMotor.bootloader.file=caterina-Arduino_Robot/Caterina-Robot-Motor.hex
robotMotor.bootloader.unlock_bits=0x3F
robotMotor.bootloader.lock_bits=0x2F
robotMotor.build.mcu=atmega32u4
robotMotor.build.f_cpu=16000000L
robotMotor.build.vid=0x2341
robotMotor.build.pid=0x8039
robotMotor.build.usb_product="Robot Motor"
robotMotor.build.board=AVR_ROBOT_MOTOR
robotMotor.build.core=arduino
robotMotor.build.variant=robot_motor
robotMotor.build.extra_flags={build.usb_flags}
##############################################################
gemma.vid.0=0x2341
gemma.pid.0=0x0c9f
gemma.name=Arduino Gemma
gemma.bootloader.low_fuses=0xF1
gemma.bootloader.high_fuses=0xD5
gemma.bootloader.extended_fuses=0xFE
gemma.bootloader.tool=avrdude
gemma.bootloader.lock_bits=
gemma.bootloader.unlock_bits=
gemma.bootloader.file=gemma/gemma_v1.hex
gemma.build.mcu=attiny85
gemma.build.f_cpu=8000000L
gemma.build.core=arduino
gemma.build.variant=gemma
gemma.build.board=AVR_GEMMA
gemma.upload.tool=avrdude
gemma.upload.maximum_size=5310
##############################################################
## Multi 4-in-1 (3.3V, 16 MHz) w/ ATmega328
## --------------------------------------------------
multi.name=Multi 4-in-1
multi.upload.tool=avrdude
multi.upload.protocol=arduino
multi.bootloader.tool=avrdude
multi.bootloader.unlock_bits=0x3F
multi.bootloader.lock_bits=0x0F
multi.build.board=AVR_PRO
multi.build.core=arduino
multi.build.variant=eightanaloginputs
multi.menu.cpu.16MHzatmega328=ATmega328 (3.3V, 16 MHz)
multi.menu.cpu.16MHzatmega328.upload.maximum_size=32768
multi.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
multi.menu.cpu.16MHzatmega328.upload.speed=57600
multi.menu.cpu.16MHzatmega328.upload.using=arduino:arduinoisp
multi.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
multi.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xD2
multi.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0xFD
multi.menu.cpu.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex
multi.menu.cpu.16MHzatmega328.build.mcu=atmega328p
multi.menu.cpu.16MHzatmega328.build.f_cpu=16000000L
## --------------------------------------------------
multi.menu.cpu.16MHzatmega328opti=ATmega328 Opti (3.3V, 16 MHz)
multi.menu.cpu.16MHzatmega328opti.upload.maximum_size=32768
multi.menu.cpu.16MHzatmega328opti.upload.maximum_data_size=2048
multi.menu.cpu.16MHzatmega328opti.upload.speed=57600
multi.menu.cpu.16MHzatmega328opti.upload.using=arduino:arduinoisp
multi.menu.cpu.16MHzatmega328opti.bootloader.low_fuses=0xFF
multi.menu.cpu.16MHzatmega328opti.bootloader.high_fuses=0xD6
multi.menu.cpu.16MHzatmega328opti.bootloader.extended_fuses=0xFD
multi.menu.cpu.16MHzatmega328opti.bootloader.file=atmega/optiboot_atmega328_16.hex
multi.menu.cpu.16MHzatmega328opti.build.mcu=atmega328p
multi.menu.cpu.16MHzatmega328opti.build.f_cpu=16000000L
##############################################################

Binary file not shown.

View File

@ -87,9 +87,4 @@ enum A7105_MASK {
A7105_MASK_VBCF = 1 << 3, A7105_MASK_VBCF = 1 << 3,
}; };
enum {
INIT_FLYSKY,
INIT_HUBSAN
};
#endif #endif

View File

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

@ -13,21 +13,28 @@
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
// 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"
#endif
#if F_CPU != 16000000L || not defined(__AVR_ATmega328P__)
#error You must select the processor type "ATmega328(5V, 16MHz)"
#endif
#endif
//****************** //******************
// Protocols // Protocols max 31 x2
//****************** //******************
enum PROTOCOLS 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_INAV = 57, // =>NRF24L01
MODE_Q303 = 58, // =>NRF24L01
MODE_SERIAL = 0, // Serial commands MODE_SERIAL = 0, // Serial commands
MODE_FLYSKY = 1, // =>A7105 MODE_FLYSKY = 1, // =>A7105
MODE_HUBSAN = 2, // =>A7105 MODE_HUBSAN = 2, // =>A7105
@ -56,19 +63,26 @@ enum PROTOCOLS
MODE_FRSKYV = 25, // =>CC2500 MODE_FRSKYV = 25, // =>CC2500
MODE_HONTAI = 26, // =>NRF24L01 MODE_HONTAI = 26, // =>NRF24L01
MODE_OPENLRS = 27, // =>OpenLRS hardware MODE_OPENLRS = 27, // =>OpenLRS hardware
MODE_AFHDS2A = 28, // =>A7105
}; };
enum Flysky enum Flysky
{ {
Flysky = 0, Flysky=0,
V9X9 = 1, V9X9=1,
V6X6 = 2, V6X6=2,
V912 = 3 V912=3
};
enum AFHDS2A
{
PWM_IBUS = 0,
PPM_IBUS = 1,
PWM_SBUS = 2,
PPM_SBUS = 3,
}; };
enum Hisky enum Hisky
{ {
Hisky = 0, Hisky=0,
HK310 = 1 HK310=1
}; };
enum DSM enum DSM
{ {
@ -80,38 +94,38 @@ enum DSM
}; };
enum YD717 enum YD717
{ {
YD717 = 0, YD717=0,
SKYWLKR = 1, SKYWLKR=1,
SYMAX4 = 2, SYMAX4=2,
XINXUN = 3, XINXUN=3,
NIHUI = 4 NIHUI=4
}; };
enum KN enum KN
{ {
WLTOYS = 0, WLTOYS=0,
FEILUN = 1 FEILUN=1
}; };
enum SYMAX enum SYMAX
{ {
SYMAX = 0, SYMAX=0,
SYMAX5C = 1 SYMAX5C=1
}; };
enum CX10 enum CX10
{ {
CX10_GREEN = 0, CX10_GREEN = 0,
CX10_BLUE = 1, // also compatible with CX10-A, CX12 CX10_BLUE=1, // also compatible with CX10-A, CX12
DM007 = 2, DM007=2,
Q282 = 3, Q282=3,
JC3015_1 = 4, JC3015_1=4,
JC3015_2 = 5, JC3015_2=5,
MK33041 = 6, MK33041=6,
Q242 = 7 Q242=7
}; };
enum CG023 enum CG023
{ {
CG023 = 0, CG023 = 0,
YD829 = 1, YD829 = 1,
H8_3D = 2 H8_3D = 2
}; };
enum MT99XX enum MT99XX
{ {
@ -126,7 +140,8 @@ enum MJXQ
X600 = 1, X600 = 1,
X800 = 2, X800 = 2,
H26D = 3, H26D = 3,
E010 = 4 E010 = 4,
H26WH = 5
}; };
enum FRSKYX enum FRSKYX
{ {
@ -135,9 +150,44 @@ enum FRSKYX
}; };
enum HONTAI enum HONTAI
{ {
FORMAT_HONTAI = 0, FORMAT_HONTAI = 0,
FORMAT_JJRCX1 = 1, 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 V2X2 {
FORMAT_V202 = 0,
FORMAT_JXD506 = 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 #define NONE 0
@ -159,27 +209,6 @@ struct PPM_Parameters
// Macros // Macros
#define NOP() __asm__ __volatile__("nop") #define NOP() __asm__ __volatile__("nop")
//*******************
//*** Timer ***
//*******************
#ifdef XMEGA
#define TIFR1 TCC1.INTFLAGS
#define OCF1A_bm TC1_CCAIF_bm
#define OCR1A TCC1.CCA
#define TCNT1 TCC1.CNT
#define UDR0 USARTC0.DATA
#define OCF1B_bm TC1_CCBIF_bm
#define OCR1B TCC1.CCB
#define TIMSK1 TCC1.INTCTRLB
#define SET_TIMSK1_OCIE1B TIMSK1 = (TIMSK1 & 0xF3) | 0x04
#define CLR_TIMSK1_OCIE1B TIMSK1 &= 0xF3
#else
#define OCF1A_bm _BV(OCF1A)
#define OCF1B_bm _BV(OCF1B)
#define SET_TIMSK1_OCIE1B TIMSK1 |= _BV(OCIE1B)
#define CLR_TIMSK1_OCIE1B TIMSK1 &=~_BV(OCIE1B)
#endif
//*************** //***************
//*** Flags *** //*** Flags ***
//*************** //***************
@ -188,7 +217,7 @@ struct PPM_Parameters
#define IS_RX_FLAG_on ( ( protocol_flags & _BV(0) ) !=0 ) #define IS_RX_FLAG_on ( ( protocol_flags & _BV(0) ) !=0 )
// //
#define CHANGE_PROTOCOL_FLAG_on protocol_flags |= _BV(1) #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 IS_CHANGE_PROTOCOL_FLAG_on ( ( protocol_flags & _BV(1) ) !=0 )
// //
#define POWER_FLAG_on protocol_flags |= _BV(2) #define POWER_FLAG_on protocol_flags |= _BV(2)
@ -206,8 +235,9 @@ struct PPM_Parameters
#define BIND_BUTTON_FLAG_on protocol_flags |= _BV(5) #define BIND_BUTTON_FLAG_on protocol_flags |= _BV(5)
#define BIND_BUTTON_FLAG_off protocol_flags &= ~_BV(5) #define BIND_BUTTON_FLAG_off protocol_flags &= ~_BV(5)
#define IS_BIND_BUTTON_FLAG_on ( ( protocol_flags & _BV(5) ) !=0 ) #define IS_BIND_BUTTON_FLAG_on ( ( protocol_flags & _BV(5) ) !=0 )
//PPM RX OK //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 PPM_FLAG_on protocol_flags |= _BV(6)
#define IS_PPM_FLAG_on ( ( protocol_flags & _BV(6) ) !=0 ) #define IS_PPM_FLAG_on ( ( protocol_flags & _BV(6) ) !=0 )
//Bind flag //Bind flag
@ -227,19 +257,27 @@ struct PPM_Parameters
#define RX_MISSED_BUFF_on protocol_flags2 |= _BV(2) #define RX_MISSED_BUFF_on protocol_flags2 |= _BV(2)
#define IS_RX_MISSED_BUFF_on ( ( protocol_flags2 & _BV(2) ) !=0 ) #define IS_RX_MISSED_BUFF_on ( ( protocol_flags2 & _BV(2) ) !=0 )
//TX Pause //TX Pause
#define TX_MAIN_PAUSE_off protocol_flags2 &= ~_BV(3) #define TX_MAIN_PAUSE_off protocol_flags2 &= ~_BV(3)
#define TX_MAIN_PAUSE_on 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 IS_TX_MAIN_PAUSE_on ( ( protocol_flags2 & _BV(3) ) !=0 )
#define TX_RX_PAUSE_off protocol_flags2 &= ~_BV(4) #define TX_RX_PAUSE_off protocol_flags2 &= ~_BV(4)
#define TX_RX_PAUSE_on 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 IS_TX_RX_PAUSE_on ( ( protocol_flags2 & _BV(4) ) !=0 )
#define IS_TX_PAUSE_on ( ( protocol_flags2 & (_BV(4)|_BV(3)) ) !=0 ) #define IS_TX_PAUSE_on ( ( protocol_flags2 & (_BV(4)|_BV(3)) ) !=0 )
//Signal OK
#define INPUT_SIGNAL_off protocol_flags2 &= ~_BV(5)
#define INPUT_SIGNAL_on protocol_flags2 |= _BV(5)
#define IS_INPUT_SIGNAL_on ( ( protocol_flags2 & _BV(5) ) !=0 )
#define IS_INPUT_SIGNAL_off ( ( protocol_flags2 & _BV(5) ) ==0 )
//******************** //********************
//*** Blink timing *** //*** Blink timing ***
//******************** //********************
#define BLINK_BIND_TIME 100 #define BLINK_BIND_TIME 100
#define BLINK_SERIAL_TIME 500 #define BLINK_SERIAL_TIME 500
#define BLINK_PPM_TIME 1000
#define BLINK_BAD_PROTO_TIME_LOW 1000 #define BLINK_BAD_PROTO_TIME_LOW 1000
#define BLINK_BAD_PROTO_TIME_HIGH 50 #define BLINK_BAD_PROTO_TIME_HIGH 50
@ -409,6 +447,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
FrskyV 25 FrskyV 25
HONTAI 26 HONTAI 26
OpenLRS 27 OpenLRS 27
AFHDS2A 28
BindBit=> 0x80 1=Bind/0=No BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No RangeCheck=> 0x20 1=Yes /0=No
@ -416,30 +455,31 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
RxNum value is 0..15 (bits 0..3) RxNum value is 0..15 (bits 0..3)
Type is 0..7 <<4 (bit 4..6) Type is 0..7 <<4 (bit 4..6)
sub_protocol==Flysky sub_protocol==Flysky
Flysky 0 Flysky 0
V9x9 1 V9x9 1
V6x6 2 V6x6 2
V912 3 V912 3
sub_protocol==Hisky sub_protocol==Hisky
Hisky 0 Hisky 0
HK310 1 HK310 1
sub_protocol==DSM sub_protocol==DSM
DSM2_22 0 DSM2_22 0
DSM2_11 1 DSM2_11 1
DSMX_22 2 DSMX_22 2
DSMX_11 3 DSMX_11 3
DSM_AUTO 4
sub_protocol==YD717 sub_protocol==YD717
YD717 0 YD717 0
SKYWLKR 1 SKYWLKR 1
SYMAX4 2 SYMAX4 2
XINXUN 3 XINXUN 3
NIHUI 4 NIHUI 4
sub_protocol==KN sub_protocol==KN
WLTOYS 0 WLTOYS 0
FEILUN 1 FEILUN 1
sub_protocol==SYMAX sub_protocol==SYMAX
SYMAX 0 SYMAX 0
SYMAX5C 1 SYMAX5C 1
sub_protocol==CX10 sub_protocol==CX10
CX10_GREEN 0 CX10_GREEN 0
CX10_BLUE 1 // also compatible with CX10-A, CX12 CX10_BLUE 1 // also compatible with CX10-A, CX12
@ -464,6 +504,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
X800 2 X800 2
H26D 3 H26D 3
E010 4 E010 4
sub_protocol==FY326
FY326 0
FY319 1
sub_protocol==FRSKYX sub_protocol==FRSKYX
CH_16 0 CH_16 0
CH_8 1 CH_8 1
@ -471,7 +514,13 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
FORMAT_HONTAI 0 FORMAT_HONTAI 0
FORMAT_JJRCX1 1 FORMAT_JJRCX1 1
FORMAT_X5C1 2 FORMAT_X5C1 2
Power value => 0x80 0=High/1=Low FQ777-521 3
sub_protocol==AFHDS2A
PWM_IBUS 0
PPM_IBUS 1
PWM_SBUS 2
PPM_SBUS 3
Power value => 0x80 0=High/1=Low
Stream[3] = option_protocol; Stream[3] = option_protocol;
option_protocol value is -127..127 option_protocol value is -127..127
Stream[4] to [25] = Channels Stream[4] to [25] = Channels
@ -483,3 +532,4 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
2047 +125% 2047 +125%
Channels bits are concatenated to fit in 22 bytes like in SBUS protocol 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.