mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-03 06:28:27 -04:00
AP_RCProtocol: put back DSM VTX control and logging, add tests
This commit is contained in:
parent
c6e45dd536
commit
1f3c24d436
@ -17,12 +17,17 @@
|
||||
/*
|
||||
with thanks to PX4 dsm.c for DSM decoding approach
|
||||
*/
|
||||
#include <AP_Vehicle/AP_Vehicle_Type.h>
|
||||
#include "AP_RCProtocol_DSM.h"
|
||||
#if !APM_BUILD_TYPE(APM_BUILD_iofirmware)
|
||||
#include "AP_RCProtocol_SRXL2.h"
|
||||
#endif
|
||||
|
||||
extern const AP_HAL::HAL& hal;
|
||||
|
||||
// #define DSM_DEBUG
|
||||
#ifdef DSM_DEBUG
|
||||
#include <stdio.h>
|
||||
# define debug(fmt, args...) printf(fmt "\n", ##args)
|
||||
#else
|
||||
# define debug(fmt, args...) do {} while(0)
|
||||
@ -31,6 +36,18 @@ extern const AP_HAL::HAL& hal;
|
||||
|
||||
#define DSM_FRAME_SIZE 16 /**<DSM frame size in bytes*/
|
||||
#define DSM_FRAME_CHANNELS 7 /**<Max supported DSM channels*/
|
||||
#define SPEKTRUM_VTX_CONTROL_FRAME_MASK 0xf000f000
|
||||
#define SPEKTRUM_VTX_CONTROL_FRAME 0xe000e000
|
||||
|
||||
#define SPEKTRUM_VTX_BAND_MASK 0x00e00000
|
||||
#define SPEKTRUM_VTX_CHANNEL_MASK 0x000f0000
|
||||
#define SPEKTRUM_VTX_PIT_MODE_MASK 0x00000010
|
||||
#define SPEKTRUM_VTX_POWER_MASK 0x00000007
|
||||
|
||||
#define SPEKTRUM_VTX_BAND_SHIFT 21
|
||||
#define SPEKTRUM_VTX_CHANNEL_SHIFT 16
|
||||
#define SPEKTRUM_VTX_PIT_MODE_SHIFT 4
|
||||
#define SPEKTRUM_VTX_POWER_SHIFT 0
|
||||
|
||||
void AP_RCProtocol_DSM::process_pulse(uint32_t width_s0, uint32_t width_s1)
|
||||
{
|
||||
@ -87,7 +104,7 @@ bool AP_RCProtocol_DSM::dsm_decode_channel(uint16_t raw, unsigned shift, unsigne
|
||||
*
|
||||
* @param[in] reset true=reset the 10/11 bit state to unknown
|
||||
*/
|
||||
void AP_RCProtocol_DSM::dsm_guess_format(bool reset, const uint8_t dsm_frame[16])
|
||||
void AP_RCProtocol_DSM::dsm_guess_format(bool reset, const uint8_t dsm_frame[16], unsigned frame_channels)
|
||||
{
|
||||
/* reset the 10/11 bit sniffed channel masks */
|
||||
if (reset) {
|
||||
@ -99,18 +116,18 @@ void AP_RCProtocol_DSM::dsm_guess_format(bool reset, const uint8_t dsm_frame[16]
|
||||
}
|
||||
|
||||
/* scan the channels in the current dsm_frame in both 10- and 11-bit mode */
|
||||
for (unsigned i = 0; i < DSM_FRAME_CHANNELS; i++) {
|
||||
for (unsigned i = 0; i < frame_channels; i++) {
|
||||
|
||||
const uint8_t *dp = &dsm_frame[2 + (2 * i)];
|
||||
uint16_t raw = (dp[0] << 8) | dp[1];
|
||||
unsigned channel, value;
|
||||
|
||||
/* if the channel decodes, remember the assigned number */
|
||||
if (dsm_decode_channel(raw, 10, &channel, &value) && (channel < 31)) {
|
||||
if (dsm_decode_channel(raw, 10, &channel, &value) && (channel < 16)) {
|
||||
cs10 |= (1 << channel);
|
||||
}
|
||||
|
||||
if (dsm_decode_channel(raw, 11, &channel, &value) && (channel < 31)) {
|
||||
if (dsm_decode_channel(raw, 11, &channel, &value) && (channel < 16)) {
|
||||
cs11 |= (1 << channel);
|
||||
}
|
||||
|
||||
@ -134,15 +151,18 @@ void AP_RCProtocol_DSM::dsm_guess_format(bool reset, const uint8_t dsm_frame[16]
|
||||
* of this issue.
|
||||
*/
|
||||
static const uint32_t masks[] = {
|
||||
0x1f, /* 5 channels (DX6 VTX frame) */
|
||||
0x3f, /* 6 channels (DX6) */
|
||||
0x7f, /* 7 channels (DX7) */
|
||||
0xff, /* 8 channels (DX8) */
|
||||
0x1ff, /* 9 channels (DX9, etc.) */
|
||||
0x3ff, /* 10 channels (DX10) */
|
||||
0x7ff, /* 11 channels DX8 22ms */
|
||||
0xfff, /* 12 channels DX8 22ms */
|
||||
0x1fff, /* 13 channels (DX10t) */
|
||||
0x3fff /* 18 channels (DX10) */
|
||||
0x7ff, /* 11 channels */
|
||||
0xfff, /* 12 channels */
|
||||
0x1fff, /* 13 channels */
|
||||
0x3fff, /* 14 channels */
|
||||
0x7fff, /* 15 channels */
|
||||
0xffff /* 16 channels */ // the remote receiver protocol supports max 16 channels
|
||||
};
|
||||
unsigned votes10 = 0;
|
||||
unsigned votes11 = 0;
|
||||
@ -172,7 +192,7 @@ void AP_RCProtocol_DSM::dsm_guess_format(bool reset, const uint8_t dsm_frame[16]
|
||||
|
||||
/* call ourselves to reset our state ... we have to try again */
|
||||
debug("DSM: format detect fail, 10: 0x%08x %u 11: 0x%08x %u", cs10, votes10, cs11, votes11);
|
||||
dsm_guess_format(true, dsm_frame);
|
||||
dsm_guess_format(true, dsm_frame, frame_channels);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,18 +207,44 @@ bool AP_RCProtocol_DSM::dsm_decode(uint32_t frame_time_ms, const uint8_t dsm_fra
|
||||
* format guessing heuristic.
|
||||
*/
|
||||
if (((frame_time_ms - last_frame_time_ms) > 200U) && (channel_shift != 0)) {
|
||||
dsm_guess_format(true, dsm_frame);
|
||||
dsm_guess_format(true, dsm_frame, DSM_FRAME_CHANNELS);
|
||||
}
|
||||
|
||||
/* we have received something we think is a dsm_frame */
|
||||
last_frame_time_ms = frame_time_ms;
|
||||
|
||||
// Get the VTX control bytes in a frame
|
||||
uint32_t vtxControl = ((dsm_frame[DSM_FRAME_SIZE-4] << 24)
|
||||
| (dsm_frame[DSM_FRAME_SIZE-3] << 16)
|
||||
| (dsm_frame[DSM_FRAME_SIZE-2] << 8)
|
||||
| (dsm_frame[DSM_FRAME_SIZE-1] << 0));
|
||||
const bool haveVtxControl =
|
||||
((vtxControl & SPEKTRUM_VTX_CONTROL_FRAME_MASK) == SPEKTRUM_VTX_CONTROL_FRAME &&
|
||||
(dsm_frame[2] & 0x80) == 0);
|
||||
|
||||
unsigned frame_channels = DSM_FRAME_CHANNELS;
|
||||
// Handle VTX control frame.
|
||||
if (haveVtxControl) {
|
||||
frame_channels = DSM_FRAME_CHANNELS - 2;
|
||||
}
|
||||
|
||||
/* if we don't know the dsm_frame format, update the guessing state machine */
|
||||
if (channel_shift == 0) {
|
||||
dsm_guess_format(false, dsm_frame);
|
||||
dsm_guess_format(false, dsm_frame, frame_channels);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle VTX control frame.
|
||||
if (haveVtxControl) {
|
||||
#if !APM_BUILD_TYPE(APM_BUILD_iofirmware)
|
||||
AP_RCProtocol_SRXL2::configure_vtx(
|
||||
(vtxControl & SPEKTRUM_VTX_BAND_MASK) >> SPEKTRUM_VTX_BAND_SHIFT,
|
||||
(vtxControl & SPEKTRUM_VTX_CHANNEL_MASK) >> SPEKTRUM_VTX_CHANNEL_SHIFT,
|
||||
(vtxControl & SPEKTRUM_VTX_POWER_MASK) >> SPEKTRUM_VTX_POWER_SHIFT,
|
||||
(vtxControl & SPEKTRUM_VTX_PIT_MODE_MASK) >> SPEKTRUM_VTX_PIT_MODE_SHIFT);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The encoding of the first two bytes is uncertain, so we're
|
||||
* going to ignore them for now.
|
||||
@ -210,7 +256,7 @@ bool AP_RCProtocol_DSM::dsm_decode(uint32_t frame_time_ms, const uint8_t dsm_fra
|
||||
* seven channels are being transmitted.
|
||||
*/
|
||||
|
||||
for (unsigned i = 0; i < DSM_FRAME_CHANNELS; i++) {
|
||||
for (unsigned i = 0; i < frame_channels; i++) {
|
||||
|
||||
const uint8_t *dp = &dsm_frame[2 + (2 * i)];
|
||||
uint16_t raw = (dp[0] << 8) | dp[1];
|
||||
@ -431,6 +477,8 @@ bool AP_RCProtocol_DSM::dsm_parse_byte(uint32_t frame_time_ms, uint8_t b, uint16
|
||||
* Great, it looks like we might have a frame. Go ahead and
|
||||
* decode it.
|
||||
*/
|
||||
log_data(AP_RCProtocol::DSM, frame_time_ms * 1000, byte_input.buf, byte_input.ofs);
|
||||
|
||||
decode_ret = dsm_decode(frame_time_ms, byte_input.buf, values, &chan_count, max_channels);
|
||||
|
||||
/* we consumed the partial frame, reset */
|
||||
|
@ -34,7 +34,7 @@ private:
|
||||
void _process_byte(uint32_t timestamp_ms, uint8_t byte);
|
||||
void dsm_decode();
|
||||
bool dsm_decode_channel(uint16_t raw, unsigned shift, unsigned *channel, unsigned *value);
|
||||
void dsm_guess_format(bool reset, const uint8_t dsm_frame[16]);
|
||||
void dsm_guess_format(bool reset, const uint8_t dsm_frame[16], unsigned frame_channels);
|
||||
bool dsm_parse_byte(uint32_t frame_time_ms, uint8_t b, uint16_t *values,
|
||||
uint16_t *num_values, uint16_t max_channels);
|
||||
bool dsm_decode(uint32_t frame_time_ms, const uint8_t dsm_frame[16],
|
||||
|
@ -75,12 +75,12 @@ static bool test_byte_protocol(const char *name, uint32_t baudrate,
|
||||
const uint8_t *bytes, uint8_t nbytes,
|
||||
const uint16_t *values, uint8_t nvalues,
|
||||
uint8_t repeats,
|
||||
int8_t pause_at)
|
||||
uint8_t pause_at)
|
||||
{
|
||||
bool ret = true;
|
||||
for (uint8_t repeat=0; repeat<repeats+4; repeat++) {
|
||||
for (uint8_t i=0; i<nbytes; i++) {
|
||||
if (pause_at >= 0 && i == pause_at) {
|
||||
if (pause_at > 0 && i > 0 && ((i % pause_at) == 0)) {
|
||||
hal.scheduler->delay(10);
|
||||
}
|
||||
rcprot->process_byte(bytes[i], baudrate);
|
||||
@ -157,13 +157,13 @@ static void send_pause(uint8_t b, uint32_t baudrate, uint32_t pause_us)
|
||||
static bool test_pulse_protocol(const char *name, uint32_t baudrate,
|
||||
const uint8_t *bytes, uint8_t nbytes,
|
||||
const uint16_t *values, uint8_t nvalues,
|
||||
uint8_t repeats, int8_t pause_at)
|
||||
uint8_t repeats, uint8_t pause_at)
|
||||
{
|
||||
bool ret = true;
|
||||
for (uint8_t repeat=0; repeat<repeats+4; repeat++) {
|
||||
send_pause(1, baudrate, 6000);
|
||||
for (uint8_t i=0; i<nbytes; i++) {
|
||||
if (pause_at >= 0 && i == pause_at) {
|
||||
if (pause_at > 0 && i > 0 && ((i % pause_at) == 0)) {
|
||||
send_pause(1, baudrate, 10000);
|
||||
}
|
||||
send_byte(bytes[i], baudrate);
|
||||
@ -248,6 +248,55 @@ void loop()
|
||||
|
||||
const uint16_t dsm_output5[] = {1498, 1496, 999, 1497, 1901, 1901, 1099};
|
||||
|
||||
// DSMX 22ms D6G3 and SPM4648 autobound
|
||||
const uint8_t dsmx22ms_bytes[] = {
|
||||
0x00, 0xB2, 0x0C, 0x00, 0x29, 0x56, 0x14, 0x00,
|
||||
0x25, 0xF8, 0x34, 0x00, 0x54, 0x00, 0xFF, 0xFF,
|
||||
0x00, 0xB2, 0x81, 0x50, 0x3C, 0x00, 0x1B, 0xFD,
|
||||
0x44, 0x00, 0x4C, 0x00, 0x5C, 0x00, 0xFF, 0xFF
|
||||
};
|
||||
const uint16_t dsmx22ms_output[] = {
|
||||
1500, 1500, 1096, 1499, 1796, 1099, 1500, 1500, 1500, 1500, 1500, 1500
|
||||
};
|
||||
|
||||
// DSMX 22ms D6G3 and SPM4648 autobound VTX frame Ch1, B1, Pw25, Race
|
||||
const uint8_t dsmx22ms_vtx_bytes[] = {
|
||||
// two normal frames to satisfy the format guesser
|
||||
0x00, 0xB2, 0x0C, 0x00, 0x29, 0x56, 0x14, 0x00,
|
||||
0x25, 0xF8, 0x34, 0x00, 0x54, 0x00, 0xFF, 0xFF,
|
||||
0x00, 0xB2, 0x81, 0x50, 0x3C, 0x00, 0x1B, 0xFD,
|
||||
0x44, 0x00, 0x4C, 0x00, 0x5C, 0x00, 0xFF, 0xFF,
|
||||
// This is channels 1, 5, 2, 4, 6
|
||||
0x00, 0xB2, 0x0C, 0x00, 0x29, 0x56, 0x14, 0x00,
|
||||
0x25, 0xF8, 0x34, 0x00, 0xE0, 0x00, 0xE0, 0x0A
|
||||
};
|
||||
const uint16_t dsmx22ms_vtx_output[] = {
|
||||
1500, 1500, 1096, 1499, 1796, 1099, 1500, 1500, 1500, 1500, 1500, 1500
|
||||
};
|
||||
// DSMX 11ms D6G3 and SPM4648 autobound
|
||||
const uint8_t dsmx11ms_bytes[] = {
|
||||
0x01, 0xB2, 0x0C, 0x00, 0x29, 0x56, 0x14, 0x00,
|
||||
0x1B, 0xFC, 0x25, 0xF8, 0x44, 0x00, 0x4C, 0x00,
|
||||
0x01, 0xB2, 0x8C, 0x00, 0x29, 0x56, 0x14, 0x00,
|
||||
0x1B, 0xFC, 0x01, 0x50, 0x3C, 0x00, 0x34, 0x00
|
||||
};
|
||||
const uint16_t dsmx11ms_output[] = {
|
||||
1500, 1500, 1096, 1498, 1796, 1099, 1500, 1500, 1500, 1500
|
||||
};
|
||||
|
||||
// DSMX 11ms D6G3 and SPM4648 autobound VTX frame Ch1, B1, Pw25, Race
|
||||
const uint8_t dsmx11ms_vtx_bytes[] = {
|
||||
0x01, 0xB2, 0x0C, 0x00, 0x29, 0x56, 0x14, 0x00,
|
||||
0x1B, 0xFD, 0x25, 0xF8, 0x44, 0x00, 0x4C, 0x00,
|
||||
0x01, 0xB2, 0x8C, 0x00, 0x29, 0x56, 0x14, 0x00,
|
||||
0x1B, 0xFD, 0x01, 0x50, 0x3C, 0x00, 0x34, 0x00,
|
||||
0x00, 0xB2, 0x0C, 0x00, 0x29, 0x56, 0x14, 0x00,
|
||||
0x1B, 0xFD, 0x25, 0xF8, 0xE0, 0x00, 0xE0, 0x0A
|
||||
};
|
||||
const uint16_t dsmx11ms_vtx_output[] = {
|
||||
1500, 1500, 1096, 1499, 1796, 1099, 1500, 1500, 1500, 1500
|
||||
};
|
||||
|
||||
const uint8_t sumd_bytes[] = {0xA8, 0x01, 0x08, 0x2F, 0x50, 0x31, 0xE8, 0x21, 0xA0,
|
||||
0x2F, 0x50, 0x22, 0x60, 0x22, 0x60, 0x2E, 0xE0, 0x2E,
|
||||
0xE0, 0x87, 0xC6};
|
||||
@ -282,6 +331,10 @@ void loop()
|
||||
test_protocol("DSM3", 115200, dsm_bytes3, sizeof(dsm_bytes3), dsm_output3, ARRAY_SIZE(dsm_output3), 9, 16);
|
||||
test_protocol("DSM4", 115200, dsm_bytes4, sizeof(dsm_bytes4), dsm_output4, ARRAY_SIZE(dsm_output4), 9, 16);
|
||||
test_protocol("DSM5", 115200, dsm_bytes5, sizeof(dsm_bytes5), dsm_output5, ARRAY_SIZE(dsm_output5), 9);
|
||||
test_protocol("DSMX22", 115200, dsmx22ms_bytes, sizeof(dsmx22ms_bytes), dsmx22ms_output, ARRAY_SIZE(dsmx22ms_output), 9, 16);
|
||||
test_protocol("DSMX22_VTX", 115200, dsmx22ms_vtx_bytes, sizeof(dsmx22ms_vtx_bytes), dsmx22ms_vtx_output, ARRAY_SIZE(dsmx22ms_vtx_output), 9, 16);
|
||||
test_protocol("DSMX11", 115200, dsmx11ms_bytes, sizeof(dsmx11ms_bytes), dsmx11ms_output, ARRAY_SIZE(dsmx11ms_output), 9, 16);
|
||||
test_protocol("DSMX11_VTX", 115200, dsmx11ms_vtx_bytes, sizeof(dsmx11ms_vtx_bytes), dsmx11ms_vtx_output, ARRAY_SIZE(dsmx11ms_vtx_output), 9, 16);
|
||||
}
|
||||
|
||||
AP_HAL_MAIN();
|
||||
|
Loading…
Reference in New Issue
Block a user