diff --git a/src/main/config/config.c b/src/main/config/config.c index 5ee80256e0..a7bb455416 100644 --- a/src/main/config/config.c +++ b/src/main/config/config.c @@ -334,6 +334,7 @@ static void resetConf(void) resetTelemetryConfig(&masterConfig.telemetryConfig); masterConfig.rxConfig.serialrx_provider = 0; + masterConfig.rxConfig.spektrum_sat_bind = 0; masterConfig.rxConfig.midrc = 1500; masterConfig.rxConfig.mincheck = 1100; masterConfig.rxConfig.maxcheck = 1900; diff --git a/src/main/io/serial_cli.c b/src/main/io/serial_cli.c index 0d8131f150..f8101d7d39 100644 --- a/src/main/io/serial_cli.c +++ b/src/main/io/serial_cli.c @@ -271,6 +271,7 @@ const clivalue_t valueTable[] = { #endif { "serialrx_provider", VAR_UINT8 | MASTER_VALUE, &masterConfig.rxConfig.serialrx_provider, 0, SERIALRX_PROVIDER_MAX }, + { "spektrum_sat_bind", VAR_UINT8 | MASTER_VALUE, &masterConfig.rxConfig.spektrum_sat_bind, 0, 10 }, { "telemetry_provider", VAR_UINT8 | MASTER_VALUE, &masterConfig.telemetryConfig.telemetry_provider, 0, TELEMETRY_PROVIDER_MAX }, { "telemetry_switch", VAR_UINT8 | MASTER_VALUE, &masterConfig.telemetryConfig.telemetry_switch, 0, 1 }, diff --git a/src/main/io/serial_msp.c b/src/main/io/serial_msp.c index 59b5ab49b1..7a34b84e9f 100644 --- a/src/main/io/serial_msp.c +++ b/src/main/io/serial_msp.c @@ -1013,6 +1013,7 @@ static bool processOutCommand(uint8_t cmdMSP) case MSP_RX_CONFIG: headSerialReply(7); serialize8(masterConfig.rxConfig.serialrx_provider); + serialize8(masterConfig.rxConfig.spektrum_sat_bind); serialize16(masterConfig.rxConfig.maxcheck); serialize16(masterConfig.rxConfig.midrc); serialize16(masterConfig.rxConfig.mincheck); @@ -1288,6 +1289,7 @@ static bool processInCommand(void) case MSP_SET_RX_CONFIG: headSerialReply(0); masterConfig.rxConfig.serialrx_provider = read8(); + masterConfig.rxConfig.spektrum_sat_bind = read8(); masterConfig.rxConfig.maxcheck = read16(); masterConfig.rxConfig.midrc = read16(); masterConfig.rxConfig.mincheck = read16(); diff --git a/src/main/main.c b/src/main/main.c index be109e3395..bfe46347e7 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -105,7 +105,7 @@ void imuInit(void); void displayInit(rxConfig_t *intialRxConfig); void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse, failsafe_t* failsafeToUse); void loop(void); - +void spektrumBind(rxConfig_t *rxConfig); #ifdef STM32F303xC // from system_stm32f30x.c @@ -150,6 +150,19 @@ void init(void) systemInit(); + // Spektrum sattelite bind - ported from Baseflight + if (feature(FEATURE_RX_MSP)) { + switch (masterConfig.rxConfig.serialrx_provider) { + case SERIALRX_SPEKTRUM1024: + case SERIALRX_SPEKTRUM2048: + // Spektrum satellite binding if enabled on startup. + // Must be called before that 100ms sleep so that we don't lose satellite's binding window after startup. + // The rest of Spektrum initialization will happen later - via spektrumInit() + spektrumBind(&masterConfig.rxConfig); + break; + } + } + delay(100); timerInit(); // timer must be initialized before any channel is allocated diff --git a/src/main/rx/rx.h b/src/main/rx/rx.h index 2c6807c3d1..117269f182 100644 --- a/src/main/rx/rx.h +++ b/src/main/rx/rx.h @@ -65,6 +65,7 @@ extern int16_t rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT]; // interval [1000;2 typedef struct rxConfig_s { uint8_t rcmap[MAX_MAPPABLE_RX_INPUTS]; // mapping of radio channels to internal RPYTA+ order uint8_t serialrx_provider; // type of UART-based receiver (0 = spek 10, 1 = spek 11, 2 = sbus). Must be enabled by FEATURE_RX_SERIAL first. + uint8_t spektrum_sat_bind; // number of bind pules for Spektrum sattelite recievers uint16_t midrc; // Some radios have not a neutral point centered on 1500. can be changed here uint16_t mincheck; // minimum rc end uint16_t maxcheck; // maximum rc end diff --git a/src/main/rx/spektrum.c b/src/main/rx/spektrum.c index f1e756dbad..146de97b35 100644 --- a/src/main/rx/spektrum.c +++ b/src/main/rx/spektrum.c @@ -21,12 +21,15 @@ #include "platform.h" +#include "drivers/gpio.h" #include "drivers/system.h" #include "drivers/serial.h" #include "drivers/serial_uart.h" #include "io/serial.h" +#include "config/config.h" + #include "rx/rx.h" #include "rx/spektrum.h" @@ -40,6 +43,8 @@ #define SPEKTRUM_BAUDRATE 115200 +#define BKP_SOFTRESET (0x50F7B007) + static uint8_t spek_chan_shift; static uint8_t spek_chan_mask; static bool rcFrameComplete = false; @@ -138,3 +143,73 @@ static uint16_t spektrumReadRawRC(rxRuntimeConfig_t *rxRuntimeConfig, uint8_t ch return data; } + +uint32_t rccReadBkpDr(void) +{ + return *((uint16_t *)BKP_BASE + 0x04) | *((uint16_t *)BKP_BASE + 0x08) << 16; +} + +/* spektrumBind function ported from Baseflight. It's used to bind satellite receiver to TX. + * Function must be called immediately after startup so that we don't miss satellite bind window. + * Known parameters. Tested with DSMX satellite and DX8 radio. Framerate (11ms or 22ms) must be selected from TX. + * 9 = DSMX 11ms / DSMX 22ms + * 5 = DSM2 11ms 2048 / DSM2 22ms 1024 + */ +void spektrumBind(rxConfig_t *rxConfig) +{ + int i; + gpio_config_t gpio; + GPIO_TypeDef *spekBindPort; + uint16_t spekBindPin; + +#ifdef HARDWARE_BIND_PLUG + // Check status of bind plug and exit if not active + GPIO_TypeDef *hwBindPort; + uint16_t hwBindPin; + + hwBindPort = GPIOB; + hwBindPin = Pin_5; + gpio.speed = Speed_2MHz; + gpio.pin = hwBindPin; + gpio.mode = Mode_IPU; + gpioInit(hwBindPort, &gpio); + if (digitalIn(hwBindPort, hwBindPin)) + return; +#endif + + // USART2, PA3 + spekBindPort = GPIOA; + spekBindPin = Pin_3; + + // don't try to bind if: here after soft reset or bind flag is out of range + if (rccReadBkpDr() == BKP_SOFTRESET || rxConfig->spektrum_sat_bind == 0 || rxConfig->spektrum_sat_bind > 10) + return; + + gpio.speed = Speed_2MHz; + gpio.pin = spekBindPin; + gpio.mode = Mode_Out_OD; + gpioInit(spekBindPort, &gpio); + // RX line, set high + digitalHi(spekBindPort, spekBindPin); + // Bind window is around 20-140ms after powerup + delay(60); + + for (i = 0; i < rxConfig->spektrum_sat_bind; i++) { + // RX line, drive low for 120us + digitalLo(spekBindPort, spekBindPin); + delayMicroseconds(120); + // RX line, drive high for 120us + digitalHi(spekBindPort, spekBindPin); + delayMicroseconds(120); + } + +#ifndef HARDWARE_BIND_PLUG + // If we came here as a result of hard reset (power up, with mcfg.spektrum_sat_bind set), then reset it back to zero and write config + // Don't reset if hardware bind plug is present + if (rccReadBkpDr() != BKP_SOFTRESET) { + rxConfig->spektrum_sat_bind = 0; + writeEEPROM(1, true); + } +#endif + +}