Skip to content

Commit

Permalink
Gemini Xrossband (GemX) - LR1121 Driver (ExpressLRS#2540)
Browse files Browse the repository at this point in the history
* lr1121

Still needs SF6 compatibility with the SX127x to be fixed.

ESP32 crashes on HWtimer resume.

* add tx target

* correct FREQ_SPREAD_SCALE

* working 900 state

still an issue with serial crashing

* Make SPI go brrrrrr

added ExpressLRS#2339

* working as a single lr1121 and 900+2G4 combined

* GetAndClearIrqStatus clean up

* Gemini tx

All lora modes working on the tx.  Rx still needs checking.

* add generic USE_HARDWARE_DCDC plus clean up

* fix CS from interrupting a busy SPI

* working rx

* fix GetLastPacketStats for diversity and optimise SPI

* make fuzzy_snr() faster... thanks Sunjun 💪

The current method with exp() would take 85us in the middle of the ISR.

* increase PACKET_TO_TOCK_SLACK so the ISR fits for 500Hz

* fix fuzzy_snr

ExpressLRS#2379

* add basic power control and change radio_rfo_hf to be more generic

changes radio_rfo_hf to radio_rfo_lp (lp = low power)

* add missing ClearIrqStatus

* Add ability to configure LR1121 targets

* fix for txen and setting 2.4 output for testing

* adds new power array power_values_dual for dual band systems

... works for the lr1121, but probably broke everything else :|

* Fix error in unified configurator

* Only call extra power setting on LR1121

* power clean up

LR1121 default mode is min power and low freq rf amp

* more power clean up

* adds  multi rx logging - DELETE ME LATER

* mods RF modes for testing - DELETE ME LATER

* adds multi rx logging cleanup - DELETE ME LATER

* Revert "mods RF modes for testing - DELETE ME LATER"

This reverts commit 18cd13e.

* add new DB mode

* fix ExpressLRS_AirRateConfig for sx1280

* post DB cleanup and comments

* fix FHSSrandomiseFHSSsequenceBuild()

* fix DEBUG_LOG_MULTI_RX define

* fix AsyncTCP

ExpressLRS#2511

* add check to dualband to use the fhss seq cnt with the lowest value

* adds ALL THE MODES!

* test code cleanup

* cleanup old SetDioAsRfSwitch

* revert janky display menu ordering...

Tested and not required as the list is circular

* wrap PACKET_TO_TOCK_SLACK in a define

* handle negative power values correctly

* simplify output power code at the expense of a little efficiency

* correct POWER_OUTPUT_VALUES_DUAL use

* add missing ClearIrqStatus

* revert USE_RADIO_RFO_HF change

* revert more USE_RADIO_RFO_HF changes

* fix missing FHSSgetInitialFreq()

---------

Co-authored-by: Jye <[email protected]>
Co-authored-by: Paul Kendall <[email protected]>
  • Loading branch information
3 people authored Feb 20, 2024
1 parent f701140 commit b4ad5ce
Show file tree
Hide file tree
Showing 35 changed files with 1,799 additions and 100 deletions.
1 change: 1 addition & 0 deletions src/html/hardware.html
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ <h1><b>ExpressLRS</b></h1>
</td><td>How the power level is set</td></tr>
<tr><td></td><td>Power Value(s)</td><td><input size='40' id='power_values' name='power_values' type='text' class='array'/></td><td>Comma-separated list of values that set the power output (if using a DAC these are the DAC values)</td></tr>
<tr><td></td><td>Secondary Power Value(s)</td><td><input size='40' id='power_values2' name='power_values2' type='text' class='array'/></td><td>Comma-separated list of values that set the power output (if using a DAC then these set the Semtech power output)</td></tr>
<tr><td></td><td>Dual Power Value(s)</td><td><input size='40' id='power_values_dual' name='power_values_dual' type='text' class='array'/></td><td>Comma-separated list of values that set the higher frequency power output of a dual band Tx/Rx</td></tr>

<tr><td colspan='2'><b>Radio Power Detection</td></tr>
<tr><td></td><td>PDET pin<img class="icon-analog"/></td><td><input size='3' id='power_pdet' name='power_pdet' type='text'/></td><td>Analog input (up to 1.1V) connected to 'power detect' pin on PA for adjustment of the power output</td></tr>
Expand Down
22 changes: 20 additions & 2 deletions src/include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#if defined(RADIO_SX127X)
#include "SX127xDriver.h"
#elif defined(RADIO_LR1121)
#include "LR1121Driver.h"
#elif defined(RADIO_SX128X)
#include "SX1280Driver.h"
#else
Expand Down Expand Up @@ -91,10 +93,14 @@ typedef enum : uint8_t
RATE_FLRC_500HZ,
RATE_FLRC_1000HZ,
RATE_DVDA_50HZ,
} expresslrs_RFrates_e; // Max value of 16 since only 4 bits have been assigned in the sync package.
RATE_LORA_200HZ_8CH,
} expresslrs_RFrates_e;

enum {
RADIO_TYPE_SX127x_LORA,
RADIO_TYPE_LR1121_LORA_900,
RADIO_TYPE_LR1121_LORA_2G4,
RADIO_TYPE_LR1121_LORA_DUAL,
RADIO_TYPE_SX128x_LORA,
RADIO_TYPE_SX128x_FLRC,
};
Expand Down Expand Up @@ -138,10 +144,16 @@ typedef struct expresslrs_mod_settings_s
uint8_t bw;
uint8_t sf;
uint8_t cr;
uint8_t PreambleLen;
#if defined(RADIO_LR1121)
uint8_t bw2;
uint8_t sf2;
uint8_t cr2;
uint8_t PreambleLen2;
#endif
expresslrs_tlm_ratio_e TLMinterval; // every X packets is a response TLM packet, should be a power of 2
uint8_t FHSShopInterval; // every X packets we hop to a new frequency. Max value of 16 since only 4 bits have been assigned in the sync package.
int32_t interval; // interval in us seconds that corresponds to that frequency
uint8_t PreambleLen;
uint8_t PayloadLength; // Number of OTA bytes to be sent.
uint8_t numOfSends; // Number of packets to send.
} expresslrs_mod_settings_t;
Expand Down Expand Up @@ -231,6 +243,12 @@ enum eAuxChannels : uint8_t

extern SX127xDriver Radio;

#elif defined(RADIO_LR1121)
#define RATE_MAX 14
#define RATE_BINDING RATE_LORA_50HZ

extern LR1121Driver Radio;

#elif defined(RADIO_SX128X)
#define RATE_MAX 10 // 2xFLRC + 2xDVDA + 4xLoRa + 2xFullRes
#define RATE_BINDING RATE_LORA_50HZ
Expand Down
1 change: 1 addition & 0 deletions src/include/hardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ typedef enum {
HARDWARE_power_control,
HARDWARE_power_values,
HARDWARE_power_values2,
HARDWARE_power_values_dual,

// Input
HARDWARE_joystick,
Expand Down
2 changes: 1 addition & 1 deletion src/include/target/FM30_RX_MINI.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#endif
#endif

#define USE_SX1280_DCDC
#define USE_HARDWARE_DCDC

// GPIO pin definitions
#define GPIO_PIN_NSS PA15
Expand Down
5 changes: 3 additions & 2 deletions src/include/target/Unified_ESP32_TX.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
#define GPIO_PIN_RST hardware_pin(HARDWARE_radio_rst)
#define GPIO_PIN_RST_2 hardware_pin(HARDWARE_radio_rst_2)
#define GPIO_PIN_SCK hardware_pin(HARDWARE_radio_sck)
#define USE_SX1280_DCDC
#define OPT_USE_SX1280_DCDC hardware_flag(HARDWARE_radio_dcdc)
#define USE_HARDWARE_DCDC
#define OPT_USE_HARDWARE_DCDC hardware_flag(HARDWARE_radio_dcdc)
#define USE_SX1276_RFO_HF
#define OPT_USE_SX1276_RFO_HF hardware_flag(HARDWARE_radio_rfo_hf)

Expand Down Expand Up @@ -89,6 +89,7 @@
#define POWER_OUTPUT_FIXED -99
#define POWER_OUTPUT_VALUES hardware_i16_array(HARDWARE_power_values)
#define POWER_OUTPUT_VALUES2 hardware_i16_array(HARDWARE_power_values2)
#define POWER_OUTPUT_VALUES_DUAL hardware_i16_array(HARDWARE_power_values_dual)

// Input
#define HAS_FIVE_WAY_BUTTON
Expand Down
5 changes: 3 additions & 2 deletions src/include/target/Unified_ESP8285_TX.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#define GPIO_PIN_RST hardware_pin(HARDWARE_radio_rst)
#define GPIO_PIN_RST_2 hardware_pin(HARDWARE_radio_rst_2)
#define GPIO_PIN_SCK hardware_pin(HARDWARE_radio_sck)
#define USE_SX1280_DCDC
#define OPT_USE_SX1280_DCDC hardware_flag(HARDWARE_radio_dcdc)
#define USE_HARDWARE_DCDC
#define OPT_USE_HARDWARE_DCDC hardware_flag(HARDWARE_radio_dcdc)

// Radio power
#define GPIO_PIN_PA_ENABLE hardware_pin(HARDWARE_power_enable)
Expand All @@ -40,6 +40,7 @@
//#define POWER_OUTPUT_DACWRITE (hardware_int(HARDWARE_power_control)==3)
#define POWER_OUTPUT_FIXED -99
#define POWER_OUTPUT_VALUES hardware_i16_array(HARDWARE_power_values)
#define POWER_OUTPUT_VALUES_DUAL hardware_i16_array(HARDWARE_power_values_dual)

// Input
#define GPIO_PIN_BUTTON hardware_pin(HARDWARE_button)
Expand Down
5 changes: 3 additions & 2 deletions src/include/target/Unified_ESP_RX.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
#define GPIO_PIN_RST hardware_pin(HARDWARE_radio_rst)
#define GPIO_PIN_RST_2 hardware_pin(HARDWARE_radio_rst_2)
#define GPIO_PIN_SCK hardware_pin(HARDWARE_radio_sck)
#define USE_SX1280_DCDC
#define OPT_USE_SX1280_DCDC hardware_flag(HARDWARE_radio_dcdc)
#define USE_HARDWARE_DCDC
#define OPT_USE_HARDWARE_DCDC hardware_flag(HARDWARE_radio_dcdc)
#define USE_SX1276_RFO_HF
#define OPT_USE_SX1276_RFO_HF hardware_flag(HARDWARE_radio_rfo_hf)

Expand Down Expand Up @@ -88,6 +88,7 @@
#define POWER_OUTPUT_FIXED -99
#define POWER_OUTPUT_VALUES hardware_i16_array(HARDWARE_power_values)
#define POWER_OUTPUT_VALUES2 hardware_i16_array(HARDWARE_power_values2)
#define POWER_OUTPUT_VALUES_DUAL hardware_i16_array(HARDWARE_power_values_dual)

// Input
#define GPIO_PIN_BUTTON hardware_pin(HARDWARE_button)
Expand Down
4 changes: 2 additions & 2 deletions src/include/targets.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ extern bool pwmSerialDefined;
#undef Regulatory_Domain_US_433
#undef Regulatory_Domain_US_433_WIDE

#elif defined(RADIO_SX127X)
#elif defined(RADIO_SX127X) || defined(RADIO_LR1121)
#if !(defined(Regulatory_Domain_AU_915) || defined(Regulatory_Domain_FCC_915) || \
defined(Regulatory_Domain_EU_868) || defined(Regulatory_Domain_IN_866) || \
defined(Regulatory_Domain_AU_433) || defined(Regulatory_Domain_EU_433) || \
Expand All @@ -280,7 +280,7 @@ extern bool pwmSerialDefined;
#error "Regulatory_Domain is not defined for 900MHz device. Check user_defines.txt!"
#endif
#else
#error "Either RADIO_SX127X or RADIO_SX128X must be defined!"
#error "Either RADIO_SX127X, RADIO_LR1121 or RADIO_SX128X must be defined!"
#endif

#if defined(TARGET_UNIFIED_TX) || defined(TARGET_UNIFIED_RX)
Expand Down
4 changes: 2 additions & 2 deletions src/lib/CONFIG/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ template<class T> static const uint32_t Model_to_U32(T const * const model)

static uint8_t RateV6toV7(uint8_t rateV6)
{
#if defined(RADIO_SX127X)
#if defined(RADIO_SX127X) || defined(RADIO_LR1121)
if (rateV6 == 0)
{
// 200Hz stays same
Expand Down Expand Up @@ -638,7 +638,7 @@ TxConfig::SetDefaults(bool commit)
for (unsigned i=0; i<CONFIG_TX_MODEL_CNT; i++)
{
SetModelId(i);
#if defined(RADIO_SX127X)
#if defined(RADIO_SX127X) || defined(RADIO_LR1121)
SetRate(enumRatetoIndex(RATE_LORA_200HZ));
#elif defined(RADIO_SX128X)
SetRate(enumRatetoIndex(RATE_LORA_250HZ));
Expand Down
2 changes: 2 additions & 0 deletions src/lib/DEVICE/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#if defined(RADIO_SX127X)
#include "SX127xDriver.h"
#elif defined(RADIO_LR1121)
#include "LR1121Driver.h"
#elif defined(RADIO_SX128X)
#include "SX1280Driver.h"
#else
Expand Down
97 changes: 72 additions & 25 deletions src/lib/FHSS/FHSS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
#include "options.h"
#include <string.h>

#if defined(RADIO_SX127X)
#if defined(RADIO_SX127X) || defined(RADIO_LR1121)

#if defined(RADIO_LR1121)
#include "LR1121Driver.h"
#else
#include "SX127xDriver.h"
#endif

const fhss_config_t domains[] = {
{"AU915", FREQ_HZ_TO_REG_VAL(915500000), FREQ_HZ_TO_REG_VAL(926900000), 20},
Expand All @@ -16,6 +21,13 @@ const fhss_config_t domains[] = {
{"US433", FREQ_HZ_TO_REG_VAL(433250000), FREQ_HZ_TO_REG_VAL(438000000), 8},
{"US433W", FREQ_HZ_TO_REG_VAL(423500000), FREQ_HZ_TO_REG_VAL(438000000), 20},
};

#if defined(RADIO_LR1121)
const fhss_config_t domainsDualBand[] = {
{"ISM2G4", FREQ_HZ_TO_REG_VAL(2400400000), FREQ_HZ_TO_REG_VAL(2479400000), 80}
};
#endif

#elif defined(RADIO_SX128X)
#include "SX1280Driver.h"

Expand All @@ -32,18 +44,62 @@ const fhss_config_t domains[] = {

// Our table of FHSS frequencies. Define a regulatory domain to select the correct set for your location and radio
const fhss_config_t *FHSSconfig;
const fhss_config_t *FHSSconfigDualBand;

// Actual sequence of hops as indexes into the frequency list
uint8_t FHSSsequence[256];
uint8_t FHSSsequence[FHSS_SEQUENCE_LEN];
uint8_t FHSSsequence_DualBand[FHSS_SEQUENCE_LEN];

// Which entry in the sequence we currently are on
uint8_t volatile FHSSptr;

// Channel for sync packets and initial connection establishment
uint_fast8_t sync_channel;
uint_fast8_t sync_channel_DualBand;

// Offset from the predefined frequency determined by AFC on Team900 (register units)
int32_t FreqCorrection;
int32_t FreqCorrection_2;

// Frequency hop separation
uint32_t freq_spread;
uint32_t freq_spread_DualBand;

// Variable for Dual Band radios
bool FHSSusePrimaryFreqBand = true;
bool FHSSuseDualBand = false;

uint16_t primaryBandCount;
uint16_t secondaryBandCount;

void FHSSrandomiseFHSSsequence(const uint32_t seed)
{
FHSSconfig = &domains[firmwareOptions.domain];
sync_channel = (FHSSconfig->freq_count / 2) + 1;
freq_spread = (FHSSconfig->freq_stop - FHSSconfig->freq_start) * FREQ_SPREAD_SCALE / (FHSSconfig->freq_count - 1);
primaryBandCount = (FHSS_SEQUENCE_LEN / FHSSconfig->freq_count) * FHSSconfig->freq_count;

DBGLN("Setting %s Mode", FHSSconfig->domain);
DBGLN("Number of FHSS frequencies = %u", FHSSconfig->freq_count);
DBGLN("Sync channel = %u", sync_channel);

FHSSrandomiseFHSSsequenceBuild(seed, FHSSconfig->freq_count, sync_channel, FHSSsequence);

#if defined(RADIO_LR1121)
FHSSconfigDualBand = &domainsDualBand[0];
sync_channel_DualBand = (FHSSconfigDualBand->freq_count / 2) + 1;
freq_spread_DualBand = (FHSSconfigDualBand->freq_stop - FHSSconfigDualBand->freq_start) * FREQ_SPREAD_SCALE / (FHSSconfigDualBand->freq_count - 1);
secondaryBandCount = (FHSS_SEQUENCE_LEN / FHSSconfigDualBand->freq_count) * FHSSconfigDualBand->freq_count;

DBGLN("Setting Dual Band %s Mode", FHSSconfigDualBand->domain);
DBGLN("Number of FHSS frequencies = %u", FHSSconfigDualBand->freq_count);
DBGLN("Sync channel Dual Band = %u", sync_channel_DualBand);

FHSSusePrimaryFreqBand = false;
FHSSrandomiseFHSSsequenceBuild(seed, FHSSconfigDualBand->freq_count, sync_channel_DualBand, FHSSsequence_DualBand);
FHSSusePrimaryFreqBand = true;
#endif
}

/**
Requirements:
Expand All @@ -58,52 +114,43 @@ uint32_t freq_spread;
another random entry, excluding the sync channel.
*/
void FHSSrandomiseFHSSsequence(const uint32_t seed)
void FHSSrandomiseFHSSsequenceBuild(const uint32_t seed, uint32_t freqCount, uint_fast8_t syncChannel, uint8_t *inSequence)
{
FHSSconfig = &domains[firmwareOptions.domain];
DBGLN("Setting %s Mode", FHSSconfig->domain);
DBGLN("Number of FHSS frequencies = %u", FHSSconfig->freq_count);

sync_channel = (FHSSconfig->freq_count / 2) + 1;
DBGLN("Sync channel = %u", sync_channel);

freq_spread = (FHSSconfig->freq_stop - FHSSconfig->freq_start) * FREQ_SPREAD_SCALE / (FHSSconfig->freq_count - 1);

// reset the pointer (otherwise the tests fail)
FHSSptr = 0;
rngSeed(seed);

// initialize the sequence array
for (uint16_t i = 0; i < FHSSgetSequenceCount(); i++)
{
if (i % FHSSconfig->freq_count == 0) {
FHSSsequence[i] = sync_channel;
} else if (i % FHSSconfig->freq_count == sync_channel) {
FHSSsequence[i] = 0;
if (i % freqCount == 0) {
inSequence[i] = syncChannel;
} else if (i % freqCount == syncChannel) {
inSequence[i] = 0;
} else {
FHSSsequence[i] = i % FHSSconfig->freq_count;
inSequence[i] = i % freqCount;
}
}

for (uint16_t i=0; i < FHSSgetSequenceCount(); i++)
for (uint16_t i = 0; i < FHSSgetSequenceCount(); i++)
{
// if it's not the sync channel
if (i % FHSSconfig->freq_count != 0)
if (i % freqCount != 0)
{
uint8_t offset = (i / FHSSconfig->freq_count) * FHSSconfig->freq_count; // offset to start of current block
uint8_t rand = rngN(FHSSconfig->freq_count-1)+1; // random number between 1 and FHSS_FREQ_CNT
uint8_t offset = (i / freqCount) * freqCount; // offset to start of current block
uint8_t rand = rngN(freqCount - 1) + 1; // random number between 1 and FHSS_FREQ_CNT

// switch this entry and another random entry in the same block
uint8_t temp = FHSSsequence[i];
FHSSsequence[i] = FHSSsequence[offset+rand];
FHSSsequence[offset+rand] = temp;
uint8_t temp = inSequence[i];
inSequence[i] = inSequence[offset+rand];
inSequence[offset+rand] = temp;
}
}

// output FHSS sequence
for (uint16_t i=0; i < FHSSgetSequenceCount(); i++)
{
DBG("%u ",FHSSsequence[i]);
DBG("%u ",inSequence[i]);
if (i % 10 == 9)
DBGCR;
}
Expand Down
Loading

0 comments on commit b4ad5ce

Please sign in to comment.