Skip to content

Commit 996f9a8

Browse files
dakejahlAlexKlimaj
authored andcommitted
dshot: refactor telemetry to use serial abstraction
1 parent 6cf494d commit 996f9a8

File tree

2 files changed

+33
-172
lines changed

2 files changed

+33
-172
lines changed

src/drivers/dshot/DShotTelemetry.cpp

Lines changed: 30 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -46,75 +46,38 @@ using namespace time_literals;
4646

4747
DShotTelemetry::~DShotTelemetry()
4848
{
49-
deinit();
49+
_uart.close();
5050
}
5151

52-
int DShotTelemetry::init(const char *uart_device, bool swap_rxtx)
52+
int DShotTelemetry::init(const char *port, bool swap_rxtx)
5353
{
54-
int ret = OK;
55-
deinit();
56-
_uart_fd = ::open(uart_device, O_RDONLY | O_NOCTTY);
57-
58-
if (_uart_fd < 0) {
59-
PX4_ERR("failed to open serial port: %s err: %d", uart_device, errno);
60-
return -errno;
54+
if (!_uart.setPort(port)) {
55+
PX4_ERR("Error configuring port %s", port);
56+
return PX4_ERROR;
6157
}
6258

63-
ret = setBaudrate(DSHOT_TELEMETRY_UART_BAUDRATE);
64-
65-
if (ret) {
66-
PX4_ERR("failed to set baurate: %s err: %d", uart_device, ret);
67-
return ret;
59+
if (!_uart.setBaudrate(DSHOT_TELEMETRY_UART_BAUDRATE)) {
60+
PX4_ERR("Error setting baudrate on %s", port);
61+
return PX4_ERROR;
6862
}
6963

7064
if (swap_rxtx) {
71-
// Swap RX/TX pins if the device supports it
72-
ret = ioctl(_uart_fd, TIOCSSWAP, SER_SWAP_ENABLED);
73-
74-
// For other devices we can still place RX on TX pin via half-duplex single-wire mode
75-
if (ret) { ret = ioctl(_uart_fd, TIOCSSINGLEWIRE, SER_SINGLEWIRE_ENABLED); }
76-
77-
if (ret) {
78-
PX4_ERR("failed to swap rx/tx pins: %s err: %d", uart_device, ret);
79-
return ret;
65+
if (!_uart.setSwapRxTxMode()) {
66+
PX4_ERR("Error swapping TX/RX");
67+
return PX4_ERROR;
8068
}
8169
}
8270

83-
_num_timeouts = 0;
84-
_num_successful_responses = 0;
85-
_current_motor_index_request = -1;
86-
87-
return ret;
88-
}
89-
90-
void DShotTelemetry::deinit()
91-
{
92-
if (_uart_fd >= 0) {
93-
close(_uart_fd);
94-
_uart_fd = -1;
71+
if (! _uart.open()) {
72+
PX4_ERR("Error opening %s", port);
73+
return PX4_ERROR;
9574
}
96-
}
9775

98-
int DShotTelemetry::redirectOutput(OutputBuffer &buffer)
99-
{
100-
if (expectingData()) {
101-
// Error: cannot override while we already expect data
102-
return -EBUSY;
103-
}
104-
105-
_current_motor_index_request = buffer.motor_index;
106-
_current_request_start = hrt_absolute_time();
107-
_redirect_output = &buffer;
108-
_redirect_output->buf_pos = 0;
109-
return 0;
76+
return PX4_OK;
11077
}
11178

11279
int DShotTelemetry::update(int num_motors)
11380
{
114-
if (_uart_fd < 0) {
115-
return -1;
116-
}
117-
11881
if (_current_motor_index_request == -1) {
11982
// nothing in progress, start a request
12083
_current_motor_index_request = 0;
@@ -124,10 +87,9 @@ int DShotTelemetry::update(int num_motors)
12487
}
12588

12689
// read from the uart. This must be non-blocking, so check first if there is data available
127-
int bytes_available = 0;
128-
int ret = ioctl(_uart_fd, FIONREAD, (unsigned long)&bytes_available);
90+
int bytes_available = _uart.bytesAvailable();
12991

130-
if (ret != 0 || bytes_available <= 0) {
92+
if (bytes_available <= 0) {
13193
// no data available. Check for a timeout
13294
const hrt_abstime now = hrt_absolute_time();
13395

@@ -149,13 +111,12 @@ int DShotTelemetry::update(int num_motors)
149111
return -1;
150112
}
151113

152-
const int buf_length = ESC_FRAME_SIZE;
153-
uint8_t buf[buf_length];
114+
uint8_t buf[ESC_FRAME_SIZE];
115+
int bytes = _uart.read(buf, sizeof(buf));
154116

155-
int num_read = read(_uart_fd, buf, buf_length);
156-
ret = -1;
117+
int ret = -1;
157118

158-
for (int i = 0; i < num_read && ret == -1; ++i) {
119+
for (int i = 0; i < bytes && ret == -1; ++i) {
159120
if (_redirect_output) {
160121
_redirect_output->buffer[_redirect_output->buf_pos++] = buf[i];
161122

@@ -223,30 +184,27 @@ void DShotTelemetry::printStatus() const
223184
PX4_INFO("Number of CRC errors: %i", _num_checksum_errors);
224185
}
225186

226-
uint8_t DShotTelemetry::updateCrc8(uint8_t crc, uint8_t crc_seed)
187+
uint8_t DShotTelemetry::crc8(const uint8_t *buf, uint8_t len)
227188
{
228-
uint8_t crc_u = crc ^ crc_seed;
189+
auto update_crc8 = [](uint8_t crc, uint8_t crc_seed) {
190+
uint8_t crc_u = crc ^ crc_seed;
229191

230-
for (int i = 0; i < 8; ++i) {
231-
crc_u = (crc_u & 0x80) ? 0x7 ^ (crc_u << 1) : (crc_u << 1);
232-
}
233-
234-
return crc_u;
235-
}
192+
for (int i = 0; i < 8; ++i) {
193+
crc_u = (crc_u & 0x80) ? 0x7 ^ (crc_u << 1) : (crc_u << 1);
194+
}
236195

196+
return crc_u;
197+
};
237198

238-
uint8_t DShotTelemetry::crc8(const uint8_t *buf, uint8_t len)
239-
{
240199
uint8_t crc = 0;
241200

242201
for (int i = 0; i < len; ++i) {
243-
crc = updateCrc8(buf[i], crc);
202+
crc = update_crc8(buf[i], crc);
244203
}
245204

246205
return crc;
247206
}
248207

249-
250208
void DShotTelemetry::requestNextMotor(int num_motors)
251209
{
252210
_current_motor_index_request = (_current_motor_index_request + 1) % num_motors;
@@ -418,83 +376,4 @@ void DShotTelemetry::decodeAndPrintEscInfoPacket(const OutputBuffer &buffer)
418376
PX4_INFO("LED %d: %s", i, setting ? (setting == 255 ? "unsupported" : "on") : "off");
419377
}
420378
}
421-
422-
423-
}
424-
425-
int DShotTelemetry::setBaudrate(unsigned baud)
426-
{
427-
int speed;
428-
429-
switch (baud) {
430-
case 9600: speed = B9600; break;
431-
432-
case 19200: speed = B19200; break;
433-
434-
case 38400: speed = B38400; break;
435-
436-
case 57600: speed = B57600; break;
437-
438-
case 115200: speed = B115200; break;
439-
440-
case 230400: speed = B230400; break;
441-
442-
default:
443-
return -EINVAL;
444-
}
445-
446-
struct termios uart_config;
447-
448-
int termios_state;
449-
450-
/* fill the struct for the new configuration */
451-
tcgetattr(_uart_fd, &uart_config);
452-
453-
//
454-
// Input flags - Turn off input processing
455-
//
456-
// convert break to null byte, no CR to NL translation,
457-
// no NL to CR translation, don't mark parity errors or breaks
458-
// no input parity check, don't strip high bit off,
459-
// no XON/XOFF software flow control
460-
//
461-
uart_config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL |
462-
INLCR | PARMRK | INPCK | ISTRIP | IXON);
463-
//
464-
// Output flags - Turn off output processing
465-
//
466-
// no CR to NL translation, no NL to CR-NL translation,
467-
// no NL to CR translation, no column 0 CR suppression,
468-
// no Ctrl-D suppression, no fill characters, no case mapping,
469-
// no local output processing
470-
//
471-
// config.c_oflag &= ~(OCRNL | ONLCR | ONLRET |
472-
// ONOCR | ONOEOT| OFILL | OLCUC | OPOST);
473-
uart_config.c_oflag = 0;
474-
475-
//
476-
// No line processing
477-
//
478-
// echo off, echo newline off, canonical mode off,
479-
// extended input processing off, signal chars off
480-
//
481-
uart_config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
482-
483-
/* no parity, one stop bit, disable flow control */
484-
uart_config.c_cflag &= ~(CSTOPB | PARENB | CRTSCTS);
485-
486-
/* set baud rate */
487-
if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) {
488-
return -errno;
489-
}
490-
491-
if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) {
492-
return -errno;
493-
}
494-
495-
if ((termios_state = tcsetattr(_uart_fd, TCSANOW, &uart_config)) < 0) {
496-
return -errno;
497-
}
498-
499-
return 0;
500379
}

src/drivers/dshot/DShotTelemetry.h

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
#pragma once
3535

36+
#include <px4_platform_common/Serial.hpp>
3637
#include <drivers/drv_hrt.h>
3738

3839
class DShotTelemetry
@@ -62,25 +63,13 @@ class DShotTelemetry
6263

6364
int init(const char *uart_device, bool swap_rxtx);
6465

65-
void deinit();
66-
6766
/**
6867
* Read telemetry from the UART (non-blocking) and handle timeouts.
6968
* @param num_motors How many DShot enabled motors
7069
* @return -1 if no update, -2 timeout, >= 0 for the motor index. Use @latestESCData() to get the data.
7170
*/
7271
int update(int num_motors);
7372

74-
/**
75-
* Redirect everything that is read into a different buffer.
76-
* Future calls to @update will write to that instead of an internal buffer, until @update returns
77-
* a value different from -1. No decoding is done.
78-
* The caller must ensure the buffer exists until that point.
79-
* @param buffer
80-
* @return 0 on success <0 on error
81-
*/
82-
int redirectOutput(OutputBuffer &buffer);
83-
8473
bool redirectActive() const { return _redirect_output != nullptr; }
8574

8675
/**
@@ -103,13 +92,6 @@ class DShotTelemetry
10392
private:
10493
static constexpr int ESC_FRAME_SIZE = 10;
10594

106-
/**
107-
* set the Baudrate
108-
* @param baud
109-
* @return 0 on success, <0 on error
110-
*/
111-
int setBaudrate(unsigned baud);
112-
11395
void requestNextMotor(int num_motors);
11496

11597
/**
@@ -120,10 +102,10 @@ class DShotTelemetry
120102
*/
121103
bool decodeByte(uint8_t byte, bool &successful_decoding);
122104

123-
static inline uint8_t updateCrc8(uint8_t crc, uint8_t crc_seed);
124105
static uint8_t crc8(const uint8_t *buf, uint8_t len);
125106

126-
int _uart_fd{-1};
107+
device::Serial _uart {};
108+
127109
uint8_t _frame_buffer[ESC_FRAME_SIZE];
128110
int _frame_position{0};
129111

0 commit comments

Comments
 (0)