|
|
|
|
@@ -43,21 +43,23 @@ enum {
|
|
|
|
|
//
|
|
|
|
|
uint8_t ch_map[14];
|
|
|
|
|
const uint8_t PROGMEM DSM_ch_map_progmem[][14] = {
|
|
|
|
|
//22+11ms for 4..7 channels
|
|
|
|
|
//22+11ms for 3..7 channels
|
|
|
|
|
{1, 0, 2, 0xff, 0xff, 0xff, 0xff, 1, 0, 2, 0xff, 0xff, 0xff, 0xff}, //3ch - Guess
|
|
|
|
|
{1, 0, 2, 3, 0xff, 0xff, 0xff, 1, 0, 2, 3, 0xff, 0xff, 0xff}, //4ch - Guess
|
|
|
|
|
{1, 0, 2, 3, 4, 0xff, 0xff, 1, 0, 2, 3, 4, 0xff, 0xff}, //5ch - Guess
|
|
|
|
|
{1, 5, 2, 3, 0, 4, 0xff, 1, 5, 2, 3, 0, 4, 0xff}, //6ch - HP6DSM
|
|
|
|
|
{1, 5, 2, 4, 3, 6, 0, 1, 5, 2, 4, 3, 6, 0xff}, //7ch - DX6i -> removed channel 0 on second packet to prevent some RXs to switch to 11ms
|
|
|
|
|
{1, 5, 2, 4, 3, 6, 0, 1, 5, 2, 4, 3, 6, 0 }, //7ch - DX6i
|
|
|
|
|
//22ms for 8..12 channels
|
|
|
|
|
{1, 5, 2, 3, 6, 0xff, 0xff, 4, 0, 7, 0xff, 0xff, 0xff, 0xff}, //8ch - DX8/DX7
|
|
|
|
|
{1, 5, 2, 3, 6, 0xff, 0xff, 4, 0, 7, 8, 0xff, 0xff, 0xff}, //9ch - Guess
|
|
|
|
|
{1, 5, 2, 3, 6, 0xff, 0xff, 4, 0, 7, 8, 9, 0xff, 0xff}, //10ch - Guess
|
|
|
|
|
{1, 5, 2, 3, 6, 10, 0xff, 4, 0, 7, 8, 9, 0xff, 0xff}, //11ch - Guess
|
|
|
|
|
{1, 5, 2, 4, 6, 10, 0xff, 0, 7, 3, 8, 9 , 11 , 0xff}, //12ch - DX18
|
|
|
|
|
//11ms for 8..12 channels
|
|
|
|
|
//11ms for 8..11 channels
|
|
|
|
|
{1, 5, 2, 3, 6, 7, 0xff, 1, 5, 2, 4, 0, 0xff, 0xff}, //8ch - DX7
|
|
|
|
|
{1, 5, 2, 3, 6, 7, 0xff, 1, 5, 2, 4, 0, 8, 0xff}, //9ch - Guess
|
|
|
|
|
{1, 5, 2, 3, 4, 8, 9, 1, 5, 2, 3, 0, 7, 6 }, //10ch - DX18
|
|
|
|
|
{1, 5, 2, 3, 4, 8, 9, 1, 10, 2, 3, 0, 7, 6 }, //11ch - Guess
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void __attribute__((unused)) DSM_build_bind_packet()
|
|
|
|
|
@@ -76,23 +78,26 @@ static void __attribute__((unused)) DSM_build_bind_packet()
|
|
|
|
|
sum += packet[i];
|
|
|
|
|
packet[8] = sum >> 8;
|
|
|
|
|
packet[9] = sum & 0xff;
|
|
|
|
|
packet[10] = 0x01; //???
|
|
|
|
|
packet[11] = num_ch;
|
|
|
|
|
packet[10] = 0x01; // ???
|
|
|
|
|
if(sub_protocol==DSM_AUTO)
|
|
|
|
|
packet[11] = 12;
|
|
|
|
|
else
|
|
|
|
|
packet[11] = num_ch;
|
|
|
|
|
|
|
|
|
|
if (sub_protocol==DSM2_22)
|
|
|
|
|
packet[12]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
|
|
|
|
|
if(sub_protocol==DSM2_11)
|
|
|
|
|
packet[12]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
|
|
|
|
|
else if(sub_protocol==DSM2_11)
|
|
|
|
|
packet[12]=0x12; // DSM2/2048 2 packets
|
|
|
|
|
if(sub_protocol==DSMX_22)
|
|
|
|
|
else if(sub_protocol==DSMX_22)
|
|
|
|
|
#if defined DSM_TELEMETRY
|
|
|
|
|
packet[12] = 0xb2; // DSMX/2048 2 packets
|
|
|
|
|
#else
|
|
|
|
|
packet[12] = 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
|
|
|
|
|
else // DSMX_11 && DSM_AUTO
|
|
|
|
|
packet[12]=0xb2; // DSMX/2048 2 packets
|
|
|
|
|
|
|
|
|
|
packet[13] = 0x00; //???
|
|
|
|
|
packet[13] = 0x00; //???
|
|
|
|
|
for(i = 8; i < 14; i++)
|
|
|
|
|
sum += packet[i];
|
|
|
|
|
packet[14] = sum >> 8;
|
|
|
|
|
@@ -112,17 +117,15 @@ static void __attribute__((unused)) DSM_initialize_bind_phase()
|
|
|
|
|
static void __attribute__((unused)) DSM_update_channels()
|
|
|
|
|
{
|
|
|
|
|
prev_option=option;
|
|
|
|
|
if(sub_protocol==DSM_AUTO)
|
|
|
|
|
num_ch=12; // Force 12 channels in mode Auto
|
|
|
|
|
else
|
|
|
|
|
num_ch=option & 0x7F; // Remove the Max Throw flag
|
|
|
|
|
if(num_ch<4 || num_ch>12)
|
|
|
|
|
num_ch=option & 0x0F; // Remove flags 0x80=max_throw, 0x40=11ms
|
|
|
|
|
|
|
|
|
|
if(num_ch<3 || num_ch>12)
|
|
|
|
|
num_ch=6; // Default to 6 channels if invalid choice...
|
|
|
|
|
|
|
|
|
|
// Create channel map based on number of channels and refresh rate
|
|
|
|
|
uint8_t idx=num_ch-4;
|
|
|
|
|
if(num_ch>7 && num_ch<11 && (sub_protocol==DSM2_11 || sub_protocol==DSMX_11))
|
|
|
|
|
idx+=5; // In 11ms mode change index only for channels 8..10
|
|
|
|
|
uint8_t idx=num_ch-3;
|
|
|
|
|
if((option & 0x40) && num_ch>7 && num_ch<12)
|
|
|
|
|
idx+=5; // In 11ms mode change index only for channels 8..11
|
|
|
|
|
for(uint8_t i=0;i<14;i++)
|
|
|
|
|
ch_map[i]=pgm_read_byte_near(&DSM_ch_map_progmem[idx][i]);
|
|
|
|
|
}
|
|
|
|
|
@@ -135,24 +138,26 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
|
|
|
|
DSM_update_channels();
|
|
|
|
|
|
|
|
|
|
if (sub_protocol==DSMX_11 || sub_protocol==DSMX_22 )
|
|
|
|
|
{
|
|
|
|
|
{//DSMX
|
|
|
|
|
packet[0] = cyrfmfg_id[2];
|
|
|
|
|
packet[1] = cyrfmfg_id[3];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
{//DSM2
|
|
|
|
|
packet[0] = (0xff ^ cyrfmfg_id[2]);
|
|
|
|
|
packet[1] = (0xff ^ cyrfmfg_id[3]);
|
|
|
|
|
if(sub_protocol==DSM2_22)
|
|
|
|
|
bits=10; // Only DSM2_22 is using a resolution of 1024
|
|
|
|
|
bits=10; // Only DSM2_22 is using a resolution of 1024
|
|
|
|
|
}
|
|
|
|
|
#ifdef DSM_THROTTLE_KILL_CH
|
|
|
|
|
uint16_t kill_ch=Channel_data[DSM_THROTTLE_KILL_CH-1];
|
|
|
|
|
#endif
|
|
|
|
|
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;;
|
|
|
|
|
uint8_t idx = ch_map[(upper?7:0) + i]; // 1,5,2,3,0,4
|
|
|
|
|
uint16_t value = 0xffff;
|
|
|
|
|
if((option&0x40) == 0 && num_ch < 8 && upper)
|
|
|
|
|
idx=0xff; // in 22ms do not transmit upper channels if <8, is it the right method???
|
|
|
|
|
if (idx != 0xff)
|
|
|
|
|
{
|
|
|
|
|
/* Spektrum own remotes transmit normal values during bind and actually use this (e.g. Nano CP X) to
|
|
|
|
|
@@ -160,7 +165,7 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
|
|
|
|
#ifdef DSM_THROTTLE_KILL_CH
|
|
|
|
|
if(idx==CH1 && kill_ch<=604)
|
|
|
|
|
{//Activate throttle kill only if channel is throttle and DSM_THROTTLE_KILL_CH below -50%
|
|
|
|
|
if(kill_ch<CHANNEL_MIN_100) // restrict val to 0...400
|
|
|
|
|
if(kill_ch<CHANNEL_MIN_100) // restrict val to 0...400
|
|
|
|
|
kill_ch=0;
|
|
|
|
|
else
|
|
|
|
|
kill_ch-=CHANNEL_MIN_100;
|
|
|
|
|
@@ -221,9 +226,9 @@ uint16_t ReadDsm()
|
|
|
|
|
case DSM_BIND_WRITE:
|
|
|
|
|
if(bind_counter--==0)
|
|
|
|
|
#if defined DSM_TELEMETRY
|
|
|
|
|
phase=DSM_BIND_CHECK; //Check RX answer
|
|
|
|
|
phase=DSM_BIND_CHECK; //Check RX answer
|
|
|
|
|
#else
|
|
|
|
|
phase=DSM_CHANSEL; //Switch to normal mode
|
|
|
|
|
phase=DSM_CHANSEL; //Switch to normal mode
|
|
|
|
|
#endif
|
|
|
|
|
CYRF_WriteDataPacket(packet);
|
|
|
|
|
return 10000;
|
|
|
|
|
@@ -231,28 +236,32 @@ uint16_t ReadDsm()
|
|
|
|
|
case DSM_BIND_CHECK:
|
|
|
|
|
//64 SDR Mode is configured so only the 8 first values are needed but we need to write 16 values...
|
|
|
|
|
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84", 16);
|
|
|
|
|
CYRF_SetTxRxMode(RX_EN); //Receive mode
|
|
|
|
|
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //Prepare to receive
|
|
|
|
|
bind_counter=2*DSM_BIND_COUNT; //Timeout of 4.2s if no packet received
|
|
|
|
|
phase++; // change from BIND_CHECK to BIND_READ
|
|
|
|
|
CYRF_SetTxRxMode(RX_EN); //Receive mode
|
|
|
|
|
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //Prepare to receive
|
|
|
|
|
bind_counter=2*DSM_BIND_COUNT; //Timeout of 4.2s if no packet received
|
|
|
|
|
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)
|
|
|
|
|
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 with no errors
|
|
|
|
|
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // Need to set RXOW before data read
|
|
|
|
|
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80);// Need to set RXOW before data read
|
|
|
|
|
if(CYRF_ReadRegister(CYRF_09_RX_COUNT)==10) // Len
|
|
|
|
|
{
|
|
|
|
|
CYRF_ReadDataPacketLen(packet_in+1, 10);
|
|
|
|
|
if(DSM_Check_RX_packet())
|
|
|
|
|
{
|
|
|
|
|
debug("Bind");
|
|
|
|
|
for(uint8_t i=0;i<10;i++)
|
|
|
|
|
debug(" %02X",packet_in[i+1]);
|
|
|
|
|
debugln("");
|
|
|
|
|
packet_in[0]=0x80;
|
|
|
|
|
packet_in[6]&=0x0F; // It looks like there is a flag 0x40 being added by some receivers
|
|
|
|
|
if(packet_in[6]>12) packet_in[6]=12;
|
|
|
|
|
else if(packet_in[6]<4) packet_in[6]=6;
|
|
|
|
|
else if(packet_in[6]<3) packet_in[6]=6;
|
|
|
|
|
telemetry_link=1; // Send received data on serial
|
|
|
|
|
phase++;
|
|
|
|
|
return 2000;
|
|
|
|
|
@@ -296,6 +305,11 @@ uint16_t ReadDsm()
|
|
|
|
|
DSM_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);
|
|
|
|
|
#if 0
|
|
|
|
|
for(uint8_t i=0;i<16;i++)
|
|
|
|
|
debug(" %02X", packet[i]);
|
|
|
|
|
debugln("");
|
|
|
|
|
#endif
|
|
|
|
|
phase++; // change from WRITE to CHECK mode
|
|
|
|
|
return DSM_WRITE_DELAY;
|
|
|
|
|
case DSM_CH1_CHECK_A:
|
|
|
|
|
@@ -329,6 +343,8 @@ uint16_t ReadDsm()
|
|
|
|
|
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
|
|
|
|
|
if(num_ch==3)
|
|
|
|
|
return 8250 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
|
|
|
|
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
|
|
|
|
case DSM_CH2_READ_A:
|
|
|
|
|
case DSM_CH2_READ_B:
|
|
|
|
|
@@ -353,6 +369,8 @@ uint16_t ReadDsm()
|
|
|
|
|
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
|
|
|
|
|
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
|
|
|
|
|
phase = DSM_CH2_READ_B;
|
|
|
|
|
if(num_ch==3)
|
|
|
|
|
return 8250;
|
|
|
|
|
return 11000;
|
|
|
|
|
}
|
|
|
|
|
if (phase == DSM_CH2_READ_A)
|
|
|
|
|
@@ -373,11 +391,15 @@ uint16_t ReadDsm()
|
|
|
|
|
else
|
|
|
|
|
{ //Normal mode 22ms
|
|
|
|
|
phase = DSM_CH1_WRITE_A; // change from CH2_CHECK_A to CH1_WRITE_A (ie no upper)
|
|
|
|
|
if(num_ch==3)
|
|
|
|
|
return 16500 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
|
|
|
|
|
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)
|
|
|
|
|
if(num_ch==3)
|
|
|
|
|
return 8250 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
|
|
|
|
|
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|