mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-23 08:15:30 +03:00
First cut of CRSF RX and telemetry code
This commit is contained in:
parent
935547fe50
commit
890eab203b
18 changed files with 1290 additions and 4 deletions
|
@ -141,6 +141,15 @@ $(OBJECT_DIR)/common_filter_unittest : \
|
|||
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
||||
|
||||
|
||||
$(OBJECT_DIR)/common/streambuf.o : \
|
||||
$(USER_DIR)/common/streambuf.c \
|
||||
$(USER_DIR)/common/streambuf.h \
|
||||
$(GTEST_HEADERS)
|
||||
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -D'__TARGET__="TEST"' -D'__REVISION__="revision"' -c $(USER_DIR)/common/streambuf.c -o $@
|
||||
|
||||
|
||||
$(OBJECT_DIR)/drivers/io.o : \
|
||||
$(USER_DIR)/drivers/io.c \
|
||||
$(USER_DIR)/drivers/io.h \
|
||||
|
@ -149,6 +158,16 @@ $(OBJECT_DIR)/drivers/io.o : \
|
|||
@mkdir -p $(dir $@)
|
||||
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/drivers/io.c -o $@
|
||||
|
||||
|
||||
$(OBJECT_DIR)/fc/runtime_config.o : \
|
||||
$(USER_DIR)/fc/runtime_config.c \
|
||||
$(USER_DIR)/fc/runtime_config.h \
|
||||
$(GTEST_HEADERS)
|
||||
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -D'FLASH_SIZE = 128' -DSTM32F10X_MD -c $(USER_DIR)/fc/runtime_config.c -o $@
|
||||
|
||||
|
||||
$(OBJECT_DIR)/sensors/battery.o : $(USER_DIR)/sensors/battery.c $(USER_DIR)/sensors/battery.h $(GTEST_HEADERS)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/sensors/battery.c -o $@
|
||||
|
@ -471,6 +490,70 @@ $(OBJECT_DIR)/rx_rx_unittest : \
|
|||
|
||||
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
||||
|
||||
$(OBJECT_DIR)/telemetry/crsf.o : \
|
||||
$(USER_DIR)/telemetry/crsf.c \
|
||||
$(USER_DIR)/telemetry/crsf.h \
|
||||
$(USER_DIR)/rx/crsf.h \
|
||||
$(GTEST_HEADERS)
|
||||
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/telemetry/crsf.c -o $@
|
||||
|
||||
$(OBJECT_DIR)/telemetry_crsf_unittest.o : \
|
||||
$(TEST_DIR)/telemetry_crsf_unittest.cc \
|
||||
$(USER_DIR)/telemetry/crsf.h \
|
||||
$(USER_DIR)/telemetry/crsf.c \
|
||||
$(USER_DIR)/rx/crsf.c \
|
||||
$(USER_DIR)/rx/crsf.h \
|
||||
$(GTEST_HEADERS)
|
||||
|
||||
@mkdir -p $(dir $@)
|
||||
$(CXX) $(CXX_FLAGS) $(TEST_CFLAGS) -c $(TEST_DIR)/telemetry_crsf_unittest.cc -o $@
|
||||
|
||||
$(OBJECT_DIR)/telemetry_crsf_unittest : \
|
||||
$(OBJECT_DIR)/telemetry/crsf.o \
|
||||
$(OBJECT_DIR)/telemetry_crsf_unittest.o \
|
||||
$(OBJECT_DIR)/common/maths.o \
|
||||
$(OBJECT_DIR)/common/streambuf.o \
|
||||
$(OBJECT_DIR)/flight/gps_conversion.o \
|
||||
$(OBJECT_DIR)/fc/runtime_config.o \
|
||||
$(OBJECT_DIR)/gtest_main.a
|
||||
|
||||
$(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 : \
|
||||
$(TEST_DIR)/rx_ranges_unittest.cc \
|
||||
$(USER_DIR)/rx/rx.h \
|
||||
|
|
|
@ -52,6 +52,11 @@ typedef struct
|
|||
void *test;
|
||||
} GPIO_TypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* test;
|
||||
} TIM_TypeDef;
|
||||
|
||||
typedef struct {
|
||||
void* test;
|
||||
} DMA_Channel_TypeDef;
|
||||
|
|
99
src/test/unit/rx_crsf_unittest.cc
Normal file
99
src/test/unit/rx_crsf_unittest.cc
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* This file is part of Cleanflight.
|
||||
*
|
||||
* Cleanflight is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Cleanflight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <algorithm>
|
||||
|
||||
extern "C" {
|
||||
#include <platform.h>
|
||||
|
||||
#include "config/parameter_group.h"
|
||||
#include "config/parameter_group_ids.h"
|
||||
|
||||
#include "rx/rx.h"
|
||||
#include "fc/rc_controls.h"
|
||||
#include "common/maths.h"
|
||||
#include "common/utils.h"
|
||||
|
||||
}
|
||||
|
||||
#include "unittest_macros.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
// CRC8 implementation with polynom = x^8+x^7+x^6+x^4+x^2+1 (0xD5)
|
||||
unsigned char crc8tab[256] = {
|
||||
0x00, 0xD5, 0x7F, 0xAA, 0xFE, 0x2B, 0x81, 0x54, 0x29, 0xFC, 0x56, 0x83, 0xD7, 0x02, 0xA8, 0x7D,
|
||||
0x52, 0x87, 0x2D, 0xF8, 0xAC, 0x79, 0xD3, 0x06, 0x7B, 0xAE, 0x04, 0xD1, 0x85, 0x50, 0xFA, 0x2F,
|
||||
0xA4, 0x71, 0xDB, 0x0E, 0x5A, 0x8F, 0x25, 0xF0, 0x8D, 0x58, 0xF2, 0x27, 0x73, 0xA6, 0x0C, 0xD9,
|
||||
0xF6, 0x23, 0x89, 0x5C, 0x08, 0xDD, 0x77, 0xA2, 0xDF, 0x0A, 0xA0, 0x75, 0x21, 0xF4, 0x5E, 0x8B,
|
||||
0x9D, 0x48, 0xE2, 0x37, 0x63, 0xB6, 0x1C, 0xC9, 0xB4, 0x61, 0xCB, 0x1E, 0x4A, 0x9F, 0x35, 0xE0,
|
||||
0xCF, 0x1A, 0xB0, 0x65, 0x31, 0xE4, 0x4E, 0x9B, 0xE6, 0x33, 0x99, 0x4C, 0x18, 0xCD, 0x67, 0xB2,
|
||||
0x39, 0xEC, 0x46, 0x93, 0xC7, 0x12, 0xB8, 0x6D, 0x10, 0xC5, 0x6F, 0xBA, 0xEE, 0x3B, 0x91, 0x44,
|
||||
0x6B, 0xBE, 0x14, 0xC1, 0x95, 0x40, 0xEA, 0x3F, 0x42, 0x97, 0x3D, 0xE8, 0xBC, 0x69, 0xC3, 0x16,
|
||||
0xEF, 0x3A, 0x90, 0x45, 0x11, 0xC4, 0x6E, 0xBB, 0xC6, 0x13, 0xB9, 0x6C, 0x38, 0xED, 0x47, 0x92,
|
||||
0xBD, 0x68, 0xC2, 0x17, 0x43, 0x96, 0x3C, 0xE9, 0x94, 0x41, 0xEB, 0x3E, 0x6A, 0xBF, 0x15, 0xC0,
|
||||
0x4B, 0x9E, 0x34, 0xE1, 0xB5, 0x60, 0xCA, 0x1F, 0x62, 0xB7, 0x1D, 0xC8, 0x9C, 0x49, 0xE3, 0x36,
|
||||
0x19, 0xCC, 0x66, 0xB3, 0xE7, 0x32, 0x98, 0x4D, 0x30, 0xE5, 0x4F, 0x9A, 0xCE, 0x1B, 0xB1, 0x64,
|
||||
0x72, 0xA7, 0x0D, 0xD8, 0x8C, 0x59, 0xF3, 0x26, 0x5B, 0x8E, 0x24, 0xF1, 0xA5, 0x70, 0xDA, 0x0F,
|
||||
0x20, 0xF5, 0x5F, 0x8A, 0xDE, 0x0B, 0xA1, 0x74, 0x09, 0xDC, 0x76, 0xA3, 0xF7, 0x22, 0x88, 0x5D,
|
||||
0xD6, 0x03, 0xA9, 0x7C, 0x28, 0xFD, 0x57, 0x82, 0xFF, 0x2A, 0x80, 0x55, 0x01, 0xD4, 0x7E, 0xAB,
|
||||
0x84, 0x51, 0xFB, 0x2E, 0x7A, 0xAF, 0x05, 0xD0, 0xAD, 0x78, 0xD2, 0x07, 0x53, 0x86, 0x2C, 0xF9
|
||||
};
|
||||
|
||||
uint8_t crc8_buf(const uint8_t * ptr, uint8_t len)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
for (uint8_t i=0; i<len; i++) {
|
||||
crc = crc8tab[crc ^ *ptr++];
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint8_t crc8_dvb_s2_buf(const uint8_t * ptr, uint8_t len)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
for (uint8_t i=0; i<len; i++) {
|
||||
crc = crc8_dvb_s2(crc, *ptr++);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
TEST(CrossFireTest, CRC)
|
||||
{
|
||||
static const uint8_t buf1[] ="abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
uint8_t crc1 = 0;
|
||||
uint8_t crc2 = 0;
|
||||
|
||||
crc1 = crc8tab[1];
|
||||
crc2 = crc8_dvb_s2(0, 1);
|
||||
EXPECT_EQ(crc1, crc2);
|
||||
|
||||
crc1 = crc8tab[2];
|
||||
crc2 = crc8_dvb_s2(0, 2);
|
||||
EXPECT_EQ(crc1, crc2);
|
||||
|
||||
crc1 = crc8_buf(buf1, 26);
|
||||
crc2 = crc8_dvb_s2_buf(buf1, 26);
|
||||
EXPECT_EQ(crc1, crc2);
|
||||
}
|
||||
|
||||
// STUBS
|
||||
|
328
src/test/unit/telemetry_crsf_unittest.cc
Normal file
328
src/test/unit/telemetry_crsf_unittest.cc
Normal file
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* This file is part of Cleanflight.
|
||||
*
|
||||
* Cleanflight is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Cleanflight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
extern "C" {
|
||||
#include "build/debug.h"
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#include "common/axis.h"
|
||||
#include "common/filter.h"
|
||||
#include "common/maths.h"
|
||||
|
||||
#include "config/parameter_group.h"
|
||||
#include "config/parameter_group_ids.h"
|
||||
|
||||
#include "drivers/system.h"
|
||||
#include "drivers/serial.h"
|
||||
|
||||
#include "fc/runtime_config.h"
|
||||
|
||||
#include "io/gps.h"
|
||||
#include "io/serial.h"
|
||||
|
||||
#include "rx/crsf.h"
|
||||
|
||||
#include "sensors/sensors.h"
|
||||
#include "sensors/battery.h"
|
||||
|
||||
#include "telemetry/telemetry.h"
|
||||
#include "telemetry/crsf.h"
|
||||
|
||||
#include "flight/pid.h"
|
||||
#include "flight/imu.h"
|
||||
#include "flight/gps_conversion.h"
|
||||
|
||||
}
|
||||
|
||||
#include "unittest_macros.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
uint8_t crfsCrc(uint8_t *frame, int frameLen)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
for (int ii = 2; ii < frameLen - 1; ++ii) {
|
||||
crc = crc8_dvb_s2(crc, frame[ii]);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
/*
|
||||
int32_t Latitude ( degree / 10`000`000 )
|
||||
int32_t Longitude (degree / 10`000`000 )
|
||||
uint16_t Groundspeed ( km/h / 100 )
|
||||
uint16_t GPS heading ( degree / 100 )
|
||||
uint16 Altitude ( meter 1000m offset )
|
||||
uint8_t Satellites in use ( counter )
|
||||
uint8_t GPS_numSat;
|
||||
int32_t GPS_coord[2];
|
||||
uint16_t GPS_distanceToHome; // distance to home point in meters
|
||||
uint16_t GPS_altitude; // altitude in m
|
||||
uint16_t GPS_speed; // speed in 0.1m/s
|
||||
uint16_t GPS_ground_course = 0; // degrees * 10
|
||||
|
||||
*/
|
||||
TEST(TelemetryCrsfTest, TestGPS)
|
||||
{
|
||||
uint8_t frame[CRSF_FRAME_SIZE_MAX];
|
||||
|
||||
int frameLen = getCrsfFrame(frame, CRSF_FRAME_GPS);
|
||||
EXPECT_EQ(CRSF_FRAME_GPS_PAYLOAD_SIZE + 4, frameLen);
|
||||
EXPECT_EQ(CRSF_RECEIVER_ADDRESS, frame[0]); // address
|
||||
EXPECT_EQ(17, frame[1]); // length
|
||||
EXPECT_EQ(0x02, frame[2]); // type
|
||||
int32_t lattitude = frame[3] << 24 | frame[4] << 16 | frame[5] << 8 | frame[6];
|
||||
EXPECT_EQ(0, lattitude);
|
||||
int32_t longitude = frame[7] << 24 | frame[8] << 16 | frame[9] << 8 | frame[10];
|
||||
EXPECT_EQ(0, longitude);
|
||||
uint16_t groundSpeed = frame[11] << 8 | frame[12];
|
||||
EXPECT_EQ(0, groundSpeed);
|
||||
uint16_t GPSheading = frame[13] << 8 | frame[14];
|
||||
EXPECT_EQ(0, GPSheading);
|
||||
uint16_t altitude = frame[15] << 8 | frame[16];
|
||||
EXPECT_EQ(1000, altitude);
|
||||
uint8_t satelliteCount = frame[17];
|
||||
EXPECT_EQ(0, satelliteCount);
|
||||
EXPECT_EQ(crfsCrc(frame, frameLen), frame[18]);
|
||||
|
||||
GPS_coord[LAT] = 56 * GPS_DEGREES_DIVIDER;
|
||||
GPS_coord[LON] = 163 * GPS_DEGREES_DIVIDER;
|
||||
ENABLE_STATE(GPS_FIX);
|
||||
GPS_altitude = 2345; // altitude in m
|
||||
GPS_speed = 163; // speed in 0.1m/s, 16.3 m/s = 58.68 km/h
|
||||
GPS_numSat = 9;
|
||||
GPS_ground_course = 1479; // degrees * 10
|
||||
frameLen = getCrsfFrame(frame, CRSF_FRAME_GPS);
|
||||
lattitude = frame[3] << 24 | frame[4] << 16 | frame[5] << 8 | frame[6];
|
||||
EXPECT_EQ(560000000, lattitude);
|
||||
longitude = frame[7] << 24 | frame[8] << 16 | frame[9] << 8 | frame[10];
|
||||
EXPECT_EQ(1630000000, longitude);
|
||||
groundSpeed = frame[11] << 8 | frame[12];
|
||||
EXPECT_EQ(5868, groundSpeed);
|
||||
GPSheading = frame[13] << 8 | frame[14];
|
||||
EXPECT_EQ(14790, GPSheading);
|
||||
altitude = frame[15] << 8 | frame[16];
|
||||
EXPECT_EQ(3345, altitude);
|
||||
satelliteCount = frame[17];
|
||||
EXPECT_EQ(9, satelliteCount);
|
||||
EXPECT_EQ(crfsCrc(frame, frameLen), frame[18]);
|
||||
}
|
||||
|
||||
TEST(TelemetryCrsfTest, TestBattery)
|
||||
{
|
||||
uint8_t frame[CRSF_FRAME_SIZE_MAX];
|
||||
batteryConfig_t workingBatteryConfig;
|
||||
|
||||
batteryConfig = &workingBatteryConfig;
|
||||
memset(batteryConfig, 0, sizeof(batteryConfig_t));
|
||||
vbat = 0; // 0.1V units
|
||||
int frameLen = getCrsfFrame(frame, CRSF_FRAME_BATTERY_SENSOR);
|
||||
EXPECT_EQ(CRSF_FRAME_BATTERY_SENSOR_PAYLOAD_SIZE + 4, frameLen);
|
||||
EXPECT_EQ(CRSF_RECEIVER_ADDRESS, frame[0]); // address
|
||||
EXPECT_EQ(10, frame[1]); // length
|
||||
EXPECT_EQ(0x08, frame[2]); // type
|
||||
uint16_t voltage = frame[3] << 8 | frame[4]; // mV * 100
|
||||
EXPECT_EQ(0, voltage);
|
||||
uint16_t current = frame[5] << 8 | frame[6]; // mA * 100
|
||||
EXPECT_EQ(0, current);
|
||||
uint32_t capacity = frame[7] << 16 | frame[8] << 8 | frame [9]; // mAh
|
||||
EXPECT_EQ(0, capacity);
|
||||
uint16_t remaining = frame[10]; // percent
|
||||
EXPECT_EQ(67, remaining);
|
||||
EXPECT_EQ(crfsCrc(frame, frameLen), frame[11]);
|
||||
|
||||
vbat = 33; // 3.3V = 3300 mv
|
||||
amperage = 2960; // = 29.60A = 29600mA - amperage is in 0.01A steps
|
||||
batteryConfig->batteryCapacity = 1234;
|
||||
frameLen = getCrsfFrame(frame, CRSF_FRAME_BATTERY_SENSOR);
|
||||
voltage = frame[3] << 8 | frame[4]; // mV * 100
|
||||
EXPECT_EQ(33, voltage);
|
||||
current = frame[5] << 8 | frame[6]; // mA * 100
|
||||
EXPECT_EQ(296, current);
|
||||
capacity = frame[7] << 16 | frame[8] << 8 | frame [9]; // mAh
|
||||
EXPECT_EQ(1234, capacity);
|
||||
remaining = frame[10]; // percent
|
||||
EXPECT_EQ(67, remaining);
|
||||
EXPECT_EQ(crfsCrc(frame, frameLen), frame[11]);
|
||||
}
|
||||
|
||||
TEST(TelemetryCrsfTest, TestLinkStatistics)
|
||||
{
|
||||
uint8_t frame[CRSF_FRAME_SIZE_MAX];
|
||||
|
||||
int frameLen = getCrsfFrame(frame, CRSF_FRAME_LINK_STATISTICS);
|
||||
EXPECT_EQ(CRSF_FRAME_LINK_STATISTICS_PAYLOAD_SIZE + 4, frameLen);
|
||||
EXPECT_EQ(CRSF_RECEIVER_ADDRESS, frame[0]); // address
|
||||
EXPECT_EQ(12, frame[1]); // length
|
||||
EXPECT_EQ(0x14, frame[2]); // type
|
||||
EXPECT_EQ(crfsCrc(frame, frameLen), frame[13]);
|
||||
}
|
||||
|
||||
TEST(TelemetryCrsfTest, TestAttitude)
|
||||
{
|
||||
uint8_t frame[CRSF_FRAME_SIZE_MAX];
|
||||
|
||||
attitude.values.pitch = 0;
|
||||
attitude.values.roll = 0;
|
||||
attitude.values.yaw = 0;
|
||||
int frameLen = getCrsfFrame(frame, CRSF_FRAME_ATTITUDE);
|
||||
EXPECT_EQ(CRSF_FRAME_ATTITUDE_PAYLOAD_SIZE + 4, frameLen);
|
||||
EXPECT_EQ(CRSF_RECEIVER_ADDRESS, frame[0]); // address
|
||||
EXPECT_EQ(8, frame[1]); // length
|
||||
EXPECT_EQ(0x1e, frame[2]); // type
|
||||
int16_t pitch = frame[3] << 8 | frame[4]; // rad / 10000
|
||||
EXPECT_EQ(0, pitch);
|
||||
int16_t roll = frame[5] << 8 | frame[6];
|
||||
EXPECT_EQ(0, roll);
|
||||
int16_t yaw = frame[7] << 8 | frame[8];
|
||||
EXPECT_EQ(0, yaw);
|
||||
EXPECT_EQ(crfsCrc(frame, frameLen), frame[9]);
|
||||
|
||||
attitude.values.pitch = 678; // decidegrees == 1.183333232852155 rad
|
||||
attitude.values.roll = 1495; // 2.609267231731523 rad
|
||||
attitude.values.yaw = -1799; //3.139847324337799 rad
|
||||
frameLen = getCrsfFrame(frame, CRSF_FRAME_ATTITUDE);
|
||||
pitch = frame[3] << 8 | frame[4]; // rad / 10000
|
||||
EXPECT_EQ(11833, pitch);
|
||||
roll = frame[5] << 8 | frame[6];
|
||||
EXPECT_EQ(26092, roll);
|
||||
yaw = frame[7] << 8 | frame[8];
|
||||
EXPECT_EQ(-31398, yaw);
|
||||
EXPECT_EQ(crfsCrc(frame, frameLen), frame[9]);
|
||||
}
|
||||
|
||||
TEST(TelemetryCrsfTest, TestFlightMode)
|
||||
{
|
||||
uint8_t frame[CRSF_FRAME_SIZE_MAX];
|
||||
|
||||
int frameLen = getCrsfFrame(frame, CRSF_FRAME_FLIGHT_MODE);
|
||||
EXPECT_EQ(6 + 4, frameLen);
|
||||
enableFlightMode(ANGLE_MODE);
|
||||
EXPECT_EQ(1, FLIGHT_MODE(ANGLE_MODE));
|
||||
EXPECT_EQ(CRSF_RECEIVER_ADDRESS, frame[0]); // address
|
||||
EXPECT_EQ(8, frame[1]); // length
|
||||
EXPECT_EQ(0x21, frame[2]); // type
|
||||
EXPECT_EQ('A', frame[3]); // type
|
||||
EXPECT_EQ('n', frame[4]); // type
|
||||
EXPECT_EQ('g', frame[5]); // type
|
||||
EXPECT_EQ('l', frame[6]); // type
|
||||
EXPECT_EQ('e', frame[7]); // type
|
||||
EXPECT_EQ(0, frame[8]); // type
|
||||
EXPECT_EQ(crfsCrc(frame, frameLen), frame[9]);
|
||||
}
|
||||
|
||||
// STUBS
|
||||
|
||||
extern "C" {
|
||||
|
||||
int16_t debug[DEBUG16_VALUE_COUNT];
|
||||
|
||||
const uint32_t baudRates[] = {0, 9600, 19200, 38400, 57600, 115200, 230400, 250000, 400000}; // see baudRate_e
|
||||
|
||||
uint16_t batteryWarningVoltage;
|
||||
uint8_t useHottAlarmSoundPeriod (void) { return 0; }
|
||||
|
||||
attitudeEulerAngles_t attitude = { { 0, 0, 0 } }; // absolute angle inclination in multiple of 0.1 degree 180 deg = 1800
|
||||
|
||||
uint8_t GPS_numSat;
|
||||
int32_t GPS_coord[2];
|
||||
uint16_t GPS_distanceToHome; // distance to home point in meters
|
||||
uint16_t GPS_altitude; // altitude in m
|
||||
uint16_t GPS_speed; // speed in 0.1m/s
|
||||
uint16_t GPS_ground_course = 0; // degrees * 10
|
||||
uint16_t vbat;
|
||||
|
||||
int32_t amperage;
|
||||
int32_t mAhDrawn;
|
||||
|
||||
void beeperConfirmationBeeps(uint8_t beepCount) {UNUSED(beepCount);}
|
||||
|
||||
uint32_t serialRxBytesWaiting(const serialPort_t *instance) {
|
||||
UNUSED(instance);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t serialTxBytesFree(const serialPort_t *instance) {
|
||||
UNUSED(instance);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t serialRead(serialPort_t *instance) {
|
||||
UNUSED(instance);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serialWrite(serialPort_t *instance, uint8_t ch) {
|
||||
UNUSED(instance);
|
||||
UNUSED(ch);
|
||||
}
|
||||
void serialWriteBuf(serialPort_t *instance, const uint8_t *data, int count) {
|
||||
UNUSED(instance);
|
||||
UNUSED(data);
|
||||
UNUSED(count);
|
||||
}
|
||||
|
||||
void serialSetMode(serialPort_t *instance, portMode_t mode) {
|
||||
UNUSED(instance);
|
||||
UNUSED(mode);
|
||||
}
|
||||
|
||||
|
||||
serialPort_t *openSerialPort(serialPortIdentifier_e identifier, serialPortFunction_e functionMask, serialReceiveCallbackPtr callback, uint32_t baudRate, portMode_t mode, portOptions_t options) {
|
||||
UNUSED(identifier);
|
||||
UNUSED(functionMask);
|
||||
UNUSED(baudRate);
|
||||
UNUSED(callback);
|
||||
UNUSED(mode);
|
||||
UNUSED(options);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void closeSerialPort(serialPort_t *serialPort) {
|
||||
UNUSED(serialPort);
|
||||
}
|
||||
|
||||
serialPortConfig_t *findSerialPortConfig(serialPortFunction_e function) {
|
||||
UNUSED(function);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool telemetryDetermineEnabledState(portSharing_e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
portSharing_e determinePortSharing(serialPortConfig_t *, serialPortFunction_e) {
|
||||
return PORTSHARING_NOT_SHARED;
|
||||
}
|
||||
|
||||
uint8_t batteryCapacityRemainingPercentage(void) {return 67;}
|
||||
|
||||
uint8_t calculateBatteryCapacityRemainingPercentage(void) {return 67;}
|
||||
|
||||
batteryState_e getBatteryState(void) {
|
||||
return BATTERY_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue