diff --git a/Multiprotocol/CC2500_SPI.ino b/Multiprotocol/CC2500_SPI.ino index afcd8bb..34f1b73 100644 --- a/Multiprotocol/CC2500_SPI.ino +++ b/Multiprotocol/CC2500_SPI.ino @@ -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); } } diff --git a/Multiprotocol/CYRF6936_SPI.ino b/Multiprotocol/CYRF6936_SPI.ino index 9880233..bb4cc23 100644 --- a/Multiprotocol/CYRF6936_SPI.ino +++ b/Multiprotocol/CYRF6936_SPI.ino @@ -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); diff --git a/Multiprotocol/DSM2_cyrf6936.ino b/Multiprotocol/DSM2_cyrf6936.ino index 19a969e..9a2b018 100644 --- a/Multiprotocol/DSM2_cyrf6936.ino +++ b/Multiprotocol/DSM2_cyrf6936.ino @@ -20,7 +20,6 @@ #define RANDOM_CHANNELS 0 // disabled //#define RANDOM_CHANNELS 1 // enabled #define BIND_CHANNEL 0x0d //13 This can be any odd channel -#define NUM_WAIT_LOOPS (100 / 5) //each loop is ~5us. Do not wait more than 100us //During binding we will send BIND_COUNT/2 packets //One packet each 10msec @@ -107,21 +106,19 @@ static void __attribute__((unused)) read_code(uint8_t *buf, uint8_t row, uint8_t } // -uint8_t chidx; uint8_t sop_col; uint8_t data_col; uint16_t cyrf_state; -uint8_t crcidx; uint8_t binding; static void __attribute__((unused)) build_bind_packet() { uint8_t i; uint16_t sum = 384 - 0x10;// - packet[0] = crc >> 8; - packet[1] = crc & 0xff; + packet[0] = 0xff ^ cyrfmfg_id[0]; + packet[1] = 0xff ^ cyrfmfg_id[1]; packet[2] = 0xff ^ cyrfmfg_id[2]; - packet[3] = (0xff ^ cyrfmfg_id[3]) + RX_num; + packet[3] = 0xff ^ cyrfmfg_id[3]; packet[4] = packet[0]; packet[5] = packet[1]; packet[6] = packet[2]; @@ -133,7 +130,11 @@ static void __attribute__((unused)) build_bind_packet() packet[10] = 0x01; //??? packet[11] = option>3?option:option+4; if(sub_protocol==DSMX) //DSMX type - packet[12] = 0xb2; // Telemetry off: packet[12] = num_channels < 8 && Model.proto_opts[PROTOOPTS_TELEMETRY] == TELEM_OFF ? 0xa2 : 0xb2; +#if defined DSM_TELEMETRY + packet[12] = 0xb2; // Telemetry on +#else + packet[12] = option<8? 0xa2 : 0xb2; // Telemetry off +#endif else packet[12] = option<8?0x01:0x02; packet[13] = 0x00; //??? @@ -196,13 +197,13 @@ static void __attribute__((unused)) build_data_packet(uint8_t upper)// if (sub_protocol==DSMX) { packet[0] = cyrfmfg_id[2]; - packet[1] = cyrfmfg_id[3] + RX_num; + packet[1] = cyrfmfg_id[3]; bits=11; } else { packet[0] = (0xff ^ cyrfmfg_id[2]); - packet[1] = (0xff ^ cyrfmfg_id[3]) + RX_num; + packet[1] = (0xff ^ cyrfmfg_id[3]); bits=10; } // @@ -251,6 +252,18 @@ static void __attribute__((unused)) build_data_packet(uint8_t upper)// case 7: value=Servo_data[AUX4]; break; + case 8: + value=Servo_data[AUX5]; + break; + case 9: + value=Servo_data[AUX6]; + break; + case 10: + value=Servo_data[AUX7]; + break; + case 11: + value=Servo_data[AUX8]; + break; } value=map(value,PPM_MIN,PPM_MAX,0,max-1); } @@ -267,7 +280,7 @@ static uint8_t __attribute__((unused)) get_pn_row(uint8_t channel) } const uint8_t init_vals[][2] = { - {CYRF_02_TX_CTRL, 0x00}, + {CYRF_02_TX_CTRL, 0x02}, //0x00 in deviation but needed to know when transmit is over {CYRF_05_RX_CTRL, 0x00}, {CYRF_28_CLK_EN, 0x02}, {CYRF_32_AUTO_CAL_TIME, 0x3c}, @@ -314,7 +327,7 @@ static void __attribute__((unused)) initialize_bind_state() CYRF_ConfigSOPCode(code); read_code(code,pn_row,data_col,16); read_code(code+16,0,8,8); - memcpy(code + 24, "\xc6\x94\x22\xfe\x48\xe6\x57\x4e", 8); + memcpy(code + 24, (void *)"\xc6\x94\x22\xfe\x48\xe6\x57\x4e", 8); CYRF_ConfigDataCode(code, 32); build_bind_packet(); @@ -347,10 +360,11 @@ static void __attribute__((unused)) cyrf_configdata() static void __attribute__((unused)) set_sop_data_crc() { uint8_t code[16]; - uint8_t pn_row = get_pn_row(hopping_frequency[chidx]); - //printf("Ch: %d Row: %d SOP: %d Data: %d\n", ch[chidx], pn_row, sop_col, data_col); - CYRF_ConfigRFChannel(hopping_frequency[chidx]); - CYRF_ConfigCRCSeed(crcidx ? ~crc : crc); + uint8_t pn_row = get_pn_row(hopping_frequency[hopping_frequency_no]); + //printf("Ch: %d Row: %d SOP: %d Data: %d\n", ch[hopping_frequency_no], pn_row, sop_col, data_col); + CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]); + CYRF_ConfigCRCSeed(crc); + crc=~crc; read_code(code,pn_row,sop_col,8); CYRF_ConfigSOPCode(code); @@ -358,10 +372,9 @@ static void __attribute__((unused)) set_sop_data_crc() CYRF_ConfigDataCode(code, 16); if(sub_protocol == DSMX) - chidx = (chidx + 1) % 23; + hopping_frequency_no = (hopping_frequency_no + 1) % 23; else - chidx = (chidx + 1) % 2; - crcidx = !crcidx; + hopping_frequency_no = (hopping_frequency_no + 1) % 2; } static void __attribute__((unused)) calc_dsmx_channel() @@ -375,7 +388,7 @@ static void __attribute__((unused)) calc_dsmx_channel() uint8_t count_3_27 = 0, count_28_51 = 0, count_52_76 = 0; id_tmp = id_tmp * 0x0019660D + 0x3C6EF35F; // Randomization uint8_t next_ch = ((id_tmp >> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3 - if (((next_ch ^ id) & 0x01 )== 0) + if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 ) continue; for (i = 0; i < idx; i++) { @@ -400,10 +413,10 @@ static void __attribute__((unused)) calc_dsmx_channel() uint16_t ReadDsm2() { -#define CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2 -#define WRITE_DELAY 1650 // 1550 original, Time after write to verify write complete -#define READ_DELAY 400 // Time before write to check read state, and switch channels - uint8_t i = 0; +#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2 +#define DSM_WRITE_DELAY 1550 // Time after write to verify write complete +#define DSM_READ_DELAY 600 // Time before write to check read state, and switch channels. Was 400 but 500 seems what the 328p needs to read a packet + uint32_t start; switch(cyrf_state) { @@ -413,8 +426,7 @@ uint16_t ReadDsm2() if(cyrf_state & 1) { //Send packet on even states - //Note state has already incremented, - // so this is actually 'even' state + //Note state has already incremented, so this is actually 'even' state CYRF_WriteDataPacket(packet); return 8500; } @@ -430,35 +442,81 @@ uint16_t ReadDsm2() //CYRF_FindBestChannels(ch, 2, 10, 1, 79); cyrf_configdata(); CYRF_SetTxRxMode(TX_EN); - chidx = 0; - crcidx = 0; - cyrf_state = DSM2_CH1_WRITE_A; // in fact cyrf_state++ + hopping_frequency_no = 0; + cyrf_state = DSM2_CH1_WRITE_A; // in fact cyrf_state++ set_sop_data_crc(); return 10000; case DSM2_CH1_WRITE_A: case DSM2_CH1_WRITE_B: - build_data_packet(cyrf_state == DSM2_CH1_WRITE_B);//compare state and DSM2_CH1_WRITE_B return 0 or 1 case DSM2_CH2_WRITE_A: case DSM2_CH2_WRITE_B: + build_data_packet(cyrf_state == DSM2_CH1_WRITE_B);// build lower or upper channels + CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags CYRF_WriteDataPacket(packet); - cyrf_state++; // change from WRITE to CHECK mode - return WRITE_DELAY; + cyrf_state++; // change from WRITE to CHECK mode + return DSM_WRITE_DELAY; case DSM2_CH1_CHECK_A: case DSM2_CH1_CHECK_B: - while (! (CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)) - if(++i > NUM_WAIT_LOOPS) + start=micros(); + while (micros()-start < 500) // Wait max 500µs + if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02) break; set_sop_data_crc(); - cyrf_state++; // change from CH1_CHECK to CH2_WRITE - return CH1_CH2_DELAY - WRITE_DELAY; + cyrf_state++; // change from CH1_CHECK to CH2_WRITE + return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY; case DSM2_CH2_CHECK_A: case DSM2_CH2_CHECK_B: - while (! (CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)) - if(++i > NUM_WAIT_LOOPS) + start=micros(); + while (micros()-start < 500) // Wait max 500µs + if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02) break; if (cyrf_state == DSM2_CH2_CHECK_A) - CYRF_SetPower(0x28); //Keep transmit power in sync - // No telemetry... + CYRF_SetPower(0x28); //Keep transmit power in sync +#if defined DSM_TELEMETRY + cyrf_state++; // change from CH2_CHECK to CH2_READ + if(option<=3 || option>7) + { // disable telemetry for option between 4 and 7 ie 4,5,6,7 channels @11ms since it does not work... + CYRF_SetTxRxMode(RX_EN); //Receive mode + CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive + } + return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY; + case DSM2_CH2_READ_A: + case DSM2_CH2_READ_B: + //Read telemetry + uint8_t rx_state = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS); + if((rx_state & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing) + rx_state |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS); + if((rx_state & 0x07) == 0x02) + { // good data (complete with no errors) + CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read + uint8_t len=CYRF_ReadRegister(CYRF_09_RX_COUNT); + if(len>MAX_PKT-2) + len=MAX_PKT-2; + CYRF_ReadDataPacketLen(pkt+1, len); + pkt[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F; // store RSSI of the received telemetry signal + telemetry_link=1; + } + if (cyrf_state == DSM2_CH2_READ_A && option <= 3) // normal 22ms mode if option<=3 ie 4,5,6,7 channels @22ms + { + //Force end read state + CYRF_WriteRegister(CYRF_0F_XACT_CFG, (CYRF_ReadRegister(CYRF_0F_XACT_CFG) | 0x20)); // Force end state + start=micros(); + while (micros()-start < 100) // Wait max 100 µs + if((CYRF_ReadRegister(CYRF_0F_XACT_CFG) & 0x20) == 0) + break; + cyrf_state = DSM2_CH2_READ_B; + CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive + return 11000; + } + if (cyrf_state == DSM2_CH2_READ_A && option>7) + cyrf_state = DSM2_CH1_WRITE_B; //Transmit upper + else + cyrf_state = DSM2_CH1_WRITE_A; //Force 11ms if option>3 ie 4,5,6,7 channels @11ms + CYRF_SetTxRxMode(TX_EN); //Write mode + set_sop_data_crc(); + return DSM_READ_DELAY; +#else + // No telemetry set_sop_data_crc(); if (cyrf_state == DSM2_CH2_CHECK_A) { @@ -466,16 +524,17 @@ uint16_t ReadDsm2() { cyrf_state = DSM2_CH1_WRITE_A; // change from CH2_CHECK_A to CH1_WRITE_A (ie no upper) if(option>3) - return 11000 - CH1_CH2_DELAY - WRITE_DELAY ; // force 11ms if option>3 ie 4,5,6,7 channels @11ms + return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ; // force 11ms if option>3 ie 4,5,6,7 channels @11ms else - return 22000 - CH1_CH2_DELAY - WRITE_DELAY ; // normal 22ms mode if option<=3 ie 4,5,6,7 channels @22ms + return 22000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ; // normal 22ms mode if option<=3 ie 4,5,6,7 channels @22ms } else cyrf_state = DSM2_CH1_WRITE_B; // change from CH2_CHECK_A to CH1_WRITE_A (to transmit upper) } else cyrf_state = DSM2_CH1_WRITE_A; // change from CH2_CHECK_B to CH1_WRITE_A (upper already transmitted so transmit lower) - return 11000 - CH1_CH2_DELAY - WRITE_DELAY; + return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY; +#endif } return 0; } @@ -484,10 +543,12 @@ uint16_t initDsm2() { CYRF_Reset(); CYRF_GetMfgData(cyrfmfg_id);// - + //Model match + cyrfmfg_id[3]+=RX_num; + cyrf_config(); - if (sub_protocol ==DSMX) + if (sub_protocol == DSMX) calc_dsmx_channel(); else { @@ -511,12 +572,12 @@ uint16_t initDsm2() #endif } - ///} - crc = ~((cyrfmfg_id[0] << 8) + cyrfmfg_id[1]); //The crc for channel 'a' is NOT(mfgid[1] << 8 + mfgid[0]) - crcidx = 0;//The crc for channel 'b' is (mfgid[1] << 8 + mfgid[0]) + //The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1]) + //The crc for channel '2' is (mfgid[0] << 8 + mfgid[1]) + crc = ~((cyrfmfg_id[0] << 8) + cyrfmfg_id[1]); // - sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;//Ok - data_col = 7 - sop_col;//ok + sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07; + data_col = 7 - sop_col; CYRF_SetTxRxMode(TX_EN); // diff --git a/Multiprotocol/FlySky_a7105.ino b/Multiprotocol/FlySky_a7105.ino index 84fa3df..ac6fddf 100644 --- a/Multiprotocol/FlySky_a7105.ino +++ b/Multiprotocol/FlySky_a7105.ino @@ -21,25 +21,6 @@ //FlySky constants & variables #define FLYSKY_BIND_COUNT 2500 -const uint8_t PROGMEM tx_channels[] = { - 0x0a, 0x5a, 0x14, 0x64, 0x1e, 0x6e, 0x28, 0x78, 0x32, 0x82, 0x3c, 0x8c, 0x46, 0x96, 0x50, 0xa0, - 0xa0, 0x50, 0x96, 0x46, 0x8c, 0x3c, 0x82, 0x32, 0x78, 0x28, 0x6e, 0x1e, 0x64, 0x14, 0x5a, 0x0a, - 0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x46, 0x96, 0x1e, 0x6e, 0x3c, 0x8c, 0x28, 0x78, 0x32, 0x82, - 0x82, 0x32, 0x78, 0x28, 0x8c, 0x3c, 0x6e, 0x1e, 0x96, 0x46, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a, - 0x28, 0x78, 0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96, - 0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a, 0x78, 0x28, - 0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96, 0x14, 0x64, - 0x64, 0x14, 0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50, - 0x50, 0xa0, 0x46, 0x96, 0x3c, 0x8c, 0x28, 0x78, 0x0a, 0x5a, 0x32, 0x82, 0x1e, 0x6e, 0x14, 0x64, - 0x64, 0x14, 0x6e, 0x1e, 0x82, 0x32, 0x5a, 0x0a, 0x78, 0x28, 0x8c, 0x3c, 0x96, 0x46, 0xa0, 0x50, - 0x46, 0x96, 0x3c, 0x8c, 0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64, - 0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50, 0x8c, 0x3c, 0x96, 0x46, - 0x46, 0x96, 0x0a, 0x5a, 0x3c, 0x8c, 0x14, 0x64, 0x50, 0xa0, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82, - 0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0xa0, 0x50, 0x64, 0x14, 0x8c, 0x3c, 0x5a, 0x0a, 0x96, 0x46, - 0x46, 0x96, 0x0a, 0x5a, 0x50, 0xa0, 0x3c, 0x8c, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64, - 0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0x8c, 0x3c, 0xa0, 0x50, 0x5a, 0x0a, 0x96, 0x46 -}; - enum { // flags going to byte 10 FLAG_V9X9_VIDEO = 0x40, @@ -164,12 +145,31 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init) const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4}; for(i = 0; i < 8; i++) { - packet[5+2*i]=lowByte(Servo_data[ch[i]]); //low byte of servo timing(1000-2000us) - packet[6+2*i]=highByte(Servo_data[ch[i]]); //high byte of servo timing(1000-2000us) + packet[5 + i*2]=Servo_data[ch[i]]&0xFF; //low byte of servo timing(1000-2000us) + packet[6 + i*2]=(Servo_data[ch[i]]>>8)&0xFF; //high byte of servo timing(1000-2000us) } flysky_apply_extension_flags(); } +const uint8_t PROGMEM tx_channels[16][16] = { + {0x0a, 0x5a, 0x14, 0x64, 0x1e, 0x6e, 0x28, 0x78, 0x32, 0x82, 0x3c, 0x8c, 0x46, 0x96, 0x50, 0xa0}, + {0xa0, 0x50, 0x96, 0x46, 0x8c, 0x3c, 0x82, 0x32, 0x78, 0x28, 0x6e, 0x1e, 0x64, 0x14, 0x5a, 0x0a}, + {0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x46, 0x96, 0x1e, 0x6e, 0x3c, 0x8c, 0x28, 0x78, 0x32, 0x82}, + {0x82, 0x32, 0x78, 0x28, 0x8c, 0x3c, 0x6e, 0x1e, 0x96, 0x46, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a}, + {0x28, 0x78, 0x0a, 0x5a, 0x50, 0xa0, 0x14, 0x64, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96}, + {0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x64, 0x14, 0xa0, 0x50, 0x5a, 0x0a, 0x78, 0x28}, + {0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x3c, 0x8c, 0x32, 0x82, 0x46, 0x96, 0x14, 0x64}, + {0x64, 0x14, 0x96, 0x46, 0x82, 0x32, 0x8c, 0x3c, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50}, + {0x50, 0xa0, 0x46, 0x96, 0x3c, 0x8c, 0x28, 0x78, 0x0a, 0x5a, 0x32, 0x82, 0x1e, 0x6e, 0x14, 0x64}, + {0x64, 0x14, 0x6e, 0x1e, 0x82, 0x32, 0x5a, 0x0a, 0x78, 0x28, 0x8c, 0x3c, 0x96, 0x46, 0xa0, 0x50}, + {0x46, 0x96, 0x3c, 0x8c, 0x50, 0xa0, 0x28, 0x78, 0x0a, 0x5a, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64}, + {0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x5a, 0x0a, 0x78, 0x28, 0xa0, 0x50, 0x8c, 0x3c, 0x96, 0x46}, + {0x46, 0x96, 0x0a, 0x5a, 0x3c, 0x8c, 0x14, 0x64, 0x50, 0xa0, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82}, + {0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0xa0, 0x50, 0x64, 0x14, 0x8c, 0x3c, 0x5a, 0x0a, 0x96, 0x46}, + {0x46, 0x96, 0x0a, 0x5a, 0x50, 0xa0, 0x3c, 0x8c, 0x28, 0x78, 0x1e, 0x6e, 0x32, 0x82, 0x14, 0x64}, + {0x64, 0x14, 0x82, 0x32, 0x6e, 0x1e, 0x78, 0x28, 0x8c, 0x3c, 0xa0, 0x50, 0x5a, 0x0a, 0x96, 0x46}, +}; + uint16_t ReadFlySky() { if (bind_counter) @@ -182,26 +182,25 @@ uint16_t ReadFlySky() } else { - flysky_build_packet(0); - A7105_WriteData(21, pgm_read_byte_near(&tx_channels[chanrow*16+chancol])-chanoffset); + flysky_build_packet(0); + A7105_WriteData(21, pgm_read_byte_near(&tx_channels[chanrow][chancol])-chanoffset); chancol = (chancol + 1) % 16; if (! chancol) //Keep transmit power updated A7105_SetPower(); } - return 1460; + return 1510; //1460 on deviation but not working with the latest V911 bricks... Turnigy 9X v2 is 1533, Flysky TX for 9XR/9XR Pro is 1510, V911 TX is 1490. } uint16_t initFlySky() { //A7105_Reset(); A7105_Init(INIT_FLYSKY); //flysky_init(); - if (rx_tx_addr[3] > 0x90) // limit offset to 9 as higher values don't work with some RX (ie V912) - rx_tx_addr[3] = rx_tx_addr[3] - 0x70; - chanrow=rx_tx_addr[3] % 16; + if ((rx_tx_addr[3]&0xF0) > 0x90) // limit offset to 9 as higher values don't work with some RX (ie V912) + rx_tx_addr[3]=rx_tx_addr[3]-0x70; + chanrow=rx_tx_addr[3] & 0x0F; chancol=0; - chanoffset=rx_tx_addr[3] / 16; + chanoffset=rx_tx_addr[3]/16; - if(IS_AUTOBIND_FLAG_on) bind_counter = FLYSKY_BIND_COUNT; else diff --git a/Multiprotocol/FrSkyX_cc2500.ino b/Multiprotocol/FrSkyX_cc2500.ino index dc6e2f2..5e29950 100644 --- a/Multiprotocol/FrSkyX_cc2500.ino +++ b/Multiprotocol/FrSkyX_cc2500.ino @@ -17,293 +17,319 @@ */ #if defined(FRSKYX_CC2500_INO) - - #include "iface_cc2500.h" - - uint8_t chanskip; - uint8_t calData[48][3]; - uint8_t channr; - uint8_t pass_ = 1 ; - uint8_t counter_rst; - uint8_t ctr; - uint8_t FS_flag=0; - // uint8_t ptr[4]={0x01,0x12,0x23,0x30}; - //uint8_t ptr[4]={0x00,0x11,0x22,0x33}; - - const PROGMEM uint8_t hop_data[]={ - 0x02, 0xD4, 0xBB, 0xA2, 0x89, - 0x70, 0x57, 0x3E, 0x25, 0x0C, - 0xDE, 0xC5, 0xAC, 0x93, 0x7A, - 0x61, 0x48, 0x2F, 0x16, 0xE8, - 0xCF, 0xB6, 0x9D, 0x84, 0x6B, - 0x52, 0x39, 0x20, 0x07, 0xD9, - 0xC0, 0xA7, 0x8E, 0x75, 0x5C, - 0x43, 0x2A, 0x11, 0xE3, 0xCA, - 0xB1, 0x98, 0x7F, 0x66, 0x4D, - 0x34, 0x1B, 0x00, 0x1D, 0x03 - }; - static uint8_t __attribute__((unused)) hop(uint8_t byte) - { - return pgm_read_byte_near(&hop_data[byte]); - } +#include "iface_cc2500.h" - static void __attribute__((unused)) set_start(uint8_t ch ) - { - cc2500_strobe(CC2500_SIDLE); - cc2500_writeReg(CC2500_23_FSCAL3, calData[ch][0]); - cc2500_writeReg(CC2500_24_FSCAL2, calData[ch][1]); - cc2500_writeReg(CC2500_25_FSCAL1, calData[ch][2]); - cc2500_writeReg(CC2500_0A_CHANNR, ch==47?0:pgm_read_word(&hop_data[ch])); - } +uint8_t chanskip; +uint8_t channr; +uint8_t counter_rst; +uint8_t ctr; +uint8_t FS_flag=0; +uint8_t seq_last_sent; +uint8_t seq_last_rcvd; + +const PROGMEM uint8_t hop_data[]={ + 0x02, 0xD4, 0xBB, 0xA2, 0x89, + 0x70, 0x57, 0x3E, 0x25, 0x0C, + 0xDE, 0xC5, 0xAC, 0x93, 0x7A, + 0x61, 0x48, 0x2F, 0x16, 0xE8, + 0xCF, 0xB6, 0x9D, 0x84, 0x6B, + 0x52, 0x39, 0x20, 0x07, 0xD9, + 0xC0, 0xA7, 0x8E, 0x75, 0x5C, + 0x43, 0x2A, 0x11, 0xE3, 0xCA, + 0xB1, 0x98, 0x7F, 0x66, 0x4D, + 0x34, 0x1B, 0x00, 0x1D, 0x03 +}; + +static uint8_t __attribute__((unused)) hop(uint8_t byte) +{ + return pgm_read_byte_near(&hop_data[byte]); +} + +static void __attribute__((unused)) set_start(uint8_t ch ) +{ + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_23_FSCAL3, calData[ch][0]); + CC2500_WriteReg(CC2500_24_FSCAL2, calData[ch][1]); + CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch][2]); + CC2500_WriteReg(CC2500_0A_CHANNR, ch==47? 0:pgm_read_word(&hop_data[ch])); +} + +static void __attribute__((unused)) frskyX_init() +{ + CC2500_Reset(); - static void __attribute__((unused)) frskyX_init() + for(uint8_t i=0;i<36;i++) { - CC2500_Reset(); + uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]); + uint8_t val=pgm_read_byte_near(&cc2500_conf[i][1]); - for(uint8_t i=0;i<36;i++) - { - uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]); - uint8_t val=pgm_read_byte_near(&cc2500_conf[i][1]); - - if(reg==CC2500_06_PKTLEN) - val=0x1E; - else - if(reg==CC2500_08_PKTCTRL0) - val=0x01; - else - if(reg==CC2500_0B_FSCTRL1) - val=0x0A; - else - if(reg==CC2500_10_MDMCFG4) - val=0x7B; - else - if(reg==CC2500_11_MDMCFG3) - val=0x61; - else - if(reg==CC2500_12_MDMCFG2) - val=0x13; - else - if(reg==CC2500_15_DEVIATN) - val=0x51; - - cc2500_writeReg(reg,val); - } + if(reg==CC2500_06_PKTLEN) + val=0x1E; + else + if(reg==CC2500_08_PKTCTRL0) + val=0x01; + else + if(reg==CC2500_0B_FSCTRL1) + val=0x0A; + else + if(reg==CC2500_10_MDMCFG4) + val=0x7B; + else + if(reg==CC2500_11_MDMCFG3) + val=0x61; + else + if(reg==CC2500_12_MDMCFG2) + val=0x13; + else + if(reg==CC2500_15_DEVIATN) + val=0x51; + + CC2500_WriteReg(reg,val); + } - cc2500_writeReg(CC2500_07_PKTCTRL1, 0x04); - cc2500_writeReg(CC2500_0C_FSCTRL0, option); - cc2500_strobe(CC2500_SIDLE); - // - for(uint8_t c=0;c < 47;c++){//calibrate hop channels - cc2500_strobe(CC2500_SIDLE); - cc2500_writeReg(CC2500_0A_CHANNR,pgm_read_word(&hop_data[c])); - cc2500_strobe(CC2500_SCAL); - delayMicroseconds(900);// - calData[c][0] = cc2500_readReg(CC2500_23_FSCAL3); - calData[c][1] = cc2500_readReg(CC2500_24_FSCAL2); - calData[c][2] = cc2500_readReg(CC2500_25_FSCAL1); - } - cc2500_strobe(CC2500_SIDLE); - cc2500_writeReg(CC2500_0A_CHANNR,0x00); - cc2500_strobe(CC2500_SCAL); - delayMicroseconds(900); - calData[47][0] = cc2500_readReg(CC2500_23_FSCAL3); - calData[47][1] = cc2500_readReg(CC2500_24_FSCAL2); - calData[47][2] = cc2500_readReg(CC2500_25_FSCAL1); - //#######END INIT######## + CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x04); + CC2500_WriteReg(CC2500_0C_FSCTRL0, option); + CC2500_Strobe(CC2500_SIDLE); + // + for(uint8_t c=0;c < 47;c++) + {//calibrate hop channels + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR,pgm_read_word(&hop_data[c])); + CC2500_Strobe(CC2500_SCAL); + delayMicroseconds(900);// + calData[c][0] = CC2500_ReadReg(CC2500_23_FSCAL3); + calData[c][1] = CC2500_ReadReg(CC2500_24_FSCAL2); + calData[c][2] = CC2500_ReadReg(CC2500_25_FSCAL1); } - - static void __attribute__((unused)) initialize_data(uint8_t adr) - { - cc2500_writeReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack - cc2500_writeReg(CC2500_18_MCSM0, 0x8); - cc2500_writeReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]); - cc2500_writeReg(CC2500_07_PKTCTRL1,0x05); - } - + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR,0x00); + CC2500_Strobe(CC2500_SCAL); + delayMicroseconds(900); + calData[47][0] = CC2500_ReadReg(CC2500_23_FSCAL3); + calData[47][1] = CC2500_ReadReg(CC2500_24_FSCAL2); + calData[47][2] = CC2500_ReadReg(CC2500_25_FSCAL1); + //#######END INIT######## +} + +static void __attribute__((unused)) initialize_data(uint8_t adr) +{ + CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack + CC2500_WriteReg(CC2500_18_MCSM0, 0x8); + CC2500_WriteReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]); + CC2500_WriteReg(CC2500_07_PKTCTRL1,0x05); +} +/* static uint8_t __attribute__((unused)) crc_Byte( uint8_t byte ) { crc = (crc<<8) ^ pgm_read_word(&CRCTable[((uint8_t)(crc>>8) ^ byte) & 0xFF]); return byte; } - - static uint16_t __attribute__((unused)) scaleForPXX( uint8_t i ) - { //mapped 860,2140(125%) range to 64,1984(PXX values); - return (uint16_t)(((Servo_data[i]-PPM_MIN)*3)>>1)+64; - } +*/ +static 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; +} + + // 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182 + //64=860,1024=1500,1984=2140//Taranis 125% + +static uint16_t __attribute__((unused)) scaleForPXX( uint8_t i ) +{ //mapped 860,2140(125%) range to 64,1984(PXX values); + return (uint16_t)(((Servo_data[i]-PPM_MIN)*3)>>1)+64; +} + +static void __attribute__((unused)) frskyX_build_bind_packet() +{ + packet[0] = 0x1D; + packet[1] = 0x03; + packet[2] = 0x01; + // + packet[3] = rx_tx_addr[3]; + packet[4] = rx_tx_addr[2]; + int idx = ((state -FRSKY_BIND) % 10) * 5; + packet[5] = idx; + packet[6] = pgm_read_word(&hop_data[idx++]); + packet[7] = pgm_read_word(&hop_data[idx++]); + packet[8] = pgm_read_word(&hop_data[idx++]); + packet[9] = pgm_read_word(&hop_data[idx++]); + packet[10] = pgm_read_word(&hop_data[idx++]); + packet[11] = 0x02; + packet[12] = RX_num; + // + memset(&packet[13], 0, 15); + uint16_t lcrc = crc_x(&packet[3], 25); + // + packet[28] = lcrc >> 8; + packet[29] = lcrc; + // +} + +static void __attribute__((unused)) frskyX_data_frame() +{ + //0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12 + // + static uint8_t lpass; + uint16_t chan_0 ; + uint16_t chan_1 ; + uint8_t startChan = 0; + // + packet[0] = 0x1D; + packet[1] = rx_tx_addr[3]; + packet[2] = rx_tx_addr[2]; + packet[3] = 0x02; + // + packet[4] = (ctr<<6)+channr; + packet[5] = counter_rst; + packet[6] = RX_num; + //FLAGS 00 - standard packet + //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet + //20 - range check packet + packet[7] = FS_flag; + packet[8] = 0; + // + if ( lpass & 1 ) + startChan += 8 ; - static void __attribute__((unused)) frskyX_build_bind_packet() - { - crc=0; - packet[0] = 0x1D; - packet[1] = 0x03; - packet[2] = 0x01; - // - packet[3] = crc_Byte(rx_tx_addr[3]); - packet[4] = crc_Byte(rx_tx_addr[2]); - int idx = ((state -FRSKY_BIND) % 10) * 5; - packet[5] = crc_Byte(idx); - packet[6] = crc_Byte(pgm_read_word(&hop_data[idx++])); - packet[7] = crc_Byte(pgm_read_word(&hop_data[idx++])); - packet[8] = crc_Byte(pgm_read_word(&hop_data[idx++])); - packet[9] = crc_Byte(pgm_read_word(&hop_data[idx++])); - packet[10] = crc_Byte(pgm_read_word(&hop_data[idx++])); - packet[11] = crc_Byte(0x02); - packet[12] = crc_Byte(RX_num); + for(uint8_t i = 0; i <12 ; i+=3) + {//12 bytes + chan_0 = scaleForPXX(startChan); + if(lpass & 1 ) + chan_0+=2048; + startChan+=1; // - for(uint8_t i=13;i<28;i++) - packet[i]=crc_Byte(0); + chan_1 = scaleForPXX(startChan); + if(lpass & 1 ) + chan_1+= 2048; + startChan+=1; // - packet[28]=highByte(crc); - packet[29]=lowByte(crc); - // - } - - static void __attribute__((unused)) frskyX_data_frame() - { - //0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12 - // - uint8_t lpass = pass_ ; - uint16_t chan_0 ; - uint16_t chan_1 ; - uint8_t flag2 = 0; - uint8_t startChan = 0; - crc = 0; - //static uint8_t p = 0; - // - packet[0] = 0x1D; - packet[1] = rx_tx_addr[3]; - packet[2] = rx_tx_addr[2]; - packet[3] = crc_Byte(0x02); - // - packet[4] = crc_Byte((ctr<<6)+channr); //*64 - packet[5] = crc_Byte(counter_rst); - packet[6] = crc_Byte(RX_num); - // FLAGS 00 - standard packet - //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet - //20 - range check packet - packet[7] = crc_Byte(FS_flag); - packet[8] = crc_Byte(flag2); - // - if ( lpass & 1 ) - startChan += 8 ; - - for(uint8_t i = 0; i <12 ; i+=3) - {//12 bytes - chan_0 = scaleForPXX(startChan); - if(lpass & 1 ) - chan_0+=2048; - - packet[9+i] = crc_Byte(lowByte(chan_0));//3 bytes*4 - startChan++; - chan_1 = scaleForPXX(startChan); - if(lpass & 1 ) - chan_1+= 2048; - - startChan++; - packet[9+i+1]=crc_Byte((((chan_0>>8) & 0x0F)|(chan_1 << 4))); - packet[9+i+2]=crc_Byte(chan_1>>4); - } - //packet[21]=crc_Byte(0x08);//first - packet[21]=crc_Byte(0x80);//??? when received first telemetry frame is changed to 0x80 - //packet[21]=crc_Byte(ptr[p]);//??? - //p=(p+1)%4;//repeating 4 bytes sequence pattern every 4th frame. - - pass_=lpass+1; - - for (uint8_t i=22;i<28;i++) - packet[i]=crc_Byte(0); - - packet[28]=highByte(crc); - packet[29]=lowByte(crc); + 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; } - uint16_t ReadFrSkyX() - { - switch(state) - { - default: - set_start(47); - CC2500_SetPower(); - cc2500_strobe(CC2500_SFRX); - // - frskyX_build_bind_packet(); - cc2500_strobe(CC2500_SIDLE); - cc2500_writeFifo(packet, packet[0]+1); - state++; - return 9000; - case FRSKY_BIND_DONE: - initialize_data(0); - channr=0; - BIND_DONE; - state++; - break; - case FRSKY_DATA1: - LED_ON; - CC2500_SetTxRxMode(TX_EN); - set_start(channr); - CC2500_SetPower(); - cc2500_strobe(CC2500_SFRX); - channr = (channr+chanskip)%47; - cc2500_strobe(CC2500_SIDLE); - cc2500_writeFifo(packet, packet[0]+1); - // - frskyX_data_frame(); - state++; - return 5500; - case FRSKY_DATA2: - CC2500_SetTxRxMode(RX_EN); - cc2500_strobe(CC2500_SIDLE); - state++; - return 200; - case FRSKY_DATA3: - cc2500_strobe(CC2500_SRX); - state++; - return 3000; - case FRSKY_DATA4: - len = cc2500_readReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; - if (len &&(len>8;//high byte + packet[29]=lcrc;//low byte +} - uint16_t initFrSkyX() - { - while(!chanskip) - { - randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7)); - chanskip=random(0xfefefefe)%47; - } - while((chanskip-ctr)%4) - ctr=(ctr+1)%4; - - counter_rst=(chanskip-ctr)>>2; - //for test*************** - //rx_tx_addr[3]=0xB3; - //rx_tx_addr[2]=0xFD; - //************************ - frskyX_init(); - // - if(IS_AUTOBIND_FLAG_on) - { - state = FRSKY_BIND; - initialize_data(1); - } - else - { - state = FRSKY_DATA1; +uint16_t ReadFrSkyX() +{ + switch(state) + { + default: + set_start(47); + CC2500_SetPower(); + CC2500_Strobe(CC2500_SFRX); + // + frskyX_build_bind_packet(); + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteData(packet, packet[0]+1); + state++; + return 9000; + case FRSKY_BIND_DONE: initialize_data(0); - } - return 10000; - } + channr=0; + BIND_DONE; + state++; + break; + case FRSKY_DATA1: + LED_ON; + CC2500_SetTxRxMode(TX_EN); + set_start(channr); + CC2500_SetPower(); + CC2500_Strobe(CC2500_SFRX); + channr = (channr+chanskip)%47; + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteData(packet, packet[0]+1); + // + frskyX_data_frame(); + state++; + return 5500; + case FRSKY_DATA2: + CC2500_SetTxRxMode(RX_EN); + CC2500_Strobe(CC2500_SIDLE); + state++; + return 200; + case FRSKY_DATA3: + CC2500_Strobe(CC2500_SRX); + state++; + return 3000; + case FRSKY_DATA4: + len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; + if (len && (len100) + {//~1sec + seq_last_sent = 0; + seq_last_rcvd = 8; + counter=0; + } + } + state = FRSKY_DATA1; + return 300; + } + return 1; +} + +uint16_t initFrSkyX() +{ + while(!chanskip) + { + randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7)); + chanskip=random(0xfefefefe)%47; + } + while((chanskip-ctr)%4) + ctr=(ctr+1)%4; + + counter_rst=(chanskip-ctr)>>2; + //for test*************** + //rx_tx_addr[3]=0xB3; + //rx_tx_addr[2]=0xFD; + //************************ + frskyX_init(); + CC2500_SetTxRxMode(TX_EN); + // + if(IS_AUTOBIND_FLAG_on) + { + state = FRSKY_BIND; + initialize_data(1); + } + else + { + state = FRSKY_DATA1; + initialize_data(0); + } + seq_last_sent = 0; + seq_last_rcvd = 8; + return 10000; +} #endif \ No newline at end of file diff --git a/Multiprotocol/FrSky_cc2500.ino b/Multiprotocol/FrSky_cc2500.ino index ec17450..85f468e 100644 --- a/Multiprotocol/FrSky_cc2500.ino +++ b/Multiprotocol/FrSky_cc2500.ino @@ -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; diff --git a/Multiprotocol/Makefile.xmega b/Multiprotocol/Makefile.xmega new file mode 100644 index 0000000..3c596b7 --- /dev/null +++ b/Multiprotocol/Makefile.xmega @@ -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 +# 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 + + + + diff --git a/Multiprotocol/Multiprotocol.cpp.xmega b/Multiprotocol/Multiprotocol.cpp.xmega new file mode 100644 index 0000000..87ebf73 --- /dev/null +++ b/Multiprotocol/Multiprotocol.cpp.xmega @@ -0,0 +1,476 @@ +#define ARDUINO_AVR_PRO 1 +//#define __AVR_ATmega328P__ 1 + +#define XMEGA 1 + +#include +#include +#include + +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() ; + } +} + diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index 41d3ac9..721ae05 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -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< 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 diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index cd62a62..d9be20b 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -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 #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<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< micros()) - { // Callback did not took more than requested time for next callback - if(next_callback>32000) - { // next_callback should not be more than 32767 so we will wait here... - delayMicroseconds(next_callback-2000); - cli(); // disable global int - OCR1A=TCNT1+4000; - sei(); // enable global int +#endif + do + { + next_callback=cb(); + while(next_callback>4000) + { // start to wait here as much as we can... + next_callback=next_callback-2000; + cli(); // disable global int +#ifdef XMEGA + TCC1.CCA +=2000*2; // set compare A for callback + TCC1.INTFLAGS = TC1_CCAIF_bm ; // clear compare A=callback flag + sei(); // enable global int + while((TCC1.INTFLAGS & TC1_CCAIF_bm) == 0); // wait 2ms... +#else + OCR1A+=2000*2; // set compare A for callback + TIFR1=(1<=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< UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; @@ -610,12 +717,25 @@ static void Mprotocol_serial_init() UDR0; //enable reception and RC complete interrupt UCSR0B = (1<RXBUFFER_SIZE) { // A full frame has been received - TIMSK1 &=~(1<=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<. + */ +// 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 \ No newline at end of file diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino index 50553b4..1b90ceb 100644 --- a/Multiprotocol/Telemetry.ino +++ b/Multiprotocol/Telemetry.ino @@ -4,173 +4,216 @@ //************************************* #if defined TELEMETRY - #if defined FRSKYX_CC2500_INO - #define SPORT_TELEMETRY - #endif - #if defined FRSKY_CC2500_INO - #define HUB_TELEMETRY - #endif - #if defined SPORT_TELEMETRY - #define SPORT_TELEMETRY - #define SPORT_TIME 12000 - uint32_t last=0; - uint8_t sport_counter=0; - uint8_t RxBt=0; - uint8_t rssi; - uint8_t ADC2; - #endif - #if defined HUB_TELEMETRY - #define MAX_PKTX 10 - uint8_t pktx[MAX_PKTX]; - uint8_t index; - uint8_t prev_index; - uint8_t pass = 0; - #endif + +#if defined DSM2_CYRF6936_INO + #define DSM_TELEMETRY +#endif +#if defined FRSKYX_CC2500_INO + #define SPORT_TELEMETRY +#endif +#if defined FRSKY_CC2500_INO + #define HUB_TELEMETRY +#endif +#if defined SPORT_TELEMETRY + #define SPORT_TIME 12000 + #define FRSKY_SPORT_PACKET_SIZE 8 + uint32_t last = 0; + uint8_t sport_counter=0; + uint8_t RxBt = 0; + uint8_t rssi; + uint8_t sport = 0; +#endif +#if defined HUB_TELEMETRY #define USER_MAX_BYTES 6 - uint8_t frame[18]; - - void frskySendStuffed() + 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++) { - Serial_write(0x7E); - for (uint8_t i = 0; i < 9; i++) + if ((frame[i] == START_STOP) || (frame[i] == BYTESTUFF)) { - if ((frame[i] == 0x7e) || (frame[i] == 0x7d)) - { - Serial_write(0x7D); - frame[i] ^= 0x20; - } - Serial_write(frame[i]); + Serial_write(BYTESTUFF); + frame[i] ^= STUFF_MASK; } - Serial_write(0x7E); + Serial_write(frame[i]); } + 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; - } + RSSI_dBm = (((uint16_t)(pktt[len-2])*18)>>5); + if(pktt[len-2] >=128) + RSSI_dBm -= 82; + else + RSSI_dBm += 65; +} - void frsky_check_telemetry(uint8_t *pkt,uint8_t len) - { - if(pkt[1] != rx_tx_addr[3] || pkt[2] != rx_tx_addr[2] || len != pkt[0] + 3) - {//only packets with the required id and packet length - for(uint8_t i=3;i<6;i++) - pktt[i]=0; - return; - } - else - { - for (uint8_t i=3;i0) - telemetry_counter=(telemetry_counter+1)%32; - } - } - - void frsky_link_frame() - { - frame[0] = 0xFE; - if ((cur_protocol[0]&0x1F)==MODE_FRSKY) - { - compute_RSSIdbm(); - frame[1] = pktt[3]; - frame[2] = pktt[4]; - frame[3] = (uint8_t)RSSI_dBm; - frame[4] = pktt[5]*2; - } - else - if ((cur_protocol[0]&0x1F)==MODE_HUBSAN) - { - frame[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V - frame[2] = frame[1]; - frame[3] = 0x00; - frame[4] = (uint8_t)RSSI_dBm; +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> 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 } - frame[5] = frame[6] = frame[7] = frame[8] = 0; + } +#endif + } +} + +void frsky_link_frame() +{ + frame[0] = 0xFE; + if ((cur_protocol[0]&0x1F)==MODE_FRSKY) + { + compute_RSSIdbm(); + frame[1] = pktt[3]; + frame[2] = pktt[4]; + frame[3] = (uint8_t)RSSI_dBm; + frame[4] = pktt[5]*2; + } + else + if ((cur_protocol[0]&0x1F)==MODE_HUBSAN) + { + frame[1] = v_lipo*2; //v_lipo; common 0x2A=42/10=4.2V + frame[2] = frame[1]; + frame[3] = 0x00; + frame[4] = (uint8_t)RSSI_dBm; + } + frame[5] = frame[6] = frame[7] = frame[8] = 0; + frskySendStuffed(); +} + +#if defined HUB_TELEMETRY +void frsky_user_frame() +{ + uint8_t indexx = 0, c=0, j=8, n=0, i; + + if(pktt[6]>0 && pktt[6]<=10) + {//only valid hub frames + frame[0] = 0xFD; + frame[2] = pktt[7]; + switch(pass) + { + case 0: + indexx=pktt[6]; + for(i=0;i0 && pktt[6]<=MAX_PKTX) - {//only valid hub frames - frame[0] = 0xFD; - frame[1] = 0; - frame[2] = pktt[7]; - - switch(pass) - { - case 0: - indexx=pktt[6]; - for(i=0;i0) - { - crc_s += p[i]; //0-1FF - crc_s += crc_s >> 8; //0-100 - crc_s &= 0x00ff; - } - } - } - - void sportIdle() - { - Serial_write(0x7e); - } + [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 - void sportSendFrame() - { - //at the moment only SWR RSSI,RxBt and A2. - sport_counter = (sport_counter + 1) %9; - - for (uint8_t i=5;i<8;i++) - frame[i]=0; - - switch (sport_counter) - { - case 0: // SWR - frame[0] = 0x98; - frame[1] = 0x10; - frame[2] = 0x05; - frame[3] = 0xf1; - frame[4] = 0x20;//dummy values if swr 20230f00 - frame[5] = 0x23; - frame[6] = 0x0F; - frame[7] = 0x00; - break; - case 1: // RSSI - frame[0] = 0x98; - frame[1] = 0x10; - frame[2] = 0x01; - frame[3] = 0xf1; - frame[4] = rssi; - break; - case 2: //BATT - frame[0] = 0x98; - frame[1] = 0x10; - frame[2] = 0x04; - frame[3] = 0xf1; - frame[4] = RxBt;//a1; - break; - case 3: //ADC2(A2) - frame[0] = 0x1A; - frame[1] = 0x10; - frame[2] = 0x03; - frame[3] = 0xf1; - frame[4] = ADC2;//a2;; - break; - default: - sportIdle(); - return; - } - sportSend(frame); - } +0x7E 0x00 0x03 0x7E 0x00 +0x1A 0x00 0xF1 0x1A 0x00 +0x10 0x00 0xD7 0x10 0x00 +0x03 0x7E 0x00 0x03 0x7E +0xF1 0x1A 0x00 0xF1 0x1A +0xD7 0x10 0x00 0xD7 0x10 + +0xE1 0x1C 0xD0 0xEE 0x33 +0x34 0x0A 0xC3 0x56 0xF3 + + */ +void sportSend(uint8_t *p) +{ + uint16_t crc_s = 0; + Serial_write(START_STOP);//+9 + for (uint8_t i = 0; i < 9; i++) + { + if (i == 8) + p[i] = 0xff - crc_s; - void process_sport_data()//only for ADC2 - { - uint8_t j=7; - if(pktt[6]>0 && pktt[6]<=USER_MAX_BYTES) - { - for(uint8_t i=0;i<6;i++) - if(pktt[j++]==0x03) - if(pktt[j]==0xF1) - { - ADC2=pktt[j+1]; - break; - } - pktt[6]=0;//new frame - } + if ((p[i] == START_STOP) || (p[i] == BYTESTUFF)) + { + 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 + crc_s += crc_s >> 8; //0-100 + crc_s &= 0x00ff; } - #endif - - - void frskyUpdate() - { - if(telemetry_link && (cur_protocol[0]&0x1F) != MODE_FRSKYX ) - { - frsky_link_frame(); - telemetry_link=0; - return; - } - #if defined HUB_TELEMETRY - if(!telemetry_link && (cur_protocol[0]&0x1F) != MODE_HUBSAN && (cur_protocol[0]&0x1F) != MODE_FRSKYX) - { - frsky_user_frame(); - return; - } - #endif - #if defined SPORT_TELEMETRY - if ((cur_protocol[0]&0x1F)==MODE_FRSKYX) - { - if(telemetry_link) - { - process_sport_data(); - if(pktt[4]>0x36) - rssi=pktt[4]/2; - else - RxBt=pktt[4]; - telemetry_link=0; - } - uint32_t now = micros(); - if ((now - last) > SPORT_TIME) - { - sportSendFrame(); - last = now; - } - } - #endif } +} + +void sportIdle() +{ + Serial_write(START_STOP); +} + +void sportSendFrame() +{ + uint8_t i; + sport_counter = (sport_counter + 1) %36; + if(sport_counter<3) + { + frame[0] = 0x98; + frame[1] = 0x10; + for (i=5;i<8;i++) + frame[i]=0; + } + switch (sport_counter) + { + case 0: + frame[2] = 0x05; + frame[3] = 0xf1; + frame[4] = 0x20;//dummy values if swr 20230f00 + frame[5] = 0x23; + frame[6] = 0x0F; + break; + case 1: // RSSI + frame[2] = 0x01; + frame[3] = 0xf1; + frame[4] = rssi; + break; + case 2: //BATT + frame[2] = 0x04; + frame[3] = 0xf1; + frame[4] = RxBt;//a1; + break; + default: + if(sport) + { + for (i=0;i= FRSKY_SPORT_PACKET_SIZE) + {//8 bytes no crc + sport = 1;//ok to send + pass = 0;//reset + } +} + +#endif + +void frskyUpdate() +{ + #if defined DSM_TELEMETRY + if(telemetry_link && (cur_protocol[0]&0x1F) == MODE_DSM2 ) + { // DSM2 + DSM2_frame(); + telemetry_link=0; + return; + } + #endif + if(telemetry_link && (cur_protocol[0]&0x1F) != MODE_FRSKYX ) + { // FrSky + Hubsan + frsky_link_frame(); + telemetry_link=0; + return; + } + #if defined HUB_TELEMETRY + if(!telemetry_link && (cur_protocol[0]&0x1F) == MODE_FRSKY) + { // FrSky + frsky_user_frame(); + return; + } + #endif + #if defined SPORT_TELEMETRY + if ((cur_protocol[0]&0x1F)==MODE_FRSKYX) + { // FrSkyX + if(telemetry_link) + { + if(pktt[4]>0x36) + rssi=pktt[4]>>1; + else + RxBt=pktt[4]; + for (uint8_t i=0; i < pktt[6]; i++) + proces_sport_data(pktt[7+i]); + telemetry_link=0; + } + uint32_t now = micros(); + if ((now - last) > SPORT_TIME) + { + sportSendFrame(); + last = now; + } + } + #endif +} + #endif \ No newline at end of file diff --git a/Multiprotocol/WMath.cpp.xmega b/Multiprotocol/WMath.cpp.xmega new file mode 100644 index 0000000..42731e4 --- /dev/null +++ b/Multiprotocol/WMath.cpp.xmega @@ -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; } \ No newline at end of file diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index fb40ddd..e4fb682 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -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