|
|
|
|
@@ -86,12 +86,14 @@ static void __attribute__((unused)) DSM_build_bind_packet()
|
|
|
|
|
if(sub_protocol==DSM_AUTO)
|
|
|
|
|
packet[11] = 12;
|
|
|
|
|
else
|
|
|
|
|
packet[11] = num_ch;
|
|
|
|
|
packet[11] = num_ch; // DX5 DSMR sends 0x48...
|
|
|
|
|
|
|
|
|
|
if (sub_protocol==DSM2_1F)
|
|
|
|
|
packet[12]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
|
|
|
|
|
if (sub_protocol==DSMR)
|
|
|
|
|
packet[12] = 0xa2;
|
|
|
|
|
else if (sub_protocol==DSM2_1F)
|
|
|
|
|
packet[12] = num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
|
|
|
|
|
else if(sub_protocol==DSM2_2F)
|
|
|
|
|
packet[12]=0x12; // DSM2/2048 2 packets
|
|
|
|
|
packet[12] = 0x12; // DSM2/2048 2 packets
|
|
|
|
|
else if(sub_protocol==DSMX_1F)
|
|
|
|
|
#if defined DSM_TELEMETRY
|
|
|
|
|
packet[12] = 0xb2; // DSMX/2048 2 packets
|
|
|
|
|
@@ -99,8 +101,9 @@ static void __attribute__((unused)) DSM_build_bind_packet()
|
|
|
|
|
packet[12] = num_ch<8? 0xa2 : 0xb2; // DSMX/2048 1 or 2 packets depending on the number of channels
|
|
|
|
|
#endif
|
|
|
|
|
else // DSMX_2F && DSM_AUTO
|
|
|
|
|
packet[12]=0xb2; // DSMX/2048 2 packets
|
|
|
|
|
packet[12] = 0xb2; // DSMX/2048 2 packets
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
packet[13] = 0x00; //???
|
|
|
|
|
for(i = 8; i < 14; i++)
|
|
|
|
|
sum += packet[i];
|
|
|
|
|
@@ -126,6 +129,9 @@ static void __attribute__((unused)) DSM_update_channels()
|
|
|
|
|
if(num_ch<3 || num_ch>12)
|
|
|
|
|
num_ch=6; // Default to 6 channels if invalid choice...
|
|
|
|
|
|
|
|
|
|
if(sub_protocol==DSMR && num_ch>7)
|
|
|
|
|
num_ch=7; // Max 7 channels in DSMR
|
|
|
|
|
|
|
|
|
|
// Create channel map based on number of channels and refresh rate
|
|
|
|
|
uint8_t idx=num_ch-3;
|
|
|
|
|
if((option & 0x40) && num_ch>7 && num_ch<12)
|
|
|
|
|
@@ -141,19 +147,32 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
|
|
|
|
if(prev_option!=option)
|
|
|
|
|
DSM_update_channels();
|
|
|
|
|
|
|
|
|
|
if (sub_protocol==DSMX_2F || sub_protocol==DSMX_1F )
|
|
|
|
|
if (sub_protocol==DSMX_2F || sub_protocol==DSMX_1F)
|
|
|
|
|
{//DSMX
|
|
|
|
|
packet[0] = cyrfmfg_id[2];
|
|
|
|
|
packet[1] = cyrfmfg_id[3];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{//DSM2
|
|
|
|
|
{//DSM2 && DSMR
|
|
|
|
|
packet[0] = (0xff ^ cyrfmfg_id[2]);
|
|
|
|
|
packet[1] = (0xff ^ cyrfmfg_id[3]);
|
|
|
|
|
if(sub_protocol==DSM2_1F)
|
|
|
|
|
bits=10; // Only DSM2_1F is using a resolution of 1024
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(sub_protocol == DSMR)
|
|
|
|
|
{
|
|
|
|
|
for (uint8_t i = 0; i < 7; i++)
|
|
|
|
|
{
|
|
|
|
|
uint16_t value = 0x0000;
|
|
|
|
|
if(i < num_ch)
|
|
|
|
|
value=Channel_data[i]<<1;
|
|
|
|
|
packet[i*2+2] = (value >> 8) & 0xff;
|
|
|
|
|
packet[i*2+3] = (value >> 0) & 0xff;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DSM_THROTTLE_KILL_CH
|
|
|
|
|
uint16_t kill_ch=Channel_data[DSM_THROTTLE_KILL_CH-1];
|
|
|
|
|
#endif
|
|
|
|
|
@@ -189,8 +208,8 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
|
|
|
|
if(bits==10) value>>=1;
|
|
|
|
|
value |= (upper && i==0 ? 0x8000 : 0) | (idx << bits);
|
|
|
|
|
}
|
|
|
|
|
packet[i*2+2] = (value >> 8) & 0xff;
|
|
|
|
|
packet[i*2+3] = (value >> 0) & 0xff;
|
|
|
|
|
packet[i*2+2] = value >> 8;
|
|
|
|
|
packet[i*2+3] = value;
|
|
|
|
|
}
|
|
|
|
|
#ifdef DSM_FWD_PGM
|
|
|
|
|
if(upper==0 && DSM_SerialRX && (DSM_SerialRX_val[0]&0xF8)==0x70 )
|
|
|
|
|
@@ -319,26 +338,32 @@ uint16_t DSM_callback()
|
|
|
|
|
DSM_cyrf_configdata();
|
|
|
|
|
CYRF_SetTxRxMode(TX_EN);
|
|
|
|
|
hopping_frequency_no = 0;
|
|
|
|
|
phase = DSM_CH1_WRITE_A; // in fact phase++
|
|
|
|
|
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F);
|
|
|
|
|
phase = DSM_CH1_WRITE_A; // in fact phase++
|
|
|
|
|
if(sub_protocol == DSMR)
|
|
|
|
|
DSM_set_sop_data_crc(false, true);
|
|
|
|
|
else
|
|
|
|
|
DSM_set_sop_data_crc(true, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F); //prep CH1
|
|
|
|
|
return 10000;
|
|
|
|
|
case DSM_CH1_WRITE_A:
|
|
|
|
|
#ifdef MULTI_SYNC
|
|
|
|
|
telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode
|
|
|
|
|
telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode
|
|
|
|
|
#endif
|
|
|
|
|
CYRF_SetPower(0x28); //Keep transmit power in sync
|
|
|
|
|
if(sub_protocol == DSMR)
|
|
|
|
|
CYRF_SetPower(0x08); //Keep transmit power in sync
|
|
|
|
|
else
|
|
|
|
|
CYRF_SetPower(0x28); //Keep transmit power in sync
|
|
|
|
|
case DSM_CH1_WRITE_B:
|
|
|
|
|
DSM_build_data_packet(phase == DSM_CH1_WRITE_B); // build lower or upper channels
|
|
|
|
|
case DSM_CH2_WRITE_A:
|
|
|
|
|
case DSM_CH2_WRITE_B:
|
|
|
|
|
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
|
|
|
|
|
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
|
|
|
|
|
phase++; // change from WRITE to CHECK mode
|
|
|
|
|
return DSM_WRITE_DELAY;
|
|
|
|
|
case DSM_CH1_CHECK_A:
|
|
|
|
|
case DSM_CH1_CHECK_B:
|
|
|
|
|
@@ -349,7 +374,7 @@ uint16_t DSM_callback()
|
|
|
|
|
if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if(phase==DSM_CH1_CHECK_A || phase==DSM_CH1_CHECK_B)
|
|
|
|
|
if((phase==DSM_CH1_CHECK_A || phase==DSM_CH1_CHECK_B) && sub_protocol!=DSMR)
|
|
|
|
|
{
|
|
|
|
|
#if defined DSM_TELEMETRY
|
|
|
|
|
// reset cyrf6936 if freezed after switching from TX to RX
|
|
|
|
|
@@ -361,14 +386,19 @@ uint16_t DSM_callback()
|
|
|
|
|
CYRF_SetTxRxMode(TX_EN);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F || sub_protocol==DSMX_1F);
|
|
|
|
|
phase++; // change from CH1_CHECK to CH2_WRITE
|
|
|
|
|
DSM_set_sop_data_crc(true, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F); // prep CH2
|
|
|
|
|
phase++; // change from CH1_CHECK to CH2_WRITE
|
|
|
|
|
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
|
|
|
|
|
}
|
|
|
|
|
#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
|
|
|
|
|
if(sub_protocol==DSMR)
|
|
|
|
|
{
|
|
|
|
|
phase = DSM_CH2_READ_B;
|
|
|
|
|
return 11000 - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
|
|
|
|
}
|
|
|
|
|
#ifdef DSM_GR300
|
|
|
|
|
if(num_ch==3)
|
|
|
|
|
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
|
|
|
|
@@ -418,7 +448,7 @@ uint16_t DSM_callback()
|
|
|
|
|
phase = DSM_CH1_WRITE_A; //Transmit lower
|
|
|
|
|
CYRF_SetTxRxMode(TX_EN); //TX mode
|
|
|
|
|
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); //Clear abort RX operation
|
|
|
|
|
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F);
|
|
|
|
|
DSM_set_sop_data_crc(false, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F||sub_protocol==DSMR);
|
|
|
|
|
return DSM_READ_DELAY;
|
|
|
|
|
#else
|
|
|
|
|
// No telemetry
|
|
|
|
|
@@ -449,25 +479,65 @@ uint16_t DSM_callback()
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const uint8_t PROGMEM DSMR_ID_FREQ[][4 + 23] = {
|
|
|
|
|
{ 0x71, 0x74, 0x1c, 0xe4, 0x11, 0x2f, 0x17, 0x3d, 0x23, 0x3b, 0x0f, 0x21, 0x25, 0x49, 0x1d, 0x13, 0x4d, 0x1f, 0x41, 0x4b, 0x47, 0x05, 0x27, 0x15, 0x19, 0x3f, 0x07 },
|
|
|
|
|
{ 0xfe, 0xfe, 0xfe, 0xfe, 0x45, 0x31, 0x33, 0x4b, 0x11, 0x29, 0x49, 0x3f, 0x09, 0x13, 0x47, 0x21, 0x1d, 0x43, 0x1f, 0x05, 0x41, 0x19, 0x1b, 0x2d, 0x15, 0x4d, 0x0f },
|
|
|
|
|
{ 0xfe, 0xff, 0xff, 0xff, 0x2a, 0x06, 0x22, 0x28, 0x16, 0x24, 0x38, 0x0e, 0x32, 0x2e, 0x14, 0x3a, 0x04, 0x44, 0x0c, 0x42, 0x1c, 0x4a, 0x10, 0x36, 0x3c, 0x48, 0x26 },
|
|
|
|
|
{ 0xff, 0xfe, 0xff, 0xff, 0x28, 0x34, 0x48, 0x46, 0x3a, 0x12, 0x18, 0x32, 0x14, 0x42, 0x16, 0x40, 0x22, 0x44, 0x1c, 0x0a, 0x36, 0x20, 0x10, 0x0c, 0x3c, 0x26, 0x2e },
|
|
|
|
|
{ 0xff, 0xff, 0xfe, 0xff, 0x3c, 0x16, 0x04, 0x48, 0x1e, 0x4a, 0x10, 0x18, 0x22, 0x28, 0x38, 0x40, 0x20, 0x06, 0x3e, 0x42, 0x30, 0x1a, 0x2c, 0x1c, 0x46, 0x14, 0x34 },
|
|
|
|
|
{ 0xff, 0xff, 0xff, 0xfe, 0x4d, 0x39, 0x1b, 0x13, 0x45, 0x2f, 0x0d, 0x3d, 0x0b, 0x11, 0x47, 0x2d, 0x19, 0x1d, 0x23, 0x35, 0x33, 0x3b, 0x21, 0x31, 0x17, 0x0f, 0x43 },
|
|
|
|
|
{ 0xff, 0xff, 0xff, 0xff, 0x14, 0x28, 0x2e, 0x32, 0x3e, 0x10, 0x38, 0x0e, 0x12, 0x06, 0x2c, 0x26, 0x30, 0x4c, 0x34, 0x16, 0x04, 0x3a, 0x42, 0x48, 0x36, 0x46, 0x1a },
|
|
|
|
|
{ 0x00, 0xff, 0xff, 0xff, 0x3e, 0x30, 0x42, 0x24, 0x06, 0x0e, 0x14, 0x1c, 0x08, 0x10, 0x20, 0x22, 0x04, 0x32, 0x0c, 0x44, 0x3c, 0x46, 0x4a, 0x26, 0x4c, 0x48, 0x1e },
|
|
|
|
|
{ 0xff, 0x00, 0xff, 0xff, 0x38, 0x0e, 0x22, 0x2a, 0x44, 0x3a, 0x4a, 0x3e, 0x16, 0x20, 0x36, 0x24, 0x46, 0x18, 0x1e, 0x12, 0x1c, 0x30, 0x2c, 0x14, 0x06, 0x0c, 0x40 },
|
|
|
|
|
{ 0x00, 0x00, 0xff, 0xff, 0x06, 0x4c, 0x26, 0x08, 0x46, 0x3e, 0x30, 0x12, 0x38, 0x1c, 0x04, 0x4a, 0x2c, 0x1a, 0x20, 0x3a, 0x18, 0x36, 0x28, 0x2e, 0x22, 0x40, 0x10 },
|
|
|
|
|
{ 0xff, 0xff, 0x00, 0xff, 0x12, 0x06, 0x3c, 0x2a, 0x22, 0x38, 0x48, 0x4c, 0x32, 0x44, 0x26, 0x16, 0x0c, 0x28, 0x2c, 0x36, 0x1c, 0x1a, 0x42, 0x10, 0x08, 0x4a, 0x34 },
|
|
|
|
|
{ 0x00, 0xff, 0x00, 0xff, 0x04, 0x4c, 0x4a, 0x28, 0x2a, 0x24, 0x14, 0x1e, 0x40, 0x48, 0x44, 0x2c, 0x2e, 0x1a, 0x12, 0x46, 0x3a, 0x0e, 0x18, 0x1c, 0x20, 0x10, 0x42 },
|
|
|
|
|
{ 0xff, 0x00, 0x00, 0xff, 0x06, 0x10, 0x14, 0x16, 0x48, 0x18, 0x44, 0x2c, 0x0a, 0x26, 0x24, 0x42, 0x36, 0x30, 0x38, 0x3e, 0x0c, 0x3c, 0x34, 0x46, 0x2a, 0x32, 0x0e },
|
|
|
|
|
{ 0x00, 0x00, 0x00, 0xff, 0x2c, 0x0a, 0x46, 0x28, 0x38, 0x24, 0x14, 0x06, 0x04, 0x10, 0x18, 0x30, 0x12, 0x20, 0x3a, 0x1a, 0x32, 0x3c, 0x3e, 0x4a, 0x1e, 0x44, 0x36 },
|
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x45, 0x23, 0x07, 0x37, 0x4b, 0x13, 0x3d, 0x31, 0x19, 0x2b, 0x2f, 0x2d, 0x1f, 0x4d, 0x3f, 0x1b, 0x43, 0x27, 0x3b, 0x11, 0x05, 0x0d, 0x17 },
|
|
|
|
|
{ 0xff, 0xff, 0xff, 0x00, 0x0b, 0x4b, 0x1d, 0x39, 0x09, 0x0f, 0x49, 0x25, 0x07, 0x35, 0x3b, 0x05, 0x33, 0x17, 0x2d, 0x11, 0x2b, 0x29, 0x1f, 0x45, 0x1b, 0x41, 0x47 },
|
|
|
|
|
{ 0x00, 0xff, 0xff, 0x00, 0x41, 0x35, 0x11, 0x25, 0x29, 0x27, 0x33, 0x47, 0x4d, 0x31, 0x05, 0x37, 0x15, 0x1f, 0x23, 0x07, 0x1b, 0x0f, 0x3b, 0x49, 0x19, 0x3f, 0x0b },
|
|
|
|
|
{ 0xff, 0x00, 0xff, 0x00, 0x25, 0x47, 0x05, 0x0b, 0x45, 0x1f, 0x2b, 0x27, 0x2d, 0x09, 0x07, 0x43, 0x49, 0x29, 0x4d, 0x39, 0x33, 0x41, 0x17, 0x0f, 0x15, 0x19, 0x3b },
|
|
|
|
|
{ 0x00, 0x00, 0xff, 0x00, 0x3b, 0x05, 0x21, 0x0d, 0x1b, 0x43, 0x17, 0x2d, 0x1d, 0x25, 0x4b, 0x35, 0x4d, 0x3f, 0x07, 0x09, 0x37, 0x41, 0x15, 0x1f, 0x0f, 0x27, 0x29 },
|
|
|
|
|
{ 0xff, 0xff, 0x00, 0x00, 0x2b, 0x35, 0x1b, 0x1d, 0x0f, 0x47, 0x09, 0x0d, 0x45, 0x41, 0x21, 0x11, 0x2f, 0x43, 0x27, 0x33, 0x4b, 0x37, 0x13, 0x19, 0x4d, 0x23, 0x17 },
|
|
|
|
|
{ 0x00, 0xff, 0x00, 0x00, 0x1b, 0x1d, 0x33, 0x13, 0x2b, 0x27, 0x09, 0x41, 0x25, 0x17, 0x19, 0x2d, 0x4b, 0x37, 0x45, 0x11, 0x21, 0x0d, 0x3d, 0x4d, 0x07, 0x39, 0x43 },
|
|
|
|
|
{ 0xff, 0x00, 0x00, 0x00, 0x37, 0x27, 0x43, 0x4b, 0x39, 0x13, 0x07, 0x0d, 0x25, 0x17, 0x29, 0x1b, 0x1d, 0x45, 0x19, 0x2d, 0x0b, 0x3d, 0x15, 0x47, 0x1f, 0x21, 0x4d } };
|
|
|
|
|
|
|
|
|
|
void DSM_init()
|
|
|
|
|
{
|
|
|
|
|
CYRF_GetMfgData(cyrfmfg_id);
|
|
|
|
|
//Model match
|
|
|
|
|
cyrfmfg_id[3]^=RX_num;
|
|
|
|
|
if(sub_protocol == DSMR)
|
|
|
|
|
{
|
|
|
|
|
uint8_t row = rx_tx_addr[3]%22;
|
|
|
|
|
for(uint8_t i=0; i< 4; i++)
|
|
|
|
|
cyrfmfg_id[i] = pgm_read_byte_near(&DSMR_ID_FREQ[row][i]);
|
|
|
|
|
for(uint8_t i=0; i< 23; i++)
|
|
|
|
|
hopping_frequency[i] = pgm_read_byte_near(&DSMR_ID_FREQ[row][i+4]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CYRF_GetMfgData(cyrfmfg_id);
|
|
|
|
|
//Model match
|
|
|
|
|
cyrfmfg_id[3]^=RX_num;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Calc sop_col
|
|
|
|
|
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
|
|
|
|
|
|
|
|
|
|
//Fix for OrangeRX using wrong DSM_pncodes by preventing access to "Col 8"
|
|
|
|
|
if(sop_col==0)
|
|
|
|
|
if(sop_col==0 && sub_protocol != DSMR)
|
|
|
|
|
{
|
|
|
|
|
cyrfmfg_id[rx_tx_addr[0]%3]^=0x01; //Change a bit so sop_col will be different from 0
|
|
|
|
|
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Calc CRC seed
|
|
|
|
|
seed = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
|
|
|
|
|
|
|
|
|
|
//Hopping frequencies
|
|
|
|
|
if (sub_protocol == DSMX_2F || sub_protocol == DSMX_1F)
|
|
|
|
|
DSM_calc_dsmx_channel();
|
|
|
|
|
else
|
|
|
|
|
else if(sub_protocol != DSMR)
|
|
|
|
|
{
|
|
|
|
|
uint8_t tmpch[10];
|
|
|
|
|
CYRF_FindBestChannels(tmpch, 10, 5, 3, 75);
|
|
|
|
|
@@ -482,6 +552,7 @@ void DSM_init()
|
|
|
|
|
}
|
|
|
|
|
hopping_frequency[1] = tmpch[idx];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
DSM_cyrf_config();
|
|
|
|
|
CYRF_SetTxRxMode(TX_EN);
|
|
|
|
|
|