...restructure for rework

This commit is contained in:
Wastl Kraus 2022-11-26 13:52:46 +01:00
parent 85814f39be
commit 873b228d59
5 changed files with 254 additions and 276 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
.vs
.vscode
.vscode/* .vscode/*
!.vscode/settings.json !.vscode/settings.json
!.vscode/tasks.json !.vscode/tasks.json
@ -12,4 +14,4 @@
*.vsix *.vsix
# Caching ESP32 Builds # Caching ESP32 Builds
buildCache/* buildCache

View File

@ -16,34 +16,34 @@ constexpr auto FAILSAVE_THROTTLE = 0x3E7;
void setup() void setup()
{ {
// ...always start the onboard usb support // ...always start the onboard usb support
USB_Serial.begin(USB_SERIAL_BAUD); USB_Serial.begin(USB_SERIAL_BAUD);
// ...start the dshot generation // ...start the dshot generation
dshot_01.begin(DSHOT300); dshot_01.begin(DSHOT300);
} }
void loop() void loop()
{ {
read_SerialThrottle(); read_SerialThrottle();
dshot_01.send_dshot_value(throttle_value); dshot_01.send_dshot_value(throttle_value);
// ...print to console // ...print to console
USB_Serial.println(throttle_value); USB_Serial.println(throttle_value);
} }
// //
// //
uint16_t read_SerialThrottle() uint16_t read_SerialThrottle()
{ {
if (USB_Serial.available() > 0) if (USB_Serial.available() > 0)
{ {
auto throttle_input = (USB_Serial.readStringUntil('\n')).toInt(); auto throttle_input = (USB_Serial.readStringUntil('\n')).toInt();
return throttle_input; return throttle_input;
} }
else else
{ {
return FAILSAVE_THROTTLE; return FAILSAVE_THROTTLE;
} }
} }

View File

@ -1,32 +0,0 @@
#pragma once
// Source: https://github.com/bitdump/BLHeli/blob/master/BLHeli_S%20SiLabs/Dshotprog%20spec%20BLHeli_S.txt
// Date: 04.07.2021
enum dshot_cmd_t
{
DSHOT_CMD_MOTOR_STOP, // Currently not implemented - STOP Motors
DSHOT_CMD_BEEP1, // Wait at least length of beep (380ms) before next command
DSHOT_CMD_BEEP2, // Wait at least length of beep (380ms) before next command
DSHOT_CMD_BEEP3, // Wait at least length of beep (400ms) before next command
DSHOT_CMD_BEEP4, // Wait at least length of beep (400ms) before next command
DSHOT_CMD_BEEP5, // Wait at least length of beep (400ms) before next command
DSHOT_CMD_ESC_INFO, // Currently not implemented
DSHOT_CMD_SPIN_DIRECTION_1, // Need 6x, no wait required
DSHOT_CMD_SPIN_DIRECTION_2, // Need 6x, no wait required
DSHOT_CMD_3D_MODE_OFF, // Need 6x, no wait required
DSHOT_CMD_3D_MODE_ON, // Need 6x, no wait required
DSHOT_CMD_SETTINGS_REQUEST, // Currently not implemented
DSHOT_CMD_SAVE_SETTINGS, // Need 6x, wait at least 12ms before next command
DSHOT_CMD_SPIN_DIRECTION_NORMAL, // Need 6x, no wait required
DSHOT_CMD_SPIN_DIRECTION_REVERSED, // Need 6x, no wait required
DSHOT_CMD_LED0_ON, // Currently not implemented
DSHOT_CMD_LED1_ON, // Currently not implemented
DSHOT_CMD_LED2_ON, // Currently not implemented
DSHOT_CMD_LED3_ON, // Currently not implemented
DSHOT_CMD_LED0_OFF, // Currently not implemented
DSHOT_CMD_LED1_OFF, // Currently not implemented
DSHOT_CMD_LED2_OFF, // Currently not implemented
DSHOT_CMD_LED3_OFF, // Currently not implemented
DSHOT_CMD_MAX = 47
};

View File

@ -8,250 +8,250 @@
DShotRMT::DShotRMT(gpio_num_t gpio, rmt_channel_t rmtChannel) DShotRMT::DShotRMT(gpio_num_t gpio, rmt_channel_t rmtChannel)
{ {
dshot_config.gpio_num = gpio; dshot_config.gpio_num = gpio;
dshot_config.pin_num = uint8_t(gpio); dshot_config.pin_num = uint8_t(gpio);
dshot_config.rmt_channel = rmtChannel; dshot_config.rmt_channel = rmtChannel;
dshot_config.mem_block_num = uint8_t(RMT_CHANNEL_MAX - uint8_t(rmtChannel)); dshot_config.mem_block_num = uint8_t(RMT_CHANNEL_MAX - uint8_t(rmtChannel));
// ...create clean packet // ...create clean packet
encode_dshot_to_rmt(DSHOT_NULL_PACKET); encode_dshot_to_rmt(DSHOT_NULL_PACKET);
} }
DShotRMT::DShotRMT(uint8_t pin, uint8_t channel) DShotRMT::DShotRMT(uint8_t pin, uint8_t channel)
{ {
dshot_config.gpio_num = gpio_num_t(pin); dshot_config.gpio_num = gpio_num_t(pin);
dshot_config.pin_num = pin; dshot_config.pin_num = pin;
dshot_config.rmt_channel = rmt_channel_t(channel); dshot_config.rmt_channel = rmt_channel_t(channel);
dshot_config.mem_block_num = (RMT_CHANNEL_MAX - channel); dshot_config.mem_block_num = (RMT_CHANNEL_MAX - channel);
// ...create clean packet // ...create clean packet
encode_dshot_to_rmt(DSHOT_NULL_PACKET); encode_dshot_to_rmt(DSHOT_NULL_PACKET);
} }
DShotRMT::~DShotRMT() DShotRMT::~DShotRMT()
{ {
rmt_driver_uninstall(dshot_config.rmt_channel); rmt_driver_uninstall(dshot_config.rmt_channel);
} }
DShotRMT::DShotRMT(DShotRMT const &) DShotRMT::DShotRMT(DShotRMT const&)
{ {
// ...write me // ...write me
} }
bool DShotRMT::begin(dshot_mode_t dshot_mode, bool is_bidirectional) bool DShotRMT::begin(dshot_mode_t dshot_mode, bool is_bidirectional)
{ {
dshot_config.mode = dshot_mode; dshot_config.mode = dshot_mode;
dshot_config.clk_div = DSHOT_CLK_DIVIDER; dshot_config.clk_div = DSHOT_CLK_DIVIDER;
dshot_config.name_str = dshot_mode_name[dshot_mode]; dshot_config.name_str = dshot_mode_name[dshot_mode];
dshot_config.bidirectional = is_bidirectional; dshot_config.bidirectional = is_bidirectional;
switch (dshot_config.mode) switch (dshot_config.mode)
{ {
case DSHOT150: case DSHOT150:
dshot_config.ticks_per_bit = 64; // ...Bit Period Time 6.67 us dshot_config.ticks_per_bit = 64; // ...Bit Period Time 6.67 us
dshot_config.ticks_zero_high = 24; // ...zero time 2.50 us dshot_config.ticks_zero_high = 24; // ...zero time 2.50 us
dshot_config.ticks_one_high = 48; // ...one time 5.00 us dshot_config.ticks_one_high = 48; // ...one time 5.00 us
break; break;
case DSHOT300: case DSHOT300:
dshot_config.ticks_per_bit = 32; // ...Bit Period Time 3.33 us dshot_config.ticks_per_bit = 32; // ...Bit Period Time 3.33 us
dshot_config.ticks_zero_high = 12; // ...zero time 1.25 us dshot_config.ticks_zero_high = 12; // ...zero time 1.25 us
dshot_config.ticks_one_high = 24; // ...one time 2.50 us dshot_config.ticks_one_high = 24; // ...one time 2.50 us
break; break;
case DSHOT600: case DSHOT600:
dshot_config.ticks_per_bit = 16; // ...Bit Period Time 1.67 us dshot_config.ticks_per_bit = 16; // ...Bit Period Time 1.67 us
dshot_config.ticks_zero_high = 6; // ...zero time 0.625 us dshot_config.ticks_zero_high = 6; // ...zero time 0.625 us
dshot_config.ticks_one_high = 12; // ...one time 1.25 us dshot_config.ticks_one_high = 12; // ...one time 1.25 us
break; break;
case DSHOT1200: case DSHOT1200:
dshot_config.ticks_per_bit = 8; // ...Bit Period Time 0.83 us dshot_config.ticks_per_bit = 8; // ...Bit Period Time 0.83 us
dshot_config.ticks_zero_high = 3; // ...zero time 0.313 us dshot_config.ticks_zero_high = 3; // ...zero time 0.313 us
dshot_config.ticks_one_high = 6; // ...one time 0.625 us dshot_config.ticks_one_high = 6; // ...one time 0.625 us
break; break;
// ...because having a default is "good style" // ...because having a default is "good style"
default: default:
dshot_config.ticks_per_bit = 0; // ...Bit Period Time endless dshot_config.ticks_per_bit = 0; // ...Bit Period Time endless
dshot_config.ticks_zero_high = 0; // ...no bits, no time dshot_config.ticks_zero_high = 0; // ...no bits, no time
dshot_config.ticks_one_high = 0; // ......no bits, no time dshot_config.ticks_one_high = 0; // ......no bits, no time
break; break;
} }
// ...calc low signal timing // ...calc low signal timing
dshot_config.ticks_zero_low = (dshot_config.ticks_per_bit - dshot_config.ticks_zero_high); dshot_config.ticks_zero_low = (dshot_config.ticks_per_bit - dshot_config.ticks_zero_high);
dshot_config.ticks_one_low = (dshot_config.ticks_per_bit - dshot_config.ticks_one_high); dshot_config.ticks_one_low = (dshot_config.ticks_per_bit - dshot_config.ticks_one_high);
dshot_tx_rmt_config.rmt_mode = RMT_MODE_TX; dshot_tx_rmt_config.rmt_mode = RMT_MODE_TX;
dshot_tx_rmt_config.channel = dshot_config.rmt_channel; dshot_tx_rmt_config.channel = dshot_config.rmt_channel;
dshot_tx_rmt_config.gpio_num = dshot_config.gpio_num; dshot_tx_rmt_config.gpio_num = dshot_config.gpio_num;
dshot_tx_rmt_config.mem_block_num = dshot_config.mem_block_num; dshot_tx_rmt_config.mem_block_num = dshot_config.mem_block_num;
dshot_tx_rmt_config.clk_div = dshot_config.clk_div; dshot_tx_rmt_config.clk_div = dshot_config.clk_div;
dshot_tx_rmt_config.tx_config.loop_en = false; dshot_tx_rmt_config.tx_config.loop_en = false;
dshot_tx_rmt_config.tx_config.carrier_en = false; dshot_tx_rmt_config.tx_config.carrier_en = false;
dshot_tx_rmt_config.tx_config.idle_output_en = true; dshot_tx_rmt_config.tx_config.idle_output_en = true;
if (dshot_config.bidirectional) if (dshot_config.bidirectional)
{ {
dshot_tx_rmt_config.tx_config.idle_level = RMT_IDLE_LEVEL_HIGH; dshot_tx_rmt_config.tx_config.idle_level = RMT_IDLE_LEVEL_HIGH;
} }
else else
{ {
dshot_tx_rmt_config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW; dshot_tx_rmt_config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
} }
// ...setup selected dshot mode // ...setup selected dshot mode
rmt_config(&dshot_tx_rmt_config); rmt_config(&dshot_tx_rmt_config);
// ...essential step, return the result // ...essential step, return the result
return rmt_driver_install(dshot_tx_rmt_config.channel, 0, 0); return rmt_driver_install(dshot_tx_rmt_config.channel, 0, 0);
} }
// ...the config part is done, now the calculating and sending part // ...the config part is done, now the calculating and sending part
void DShotRMT::send_dshot_value(uint16_t throttle_value, telemetric_request_t telemetric_request) void DShotRMT::send_dshot_value(uint16_t throttle_value, telemetric_request_t telemetric_request)
{ {
dshot_packet_t dshot_rmt_packet = {}; dshot_packet_t dshot_rmt_packet = {};
if (throttle_value < DSHOT_THROTTLE_MIN) if (throttle_value < DSHOT_THROTTLE_MIN)
{ {
throttle_value = DSHOT_THROTTLE_MIN; throttle_value = DSHOT_THROTTLE_MIN;
} }
if (throttle_value > DSHOT_THROTTLE_MAX) if (throttle_value > DSHOT_THROTTLE_MAX)
{ {
throttle_value = DSHOT_THROTTLE_MAX; throttle_value = DSHOT_THROTTLE_MAX;
} }
// ...packets are the same for bidirectional mode // ...packets are the same for bidirectional mode
dshot_rmt_packet.throttle_value = throttle_value; dshot_rmt_packet.throttle_value = throttle_value;
dshot_rmt_packet.telemetric_request = telemetric_request; dshot_rmt_packet.telemetric_request = telemetric_request;
dshot_rmt_packet.checksum = this->calc_dshot_chksum(dshot_rmt_packet); dshot_rmt_packet.checksum = this->calc_dshot_chksum(dshot_rmt_packet);
output_rmt_data(dshot_rmt_packet); output_rmt_data(dshot_rmt_packet);
} }
// ...get all setup data about current mode // ...get all setup data about current mode
dshot_config_t *DShotRMT::get_dshot_info() dshot_config_t* DShotRMT::get_dshot_info()
{ {
return &dshot_config; return &dshot_config;
} }
// ...get the ABP_Clock Divider for further calculations // ...get the ABP_Clock Divider for further calculations
uint8_t *DShotRMT::get_dshot_clock_div() uint8_t* DShotRMT::get_dshot_clock_div()
{ {
return &dshot_config.clk_div; return &dshot_config.clk_div;
} }
rmt_item32_t *DShotRMT::encode_dshot_to_rmt(uint16_t parsed_packet) rmt_item32_t* DShotRMT::encode_dshot_to_rmt(uint16_t parsed_packet)
{ {
// ...is bidirecional mode activated // ...is bidirecional mode activated
if (dshot_config.bidirectional) if (dshot_config.bidirectional)
{ {
// ..."invert" the signal duration // ..."invert" the signal duration
for (int i = 0; i < DSHOT_PAUSE_BIT; i++, parsed_packet <<= 1) for (int i = 0; i < DSHOT_PAUSE_BIT; i++, parsed_packet <<= 1)
{ {
if (parsed_packet & 0b1000000000000000) if (parsed_packet & 0b1000000000000000)
{ {
// set one // set one
dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_one_low; dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_one_low;
dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_one_high; dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_one_high;
} }
else else
{ {
// set zero // set zero
dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_zero_low; dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_zero_low;
dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_zero_high; dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_zero_high;
} }
dshot_tx_rmt_item[i].level0 = 0; dshot_tx_rmt_item[i].level0 = 0;
dshot_tx_rmt_item[i].level1 = 1; dshot_tx_rmt_item[i].level1 = 1;
} }
} }
// ..."normal" DShot mode / "bidirectional" mode OFF // ..."normal" DShot mode / "bidirectional" mode OFF
else else
{ {
for (int i = 0; i < DSHOT_PAUSE_BIT; i++, parsed_packet <<= 1) for (int i = 0; i < DSHOT_PAUSE_BIT; i++, parsed_packet <<= 1)
{ {
if (parsed_packet & 0b1000000000000000) if (parsed_packet & 0b1000000000000000)
{ {
// set one // set one
dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_one_high; dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_one_high;
dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_one_low; dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_one_low;
} }
else else
{ {
// set zero // set zero
dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_zero_high; dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_zero_high;
dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_zero_low; dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_zero_low;
} }
dshot_tx_rmt_item[i].level0 = 1; dshot_tx_rmt_item[i].level0 = 1;
dshot_tx_rmt_item[i].level1 = 0; dshot_tx_rmt_item[i].level1 = 0;
} }
} }
if (dshot_config.bidirectional) if (dshot_config.bidirectional)
{ {
dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level0 = 1; dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level0 = 1;
dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level1 = 0; dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level1 = 0;
} }
else else
{ {
dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level0 = 0; dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level0 = 0;
dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level1 = 1; dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level1 = 1;
} }
// ...end marker added to each frame // ...end marker added to each frame
dshot_tx_rmt_item[DSHOT_PAUSE_BIT].duration1 = (DSHOT_PAUSE / 2); dshot_tx_rmt_item[DSHOT_PAUSE_BIT].duration1 = (DSHOT_PAUSE / 2);
return dshot_tx_rmt_item; return dshot_tx_rmt_item;
} }
// ...just returns the checksum // ...just returns the checksum
// DOES NOT APPEND CHECKSUM!!! // DOES NOT APPEND CHECKSUM!!!
uint16_t DShotRMT::calc_dshot_chksum(const dshot_packet_t &dshot_packet) uint16_t DShotRMT::calc_dshot_chksum(const dshot_packet_t& dshot_packet)
{ {
// ...start with two emprty "container" // ...start with two emprty "container"
uint16_t packet = DSHOT_NULL_PACKET; uint16_t packet = DSHOT_NULL_PACKET;
uint16_t chksum = DSHOT_NULL_PACKET; uint16_t chksum = DSHOT_NULL_PACKET;
// ...same initial 12bit data for bidirectional or "normal" mode // ...same initial 12bit data for bidirectional or "normal" mode
packet = (dshot_packet.throttle_value << 1) | dshot_packet.telemetric_request; packet = (dshot_packet.throttle_value << 1) | dshot_packet.telemetric_request;
if (dshot_config.bidirectional) if (dshot_config.bidirectional)
{ {
// ...calc the checksum "inverted" / bidirectional mode // ...calc the checksum "inverted" / bidirectional mode
chksum = (~(packet ^ (packet >> 4) ^ (packet >> 8))) & 0x0F; chksum = (~(packet ^ (packet >> 4) ^ (packet >> 8))) & 0x0F;
} }
else else
{ {
// ...calc the checksum "normal" mode // ...calc the checksum "normal" mode
chksum = (packet ^ (packet >> 4) ^ (packet >> 8)) & 0x0F; chksum = (packet ^ (packet >> 4) ^ (packet >> 8)) & 0x0F;
} }
return chksum; return chksum;
} }
uint16_t DShotRMT::prepare_rmt_data(const dshot_packet_t &dshot_packet) uint16_t DShotRMT::prepare_rmt_data(const dshot_packet_t& dshot_packet)
{ {
uint16_t prepared_to_encode = DSHOT_NULL_PACKET; uint16_t prepared_to_encode = DSHOT_NULL_PACKET;
uint16_t chksum = calc_dshot_chksum(dshot_packet); uint16_t chksum = calc_dshot_chksum(dshot_packet);
// ..."construct" the packet // ..."construct" the packet
prepared_to_encode = (dshot_packet.throttle_value << 1) | dshot_packet.telemetric_request; prepared_to_encode = (dshot_packet.throttle_value << 1) | dshot_packet.telemetric_request;
prepared_to_encode = (prepared_to_encode << 4) | chksum; prepared_to_encode = (prepared_to_encode << 4) | chksum;
return prepared_to_encode; return prepared_to_encode;
} }
// ...finally output using ESP32 RMT // ...finally output using ESP32 RMT
void DShotRMT::output_rmt_data(const dshot_packet_t &dshot_packet) void DShotRMT::output_rmt_data(const dshot_packet_t& dshot_packet)
{ {
encode_dshot_to_rmt(prepare_rmt_data(dshot_packet)); encode_dshot_to_rmt(prepare_rmt_data(dshot_packet));
// //
rmt_write_items(dshot_tx_rmt_config.channel, dshot_tx_rmt_item, DSHOT_PACKET_LENGTH, false); rmt_write_items(dshot_tx_rmt_config.channel, dshot_tx_rmt_item, DSHOT_PACKET_LENGTH, false);
} }

View File

@ -6,10 +6,16 @@
#pragma once #pragma once
#include "BlheliCmdMap.h" #ifndef _DSHOTRMT_h
#include <Arduino.h> #define _DSHOTRMT_h
// ...utilizing the IR Module library for generating the DShot signal #if defined(ARDUINO) && ARDUINO >= 100
#include "arduino.h"
#else
#include "WProgram.h"
#endif
// ...utilizing the RMT Module library for generating the DShot signal
#include <driver/rmt.h> #include <driver/rmt.h>
constexpr auto DSHOT_CLK_DIVIDER = 8; // ...slow down RMT clock to 0.1 microseconds / 100 nanoseconds per cycle constexpr auto DSHOT_CLK_DIVIDER = 8; // ...slow down RMT clock to 0.1 microseconds / 100 nanoseconds per cycle
@ -28,85 +34,87 @@ constexpr auto RMT_CYCLES_PER_ESP_CYCLE = (F_CPU / RMT_CYCLES_PER_SEC);
typedef enum dshot_mode_e typedef enum dshot_mode_e
{ {
DSHOT_OFF, DSHOT_OFF,
DSHOT150, DSHOT150,
DSHOT300, DSHOT300,
DSHOT600, DSHOT600,
DSHOT1200 DSHOT1200
} dshot_mode_t; } dshot_mode_t;
// ...to get human readable DShot Mode // ...to get human readable DShot Mode
static const char *const dshot_mode_name[] = { static const char* const dshot_mode_name[] = {
"DSHOT_OFF", "DSHOT_OFF",
"DSHOT150", "DSHOT150",
"DSHOT300", "DSHOT300",
"DSHOT600", "DSHOT600",
"DSHOT1200"}; "DSHOT1200" };
typedef String dshot_name_t; typedef String dshot_name_t;
typedef enum telemetric_request_e typedef enum telemetric_request_e
{ {
NO_TELEMETRIC, NO_TELEMETRIC,
ENABLE_TELEMETRIC, ENABLE_TELEMETRIC,
} telemetric_request_t; } telemetric_request_t;
// ...set bitcount for DShot packet // ...set bitcount for DShot packet
typedef struct dshot_packet_s typedef struct dshot_packet_s
{ {
uint16_t throttle_value : 11; uint16_t throttle_value : 11;
telemetric_request_t telemetric_request : 1; telemetric_request_t telemetric_request : 1;
uint16_t checksum : 4; uint16_t checksum : 4;
} dshot_packet_t; } dshot_packet_t;
// ...set bitcount for eRPM packet // ...set bitcount for eRPM packet
typedef struct eRPM_packet_s typedef struct eRPM_packet_s
{ {
uint16_t eRPM_data : 12; uint16_t eRPM_data : 12;
uint8_t checksum : 4; uint8_t checksum : 4;
} eRPM_packet_t; } eRPM_packet_t;
// ...all settings for the dshot mode // ...all settings for the dshot mode
typedef struct dshot_config_s typedef struct dshot_config_s
{ {
dshot_mode_t mode; dshot_mode_t mode;
dshot_name_t name_str; dshot_name_t name_str;
bool bidirectional; bool bidirectional;
gpio_num_t gpio_num; gpio_num_t gpio_num;
uint8_t pin_num; uint8_t pin_num;
rmt_channel_t rmt_channel; rmt_channel_t rmt_channel;
uint8_t mem_block_num; uint8_t mem_block_num;
uint16_t ticks_per_bit; uint16_t ticks_per_bit;
uint8_t clk_div; uint8_t clk_div;
uint16_t ticks_zero_high; uint16_t ticks_zero_high;
uint16_t ticks_zero_low; uint16_t ticks_zero_low;
uint16_t ticks_one_high; uint16_t ticks_one_high;
uint16_t ticks_one_low; uint16_t ticks_one_low;
} dshot_config_t; } dshot_config_t;
class DShotRMT class DShotRMT
{ {
public: public:
DShotRMT(gpio_num_t gpio, rmt_channel_t rmtChannel); DShotRMT(gpio_num_t gpio, rmt_channel_t rmtChannel);
DShotRMT(uint8_t pin, uint8_t channel); DShotRMT(uint8_t pin, uint8_t channel);
~DShotRMT(); ~DShotRMT();
DShotRMT(DShotRMT const &); DShotRMT(DShotRMT const&);
// ...safety first ...no parameters, no DShot // ...safety first ...no parameters, no DShot
bool begin(dshot_mode_t dshot_mode = DSHOT_OFF, bool is_bidirectional = false); bool begin(dshot_mode_t dshot_mode = DSHOT_OFF, bool is_bidirectional = false);
void send_dshot_value(uint16_t throttle_value, telemetric_request_t telemetric_request = NO_TELEMETRIC); void send_dshot_value(uint16_t throttle_value, telemetric_request_t telemetric_request = NO_TELEMETRIC);
dshot_config_t *get_dshot_info(); dshot_config_t* get_dshot_info();
uint8_t *get_dshot_clock_div(); uint8_t* get_dshot_clock_div();
private: private:
rmt_item32_t dshot_tx_rmt_item[DSHOT_PACKET_LENGTH]; rmt_item32_t dshot_tx_rmt_item[DSHOT_PACKET_LENGTH];
rmt_config_t dshot_tx_rmt_config; rmt_config_t dshot_tx_rmt_config;
dshot_config_t dshot_config; dshot_config_t dshot_config;
rmt_item32_t *encode_dshot_to_rmt(uint16_t parsed_packet); rmt_item32_t* encode_dshot_to_rmt(uint16_t parsed_packet);
uint16_t calc_dshot_chksum(const dshot_packet_t &dshot_packet); uint16_t calc_dshot_chksum(const dshot_packet_t& dshot_packet);
uint16_t prepare_rmt_data(const dshot_packet_t &dshot_packet); uint16_t prepare_rmt_data(const dshot_packet_t& dshot_packet);
void output_rmt_data(const dshot_packet_t &dshot_packet); void output_rmt_data(const dshot_packet_t& dshot_packet);
}; };
#endif