DSM: selectable refresh rate 22/11ms when supported

This commit is contained in:
Pascal Langer
2020-06-12 00:25:09 +02:00
parent 944ec62f49
commit f52f96d44e
6 changed files with 66 additions and 44 deletions

View File

@@ -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
}