319 lines
8.4 KiB
Arduino
Raw Normal View History

#if defined(FRSKYR9_SX1276_INO)
#include "iface_sx1276.h"
2020-07-06 09:52:43 +02:00
#define DISP_FREQ_TABLE
2020-07-06 09:52:43 +02:00
#define FLEX_FREQ 29
#define FCC_FREQ 43
#define EU_FREQ 19
2020-07-03 19:51:11 +02:00
enum {
FRSKYR9_FREQ=0,
FRSKYR9_DATA,
FRSKYR9_RX1,
FRSKYR9_RX2,
};
2020-07-06 09:52:43 +02:00
void FrSkyR9_set_frequency()
{
2020-07-06 09:52:43 +02:00
uint8_t data[3];
uint16_t num=0;
hopping_frequency_no += FrSkyX_chanskip;
switch(sub_protocol & 0xFD)
2020-07-01 14:39:11 +02:00
{
2020-07-06 09:52:43 +02:00
case R9_868:
if(IS_BIND_DONE) // if bind is in progress use R9_915 instead
{
hopping_frequency_no %= FLEX_FREQ;
num=hopping_frequency_no;
if(hopping_frequency_no>=FLEX_FREQ-2)
num+=FrSkyX_chanskip-FLEX_FREQ+2; // the last 2 values are FrSkyX_chanskip and FrSkyX_chanskip+1
num <<= 5;
num += 0xD700;
break;
}//else use R9_915
case R9_915:
hopping_frequency_no %= FLEX_FREQ;
num=hopping_frequency_no;
if(hopping_frequency_no>=FLEX_FREQ-2)
num+=FrSkyX_chanskip-FLEX_FREQ+2; // the last 2 values are FrSkyX_chanskip and FrSkyX_chanskip+1
num <<= 5;
num += 0xE4C0;
break;
case R9_FCC:
hopping_frequency_no %= FCC_FREQ;
num=hopping_frequency_no;
num <<= 5;
num += 0xE200;
break;
case R9_EU:
hopping_frequency_no %= EU_FREQ;
num=hopping_frequency_no;
num <<= 4;
num += 0xD7D0;
break;
2020-07-01 14:39:11 +02:00
}
2020-07-06 09:52:43 +02:00
data[0] = num>>8;
data[1] = num&0xFF;
data[2] = 0x00;
#ifdef DISP_FREQ_TABLE
if(phase==0xFF)
debugln("F%d=%02X%02X%02X=%lu", hopping_frequency_no, data[0], data[1], data[2], (uint32_t)((data[0]<<16)+(data[1]<<8)+data[2])*61);
#endif
SX1276_WriteRegisterMulti(SX1276_06_FRFMSB, data, 3);
2020-07-01 14:39:11 +02:00
}
2020-06-06 01:57:52 +02:00
2020-07-01 14:39:11 +02:00
static void __attribute__((unused)) FrSkyR9_build_packet()
{
2020-06-06 01:57:52 +02:00
//ID
2020-07-01 14:39:11 +02:00
packet[0] = rx_tx_addr[1];
packet[1] = rx_tx_addr[2];
packet[2] = rx_tx_addr[3];
2020-06-06 01:57:52 +02:00
//Hopping
packet[3] = hopping_frequency_no; // current channel index
packet[4] = FrSkyX_chanskip; // step size and last 2 channels start index
2020-06-06 01:57:52 +02:00
//RX number
packet[5] = RX_num; // receiver number from OpenTX
2020-07-04 22:43:19 +02:00
//Channels
FrSkyX_channels(6); // Set packet[6]=failsafe, packet[7]=0?? and packet[8..19]=channels data
2020-06-06 01:57:52 +02:00
//Bind
if(IS_BIND_IN_PROGRESS)
{// 915 0x01=CH1-8_TELEM_ON 0x41=CH1-8_TELEM_OFF 0xC1=CH9-16_TELEM_OFF 0x81=CH9-16_TELEM_ON
packet[6] = 0x01; // bind indicator
2020-07-01 14:39:11 +02:00
if(sub_protocol & 1)
packet[6] |= 0x20; // 868
if(binding_idx&0x01)
packet[6] |= 0x40; // telem OFF
if(binding_idx&0x02)
packet[6] |= 0x80; // ch9-16
2020-07-01 14:39:11 +02:00
}
2020-06-06 01:57:52 +02:00
2020-07-04 22:43:19 +02:00
//Sequence and send SPort
FrSkyX_seq_sport(20,23); //20=RX|TXseq, 21=bytes count, 22&23=data
2020-06-06 01:57:52 +02:00
//CRC
uint16_t crc = FrSkyX_crc(packet, 24);
packet[24] = crc; // low byte
packet[25] = crc >> 8; // high byte
}
2020-07-28 00:55:47 +02:00
static uint8_t __attribute__((unused)) FrSkyR9_CRC8(uint8_t *p, uint8_t l)
{
uint8_t crc = 0xFF;
for (uint8_t i = 0; i < l; i++)
{
crc = crc ^ p[i];
for ( uint8_t j = 0; j < 8; j++ )
if ( crc & 0x80 )
{
crc <<= 1;
crc ^= 0x07;
}
else
crc <<= 1;
}
return crc;
}
static void __attribute__((unused)) FrSkyR9_build_EU_packet()
{
//ID
packet[0] = rx_tx_addr[1];
packet[1] = rx_tx_addr[2];
packet[2] = rx_tx_addr[3];
//Hopping
packet[3] = FrSkyX_chanskip; // step size and last 2 channels start index
//RX number
packet[4] = RX_num; // receiver number from OpenTX
//Channels
//TODO FrSkyX_channels(5,4); // Set packet[5]=failsafe and packet[6..11]=4 channels data
//Bind
if(IS_BIND_IN_PROGRESS)
{
packet[5] = 0x01; // bind indicator
if((sub_protocol & 2) == 0)
packet[5] |= 0x10; // 16CH
// if(sub_protocol & 1)
// packet[5] |= 0x20; // 868
if(binding_idx&0x01)
packet[5] |= 0x40; // telem OFF
if(binding_idx&0x02)
packet[5] |= 0x80; // ch9-16
}
//Sequence and send SPort
packet[12] = (FrSkyX_RX_Seq << 4)|0x08; //TX=8 at startup
//CRC
packet[13] = FrSkyR9_CRC8(packet, 13);
}
2021-02-09 18:23:33 +01:00
void FRSKYR9_init()
{
2020-07-06 09:52:43 +02:00
//Check frequencies
#ifdef DISP_FREQ_TABLE
phase=0xFF;
FrSkyX_chanskip=1;
hopping_frequency_no=0xFF;
for(uint8_t i=0;i<FCC_FREQ;i++)
FrSkyR9_set_frequency();
#endif
//Reset ID
set_rx_tx_addr(MProtocol_id_master);
//FrSkyX_chanskip
FrSkyX_chanskip = 1 + (random(0xfefefefe) % 24);
2020-07-06 09:52:43 +02:00
debugln("chanskip=%d", FrSkyX_chanskip);
2020-07-01 14:39:11 +02:00
2020-06-06 01:57:52 +02:00
//Set FrSkyFormat
if((sub_protocol & 0x02) == 0)
2020-07-06 09:52:43 +02:00
FrSkyFormat=0; // 16 channels
2020-06-06 01:57:52 +02:00
else
2020-07-06 09:52:43 +02:00
FrSkyFormat=1; // 8 channels
2020-06-06 01:57:52 +02:00
debugln("%dCH", FrSkyFormat&1 ? 8:16);
2020-07-28 00:55:47 +02:00
//EU packet length
if( (sub_protocol & 0xFD) == R9_EU )
packet_length=14;
else
packet_length=26;
2020-06-06 01:57:52 +02:00
//SX1276 Init
SX1276_SetMode(true, false, SX1276_OPMODE_SLEEP);
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
// uint8_t buffer[2];
// buffer[0] = 0x00;
// buffer[1] = 0x00;
// SX1276_WriteRegisterMulti(SX1276_40_DIOMAPPING1, buffer, 2);
SX1276_SetDetectOptimize(true, SX1276_DETECT_OPTIMIZE_SF6);
SX1276_ConfigModem1(SX1276_MODEM_CONFIG1_BW_500KHZ, SX1276_MODEM_CONFIG1_CODING_RATE_4_5, true);
SX1276_ConfigModem2(6, false, false);
SX1276_ConfigModem3(false, false);
SX1276_SetPreambleLength(9);
SX1276_SetDetectionThreshold(SX1276_MODEM_DETECTION_THRESHOLD_SF6);
SX1276_SetLna(1, true);
2020-07-06 09:52:43 +02:00
SX1276_SetHopPeriod(0); // 0 = disabled, we hop frequencies manually
//RF Power
SX1276_SetPaDac(false); // Disable 20dBm mode
#if MULTI_5IN1_INTERNAL == JP_T18
SX1276_SetPaConfig(true, 7, 0); // Lowest power for the T18: 2dBm
#else
SX1276_SetPaConfig(true, 7, option); // Use PA_HP on PA_BOOST, power=17-(15-option) dBm with option equal or lower to 15
#endif
SX1276_SetOcp(true,27); // Set OCP to max 240mA
2020-07-06 09:52:43 +02:00
SX1276_SetTxRxMode(TX_EN); // Set RF switch to TX
2020-08-13 21:21:34 +02:00
//Enable all IRQ flags
SX1276_WriteReg(SX1276_11_IRQFLAGSMASK,0x00);
FrSkyX_telem_init();
2020-07-03 19:51:11 +02:00
2020-07-06 09:52:43 +02:00
hopping_frequency_no=0;
2020-07-03 19:51:11 +02:00
phase=FRSKYR9_FREQ;
}
2021-02-09 18:23:33 +01:00
uint16_t FRSKYR9_callback()
{
2020-07-03 19:51:11 +02:00
switch (phase)
{
case FRSKYR9_FREQ:
//Force standby
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
//Set frequency
2020-07-06 09:52:43 +02:00
FrSkyR9_set_frequency(); // Set current center frequency
2020-07-03 19:51:11 +02:00
//Set power
// max power: 15dBm (10.8 + 0.6 * MaxPower [dBm])
// output_power: 2 dBm ( (if pa_boost_pin == true))
#if MULTI_5IN1_INTERNAL != JP_T18
if(option != prev_option)
{ // Set RF power if it has changed
SX1276_SetPaConfig(true, 7, option); // Use PA_HP on PA_BOOST, power=17-(15-option) dBm with option equal or lower to 15
prev_option = option;
}
#endif
2020-07-03 19:51:11 +02:00
//Build packet
2020-07-28 00:55:47 +02:00
if( packet_length == 26 )
FrSkyR9_build_packet();
else
FrSkyR9_build_EU_packet();
2020-07-03 19:51:11 +02:00
phase++;
2020-07-06 09:52:43 +02:00
return 460; // Frequency settle time
2020-07-03 19:51:11 +02:00
case FRSKYR9_DATA:
//Set RF switch to TX
SX1276_SetTxRxMode(TX_EN);
//Send packet
2020-07-28 00:55:47 +02:00
SX1276_WritePayloadToFifo(packet, packet_length);
2020-07-03 19:51:11 +02:00
SX1276_SetMode(true, false, SX1276_OPMODE_TX);
#if not defined TELEMETRY
phase=FRSKYR9_FREQ;
return 20000-460;
#else
phase++;
2020-07-06 09:52:43 +02:00
return 11140; // Packet send time
2020-07-03 19:51:11 +02:00
case FRSKYR9_RX1:
//Force standby
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
//RX packet size is 13
SX1276_WriteReg(SX1276_22_PAYLOAD_LENGTH, 13);
//Reset pointer
SX1276_WriteReg(SX1276_0D_FIFOADDRPTR, 0x00);
//Set RF switch to RX
SX1276_SetTxRxMode(RX_EN);
2020-08-13 21:21:34 +02:00
//Clear all IRQ flags
SX1276_WriteReg(SX1276_12_REGIRQFLAGS,0xFF);
2020-07-03 19:51:11 +02:00
//Switch to RX
SX1276_WriteReg(SX1276_01_OPMODE, 0x85);
phase++;
return 7400;
case FRSKYR9_RX2:
if( (SX1276_ReadReg(SX1276_12_REGIRQFLAGS)&0xF0) == (_BV(SX1276_REGIRQFLAGS_RXDONE) | _BV(SX1276_REGIRQFLAGS_VALIDHEADER)) )
{
if(SX1276_ReadReg(SX1276_13_REGRXNBBYTES)==13)
{
SX1276_ReadRegisterMulti(SX1276_00_FIFO,packet_in,13);
if( packet_in[9]==rx_tx_addr[1] && packet_in[10]==rx_tx_addr[2] && FrSkyX_crc(packet_in, 11, rx_tx_addr[1]+(rx_tx_addr[2]<<8))==(packet_in[11]+(packet_in[12]<<8)) )
{
if(packet_in[0]&0x80)
RX_RSSI=packet_in[0]<<1;
else
v_lipo1=(packet_in[0]<<1)+1;
//TX_LQI=~(SX1276_ReadReg(SX1276_19_PACKETSNR)>>2)+1;
2020-07-03 19:51:11 +02:00
TX_RSSI=SX1276_ReadReg(SX1276_1A_PACKETRSSI)-157;
for(uint8_t i=0;i<9;i++)
2020-07-06 09:52:43 +02:00
packet[4+i]=packet_in[i]; // Adjust buffer to match FrSkyX
2020-07-04 22:43:19 +02:00
frsky_process_telemetry(packet,len); // Process telemetry packet
pps_counter++;
if(TX_LQI==0)
2020-07-06 09:52:43 +02:00
TX_LQI++; // Recover telemetry right away
2020-07-03 19:51:11 +02:00
}
}
}
if (millis() - pps_timer >= 1000)
2020-07-04 22:43:19 +02:00
{//1 packet every 20ms
pps_timer = millis();
debugln("%d pps", pps_counter);
2020-07-06 09:52:43 +02:00
TX_LQI = pps_counter<<1; // Max=100%
pps_counter = 0;
2020-07-03 19:51:11 +02:00
}
if(TX_LQI==0)
2020-07-06 09:52:43 +02:00
FrSkyX_telem_init(); // Reset telemetry
else
2020-07-06 09:52:43 +02:00
telemetry_link=1; // Send telemetry out anyway
2020-07-03 19:51:11 +02:00
phase=FRSKYR9_FREQ;
break;
#endif
}
return 1000;
}
#endif