update to last multi modification

This commit is contained in:
midelic 2016-09-24 01:04:35 +03:00 committed by GitHub
parent 2ab47c08c8
commit ee10ba29a4
29 changed files with 980 additions and 712 deletions

View File

@ -74,17 +74,17 @@ uint16_t ASSAN_callback()
NRF24L01_SetTxRxMode(RX_EN); NRF24L01_SetTxRxMode(RX_EN);
phase++; phase++;
case ASSAN_BIND1: case ASSAN_BIND1:
//Wait for RX to send the frames //Wait for receiver to send the frames
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR)) if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ //Something has been received { //Something has been received
NRF24L01_ReadPayload(packet, ASSAN_PACKET_SIZE); NRF24L01_ReadPayload(packet, ASSAN_PACKET_SIZE);
if(packet[19]==0x13) if(packet[19]==0x13)
{ //Last packet received { //Last frame received
phase++; phase++;
//Switch to TX //Switch to TX
NRF24L01_SetTxRxMode(TXRX_OFF); NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
//Prepare packet //Prepare bind packet
memset(packet,0x05,ASSAN_PACKET_SIZE-5); memset(packet,0x05,ASSAN_PACKET_SIZE-5);
packet[15]=0x99; packet[15]=0x99;
for(uint8_t i=0;i<4;i++) for(uint8_t i=0;i<4;i++)
@ -134,7 +134,7 @@ uint16_t ASSAN_callback()
static void __attribute__((unused)) ASSAN_initialize_txid() static void __attribute__((unused)) ASSAN_initialize_txid()
{ {
/* //Renaud TXID with Freq=36 and alternate freq 67 or 68 or 69 or 70 or 71 or 73 or 74 or 75 or 78 and may be more... /* //Renaud TXID with Freq=36 and alternate Freq 67 or 68 or 69 or 70 or 71 or 73 or 74 or 75 or 78 and may be more...
packet[23]=0x22; packet[23]=0x22;
packet[22]=0x37; packet[22]=0x37;
packet[21]=0xFA; packet[21]=0xFA;
@ -153,19 +153,15 @@ static void __attribute__((unused)) ASSAN_initialize_txid()
freq=((freq%25)+2)<<1; freq=((freq%25)+2)<<1;
if(freq&0x02) freq|=0x01; if(freq&0x02) freq|=0x01;
hopping_frequency[0]=freq; hopping_frequency[0]=freq;
// Alternate frequency // Alternate frequency has some random
hopping_frequency[1]=freq*2-6;
do do
{ {
#if defined STM32_board #if defined STM32_board
randomSeed((uint32_t)analogRead(PB0) << 10 | analogRead(PB1)); randomSeed((uint32_t)analogRead(PB0) << 10 | analogRead(PB1));
#else #endif
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
#endif
freq2=random(0xfefefefe)%9; freq2=random(0xfefefefe)%9;
freq2+=freq*2-5; freq2+=freq*2-5;
} }
while( (freq2>118) || (freq2<freq+1) || (freq2==2*freq) ); while( (freq2>118) || (freq2<freq+1) || (freq2==2*freq) );
hopping_frequency[1]=freq2; // Add some random to the second channel hopping_frequency[1]=freq2; // Add some random to the second channel
} }

View File

@ -99,7 +99,7 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
// Power on, TX mode, 2byte CRC // Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing // Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? BAYANG_RF_BIND_CHANNEL:hopping_frequency[hopping_frequency_no++]); NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? BAYANG_RF_BIND_CHANNEL:hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no%=BAYANG_RF_NUM_CHANNELS; hopping_frequency_no%=BAYANG_RF_NUM_CHANNELS;

View File

@ -84,11 +84,11 @@ void CC2500_Strobe(uint8_t address)
{ {
// Toggle chip select signal // Toggle chip select signal
CC25_CSN_on; CC25_CSN_on;
_delay_us(30); delayMicroseconds(30);
CC25_CSN_off; CC25_CSN_off;
_delay_us(30); delayMicroseconds(30);
CC25_CSN_on; CC25_CSN_on;
_delay_us(45); delayMicroseconds(45);
CC2500_Strobe(CC2500_SRES); CC2500_Strobe(CC2500_SRES);
_delay_ms(100); _delay_ms(100);
} }
@ -96,7 +96,7 @@ void CC2500_Strobe(uint8_t address)
uint8_t CC2500_Reset() uint8_t CC2500_Reset()
{ {
CC2500_Strobe(CC2500_SRES); CC2500_Strobe(CC2500_SRES);
_delay_us(1000); delayMilliseconds(1);
CC2500_SetTxRxMode(TXRX_OFF); CC2500_SetTxRxMode(TXRX_OFF);
return CC2500_ReadReg(CC2500_0E_FREQ1) == 0xC4;//check if reset return CC2500_ReadReg(CC2500_0E_FREQ1) == 0xC4;//check if reset
} }

View File

@ -171,7 +171,7 @@ static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
// Power on, TX mode, 2byte CRC // Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing // Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (bind) if (bind)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, sub_protocol==H8_3D?hopping_frequency[0]:CG023_RF_BIND_CHANNEL); NRF24L01_WriteReg(NRF24L01_05_RF_CH, sub_protocol==H8_3D?hopping_frequency[0]:CG023_RF_BIND_CHANNEL);
else else

View File

@ -148,7 +148,7 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
// Power on, TX mode, 2byte CRC // Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing // Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (bind) if (bind)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CX10_RF_BIND_CHANNEL); NRF24L01_WriteReg(NRF24L01_05_RF_CH, CX10_RF_BIND_CHANNEL);
else else
@ -197,7 +197,7 @@ uint16_t CX10_callback()
} }
break; break;
case CX10_BIND2: case CX10_BIND2:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR)) if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready { // RX fifo data ready
XN297_ReadPayload(packet, packet_length); XN297_ReadPayload(packet, packet_length);
NRF24L01_SetTxRxMode(TXRX_OFF); NRF24L01_SetTxRxMode(TXRX_OFF);
@ -215,12 +215,12 @@ uint16_t CX10_callback()
NRF24L01_FlushTx(); NRF24L01_FlushTx();
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
CX10_Write_Packet(1); CX10_Write_Packet(1);
_delay_us(400); delayMicroseconds(400);
// switch to RX mode // switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF); NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx(); NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN); NRF24L01_SetTxRxMode(RX_EN);
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP) | BV(NRF24L01_00_PRIM_RX)); XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
} }
break; break;
case CX10_DATA: case CX10_DATA:

View File

@ -14,11 +14,7 @@
*/ */
#include "iface_cyrf6936.h" #include "iface_cyrf6936.h"
#ifdef XMEGA
#define XNOP() NOP()
#else
#define XNOP()
#endif
void CYRF_WriteRegister(uint8_t address, uint8_t data) void CYRF_WriteRegister(uint8_t address, uint8_t data)
@ -64,17 +60,19 @@ uint8_t CYRF_ReadRegister(uint8_t address)
uint8_t CYRF_Reset() uint8_t CYRF_Reset()
{ {
//CYRF_WriteRegister(CYRF_1D_MODE_OVERRIDE, 0x01);//software reset #ifdef CYRF_RST_HI
// _delay_us(200);// CYRF_RST_HI; //Hardware reset
CYRF_RST_HI; delayMicroseconds(100);
_delay_us(100);
CYRF_RST_LO; CYRF_RST_LO;
_delay_us(100); delayMicroseconds(100);
#endif
CYRF_WriteRegister(CYRF_1D_MODE_OVERRIDE, 0x01); //Software reset
delayMicroseconds(200);
CYRF_WriteRegister(CYRF_0C_XTAL_CTRL, 0xC0); //Enable XOUT as GPIO CYRF_WriteRegister(CYRF_0C_XTAL_CTRL, 0xC0); //Enable XOUT as GPIO
CYRF_WriteRegister(CYRF_0D_IO_CFG, 0x04); //Enable PACTL as GPIO CYRF_WriteRegister(CYRF_0D_IO_CFG, 0x04); //Enable PACTL as GPIO
CYRF_SetTxRxMode(TXRX_OFF); CYRF_SetTxRxMode(TXRX_OFF);
//Verify the CYRD chip is responding //Verify the CYRF chip is responding
return (CYRF_ReadRegister(CYRF_10_FRAMING_CFG) == 0xa5);//return if reset return (CYRF_ReadRegister(CYRF_10_FRAMING_CFG) == 0xa5);
} }
/* /*
@ -106,9 +104,15 @@ void CYRF_SetTxRxMode(uint8_t mode)
//Set the post tx/rx state //Set the post tx/rx state
CYRF_WriteRegister(CYRF_0F_XACT_CFG, mode == TX_EN ? 0x28 : 0x2C); // 4=IDLE, 8=TX, C=RX CYRF_WriteRegister(CYRF_0F_XACT_CFG, mode == TX_EN ? 0x28 : 0x2C); // 4=IDLE, 8=TX, C=RX
if(mode == TX_EN) if(mode == TX_EN)
#ifdef DSM_BLUE
CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x20); // XOUT=1, PACTL=0
else
CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x80); // XOUT=0, PACTL=1
#else
CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x80); // XOUT=1, PACTL=0 CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x80); // XOUT=1, PACTL=0
else else
CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x20); // XOUT=0, PACTL=1 CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x20); // XOUT=0, PACTL=1
#endif
} }
} }
/* /*
@ -134,6 +138,7 @@ void CYRF_SetPower(uint8_t val)
power=IS_POWER_FLAG_on?CYRF_HIGH_POWER:CYRF_LOW_POWER; power=IS_POWER_FLAG_on?CYRF_HIGH_POWER:CYRF_LOW_POWER;
if(IS_RANGE_FLAG_on) if(IS_RANGE_FLAG_on)
power=CYRF_RANGE_POWER; power=CYRF_RANGE_POWER;
power|=val;
if(prev_power != power) if(prev_power != power)
{ {
CYRF_WriteRegister(CYRF_03_TX_CFG, power); CYRF_WriteRegister(CYRF_03_TX_CFG, power);
@ -236,13 +241,13 @@ void CYRF_FindBestChannels(uint8_t *channels, uint8_t len, uint8_t minspace, uin
CYRF_ConfigCRCSeed(0x0000); CYRF_ConfigCRCSeed(0x0000);
CYRF_SetTxRxMode(RX_EN); CYRF_SetTxRxMode(RX_EN);
//Wait for pre-amp to switch from send to receive //Wait for pre-amp to switch from send to receive
_delay_us(1000); delayMilliseconds(1);
for(i = 0; i < NUM_FREQ; i++) for(i = 0; i < NUM_FREQ; i++)
{ {
CYRF_ConfigRFChannel(i); CYRF_ConfigRFChannel(i);
CYRF_ReadRegister(CYRF_13_RSSI); CYRF_ReadRegister(CYRF_13_RSSI);
CYRF_StartReceive(); CYRF_StartReceive();
_delay_us(10); delayMicroseconds(10);
rssi[i] = CYRF_ReadRegister(CYRF_13_RSSI); rssi[i] = CYRF_ReadRegister(CYRF_13_RSSI);
} }
@ -261,3 +266,37 @@ void CYRF_FindBestChannels(uint8_t *channels, uint8_t len, uint8_t minspace, uin
} }
CYRF_SetTxRxMode(TX_EN); CYRF_SetTxRxMode(TX_EN);
} }
#if defined(DEVO_CYRF6936_INO) || defined(J6PRO_CYRF6936_INO)
const uint8_t PROGMEM DEVO_j6pro_sopcodes[][8] = {
/* Note these are in order transmitted (LSB 1st) */
{0x3C, 0x37, 0xCC, 0x91, 0xE2, 0xF8, 0xCC, 0x91},
{0x9B, 0xC5, 0xA1, 0x0F, 0xAD, 0x39, 0xA2, 0x0F},
{0xEF, 0x64, 0xB0, 0x2A, 0xD2, 0x8F, 0xB1, 0x2A},
{0x66, 0xCD, 0x7C, 0x50, 0xDD, 0x26, 0x7C, 0x50},
{0x5C, 0xE1, 0xF6, 0x44, 0xAD, 0x16, 0xF6, 0x44},
{0x5A, 0xCC, 0xAE, 0x46, 0xB6, 0x31, 0xAE, 0x46},
{0xA1, 0x78, 0xDC, 0x3C, 0x9E, 0x82, 0xDC, 0x3C},
{0xB9, 0x8E, 0x19, 0x74, 0x6F, 0x65, 0x18, 0x74},
{0xDF, 0xB1, 0xC0, 0x49, 0x62, 0xDF, 0xC1, 0x49},
{0x97, 0xE5, 0x14, 0x72, 0x7F, 0x1A, 0x14, 0x72},
#if defined(J6PRO_CYRF6936_INO)
{0x82, 0xC7, 0x90, 0x36, 0x21, 0x03, 0xFF, 0x17},
{0xE2, 0xF8, 0xCC, 0x91, 0x3C, 0x37, 0xCC, 0x91}, //Note: the '03' was '9E' in the Cypress recommended table
{0xAD, 0x39, 0xA2, 0x0F, 0x9B, 0xC5, 0xA1, 0x0F}, //The following are the same as the 1st 8 above,
{0xD2, 0x8F, 0xB1, 0x2A, 0xEF, 0x64, 0xB0, 0x2A}, //but with the upper and lower word swapped
{0xDD, 0x26, 0x7C, 0x50, 0x66, 0xCD, 0x7C, 0x50},
{0xAD, 0x16, 0xF6, 0x44, 0x5C, 0xE1, 0xF6, 0x44},
{0xB6, 0x31, 0xAE, 0x46, 0x5A, 0xCC, 0xAE, 0x46},
{0x9E, 0x82, 0xDC, 0x3C, 0xA1, 0x78, 0xDC, 0x3C},
{0x6F, 0x65, 0x18, 0x74, 0xB9, 0x8E, 0x19, 0x74},
#endif
};
#endif
static void __attribute__((unused)) CYRF_PROGMEM_ConfigSOPCode(const uint8_t *data)
{
uint8_t code[8];
for(uint8_t i=0;i<8;i++)
code[i]=pgm_read_byte_near(&data[i]);
CYRF_ConfigSOPCode(code);
}

View File

@ -0,0 +1,620 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(DSM_CYRF6936_INO)
#include "iface_cyrf6936.h"
#define DSM_BIND_CHANNEL 0x0d //13 This can be any odd channel
//During binding we will send BIND_COUNT/2 packets
//One packet each 10msec
#define DSM_BIND_COUNT 300
enum {
DSM_BIND_WRITE=0,
DSM_BIND_CHECK,
DSM_BIND_READ,
DSM_CHANSEL,
DSM_CH1_WRITE_A,
DSM_CH1_CHECK_A,
DSM_CH2_WRITE_A,
DSM_CH2_CHECK_A,
DSM_CH2_READ_A,
DSM_CH1_WRITE_B,
DSM_CH1_CHECK_B,
DSM_CH2_WRITE_B,
DSM_CH2_CHECK_B,
DSM_CH2_READ_B,
};
//
uint8_t sop_col;
uint8_t DSM_orx=0;
uint8_t DSM_num_ch=0;
uint8_t ch_map[14];
const uint8_t PROGMEM ch_map_progmem[][12] = {
{0, 1, 2, 3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, //Guess
{0, 1, 2, 3, 4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, //Guess
{1, 5, 2, 3, 0, 4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, //HP6DSM
{1, 5, 2, 4, 3, 6, 0, 0xff, 0xff, 0xff, 0xff, 0xff}, //DX6i
{1, 5, 2, 3, 6, 0xff, 0xff, 4, 0, 7, 0xff, 0xff}, //DX8
{3, 2, 1, 5, 0, 4, 6, 7, 8, 0xff, 0xff, 0xff}, //DM9
{3, 2, 1, 5, 0, 4, 6, 7, 8, 9, 0xff, 0xff}, //Guess
{3, 2, 1, 5, 0, 4, 6, 7, 8, 9, 10, 0xff}, //Guess
{3, 2, 1, 5, 0, 4, 6, 7, 8, 9, 10, 11} }; //Guess
const uint8_t PROGMEM pncodes[5][9][8] = {
/* Note these are in order transmitted (LSB 1st) */
{ /* Row 0 */
/* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8},
/* Col 1 */ {0x88, 0x17, 0x13, 0x3B, 0x2D, 0xBF, 0x06, 0xD6},
/* Col 2 */ {0xF1, 0x94, 0x30, 0x21, 0xA1, 0x1C, 0x88, 0xA9},
/* Col 3 */ {0xD0, 0xD2, 0x8E, 0xBC, 0x82, 0x2F, 0xE3, 0xB4},
/* Col 4 */ {0x8C, 0xFA, 0x47, 0x9B, 0x83, 0xA5, 0x66, 0xD0},
/* Col 5 */ {0x07, 0xBD, 0x9F, 0x26, 0xC8, 0x31, 0x0F, 0xB8},
/* Col 6 */ {0xEF, 0x03, 0x95, 0x89, 0xB4, 0x71, 0x61, 0x9D},
/* Col 7 */ {0x40, 0xBA, 0x97, 0xD5, 0x86, 0x4F, 0xCC, 0xD1},
/* Col 8 */ {0xD7, 0xA1, 0x54, 0xB1, 0x5E, 0x89, 0xAE, 0x86}
},
{ /* Row 1 */
/* Col 0 */ {0x83, 0xF7, 0xA8, 0x2D, 0x7A, 0x44, 0x64, 0xD3},
/* Col 1 */ {0x3F, 0x2C, 0x4E, 0xAA, 0x71, 0x48, 0x7A, 0xC9},
/* Col 2 */ {0x17, 0xFF, 0x9E, 0x21, 0x36, 0x90, 0xC7, 0x82},
/* Col 3 */ {0xBC, 0x5D, 0x9A, 0x5B, 0xEE, 0x7F, 0x42, 0xEB},
/* Col 4 */ {0x24, 0xF5, 0xDD, 0xF8, 0x7A, 0x77, 0x74, 0xE7},
/* Col 5 */ {0x3D, 0x70, 0x7C, 0x94, 0xDC, 0x84, 0xAD, 0x95},
/* Col 6 */ {0x1E, 0x6A, 0xF0, 0x37, 0x52, 0x7B, 0x11, 0xD4},
/* Col 7 */ {0x62, 0xF5, 0x2B, 0xAA, 0xFC, 0x33, 0xBF, 0xAF},
/* Col 8 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97}
},
{ /* Row 2 */
/* Col 0 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97},
/* Col 1 */ {0x8E, 0x4A, 0xD0, 0xA9, 0xA7, 0xFF, 0x20, 0xCA},
/* Col 2 */ {0x4C, 0x97, 0x9D, 0xBF, 0xB8, 0x3D, 0xB5, 0xBE},
/* Col 3 */ {0x0C, 0x5D, 0x24, 0x30, 0x9F, 0xCA, 0x6D, 0xBD},
/* Col 4 */ {0x50, 0x14, 0x33, 0xDE, 0xF1, 0x78, 0x95, 0xAD},
/* Col 5 */ {0x0C, 0x3C, 0xFA, 0xF9, 0xF0, 0xF2, 0x10, 0xC9},
/* Col 6 */ {0xF4, 0xDA, 0x06, 0xDB, 0xBF, 0x4E, 0x6F, 0xB3},
/* Col 7 */ {0x9E, 0x08, 0xD1, 0xAE, 0x59, 0x5E, 0xE8, 0xF0},
/* Col 8 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E}
},
{ /* Row 3 */
/* Col 0 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E},
/* Col 1 */ {0x80, 0x69, 0x26, 0x80, 0x08, 0xF8, 0x49, 0xE7},
/* Col 2 */ {0x7D, 0x2D, 0x49, 0x54, 0xD0, 0x80, 0x40, 0xC1},
/* Col 3 */ {0xB6, 0xF2, 0xE6, 0x1B, 0x80, 0x5A, 0x36, 0xB4},
/* Col 4 */ {0x42, 0xAE, 0x9C, 0x1C, 0xDA, 0x67, 0x05, 0xF6},
/* Col 5 */ {0x9B, 0x75, 0xF7, 0xE0, 0x14, 0x8D, 0xB5, 0x80},
/* Col 6 */ {0xBF, 0x54, 0x98, 0xB9, 0xB7, 0x30, 0x5A, 0x88},
/* Col 7 */ {0x35, 0xD1, 0xFC, 0x97, 0x23, 0xD4, 0xC9, 0x88},
/* Col 8 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93}
// Wrong values used by Orange TX/RX
// /* Col 8 */ {0x88, 0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40}
},
{ /* Row 4 */
/* Col 0 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93},
/* Col 1 */ {0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C},
/* Col 2 */ {0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA},
/* Col 3 */ {0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC},
/* Col 4 */ {0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84},
/* Col 5 */ {0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7},
/* Col 6 */ {0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0},
/* Col 7 */ {0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1},
/* Col 8 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8}
},
};
static void __attribute__((unused)) read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
{
if(DSM_orx==1 && row==3 && col==7 && len==16)
{
uint8_t dec=0;
for(uint8_t i=0;i<len;i++)
{
if(i==8)
{
buf[8]=0x88;
dec=1;
}
else
buf[i]=pgm_read_byte_near( &pncodes[row][col][i-dec] );
}
}
else
for(uint8_t i=0;i<len;i++)
buf[i]=pgm_read_byte_near( &pncodes[row][col][i] );
}
static uint8_t __attribute__((unused)) get_pn_row(uint8_t channel)
{
return ((sub_protocol == DSMX_11 || sub_protocol == DSMX_22 )? (channel - 2) % 5 : channel % 5);
}
const uint8_t PROGMEM init_vals[][2] = {
{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},
{CYRF_35_AUTOCAL_OFFSET, 0x14},
{CYRF_06_RX_CFG, 0x4A},
{CYRF_1B_TX_OFFSET_LSB, 0x55},
{CYRF_1C_TX_OFFSET_MSB, 0x05},
{CYRF_0F_XACT_CFG, 0x24}, // Force Idle
{CYRF_03_TX_CFG, 0x38 | CYRF_BIND_POWER}, //Set 64chip, SDR mode
{CYRF_12_DATA64_THOLD, 0x0a},
{CYRF_0F_XACT_CFG, 0x04}, // Idle
{CYRF_39_ANALOG_CTRL, 0x01},
{CYRF_0F_XACT_CFG, 0x24}, //Force IDLE
{CYRF_29_RX_ABORT, 0x00}, //Clear RX abort
{CYRF_12_DATA64_THOLD, 0x0a}, //set pn correlation threshold
{CYRF_10_FRAMING_CFG, 0x4a}, //set sop len and threshold
{CYRF_29_RX_ABORT, 0x0f}, //Clear RX abort?
{CYRF_03_TX_CFG, 0x38 | CYRF_BIND_POWER}, //Set 64chip, SDR mode
{CYRF_10_FRAMING_CFG, 0x4E}, //0x4a}, //set sop len and threshold
{CYRF_1F_TX_OVERRIDE, 0x04}, //disable tx CRC
{CYRF_1E_RX_OVERRIDE, 0x14}, //disable rx crc
{CYRF_14_EOP_CTRL, 0x02}, //set EOP sync == 2
{CYRF_01_TX_LENGTH, 0x10}, //16byte packet
};
static void __attribute__((unused)) cyrf_config()
{
for(uint8_t i = 0; i < sizeof(init_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&init_vals[i][0]), pgm_read_byte_near(&init_vals[i][1]));
CYRF_WritePreamble(0x333304);
CYRF_ConfigRFChannel(0x61);
}
static void __attribute__((unused)) build_bind_packet()
{
uint8_t i;
uint16_t sum = 384 - 0x10;//
packet[0] = 0xff ^ cyrfmfg_id[0];
packet[1] = 0xff ^ cyrfmfg_id[1];
packet[2] = 0xff ^ cyrfmfg_id[2];
packet[3] = 0xff ^ cyrfmfg_id[3];
packet[4] = packet[0];
packet[5] = packet[1];
packet[6] = packet[2];
packet[7] = packet[3];
for(i = 0; i < 8; i++)
sum += packet[i];
packet[8] = sum >> 8;
packet[9] = sum & 0xff;
packet[10] = 0x01; //???
packet[11] = DSM_num_ch;
if (sub_protocol==DSM2_22)
packet[12]=DSM_num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
if(sub_protocol==DSM2_11)
packet[12]=0x12; // DSM2/2048 2 packets
if(sub_protocol==DSMX_22)
#if defined DSM_TELEMETRY
packet[12] = 0xb2; // DSMX/2048 2 packets
#else
packet[12] = DSM_num_ch<8? 0xa2 : 0xb2; // DSMX/2048 1 or 2 packets depending on the number of channels
#endif
if(sub_protocol==DSMX_11 || sub_protocol==DSM_AUTO) // Force DSMX/1024 in mode Auto
packet[12]=0xb2; // DSMX/1024 2 packets
packet[13] = 0x00; //???
for(i = 8; i < 14; i++)
sum += packet[i];
packet[14] = sum >> 8;
packet[15] = sum & 0xff;
}
static void __attribute__((unused)) initialize_bind_phase()
{
uint8_t code[32];
CYRF_ConfigRFChannel(DSM_BIND_CHANNEL); //This seems to be random?
uint8_t pn_row = get_pn_row(DSM_BIND_CHANNEL);
//printf("Ch: %d Row: %d SOP: %d Data: %d\n", DSM_BIND_CHANNEL, pn_row, sop_col, 7 - sop_col);
CYRF_ConfigCRCSeed(crc);
read_code(code,pn_row,sop_col,8);
CYRF_ConfigSOPCode(code);
read_code(code,pn_row,7 - sop_col,16);
read_code(code+16,0,8,8);
memcpy(code + 24, (void *)"\xc6\x94\x22\xfe\x48\xe6\x57\x4e", 8);
CYRF_ConfigDataCode(code, 32);
build_bind_packet();
}
const uint8_t PROGMEM data_vals[][2] = {
{CYRF_05_RX_CTRL, 0x83}, //Initialize for reading RSSI
{CYRF_29_RX_ABORT, 0x20},
{CYRF_0F_XACT_CFG, 0x24},
{CYRF_29_RX_ABORT, 0x00},
{CYRF_03_TX_CFG, 0x08 | CYRF_HIGH_POWER},
{CYRF_10_FRAMING_CFG, 0xea},
{CYRF_1F_TX_OVERRIDE, 0x00},
{CYRF_1E_RX_OVERRIDE, 0x00},
{CYRF_03_TX_CFG, 0x28 | CYRF_HIGH_POWER},
{CYRF_12_DATA64_THOLD, 0x3f},
{CYRF_10_FRAMING_CFG, 0xff},
{CYRF_0F_XACT_CFG, 0x24}, //Switch from reading RSSI to Writing
{CYRF_29_RX_ABORT, 0x00},
{CYRF_12_DATA64_THOLD, 0x0a},
{CYRF_10_FRAMING_CFG, 0xea},
};
static void __attribute__((unused)) cyrf_configdata()
{
for(uint8_t i = 0; i < sizeof(data_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&data_vals[i][0]), pgm_read_byte_near(&data_vals[i][1]));
}
static void __attribute__((unused)) update_channels()
{
prev_option=option;
if(sub_protocol==DSM_AUTO)
DSM_num_ch=12; // Force 12 channels in mode Auto
else
if(option&0x80)
{
DSM_num_ch=-option;
DSM_orx=1; // Use orange table
}
else
{
DSM_num_ch=option;
DSM_orx=0; // Use normal table
}
if(DSM_num_ch<4 || DSM_num_ch>12)
DSM_num_ch=6; // Default to 6 channels if invalid choice...
// Create channel map based on number of channels
for(uint8_t i=0;i<12;i++)
ch_map[i]=pgm_read_byte_near(&ch_map_progmem[DSM_num_ch-4][i]);
ch_map[12]=0xFF;
ch_map[13]=0xFF;
// TODO: if DSM2_11 or DSMX_11 then repeat lower channels to upper channels need to rewrite this part
if(DSM_num_ch<8)
for(uint8_t i=7;i<14;i++)
ch_map[i]=ch_map[i-7];
}
static void __attribute__((unused)) build_data_packet(uint8_t upper)
{
uint16_t max = 2047;
uint8_t bits = 11;
if(prev_option!=option)
update_channels();
if (sub_protocol==DSMX_11 || sub_protocol==DSMX_22 )
{
packet[0] = cyrfmfg_id[2];
packet[1] = cyrfmfg_id[3];
}
else
{
packet[0] = (0xff ^ cyrfmfg_id[2]);
packet[1] = (0xff ^ cyrfmfg_id[3]);
if(sub_protocol==DSM2_22)
{
max=1023; // Only DSM_22 is using a resolution of 1024
bits=10;
}
}
for (uint8_t i = 0; i < 7; i++)
{
uint8_t idx = ch_map[(upper?7:0) + i];//1,5,2,3,0,4
uint16_t value = 0xffff;;
if (idx != 0xff)
{
if (!IS_BIND_DONE_on)
{ // Failsafe position during binding
value=max/2; //all channels to middle
if(idx==0)
value=1; //except throttle
}
else
value=map(Servo_data[CH_TAER[idx]],servo_min_125,servo_max_125,0,max);
value |= (upper ? 0x8000 : 0) | (idx << bits);
}
packet[i*2+2] = (value >> 8) & 0xff;
packet[i*2+3] = (value >> 0) & 0xff;
}
}
static void __attribute__((unused)) set_sop_data_crc()
{
//The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1])
//The crc for channel '2' is (mfgid[0] << 8 + mfgid[1])
uint16_t crc = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
if(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B)
CYRF_ConfigCRCSeed(crc); //CH2
else
CYRF_ConfigCRCSeed(~crc); //CH1
uint8_t pn_row = get_pn_row(hopping_frequency[hopping_frequency_no]);
uint8_t code[16];
read_code(code,pn_row,sop_col,8);
CYRF_ConfigSOPCode(code);
read_code(code,pn_row,7 - sop_col,16);
CYRF_ConfigDataCode(code, 16);
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
hopping_frequency_no++;
if(sub_protocol == DSMX_11 || sub_protocol == DSMX_22)
hopping_frequency_no %=23;
else
hopping_frequency_no %=2;
}
static void __attribute__((unused)) calc_dsmx_channel()
{
uint8_t idx = 0;
uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0));
uint32_t id_tmp = id;
while(idx < 23)
{
uint8_t i;
uint8_t count_3_27 = 0, count_28_51 = 0, count_52_76 = 0;
id_tmp = id_tmp * 0x0019660D + 0x3C6EF35F; // Randomization
uint8_t next_ch = ((id_tmp >> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3
if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 )
continue;
for (i = 0; i < idx; i++)
{
if(hopping_frequency[i] == next_ch)
break;
if(hopping_frequency[i] <= 27)
count_3_27++;
else
if (hopping_frequency[i] <= 51)
count_28_51++;
else
count_52_76++;
}
if (i != idx)
continue;
if ((next_ch < 28 && count_3_27 < 8)
||(next_ch >= 28 && next_ch < 52 && count_28_51 < 7)
||(next_ch >= 52 && count_52_76 < 8))
hopping_frequency[idx++] = next_ch;
}
}
static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
{
uint8_t result=1; // assume good packet
uint16_t sum = 384 - 0x10;
for(uint8_t i = 1; i < 9; i++)
{
sum += pkt[i];
if(i<5)
if(pkt[i] != (0xff ^ cyrfmfg_id[i-1]))
result=0; // bad packet
}
if( pkt[9] != (sum>>8) && pkt[10] != (uint8_t)sum )
result=0;
return result;
}
uint16_t ReadDsm()
{
#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 phase, and switch channels. Was 400 but 600 seems what the 328p needs to read a packet
uint16_t start;
#if defined DSM_TELEMETRY
uint8_t rx_phase;
uint8_t len;
#endif
switch(phase)
{
case DSM_BIND_WRITE:
if(bind_counter--==0)
#if defined DSM_TELEMETRY
phase=DSM_BIND_CHECK; //Check RX answer
#else
phase=DSM_CHANSEL; //Switch to normal mode
#endif
CYRF_WriteDataPacket(packet);
return 10000;
#if defined DSM_TELEMETRY
case DSM_BIND_CHECK:
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84\xC9\x2C\x06\x93\x86\xB9\x9E", 16);
CYRF_SetTxRxMode(RX_EN); //Receive mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); //Prepare to receive
bind_counter=300;
phase++; // change from BIND_CHECK to BIND_READ
return 2000;
case DSM_BIND_READ:
//Read data from RX
rx_phase = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_phase & 0x07) == 0x02)
{ // data received
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
if(len>MAX_PKT-2)
len=MAX_PKT-2;
CYRF_ReadDataPacketLen(pkt+1, len);
if(len==10 && DSM_Check_RX_packet())
{
pkt[0]=0x80;
telemetry_link=1; // send received data on serial
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20);
CYRF_SetTxRxMode(TX_EN); // Write mode
phase++;
return 2000;
}
}
//Force end read phase
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x2C); // Force end phase
start=micros();
while ((uint16_t)micros()-start < 100) // Wait max 100 µs
if((CYRF_ReadRegister(CYRF_0F_XACT_CFG) & 0x20) == 0)
break;
if( --bind_counter == 0 )
{
phase++; // Exit if no answer has been received for some time
return 7000 ;
}
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x0C); // Read mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive
return 7000;
#endif
case DSM_CHANSEL:
BIND_DONE;
cyrf_configdata();
CYRF_SetTxRxMode(TX_EN);
hopping_frequency_no = 0;
phase = DSM_CH1_WRITE_A; // in fact phase++
set_sop_data_crc();
return 10000;
case DSM_CH1_WRITE_A:
case DSM_CH1_WRITE_B:
case DSM_CH2_WRITE_A:
case DSM_CH2_WRITE_B:
build_data_packet(phase == DSM_CH1_WRITE_B||phase == DSM_CH2_WRITE_B); // build lower or upper channels
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
CYRF_WriteDataPacket(packet);
phase++; // change from WRITE to CHECK mode
return DSM_WRITE_DELAY;
case DSM_CH1_CHECK_A:
case DSM_CH1_CHECK_B:
start=micros();
while ((uint16_t)micros()-start < 500) // Wait max 500µs
if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)
break;
set_sop_data_crc();
phase++; // change from CH1_CHECK to CH2_WRITE
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
case DSM_CH2_CHECK_A:
case DSM_CH2_CHECK_B:
start=micros();
while ((uint16_t)micros()-start < 500) // Wait max 500µs
if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)
break;
if (phase == DSM_CH2_CHECK_A)
CYRF_SetPower(0x28); //Keep transmit power in sync
#if defined DSM_TELEMETRY
phase++; // change from CH2_CHECK to CH2_READ
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 DSM_CH2_READ_A:
case DSM_CH2_READ_B:
//Read telemetry
rx_phase = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_phase & 0x07) == 0x02)
{ // good data (complete with no errors)
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
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 (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_22 || sub_protocol==DSMX_22) && DSM_num_ch < 8) // 22ms mode
{
//Force end read phase
CYRF_WriteRegister(CYRF_0F_XACT_CFG, (CYRF_ReadRegister(CYRF_0F_XACT_CFG) | 0x20)); // Force end phase
start=micros();
while ((uint16_t)micros()-start < 100) // Wait max 100 µs
if((CYRF_ReadRegister(CYRF_0F_XACT_CFG) & 0x20) == 0)
break;
phase = DSM_CH2_READ_B;
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
return 11000;
}
if (phase == DSM_CH2_READ_A)
phase = DSM_CH1_WRITE_B; //Transmit upper
else
phase = DSM_CH1_WRITE_A; //Transmit lower
CYRF_SetTxRxMode(TX_EN); //Write mode
set_sop_data_crc();
return DSM_READ_DELAY;
#else
// No telemetry
set_sop_data_crc();
if (phase == DSM_CH2_CHECK_A)
{
if(DSM_num_ch > 7 || sub_protocol==DSM2_11 || sub_protocol==DSMX_11)
phase = DSM_CH1_WRITE_B; //11ms mode or upper to transmit change from CH2_CHECK_A to CH1_WRITE_A
else
{ //Normal mode 22ms
phase = DSM_CH1_WRITE_A; // change from CH2_CHECK_A to CH1_WRITE_A (ie no upper)
return 22000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
}
}
else
phase = DSM_CH1_WRITE_A; // change from CH2_CHECK_B to CH1_WRITE_A (upper already transmitted so transmit lower)
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
#endif
}
return 0;
}
uint16_t initDsm()
{
CYRF_GetMfgData(cyrfmfg_id);//
//Model match
cyrfmfg_id[3]+=RX_num;
cyrf_config();
if (sub_protocol == DSMX_11 || sub_protocol == DSMX_22)
calc_dsmx_channel();
else
{
uint8_t tmpch[10];
CYRF_FindBestChannels(tmpch, 10, 5, 3, 75);
//
uint8_t idx = random(0xfefefefe) % 10;
hopping_frequency[0] = tmpch[idx];
while(1)
{
idx = random(0xfefefefe) % 10;
if (tmpch[idx] != hopping_frequency[0])
break;
}
hopping_frequency[1] = tmpch[idx];
}
//
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
CYRF_SetTxRxMode(TX_EN);
//
update_channels();
if(IS_AUTOBIND_FLAG_on )
{
BIND_IN_PROGRESS;
initialize_bind_phase();
phase = DSM_BIND_WRITE;
bind_counter=DSM_BIND_COUNT;
}
else
phase = DSM_CHANSEL;//
return 10000;
}
#endif

View File

@ -43,28 +43,6 @@ enum {
DEVO_BOUND_10, DEVO_BOUND_10,
}; };
const uint8_t PROGMEM DEVO_sopcodes[][8] = {
/* Note these are in order transmitted (LSB 1st) */
/* 0 */ {0x3C,0x37,0xCC,0x91,0xE2,0xF8,0xCC,0x91}, //0x91CCF8E291CC373C
/* 1 */ {0x9B,0xC5,0xA1,0x0F,0xAD,0x39,0xA2,0x0F}, //0x0FA239AD0FA1C59B
/* 2 */ {0xEF,0x64,0xB0,0x2A,0xD2,0x8F,0xB1,0x2A}, //0x2AB18FD22AB064EF
/* 3 */ {0x66,0xCD,0x7C,0x50,0xDD,0x26,0x7C,0x50}, //0x507C26DD507CCD66
/* 4 */ {0x5C,0xE1,0xF6,0x44,0xAD,0x16,0xF6,0x44}, //0x44F616AD44F6E15C
/* 5 */ {0x5A,0xCC,0xAE,0x46,0xB6,0x31,0xAE,0x46}, //0x46AE31B646AECC5A
/* 6 */ {0xA1,0x78,0xDC,0x3C,0x9E,0x82,0xDC,0x3C}, //0x3CDC829E3CDC78A1
/* 7 */ {0xB9,0x8E,0x19,0x74,0x6F,0x65,0x18,0x74}, //0x7418656F74198EB9
/* 8 */ {0xDF,0xB1,0xC0,0x49,0x62,0xDF,0xC1,0x49}, //0x49C1DF6249C0B1DF
/* 9 */ {0x97,0xE5,0x14,0x72,0x7F,0x1A,0x14,0x72}, //0x72141A7F7214E597
};
static void __attribute__((unused)) DEVO_ConfigSOPCode(uint8_t val)
{
uint8_t code[8];
for(uint8_t i=0;i<8;i++)
code[i]=pgm_read_byte_near(&DEVO_sopcodes[val][i]);
CYRF_ConfigSOPCode(code);
}
static void __attribute__((unused)) DEVO_scramble_pkt() static void __attribute__((unused)) DEVO_scramble_pkt()
{ {
#ifdef NO_SCRAMBLE #ifdef NO_SCRAMBLE
@ -185,7 +163,7 @@ static void __attribute__((unused)) DEVO_cyrf_set_bound_sop_code()
uint8_t sopidx = (0xff &((cyrfmfg_id[0] << 2) + cyrfmfg_id[1] + cyrfmfg_id[2])) % 10; uint8_t sopidx = (0xff &((cyrfmfg_id[0] << 2) + cyrfmfg_id[1] + cyrfmfg_id[2])) % 10;
CYRF_SetTxRxMode(TX_EN); CYRF_SetTxRxMode(TX_EN);
CYRF_ConfigCRCSeed((crc << 8) + crc); CYRF_ConfigCRCSeed((crc << 8) + crc);
DEVO_ConfigSOPCode(sopidx); CYRF_PROGMEM_ConfigSOPCode(DEVO_j6pro_sopcodes[sopidx]);
CYRF_SetPower(0x08); CYRF_SetPower(0x08);
} }
@ -317,7 +295,7 @@ uint16_t DevoInit()
CYRF_GetMfgData(cyrfmfg_id); CYRF_GetMfgData(cyrfmfg_id);
CYRF_SetTxRxMode(TX_EN); CYRF_SetTxRxMode(TX_EN);
CYRF_ConfigCRCSeed(0x0000); CYRF_ConfigCRCSeed(0x0000);
DEVO_ConfigSOPCode(0); CYRF_PROGMEM_ConfigSOPCode(DEVO_j6pro_sopcodes[0]);
DEVO_set_radio_channels(); DEVO_set_radio_channels();
hopping_frequency_ptr = hopping_frequency; hopping_frequency_ptr = hopping_frequency;

View File

@ -35,7 +35,7 @@ static void __attribute__((unused)) ESKY_init(uint8_t bind)
NRF24L01_Initialize(); NRF24L01_Initialize();
// 2-bytes CRC, radio off // 2-bytes CRC, radio off
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)); NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
if (bind) if (bind)

View File

@ -105,7 +105,7 @@ uint16_t FY326_callback()
switch (phase) switch (phase)
{ {
case FY326_BIND1: case FY326_BIND1:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR)) if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready { // RX fifo data ready
NRF24L01_ReadPayload(packet, FY326_PACKET_SIZE); NRF24L01_ReadPayload(packet, FY326_PACKET_SIZE);
rxid = packet[13]; rxid = packet[13];
@ -127,7 +127,7 @@ uint16_t FY326_callback()
} }
break; break;
case FY326_BIND2: case FY326_BIND2:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_TX_DS)) if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS))
{ // TX data sent -> switch to RX mode { // TX data sent -> switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF); NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx(); NRF24L01_FlushRx();

View File

@ -50,16 +50,11 @@ enum {
FLAG_V912_BTMBTN= 0x80, FLAG_V912_BTMBTN= 0x80,
}; };
uint8_t chanrow;
uint8_t chancol;
uint8_t chanoffset;
const uint8_t PROGMEM V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, // sometime first byte is 0x15 ? const uint8_t PROGMEM V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, // sometime first byte is 0x15 ?
0x49, 0x49, 0x49, 0x49, 0x49, }; 0x49, 0x49, 0x49, 0x49, 0x49, };
static void __attribute__((unused)) flysky_apply_extension_flags() static void __attribute__((unused)) flysky_apply_extension_flags()
{ {
static uint8_t seq_counter; static uint8_t seq_counter;
switch(sub_protocol) switch(sub_protocol)
{ {
@ -144,34 +139,14 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
packet[2] = rx_tx_addr[2]; packet[2] = rx_tx_addr[2];
packet[3] = rx_tx_addr[1]; packet[3] = rx_tx_addr[1];
packet[4] = rx_tx_addr[0]; packet[4] = rx_tx_addr[0];
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4};
for(i = 0; i < 8; i++) for(i = 0; i < 8; i++)
{ {
packet[5 + i*2]=Servo_data[ch[i]]&0xFF; //low byte of servo timing(1000-2000us) packet[5 + i*2]=Servo_data[CH_AETR[i]]&0xFF; //low byte of servo timing(1000-2000us)
packet[6 + i*2]=(Servo_data[ch[i]]>>8)&0xFF; //high byte of servo timing(1000-2000us) packet[6 + i*2]=(Servo_data[CH_AETR[i]]>>8)&0xFF; //high byte of servo timing(1000-2000us)
} }
flysky_apply_extension_flags(); 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() uint16_t ReadFlySky()
{ {
if (bind_counter) if (bind_counter)
@ -185,28 +160,56 @@ uint16_t ReadFlySky()
else else
{ {
flysky_build_packet(0); flysky_build_packet(0);
A7105_WriteData(21, pgm_read_byte_near(&tx_channels[chanrow][chancol])-chanoffset); A7105_WriteData(21, hopping_frequency[hopping_frequency_no]);
chancol = (chancol + 1) % 16; hopping_frequency_no = (hopping_frequency_no + 1) & 0x0F;
if (! chancol) //Keep transmit power updated
A7105_SetPower(); A7105_SetPower();
} }
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. 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() { const uint8_t PROGMEM tx_channels[8][4] = {
{ 0x12, 0x34, 0x56, 0x78},
{ 0x18, 0x27, 0x36, 0x45},
{ 0x41, 0x82, 0x36, 0x57},
{ 0x84, 0x13, 0x65, 0x72},
{ 0x87, 0x64, 0x15, 0x32},
{ 0x76, 0x84, 0x13, 0x52},
{ 0x71, 0x62, 0x84, 0x35},
{ 0x71, 0x86, 0x43, 0x52}
};
uint16_t initFlySky()
{
uint8_t chanrow;
uint8_t chanoffset;
uint8_t temp;
A7105_Init(INIT_FLYSKY); //flysky_init(); A7105_Init(INIT_FLYSKY); //flysky_init();
if ((rx_tx_addr[3]&0xF0) > 0x90) // limit offset to 9 as higher values don't work with some RX (ie V912) if ((rx_tx_addr[3]&0xF0) > 0x90) // limit offset to 9 as higher values don't work with some RX (ie V912)
rx_tx_addr[3]=rx_tx_addr[3]-0x70; rx_tx_addr[3]=rx_tx_addr[3]-0x70;
chanrow=rx_tx_addr[3] & 0x0F; chanrow=rx_tx_addr[3] & 0x0F;
chancol=0;
chanoffset=rx_tx_addr[3]/16; chanoffset=rx_tx_addr[3]/16;
// Build frequency hop table
for(uint8_t i=0;i<16;i++)
{
temp=pgm_read_byte_near(&tx_channels[chanrow>>1][i>>2]);
if(i&0x01)
temp&=0x0F;
else
temp>>=4;
temp*=0x0A;
if(i&0x02)
temp+=0x50;
hopping_frequency[((chanrow&1)?15-i:i)]=temp-chanoffset;
}
hopping_frequency_no=0;
if(IS_AUTOBIND_FLAG_on) if(IS_AUTOBIND_FLAG_on)
bind_counter = FLYSKY_BIND_COUNT; bind_counter = FLYSKY_BIND_COUNT;
else else
bind_counter = 0; bind_counter = 0;
return 2400; return 2400;
} }
#endif #endif

View File

@ -13,30 +13,13 @@
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
#if defined(FRSKY_CC2500_INO) #if defined(FRSKYD_CC2500_INO)
#include "iface_cc2500.h" #include "iface_cc2500.h"
//##########Variables########
//uint32_t state;
//uint8_t len;
/*
enum {
FRSKY_BIND = 0,
FRSKY_BIND_DONE = 1000,
FRSKY_DATA1,
FRSKY_DATA2,
FRSKY_DATA3,
FRSKY_DATA4,
FRSKY_DATA5
};
*/
static void __attribute__((unused)) frsky2way_init(uint8_t bind) static void __attribute__((unused)) frsky2way_init(uint8_t bind)
{ {
// Configure cc2500 for tx mode // Configure cc2500 for tx mode
CC2500_Reset();
// //
for(uint8_t i=0;i<36;i++) for(uint8_t i=0;i<36;i++)
{ {
@ -51,6 +34,7 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind)
CC2500_WriteReg(reg,val); CC2500_WriteReg(reg,val);
} }
prev_option = option ; prev_option = option ;
CC2500_SetTxRxMode(TX_EN); CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower(); CC2500_SetPower();
@ -143,7 +127,7 @@ uint16_t initFrSky_2way()
if(IS_AUTOBIND_FLAG_on) if(IS_AUTOBIND_FLAG_on)
{ {
frsky2way_init(1); frsky2way_init(1);
state = FRSKY_BIND;// state = FRSKY_BIND;
} }
else else
{ {
@ -206,14 +190,13 @@ uint16_t ReadFrSky_2way()
CC2500_SetTxRxMode(TX_EN); CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower(); // Set tx_power CC2500_SetPower(); // Set tx_power
} }
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
if ( prev_option != option ) if ( prev_option != option )
{ {
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
prev_option = option ; prev_option = option ;
} }
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, get_chan_num(counter % 47));
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89); CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
CC2500_Strobe(CC2500_SFRX); CC2500_Strobe(CC2500_SFRX);
frsky2way_data_frame(); frsky2way_data_frame();

View File

@ -3,10 +3,12 @@
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful, Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */

View File

@ -23,7 +23,6 @@
uint8_t chanskip; uint8_t chanskip;
uint8_t counter_rst; uint8_t counter_rst;
uint8_t ctr; uint8_t ctr;
uint8_t FS_flag=0;
uint8_t seq_last_sent; uint8_t seq_last_sent;
uint8_t seq_last_rcvd; uint8_t seq_last_rcvd;
@ -90,8 +89,6 @@ static void __attribute__((unused)) set_start(uint8_t ch )
static void __attribute__((unused)) frskyX_init() static void __attribute__((unused)) frskyX_init()
{ {
CC2500_Reset();
for(uint8_t i=0;i<36;i++) for(uint8_t i=0;i<36;i++)
{ {
uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]); uint8_t reg=pgm_read_byte_near(&cc2500_conf[i][0]);
@ -215,10 +212,10 @@ static void __attribute__((unused)) frskyX_data_frame()
packet[4] = (ctr<<6)+hopping_frequency_no; packet[4] = (ctr<<6)+hopping_frequency_no;
packet[5] = counter_rst; packet[5] = counter_rst;
packet[6] = RX_num; packet[6] = RX_num;
//FLAGS 00 - standard packet //packet[7] = FLAGS 00 - standard packet
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
//20 - range check packet //20 - range check packet
packet[7] = FS_flag; packet[7] = 0;
packet[8] = 0; packet[8] = 0;
// //
if ( lpass & 1 ) if ( lpass & 1 )
@ -286,7 +283,7 @@ uint16_t ReadFrSkyX()
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
prev_option = option ; prev_option = option ;
} }
LED_ON; LED_on;
CC2500_SetTxRxMode(TX_EN); CC2500_SetTxRxMode(TX_EN);
set_start(hopping_frequency_no); set_start(hopping_frequency_no);
CC2500_SetPower(); CC2500_SetPower();
@ -339,10 +336,8 @@ uint16_t initFrSkyX()
{ {
while(!chanskip) while(!chanskip)
{ {
#if defined STM32_board #if defined STM32_board
randomSeed((uint32_t)analogRead(PB0) << 10 | analogRead(PB1)); randomSeed((uint32_t)analogRead(PB0) << 10 | analogRead(PB1));
#else
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
#endif #endif
chanskip=random(0xfefefefe)%47; chanskip=random(0xfefefefe)%47;
} }

View File

@ -120,9 +120,8 @@ static void __attribute__((unused)) build_ch_data()
{ {
uint16_t temp; uint16_t temp;
uint8_t i,j; uint8_t i,j;
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4};
for (i = 0; i< 8; i++) { for (i = 0; i< 8; i++) {
j=ch[i]; j=CH_AETR[i];
temp=map(limit_channel_100(j),servo_min_100,servo_max_100,0,1000); temp=map(limit_channel_100(j),servo_min_100,servo_max_100,0,1000);
if (j == THROTTLE) // It is clear that hisky's throttle stick is made reversely, so I adjust it here on purpose if (j == THROTTLE) // It is clear that hisky's throttle stick is made reversely, so I adjust it here on purpose
temp = 1000 -temp; temp = 1000 -temp;

View File

@ -121,7 +121,7 @@ static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
if(sub_protocol == FORMAT_JJRCX1) if(sub_protocol == FORMAT_JJRCX1)
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
else else
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? HONTAI_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]); NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? HONTAI_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no %= 3; hopping_frequency_no %= 3;

View File

@ -347,8 +347,6 @@ uint16_t initHubsan() {
#if defined STM32_board #if defined STM32_board
randomSeed((uint32_t)analogRead(PB0) << 10 | analogRead(PB1)); randomSeed((uint32_t)analogRead(PB0) << 10 | analogRead(PB1));
#else
randomSeed((uint32_t)analogRead(A6) << 10 | analogRead(A7));
#endif #endif
sessionid = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16); sessionid = random(0xfefefefe) + ((uint32_t)random(0xfefefefe) << 16);
channel = allowed_ch[random(0xfefefefe) % sizeof(allowed_ch)]; channel = allowed_ch[random(0xfefefefe) % sizeof(allowed_ch)];

View File

@ -35,30 +35,8 @@ enum PktState {
J6PRO_CHAN_4, J6PRO_CHAN_4,
}; };
const uint8_t j6pro_sopcodes[][8] = { const uint8_t PROGMEM j6pro_bind_sop_code[] = {0x62, 0xdf, 0xc1, 0x49, 0xdf, 0xb1, 0xc0, 0x49};
/* Note these are in order transmitted (LSB 1st) */ const uint8_t j6pro_data_code[] = {0x02, 0xf9, 0x93, 0x97, 0x02, 0xfa, 0x5c, 0xe3, 0x01, 0x2b, 0xf1, 0xdb, 0x01, 0x32, 0xbe, 0x6f};
{0x3C, 0x37, 0xCC, 0x91, 0xE2, 0xF8, 0xCC, 0x91},
{0x9B, 0xC5, 0xA1, 0x0F, 0xAD, 0x39, 0xA2, 0x0F},
{0xEF, 0x64, 0xB0, 0x2A, 0xD2, 0x8F, 0xB1, 0x2A},
{0x66, 0xCD, 0x7C, 0x50, 0xDD, 0x26, 0x7C, 0x50},
{0x5C, 0xE1, 0xF6, 0x44, 0xAD, 0x16, 0xF6, 0x44},
{0x5A, 0xCC, 0xAE, 0x46, 0xB6, 0x31, 0xAE, 0x46},
{0xA1, 0x78, 0xDC, 0x3C, 0x9E, 0x82, 0xDC, 0x3C},
{0xB9, 0x8E, 0x19, 0x74, 0x6F, 0x65, 0x18, 0x74},
{0xDF, 0xB1, 0xC0, 0x49, 0x62, 0xDF, 0xC1, 0x49},
{0x97, 0xE5, 0x14, 0x72, 0x7F, 0x1A, 0x14, 0x72},
{0x82, 0xC7, 0x90, 0x36, 0x21, 0x03, 0xFF, 0x17},
{0xE2, 0xF8, 0xCC, 0x91, 0x3C, 0x37, 0xCC, 0x91}, //Note: the '03' was '9E' in the Cypress recommended table
{0xAD, 0x39, 0xA2, 0x0F, 0x9B, 0xC5, 0xA1, 0x0F}, //The following are the same as the 1st 8 above,
{0xD2, 0x8F, 0xB1, 0x2A, 0xEF, 0x64, 0xB0, 0x2A}, //but with the upper and lower word swapped
{0xDD, 0x26, 0x7C, 0x50, 0x66, 0xCD, 0x7C, 0x50},
{0xAD, 0x16, 0xF6, 0x44, 0x5C, 0xE1, 0xF6, 0x44},
{0xB6, 0x31, 0xAE, 0x46, 0x5A, 0xCC, 0xAE, 0x46},
{0x9E, 0x82, 0xDC, 0x3C, 0xA1, 0x78, 0xDC, 0x3C},
{0x6F, 0x65, 0x18, 0x74, 0xB9, 0x8E, 0x19, 0x74},
};
const uint8_t bind_sop_code[] = {0x62, 0xdf, 0xc1, 0x49, 0xdf, 0xb1, 0xc0, 0x49};
const uint8_t data_code[] = {0x02, 0xf9, 0x93, 0x97, 0x02, 0xfa, 0x5c, 0xe3, 0x01, 0x2b, 0xf1, 0xdb, 0x01, 0x32, 0xbe, 0x6f};
static void __attribute__((unused)) j6pro_build_bind_packet() static void __attribute__((unused)) j6pro_build_bind_packet()
{ {
@ -106,7 +84,7 @@ static void __attribute__((unused)) j6pro_cyrf_init()
CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xee); CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xee);
CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00); CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00);
CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x00); CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x00);
CYRF_ConfigDataCode(data_code, 16); CYRF_ConfigDataCode(j6pro_data_code, 16);
CYRF_WritePreamble(0x023333); CYRF_WritePreamble(0x023333);
CYRF_GetMfgData(cyrfmfg_id); CYRF_GetMfgData(cyrfmfg_id);
@ -121,7 +99,7 @@ static void __attribute__((unused)) cyrf_bindinit()
CYRF_SetPower(0x28); //Deviation using max power, replaced by bind power... CYRF_SetPower(0x28); //Deviation using max power, replaced by bind power...
CYRF_ConfigRFChannel(0x52); CYRF_ConfigRFChannel(0x52);
CYRF_ConfigSOPCode(bind_sop_code); CYRF_PROGMEM_ConfigSOPCode(j6pro_bind_sop_code);
CYRF_ConfigCRCSeed(0x0000); CYRF_ConfigCRCSeed(0x0000);
CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a); CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4a);
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83);
@ -144,7 +122,7 @@ static void __attribute__((unused)) cyrf_datainit()
uint16_t crc = (0xff & (cyrfmfg_id[1] - cyrfmfg_id[4] + cyrfmfg_id[5])) | uint16_t crc = (0xff & (cyrfmfg_id[1] - cyrfmfg_id[4] + cyrfmfg_id[5])) |
((0xff & (cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[4] + cyrfmfg_id[5])) << 8); ((0xff & (cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[4] + cyrfmfg_id[5])) << 8);
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25); CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x25);
CYRF_ConfigSOPCode(j6pro_sopcodes[sop_idx]); CYRF_PROGMEM_ConfigSOPCode(DEVO_j6pro_sopcodes[sop_idx]);
CYRF_ConfigCRCSeed(crc); CYRF_ConfigCRCSeed(crc);
} }
@ -257,7 +235,6 @@ uint16_t ReadJ6Pro()
uint16_t initJ6Pro() uint16_t initJ6Pro()
{ {
CYRF_Reset();
j6pro_cyrf_init(); j6pro_cyrf_init();
if(IS_AUTOBIND_FLAG_on) { if(IS_AUTOBIND_FLAG_on) {

View File

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

View File

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

View File

@ -12,7 +12,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
// compatible with MT99xx, Eachine H7, Yi Zhan i6S // compatible with MT99xx, Eachine H7, Yi Zhan i6S and LS114/124
// Last sync with Goebish mt99xx_nrf24l01.c dated 2016-01-29 // Last sync with Goebish mt99xx_nrf24l01.c dated 2016-01-29
#if defined(MT99XX_NRF24L01_INO) #if defined(MT99XX_NRF24L01_INO)
@ -53,34 +53,54 @@ enum {
MT99XX_DATA MT99XX_DATA
}; };
static void __attribute__((unused)) MT99XX_send_packet() const uint8_t h7_mys_byte[] = {
{
const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
const uint8_t mys_byte[] = {
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10 0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10
}; };
static const uint8_t ls_mys_byte[] = {
0x05, 0x15, 0x25, 0x06, 0x16, 0x26,
0x07, 0x17, 0x27, 0x00, 0x10, 0x20,
0x01, 0x11, 0x21, 0x02, 0x12, 0x22,
0x03, 0x13, 0x23, 0x04, 0x14, 0x24
};
static void __attribute__((unused)) MT99XX_send_packet()
{
const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
static uint8_t yz_seq_num=0; static uint8_t yz_seq_num=0;
static uint8_t ls_counter=0;
if(sub_protocol != YZ) if(sub_protocol != YZ)
{ // MT99XX & H7 { // MT99XX & H7 & LS
packet[0] = convert_channel_8b_scale(THROTTLE,0x00,0xE1); // throttle packet[0] = convert_channel_8b_scale(THROTTLE,0xE1,0x00); // throttle
packet[1] = convert_channel_8b_scale(RUDDER ,0x00,0xE1); // rudder packet[1] = convert_channel_8b_scale(RUDDER ,0x00,0xE1); // rudder
packet[2] = convert_channel_8b_scale(AILERON ,0x00,0xE1); // aileron packet[2] = convert_channel_8b_scale(AILERON ,0xE1,0x00); // aileron
packet[3] = convert_channel_8b_scale(ELEVATOR,0x00,0xE1); // elevator packet[3] = convert_channel_8b_scale(ELEVATOR,0x00,0xE1); // elevator
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00) packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f) packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
packet[6] = GET_FLAG( Servo_AUX1, FLAG_MT_FLIP ) packet[6] = GET_FLAG( Servo_AUX1, FLAG_MT_FLIP );
| GET_FLAG( Servo_AUX3, FLAG_MT_SNAPSHOT ) packet[7] = h7_mys_byte[hopping_frequency_no]; // next rf channel index ?
| GET_FLAG( Servo_AUX4, FLAG_MT_VIDEO );
if(sub_protocol==MT99) if(sub_protocol==H7)
packet[6] |= 0x40 | FLAG_MT_RATE2;
else
packet[6] |= FLAG_MT_RATE1; // max rate on H7 packet[6] |= FLAG_MT_RATE1; // max rate on H7
// todo: mys_byte = next channel index ? else
// low nibble: index in chan list ? if(sub_protocol==MT99)
// high nibble: 0->start from start of list, 1->start from end of list ? packet[6] |= 0x40 | FLAG_MT_RATE2
packet[7] = mys_byte[hopping_frequency_no]; | GET_FLAG( Servo_AUX3, FLAG_MT_SNAPSHOT )
| GET_FLAG( Servo_AUX4, FLAG_MT_VIDEO ); // max rate on MT99xx
else //LS
{
packet[6] |= FLAG_LS_RATE // max rate
| GET_FLAG( Servo_AUX2, FLAG_LS_INVERT ) //INVERT
| GET_FLAG( Servo_AUX3, FLAG_LS_SNAPSHOT ) //SNAPSHOT
| GET_FLAG( Servo_AUX4, FLAG_LS_VIDEO ) //VIDEO
| GET_FLAG( Servo_AUX5, FLAG_LS_HEADLESS ); //HEADLESS
packet[7] = ls_mys_byte[ls_counter++];
if(ls_counter >= sizeof(ls_mys_byte))
ls_counter=0;
}
uint8_t result=checksum_offset; uint8_t result=checksum_offset;
for(uint8_t i=0; i<8; i++) for(uint8_t i=0; i<8; i++)
result += packet[i]; result += packet[i];
@ -89,9 +109,9 @@ static void __attribute__((unused)) MT99XX_send_packet()
else else
{ // YZ { // YZ
packet[0] = convert_channel_8b_scale(THROTTLE,0x00,0x64); // throttle packet[0] = convert_channel_8b_scale(THROTTLE,0x00,0x64); // throttle
packet[1] = convert_channel_8b_scale(RUDDER ,0x00,0x64); // rudder packet[1] = convert_channel_8b_scale(RUDDER ,0x64,0x00); // rudder
packet[2] = convert_channel_8b_scale(ELEVATOR,0x00,0x64); // elevator packet[2] = convert_channel_8b_scale(ELEVATOR,0x00,0x64); // elevator
packet[3] = convert_channel_8b_scale(AILERON ,0x00,0x64); // aileron packet[3] = convert_channel_8b_scale(AILERON ,0x64,0x00); // aileron
if(packet_count++ >= 23) if(packet_count++ >= 23)
{ {
yz_seq_num ++; yz_seq_num ++;
@ -111,6 +131,7 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[7] += packet[idx]; packet[7] += packet[idx];
packet[8] = 0xff; packet[8] = 0xff;
} }
if(sub_protocol == LS) if(sub_protocol == LS)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel
else else
@ -132,8 +153,11 @@ static void __attribute__((unused)) MT99XX_send_packet()
static void __attribute__((unused)) MT99XX_init() static void __attribute__((unused)) MT99XX_init()
{ {
NRF24L01_Initialize(); NRF24L01_Initialize();
if(sub_protocol == YZ)
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx(); NRF24L01_FlushTx();
XN297_SetTXAddr((uint8_t *)"\xCC\xCC\xCC\xCC\xCC", 5);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
@ -145,7 +169,7 @@ static void __attribute__((unused)) MT99XX_init()
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower(); NRF24L01_SetPower();
XN297_Configure(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP) ); XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) );
} }
@ -153,13 +177,17 @@ static void __attribute__((unused)) MT99XX_initialize_txid()
{ {
rx_tx_addr[3] = 0xCC; rx_tx_addr[3] = 0xCC;
rx_tx_addr[4] = 0xCC; rx_tx_addr[4] = 0xCC;
if(sub_protocol == YZ) if(sub_protocol == YZ)
{ {
rx_tx_addr[0] = 0x53; // test (SB id) rx_tx_addr[0] = 0x53; // test (SB id)
rx_tx_addr[1] = 0x00; rx_tx_addr[1] = 0x00;
rx_tx_addr[2] = 0x00; rx_tx_addr[2] = 0x00;
} }
else
if(sub_protocol == LS)
rx_tx_addr[0] = 0xCC;
else //MT99 & H7
rx_tx_addr[2] = 0x00;
checksum_offset = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2]; checksum_offset = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2];
channel_offset = (((checksum_offset & 0xf0)>>4) + (checksum_offset & 0x0f)) % 8; channel_offset = (((checksum_offset & 0xf0)>>4) + (checksum_offset & 0x0f)) % 8;
} }
@ -208,6 +236,7 @@ uint16_t initMT99XX(void)
MT99XX_init(); MT99XX_init();
packet[0] = 0x20; packet[0] = 0x20;
packet_period = MT99XX_PACKET_PERIOD_MT;
switch(sub_protocol) switch(sub_protocol)
{ // MT99 & H7 { // MT99 & H7
case MT99: case MT99:
@ -228,9 +257,9 @@ uint16_t initMT99XX(void)
packet[3] = 0x11; packet[3] = 0x11;
break; break;
} }
packet[4] = rx_tx_addr[0]; // 1st byte for data state tx address packet[4] = rx_tx_addr[0];
packet[5] = rx_tx_addr[1]; // 2nd byte for data state tx address (always 0x00 on Yi Zhan ?) packet[5] = rx_tx_addr[1];
packet[6] = 0x00; // 3rd byte for data state tx address (always 0x00 ?) packet[6] = rx_tx_addr[2];
packet[7] = checksum_offset; // checksum offset packet[7] = checksum_offset; // checksum offset
packet[8] = 0xAA; // fixed packet[8] = 0xAA; // fixed
packet_count=0; packet_count=0;

View File

@ -3,17 +3,18 @@
#define XMEGA 1 #define XMEGA 1
// For BLUE module use:
//#define DSM_BLUE
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
static void protocol_init(void) ; static void protocol_init(void) ;
static void update_aux_flags(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 uint32_t random_id(uint16_t adress, uint8_t create_new) ;
static void update_serial_data(void) ; static void update_serial_data(void) ;
static void Mprotocol_serial_init(void) ; static void Mprotocol_serial_init(void) ;
static void module_reset(void) ;
static void update_led_status(void) ; static void update_led_status(void) ;
static void set_rx_tx_addr(uint32_t id) ; static void set_rx_tx_addr(uint32_t id) ;
uint16_t limit_channel_100(uint8_t ch) ; uint16_t limit_channel_100(uint8_t ch) ;
@ -31,6 +32,8 @@ extern uint16_t initDsm2(void) ;
extern uint16_t ReadDsm2(void) ; extern uint16_t ReadDsm2(void) ;
extern uint16_t DevoInit(void) ; extern uint16_t DevoInit(void) ;
extern uint16_t devo_callback(void) ; extern uint16_t devo_callback(void) ;
extern uint16_t initJ6Pro(void) ;
extern uint16_t ReadJ6Pro(void) ;
extern void randomSeed(unsigned int seed) ; extern void randomSeed(unsigned int seed) ;
extern long random(long howbig) ; extern long random(long howbig) ;
@ -39,20 +42,19 @@ 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 millis(void) ;
extern uint32_t micros(void) ; extern uint32_t micros(void) ;
extern void delayMicroseconds(uint16_t x) ; extern void delayMicroseconds(uint16_t x) ;
extern void delayMilliseconds(unsigned long ms) ;
extern void init(void) ; extern void init(void) ;
extern int analogRead(uint8_t pin) ; extern void modules_reset() ;
extern void Update_All() ;
#define A6 20 extern void tx_pause() ;
#define A7 21 extern void tx_resume() ;
extern void TelemetryUpdate() ;
extern uint16_t initDsm() ;
extern uint16_t ReadDsm() ;
#define yield() #define yield()
//void _delay_us( uint16_t x )
//{
// delayMicroseconds( x ) ;
//}
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
@ -69,219 +71,6 @@ extern int analogRead(uint8_t pin) ;
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (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 #ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif #endif
@ -314,27 +103,6 @@ void init()
PMIC.CTRL = 7 ; // Enable all interrupt levels PMIC.CTRL = 7 ; // Enable all interrupt levels
sei(); 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) #if defined(ADCSRA)
// set a2d prescale factor to 128 // set a2d prescale factor to 128
// 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
@ -357,12 +125,6 @@ void init()
UCSR0B = 0; UCSR0B = 0;
#endif #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 // Dip Switch inputs
PORTA.DIRCLR = 0xFF ; PORTA.DIRCLR = 0xFF ;
PORTA.PIN0CTRL = 0x18 ; PORTA.PIN0CTRL = 0x18 ;
@ -375,95 +137,15 @@ void init()
PORTA.PIN7CTRL = 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 "Multiprotocol.ino"
#include "SPI.ino"
#include "Convert.ino"
#include "Arduino.ino"
#include "cyrf6936_SPI.ino" #include "cyrf6936_SPI.ino"
#include "DSM2_cyrf6936.ino" #include "DSM_cyrf6936.ino"
#include "Devo_cyrf6936.ino" #include "Devo_cyrf6936.ino"
#include "J6Pro_cyrf6936.ino"
#include "Telemetry.ino" #include "Telemetry.ino"

View File

@ -19,6 +19,7 @@
//--------------------------- //---------------------------
#include "iface_nrf24l01.h" #include "iface_nrf24l01.h"
//--------------------------- //---------------------------
// NRF24L01+ SPI Specific Functions // NRF24L01+ SPI Specific Functions
//--------------------------- //---------------------------
@ -156,6 +157,42 @@ void NRF24L01_SetPower()
} }
} }
void NRF24L01_SetTxRxMode(enum TXRX_State mode)
{
if(mode == TX_EN) {
NRF_CSN_off;
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
| (1 << NRF24L01_07_TX_DS)
| (1 << NRF24L01_07_MAX_RT));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC) // switch to TX mode
| (1 << NRF24L01_00_CRCO)
| (1 << NRF24L01_00_PWR_UP));
_delay_us(130);
NRF_CSN_on;
}
else
if (mode == RX_EN) {
NRF_CSN_off;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // reset the flag(s)
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // switch to RX mode
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
| (1 << NRF24L01_07_TX_DS)
| (1 << NRF24L01_07_MAX_RT));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC) // switch to RX mode
| (1 << NRF24L01_00_CRCO)
| (1 << NRF24L01_00_PWR_UP)
| (1 << NRF24L01_00_PRIM_RX));
_delay_us(130);
NRF_CSN_on;
}
else
{
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC)); //PowerDown
NRF_CSN_off;
}
}
/*
void NRF24L01_SetTxRxMode(enum TXRX_State mode) void NRF24L01_SetTxRxMode(enum TXRX_State mode)
{ {
if(mode == TX_EN) { if(mode == TX_EN) {
@ -167,7 +204,7 @@ void NRF24L01_SetTxRxMode(enum TXRX_State mode)
| (1 << NRF24L01_00_CRCO) | (1 << NRF24L01_00_CRCO)
| (1 << NRF24L01_00_PWR_UP)); | (1 << NRF24L01_00_PWR_UP));
delayMicroseconds(130); delayMicroseconds(130);
NRF_CSN_on; NRF_CE_on;
} }
else else
if (mode == RX_EN) { if (mode == RX_EN) {
@ -190,7 +227,7 @@ void NRF24L01_SetTxRxMode(enum TXRX_State mode)
NRF_CE_off; NRF_CE_off;
} }
} }
*/
void NRF24L01_Reset() void NRF24L01_Reset()
{ {
//** not in deviation but needed to hot switch between models //** not in deviation but needed to hot switch between models
@ -205,24 +242,25 @@ void NRF24L01_Reset()
NRF24L01_Strobe(0xff); // NOP NRF24L01_Strobe(0xff); // NOP
NRF24L01_ReadReg(NRF24L01_07_STATUS); NRF24L01_ReadReg(NRF24L01_07_STATUS);
NRF24L01_SetTxRxMode(TXRX_OFF); NRF24L01_SetTxRxMode(TXRX_OFF);
_delay_us(100); delayMicroseconds(100);
} }
uint8_t NRF24L01_packet_ack() uint8_t NRF24L01_packet_ack()
{ {
switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))) switch (NRF24L01_ReadReg(NRF24L01_07_STATUS) & (_BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)))
{ {
case BV(NRF24L01_07_TX_DS): case _BV(NRF24L01_07_TX_DS):
return PKT_ACKED; return PKT_ACKED;
case BV(NRF24L01_07_MAX_RT): case _BV(NRF24L01_07_MAX_RT):
return PKT_TIMEOUT; return PKT_TIMEOUT;
} }
return PKT_PENDING; return PKT_PENDING;
} }
/////////////// ///////////////
// XN297 emulation layer // XN297 emulation layer
uint8_t xn297_scramble_enabled=1; //enabled by default uint8_t xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
uint8_t xn297_addr_len; uint8_t xn297_addr_len;
uint8_t xn297_tx_addr[5]; uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5]; uint8_t xn297_rx_addr[5];
@ -235,13 +273,6 @@ static const uint8_t xn297_scramble[] = {
0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f, 0x1b, 0x5d, 0x19, 0x10, 0x24, 0xd3, 0xdc, 0x3f,
0x8e, 0xc5, 0x2f}; 0x8e, 0xc5, 0x2f};
const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3d5f, 0xa6f1, 0x3a23, 0xaa16, 0x1caf,
0x62b2, 0xe0eb, 0x0821, 0xbe07, 0x5f1a, 0xaf15,
0x4f0a, 0xad24, 0x5e48, 0xed34, 0x068c, 0xf2c9,
0x1852, 0xdf36, 0x129d, 0xb17c, 0xd5f5, 0x70d7,
0xb798, 0x5133, 0x67db, 0xd94e};
const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = { const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C, 0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B, 0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
@ -249,6 +280,13 @@ const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401, 0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
0x2138, 0x129F, 0xB3A0, 0x2988}; 0x2138, 0x129F, 0xB3A0, 0x2988};
const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3d5f, 0xa6f1, 0x3a23, 0xaa16, 0x1caf,
0x62b2, 0xe0eb, 0x0821, 0xbe07, 0x5f1a, 0xaf15,
0x4f0a, 0xad24, 0x5e48, 0xed34, 0x068c, 0xf2c9,
0x1852, 0xdf36, 0x129d, 0xb17c, 0xd5f5, 0x70d7,
0xb798, 0x5133, 0x67db, 0xd94e};
static uint8_t bit_reverse(uint8_t b_in) static uint8_t bit_reverse(uint8_t b_in)
{ {
uint8_t b_out = 0; uint8_t b_out = 0;
@ -260,10 +298,9 @@ static uint8_t bit_reverse(uint8_t b_in)
return b_out; return b_out;
} }
static const uint16_t polynomial = 0x1021;
static uint16_t crc16_update(uint16_t crc, uint8_t a) static uint16_t crc16_update(uint16_t crc, uint8_t a)
{ {
static const uint16_t polynomial = 0x1021;
crc ^= a << 8; crc ^= a << 8;
for (uint8_t i = 0; i < 8; ++i) for (uint8_t i = 0; i < 8; ++i)
if (crc & 0x8000) if (crc & 0x8000)
@ -309,14 +346,18 @@ void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5); NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
} }
void XN297_Configure(uint16_t flags) void XN297_Configure(uint8_t flags)
{ {
xn297_scramble_enabled = !(flags & BV(XN297_UNSCRAMBLED)); xn297_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
xn297_crc = !!(flags & BV(NRF24L01_00_EN_CRC)); flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
flags &= ~(BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF); NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
} }
void XN297_SetScrambledMode(const uint8_t mode)
{
xn297_scramble_enabled = mode;
}
void XN297_WritePayload(uint8_t* msg, uint8_t len) void XN297_WritePayload(uint8_t* msg, uint8_t len)
{ {
uint8_t buf[32]; uint8_t buf[32];

View File

@ -18,7 +18,6 @@
#include "iface_cc2500.h" #include "iface_cc2500.h"
#define SFHSS_COARSE 0 #define SFHSS_COARSE 0
#define SFHSS_PACKET_LEN 13 #define SFHSS_PACKET_LEN 13
@ -27,11 +26,11 @@
uint8_t fhss_code; // 0-27 uint8_t fhss_code; // 0-27
enum { enum {
SFHSS_START = 0x101, SFHSS_START = 0x00,
SFHSS_CAL = 0x102, SFHSS_CAL = 0x01,
SFHSS_TUNE = 0x103, SFHSS_DATA1 = 0x02, // do not change this value
SFHSS_DATA1 = 0x02, SFHSS_DATA2 = 0x0B, // do not change this value
SFHSS_DATA2 = 0x0b SFHSS_TUNE = 0x0F
}; };
#define SFHSS_FREQ0_VAL 0xC4 #define SFHSS_FREQ0_VAL 0xC4
@ -75,12 +74,11 @@ const PROGMEM uint8_t SFHSS_init_values[] = {
static void __attribute__((unused)) SFHSS_rf_init() static void __attribute__((unused)) SFHSS_rf_init()
{ {
CC2500_Reset();
CC2500_Strobe(CC2500_SIDLE); CC2500_Strobe(CC2500_SIDLE);
for (uint8_t i = 0; i < 39; ++i) for (uint8_t i = 0; i < 39; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&SFHSS_init_values[i])); CC2500_WriteReg(i, pgm_read_byte_near(&SFHSS_init_values[i]));
//CC2500_WriteRegisterMulti(CC2500_00_IOCFG2, init_values, sizeof(init_values));
prev_option = option; prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option); CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
@ -102,16 +100,14 @@ static void __attribute__((unused)) SFHSS_tune_chan_fast()
CC2500_WriteReg(CC2500_25_FSCAL1, calData[rf_ch_num]); CC2500_WriteReg(CC2500_25_FSCAL1, calData[rf_ch_num]);
} }
static void __attribute__((unused)) 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
if ( prev_option != option ) if ( prev_option != option )
{ {
CC2500_WriteReg(CC2500_0C_FSCTRL0, option); CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_WriteReg(CC2500_0F_FREQ0, SFHSS_FREQ0_VAL + SFHSS_COARSE); CC2500_WriteReg(CC2500_0F_FREQ0, SFHSS_FREQ0_VAL + SFHSS_COARSE);
prev_option = option ; prev_option = option ;
phase = SFHSS_START; // Restart the tune process if option is changed to get good tuned values
} }
} }
@ -130,23 +126,20 @@ static void __attribute__((unused)) SFHSS_calc_next_chan()
// Values grow down and to the right, so we just revert every channel. // Values grow down and to the right, so we just revert every channel.
static uint16_t __attribute__((unused)) SFHSS_convert_channel(uint8_t num) 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,906,86)); return (uint16_t) (map(limit_channel_100(num),servo_min_100,servo_max_100,906,86));
} }
static void __attribute__((unused)) SFHSS_build_data_packet() static void __attribute__((unused)) SFHSS_build_data_packet()
{ {
#define spacer1 0x02 //0b10 #define spacer1 0x02 //0b10
#define spacer2 (spacer1 << 4) #define spacer2 (spacer1 << 4)
uint8_t ch_offset = state == SFHSS_DATA1 ? 0 : 4; uint8_t ch_offset = phase == SFHSS_DATA1 ? 0 : 4;
const uint8_t ch[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4}; uint16_t ch1 = SFHSS_convert_channel(CH_AETR[ch_offset+0]);
uint16_t ch2 = SFHSS_convert_channel(CH_AETR[ch_offset+1]);
uint16_t ch3 = SFHSS_convert_channel(CH_AETR[ch_offset+2]);
uint16_t ch4 = SFHSS_convert_channel(CH_AETR[ch_offset+3]);
uint16_t ch1 = SFHSS_convert_channel(ch[ch_offset+0]); packet[0] = 0x81; // can be 80 or 81 for Orange, only 81 for XK
uint16_t ch2 = SFHSS_convert_channel(ch[ch_offset+1]);
uint16_t ch3 = SFHSS_convert_channel(ch[ch_offset+2]);
uint16_t 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[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1]; packet[2] = rx_tx_addr[1];
packet[3] = 0; packet[3] = 0;
@ -158,23 +151,22 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
packet[9] = (ch3 >> 1); packet[9] = (ch3 >> 1);
packet[10] = (ch3 << 7) | spacer2 | ((ch4 >> 5) & 0x1F /*0b11111*/); packet[10] = (ch3 << 7) | spacer2 | ((ch4 >> 5) & 0x1F /*0b11111*/);
packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0x07 /*0b111 */); packet[11] = (ch4 << 3) | ((fhss_code >> 2) & 0x07 /*0b111 */);
packet[12] = (fhss_code << 6) | state; packet[12] = (fhss_code << 6) | phase;
} }
static void __attribute__((unused)) SFHSS_send_packet() static void __attribute__((unused)) SFHSS_send_packet()
{ {
//SFHSS_tune_chan_fast();
CC2500_WriteData(packet, SFHSS_PACKET_LEN); CC2500_WriteData(packet, SFHSS_PACKET_LEN);
} }
uint16_t ReadSFHSS() uint16_t ReadSFHSS()
{ {
switch(state) switch(phase)
{ {
case SFHSS_START: case SFHSS_START:
rf_ch_num = 0; rf_ch_num = 0;
SFHSS_tune_chan(); SFHSS_tune_chan();
state = SFHSS_CAL; phase = SFHSS_CAL;
return 2000; return 2000;
case SFHSS_CAL: case SFHSS_CAL:
calData[rf_ch_num]=CC2500_ReadReg(CC2500_25_FSCAL1); calData[rf_ch_num]=CC2500_ReadReg(CC2500_25_FSCAL1);
@ -183,7 +175,7 @@ uint16_t ReadSFHSS()
else else
{ {
rf_ch_num = 0; rf_ch_num = 0;
state = SFHSS_DATA1; phase = SFHSS_DATA1;
} }
return 2000; return 2000;
@ -191,16 +183,16 @@ uint16_t ReadSFHSS()
case SFHSS_DATA1: case SFHSS_DATA1:
SFHSS_build_data_packet(); SFHSS_build_data_packet();
SFHSS_send_packet(); SFHSS_send_packet();
state = SFHSS_DATA2; phase = SFHSS_DATA2;
return 1650; return 1650;
case SFHSS_DATA2: case SFHSS_DATA2:
SFHSS_build_data_packet(); SFHSS_build_data_packet();
SFHSS_send_packet(); SFHSS_send_packet();
SFHSS_calc_next_chan(); SFHSS_calc_next_chan();
state = SFHSS_TUNE; phase = SFHSS_TUNE;
return 2000; return 2000;
case SFHSS_TUNE: case SFHSS_TUNE:
state = SFHSS_DATA1; phase = SFHSS_DATA1;
SFHSS_tune_freq(); SFHSS_tune_freq();
SFHSS_tune_chan_fast(); SFHSS_tune_chan_fast();
CC2500_SetPower(); CC2500_SetPower();
@ -241,13 +233,13 @@ static void __attribute__((unused)) SFHSS_get_tx_id()
uint16_t initSFHSS() uint16_t initSFHSS()
{ {
BIND_DONE; // No bind protocol BIND_DONE; // Not a TX bind protocol
SFHSS_get_tx_id(); SFHSS_get_tx_id();
fhss_code=rx_tx_addr[2]%28; // Initialize it to random 0-27 inclusive fhss_code=rx_tx_addr[2]%28; // Initialize it to random 0-27 inclusive
SFHSS_rf_init(); SFHSS_rf_init();
state = SFHSS_START; phase = SFHSS_START;
return 10000; return 10000;
} }

View File

@ -4,10 +4,12 @@
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful, Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>. along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -93,7 +95,7 @@ uint16_t SHENQI_callback()
SHENQI_send_packet(); SHENQI_send_packet();
else else
{ {
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_RX_DR)) if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ {
if(LT8900_ReadPayload(packet, 3)) if(LT8900_ReadPayload(packet, 3))
{ {
@ -115,7 +117,7 @@ uint16_t initSHENQI()
SHENQI_init(); SHENQI_init();
hopping_frequency_no = 0; hopping_frequency_no = 0;
packet_count=0; packet_count=0;
packet_period=100; packet_period=500;
return 1000; return 1000;
} }

View File

@ -34,7 +34,7 @@ enum {
static void __attribute__((unused)) SLT_init() static void __attribute__((unused)) SLT_init()
{ {
NRF24L01_Initialize(); NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)); // 2-bytes CRC, radio off NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)); // 2-bytes CRC, radio off
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4-byte RX/TX address NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4-byte RX/TX address
@ -93,7 +93,7 @@ static void __attribute__((unused)) SLT_set_tx_id(void)
static void __attribute__((unused)) SLT_wait_radio() static void __attribute__((unused)) SLT_wait_radio()
{ {
if (packet_sent) if (packet_sent)
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & BV(NRF24L01_07_TX_DS))) ; while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS))) ;
packet_sent = 0; packet_sent = 0;
} }
@ -101,7 +101,7 @@ static void __attribute__((unused)) SLT_send_data(uint8_t *data, uint8_t len)
{ {
SLT_wait_radio(); SLT_wait_radio();
NRF24L01_FlushTx(); NRF24L01_FlushTx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_RX_DR) | BV(NRF24L01_07_MAX_RT)); NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
NRF24L01_WritePayload(data, len); NRF24L01_WritePayload(data, len);
//NRF24L01_PulseCE(); //NRF24L01_PulseCE();
packet_sent = 1; packet_sent = 1;

View File

@ -174,7 +174,7 @@ static void __attribute__((unused)) symax_init()
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
// //
NRF24L01_ReadReg(NRF24L01_07_STATUS); NRF24L01_ReadReg(NRF24L01_07_STATUS);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)); NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes (even though not used?) NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes (even though not used?)
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address

View File

@ -80,7 +80,7 @@ static void __attribute__((unused)) v202_init()
NRF24L01_Initialize(); NRF24L01_Initialize();
// 2-bytes CRC, radio off // 2-bytes CRC, radio off
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO)); NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
@ -116,7 +116,7 @@ static void __attribute__((unused)) V202_init2()
// Turn radio power on // Turn radio power on
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
//Done by TX_EN??? => NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_CRCO) | BV(NRF24L01_00_PWR_UP)); //Done by TX_EN??? => NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
} }
static void __attribute__((unused)) V2X2_set_tx_id(void) static void __attribute__((unused)) V2X2_set_tx_id(void)

View File

@ -34,13 +34,6 @@
#define YD717_PAYLOADSIZE 8 // receive data pipes set to this size, but unused #define YD717_PAYLOADSIZE 8 // receive data pipes set to this size, but unused
enum {
YD717_INIT1 = 0,
YD717_BIND2,
YD717_BIND3,
YD717_DATA
};
static void __attribute__((unused)) yd717_send_packet(uint8_t bind) static void __attribute__((unused)) yd717_send_packet(uint8_t bind)
{ {
uint8_t rudder_trim, elevator_trim, aileron_trim; uint8_t rudder_trim, elevator_trim, aileron_trim;
@ -108,7 +101,7 @@ static void __attribute__((unused)) yd717_send_packet(uint8_t bind)
} }
// clear packet status bits and TX FIFO // clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, (BV(NRF24L01_07_TX_DS) | BV(NRF24L01_07_MAX_RT))); NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)));
NRF24L01_FlushTx(); NRF24L01_FlushTx();
if( sub_protocol == YD717 ) if( sub_protocol == YD717 )
@ -131,117 +124,62 @@ static void __attribute__((unused)) yd717_init()
// CRC, radio on // CRC, radio on
NRF24L01_SetTxRxMode(TX_EN); NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, BV(NRF24L01_00_EN_CRC) | BV(NRF24L01_00_PWR_UP)); NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3F); // Auto Acknoledgement on all data pipes NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // Disable Acknoledgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00); // Disable all data pipes
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x1A); // 500uS retransmit t/o, 10 tries NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmit
NRF24L01_WriteReg(NRF24L01_05_RF_CH, YD717_RF_CHANNEL); // Channel 3C NRF24L01_WriteReg(NRF24L01_05_RF_CH, YD717_RF_CHANNEL); // Channel 3C
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower(); NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_0C_RX_ADDR_P2, 0xC3); // LSB byte of pipe 2 receive address
NRF24L01_WriteReg(NRF24L01_0D_RX_ADDR_P3, 0xC4);
NRF24L01_WriteReg(NRF24L01_0E_RX_ADDR_P4, 0xC5);
NRF24L01_WriteReg(NRF24L01_0F_RX_ADDR_P5, 0xC6);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, YD717_PAYLOADSIZE); // bytes of data payload for pipe 1
NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, YD717_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_13_RX_PW_P2, YD717_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_14_RX_PW_P3, YD717_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_15_RX_PW_P4, YD717_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_16_RX_PW_P5, YD717_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
NRF24L01_Activate(0x73); // Activate feature register NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F); // Enable dynamic payload length on all pipes NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F); // Enable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Set feature bits on NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Set feature bits on
NRF24L01_Activate(0x73); NRF24L01_Activate(0x73);
// set tx id
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
}
static void __attribute__((unused)) YD717_init1()
{
// for bind packets set address to prearranged value known to receiver // for bind packets set address to prearranged value known to receiver
uint8_t bind_rx_tx_addr[] = {0x65, 0x65, 0x65, 0x65, 0x65}; uint8_t bind_rx_tx_addr[] = {0x65, 0x65, 0x65, 0x65, 0x65};
uint8_t i;
if( sub_protocol==SYMAX4 ) if( sub_protocol==SYMAX4 )
for(i=0; i < 5; i++) for(uint8_t i=0; i < 5; i++)
bind_rx_tx_addr[i] = 0x60; bind_rx_tx_addr[i] = 0x60;
else else
if( sub_protocol==NIHUI ) if( sub_protocol==NIHUI )
for(i=0; i < 5; i++) for(uint8_t i=0; i < 5; i++)
bind_rx_tx_addr[i] = 0x64; bind_rx_tx_addr[i] = 0x64;
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, bind_rx_tx_addr, 5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_rx_tx_addr, 5); NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, bind_rx_tx_addr, 5);
} }
static void __attribute__((unused)) YD717_init2()
{
// set rx/tx address for data phase
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
}
uint16_t yd717_callback() uint16_t yd717_callback()
{ {
switch (phase) if(IS_BIND_DONE_on)
yd717_send_packet(0);
else
{ {
case YD717_INIT1: if (bind_counter == 0)
yd717_send_packet(0); // receiver doesn't re-enter bind mode if connection lost...check if already bound
phase = YD717_BIND3;
break;
case YD717_BIND2:
if (counter == 0)
{ {
if (NRF24L01_packet_ack() == PKT_PENDING) NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5); // set address
return YD717_PACKET_CHKTIME; // packet send not yet complete
YD717_init2(); // change to data phase rx/tx address
yd717_send_packet(0); yd717_send_packet(0);
phase = YD717_BIND3; BIND_DONE; // bind complete
} }
else else
{ {
if (NRF24L01_packet_ack() == PKT_PENDING)
return YD717_PACKET_CHKTIME; // packet send not yet complete;
yd717_send_packet(1); yd717_send_packet(1);
counter--; bind_counter--;
} }
break;
case YD717_BIND3:
switch (NRF24L01_packet_ack())
{
case PKT_PENDING:
return YD717_PACKET_CHKTIME; // packet send not yet complete
case PKT_ACKED:
phase = YD717_DATA;
BIND_DONE; // bind complete
break;
case PKT_TIMEOUT:
YD717_init1(); // change to bind rx/tx address
counter = YD717_BIND_COUNT;
phase = YD717_BIND2;
yd717_send_packet(1);
}
break;
case YD717_DATA:
if (NRF24L01_packet_ack() == PKT_PENDING)
return YD717_PACKET_CHKTIME; // packet send not yet complete
yd717_send_packet(0);
break;
} }
return YD717_PACKET_PERIOD; // Packet every 8ms return YD717_PACKET_PERIOD; // Packet every 8ms
} }
uint16_t initYD717() uint16_t initYD717()
{ {
BIND_IN_PROGRESS; // autobind protocol
rx_tx_addr[4] = 0xC1; // always uses first data port rx_tx_addr[4] = 0xC1; // always uses first data port
yd717_init(); yd717_init();
phase = YD717_INIT1; bind_counter = YD717_BIND_COUNT;
BIND_IN_PROGRESS; // autobind protocol
// Call callback in 50ms // Call callback in 50ms
return YD717_INITIAL_WAIT; return YD717_INITIAL_WAIT;