Multi core fixes, DSM2/X fixes and telemetry, SFHSS addition, Flysky fixes, FrSkyX full telemetry and sub protocols

Many things since last commit...
This commit is contained in:
pascallanger 2016-04-06 12:57:42 +02:00
parent 6c3535951f
commit d938f2ea50
14 changed files with 2608 additions and 743 deletions

View File

@ -19,18 +19,18 @@
//-------------------------------
#include "iface_cc2500.h"
void cc2500_readFifo(uint8_t *dpbuffer, uint8_t len)
void CC2500_ReadData(uint8_t *dpbuffer, uint8_t len)
{
ReadRegisterMulti(CC2500_3F_RXFIFO | CC2500_READ_BURST, dpbuffer, len);
CC2500_ReadRegisterMulti(CC2500_3F_RXFIFO | CC2500_READ_BURST, dpbuffer, len);
}
//----------------------
static void ReadRegisterMulti(uint8_t address, uint8_t data[], uint8_t length)
static void CC2500_ReadRegisterMulti(uint8_t address, uint8_t data[], uint8_t length)
{
CC25_CSN_off;
cc2500_spi_write(address);
CC2500_SPI_Write(address);
for(uint8_t i = 0; i < length; i++)
data[i] = cc2500_spi_read();
data[i] = CC2500_SPI_Read();
CC25_CSN_on;
}
@ -39,21 +39,21 @@ static void ReadRegisterMulti(uint8_t address, uint8_t data[], uint8_t length)
static void CC2500_WriteRegisterMulti(uint8_t address, const uint8_t data[], uint8_t length)
{
CC25_CSN_off;
cc2500_spi_write(CC2500_WRITE_BURST | address);
CC2500_SPI_Write(CC2500_WRITE_BURST | address);
for(uint8_t i = 0; i < length; i++)
cc2500_spi_write(data[i]);
CC2500_SPI_Write(data[i]);
CC25_CSN_on;
}
void cc2500_writeFifo(uint8_t *dpbuffer, uint8_t len)
void CC2500_WriteData(uint8_t *dpbuffer, uint8_t len)
{
cc2500_strobe(CC2500_SFTX);//0x3B
CC2500_Strobe(CC2500_SFTX);//0x3B
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, dpbuffer, len);
cc2500_strobe(CC2500_STX);//0x35
CC2500_Strobe(CC2500_STX);//0x35
}
//--------------------------------------
static void cc2500_spi_write(uint8_t command) {
static void CC2500_SPI_Write(uint8_t command) {
uint8_t n=8;
SCK_off;//SCK start low
@ -73,15 +73,15 @@ static void cc2500_spi_write(uint8_t command) {
}
//----------------------------
void cc2500_writeReg(uint8_t address, uint8_t data) {//same as 7105
void CC2500_WriteReg(uint8_t address, uint8_t data) {//same as 7105
CC25_CSN_off;
cc2500_spi_write(address);
CC2500_SPI_Write(address);
NOP();
cc2500_spi_write(data);
CC2500_SPI_Write(data);
CC25_CSN_on;
}
static uint8_t cc2500_spi_read(void)
static uint8_t CC2500_SPI_Read(void)
{
uint8_t result;
uint8_t i;
@ -101,21 +101,21 @@ static uint8_t cc2500_spi_read(void)
}
//--------------------------------------------
static uint8_t cc2500_readReg(uint8_t address)
static uint8_t CC2500_ReadReg(uint8_t address)
{
uint8_t result;
CC25_CSN_off;
address |=0x80; //bit 7 =1 for reading
cc2500_spi_write(address);
result = cc2500_spi_read();
CC2500_SPI_Write(address);
result = CC2500_SPI_Read();
CC25_CSN_on;
return(result);
}
//------------------------
void cc2500_strobe(uint8_t address)
void CC2500_Strobe(uint8_t address)
{
CC25_CSN_off;
cc2500_spi_write(address);
CC2500_SPI_Write(address);
CC25_CSN_on;
}
//------------------------
@ -128,16 +128,16 @@ void cc2500_strobe(uint8_t address)
_delay_us(30);
CC25_CSN_on;
_delay_us(45);
cc2500_strobe(CC2500_SRES);
CC2500_Strobe(CC2500_SRES);
_delay_ms(100);
}
*/
uint8_t CC2500_Reset()
{
cc2500_strobe(CC2500_SRES);
CC2500_Strobe(CC2500_SRES);
_delay_us(1000);
CC2500_SetTxRxMode(TXRX_OFF);
return cc2500_readReg(CC2500_0E_FREQ1) == 0xC4;//check if reset
return CC2500_ReadReg(CC2500_0E_FREQ1) == 0xC4;//check if reset
}
/*
static void CC2500_SetPower_Value(uint8_t power)
@ -154,7 +154,7 @@ static void CC2500_SetPower_Value(uint8_t power)
};
if (power > 7)
power = 7;
cc2500_writeReg(CC2500_3E_PATABLE, patable[power]);
CC2500_WriteReg(CC2500_3E_PATABLE, patable[power]);
}
*/
void CC2500_SetPower()
@ -164,25 +164,25 @@ void CC2500_SetPower()
power=IS_POWER_FLAG_on?CC2500_HIGH_POWER:CC2500_LOW_POWER;
if(IS_RANGE_FLAG_on)
power=CC2500_RANGE_POWER;
cc2500_writeReg(CC2500_3E_PATABLE, power);
CC2500_WriteReg(CC2500_3E_PATABLE, power);
}
void CC2500_SetTxRxMode(uint8_t mode)
{
if(mode == TX_EN)
{//from deviation firmware
cc2500_writeReg(CC2500_02_IOCFG0, 0x2F | 0x40);
cc2500_writeReg(CC2500_00_IOCFG2, 0x2F);
CC2500_WriteReg(CC2500_02_IOCFG0, 0x2F | 0x40);
CC2500_WriteReg(CC2500_00_IOCFG2, 0x2F);
}
else
if (mode == RX_EN)
{
cc2500_writeReg(CC2500_02_IOCFG0, 0x2F);
cc2500_writeReg(CC2500_00_IOCFG2, 0x2F | 0x40);
CC2500_WriteReg(CC2500_02_IOCFG0, 0x2F);
CC2500_WriteReg(CC2500_00_IOCFG2, 0x2F | 0x40);
}
else
{
cc2500_writeReg(CC2500_02_IOCFG0, 0x2F);
cc2500_writeReg(CC2500_00_IOCFG2, 0x2F);
CC2500_WriteReg(CC2500_02_IOCFG0, 0x2F);
CC2500_WriteReg(CC2500_00_IOCFG2, 0x2F);
}
}

View File

@ -14,20 +14,32 @@
*/
#include "iface_cyrf6936.h"
#ifdef XMEGA
#define XNOP() NOP()
#else
#define XNOP()
#endif
static void cyrf_spi_write(uint8_t command)
{
uint8_t n=8;
SCK_off;//SCK start low
XNOP() ;
SDI_off;
XNOP() ;
while(n--) {
if(command&0x80)
SDI_on;
else
SDI_off;
XNOP() ;
SCK_on;
NOP();
XNOP() ;
XNOP() ;
SCK_off;
command = command << 1;
XNOP() ;
}
SDI_on;
}
@ -39,13 +51,16 @@ static uint8_t cyrf_spi_read()
result=0;
for(i=0;i<8;i++)
{
result<<=1;
if(SDO_1) ///
result=(result<<1)|0x01;
else
result=result<<1;
result|=0x01;
SCK_on;
XNOP() ;
XNOP() ;
NOP();
SCK_off;
XNOP() ;
XNOP() ;
NOP();
}
return result;
@ -215,11 +230,11 @@ static void CYRF_StartReceive()
CYRF_ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, 0x10);
}
*/
/*static void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length)
void CYRF_ReadDataPacketLen(uint8_t dpbuffer[], uint8_t length)
{
ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, length);
CYRF_ReadRegisterMulti(CYRF_21_RX_BUFFER, dpbuffer, length);
}
*/
static void CYRF_WriteDataPacketLen(const uint8_t dpbuffer[], uint8_t len)
{
CYRF_WriteRegister(CYRF_01_TX_LENGTH, len);

View File

@ -20,7 +20,6 @@
#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
@ -107,21 +106,19 @@ static void __attribute__((unused)) read_code(uint8_t *buf, uint8_t row, uint8_t
}
//
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[0] = 0xff ^ cyrfmfg_id[0];
packet[1] = 0xff ^ cyrfmfg_id[1];
packet[2] = 0xff ^ cyrfmfg_id[2];
packet[3] = (0xff ^ cyrfmfg_id[3]) + RX_num;
packet[3] = 0xff ^ cyrfmfg_id[3];
packet[4] = packet[0];
packet[5] = packet[1];
packet[6] = packet[2];
@ -133,7 +130,11 @@ static void __attribute__((unused)) build_bind_packet()
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;
#if defined DSM_TELEMETRY
packet[12] = 0xb2; // Telemetry on
#else
packet[12] = option<8? 0xa2 : 0xb2; // Telemetry off
#endif
else
packet[12] = option<8?0x01:0x02;
packet[13] = 0x00; //???
@ -196,13 +197,13 @@ static void __attribute__((unused)) build_data_packet(uint8_t upper)//
if (sub_protocol==DSMX)
{
packet[0] = cyrfmfg_id[2];
packet[1] = cyrfmfg_id[3] + RX_num;
packet[1] = cyrfmfg_id[3];
bits=11;
}
else
{
packet[0] = (0xff ^ cyrfmfg_id[2]);
packet[1] = (0xff ^ cyrfmfg_id[3]) + RX_num;
packet[1] = (0xff ^ cyrfmfg_id[3]);
bits=10;
}
//
@ -251,6 +252,18 @@ static void __attribute__((unused)) build_data_packet(uint8_t upper)//
case 7:
value=Servo_data[AUX4];
break;
case 8:
value=Servo_data[AUX5];
break;
case 9:
value=Servo_data[AUX6];
break;
case 10:
value=Servo_data[AUX7];
break;
case 11:
value=Servo_data[AUX8];
break;
}
value=map(value,PPM_MIN,PPM_MAX,0,max-1);
}
@ -267,7 +280,7 @@ static uint8_t __attribute__((unused)) get_pn_row(uint8_t channel)
}
const uint8_t init_vals[][2] = {
{CYRF_02_TX_CTRL, 0x00},
{CYRF_02_TX_CTRL, 0x02}, //0x00 in deviation but needed to know when transmit is over
{CYRF_05_RX_CTRL, 0x00},
{CYRF_28_CLK_EN, 0x02},
{CYRF_32_AUTO_CAL_TIME, 0x3c},
@ -314,7 +327,7 @@ static void __attribute__((unused)) initialize_bind_state()
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);
memcpy(code + 24, (void *)"\xc6\x94\x22\xfe\x48\xe6\x57\x4e", 8);
CYRF_ConfigDataCode(code, 32);
build_bind_packet();
@ -347,10 +360,11 @@ static void __attribute__((unused)) cyrf_configdata()
static void __attribute__((unused)) set_sop_data_crc()
{
uint8_t code[16];
uint8_t pn_row = get_pn_row(hopping_frequency[chidx]);
//printf("Ch: %d Row: %d SOP: %d Data: %d\n", ch[chidx], pn_row, sop_col, data_col);
CYRF_ConfigRFChannel(hopping_frequency[chidx]);
CYRF_ConfigCRCSeed(crcidx ? ~crc : crc);
uint8_t pn_row = get_pn_row(hopping_frequency[hopping_frequency_no]);
//printf("Ch: %d Row: %d SOP: %d Data: %d\n", ch[hopping_frequency_no], pn_row, sop_col, data_col);
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
CYRF_ConfigCRCSeed(crc);
crc=~crc;
read_code(code,pn_row,sop_col,8);
CYRF_ConfigSOPCode(code);
@ -358,10 +372,9 @@ static void __attribute__((unused)) set_sop_data_crc()
CYRF_ConfigDataCode(code, 16);
if(sub_protocol == DSMX)
chidx = (chidx + 1) % 23;
hopping_frequency_no = (hopping_frequency_no + 1) % 23;
else
chidx = (chidx + 1) % 2;
crcidx = !crcidx;
hopping_frequency_no = (hopping_frequency_no + 1) % 2;
}
static void __attribute__((unused)) calc_dsmx_channel()
@ -375,7 +388,7 @@ static void __attribute__((unused)) calc_dsmx_channel()
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)
if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 )
continue;
for (i = 0; i < idx; i++)
{
@ -400,10 +413,10 @@ static void __attribute__((unused)) calc_dsmx_channel()
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;
#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_READ_DELAY 600 // Time before write to check read state, and switch channels. Was 400 but 500 seems what the 328p needs to read a packet
uint32_t start;
switch(cyrf_state)
{
@ -413,8 +426,7 @@ uint16_t ReadDsm2()
if(cyrf_state & 1)
{
//Send packet on even states
//Note state has already incremented,
// so this is actually 'even' state
//Note state has already incremented, so this is actually 'even' state
CYRF_WriteDataPacket(packet);
return 8500;
}
@ -430,35 +442,81 @@ uint16_t ReadDsm2()
//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++
hopping_frequency_no = 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:
build_data_packet(cyrf_state == DSM2_CH1_WRITE_B);// build lower or upper channels
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
CYRF_WriteDataPacket(packet);
cyrf_state++; // change from WRITE to CHECK mode
return WRITE_DELAY;
cyrf_state++; // change from WRITE to CHECK mode
return DSM_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)
start=micros();
while (micros()-start < 500) // Wait max 500µs
if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)
break;
set_sop_data_crc();
cyrf_state++; // change from CH1_CHECK to CH2_WRITE
return CH1_CH2_DELAY - WRITE_DELAY;
cyrf_state++; // change from CH1_CHECK to CH2_WRITE
return DSM_CH1_CH2_DELAY - DSM_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)
start=micros();
while (micros()-start < 500) // Wait max 500µs
if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)
break;
if (cyrf_state == DSM2_CH2_CHECK_A)
CYRF_SetPower(0x28); //Keep transmit power in sync
// No telemetry...
CYRF_SetPower(0x28); //Keep transmit power in sync
#if defined DSM_TELEMETRY
cyrf_state++; // change from CH2_CHECK to CH2_READ
if(option<=3 || option>7)
{ // disable telemetry for option between 4 and 7 ie 4,5,6,7 channels @11ms since it does not work...
CYRF_SetTxRxMode(RX_EN); //Receive mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
}
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
case DSM2_CH2_READ_A:
case DSM2_CH2_READ_B:
//Read telemetry
uint8_t rx_state = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_state & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
rx_state |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_state & 0x07) == 0x02)
{ // good data (complete with no errors)
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
uint8_t len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
if(len>MAX_PKT-2)
len=MAX_PKT-2;
CYRF_ReadDataPacketLen(pkt+1, len);
pkt[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F; // store RSSI of the received telemetry signal
telemetry_link=1;
}
if (cyrf_state == DSM2_CH2_READ_A && option <= 3) // normal 22ms mode if option<=3 ie 4,5,6,7 channels @22ms
{
//Force end read state
CYRF_WriteRegister(CYRF_0F_XACT_CFG, (CYRF_ReadRegister(CYRF_0F_XACT_CFG) | 0x20)); // Force end state
start=micros();
while (micros()-start < 100) // Wait max 100 µs
if((CYRF_ReadRegister(CYRF_0F_XACT_CFG) & 0x20) == 0)
break;
cyrf_state = DSM2_CH2_READ_B;
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
return 11000;
}
if (cyrf_state == DSM2_CH2_READ_A && option>7)
cyrf_state = DSM2_CH1_WRITE_B; //Transmit upper
else
cyrf_state = DSM2_CH1_WRITE_A; //Force 11ms if option>3 ie 4,5,6,7 channels @11ms
CYRF_SetTxRxMode(TX_EN); //Write mode
set_sop_data_crc();
return DSM_READ_DELAY;
#else
// No telemetry
set_sop_data_crc();
if (cyrf_state == DSM2_CH2_CHECK_A)
{
@ -466,16 +524,17 @@ uint16_t ReadDsm2()
{
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
return 11000 - DSM_CH1_CH2_DELAY - DSM_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
return 22000 - DSM_CH1_CH2_DELAY - DSM_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 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
#endif
}
return 0;
}
@ -484,10 +543,12 @@ uint16_t initDsm2()
{
CYRF_Reset();
CYRF_GetMfgData(cyrfmfg_id);//
//Model match
cyrfmfg_id[3]+=RX_num;
cyrf_config();
if (sub_protocol ==DSMX)
if (sub_protocol == DSMX)
calc_dsmx_channel();
else
{
@ -511,12 +572,12 @@ uint16_t initDsm2()
#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])
//The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1])
//The crc for channel '2' is (mfgid[0] << 8 + mfgid[1])
crc = ~((cyrfmfg_id[0] << 8) + cyrfmfg_id[1]);
//
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;//Ok
data_col = 7 - sop_col;//ok
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
data_col = 7 - sop_col;
CYRF_SetTxRxMode(TX_EN);
//

View File

@ -21,25 +21,6 @@
//FlySky constants & variables
#define FLYSKY_BIND_COUNT 2500
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,
@ -164,12 +145,31 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
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)
packet[5 + i*2]=Servo_data[ch[i]]&0xFF; //low byte of servo timing(1000-2000us)
packet[6 + i*2]=(Servo_data[ch[i]]>>8)&0xFF; //high byte of servo timing(1000-2000us)
}
flysky_apply_extension_flags();
}
const uint8_t PROGMEM tx_channels[16][16] = {
{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},
};
uint16_t ReadFlySky()
{
if (bind_counter)
@ -182,25 +182,24 @@ uint16_t ReadFlySky()
}
else
{
flysky_build_packet(0);
A7105_WriteData(21, pgm_read_byte_near(&tx_channels[chanrow*16+chancol])-chanoffset);
flysky_build_packet(0);
A7105_WriteData(21, pgm_read_byte_near(&tx_channels[chanrow][chancol])-chanoffset);
chancol = (chancol + 1) % 16;
if (! chancol) //Keep transmit power updated
A7105_SetPower();
}
return 1460;
return 1510; //1460 on deviation but not working with the latest V911 bricks... Turnigy 9X v2 is 1533, Flysky TX for 9XR/9XR Pro is 1510, V911 TX is 1490.
}
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;
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;
chanrow=rx_tx_addr[3] & 0x0F;
chancol=0;
chanoffset=rx_tx_addr[3] / 16;
chanoffset=rx_tx_addr[3]/16;
if(IS_AUTOBIND_FLAG_on)
bind_counter = FLYSKY_BIND_COUNT;

View File

@ -18,292 +18,318 @@
#if defined(FRSKYX_CC2500_INO)
#include "iface_cc2500.h"
#include "iface_cc2500.h"
uint8_t chanskip;
uint8_t calData[48][3];
uint8_t channr;
uint8_t pass_ = 1 ;
uint8_t counter_rst;
uint8_t ctr;
uint8_t FS_flag=0;
// uint8_t ptr[4]={0x01,0x12,0x23,0x30};
//uint8_t ptr[4]={0x00,0x11,0x22,0x33};
uint8_t chanskip;
uint8_t channr;
uint8_t counter_rst;
uint8_t ctr;
uint8_t FS_flag=0;
uint8_t seq_last_sent;
uint8_t seq_last_rcvd;
const PROGMEM uint8_t hop_data[]={
0x02, 0xD4, 0xBB, 0xA2, 0x89,
0x70, 0x57, 0x3E, 0x25, 0x0C,
0xDE, 0xC5, 0xAC, 0x93, 0x7A,
0x61, 0x48, 0x2F, 0x16, 0xE8,
0xCF, 0xB6, 0x9D, 0x84, 0x6B,
0x52, 0x39, 0x20, 0x07, 0xD9,
0xC0, 0xA7, 0x8E, 0x75, 0x5C,
0x43, 0x2A, 0x11, 0xE3, 0xCA,
0xB1, 0x98, 0x7F, 0x66, 0x4D,
0x34, 0x1B, 0x00, 0x1D, 0x03
};
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)
static uint8_t __attribute__((unused)) hop(uint8_t byte)
{
return pgm_read_byte_near(&hop_data[byte]);
}
static void __attribute__((unused)) set_start(uint8_t ch )
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_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++)
{
return pgm_read_byte_near(&hop_data[byte]);
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);
}
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);
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)) crc_x(uint8_t *data, uint8_t len)
{
uint16_t crc = 0;
for(uint8_t i=0; i < len; i++)
crc = (crc<<8) ^ pgm_read_word(&CRCTable[((uint8_t)(crc>>8) ^ *data++) & 0xFF]);
return crc;
}
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;
// 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182
//64=860,1024=1500,1984=2140//Taranis 125%
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()
{
packet[0] = 0x1D;
packet[1] = 0x03;
packet[2] = 0x01;
//
packet[3] = rx_tx_addr[3];
packet[4] = rx_tx_addr[2];
int idx = ((state -FRSKY_BIND) % 10) * 5;
packet[5] = idx;
packet[6] = pgm_read_word(&hop_data[idx++]);
packet[7] = pgm_read_word(&hop_data[idx++]);
packet[8] = pgm_read_word(&hop_data[idx++]);
packet[9] = pgm_read_word(&hop_data[idx++]);
packet[10] = pgm_read_word(&hop_data[idx++]);
packet[11] = 0x02;
packet[12] = RX_num;
//
memset(&packet[13], 0, 15);
uint16_t lcrc = crc_x(&packet[3], 25);
//
packet[28] = lcrc >> 8;
packet[29] = lcrc;
//
}
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
//
static uint8_t lpass;
uint16_t chan_0 ;
uint16_t chan_1 ;
uint8_t startChan = 0;
//
packet[0] = 0x1D;
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = 0x02;
//
packet[4] = (ctr<<6)+channr;
packet[5] = counter_rst;
packet[6] = RX_num;
//FLAGS 00 - standard packet
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
//20 - range check packet
packet[7] = FS_flag;
packet[8] = 0;
//
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;
startChan+=1;
//
chan_1 = scaleForPXX(startChan);
if(lpass & 1 )
chan_1+= 2048;
startChan+=1;
//
packet[9+i] = lowByte(chan_0);//3 bytes*4
packet[9+i+1]=(((chan_0>>8) & 0x0F)|(chan_1 << 4));
packet[9+i+2]=chan_1>>4;
}
static void __attribute__((unused)) frskyX_build_bind_packet()
packet[21] = seq_last_sent << 4 | seq_last_rcvd;//8 at start
if (seq_last_sent < 0x08 && seq_last_rcvd < 8)
seq_last_sent = (seq_last_sent + 1) % 4;
else if (seq_last_rcvd == 0x00)
seq_last_sent = 1;
if(sub_protocol== CH_8 )// in X8 mode send only 8ch every 9ms
lpass = 0 ;
else
lpass += 1 ;
for (uint8_t i=22;i<28;i++)
packet[i]=0;
uint16_t lcrc = crc_x(&packet[3], 25);
packet[28]=lcrc>>8;//high byte
packet[29]=lcrc;//low byte
}
uint16_t ReadFrSkyX()
{
switch(state)
{
crc=0;
packet[0] = 0x1D;
packet[1] = 0x03;
packet[2] = 0x01;
//
packet[3] = crc_Byte(rx_tx_addr[3]);
packet[4] = crc_Byte(rx_tx_addr[2]);
int idx = ((state -FRSKY_BIND) % 10) * 5;
packet[5] = crc_Byte(idx);
packet[6] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[7] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[8] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[9] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[10] = crc_Byte(pgm_read_word(&hop_data[idx++]));
packet[11] = crc_Byte(0x02);
packet[12] = crc_Byte(RX_num);
//
for(uint8_t i=13;i<28;i++)
packet[i]=crc_Byte(0);
//
packet[28]=highByte(crc);
packet[29]=lowByte(crc);
//
}
static void __attribute__((unused)) frskyX_data_frame()
{
//0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12
//
uint8_t lpass = pass_ ;
uint16_t chan_0 ;
uint16_t chan_1 ;
uint8_t flag2 = 0;
uint8_t startChan = 0;
crc = 0;
//static uint8_t p = 0;
//
packet[0] = 0x1D;
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = crc_Byte(0x02);
//
packet[4] = crc_Byte((ctr<<6)+channr); //*64
packet[5] = crc_Byte(counter_rst);
packet[6] = crc_Byte(RX_num);
// FLAGS 00 - standard packet
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
//20 - range check packet
packet[7] = crc_Byte(FS_flag);
packet[8] = crc_Byte(flag2);
//
if ( lpass & 1 )
startChan += 8 ;
for(uint8_t i = 0; i <12 ; i+=3)
{//12 bytes
chan_0 = scaleForPXX(startChan);
if(lpass & 1 )
chan_0+=2048;
packet[9+i] = crc_Byte(lowByte(chan_0));//3 bytes*4
startChan++;
chan_1 = scaleForPXX(startChan);
if(lpass & 1 )
chan_1+= 2048;
startChan++;
packet[9+i+1]=crc_Byte((((chan_0>>8) & 0x0F)|(chan_1 << 4)));
packet[9+i+2]=crc_Byte(chan_1>>4);
}
//packet[21]=crc_Byte(0x08);//first
packet[21]=crc_Byte(0x80);//??? when received first telemetry frame is changed to 0x80
//packet[21]=crc_Byte(ptr[p]);//???
//p=(p+1)%4;//repeating 4 bytes sequence pattern every 4th frame.
pass_=lpass+1;
for (uint8_t i=22;i<28;i++)
packet[i]=crc_Byte(0);
packet[28]=highByte(crc);
packet[29]=lowByte(crc);
}
uint16_t ReadFrSkyX()
{
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;
default:
set_start(47);
CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX);
//
frskyX_build_bind_packet();
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteData(packet, packet[0]+1);
state++;
return 9000;
case FRSKY_BIND_DONE:
initialize_data(0);
}
return 10000;
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_WriteData(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_ReadData(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
}
else
{
counter++;
// restart sequence on missed packet - might need count or timeout instead of one missed
if(counter>100)
{//~1sec
seq_last_sent = 0;
seq_last_rcvd = 8;
counter=0;
}
}
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();
CC2500_SetTxRxMode(TX_EN);
//
if(IS_AUTOBIND_FLAG_on)
{
state = FRSKY_BIND;
initialize_data(1);
}
else
{
state = FRSKY_DATA1;
initialize_data(0);
}
seq_last_sent = 0;
seq_last_rcvd = 8;
return 10000;
}
#endif

View File

@ -48,21 +48,21 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind)
else
if(reg==CC2500_1B_AGCCTRL2)
val=bind ? 0x43 : 0x03;
cc2500_writeReg(reg,val);
CC2500_WriteReg(reg,val);
}
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
cc2500_strobe(CC2500_SIDLE);
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_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);
CC2500_WriteReg(CC2500_0A_CHANNR, 0x00);
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
CC2500_Strobe(CC2500_SFRX);
//#######END INIT########
}
@ -158,11 +158,11 @@ 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);
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, 0x00);
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
CC2500_Strobe(CC2500_SFRX);//0x3A
CC2500_WriteData(packet, packet[0]+1);
state++;
return 9000;
}
@ -176,7 +176,7 @@ uint16_t ReadFrSky_2way()
else
if (state == FRSKY_DATA5)
{
cc2500_strobe(CC2500_SRX);//0x34 RX enable
CC2500_Strobe(CC2500_SRX);//0x34 RX enable
state = FRSKY_DATA1;
return 9200;
}
@ -184,9 +184,9 @@ uint16_t ReadFrSky_2way()
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);
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
state++;
return 1300;
}
@ -194,10 +194,10 @@ uint16_t ReadFrSky_2way()
{
if (state == FRSKY_DATA1)
{
len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len<=MAX_PKT)//27 bytes
{
cc2500_readFifo(pkt, len); //received telemetry packets
CC2500_ReadData(pkt, len); //received telemetry packets
#if defined(TELEMETRY)
//parse telemetry packet here
frsky_check_telemetry(pkt,len); //check if valid telemetry packets and buffer them.
@ -206,12 +206,12 @@ uint16_t ReadFrSky_2way()
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);
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);
CC2500_WriteData(packet, packet[0]+1);
state++;
}
return state == FRSKY_DATA4 ? 7500 : 9000;

View File

@ -0,0 +1,624 @@
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile
#
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
# Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# MCU name
MCU = atxmega32d4
# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
# automatically to create a 32-bit value in your source code.
# Typical values are:
# F_CPU = 1000000
# F_CPU = 1843200
# F_CPU = 2000000
# F_CPU = 3686400
# F_CPU = 4000000
# F_CPU = 7372800
# F_CPU = 8000000
# F_CPU = 11059200
# F_CPU = 14745600
# F_CPU = 16000000
# F_CPU = 18432000
# F_CPU = 20000000
F_CPU = 32000000
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Target file name (without extension).
TARGET = MultiOrange
# Object files directory
# To put object files in current directory, use a dot (.), do NOT make
# this an empty or blank macro!
OBJDIR = .
# List C source files here. (C dependencies are automatically generated.)
SRC =
# List C++ source files here. (C dependencies are automatically generated.)
CPPSRC = $(TARGET).cpp
CPPSRC += Wmath.cpp
#CPPSRC += DSM2_cyrf6936.cpp
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
# Debugging format.
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
# AVR Studio 4.10 requires dwarf-2.
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
#DEBUG = stabs
DEBUG = dwarf-2
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS =
# Compiler flag to set the C Standard level.
# c89 = "ANSI" C
# gnu89 = c89 plus GCC extensions
# c99 = ISO C99 standard (not yet fully implemented)
# gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL
# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)
# Place -D or -U options here for C++ sources
CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS
#---------------- Compiler Options C ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -Wall
CFLAGS += -Wno-main
CFLAGS += -Wstrict-prototypes
#CFLAGS += -mshort-calls
#CFLAGS += -fno-unit-at-a-time
#CFLAGS += -Wundef
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
CFLAGS += -Wa,-adlns=$(<:%.c=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
# Next line dumps rtl file
#CFLAGS += -dr
#CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
#---------------- Compiler Options C++ ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CPPFLAGS = -g$(DEBUG)
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
CPPFLAGS += -funsigned-char
CPPFLAGS += -funsigned-bitfields
CPPFLAGS += -fpack-struct
CPPFLAGS += -fshort-enums
CPPFLAGS += -fno-exceptions
CPPFLAGS += -Wall
CFLAGS += -Wundef
#CPPFLAGS += -mshort-calls
#CPPFLAGS += -fno-unit-at-a-time
#CPPFLAGS += -Wstrict-prototypes
#CPPFLAGS += -Wunreachable-code
#CPPFLAGS += -Wsign-compare
CPPFLAGS += -Wa,-adlns=$(<:%.cpp=$(OBJDIR)/%.lst)
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
#CPPFLAGS += $(CSTANDARD)
#CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
# dump that will be displayed for a given single line of source input.
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB =
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB =
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)
MATH_LIB = -lm
# List any extra directories to look for libraries here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRALIBDIRS =
#---------------- External Memory Options ----------------
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#LDFLAGS += -Wl,--section-start=.text=0x00D0
#LDFLAGS += -Wl,--section-start=.vectors=0x0080
#LDFLAGS += -T avr3-167.ld
LDFLAGS += -N
#---------------- Programming Options (avrdude) ----------------
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = stk500
# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = com3
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
#---------------- Debugging Options ----------------
# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)
# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight
# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr
# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit
# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1
# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242
# Debugging host used to communicate between GDB / avarice / simulavr, normally
# just set to localhost unless doing some sort of crazy debugging when
# avarice is running on a different computer.
DEBUG_HOST = localhost
#============================================================================
# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AR = avr-ar rcs
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
REMOVEDIR = rm -rf
COPY = cp
WINSHELL = cmd
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling C:
MSG_COMPILING_CPP = Compiling C++:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library:
# Define all object files.
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
# Define all listing files.
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: begin gccversion sizebefore build sizeafter end
# Change the build target to build a HEX file or a library.
build: elf hex eep lss sym bin
#build: lib
elf: $(TARGET).elf
hex: $(TARGET).hex
bin: $(TARGET).bin
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
LIBNAME=lib$(TARGET).a
lib: $(LIBNAME)
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
end:
@echo $(MSG_END)
@echo
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
sizebefore:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
2>/dev/null; echo; fi
sizeafter:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
2>/dev/null; echo; fi
# Display compiler version information.
gccversion :
@$(CC) --version
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
# Generate avr-gdb config/init file which does the following:
# define the reset signal, load the target file, connect to target, and set
# a breakpoint at main().
gdb-config:
@$(REMOVE) $(GDBINIT_FILE)
@echo define reset >> $(GDBINIT_FILE)
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
@echo end >> $(GDBINIT_FILE)
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
@echo load >> $(GDBINIT_FILE)
endif
@echo break main >> $(GDBINIT_FILE)
debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
@$(WINSHELL) /c pause
else
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT = $(OBJCOPY) --debugging
COFFCONVERT += --change-section-address .data-0x800000
COFFCONVERT += --change-section-address .bss-0x800000
COFFCONVERT += --change-section-address .noinit-0x800000
COFFCONVERT += --change-section-address .eeprom-0x810000
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
%.bin: %.elf
$(OBJCOPY) -O binary $< $@
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
$(NM) -n $< > $@
# Create library from object files.
.SECONDARY : $(TARGET).a
.PRECIOUS : $(OBJ)
%.a: $(OBJ)
@echo
@echo $(MSG_CREATING_LIBRARY) $@
$(AR) $@ $(OBJ)
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create object files from C++ source files.
$(OBJDIR)/%.o : %.cpp
@echo
@echo $(MSG_COMPILING_CPP) $<
$(CC) -c $(ALL_CPPFLAGS) $< -o $@
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C++ source files.
%.s : %.cpp
$(CC) -S $(ALL_CPPFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Create preprocessed source for use in sending a bug report.
%.i : %.c
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
# Target: clean project.
clean: begin clean_list end
clean_list :
@echo
@echo $(MSG_CLEANING)
$(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lss
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
$(REMOVE) $(SRC:.c=.i)
$(REMOVEDIR) .dep
# Create object files directory
$(shell mkdir $(OBJDIR) 2>/dev/null)
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config

View File

@ -0,0 +1,476 @@
#define ARDUINO_AVR_PRO 1
//#define __AVR_ATmega328P__ 1
#define XMEGA 1
#include <stdlib.h>
#include <string.h>
#include <avr/interrupt.h>
static void protocol_init(void) ;
static void update_aux_flags(void) ;
static void PPM_Telemetry_serial_init(void) ;
static uint32_t random_id(uint16_t adress, uint8_t create_new) ;
static void update_serial_data(void) ;
static void Mprotocol_serial_init(void) ;
static void module_reset(void) ;
static void update_led_status(void) ;
static void set_rx_tx_addr(uint32_t id) ;
uint16_t limit_channel_100(uint8_t ch) ;
extern void NRF24L01_Reset(void ) ;
extern void A7105_Reset(void ) ;
extern void CC2500_Reset(void ) ;
extern uint8_t CYRF_Reset(void ) ;
extern void CYRF_SetTxRxMode(uint8_t mode) ;
extern void frskyUpdate(void) ;
extern uint16_t initDsm2(void) ;
extern uint16_t ReadDsm2(void) ;
extern void randomSeed(unsigned int seed) ;
extern long random(long howbig) ;
extern long map(long x, long in_min, long in_max, long out_min, long out_max) ;
extern uint32_t millis(void) ;
extern uint32_t micros(void) ;
extern void delayMicroseconds(uint16_t x) ;
extern void init(void) ;
extern int analogRead(uint8_t pin) ;
#define A6 20
#define A7 21
#define yield()
//void _delay_us( uint16_t x )
//{
// delayMicroseconds( x ) ;
//}
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;
//void chipInit()
//{
// PR.PRGEN = 0 ; // RTC and event system active
// PR.PRPC = 0 ; // No power reduction port C
// PR.PRPD = 0 ; // No power reduction port D
// PMIC.CTRL = 7 ;
// OSC.CTRL = 0xC3 ; // unclear
// OSC.CTRL |= 0x08 ; // Enable external oscillator
// while( ( OSC.STATUS & 0x08 ) == 0 ) ; // Wait for ext osc to be ready
// OSC.PLLCTRL = 0xC2 ; // Ext. Osc times 2
// OSC.CTRL |= 0x10 ; // Enable PLL
// while( ( OSC.STATUS & 0x10 ) == 0 ) ; // Wait PLL ready
// CPU_CCP = 0xD8 ; // 0x34
// CLK.CTRL = 0 ; // Select 2MHz internal clock
// CPU_CCP = 0xD8 ; // 0x34
// CLK.CTRL = 0x04 ; // Select PLL as clock (32MHz)
// PORTD.OUTSET = 0x17 ;
// PORTD.DIRSET = 0xB2 ;
// PORTD.DIRCLR = 0x4D ;
// PORTD.PIN0CTRL = 0x18 ;
// PORTD.PIN2CTRL = 0x18 ;
// PORTE.DIRSET = 0x01 ;
// PORTE.DIRCLR = 0x02 ;
// PORTE.OUTSET = 0x01 ;
// PORTA.DIRCLR = 0xFF ;
// PORTA.PIN0CTRL = 0x18 ;
// PORTA.PIN1CTRL = 0x18 ;
// PORTA.PIN2CTRL = 0x18 ;
// PORTA.PIN3CTRL = 0x18 ;
// PORTA.PIN4CTRL = 0x18 ;
// PORTA.PIN5CTRL = 0x18 ;
// PORTA.PIN6CTRL = 0x18 ;
// PORTA.PIN7CTRL = 0x18 ;
// PORTC.DIRSET = 0x20 ;
// PORTC.OUTCLR = 0x20 ;
// SPID.CTRL = 0x51 ;
// PORTC.OUTSET = 0x08 ;
// PORTC.DIRSET = 0x08 ;
// PORTC.PIN3CTRL = 0x18 ;
// PORTC.PIN2CTRL = 0x18 ;
// USARTC0.BAUDCTRLA = 19 ;
// USARTC0.BAUDCTRLB = 0 ;
// USARTC0.CTRLB = 0x18 ;
// USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
// USARTC0.CTRLC = 0x03 ;
// TCC0.CTRLB = 0 ;
// TCC0.CTRLC = 0 ;
// TCC0.CTRLD = 0 ;
// TCC0.CTRLE = 0 ;
// TCC0.INTCTRLA = 0x01 ;
// TCC0.INTCTRLB = 0 ;
// TCC0.PER = 0x00FF ;
// TCC0.CTRLA = 4 ;
// TCC1.CTRLB = 0 ;
// TCC1.CTRLC = 0 ;
// TCC1.CTRLD = 0 ;
// TCC1.CTRLE = 0 ;
// TCC1.INTCTRLA = 0x03 ;
// TCC1.INTCTRLB = 0 ;
// TCC1.PER = 0xFFFF ;
// TCC1.CNT = 0 ;
// TCC1.CTRLA = 4 ;
// TCD0.CTRLA = 4 ;
// TCD0.INTCTRLA = 0x03 ;
// TCD0.PER = 0x02ED ;
//// L0EDB() ;
// NVM.CTRLB &= 0xF7 ; // No EEPROM mapping
//}
ISR(TCC0_OVF_vect)
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}
timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
unsigned long micros()
{
unsigned long m;
uint8_t oldSREG = SREG, t;
cli();
m = timer0_overflow_count;
t = TCC0.CNT ;
if ((TCC0.INTFLAGS & TC0_OVFIF_bm) && (t < 255))
m++;
SREG = oldSREG;
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}
void delay(unsigned long ms)
{
uint16_t start = (uint16_t)micros();
while (ms > 0) {
yield();
if (((uint16_t)micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */
void delayMicroseconds(unsigned int us)
{
// calling avrlib's delay_us() function with low values (e.g. 1 or
// 2 microseconds) gives delays longer than desired.
//delay_us(us);
#if F_CPU >= 20000000L
// for the 20 MHz clock on rare Arduino boards
// for a one-microsecond delay, simply wait 2 cycle and return. The overhead
// of the function call yields a delay of exactly a one microsecond.
__asm__ __volatile__ (
"nop" "\n\t"
"nop"); //just waiting 2 cycle
if (--us == 0)
return;
// the following loop takes a 1/5 of a microsecond (4 cycles)
// per iteration, so execute it five times for each microsecond of
// delay requested.
us = (us<<2) + us; // x5 us
// account for the time taken in the preceeding commands.
us -= 2;
#elif F_CPU >= 16000000L
// for the 16 MHz clock on most Arduino boards
// for a one-microsecond delay, simply return. the overhead
// of the function call yields a delay of approximately 1 1/8 us.
if (--us == 0)
return;
// the following loop takes a quarter of a microsecond (4 cycles)
// per iteration, so execute it four times for each microsecond of
// delay requested.
us <<= 2;
// account for the time taken in the preceeding commands.
us -= 2;
#else
// for the 8 MHz internal clock on the ATmega168
// for a one- or two-microsecond delay, simply return. the overhead of
// the function calls takes more than two microseconds. can't just
// subtract two, since us is unsigned; we'd overflow.
if (--us == 0)
return;
if (--us == 0)
return;
// the following loop takes half of a microsecond (4 cycles)
// per iteration, so execute it twice for each microsecond of
// delay requested.
us <<= 1;
// partially compensate for the time taken by the preceeding commands.
// we can't subtract any more than this or we'd overflow w/ small delays.
us--;
#endif
// busy wait
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t" // 2 cycles
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
);
}
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
void init()
{
// this needs to be called before setup() or some functions won't
// work there
// Enable external oscillator (16MHz)
OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_256CLK_gc ;
OSC.CTRL |= OSC_XOSCEN_bm ;
while( ( OSC.STATUS & OSC_XOSCRDY_bm ) == 0 )
/* wait */ ;
// Enable PLL (*2 = 32MHz)
OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 2 ;
OSC.CTRL |= OSC_PLLEN_bm ;
while( ( OSC.STATUS & OSC_PLLRDY_bm ) == 0 )
/* wait */ ;
// Switch to PLL clock
CPU_CCP = 0xD8 ;
CLK.CTRL = CLK_SCLKSEL_RC2M_gc ;
CPU_CCP = 0xD8 ;
CLK.CTRL = CLK_SCLKSEL_PLL_gc ;
PMIC.CTRL = 7 ; // Enable all interrupt levels
sei();
// on the ATmega168, timer 0 is also used for fast hardware pwm
// (using phase-correct PWM would mean that timer 0 overflowed half as often
// resulting in different millis() behavior on the ATmega8 and ATmega168)
//#if defined(TCCR0A) && defined(WGM01)
// sbi(TCCR0A, WGM01);
// sbi(TCCR0A, WGM00);
//#endif
// TCC0 counts 0-255 at 4uS clock rate
EVSYS.CH2MUX = 0x80 + 0x07 ; // Prescaler of 128
TCC0.CTRLB = 0 ;
TCC0.CTRLC = 0 ;
TCC0.CTRLD = 0 ;
TCC0.CTRLE = 0 ;
TCC0.INTCTRLA = 0x01 ;
TCC0.INTCTRLB = 0 ;
TCC0.PER = 0x00FF ;
TCC0.CTRLA = 0x0A ;
#if defined(ADCSRA)
// set a2d prescale factor to 128
// 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
// XXX: this will not work properly for other clock speeds, and
// this code should use F_CPU to determine the prescale factor.
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
// enable a2d conversions
sbi(ADCSRA, ADEN);
#endif
// the bootloader connects pins 0 and 1 to the USART; disconnect them
// here so they can be used as normal digital i/o; they will be
// reconnected in Serial.begin()
#if defined(UCSRB)
UCSRB = 0;
#elif defined(UCSR0B)
UCSR0B = 0;
#endif
// PPM interrupt
PORTD.DIRCLR = 0x08 ; // D3 is input
PORTD.PIN3CTRL = 0x01 ; // Rising edge
PORTD.INT0MASK = 0x08 ;
PORTD.INTCTRL = 0x02 ; // Medium level interrupt
// Dip Switch inputs
PORTA.DIRCLR = 0xFF ;
PORTA.PIN0CTRL = 0x18 ;
PORTA.PIN1CTRL = 0x18 ;
PORTA.PIN2CTRL = 0x18 ;
PORTA.PIN3CTRL = 0x18 ;
PORTA.PIN4CTRL = 0x18 ;
PORTA.PIN5CTRL = 0x18 ;
PORTA.PIN6CTRL = 0x18 ;
PORTA.PIN7CTRL = 0x18 ;
}
#define DEFAULT 1
uint8_t analog_reference = DEFAULT;
void analogReference(uint8_t mode)
{
// can't actually set the register here because the default setting
// will connect AVCC and the AREF pin, which would cause a short if
// there's something connected to AREF.
analog_reference = mode;
}
int analogRead(uint8_t pin)
{
uint8_t low, high;
#if defined(analogPinToChannel)
#if defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#endif
pin = analogPinToChannel(pin);
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
if (pin >= 24) pin -= 24; // allow for channel or pin numbers
#else
if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif
#if defined(ADCSRB) && defined(MUX5)
// the MUX5 bit of ADCSRB selects whether we're reading from channels
// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits). this also sets ADLAR (left-adjust result)
// to 0 (the default).
#if defined(ADMUX)
ADMUX = (analog_reference << 6) | (pin & 0x07);
#endif
// without a delay, we seem to read from the wrong channel
//delay(1);
#if defined(ADCSRA) && defined(ADCL)
// start the conversion
sbi(ADCSRA, ADSC);
// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));
// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
low = ADCL;
high = ADCH;
#else
// we dont have an ADC, return 0
low = 0;
high = 0;
#endif
// combine the two bytes
return (high << 8) | low;
}
void A7105_Reset()
{
}
void CC2500_Reset()
{
}
void NRF24L01_Reset()
{
}
#include "Multiprotocol.ino"
#include "cyrf6936_SPI.ino"
#include "DSM2_cyrf6936.ino"
#include "Telemetry.ino"
int main(void)
{
init() ;
setup() ;
for(;;)
{
loop() ;
}
}

View File

@ -14,12 +14,14 @@
*/
// Check selected board type
#ifndef XMEGA
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_AVR_MINI)
#error You must select the board type "Arduino Pro or Pro Mini" or "Arduino Mini"
#endif
#if F_CPU != 16000000L || not defined(__AVR_ATmega328P__)
#error You must select the processor type "ATmega328(5V, 16MHz)"
#endif
#endif
//******************
// Protocols
@ -46,7 +48,8 @@ enum PROTOCOLS
MODE_MT99XX=17, // =>NRF24L01
MODE_MJXQ=18, // =>NRF24L01
MODE_SHENQI=19, // =>NRF24L01
MODE_FY326=20 // =>NRF24L01
MODE_FY326=20, // =>NRF24L01
MODE_SFHSS=21 // =>CC2500
};
enum Flysky
@ -114,6 +117,12 @@ enum MJXQ
H26D = 3
};
enum FRSKYX
{
CH_16 = 0,
CH_8 = 1,
};
#define NONE 0
#define P_HIGH 1
#define P_LOW 0
@ -137,7 +146,11 @@ struct PPM_Parameters
#define LED_pin 13 //Promini original led on B5
//
#define PPM_pin 3 //PPM -D3
#ifdef XMEGA
#define SDI_pin 6 //SDIO-D6
#else
#define SDI_pin 5 //SDIO-D5
#endif
#define SCLK_pin 4 //SCK-D4
#define CS_pin 2 //CS-D2
#define SDO_pin 6 //D6
@ -145,23 +158,51 @@ struct PPM_Parameters
#define CTRL1 1 //C1 (A1)
#define CTRL2 2 //C2 (A2)
//
#ifdef XMEGA
#define CTRL1_on
#define CTRL1_off
//
#define CTRL2_on
#define CTRL2_off
#else
#define CTRL1_on PORTC |= _BV(1)
#define CTRL1_off PORTC &= ~_BV(1)
//
#define CTRL2_on PORTC |= _BV(2)
#define CTRL2_off PORTC &= ~_BV(2)
#endif
//
#ifdef XMEGA
#define CS_on PORTD.OUTSET = _BV(4) //D4
#define CS_off PORTD.OUTCLR = _BV(4) //D4
#else
#define CS_on PORTD |= _BV(2) //D2
#define CS_off PORTD &= ~_BV(2) //D2
#endif
//
#ifdef XMEGA
#define SCK_on PORTD.OUTSET = _BV(7) //D7
#define SCK_off PORTD.OUTCLR = _BV(7) //D7
#else
#define SCK_on PORTD |= _BV(4) //D4
#define SCK_off PORTD &= ~_BV(4) //D4
#endif
//
#ifdef XMEGA
#define SDI_on PORTD.OUTSET = _BV(5) //D5
#define SDI_off PORTD.OUTCLR = _BV(5) //D5
#else
#define SDI_on PORTD |= _BV(5) //D5
#define SDI_off PORTD &= ~_BV(5) //D5
#endif
#ifdef XMEGA
#define SDI_1 (PORTD.IN & (1<<SDI_pin)) == (1<<SDI_pin) //D5
#define SDI_0 (PORTD.IN & (1<<SDI_pin)) == 0x00 //D5
#else
#define SDI_1 (PIND & (1<<SDI_pin)) == (1<<SDI_pin) //D5
#define SDI_0 (PIND & (1<<SDI_pin)) == 0x00 //D5
#endif
//
#define SDI_SET_INPUT DDRD &= ~_BV(5) //D5
#define SDI_SET_OUTPUT DDRD |= _BV(5) //D5
@ -172,17 +213,37 @@ struct PPM_Parameters
//
#define CYRF_RST_pin A5 //reset pin
//
#ifdef XMEGA
#define CC25_CSN_on PORTD.OUTSET = _BV(7) //D7
#define CC25_CSN_off PORTD.OUTCLR = _BV(7) //D7
#else
#define CC25_CSN_on PORTD |= _BV(7) //D7
#define CC25_CSN_off PORTD &= ~_BV(7) //D7
#endif
//
#ifdef XMEGA
#define NRF_CSN_on
#define NRF_CSN_off
#else
#define NRF_CSN_on PORTB |= _BV(0) //D8
#define NRF_CSN_off PORTB &= ~_BV(0) //D8
#endif
//
#ifdef XMEGA
#define CYRF_CSN_on PORTD.OUTSET = _BV(4) //D9
#define CYRF_CSN_off PORTD.OUTCLR = _BV(4) //D9
#else
#define CYRF_CSN_on PORTB |= _BV(1) //D9
#define CYRF_CSN_off PORTB &= ~_BV(1) //D9
#endif
//
#ifdef XMEGA
#define SDO_1 (PORTD.IN & (1<<SDO_pin)) == (1<<SDO_pin) //D6
#define SDO_0 (PORTD.IN & (1<<SDO_pin)) == 0x00 //D6
#else
#define SDO_1 (PIND & (1<<SDO_pin)) == (1<<SDO_pin) //D6
#define SDO_0 (PIND & (1<<SDO_pin)) == 0x00 //D6
#endif
//
#define RS_HI PORTC|=_BV(5) //reset pin cyrf
#define RX_LO PORTB &= ~_BV(5)//
@ -190,11 +251,25 @@ struct PPM_Parameters
//
// LED
#ifdef XMEGA
#define LED_ON PORTD.OUTCLR = _BV(1)
#define LED_OFF PORTD.OUTSET = _BV(1)
#define LED_TOGGLE PORTD.OUTTGL = _BV(1)
#define LED_SET_OUTPUT PORTD.DIRSET = _BV(1)
#define IS_LED_on ( (PORTD.OUT & _BV(1)) != 0x00 )
#else
#define LED_ON PORTB |= _BV(5)
#define LED_OFF PORTB &= ~_BV(5)
#define LED_TOGGLE PORTB ^= _BV(5)
#define LED_SET_OUTPUT DDRB |= _BV(5)
#define IS_LED_on ( (PORTB & _BV(5)) != 0x00 )
#endif
// TX
#define TX_ON PORTD |= _BV(1)
#define TX_OFF PORTD &= ~_BV(1)
#define TX_TOGGLE PORTD ^= _BV(1)
#define TX_SET_OUTPUT DDRD |= _BV(1)
// Macros
#define NOP() __asm__ __volatile__("nop")
@ -283,10 +358,10 @@ enum A7105_POWER
A7105_POWER_6 = 0x03<<3 | 0x07, // TXPOWER_100mW = 1dBm == PAC=3 TBG=7
A7105_POWER_7 = 0x03<<3 | 0x07 // TXPOWER_150mW = 1dBm == PAC=3 TBG=7
};
#define A7105_HIGH_POWER A7105_POWER_5
#define A7105_HIGH_POWER A7105_POWER_7
#define A7105_LOW_POWER A7105_POWER_3
#define A7105_BIND_POWER A7105_POWER_0
#define A7105_RANGE_POWER A7105_POWER_0
#define A7105_BIND_POWER A7105_POWER_0
// NRF Power
// Power setting is 0..3 for nRF24L01
@ -300,8 +375,8 @@ enum NRF_POWER
};
#define NRF_HIGH_POWER NRF_POWER_2
#define NRF_LOW_POWER NRF_POWER_1
#define NRF_BIND_POWER NRF_POWER_0
#define NRF_RANGE_POWER NRF_POWER_0
#define NRF_BIND_POWER NRF_POWER_0
// CC2500 power
enum CC2500_POWER
@ -318,8 +393,8 @@ enum CC2500_POWER
};
#define CC2500_HIGH_POWER CC2500_POWER_6
#define CC2500_LOW_POWER CC2500_POWER_3
#define CC2500_BIND_POWER CC2500_POWER_0
#define CC2500_RANGE_POWER CC2500_POWER_0
#define CC2500_BIND_POWER CC2500_POWER_0
// CYRF power
enum CYRF_POWER
@ -335,8 +410,8 @@ enum CYRF_POWER
};
#define CYRF_HIGH_POWER CYRF_POWER_7
#define CYRF_LOW_POWER CYRF_POWER_3
#define CYRF_RANGE_POWER CYRF_POWER_1
#define CYRF_BIND_POWER CYRF_POWER_0
#define CYRF_RANGE_POWER CYRF_POWER_0
enum TXRX_State {
TXRX_OFF,
@ -424,6 +499,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
MJXQ 18
SHENQI 19
FY326 20
SFHSS 21
BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No
@ -475,6 +551,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
X600 1
X800 2
H26D 3
sub_protocol==FRSKYX
CH_16 0
CH_8 1
Power value => 0x80 0=High/1=Low
Stream[3] = option_protocol;
option_protocol value is -127..127

View File

@ -4,7 +4,7 @@
http://www.rcgroups.com/forums/showthread.php?t=2165676
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/edit/master/README.md
Thanks to PhracturedBlue, Hexfet, Goebish and all protocol developers
Thanks to PhracturedBlue, Hexfet, Goebish, Victzh and all protocol developers
Ported from deviation firmware
This project is free software: you can redistribute it and/or modify
@ -25,6 +25,8 @@
#include <util/delay.h>
#include "Multiprotocol.h"
//#define DEBUG_TX
//Multiprotocol module configuration file
#include "_Config.h"
@ -68,6 +70,10 @@ uint32_t state;
uint8_t len;
uint8_t RX_num;
#if defined(FRSKYX_CC2500_INO) || defined(SFHSS_CC2500_INO)
uint8_t calData[48][3];
#endif
// Mode_select variables
uint8_t mode_select;
uint8_t protocol_flags=0,protocol_flags2=0;
@ -77,7 +83,7 @@ volatile uint16_t PPM_data[NUM_CHN];
// Serial variables
#define RXBUFFER_SIZE 25
#define TXBUFFER_SIZE 12
#define TXBUFFER_SIZE 20
volatile uint8_t rx_buff[RXBUFFER_SIZE];
volatile uint8_t rx_ok_buff[RXBUFFER_SIZE];
volatile uint8_t tx_buff[TXBUFFER_SIZE];
@ -94,8 +100,8 @@ uint8_t prev_protocol=0;
uint8_t pkt[MAX_PKT];//telemetry receiving packets
#if defined(TELEMETRY)
uint8_t pktt[MAX_PKT];//telemetry receiving packets
volatile uint8_t tx_head;
volatile uint8_t tx_tail;
volatile uint8_t tx_head=0;
volatile uint8_t tx_tail=0;
uint8_t v_lipo;
int16_t RSSI_dBm;
//const uint8_t RSSI_offset=72;//69 71.72 values db
@ -111,6 +117,20 @@ static void CheckTimer(uint16_t (*cb)(void));
// Init
void setup()
{
#ifdef XMEGA
PORTD.OUTSET = 0x17 ;
PORTD.DIRSET = 0xB2 ;
PORTD.DIRCLR = 0x4D ;
PORTD.PIN0CTRL = 0x18 ;
PORTD.PIN2CTRL = 0x18 ;
PORTE.DIRSET = 0x01 ;
PORTE.DIRCLR = 0x02 ;
PORTE.OUTSET = 0x01 ;
for ( uint8_t count = 0 ; count < 20 ; count += 1 )
asm("nop") ;
PORTE.OUTCLR = 0x01 ;
#else
// General pinout
DDRD = (1<<CS_pin)|(1<<SDI_pin)|(1<<SCLK_pin)|(1<<CS_pin)|(1<< CC25_CSN_pin);
DDRC = (1<<CTRL1)|(1<<CTRL2); //output
@ -118,6 +138,7 @@ void setup()
DDRB = _BV(0)|_BV(1);
PORTB = _BV(2)|_BV(3)|_BV(4)|_BV(5);//pullup 10,11,12 and bind button
PORTC = _BV(0);//A0 high pullup
#endif
// Set Chip selects
CS_on;
@ -128,9 +149,24 @@ void setup()
SDI_on;
SCK_off;
//#ifdef XMEGA
// // SPI enable, master, prescale of 16
// SPID.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_PRESCALER0_bm ;
//#endif
// Timer1 config
#ifdef XMEGA
// TCC1 16-bit timer, clocked at 0.5uS
EVSYS.CH3MUX = 0x80 + 0x04 ; // Prescaler of 16
TCC1.CTRLB = 0; TCC1.CTRLC = 0; TCC1.CTRLD = 0; TCC1.CTRLE = 0;
TCC1.INTCTRLA = 0; TCC1.INTCTRLB = 0;
TCC1.PER = 0xFFFF ;
TCC1.CNT = 0 ;
TCC1.CTRLA = 0x0B ; // Event3 (prescale of 16)
#else
TCCR1A = 0;
TCCR1B = (1 << CS11); //prescaler8, set timer1 to increment every 0.5us(16Mhz) and start timer
#endif
// Set servos positions
for(uint8_t i=0;i<NUM_CHN;i++)
@ -142,12 +178,21 @@ void setup()
delay(100);
// Read status of bind button
#ifdef XMEGA
if( (PORTD.IN & _BV(2)) == 0x00 )
#else
if( (PINB & _BV(5)) == 0x00 )
#endif
BIND_BUTTON_FLAG_on; // If bind button pressed save the status for protocol id reset under hubsan
// Read status of mode select binary switch
// after this mode_select will be one of {0000, 0001, ..., 1111}
#ifdef XMEGA
mode_select=0x0F - ( PORTA.IN & 0x0F ) ; //encoder dip switches 1,2,4,8=>B2,B3,B4,C0
mode_select = MODE_SERIAL ;
#else
mode_select=0x0F - ( ( (PINB>>2)&0x07 ) | ( (PINC<<3)&0x08) );//encoder dip switches 1,2,4,8=>B2,B3,B4,C0
#endif
//**********************************
//mode_select=1; // here to test PPM
//**********************************
@ -179,9 +224,12 @@ void setup()
protocol_init();
#ifndef XMEGA
//Configure PPM interrupt
EICRA |=(1<<ISC11); // The rising edge of INT1 pin D3 generates an interrupt request
EIMSK |= (1<<INT1); // INT1 interrupt enable
#endif
#if defined(TELEMETRY)
PPM_Telemetry_serial_init(); // Configure serial for telemetry
#endif
@ -223,7 +271,7 @@ void loop()
}
update_led_status();
#if defined(TELEMETRY)
if( ((cur_protocol[0]&0x1F)==MODE_FRSKY) || ((cur_protocol[0]&0x1F)==MODE_HUBSAN) || ((cur_protocol[0]&0x1F)==MODE_FRSKYX) )
if( ((cur_protocol[0]&0x1F)==MODE_FRSKY) || ((cur_protocol[0]&0x1F)==MODE_HUBSAN) || ((cur_protocol[0]&0x1F)==MODE_FRSKYX) || ((cur_protocol[0]&0x1F)==MODE_DSM2) )
frskyUpdate();
#endif
if (remote_callback != 0)
@ -266,8 +314,17 @@ static void update_led_status(void)
// Protocol scheduler
static void CheckTimer(uint16_t (*cb)(void))
{
uint16_t next_callback;
uint32_t prev;
uint16_t next_callback,diff;
#ifdef XMEGA
if( (TCC1.INTFLAGS & TC1_CCAIF_bm) != 0)
{
cli(); // disable global int
TCC1.CCA = TCC1.CNT ; // Callback should already have been called... Use "now" as new sync point.
sei(); // enable global int
}
else
while((TCC1.INTFLAGS & TC1_CCAIF_bm) == 0); // wait before callback
#else
if( (TIFR1 & (1<<OCF1A)) != 0)
{
cli(); // disable global int
@ -276,25 +333,42 @@ static void CheckTimer(uint16_t (*cb)(void))
}
else
while((TIFR1 & (1<<OCF1A)) == 0); // wait before callback
prev=micros();
next_callback=cb();
if(prev+next_callback+50 > micros())
{ // Callback did not took more than requested time for next callback
if(next_callback>32000)
{ // next_callback should not be more than 32767 so we will wait here...
delayMicroseconds(next_callback-2000);
cli(); // disable global int
OCR1A=TCNT1+4000;
sei(); // enable global int
#endif
do
{
next_callback=cb();
while(next_callback>4000)
{ // start to wait here as much as we can...
next_callback=next_callback-2000;
cli(); // disable global int
#ifdef XMEGA
TCC1.CCA +=2000*2; // set compare A for callback
TCC1.INTFLAGS = TC1_CCAIF_bm ; // clear compare A=callback flag
sei(); // enable global int
while((TCC1.INTFLAGS & TC1_CCAIF_bm) == 0); // wait 2ms...
#else
OCR1A+=2000*2; // set compare A for callback
TIFR1=(1<<OCF1A); // clear compare A=callback flag
sei(); // enable global int
while((TIFR1 & (1<<OCF1A)) == 0); // wait 2ms...
#endif
}
else
{
cli(); // disable global int
OCR1A+=next_callback*2; // set compare A for callback
sei(); // enable global int
}
TIFR1=(1<<OCF1A); // clear compare A=callback flag
// at this point we have between 2ms and 4ms in next_callback
cli(); // disable global int
#ifdef XMEGA
TCC1.CCA +=next_callback*2; // set compare A for callback
TCC1.INTFLAGS = TC1_CCAIF_bm ; // clear compare A=callback flag
diff=TCC1.CCA-TCC1.CNT; // compare timer and comparator
sei(); // enable global int
#else
OCR1A+=next_callback*2; // set compare A for callback
TIFR1=(1<<OCF1A); // clear compare A=callback flag
diff=OCR1A-TCNT1; // compare timer and comparator
sei(); // enable global int
#endif
}
while(diff&0x8000); // Callback did not took more than requested time for next callback
// so we can let main do its stuff before next callback
}
// Protocol start
@ -348,6 +422,14 @@ static void protocol_init()
remote_callback = ReadFrSkyX;
break;
#endif
#if defined(SFHSS_CC2500_INO)
case MODE_SFHSS:
CTRL1_off; //antenna RF2
CTRL2_on;
next_callback = initSFHSS();
remote_callback = ReadSFHSS;
break;
#endif
#if defined(DSM2_CYRF6936_INO)
case MODE_DSM2:
CTRL2_on; //antenna RF4
@ -455,9 +537,15 @@ static void protocol_init()
next_callback=2000;
}
cli(); // disable global int
#ifdef XMEGA
TCC1.CCA = TCC1.CNT + next_callback*2; // set compare A for callback
sei(); // enable global int
TCC1.INTFLAGS = TC1_CCAIF_bm ; // clear compare A flag
#else
OCR1A=TCNT1+next_callback*2; // set compare A for callback
sei(); // enable global int
TIFR1=(1<<OCF1A); // clear compare A flag
#endif
BIND_BUTTON_FLAG_off; // do not bind/reset id anymore even if protocol change
}
@ -522,6 +610,7 @@ static void module_reset()
break;
case MODE_FRSKY:
case MODE_FRSKYX:
case MODE_SFHSS:
CC2500_Reset();
break;
case MODE_DSM2:
@ -593,13 +682,31 @@ void Serial_write(uint8_t data)
if(++tx_head>=TXBUFFER_SIZE)
tx_head=0;
tx_buff[tx_head]=data;
sei(); // enable global int
#ifdef XMEGA
USARTC0.CTRLA = (USARTC0.CTRLA & 0xFC) | 0x01 ;
#else
UCSR0B |= (1<<UDRIE0);//enable UDRE interrupt
#endif
sei(); // enable global int
}
#endif
static void Mprotocol_serial_init()
{
#ifdef XMEGA
PORTC.OUTSET = 0x08 ;
PORTC.DIRSET = 0x08 ;
USARTC0.BAUDCTRLA = 19 ;
USARTC0.BAUDCTRLB = 0 ;
USARTC0.CTRLB = 0x18 ;
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
USARTC0.CTRLC = 0x2B ;
USARTC0.DATA ;
#else
#include <util/setbaud.h>
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
@ -610,12 +717,25 @@ static void Mprotocol_serial_init()
UDR0;
//enable reception and RC complete interrupt
UCSR0B = (1<<RXEN0)|(1<<RXCIE0);//rx enable and interrupt
#ifdef DEBUG_TX
TX_SET_OUTPUT;
#else
UCSR0B |= (1<<TXEN0);//tx enable
#endif
#endif
}
#if defined(TELEMETRY)
static void PPM_Telemetry_serial_init()
{
#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;
@ -623,6 +743,7 @@ static void PPM_Telemetry_serial_init()
//Set frame format to 8 data bits, none, 1 stop bit
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
UCSR0B = (1<<TXEN0);//tx enable
#endif
}
#endif
@ -668,13 +789,21 @@ static uint32_t random_id(uint16_t adress, uint8_t create_new)
/**************************/
//PPM
#ifdef XMEGA
ISR(PORTD_INT0_vect)
#else
ISR(INT1_vect)
#endif
{ // Interrupt on PPM pin
static int8_t chan=-1;
static uint16_t Prev_TCNT1=0;
uint16_t Cur_TCNT1;
#ifdef XMEGA
Cur_TCNT1 = TCC1.CNT - Prev_TCNT1 ; // Capture current Timer1 value
#else
Cur_TCNT1=TCNT1-Prev_TCNT1; // Capture current Timer1 value
#endif
if(Cur_TCNT1<1000)
chan=-1; // bad frame
else
@ -697,62 +826,107 @@ ISR(INT1_vect)
}
//Serial RX
#ifdef XMEGA
ISR(USARTC0_RXC_vect)
#else
ISR(USART_RX_vect)
#endif
{ // RX interrupt
#ifdef XMEGA
if((USARTC0.STATUS & 0x1C)==0) // Check frame error, data overrun and parity error
#else
if((UCSR0A&0x1C)==0) // Check frame error, data overrun and parity error
#endif
{ // received byte is ok to process
if(idx==0)
{ // Let's try to sync at this point
#ifdef XMEGA
if(USARTC0.DATA==0x55) // If 1st byte is 0x55 it looks ok
#else
if(UDR0==0x55) // If 1st byte is 0x55 it looks ok
#endif
{
idx++;
#ifdef XMEGA
TCC1.CCB = TCC1.CNT+(6500L) ; // Full message should be received within timer of 3250us
TCC1.INTFLAGS = TC1_CCBIF_bm ; // clear OCR1B match flag
TCC1.INTCTRLB = (TCC1.INTCTRLB & 0xF3) | 0x04 ; // enable interrupt on compare B match
#else
OCR1B=TCNT1+6500L; // Full message should be received within timer of 3250us
TIFR1=(1<<OCF1B); // clear OCR1B match flag
TIMSK1 |=(1<<OCIE1B); // enable interrupt on compare B match
#endif
}
}
else
{
rx_buff[(idx++)-1]=UDR0; // Store received byte
#ifdef XMEGA
rx_buff[(idx++)-1]=USARTC0.DATA; // Store received byte
#else
rx_buff[(idx++)-1]=UDR0; // Store received byte
#endif
if(idx>RXBUFFER_SIZE)
{ // A full frame has been received
TIMSK1 &=~(1<<OCIE1B); // disable interrupt on compare B match
#ifdef XMEGA
TCC1.INTCTRLB &=0xF3; // disable interrupt on compare B match
#else
TIMSK1 &=~(1<<OCIE1B); // disable interrupt on compare B match
#endif
if(!IS_RX_FLAG_on)
{ //Good frame received and main has finished with previous buffer
for(idx=0;idx<RXBUFFER_SIZE;idx++)
rx_ok_buff[idx]=rx_buff[idx]; // Duplicate the buffer
RX_FLAG_on; //flag for main to process servo data
RX_FLAG_on; // flag for main to process servo data
}
idx=0; // start again
idx=0; // start again
}
}
}
else
{
#ifdef XMEGA
idx = USARTC0.DATA ; // Dummy read
#else
idx=UDR0; // Dummy read
#endif
idx=0; // Error encountered discard full frame...
}
}
//Serial timer
#ifdef XMEGA
ISR(TCC1_CCB_vect)
#else
ISR(TIMER1_COMPB_vect)
#endif
{ // Timer1 compare B interrupt
idx=0;
}
#if defined(TELEMETRY)
//Serial TX
#ifdef XMEGA
ISR(USARTC0_DRE_vect)
#else
ISR(USART_UDRE_vect)
#endif
{ // Transmit interrupt
uint8_t t = tx_tail;
if(tx_head!=t)
if(tx_head!=tx_tail)
{
if(++t>=TXBUFFER_SIZE)//head
t=0;
UDR0=tx_buff[t];
tx_tail=t;
if(++tx_tail>=TXBUFFER_SIZE)//head
tx_tail=0;
#ifdef XMEGA
USARTC0.DATA = tx_buff[tx_tail] ;
#else
UDR0=tx_buff[tx_tail];
#endif
}
if (t == tx_head)
if (tx_tail == tx_head)
#ifdef XMEGA
USARTC0.CTRLA &= ~0x03 ;
#else
UCSR0B &= ~(1<<UDRIE0); // Check if all data is transmitted . if yes disable transmitter UDRE interrupt
#endif
}
#endif

View File

@ -0,0 +1,265 @@
/*
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 main deviation/sfhss_cc2500.c dated 2016-03-23
#if defined(SFHSS_CC2500_INO)
#include "iface_cc2500.h"
//#define SFHSS_USE_TUNE_FREQ
#define SFHSS_COARSE 0
#define SFHSS_PACKET_LEN 13
#define SFHSS_TX_ID_LEN 2
uint8_t fhss_code; // 0-27
enum {
SFHSS_START = 0x101,
SFHSS_CAL = 0x102,
SFHSS_TUNE = 0x103,
SFHSS_DATA1 = 0x02,
SFHSS_DATA2 = 0x0b
};
#define SFHSS_FREQ0_VAL 0xC4
// Some important initialization parameters, all others are either default,
// or not important in the context of transmitter
// IOCFG2 2F - GDO2_INV=0 GDO2_CFG=2F - HW0
// IOCFG1 2E - GDO1_INV=0 GDO1_CFG=2E - High Impedance
// IOCFG0 2F - GDO0 same as GDO2, TEMP_SENSOR_ENABLE=off
// FIFOTHR 07 - 33 decimal TX threshold
// SYNC1 D3
// SYNC0 91
// PKTLEN 0D - Packet length, 0D bytes
// PKTCTRL1 04 - APPEND_STATUS on, all other are receive parameters - irrelevant
// PKTCTRL0 0C - No whitening, use FIFO, CC2400 compatibility on, use CRC, fixed packet length
// ADDR 29
// CHANNR 10
// FSCTRL1 06 - IF 152343.75Hz, see page 65
// FSCTRL0 00 - zero freq offset
// FREQ2 5C - synthesizer frequency 2399999633Hz for 26MHz crystal, ibid
// FREQ1 4E
// FREQ0 C4
// MDMCFG4 7C - CHANBW_E - 01, CHANBW_M - 03, DRATE_E - 0C. Filter bandwidth = 232142Hz
// MDMCFG3 43 - DRATE_M - 43. Data rate = 128143bps
// MDMCFG2 83 - disable DC blocking, 2-FSK, no Manchester code, 15/16 sync bits detected (irrelevant for TX)
// MDMCFG1 23 - no FEC, 4 preamble bytes, CHANSPC_E - 03
// MDMCFG0 3B - CHANSPC_M - 3B. Channel spacing = 249938Hz (each 6th channel used, resulting in spacing of 1499628Hz)
// DEVIATN 44 - DEVIATION_E - 04, DEVIATION_M - 04. Deviation = 38085.9Hz
// MCSM2 07 - receive parameters, default, irrelevant
// MCSM1 0C - no CCA (transmit always), when packet received stay in RX, when sent go to IDLE
// MCSM0 08 - no autocalibration, PO_TIMEOUT - 64, no pin radio control, no forcing XTAL to stay in SLEEP
// FOCCFG 1D - not interesting, Frequency Offset Compensation
// FREND0 10 - PA_POWER = 0
const PROGMEM uint8_t SFHSS_init_values[] = {
/* 00 */ 0x2F, 0x2E, 0x2F, 0x07, 0xD3, 0x91, 0x0D, 0x04,
/* 08 */ 0x0C, 0x29, 0x10, 0x06, 0x00, 0x5C, 0x4E, SFHSS_FREQ0_VAL + SFHSS_COARSE,
/* 10 */ 0x7C, 0x43, 0x83, 0x23, 0x3B, 0x44, 0x07, 0x0C,
/* 18 */ 0x08, 0x1D, 0x1C, 0x43, 0x40, 0x91, 0x57, 0x6B,
/* 20 */ 0xF8, 0xB6, 0x10, 0xEA, 0x0A, 0x11, 0x11
};
static void __attribute__((unused)) SFHSS_tune_chan()
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, rf_ch_num*6+16);
CC2500_Strobe(CC2500_SCAL);
}
static void __attribute__((unused)) SFHSS_tune_chan_fast()
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, rf_ch_num*6+16);
CC2500_WriteRegisterMulti(CC2500_23_FSCAL3, calData[rf_ch_num], 3);
_delay_us(6);
}
#ifdef USE_SFHSS_TUNE_FREQ
static void __attribute__((unused)) SFHSS_tune_freq() {
// May be we'll need this tuning routine - some receivers are more sensitive to
// frequency impreciseness, and though CC2500 has a procedure to handle it it
// may not be applied in receivers, so we need to compensate for it on TX
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_WriteReg(CC2500_0F_FREQ0, SFHSS_FREQ0_VAL + SFHSS_COARSE);
}
#endif
static void __attribute__((unused)) SFHSS_rf_init()
{
CC2500_Reset();
CC2500_Strobe(CC2500_SIDLE);
for (uint8_t i = 0; i < 39; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&SFHSS_init_values[i]));
//CC2500_WriteRegisterMulti(CC2500_00_IOCFG2, init_values, sizeof(init_values));
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
}
static void __attribute__((unused)) SFHSS_calc_next_chan()
{
rf_ch_num += fhss_code + 2;
if (rf_ch_num > 29) {
if (rf_ch_num < 31) rf_ch_num += fhss_code + 2;
rf_ch_num -= 31;
}
}
// Channel values are 10-bit values between 86 and 906, 496 is the middle.
static uint16_t __attribute__((unused)) SFHSS_convert_channel(uint8_t num)
{
return (uint16_t) (map(limit_channel_100(num),PPM_MIN_100,PPM_MAX_100,86,906));
}
static void __attribute__((unused)) SFHSS_build_data_packet()
{
#define spacer1 0b10
#define spacer2 (spacer1 << 4)
uint8_t ch_offset = state == SFHSS_DATA1 ? 0 : 4;
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4};
u16 ch1 = SFHSS_convert_channel(ch[ch_offset+0]);
u16 ch2 = SFHSS_convert_channel(ch[ch_offset+1]);
u16 ch3 = SFHSS_convert_channel(ch[ch_offset+2]);
u16 ch4 = SFHSS_convert_channel(ch[ch_offset+3]);
packet[0] = 0x81; // can be 80, 81, 81 for Orange, only 81 for XK
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
packet[3] = 0;
packet[4] = 0;
packet[5] = (rf_ch_num << 3) | spacer1 | ((ch1 >> 9) & 0x01);
packet[6] = (ch1 >> 1);
packet[7] = (ch1 << 7) | spacer2 | ((ch2 >> 5) & 0b11111);
packet[8] = (ch2 << 3) | spacer1 | ((ch3 >> 9) & 0x01);
packet[9] = (ch3 >> 1);
packet[10] = (ch3 << 7) | spacer2 | ((ch4 >> 5) & 0b11111);
packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0b111);
packet[12] = (fhss_code << 6) | state;
}
static void __attribute__((unused)) SFHSS_send_packet()
{
SFHSS_tune_chan_fast();
CC2500_WriteData(packet, SFHSS_PACKET_LEN);
}
uint16_t ReadSFHSS()
{
switch(state)
{
case SFHSS_START:
rf_ch_num = 0;
SFHSS_tune_chan();
state = SFHSS_CAL;
return 2000;
case SFHSS_CAL:
CC2500_ReadRegisterMulti(CC2500_23_FSCAL3, calData[rf_ch_num], 3);
if (++rf_ch_num < 30)
SFHSS_tune_chan();
else
{
rf_ch_num = 0;
state = SFHSS_DATA1;
}
return 2000;
/* Work cycle, 6.8ms, second packet 1.65ms after first */
case SFHSS_DATA1:
SFHSS_build_data_packet();
SFHSS_send_packet();
state = SFHSS_DATA2;
return 1650;
case SFHSS_DATA2:
SFHSS_build_data_packet();
SFHSS_send_packet();
SFHSS_calc_next_chan();
state = SFHSS_TUNE;
return 2000;
case SFHSS_TUNE:
CC2500_SetPower();
state = SFHSS_DATA1;
return 3150;
/*
case SFHSS_DATA1:
SFHSS_build_data_packet();
SFHSS_send_packet();
state = SFHSS_DATA2;
return 1650;
case SFHSS_DATA2:
SFHSS_build_data_packet();
SFHSS_send_packet();
state = SFHSS_CAL2;
return 500;
case SFHSS_CAL2:
SFHSS_tune_freq();
// CC2500_SetPower();
SFHSS_calc_next_chan();
SFHSS_tune_chan();
state = SFHSS_DATA1;
return 4650;
*/
}
return 0;
}
// Generate internal id
static void __attribute__((unused)) SFHSS_get_tx_id()
{
uint32_t fixed_id;
// Some receivers (Orange) behaves better if they tuned to id that has
// no more than 6 consequtive zeos and ones
uint8_t run_count = 0;
// add guard for bit count
fixed_id = 1 ^ (MProtocol_id & 1);
for (uint8_t i = 0; i < 16; ++i)
{
fixed_id = (fixed_id << 1) | (MProtocol_id & 1);
MProtocol_id >>= 1;
// If two LS bits are the same
if ((fixed_id & 3) == 0 || (fixed_id & 3) == 3)
{
if (++run_count > 6)
{
fixed_id ^= 1;
run_count = 0;
}
}
else
run_count = 0;
}
// fixed_id = 0xBC11;
rx_tx_addr[0] = fixed_id >> 8;
rx_tx_addr[1] = fixed_id;
}
uint16_t initSFHSS()
{
SFHSS_get_tx_id();
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
fhss_code=random(0xfefefefe)%28; // Initialize it to random 0-27 inclusive
SFHSS_rf_init();
state = SFHSS_START;
return 10000;
}
#endif

View File

@ -4,173 +4,216 @@
//*************************************
#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
#if defined DSM2_CYRF6936_INO
#define DSM_TELEMETRY
#endif
#if defined FRSKYX_CC2500_INO
#define SPORT_TELEMETRY
#endif
#if defined FRSKY_CC2500_INO
#define HUB_TELEMETRY
#endif
#if defined SPORT_TELEMETRY
#define SPORT_TIME 12000
#define FRSKY_SPORT_PACKET_SIZE 8
uint32_t last = 0;
uint8_t sport_counter=0;
uint8_t RxBt = 0;
uint8_t rssi;
uint8_t sport = 0;
#endif
#if defined HUB_TELEMETRY
#define USER_MAX_BYTES 6
uint8_t frame[18];
uint8_t prev_index;
#endif
void frskySendStuffed()
#define START_STOP 0x7e
#define BYTESTUFF 0x7d
#define STUFF_MASK 0x20
#define MAX_PKTX 10
uint8_t pktx[MAX_PKTX];
uint8_t index;
uint8_t pass = 0;
uint8_t frame[18];
#if defined DSM_TELEMETRY
void DSM2_frame()
{
Serial_write(0xAA); // Start
for (uint8_t i = 0; i < 17; i++) // RSSI value followed by 16 bytes of telemetry data
Serial_write(pkt[i]);
}
#endif
void frskySendStuffed()
{
Serial_write(START_STOP);
for (uint8_t i = 0; i < 9; i++)
{
Serial_write(0x7E);
for (uint8_t i = 0; i < 9; i++)
if ((frame[i] == START_STOP) || (frame[i] == BYTESTUFF))
{
if ((frame[i] == 0x7e) || (frame[i] == 0x7d))
Serial_write(BYTESTUFF);
frame[i] ^= STUFF_MASK;
}
Serial_write(frame[i]);
}
Serial_write(START_STOP);
}
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))
{
for (uint8_t i=3;i<len;i++)
pktt[i]=pkt[i];
telemetry_link=1;
if(pktt[6])
telemetry_counter=(telemetry_counter+1)%32;
//
#if defined FRSKYX_CC2500_INO
if ((cur_protocol[0]&0x1F)==MODE_FRSKYX)
{
if ((pktt[5] >> 4 & 0x0f) == 0x08)
{
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();
seq_last_sent = 8;
seq_last_rcvd = 0;
pass=0;
}
else
pass=0;
{
if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4)
seq_last_rcvd = (seq_last_rcvd + 1) % 4;
else
pass=0;//reset if sequence wrong
}
}
#endif
#endif
}
}
#if defined SPORT_TELEMETRY
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();
}
/* SPORT details serial
#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]<=10)
{//only valid hub frames
frame[0] = 0xFD;
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
/*
HuB RX packets.
pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
%32
01 08 5E 28 12 00 5E 5E 3A 06 00 5E
0A 09 28 12 00 5E 5E 3A 06 00 5E 5E
09 0A 3B 09 00 5E 5E 06 36 7D 5E 5E
03 0B 5E 28 11 00 5E 5E 06 06 6C 5E
0A 0C 00 5E 5E 3A 06 00 5E 5E 3B 09
07 0D 00 5E 5E 06 06 6C 5E 16 72 5E
05 0E 5E 28 11 00 5E 5E 3A 06 00 5E
0A 0F 5E 3A 06 00 5E 5E 3B 09 00 5E
05 10 5E 06 16 72 5E 5E 3A 06 00 5E
*/
#if defined SPORT_TELEMETRY
/* SPORT details serial
100K 8E2 normal-multiprotocol
-every 12ms-
1 2 3 4 5 6 7 8 9 CRC DESCR
-every 12ms-or multiple of 12; %36
1 2 3 4 5 6 7 8 9 CRC DESCR
7E 98 10 05 F1 20 23 0F 00 A6 SWR_ID
7E 98 10 01 F1 33 00 00 00 C9 RSSI_ID
7E 98 10 04 F1 58 00 00 00 A1 BATT_ID
@ -182,14 +225,15 @@
7E BA 10 03 F1 E2 00 00 00 18 ADC2_ID
Telemetry frames(RF) SPORT info 15 bytes
SPORT frame 6+3 bytes
Telemetry frames(RF) SPORT info
15 bytes payload
SPORT frame valid 6+3 bytes
[00] PKLEN 0E 0E 0E 0E
[01] TXID1 DD DD DD DD
[02] TXID2 6D 6D 6D 6D
[03] CONST 02 02 02 02
[04] RS/RB 2C D0 2C CE //D0;CE=2*RSSI;....2C = RX battery voltage(5V from Bec)
[05] ????? 03 10 21 32 //TX/RX telemetry hand-shake bytes
[05] HD-SK 03 10 21 32 //TX/RX telemetry hand-shake bytes
[06] NO.BT 00 00 06 03 //No.of valid SPORT frame bytes in the frame
[07] STRM1 00 00 7E 00
[08] STRM2 00 00 1A 00
@ -197,141 +241,179 @@
[10] STRM4 03 03 03 03
[11] STRM5 F1 F1 F1 F1
[12] STRM6 D1 D1 D0 D0
[13] CHKSUM1
[14] CHKSUM2
[13] CHKSUM1 --|2 CRC bytes sent by RX (calculated on RX side crc16/table)
[14] CHKSUM2 --|
+2 appended bytes automatically RSSI and LQI/CRC bytes(len=0x0E+3);
0x06 0x06 0x06 0x06 0x06
0x7E 0x00 0x03 0x7E 0x00
0x1A 0x00 0xF1 0x1A 0x00
0x10 0x00 0xD7 0x10 0x00
0x03 0x7E 0x00 0x03 0x7E
0xF1 0x1A 0x00 0xF1 0x1A
0xD7 0x10 0x00 0xD7 0x10
0xE1 0x1C 0xD0 0xEE 0x33
0x34 0x0A 0xC3 0x56 0xF3
*/
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()
void sportSend(uint8_t *p)
{
uint16_t crc_s = 0;
Serial_write(START_STOP);//+9
for (uint8_t i = 0; i < 9; i++)
{
if(telemetry_link && (cur_protocol[0]&0x1F) != MODE_FRSKYX )
if (i == 8)
p[i] = 0xff - crc_s;
if ((p[i] == START_STOP) || (p[i] == BYTESTUFF))
{
frsky_link_frame();
telemetry_link=0;
return;
Serial_write(BYTESTUFF);//stuff again
Serial_write(STUFF_MASK ^ p[i]);
}
#if defined HUB_TELEMETRY
if(!telemetry_link && (cur_protocol[0]&0x1F) != MODE_HUBSAN && (cur_protocol[0]&0x1F) != MODE_FRSKYX)
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(START_STOP);
}
void sportSendFrame()
{
uint8_t i;
sport_counter = (sport_counter + 1) %36;
if(sport_counter<3)
{
frame[0] = 0x98;
frame[1] = 0x10;
for (i=5;i<8;i++)
frame[i]=0;
}
switch (sport_counter)
{
case 0:
frame[2] = 0x05;
frame[3] = 0xf1;
frame[4] = 0x20;//dummy values if swr 20230f00
frame[5] = 0x23;
frame[6] = 0x0F;
break;
case 1: // RSSI
frame[2] = 0x01;
frame[3] = 0xf1;
frame[4] = rssi;
break;
case 2: //BATT
frame[2] = 0x04;
frame[3] = 0xf1;
frame[4] = RxBt;//a1;
break;
default:
if(sport)
{
frsky_user_frame();
for (i=0;i<FRSKY_SPORT_PACKET_SIZE;i++)
frame[i]=pktx[i];
sport=0;
break;
}
else
{
sportIdle();
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
}
sportSend(frame);
}
void proces_sport_data(uint8_t data)
{
switch (pass)
{
case 0:
if (data == START_STOP)
{//waiting for 0x7e
index = 0;
pass = 1;
}
break;
case 1:
if(data == BYTESTUFF)//if they are stuffed
pass=2;
else
if (index < MAX_PKTX)
pktx[index++] = data;
break;
case 2:
if (index < MAX_PKTX)
pktx[index++] = data ^ STUFF_MASK; //unstuff bytes
pass=1;
break;
} // end switch
if (index >= FRSKY_SPORT_PACKET_SIZE)
{//8 bytes no crc
sport = 1;//ok to send
pass = 0;//reset
}
}
#endif
void frskyUpdate()
{
#if defined DSM_TELEMETRY
if(telemetry_link && (cur_protocol[0]&0x1F) == MODE_DSM2 )
{ // DSM2
DSM2_frame();
telemetry_link=0;
return;
}
#endif
if(telemetry_link && (cur_protocol[0]&0x1F) != MODE_FRSKYX )
{ // FrSky + Hubsan
frsky_link_frame();
telemetry_link=0;
return;
}
#if defined HUB_TELEMETRY
if(!telemetry_link && (cur_protocol[0]&0x1F) == MODE_FRSKY)
{ // FrSky
frsky_user_frame();
return;
}
#endif
#if defined SPORT_TELEMETRY
if ((cur_protocol[0]&0x1F)==MODE_FRSKYX)
{ // FrSkyX
if(telemetry_link)
{
if(pktt[4]>0x36)
rssi=pktt[4]>>1;
else
RxBt=pktt[4];
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();
last = now;
}
}
#endif
}
#endif

View File

@ -0,0 +1,60 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Wiring project - http://wiring.org.co
Copyright (c) 2004-06 Hernando Barragan
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id$
*/
extern "C" {
#include "stdlib.h"
}
void randomSeed(unsigned int seed)
{
if (seed != 0) {
srandom(seed);
}
}
long random(long howbig)
{
if (howbig == 0) {
return 0;
}
return random() % howbig;
}
//long random(long howsmall, long howbig)
//{
// if (howsmall >= howbig) {
// return howsmall;
// }
// long diff = howbig - howsmall;
// return random(diff) + howsmall;
//}
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
unsigned int makeWord(unsigned int w) { return w; }
unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }

View File

@ -42,6 +42,7 @@
#ifdef CC2500_INSTALLED
#define FRSKY_CC2500_INO
#define FRSKYX_CC2500_INO
#define SFHSS_CC2500_INO
#endif
#ifdef NFR24L01_INSTALLED
#define BAYANG_NRF24L01_INO
@ -129,7 +130,8 @@ const PPM_Parameters PPM_prot[15]= {
MODE_BAYANG
NONE
MODE_FRSKYX
NONE
CH_16
CH_8
MODE_ESKY
NONE
MODE_MT99XX
@ -145,6 +147,8 @@ const PPM_Parameters PPM_prot[15]= {
NONE
MODE_FY326
NONE
MODE_SFHSS
NONE
RX_Num value between 0 and 15