mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-25 01:05:27 +03:00
Fixed baud rate and inversion. Added more tests
This commit is contained in:
parent
6b53b200ae
commit
818a91b6c1
6 changed files with 151 additions and 57 deletions
|
@ -37,6 +37,7 @@
|
||||||
#include "fc/fc_debug.h"
|
#include "fc/fc_debug.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "build/build_config.h"
|
||||||
#include "build/debug.h"
|
#include "build/debug.h"
|
||||||
|
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
|
@ -54,14 +55,13 @@
|
||||||
|
|
||||||
#define CRSF_TIME_NEEDED_PER_FRAME_US 1500 //!! this needs checking
|
#define CRSF_TIME_NEEDED_PER_FRAME_US 1500 //!! this needs checking
|
||||||
|
|
||||||
#define CRSF_MAX_CHANNEL 16
|
|
||||||
|
|
||||||
#define CRSF_DIGITAL_CHANNEL_MIN 172
|
#define CRSF_DIGITAL_CHANNEL_MIN 172
|
||||||
#define CRSF_DIGITAL_CHANNEL_MAX 1811
|
#define CRSF_DIGITAL_CHANNEL_MAX 1811
|
||||||
|
|
||||||
static bool crsfFrameDone = false;
|
STATIC_UNIT_TESTED bool crsfFrameDone = false;
|
||||||
|
STATIC_UNIT_TESTED crsfFrame_t crsfFrame;
|
||||||
|
|
||||||
static uint32_t crsfChannelData[CRSF_MAX_CHANNEL];
|
STATIC_UNIT_TESTED uint32_t crsfChannelData[CRSF_MAX_CHANNEL];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Structure
|
Structure
|
||||||
|
@ -101,19 +101,6 @@ struct crsfPayloadRcChannelsPacked_s {
|
||||||
|
|
||||||
typedef struct crsfPayloadRcChannelsPacked_s crsfPayloadRcChannelsPacked_t;
|
typedef struct crsfPayloadRcChannelsPacked_s crsfPayloadRcChannelsPacked_t;
|
||||||
|
|
||||||
typedef union crsfFrameDef_s {
|
|
||||||
uint8_t deviceAddress;
|
|
||||||
uint8_t frameLength;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t payload[CRSF_PAYLOAD_SIZE_MAX + 1]; // +1 for CRC at end of payload
|
|
||||||
} crsfFrameDef_t;
|
|
||||||
|
|
||||||
typedef union crsfFrame_u {
|
|
||||||
uint8_t bytes[CRSF_FRAME_SIZE_MAX];
|
|
||||||
crsfFrameDef_t frame;
|
|
||||||
} crsfFrame_t;
|
|
||||||
|
|
||||||
static crsfFrame_t crsfFrame;
|
|
||||||
|
|
||||||
// Receive ISR callback, called back from serial port
|
// Receive ISR callback, called back from serial port
|
||||||
static void crsfDataReceive(uint16_t c)
|
static void crsfDataReceive(uint16_t c)
|
||||||
|
@ -123,7 +110,9 @@ static void crsfDataReceive(uint16_t c)
|
||||||
const uint32_t now = micros();
|
const uint32_t now = micros();
|
||||||
|
|
||||||
const int32_t crsfFrameTime = now - crsfFrameStartAt;
|
const int32_t crsfFrameTime = now - crsfFrameStartAt;
|
||||||
DEBUG_SET(DEBUG_CRSF, 2, crsfFrameTime);
|
#ifdef DEBUG_CRSF_PACKETS
|
||||||
|
debug[2] = crsfFrameTime;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (crsfFrameTime > (long)(CRSF_TIME_NEEDED_PER_FRAME_US + 500)) {
|
if (crsfFrameTime > (long)(CRSF_TIME_NEEDED_PER_FRAME_US + 500)) {
|
||||||
crsfFramePosition = 0;
|
crsfFramePosition = 0;
|
||||||
|
@ -146,6 +135,7 @@ uint8_t crsfFrameStatus(void)
|
||||||
if (crsfFrameDone) {
|
if (crsfFrameDone) {
|
||||||
crsfFrameDone = false;
|
crsfFrameDone = false;
|
||||||
if (crsfFrame.frame.type == CRSF_FRAMETYPE_RC_CHANNELS_PACKED) {
|
if (crsfFrame.frame.type == CRSF_FRAMETYPE_RC_CHANNELS_PACKED) {
|
||||||
|
crsfFrame.frame.frameLength = CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE + CRSF_FRAME_LENGTH_TYPE_CRC;
|
||||||
// unpack the RC channels
|
// unpack the RC channels
|
||||||
const crsfPayloadRcChannelsPacked_t* rcChannels = (crsfPayloadRcChannelsPacked_t*)&crsfFrame.frame.payload;
|
const crsfPayloadRcChannelsPacked_t* rcChannels = (crsfPayloadRcChannelsPacked_t*)&crsfFrame.frame.payload;
|
||||||
crsfChannelData[0] = rcChannels->chan0;
|
crsfChannelData[0] = rcChannels->chan0;
|
||||||
|
|
|
@ -17,8 +17,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define CRSF_BAUDRATE 400000
|
#define CRSF_BAUDRATE 420000
|
||||||
#define CRSF_PORT_OPTIONS (SERIAL_INVERTED | SERIAL_STOPBITS_1 | SERIAL_PARITY_NO)
|
#define CRSF_PORT_OPTIONS (SERIAL_STOPBITS_1 | SERIAL_PARITY_NO)
|
||||||
|
|
||||||
|
#define CRSF_MAX_CHANNEL 16
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CRSF_FRAMETYPE_GPS = 0x02,
|
CRSF_FRAMETYPE_GPS = 0x02,
|
||||||
|
@ -45,6 +47,18 @@ enum {
|
||||||
#define CRSF_PAYLOAD_SIZE_MAX 32 // !!TODO needs checking
|
#define CRSF_PAYLOAD_SIZE_MAX 32 // !!TODO needs checking
|
||||||
#define CRSF_FRAME_SIZE_MAX (CRSF_PAYLOAD_SIZE_MAX + 4)
|
#define CRSF_FRAME_SIZE_MAX (CRSF_PAYLOAD_SIZE_MAX + 4)
|
||||||
|
|
||||||
|
typedef struct crsfFrameDef_s {
|
||||||
|
uint8_t deviceAddress;
|
||||||
|
uint8_t frameLength;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t payload[CRSF_PAYLOAD_SIZE_MAX + 1]; // +1 for CRC at end of payload
|
||||||
|
} crsfFrameDef_t;
|
||||||
|
|
||||||
|
typedef union crsfFrame_u {
|
||||||
|
uint8_t bytes[CRSF_FRAME_SIZE_MAX];
|
||||||
|
crsfFrameDef_t frame;
|
||||||
|
} crsfFrame_t;
|
||||||
|
|
||||||
uint8_t crsfFrameStatus(void);
|
uint8_t crsfFrameStatus(void);
|
||||||
struct rxConfig_s;
|
struct rxConfig_s;
|
||||||
struct rxRuntimeConfig_s;
|
struct rxRuntimeConfig_s;
|
||||||
|
|
|
@ -490,6 +490,31 @@ $(OBJECT_DIR)/rx_rx_unittest : \
|
||||||
|
|
||||||
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
||||||
|
|
||||||
|
$(OBJECT_DIR)/rx/crsf.o : \
|
||||||
|
$(USER_DIR)/rx/crsf.c \
|
||||||
|
$(USER_DIR)/rx/crsf.h \
|
||||||
|
$(GTEST_HEADERS)
|
||||||
|
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/rx/crsf.c -o $@
|
||||||
|
|
||||||
|
$(OBJECT_DIR)/rx_crsf_unittest.o : \
|
||||||
|
$(TEST_DIR)/rx_crsf_unittest.cc \
|
||||||
|
$(USER_DIR)/rx/crsf.h \
|
||||||
|
$(USER_DIR)/rx/crsf.c \
|
||||||
|
$(GTEST_HEADERS)
|
||||||
|
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CXX) $(CXX_FLAGS) $(TEST_CFLAGS) -c $(TEST_DIR)/rx_crsf_unittest.cc -o $@
|
||||||
|
|
||||||
|
$(OBJECT_DIR)/rx_crsf_unittest : \
|
||||||
|
$(OBJECT_DIR)/rx/crsf.o \
|
||||||
|
$(OBJECT_DIR)/rx_crsf_unittest.o \
|
||||||
|
$(OBJECT_DIR)/common/maths.o \
|
||||||
|
$(OBJECT_DIR)/gtest_main.a
|
||||||
|
|
||||||
|
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
||||||
|
|
||||||
$(OBJECT_DIR)/telemetry/crsf.o : \
|
$(OBJECT_DIR)/telemetry/crsf.o : \
|
||||||
$(USER_DIR)/telemetry/crsf.c \
|
$(USER_DIR)/telemetry/crsf.c \
|
||||||
$(USER_DIR)/telemetry/crsf.h \
|
$(USER_DIR)/telemetry/crsf.h \
|
||||||
|
@ -521,39 +546,6 @@ $(OBJECT_DIR)/telemetry_crsf_unittest : \
|
||||||
|
|
||||||
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
||||||
|
|
||||||
$(OBJECT_DIR)/rx/crsf.o : \
|
|
||||||
$(USER_DIR)/rx/crsf.c \
|
|
||||||
$(USER_DIR)/rx/crsf.h \
|
|
||||||
$(GTEST_HEADERS)
|
|
||||||
|
|
||||||
@mkdir -p $(dir $@)
|
|
||||||
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/rx/crsf.c -o $@
|
|
||||||
|
|
||||||
$(OBJECT_DIR)/telemetry/crsf.o : \
|
|
||||||
$(USER_DIR)/telemetry/crsf.c \
|
|
||||||
$(USER_DIR)/telemetry/crsf.h \
|
|
||||||
$(GTEST_HEADERS)
|
|
||||||
|
|
||||||
@mkdir -p $(dir $@)
|
|
||||||
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/telemetry/crsf.c -o $@
|
|
||||||
|
|
||||||
$(OBJECT_DIR)/rx_crsf_unittest.o : \
|
|
||||||
$(TEST_DIR)/rx_crsf_unittest.cc \
|
|
||||||
$(USER_DIR)/rx/crsf.h \
|
|
||||||
$(USER_DIR)/rx/crsf.c \
|
|
||||||
$(GTEST_HEADERS)
|
|
||||||
|
|
||||||
@mkdir -p $(dir $@)
|
|
||||||
$(CXX) $(CXX_FLAGS) $(TEST_CFLAGS) -c $(TEST_DIR)/rx_crsf_unittest.cc -o $@
|
|
||||||
|
|
||||||
$(OBJECT_DIR)/rx_crsf_unittest : \
|
|
||||||
$(OBJECT_DIR)/rx/crsf.o \
|
|
||||||
$(OBJECT_DIR)/common/maths.o \
|
|
||||||
$(OBJECT_DIR)/rx_crsf_unittest.o \
|
|
||||||
$(OBJECT_DIR)/gtest_main.a
|
|
||||||
|
|
||||||
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
|
||||||
|
|
||||||
$(OBJECT_DIR)/rx_ranges_unittest.o : \
|
$(OBJECT_DIR)/rx_ranges_unittest.o : \
|
||||||
$(TEST_DIR)/rx_ranges_unittest.cc \
|
$(TEST_DIR)/rx_ranges_unittest.cc \
|
||||||
$(USER_DIR)/rx/rx.h \
|
$(USER_DIR)/rx/rx.h \
|
||||||
|
|
|
@ -65,6 +65,11 @@ uint8_t DMA_GetFlagStatus(void *);
|
||||||
void DMA_Cmd(DMA_Channel_TypeDef*, FunctionalState );
|
void DMA_Cmd(DMA_Channel_TypeDef*, FunctionalState );
|
||||||
void DMA_ClearFlag(uint32_t);
|
void DMA_ClearFlag(uint32_t);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void* test;
|
||||||
|
} USART_TypeDef;
|
||||||
|
|
||||||
#define WS2811_DMA_TC_FLAG (void *)1
|
#define WS2811_DMA_TC_FLAG (void *)1
|
||||||
#define WS2811_DMA_HANDLER_IDENTIFER 0
|
#define WS2811_DMA_HANDLER_IDENTIFER 0
|
||||||
|
|
||||||
|
|
|
@ -24,14 +24,19 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
|
|
||||||
#include "config/parameter_group.h"
|
#include "build/debug.h"
|
||||||
#include "config/parameter_group_ids.h"
|
|
||||||
|
|
||||||
#include "rx/rx.h"
|
|
||||||
#include "fc/rc_controls.h"
|
|
||||||
#include "common/maths.h"
|
#include "common/maths.h"
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
|
|
||||||
|
#include "io/serial.h"
|
||||||
|
|
||||||
|
#include "rx/rx.h"
|
||||||
|
#include "rx/crsf.h"
|
||||||
|
|
||||||
|
extern bool crsfFrameDone;
|
||||||
|
extern crsfFrame_t crsfFrame;
|
||||||
|
extern uint32_t crsfChannelData[CRSF_MAX_CHANNEL];
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "unittest_macros.h"
|
#include "unittest_macros.h"
|
||||||
|
@ -95,5 +100,92 @@ TEST(CrossFireTest, CRC)
|
||||||
EXPECT_EQ(crc1, crc2);
|
EXPECT_EQ(crc1, crc2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CrossFireTest, TestCrsfFrameStatus)
|
||||||
|
{
|
||||||
|
crsfFrameDone = true;
|
||||||
|
crsfFrame.frame.deviceAddress = CRSF_RECEIVER_ADDRESS;
|
||||||
|
crsfFrame.frame.frameLength = 0;
|
||||||
|
crsfFrame.frame.type = CRSF_FRAMETYPE_RC_CHANNELS_PACKED;
|
||||||
|
memset(crsfFrame.frame.payload, 0, CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE);
|
||||||
|
|
||||||
|
const uint8_t status = crsfFrameStatus();
|
||||||
|
EXPECT_EQ(RX_FRAME_COMPLETE, status);
|
||||||
|
EXPECT_EQ(false, crsfFrameDone);
|
||||||
|
|
||||||
|
EXPECT_EQ(CRSF_RECEIVER_ADDRESS, crsfFrame.frame.deviceAddress);
|
||||||
|
EXPECT_EQ(CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE + CRSF_FRAME_LENGTH_TYPE_CRC, crsfFrame.frame.frameLength);
|
||||||
|
EXPECT_EQ(CRSF_FRAMETYPE_RC_CHANNELS_PACKED, crsfFrame.frame.type);
|
||||||
|
for (int ii = 0; ii < CRSF_MAX_CHANNEL; ++ii) {
|
||||||
|
EXPECT_EQ(0, crsfChannelData[ii]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CrossFireTest, TestCrsfFrameStatusUnpacking)
|
||||||
|
{
|
||||||
|
crsfFrameDone = true;
|
||||||
|
crsfFrame.frame.deviceAddress = CRSF_RECEIVER_ADDRESS;
|
||||||
|
crsfFrame.frame.frameLength = 0;
|
||||||
|
crsfFrame.frame.type = CRSF_FRAMETYPE_RC_CHANNELS_PACKED;
|
||||||
|
// 16 11-bit channels packed into 22 bytes of data
|
||||||
|
crsfFrame.frame.payload[0] = 0xFF;
|
||||||
|
crsfFrame.frame.payload[1] = 0xFF;
|
||||||
|
// !!TODO add more test data
|
||||||
|
crsfFrame.frame.payload[2] = 0;
|
||||||
|
crsfFrame.frame.payload[3] = 0;
|
||||||
|
crsfFrame.frame.payload[4] = 0;
|
||||||
|
crsfFrame.frame.payload[5] = 0;
|
||||||
|
crsfFrame.frame.payload[6] = 0;
|
||||||
|
crsfFrame.frame.payload[7] = 0;
|
||||||
|
crsfFrame.frame.payload[8] = 0;
|
||||||
|
crsfFrame.frame.payload[9] = 0;
|
||||||
|
crsfFrame.frame.payload[10] = 0;
|
||||||
|
crsfFrame.frame.payload[11] = 0;
|
||||||
|
crsfFrame.frame.payload[12] = 0;
|
||||||
|
crsfFrame.frame.payload[13] = 0;
|
||||||
|
crsfFrame.frame.payload[14] = 0;
|
||||||
|
crsfFrame.frame.payload[15] = 0;
|
||||||
|
crsfFrame.frame.payload[16] = 0;
|
||||||
|
crsfFrame.frame.payload[17] = 0;
|
||||||
|
crsfFrame.frame.payload[18] = 0;
|
||||||
|
crsfFrame.frame.payload[19] = 0;
|
||||||
|
crsfFrame.frame.payload[20] = 0;
|
||||||
|
crsfFrame.frame.payload[21] = 0;
|
||||||
|
|
||||||
|
const uint8_t status = crsfFrameStatus();
|
||||||
|
EXPECT_EQ(RX_FRAME_COMPLETE, status);
|
||||||
|
EXPECT_EQ(false, crsfFrameDone);
|
||||||
|
|
||||||
|
EXPECT_EQ(CRSF_RECEIVER_ADDRESS, crsfFrame.frame.deviceAddress);
|
||||||
|
EXPECT_EQ(CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE + CRSF_FRAME_LENGTH_TYPE_CRC, crsfFrame.frame.frameLength);
|
||||||
|
EXPECT_EQ(CRSF_FRAMETYPE_RC_CHANNELS_PACKED, crsfFrame.frame.type);
|
||||||
|
EXPECT_EQ(0x7ff, crsfChannelData[0]);
|
||||||
|
EXPECT_EQ(0x1f, crsfChannelData[1]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[2]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[3]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[4]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[5]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[6]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[7]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[8]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[9]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[10]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[11]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[12]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[13]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[14]);
|
||||||
|
EXPECT_EQ(0, crsfChannelData[15]);
|
||||||
|
}
|
||||||
// STUBS
|
// STUBS
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
int16_t debug[DEBUG16_VALUE_COUNT];
|
||||||
|
uint32_t micros(void) {return 0;}
|
||||||
|
serialPort_t *openSerialPort(serialPortIdentifier_e, serialPortFunction_e, serialReceiveCallbackPtr, uint32_t, portMode_t, portOptions_t)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
serialPortConfig_t *findSerialPortConfig(serialPortFunction_e ) {return NULL;}
|
||||||
|
bool telemetryCheckRxPortShared(const serialPortConfig_t *) {return false;}
|
||||||
|
serialPort_t *telemetrySharedPort = NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#define BARO
|
#define BARO
|
||||||
#define GPS
|
#define GPS
|
||||||
#define DISPLAY
|
#define DISPLAY
|
||||||
|
#define SERIAL_RX
|
||||||
#define TELEMETRY
|
#define TELEMETRY
|
||||||
#define LED_STRIP
|
#define LED_STRIP
|
||||||
#define USE_SERVOS
|
#define USE_SERVOS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue