mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-02-04 19:58:13 +00:00
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:
parent
6c3535951f
commit
d938f2ea50
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
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;
|
||||
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;
|
||||
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...
|
||||
#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);
|
||||
//
|
||||
|
@ -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)
|
||||
@ -183,24 +183,23 @@ uint16_t ReadFlySky()
|
||||
else
|
||||
{
|
||||
flysky_build_packet(0);
|
||||
A7105_WriteData(21, pgm_read_byte_near(&tx_channels[chanrow*16+chancol])-chanoffset);
|
||||
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;
|
||||
|
@ -18,19 +18,17 @@
|
||||
|
||||
#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[]={
|
||||
const PROGMEM uint8_t hop_data[]={
|
||||
0x02, 0xD4, 0xBB, 0xA2, 0x89,
|
||||
0x70, 0x57, 0x3E, 0x25, 0x0C,
|
||||
0xDE, 0xC5, 0xAC, 0x93, 0x7A,
|
||||
@ -41,24 +39,24 @@
|
||||
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)) 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()
|
||||
{
|
||||
static void __attribute__((unused)) frskyX_init()
|
||||
{
|
||||
CC2500_Reset();
|
||||
|
||||
for(uint8_t i=0;i<36;i++)
|
||||
@ -87,103 +85,111 @@
|
||||
if(reg==CC2500_15_DEVIATN)
|
||||
val=0x51;
|
||||
|
||||
cc2500_writeReg(reg,val);
|
||||
CC2500_WriteReg(reg,val);
|
||||
}
|
||||
|
||||
cc2500_writeReg(CC2500_07_PKTCTRL1, 0x04);
|
||||
cc2500_writeReg(CC2500_0C_FSCTRL0, option);
|
||||
cc2500_strobe(CC2500_SIDLE);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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 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);
|
||||
// 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()
|
||||
{
|
||||
crc=0;
|
||||
static void __attribute__((unused)) frskyX_build_bind_packet()
|
||||
{
|
||||
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]);
|
||||
packet[3] = rx_tx_addr[3];
|
||||
packet[4] = 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);
|
||||
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;
|
||||
//
|
||||
for(uint8_t i=13;i<28;i++)
|
||||
packet[i]=crc_Byte(0);
|
||||
memset(&packet[13], 0, 15);
|
||||
uint16_t lcrc = crc_x(&packet[3], 25);
|
||||
//
|
||||
packet[28]=highByte(crc);
|
||||
packet[29]=lowByte(crc);
|
||||
packet[28] = lcrc >> 8;
|
||||
packet[29] = lcrc;
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frskyX_data_frame()
|
||||
{
|
||||
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_ ;
|
||||
static uint8_t lpass;
|
||||
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[3] = 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
|
||||
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] = crc_Byte(FS_flag);
|
||||
packet[8] = crc_Byte(flag2);
|
||||
packet[7] = FS_flag;
|
||||
packet[8] = 0;
|
||||
//
|
||||
if ( lpass & 1 )
|
||||
startChan += 8 ;
|
||||
@ -193,43 +199,49 @@
|
||||
chan_0 = scaleForPXX(startChan);
|
||||
if(lpass & 1 )
|
||||
chan_0+=2048;
|
||||
|
||||
packet[9+i] = crc_Byte(lowByte(chan_0));//3 bytes*4
|
||||
startChan++;
|
||||
startChan+=1;
|
||||
//
|
||||
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);
|
||||
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;
|
||||
}
|
||||
//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;
|
||||
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]=crc_Byte(0);
|
||||
packet[i]=0;
|
||||
uint16_t lcrc = crc_x(&packet[3], 25);
|
||||
|
||||
packet[28]=highByte(crc);
|
||||
packet[29]=lowByte(crc);
|
||||
}
|
||||
packet[28]=lcrc>>8;//high byte
|
||||
packet[29]=lcrc;//low byte
|
||||
}
|
||||
|
||||
uint16_t ReadFrSkyX()
|
||||
{
|
||||
uint16_t ReadFrSkyX()
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
default:
|
||||
set_start(47);
|
||||
CC2500_SetPower();
|
||||
cc2500_strobe(CC2500_SFRX);
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
//
|
||||
frskyX_build_bind_packet();
|
||||
cc2500_strobe(CC2500_SIDLE);
|
||||
cc2500_writeFifo(packet, packet[0]+1);
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteData(packet, packet[0]+1);
|
||||
state++;
|
||||
return 9000;
|
||||
case FRSKY_BIND_DONE:
|
||||
@ -243,42 +255,53 @@
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
set_start(channr);
|
||||
CC2500_SetPower();
|
||||
cc2500_strobe(CC2500_SFRX);
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
channr = (channr+chanskip)%47;
|
||||
cc2500_strobe(CC2500_SIDLE);
|
||||
cc2500_writeFifo(packet, packet[0]+1);
|
||||
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);
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
state++;
|
||||
return 200;
|
||||
case FRSKY_DATA3:
|
||||
cc2500_strobe(CC2500_SRX);
|
||||
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))
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if (len && (len<MAX_PKT))
|
||||
{
|
||||
cc2500_readFifo(pkt, len);
|
||||
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()
|
||||
{
|
||||
uint16_t initFrSkyX()
|
||||
{
|
||||
while(!chanskip)
|
||||
{
|
||||
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
|
||||
@ -293,6 +316,7 @@
|
||||
//rx_tx_addr[2]=0xFD;
|
||||
//************************
|
||||
frskyX_init();
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
//
|
||||
if(IS_AUTOBIND_FLAG_on)
|
||||
{
|
||||
@ -304,6 +328,8 @@
|
||||
state = FRSKY_DATA1;
|
||||
initialize_data(0);
|
||||
}
|
||||
seq_last_sent = 0;
|
||||
seq_last_rcvd = 8;
|
||||
return 10000;
|
||||
}
|
||||
}
|
||||
#endif
|
@ -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;
|
||||
|
624
Multiprotocol/Makefile.xmega
Normal file
624
Multiprotocol/Makefile.xmega
Normal 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
|
||||
|
||||
|
||||
|
||||
|
476
Multiprotocol/Multiprotocol.cpp.xmega
Normal file
476
Multiprotocol/Multiprotocol.cpp.xmega
Normal 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() ;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
else
|
||||
#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
|
||||
OCR1A+=next_callback*2; // set compare A for callback
|
||||
#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
|
||||
}
|
||||
// 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,31 +826,57 @@ 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
|
||||
{
|
||||
#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
|
||||
#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
|
||||
}
|
||||
@ -729,30 +884,49 @@ ISR(USART_RX_vect)
|
||||
}
|
||||
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
|
||||
|
265
Multiprotocol/SFHSS_cc2500.ino
Normal file
265
Multiprotocol/SFHSS_cc2500.ino
Normal 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
|
@ -4,75 +4,106 @@
|
||||
//*************************************
|
||||
|
||||
#if defined TELEMETRY
|
||||
#if defined FRSKYX_CC2500_INO
|
||||
#define SPORT_TELEMETRY
|
||||
#endif
|
||||
#if defined FRSKY_CC2500_INO
|
||||
#define HUB_TELEMETRY
|
||||
#endif
|
||||
#if defined SPORT_TELEMETRY
|
||||
#define SPORT_TELEMETRY
|
||||
#define SPORT_TIME 12000
|
||||
uint32_t last=0;
|
||||
uint8_t sport_counter=0;
|
||||
uint8_t RxBt=0;
|
||||
uint8_t rssi;
|
||||
uint8_t ADC2;
|
||||
#endif
|
||||
#if defined HUB_TELEMETRY
|
||||
#define MAX_PKTX 10
|
||||
uint8_t pktx[MAX_PKTX];
|
||||
uint8_t index;
|
||||
uint8_t prev_index;
|
||||
uint8_t pass = 0;
|
||||
#endif
|
||||
#define USER_MAX_BYTES 6
|
||||
uint8_t frame[18];
|
||||
|
||||
void frskySendStuffed()
|
||||
{
|
||||
Serial_write(0x7E);
|
||||
#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 prev_index;
|
||||
#endif
|
||||
|
||||
#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++)
|
||||
{
|
||||
if ((frame[i] == 0x7e) || (frame[i] == 0x7d))
|
||||
if ((frame[i] == START_STOP) || (frame[i] == BYTESTUFF))
|
||||
{
|
||||
Serial_write(0x7D);
|
||||
frame[i] ^= 0x20;
|
||||
Serial_write(BYTESTUFF);
|
||||
frame[i] ^= STUFF_MASK;
|
||||
}
|
||||
Serial_write(frame[i]);
|
||||
}
|
||||
Serial_write(0x7E);
|
||||
}
|
||||
Serial_write(START_STOP);
|
||||
}
|
||||
|
||||
void compute_RSSIdbm(){
|
||||
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
|
||||
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]>0)
|
||||
if(pktt[6])
|
||||
telemetry_counter=(telemetry_counter+1)%32;
|
||||
}
|
||||
}
|
||||
|
||||
void frsky_link_frame()
|
||||
//
|
||||
#if defined FRSKYX_CC2500_INO
|
||||
if ((cur_protocol[0]&0x1F)==MODE_FRSKYX)
|
||||
{
|
||||
if ((pktt[5] >> 4 & 0x0f) == 0x08)
|
||||
{
|
||||
seq_last_sent = 8;
|
||||
seq_last_rcvd = 0;
|
||||
pass=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
void frsky_link_frame()
|
||||
{
|
||||
frame[0] = 0xFE;
|
||||
if ((cur_protocol[0]&0x1F)==MODE_FRSKY)
|
||||
{
|
||||
@ -92,19 +123,17 @@
|
||||
}
|
||||
frame[5] = frame[6] = frame[7] = frame[8] = 0;
|
||||
frskySendStuffed();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined HUB_TELEMETRY
|
||||
void frsky_user_frame()
|
||||
{
|
||||
#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)
|
||||
if(pktt[6]>0 && pktt[6]<=10)
|
||||
{//only valid hub frames
|
||||
frame[0] = 0xFD;
|
||||
frame[1] = 0;
|
||||
frame[2] = pktt[7];
|
||||
|
||||
switch(pass)
|
||||
{
|
||||
case 0:
|
||||
@ -146,7 +175,7 @@
|
||||
case 2:
|
||||
index = prev_index - index;
|
||||
prev_index=0;
|
||||
if(index<MAX_PKTX-USER_MAX_BYTES) //10-6=4
|
||||
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;
|
||||
@ -162,14 +191,28 @@
|
||||
}
|
||||
else
|
||||
pass=0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined SPORT_TELEMETRY
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
/* SPORT details serial
|
||||
#if defined SPORT_TELEMETRY
|
||||
/* SPORT details serial
|
||||
100K 8E2 normal-multiprotocol
|
||||
-every 12ms-
|
||||
-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
|
||||
@ -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,26 +241,40 @@
|
||||
[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)
|
||||
{
|
||||
void sportSend(uint8_t *p)
|
||||
{
|
||||
uint16_t crc_s = 0;
|
||||
Serial_write(0x7e);//+9
|
||||
Serial_write(START_STOP);//+9
|
||||
for (uint8_t i = 0; i < 9; i++)
|
||||
{
|
||||
if (i == 8)
|
||||
p[i] = 0xff - crc_s;
|
||||
if ((p[i] == 0x7e) || (p[i] == 0x7d))
|
||||
|
||||
if ((p[i] == START_STOP) || (p[i] == BYTESTUFF))
|
||||
{
|
||||
Serial_write(0x7d);
|
||||
Serial_write(0x20 ^ p[i]);
|
||||
Serial_write(BYTESTUFF);//stuff again
|
||||
Serial_write(STUFF_MASK ^ p[i]);
|
||||
}
|
||||
else
|
||||
Serial_write(p[i]);
|
||||
|
||||
if (i>0)
|
||||
{
|
||||
crc_s += p[i]; //0-1FF
|
||||
@ -224,104 +282,128 @@
|
||||
crc_s &= 0x00ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sportIdle()
|
||||
void sportIdle()
|
||||
{
|
||||
Serial_write(START_STOP);
|
||||
}
|
||||
|
||||
void sportSendFrame()
|
||||
{
|
||||
uint8_t i;
|
||||
sport_counter = (sport_counter + 1) %36;
|
||||
|
||||
if(sport_counter<3)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
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:
|
||||
if(sport)
|
||||
{
|
||||
for (i=0;i<FRSKY_SPORT_PACKET_SIZE;i++)
|
||||
frame[i]=pktx[i];
|
||||
sport=0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sportIdle();
|
||||
return;
|
||||
}
|
||||
}
|
||||
sportSend(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void process_sport_data()//only for ADC2
|
||||
void proces_sport_data(uint8_t data)
|
||||
{
|
||||
switch (pass)
|
||||
{
|
||||
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];
|
||||
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
|
||||
}
|
||||
pktt[6]=0;//new frame
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void frskyUpdate()
|
||||
{
|
||||
#if defined DSM_TELEMETRY
|
||||
if(telemetry_link && (cur_protocol[0]&0x1F) == MODE_DSM2 )
|
||||
{ // DSM2
|
||||
DSM2_frame();
|
||||
telemetry_link=0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void frskyUpdate()
|
||||
{
|
||||
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_HUBSAN && (cur_protocol[0]&0x1F) != MODE_FRSKYX)
|
||||
{
|
||||
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)
|
||||
{
|
||||
process_sport_data();
|
||||
if(pktt[4]>0x36)
|
||||
rssi=pktt[4]/2;
|
||||
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();
|
||||
@ -332,6 +414,6 @@
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
60
Multiprotocol/WMath.cpp.xmega
Normal file
60
Multiprotocol/WMath.cpp.xmega
Normal 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; }
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user