1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-23 16:25:31 +03:00

Merge pull request #9960 from phobos-/f4-dsmx

Spektrum SPI protocol improvements
This commit is contained in:
Michael Keller 2020-06-30 01:03:09 +12:00 committed by GitHub
commit 4abc447ffe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 135 additions and 87 deletions

View file

@ -104,6 +104,8 @@ static const uint8_t pnCodes[5][9][8] = {
},
};
static const uint8_t bindDataCode[16] = {0x98, 0x88, 0x1B, 0xE4, 0x30, 0x79, 0x03, 0x84, 0x98, 0x88, 0x1B, 0xE4, 0x30, 0x79, 0x03, 0x84};
static const uint8_t cyrf6936Config[][2] = {
{CYRF6936_CLK_EN, CYRF6936_RXF}, // Enable the clock
{CYRF6936_AUTO_CAL_TIME, 0x3C}, // From manual, needed for initialization
@ -132,24 +134,26 @@ static const uint8_t cyrf6936TransferConfig[][2] = {
typedef enum {
DSM2_22 = 0x01,
DSM2_11 = 0x02,
DSM2_11_DX6 = 0x03,
DSM2_11_DX8 = 0x12,
DSMX_22 = 0xA2,
DSMX_11 = 0xB2,
} dsm_protocol_e;
#define IS_DSM2(x) (x == DSM2_22 || x == DSM2_11 || x == DSM2_11_DX8)
#define IS_DSM2(x) (x == DSM2_22 || x == DSM2_11 || x == DSM2_11_DX6 || x == DSM2_11_DX8)
#define IS_DSMX(x) (!IS_DSM2(x))
#define CHECK_MFG_ID(protocol, packet, id) ((IS_DSM2(protocol) && packet[0] == (~id[2]&0xFF) && packet[1] == (~id[3]&0xFF)) || \
(IS_DSMX(protocol) && packet[0] == id[2] && packet[1] == id[3]))
typedef enum {
DSM_RECEIVER_BIND = 0x0,
DSM_RECEIVER_SYNC_A = 0x1,
DSM_RECEIVER_SYNC_B = 0x2,
DSM_RECEIVER_RECV = 0x3,
DSM_RECEIVER_BIND = 0,
DSM_RECEIVER_BIND2,
DSM_RECEIVER_SYNC_A,
DSM_RECEIVER_SYNC_B,
DSM_RECEIVER_RECV,
#ifdef USE_RX_SPEKTRUM_TELEMETRY
DSM_RECEIVER_TLM = 0x4,
DSM_RECEIVER_TLM,
#endif
} dsm_receiver_status_e;
@ -175,6 +179,8 @@ typedef struct dsmReceiver_s {
uint32_t timeout;
uint32_t timeLastPacket;
uint16_t bindPackets;
#ifdef USE_RX_SPEKTRUM_TELEMETRY
uint32_t timeLastTelemetry;
bool sendTelemetry;
@ -264,68 +270,6 @@ static void resetReceiveTimeout(const uint32_t timeStamp)
}
}
static void checkTimeout(void)
{
const uint32_t time = micros();
#ifdef USE_RX_SPEKTRUM_TELEMETRY
if (featureIsEnabled(FEATURE_TELEMETRY) && (time - dsmReceiver.timeLastTelemetry) > DSM_TELEMETRY_TIME_US) {
dsmReceiver.timeLastTelemetry = time;
dsmReceiver.sendTelemetry = true;
}
#endif
if ((time - dsmReceiver.timeLastPacket) > dsmReceiver.timeout) {
cyrf6936SetMode(CYRF6936_MODE_SYNTH_RX, true);
cyrf6936WriteRegister(CYRF6936_RX_ABORT, 0x00);
dsmReceiver.timeLastPacket += dsmReceiver.timeout;
switch (dsmReceiver.status) {
case DSM_RECEIVER_BIND:
dsmReceiver.rfChannel = (dsmReceiver.rfChannel + 2) % DSM_MAX_RF_CHANNEL;
cyrf6936SetChannel(dsmReceiver.rfChannel);
dsmReceiver.timeout = DSM_BIND_TIMEOUT_US;
cyrf6936StartRecv();
break;
case DSM_RECEIVER_SYNC_A:
case DSM_RECEIVER_SYNC_B:
IS_DSM2(dsmReceiver.protocol) ? dsmReceiverSetNextSyncChannel() : dsmReceiverSetNextChannel();
dsmReceiver.timeout = DSM_SYNC_TIMEOUT_US;
cyrf6936StartRecv();
break;
case DSM_RECEIVER_RECV:
dsmReceiver.missedPackets++;
DEBUG_SET(DEBUG_RX_SPEKTRUM_SPI, 0, dsmReceiver.missedPackets);
if (dsmReceiver.missedPackets < DSM_MAX_MISSED_PACKETS) {
dsmReceiverSetNextChannel();
if (dsmReceiver.crcSeed == ((dsmReceiver.mfgId[0] << 8) + dsmReceiver.mfgId[1])) {
dsmReceiver.timeout = DSM_RECV_SHORT_TIMEOUT_US;
} else {
dsmReceiver.timeout = DSM_RECV_TIMEOUT_OFFSET_US + (dsmReceiver.numChannels < 8 ? DSM_RECV_LONG_TIMEOUT_US : DSM_RECV_MID_TIMEOUT_US);
}
cyrf6936StartRecv();
} else {
setRssiDirect(0, RSSI_SOURCE_RX_PROTOCOL);
dsmReceiver.status = DSM_RECEIVER_SYNC_A;
dsmReceiver.timeout = DSM_SYNC_TIMEOUT_US;
}
break;
#ifdef USE_RX_SPEKTRUM_TELEMETRY
case DSM_RECEIVER_TLM:
DEBUG_SET(DEBUG_RX_SPEKTRUM_SPI, 2, (cyrf6936ReadRegister(CYRF6936_TX_IRQ_STATUS) & CYRF6936_TXC_IRQ) == 0);
dsmReceiverSetNextChannel();
dsmReceiver.status = DSM_RECEIVER_RECV;
dsmReceiver.timeout = (dsmReceiver.numChannels < 8 ? DSM_RECV_LONG_TIMEOUT_US : DSM_RECV_MID_TIMEOUT_US) - DSM_TELEMETRY_TIMEOUT_US;
cyrf6936StartRecv();
break;
#endif
default:
break;
}
}
}
static void dsmReceiverStartBind(void)
{
uint8_t dataCode[16];
@ -437,6 +381,96 @@ static void dsmSendTelemetryPacket(void)
}
#endif
static void dsmSendBindPacket(void)
{
uint8_t packet[10];
uint16_t sum = 384 - 0x10;
packet[0] = 0xff ^ dsmReceiver.mfgId[0];
packet[1] = 0xff ^ dsmReceiver.mfgId[1];
packet[2] = 0xff ^ dsmReceiver.mfgId[2];
packet[3] = 0xff ^ dsmReceiver.mfgId[3];
packet[4] = 0x01;
packet[5] = dsmReceiver.numChannels;
packet[6] = dsmReceiver.protocol;
packet[7] = 0x00;
for(unsigned i = 0; i < 8; i++)
sum += packet[i];
packet[8] = sum >> 8;
packet[9] = sum & 0xff;
cyrf6936SetMode(CYRF6936_MODE_IDLE, true);
cyrf6936SendLen(packet, 10);
}
static void checkTimeout(void)
{
const uint32_t time = micros();
#ifdef USE_RX_SPEKTRUM_TELEMETRY
if (featureIsEnabled(FEATURE_TELEMETRY) && (time - dsmReceiver.timeLastTelemetry) > DSM_TELEMETRY_TIME_US) {
dsmReceiver.timeLastTelemetry = time;
dsmReceiver.sendTelemetry = true;
}
#endif
if ((time - dsmReceiver.timeLastPacket) > dsmReceiver.timeout) {
cyrf6936SetMode(CYRF6936_MODE_SYNTH_RX, true);
cyrf6936WriteRegister(CYRF6936_RX_ABORT, 0x00);
dsmReceiver.timeLastPacket += dsmReceiver.timeout;
switch (dsmReceiver.status) {
case DSM_RECEIVER_BIND:
dsmReceiver.rfChannel = (dsmReceiver.rfChannel + 2) % DSM_MAX_RF_CHANNEL;
cyrf6936SetChannel(dsmReceiver.rfChannel);
dsmReceiver.timeout = DSM_BIND_TIMEOUT_US;
cyrf6936StartRecv();
break;
case DSM_RECEIVER_BIND2:
if (dsmReceiver.bindPackets++ > DSM_MAX_BIND_PACKETS) {
dsmReceiverStartTransfer();
} else {
dsmReceiver.timeout = DSM_BIND_TIMEOUT_US;
dsmSendBindPacket();
}
break;
case DSM_RECEIVER_SYNC_A:
case DSM_RECEIVER_SYNC_B:
IS_DSM2(dsmReceiver.protocol) ? dsmReceiverSetNextSyncChannel() : dsmReceiverSetNextChannel();
dsmReceiver.timeout = DSM_SYNC_TIMEOUT_US;
cyrf6936StartRecv();
break;
case DSM_RECEIVER_RECV:
dsmReceiver.missedPackets++;
DEBUG_SET(DEBUG_RX_SPEKTRUM_SPI, 0, dsmReceiver.missedPackets);
if (dsmReceiver.missedPackets < DSM_MAX_MISSED_PACKETS) {
dsmReceiverSetNextChannel();
if (dsmReceiver.crcSeed == ((dsmReceiver.mfgId[0] << 8) + dsmReceiver.mfgId[1])) {
dsmReceiver.timeout = DSM_RECV_SHORT_TIMEOUT_US;
} else {
dsmReceiver.timeout = dsmReceiver.numChannels < 8 ? DSM_RECV_LONG_TIMEOUT_US : DSM_RECV_MID_TIMEOUT_US;
}
cyrf6936StartRecv();
} else {
setRssiDirect(0, RSSI_SOURCE_RX_PROTOCOL);
dsmReceiver.status = DSM_RECEIVER_SYNC_A;
dsmReceiver.timeout = DSM_SYNC_TIMEOUT_US;
}
break;
#ifdef USE_RX_SPEKTRUM_TELEMETRY
case DSM_RECEIVER_TLM:
DEBUG_SET(DEBUG_RX_SPEKTRUM_SPI, 2, (cyrf6936ReadRegister(CYRF6936_TX_IRQ_STATUS) & CYRF6936_TXC_IRQ) == 0);
dsmReceiverSetNextChannel();
dsmReceiver.status = DSM_RECEIVER_RECV;
dsmReceiver.timeout = (dsmReceiver.numChannels < 8 ? DSM_RECV_LONG_TIMEOUT_US : DSM_RECV_MID_TIMEOUT_US) - DSM_TELEMETRY_TIMEOUT_US;
cyrf6936StartRecv();
break;
#endif
default:
break;
}
}
}
void spektrumSpiSetRcDataFromPayload(uint16_t *rcData, const uint8_t *payload)
{
if (rcData && payload) {
@ -528,9 +562,14 @@ rx_spi_received_e spektrumReadPacket(uint8_t *payload, const uint32_t timeStamp)
spektrumConfigMutable()->protocol = dsmReceiver.protocol;
writeEEPROM();
dsmReceiverStartTransfer();
cyrf6936SetDataCode(bindDataCode);
dsmReceiver.bindPackets = 0;
dsmReceiver.status = DSM_RECEIVER_BIND2;
dsmReceiver.timeLastPacket = timeStamp;
dsmReceiver.timeout = DSM_BIND_TIMEOUT_US;
dsmReceiver.bound = true;
result = RX_SPI_RECEIVED_BIND;
break;
case DSM_RECEIVER_SYNC_A:
@ -548,6 +587,8 @@ rx_spi_received_e spektrumReadPacket(uint8_t *payload, const uint32_t timeStamp)
IS_DSM2(dsmReceiver.protocol) ? dsmReceiverSetNextSyncChannel() : dsmReceiverSetNextChannel();
resetReceiveTimeout(timeStamp);
cyrf6936StartRecv();
result = RX_SPI_RECEIVED_DATA;
}
break;
case DSM_RECEIVER_SYNC_B:
@ -565,6 +606,8 @@ rx_spi_received_e spektrumReadPacket(uint8_t *payload, const uint32_t timeStamp)
resetReceiveTimeout(timeStamp);
cyrf6936StartRecv();
}
result = RX_SPI_RECEIVED_DATA;
}
break;
case DSM_RECEIVER_RECV:
@ -614,7 +657,7 @@ rx_spi_received_e spektrumSpiDataReceived(uint8_t *payload)
checkTimeout();
dsmReceiver.bound ? rxSpiLedBlinkRxLoss(result) : rxSpiLedBlinkBind();
dsmReceiver.bound ? (dsmReceiver.status == DSM_RECEIVER_BIND2 ? rxSpiLedBlinkRxLoss(RX_SPI_RECEIVED_DATA) : rxSpiLedBlinkRxLoss(result)) : rxSpiLedBlinkBind();
return result;
}

View file

@ -23,13 +23,13 @@
#include <stdbool.h>
#include <stdint.h>
#define DSM_BIND_TIMEOUT_US 10000
#define DSM_BIND_TIMEOUT_US 11000
#define DSM_SYNC_TIMEOUT_US 20000
#define DSM_RECV_LONG_TIMEOUT_US 18010
#define DSM_RECV_MID_TIMEOUT_US 7000
#define DSM_RECV_SHORT_TIMEOUT_US 4010
#define DSM_RECV_TIMEOUT_OFFSET_US 1000
#define DSM_RECV_LONG_TIMEOUT_US 18500
#define DSM_RECV_MID_TIMEOUT_US 7500
#define DSM_RECV_SHORT_TIMEOUT_US 4500
#define DSM_MAX_BIND_PACKETS 500
#define DSM_MAX_MISSED_PACKETS 31
#define DSM_MAX_RF_CHANNEL 0x4F

View file

@ -94,19 +94,18 @@ void rxSpiLedBlink(timeMs_t blinkMs)
void rxSpiLedBlinkRxLoss(rx_spi_received_e result)
{
static uint16_t rxLossCount = 0;
static timeMs_t rxLossMs = 0;
if (ledPin) {
if (result == RX_SPI_RECEIVED_DATA) {
rxLossCount = 0;
rxSpiLedOn();
} else {
if (rxLossCount < RX_LOSS_COUNT) {
rxLossCount++;
} else {
rxSpiLedBlink(INTERVAL_RX_LOSS_MS);
if ((rxLossMs + INTERVAL_RX_LOSS_MS) > millis()) {
return;
}
rxSpiLedToggle();
}
rxLossMs = millis();
}
}

View file

@ -24,7 +24,6 @@
#define INTERVAL_RX_LOSS_MS 1000
#define INTERVAL_RX_BIND_MS 250
#define RX_LOSS_COUNT 1000
void rxSpiCommonIOInit(const rxSpiConfig_t *rxSpiConfig);

View file

@ -249,4 +249,7 @@
#define USE_RX_FLYSKY
#define USE_RX_FLYSKY_SPI_LED
#define USE_RX_SPEKTRUM
#define USE_RX_SPEKTRUM_TELEMETRY
#define USE_CUSTOM_DEFAULTS

View file

@ -44,12 +44,13 @@ extern "C" {
#define IS_DSMX(x) (!IS_DSM2(x))
typedef enum {
DSM_RECEIVER_BIND = 0x0,
DSM_RECEIVER_SYNC_A = 0x1,
DSM_RECEIVER_SYNC_B = 0x2,
DSM_RECEIVER_RECV = 0x3,
DSM_RECEIVER_BIND = 0,
DSM_RECEIVER_BIND2,
DSM_RECEIVER_SYNC_A,
DSM_RECEIVER_SYNC_B,
DSM_RECEIVER_RECV,
#ifdef USE_RX_SPEKTRUM_TELEMETRY
DSM_RECEIVER_TLM = 0x4,
DSM_RECEIVER_TLM,
#endif
} dsm_receiver_status_e;
@ -75,6 +76,8 @@ extern "C" {
uint32_t timeout;
uint32_t timeLastPacket;
uint16_t bindPackets;
#ifdef USE_RX_SPEKTRUM_TELEMETRY
uint32_t timeLastTelemetry;
bool sendTelemetry;
@ -375,6 +378,7 @@ extern "C" {
void cyrf6936SetSopCode(const uint8_t ) {}
void cyrf6936SetDataCode(const uint8_t ) {}
void cyrf6936StartRecv(void) {}
void cyrf6936SendLen(uint8_t *, const uint8_t ) {}
void cyrf6936RecvLen(uint8_t *data, const uint8_t length)
{
if (length == packetLen) {