experiments
This commit is contained in:
parent
de2358e3c8
commit
d7e8386129
|
|
@ -17,7 +17,7 @@ The checksum is calculated over the throttle value and the telemetry bit, so the
|
||||||
crc = (value ^ (value >> 4) ^ (value >> 8)) & 0x0F;
|
crc = (value ^ (value >> 4) ^ (value >> 8)) & 0x0F;
|
||||||
|
|
||||||
### Bidirectional DSHOT
|
### Bidirectional DSHOT
|
||||||
Bidirictional DSHOT is also known as inverted DSHOT, because the signal level is inverted, so 1 is low and a 0 is high. This is done in order to let the ESC know, that we are operating in bidirectional mode and that it should be sending back eRPM telemetry packages.
|
Bidirectional DSHOT is also known as inverted DSHOT, because the signal level is inverted, so 1 is low and a 0 is high. This is done in order to let the ESC know, that we are operating in bidirectional mode and that it should be sending back eRPM telemetry packages.
|
||||||
|
|
||||||
#### Calculating the Bidirectional CRC
|
#### Calculating the Bidirectional CRC
|
||||||
The calculation of the checksum is basically the same, just before the last step the values are inverted:
|
The calculation of the checksum is basically the same, just before the last step the values are inverted:
|
||||||
|
|
|
||||||
348
src/DShotRMT.cpp
348
src/DShotRMT.cpp
|
|
@ -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 empty 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 empty 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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
100
src/DShotRMT.h
100
src/DShotRMT.h
|
|
@ -4,8 +4,6 @@
|
||||||
// Author: derdoktor667
|
// Author: derdoktor667
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef _DSHOTRMT_h
|
#ifndef _DSHOTRMT_h
|
||||||
#define _DSHOTRMT_h
|
#define _DSHOTRMT_h
|
||||||
|
|
||||||
|
|
@ -37,87 +35,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
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue