292 lines
8.2 KiB
Arduino
Raw Permalink Normal View History

/*
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/>.
*/
2017-11-20 16:01:12 +01:00
#if defined(FRSKYX_CC2500_INO)
#include "iface_cc2500.h"
static void __attribute__((unused)) FrSkyX_build_bind_packet()
2017-11-20 16:01:12 +01:00
{
//Header
2021-04-06 10:18:48 +02:00
packet[0] = packet_length; // Number of bytes in the packet (after this one)
packet[1] = 0x03; // Bind packet
packet[2] = 0x01; // Bind packet
//ID
2021-04-06 10:18:48 +02:00
packet[3] = rx_tx_addr[3]; // ID
packet[4] = rx_tx_addr[2]; // ID
if(protocol==PROTO_FRSKYX)
{
int idx = ((state -FRSKY_BIND) % 10) * 5;
packet[5] = idx;
packet[6] = hopping_frequency[idx++];
packet[7] = hopping_frequency[idx++];
packet[8] = hopping_frequency[idx++];
packet[9] = hopping_frequency[idx++];
packet[10] = hopping_frequency[idx++];
2021-04-06 10:18:48 +02:00
packet[11] = rx_tx_addr[1]; // ID
packet[12] = RX_num;
//
2021-03-25 10:10:53 +01:00
memset(&packet[13], 0, packet_length - 14);
if(binding_idx&0x01)
memcpy(&packet[13],(void *)"\x55\xAA\x5A\xA5",4); // Telem off
if(binding_idx&0x02)
memcpy(&packet[17],(void *)"\x55\xAA\x5A\xA5",4); // CH9-16
}
else
{
//packet 1D 03 01 0E 1C 02 00 00 32 0B 00 00 A8 26 28 01 A1 00 00 00 3E F6 87 C7 00 00 00 00 C9 C9
2021-04-06 10:18:48 +02:00
//Unknown bytes
if(state & 0x01)
2023-08-26 00:04:36 +02:00
memcpy(&packet[7],"\x00\xCC\x00\x00\x00\x70\x14\x15\x00\xD3\x08\x00\x00\xCE\xE2\x85\xC7\x00\x00\x00\x00",21);
2021-04-06 10:18:48 +02:00
else
2023-08-26 00:04:36 +02:00
memcpy(&packet[7],"\x27\xFB\x00\x00\x00\xBC\xEF\x19\x00\x26\x07\x00\x00\xB7\xED\x85\xC7\xA7\xA7\xA7\xA7",21);
2021-04-06 10:18:48 +02:00
//ID
packet[5] = rx_tx_addr[1]; // ID
packet[6] = RX_num;
//Bind flags
if(binding_idx&0x01)
packet[7] |= 0x40; // Telem off
if(binding_idx&0x02)
packet[7] |= 0x80; // CH9-16
2021-04-06 10:18:48 +02:00
//Replace the ID
2023-08-26 00:04:36 +02:00
packet[20] ^= rx_tx_addr[3]; // Update the ID
packet[21] ^= rx_tx_addr[2]; // Update the ID
packet[22] ^= rx_tx_addr[1] & 0x3F; // Update the ID
//Xor
2021-03-25 10:10:53 +01:00
for(uint8_t i=3; i<packet_length-1; i++)
packet[i] ^= 0xA7;
}
//CRC
2021-03-25 10:10:53 +01:00
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_length-4);
packet[packet_length-1] = lcrc >> 8;
packet[packet_length] = lcrc;
/*//Debug
debug("Bind:");
2021-03-25 10:10:53 +01:00
for(uint8_t i=0;i<=packet_length;i++)
debug(" %02X",packet[i]);
debugln("");*/
2017-11-20 16:01:12 +01:00
}
static void __attribute__((unused)) FrSkyX_build_packet()
2017-11-20 16:01:12 +01:00
{
//0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12
2017-12-10 09:48:20 +01:00
// data frames sent every 9ms; failsafe every 9 seconds
2020-05-23 22:39:26 +02:00
//
//Header
2021-03-25 10:10:53 +01:00
packet[0] = packet_length; // Number of bytes in the packet (after this one)
packet[1] = rx_tx_addr[3]; // ID
packet[2] = rx_tx_addr[2]; // ID
packet[3] = rx_tx_addr[1]; // Unknown but constant ID?
2017-11-20 16:01:12 +01:00
//
packet[4] = (FrSkyX_chanskip<<6)|hopping_frequency_no;
packet[5] = FrSkyX_chanskip>>2;
2017-11-20 16:01:12 +01:00
packet[6] = RX_num;
2020-05-23 22:39:26 +02:00
2020-07-04 22:43:19 +02:00
//Channels
2020-06-05 22:22:13 +02:00
FrSkyX_channels(7); // Set packet[7]=failsafe, packet[8]=0?? and packet[9..20]=channels data
2017-11-20 16:01:12 +01:00
2020-07-04 22:43:19 +02:00
//Sequence and send SPort
2023-08-12 13:17:06 +02:00
FrSkyX_seq_sport(21,packet_length-((protocol==PROTO_FRSKYX && (FrSkyFormat & 2 )) ? 4 : 2)); //21=RX|TXseq, 22=bytes count, 23..packet_length-2=data
//CRC
2021-03-25 10:10:53 +01:00
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_length-4);
packet[packet_length-1] = lcrc >> 8;
packet[packet_length] = lcrc;
/*//Debug
debug("Norm:");
2021-03-25 10:10:53 +01:00
for(uint8_t i=0;i<=packet_length;i++)
debug(" %02X",packet[i]);
debugln("");*/
2017-11-20 16:01:12 +01:00
}
2021-02-09 18:23:33 +01:00
uint16_t FRSKYX_callback()
2017-11-20 16:01:12 +01:00
{
2022-12-08 08:28:45 +01:00
#if defined MULTI_EU
if(sub_protocol == CH_16 || sub_protocol == CH_8)
return 9000;
#endif
2017-11-20 16:01:12 +01:00
switch(state)
{
default:
FrSkyX_set_start(47);
2017-11-20 16:01:12 +01:00
CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX);
//
FrSkyX_build_bind_packet();
2017-11-20 16:01:12 +01:00
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteData(packet, packet[0]+1);
if(IS_BIND_DONE)
2017-11-20 16:01:12 +01:00
state = FRSKY_BIND_DONE;
else
state++;
2021-03-25 10:10:53 +01:00
break;
2017-11-20 16:01:12 +01:00
case FRSKY_BIND_DONE:
FrSkyX_initialize_data(0);
2017-11-20 16:01:12 +01:00
hopping_frequency_no=0;
BIND_DONE;
2020-07-05 17:19:29 +02:00
state++; //FRSKY_DATA1
2019-10-31 23:33:10 +01:00
break;
case FRSKY_DATA1:
CC2500_Strobe(CC2500_SIDLE);
2021-01-25 11:33:30 +01:00
CC2500_SetFreqOffset();
FrSkyX_set_start(hopping_frequency_no);
FrSkyX_build_packet();
if(FrSkyFormat & 2)
{// LBT
2020-07-05 17:19:29 +02:00
CC2500_Strobe(CC2500_SRX); //Acquire RSSI
state++;
return 400; // LBT
}
case FRSKY_DATA2:
if(FrSkyFormat & 2)
{
uint16_t rssi=0;
for(uint8_t i=0;i<4;i++)
rssi += CC2500_ReadReg(CC2500_34_RSSI | CC2500_READ_BURST); // 0.5 db/count, RSSI value read from the RSSI status register is a 2's complement number
rssi>>=2;
#if 0
2020-07-05 17:19:29 +02:00
uint8_t rssi_level=convert_channel_8b(CH16)>>1; //CH16 0..127
if ( rssi > rssi_level && rssi < 128) //test rssi level dynamically
#else
2020-07-05 17:19:29 +02:00
if ( rssi > 14 && rssi < 128) //if RSSI above -65dBm (12=-70) => ETSI requirement
#endif
{
2020-07-05 17:19:29 +02:00
LBT_POWER_on; //Reduce to low power before transmitting
debugln("Busy %d %d",hopping_frequency_no,rssi);
}
}
CC2500_Strobe(CC2500_SIDLE);
2020-07-05 17:19:29 +02:00
CC2500_Strobe(CC2500_SFTX); //Flush the TXFIFO
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
hopping_frequency_no = (hopping_frequency_no+FrSkyX_chanskip)%47;
CC2500_WriteData(packet, packet[0]+1);
state=FRSKY_DATA3;
if(FrSkyFormat & 2)
return 4000; // LBT
else
return 5200; // FCC
case FRSKY_DATA3:
CC2500_Strobe(CC2500_SIDLE);
2020-07-05 17:19:29 +02:00
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SRX);
state++;
if(FrSkyFormat & 2)
return 4200; // LBT
else
return 3400; // FCC
case FRSKY_DATA4:
2019-11-11 19:15:39 +01:00
#ifdef MULTI_SYNC
telemetry_set_input_sync(9000);
#endif
2019-11-01 18:42:45 +01:00
#if defined TELEMETRY
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && len <= 17) //Telemetry frame is 17 bytes
{
//debug("Telem:");
CC2500_ReadData(packet_in, len); //Read what has been received so far
if(len<17)
{//not all bytes were received
uint8_t last_len=CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if(last_len==17) //All bytes received
{
CC2500_ReadData(packet_in+len, last_len-len); //Finish to read
len=17;
}
2020-07-04 15:15:55 +02:00
}
2020-07-04 22:43:19 +02:00
if(len==17 && (protocol==PROTO_FRSKYX || (protocol==PROTO_FRSKYX2 && (packet_in[len-1] & 0x80))) )
{//Telemetry received with valid crc for FRSKYX2
//Debug
//for(uint8_t i=0;i<len;i++)
// debug(" %02X",packet_in[i]);
if(frsky_process_telemetry(packet_in,len)) //Check and process telemetry packet
{//good packet received
pps_counter++;
if(TX_LQI==0)
TX_LQI++; //Recover telemetry right away
}
2020-07-04 22:43:19 +02:00
}
//debugln("");
}
2020-07-04 22:43:19 +02:00
if (millis() - pps_timer >= 900)
{//1 packet every 9ms
pps_timer = millis();
debugln("%d pps", pps_counter);
TX_LQI = pps_counter; //Max=100%
pps_counter = 0;
2019-10-27 16:44:36 +01:00
}
2020-07-04 22:43:19 +02:00
if(TX_LQI==0)
FrSkyX_telem_init(); //Reset telemetry
else
telemetry_link=1; //Send telemetry out anyway
#endif
2019-10-27 16:44:36 +01:00
state = FRSKY_DATA1;
return 400; // FCC & LBT
}
2021-03-25 10:10:53 +01:00
return 9000;
2017-11-20 16:01:12 +01:00
}
2021-02-09 18:23:33 +01:00
void FRSKYX_init()
2017-11-20 16:01:12 +01:00
{
set_rx_tx_addr(MProtocol_id_master);
FrSkyFormat = sub_protocol;
2020-07-21 01:40:14 +02:00
if (sub_protocol==XCLONE_16||sub_protocol==XCLONE_8)
Frsky_init_clone();
else
{
2021-03-25 10:10:53 +01:00
if(protocol==PROTO_FRSKYX)
Frsky_init_hop();
else
{
#ifdef FRSKYX2_FORCE_ID
rx_tx_addr[3]=0x0E;
rx_tx_addr[2]=0x1C;
FrSkyX_chanskip=18;
#endif
FrSkyX2_init_hop();
}
2021-03-30 15:13:00 +02:00
rx_tx_addr[1]=0x02; // ID related, hw version?
}
2021-03-25 10:10:53 +01:00
if(protocol==PROTO_FRSKYX && (FrSkyFormat & 2 ))
packet_length = 0x20; // FrSkyX V1 LBT
else
packet_length = 0x1D;
2017-11-20 16:01:12 +01:00
packet_count=0;
while(!FrSkyX_chanskip)
FrSkyX_chanskip=random(0xfefefefe)%47;
2017-11-20 16:01:12 +01:00
2021-02-09 18:23:33 +01:00
FrSkyX_RF_init();
if(IS_BIND_IN_PROGRESS)
2017-11-20 16:01:12 +01:00
{
2021-04-06 10:18:48 +02:00
memset(packet, 0, packet_length);
2017-11-20 16:01:12 +01:00
state = FRSKY_BIND;
FrSkyX_initialize_data(1);
2017-11-20 16:01:12 +01:00
}
else
2021-03-30 15:13:00 +02:00
state = FRSKY_BIND_DONE;
FrSkyX_telem_init();
}
#endif