From 85814f39be5cbc5f7d76ba2c6985dff7d5142eb4 Mon Sep 17 00:00:00 2001 From: Wastl Kraus Date: Fri, 25 Nov 2022 16:08:58 +0100 Subject: [PATCH] ...cosmetics --- .gitignore | 3 + DShotRMT.code-workspace | 8 + examples/dshot300/dshot300.ino | 22 ++- library.properties | 2 +- src/BlheliCmdMap.h | 51 +++--- src/DShotRMT.cpp | 316 ++++++++++++++++++--------------- src/DShotRMT.h | 119 +++++++------ 7 files changed, 288 insertions(+), 233 deletions(-) create mode 100644 DShotRMT.code-workspace diff --git a/.gitignore b/.gitignore index 45fce1d..ca97c50 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ # Built Visual Studio Code Extensions *.vsix + +# Caching ESP32 Builds +buildCache/* diff --git a/DShotRMT.code-workspace b/DShotRMT.code-workspace new file mode 100644 index 0000000..517e0b2 --- /dev/null +++ b/DShotRMT.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/examples/dshot300/dshot300.ino b/examples/dshot300/dshot300.ino index 18e7331..faf826d 100644 --- a/examples/dshot300/dshot300.ino +++ b/examples/dshot300/dshot300.ino @@ -14,15 +14,17 @@ DShotRMT dshot_01(GPIO_NUM_4, RMT_CHANNEL_0); volatile uint16_t throttle_value = 0x30; // ...sending "48", the first throttle value constexpr auto FAILSAVE_THROTTLE = 0x3E7; -void setup() { +void setup() +{ // ...always start the onboard usb support - USB_Serial.begin(USB_SERIAL_BAUD); + USB_Serial.begin(USB_SERIAL_BAUD); // ...start the dshot generation dshot_01.begin(DSHOT300); } -void loop() { +void loop() +{ read_SerialThrottle(); dshot_01.send_dshot_value(throttle_value); @@ -33,11 +35,15 @@ void loop() { // // -uint16_t read_SerialThrottle() { - if (USB_Serial.available() > 0) { - auto throttle_input = (USB_Serial.readStringUntil('\n')).toInt(); - return throttle_input; - } else { +uint16_t read_SerialThrottle() +{ + if (USB_Serial.available() > 0) + { + auto throttle_input = (USB_Serial.readStringUntil('\n')).toInt(); + return throttle_input; + } + else + { return FAILSAVE_THROTTLE; } } diff --git a/library.properties b/library.properties index 6bd8fff..be1038b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=DShotRMT -version=0.2.0 +version=0.2.1 author=derdoktor667 maintainer=derdoktor667 sentence=DShotRMT Library supporting all DShot Types and speeds. Tested with BlHeli_S. diff --git a/src/BlheliCmdMap.h b/src/BlheliCmdMap.h index 9d261d1..f4b7c43 100644 --- a/src/BlheliCmdMap.h +++ b/src/BlheliCmdMap.h @@ -3,29 +3,30 @@ // 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 +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 }; diff --git a/src/DShotRMT.cpp b/src/DShotRMT.cpp index db0db64..9bb1bd5 100644 --- a/src/DShotRMT.cpp +++ b/src/DShotRMT.cpp @@ -6,220 +6,252 @@ #include "DShotRMT.h" -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.pin_num = uint8_t(gpio); - dshot_config.rmt_channel = rmtChannel; - dshot_config.mem_block_num = uint8_t(RMT_CHANNEL_MAX - uint8_t(rmtChannel)); + dshot_config.pin_num = uint8_t(gpio); + dshot_config.rmt_channel = rmtChannel; + dshot_config.mem_block_num = uint8_t(RMT_CHANNEL_MAX - uint8_t(rmtChannel)); - // ...create clean packet - encode_dshot_to_rmt(DSHOT_NULL_PACKET); + // ...create clean packet + encode_dshot_to_rmt(DSHOT_NULL_PACKET); } -DShotRMT::DShotRMT(uint8_t pin, uint8_t channel) { - dshot_config.gpio_num = gpio_num_t(pin); - dshot_config.pin_num = pin; - dshot_config.rmt_channel = rmt_channel_t(channel); - dshot_config.mem_block_num = (RMT_CHANNEL_MAX - channel); +DShotRMT::DShotRMT(uint8_t pin, uint8_t channel) +{ + dshot_config.gpio_num = gpio_num_t(pin); + dshot_config.pin_num = pin; + dshot_config.rmt_channel = rmt_channel_t(channel); + dshot_config.mem_block_num = (RMT_CHANNEL_MAX - channel); - // ...create clean packet - encode_dshot_to_rmt(DSHOT_NULL_PACKET); + // ...create clean packet + encode_dshot_to_rmt(DSHOT_NULL_PACKET); } -DShotRMT::~DShotRMT() { - rmt_driver_uninstall(dshot_config.rmt_channel); +DShotRMT::~DShotRMT() +{ + rmt_driver_uninstall(dshot_config.rmt_channel); } -DShotRMT::DShotRMT(DShotRMT const&) { - // ...write me +DShotRMT::DShotRMT(DShotRMT const &) +{ + // ...write me } -bool DShotRMT::begin(dshot_mode_t dshot_mode, bool is_bidirectional) { - dshot_config.mode = dshot_mode; - dshot_config.clk_div = DSHOT_CLK_DIVIDER; - dshot_config.name_str = dshot_mode_name[dshot_mode]; - dshot_config.bidirectional = is_bidirectional; +bool DShotRMT::begin(dshot_mode_t dshot_mode, bool is_bidirectional) +{ + dshot_config.mode = dshot_mode; + dshot_config.clk_div = DSHOT_CLK_DIVIDER; + dshot_config.name_str = dshot_mode_name[dshot_mode]; + dshot_config.bidirectional = is_bidirectional; - switch (dshot_config.mode) { - case DSHOT150: - 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_one_high = 48; // ...one time 5.00 us - break; + switch (dshot_config.mode) + { + case DSHOT150: + 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_one_high = 48; // ...one time 5.00 us + break; - case DSHOT300: - 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_one_high = 24; // ...one time 2.50 us - break; + case DSHOT300: + 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_one_high = 24; // ...one time 2.50 us + break; - case DSHOT600: - 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_one_high = 12; // ...one time 1.25 us - break; + case DSHOT600: + 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_one_high = 12; // ...one time 1.25 us + break; - case DSHOT1200: - 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_one_high = 6; // ...one time 0.625 us - break; + case DSHOT1200: + 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_one_high = 6; // ...one time 0.625 us + break; - // ...because having a default is "good style" - default: - dshot_config.ticks_per_bit = 0; // ...Bit Period Time endless - dshot_config.ticks_zero_high = 0; // ...no bits, no time - dshot_config.ticks_one_high = 0; // ......no bits, no time - break; - } + // ...because having a default is "good style" + default: + dshot_config.ticks_per_bit = 0; // ...Bit Period Time endless + dshot_config.ticks_zero_high = 0; // ...no bits, no time + dshot_config.ticks_one_high = 0; // ......no bits, no time + break; + } - // ...calc low signal timing - 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); + // ...calc low signal timing + 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_tx_rmt_config.rmt_mode = RMT_MODE_TX; - dshot_tx_rmt_config.channel = dshot_config.rmt_channel; - 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.clk_div = dshot_config.clk_div; + dshot_tx_rmt_config.rmt_mode = RMT_MODE_TX; + dshot_tx_rmt_config.channel = dshot_config.rmt_channel; + 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.clk_div = dshot_config.clk_div; - dshot_tx_rmt_config.tx_config.loop_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.loop_en = false; + dshot_tx_rmt_config.tx_config.carrier_en = false; + 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; - } else { + } + else + { dshot_tx_rmt_config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW; } - // ...setup selected dshot mode - rmt_config(&dshot_tx_rmt_config); + // ...setup selected dshot mode + rmt_config(&dshot_tx_rmt_config); - // ...essential step, return the result - return rmt_driver_install(dshot_tx_rmt_config.channel, 0, 0); + // ...essential step, return the result + return rmt_driver_install(dshot_tx_rmt_config.channel, 0, 0); } // ...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) { - dshot_packet_t dshot_rmt_packet = { }; +void DShotRMT::send_dshot_value(uint16_t throttle_value, telemetric_request_t telemetric_request) +{ + dshot_packet_t dshot_rmt_packet = {}; - if (throttle_value < DSHOT_THROTTLE_MIN) { - throttle_value = DSHOT_THROTTLE_MIN; - } + if (throttle_value < DSHOT_THROTTLE_MIN) + { + throttle_value = DSHOT_THROTTLE_MIN; + } - if (throttle_value > DSHOT_THROTTLE_MAX) { - throttle_value = DSHOT_THROTTLE_MAX; - } + if (throttle_value > DSHOT_THROTTLE_MAX) + { + throttle_value = DSHOT_THROTTLE_MAX; + } - // ...packets are the same for bidirectional mode - dshot_rmt_packet.throttle_value = throttle_value; - dshot_rmt_packet.telemetric_request = telemetric_request; - dshot_rmt_packet.checksum = this->calc_dshot_chksum(dshot_rmt_packet); + // ...packets are the same for bidirectional mode + dshot_rmt_packet.throttle_value = throttle_value; + dshot_rmt_packet.telemetric_request = telemetric_request; + 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 -dshot_config_t* DShotRMT::get_dshot_info() { - return &dshot_config; +dshot_config_t *DShotRMT::get_dshot_info() +{ + return &dshot_config; } // ...get the ABP_Clock Divider for further calculations -uint8_t* DShotRMT::get_dshot_clock_div() { - return &dshot_config.clk_div; +uint8_t *DShotRMT::get_dshot_clock_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 - if (dshot_config.bidirectional) { + if (dshot_config.bidirectional) + { // ..."invert" the signal duration - for (int i = 0; i < DSHOT_PAUSE_BIT; i++, parsed_packet <<= 1) { - if (parsed_packet & 0b1000000000000000) { - // set one - dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_one_low; - dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_one_high; - } - else { - // set zero - dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_zero_low; - dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_zero_high; - } + for (int i = 0; i < DSHOT_PAUSE_BIT; i++, parsed_packet <<= 1) + { + if (parsed_packet & 0b1000000000000000) + { + // set one + dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_one_low; + dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_one_high; + } + else + { + // set zero + 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].level0 = 0; - dshot_tx_rmt_item[i].level1 = 1; + dshot_tx_rmt_item[i].level0 = 0; + dshot_tx_rmt_item[i].level1 = 1; } } - + // ..."normal" DShot mode / "bidirectional" mode OFF - else { - for (int i = 0; i < DSHOT_PAUSE_BIT; i++, parsed_packet <<= 1) { - if (parsed_packet & 0b1000000000000000) { - // set one - dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_one_high; - dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_one_low; - } - else { - // set zero - dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_zero_high; - dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_zero_low; - } + else + { + for (int i = 0; i < DSHOT_PAUSE_BIT; i++, parsed_packet <<= 1) + { + if (parsed_packet & 0b1000000000000000) + { + // set one + dshot_tx_rmt_item[i].duration0 = dshot_config.ticks_one_high; + dshot_tx_rmt_item[i].duration1 = dshot_config.ticks_one_low; + } + else + { + // set zero + 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].level0 = 1; - dshot_tx_rmt_item[i].level1 = 0; + dshot_tx_rmt_item[i].level0 = 1; + 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].level1 = 0; - } else { + } + else + { dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level0 = 0; dshot_tx_rmt_item[DSHOT_PAUSE_BIT].level1 = 1; } - // ...end marker added to each frame - dshot_tx_rmt_item[DSHOT_PAUSE_BIT].duration1 = (DSHOT_PAUSE / 2); + // ...end marker added to each frame + 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 // 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" - uint16_t packet = DSHOT_NULL_PACKET; - uint16_t chksum = DSHOT_NULL_PACKET; + uint16_t packet = DSHOT_NULL_PACKET; + uint16_t chksum = DSHOT_NULL_PACKET; - // ...same initial 12bit data for bidirectional or "normal" mode - packet = (dshot_packet.throttle_value << 1) | dshot_packet.telemetric_request; + // ...same initial 12bit data for bidirectional or "normal" mode + packet = (dshot_packet.throttle_value << 1) | dshot_packet.telemetric_request; - if (dshot_config.bidirectional) { - // ...calc the checksum "inverted" / bidirectional mode - chksum = (~(packet ^ (packet >> 4) ^ (packet >> 8))) & 0x0F; - } else { - // ...calc the checksum "normal" mode - chksum = (packet ^ (packet >> 4) ^ (packet >> 8)) & 0x0F; - } + if (dshot_config.bidirectional) + { + // ...calc the checksum "inverted" / bidirectional mode + chksum = (~(packet ^ (packet >> 4) ^ (packet >> 8))) & 0x0F; + } + else + { + // ...calc the checksum "normal" mode + 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 prepared_to_encode = DSHOT_NULL_PACKET; - uint16_t chksum = calc_dshot_chksum(dshot_packet); +uint16_t DShotRMT::prepare_rmt_data(const dshot_packet_t &dshot_packet) +{ + uint16_t prepared_to_encode = DSHOT_NULL_PACKET; + uint16_t chksum = calc_dshot_chksum(dshot_packet); // ..."construct" the packet - prepared_to_encode = (dshot_packet.throttle_value << 1) | dshot_packet.telemetric_request; - prepared_to_encode = (prepared_to_encode << 4) | chksum; + prepared_to_encode = (dshot_packet.throttle_value << 1) | dshot_packet.telemetric_request; + prepared_to_encode = (prepared_to_encode << 4) | chksum; - return prepared_to_encode; + return prepared_to_encode; } // ...finally output using ESP32 RMT -void DShotRMT::output_rmt_data(const dshot_packet_t &dshot_packet) { - encode_dshot_to_rmt(prepare_rmt_data(dshot_packet)); +void DShotRMT::output_rmt_data(const dshot_packet_t &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); } diff --git a/src/DShotRMT.h b/src/DShotRMT.h index 2a52d3f..0737cc0 100644 --- a/src/DShotRMT.h +++ b/src/DShotRMT.h @@ -6,13 +6,13 @@ #pragma once -#include #include "BlheliCmdMap.h" +#include // ...utilizing the IR Module library for generating the DShot signal #include -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 constexpr auto DSHOT_PACKET_LENGTH = 17; // ...last pack is the pause constexpr auto DSHOT_THROTTLE_MIN = 48; @@ -26,82 +26,87 @@ constexpr auto F_CPU_RMT = APB_CLK_FREQ; constexpr auto RMT_CYCLES_PER_SEC = (F_CPU_RMT / DSHOT_CLK_DIVIDER); constexpr auto RMT_CYCLES_PER_ESP_CYCLE = (F_CPU / RMT_CYCLES_PER_SEC); -typedef enum dshot_mode_e { - DSHOT_OFF, - DSHOT150, - DSHOT300, - DSHOT600, - DSHOT1200 +typedef enum dshot_mode_e +{ + DSHOT_OFF, + DSHOT150, + DSHOT300, + DSHOT600, + DSHOT1200 } dshot_mode_t; -// ...to get human readable DShot Mode -static const char* const dshot_mode_name[] = { - "DSHOT_OFF", - "DSHOT150", - "DSHOT300", - "DSHOT600", - "DSHOT1200" -}; +// ...to get human readable DShot Mode +static const char *const dshot_mode_name[] = { + "DSHOT_OFF", + "DSHOT150", + "DSHOT300", + "DSHOT600", + "DSHOT1200"}; typedef String dshot_name_t; -typedef enum telemetric_request_e { - NO_TELEMETRIC, - ENABLE_TELEMETRIC, +typedef enum telemetric_request_e +{ + NO_TELEMETRIC, + ENABLE_TELEMETRIC, } telemetric_request_t; // ...set bitcount for DShot packet -typedef struct dshot_packet_s { - uint16_t throttle_value : 11; - telemetric_request_t telemetric_request : 1; - uint16_t checksum : 4; +typedef struct dshot_packet_s +{ + uint16_t throttle_value : 11; + telemetric_request_t telemetric_request : 1; + uint16_t checksum : 4; } dshot_packet_t; // ...set bitcount for eRPM packet -typedef struct eRPM_packet_s { +typedef struct eRPM_packet_s +{ uint16_t eRPM_data : 12; uint8_t checksum : 4; } eRPM_packet_t; // ...all settings for the dshot mode -typedef struct dshot_config_s { - dshot_mode_t mode; - dshot_name_t name_str; - bool bidirectional; - gpio_num_t gpio_num; - uint8_t pin_num; - rmt_channel_t rmt_channel; - uint8_t mem_block_num; - uint16_t ticks_per_bit; - uint8_t clk_div; - uint16_t ticks_zero_high; - uint16_t ticks_zero_low; - uint16_t ticks_one_high; - uint16_t ticks_one_low; +typedef struct dshot_config_s +{ + dshot_mode_t mode; + dshot_name_t name_str; + bool bidirectional; + gpio_num_t gpio_num; + uint8_t pin_num; + rmt_channel_t rmt_channel; + uint8_t mem_block_num; + uint16_t ticks_per_bit; + uint8_t clk_div; + uint16_t ticks_zero_high; + uint16_t ticks_zero_low; + uint16_t ticks_one_high; + uint16_t ticks_one_low; } dshot_config_t; -class DShotRMT { - public: - DShotRMT(gpio_num_t gpio, rmt_channel_t rmtChannel); - DShotRMT(uint8_t pin, uint8_t channel); - ~DShotRMT(); - DShotRMT(DShotRMT const&); +class DShotRMT +{ +public: + DShotRMT(gpio_num_t gpio, rmt_channel_t rmtChannel); + DShotRMT(uint8_t pin, uint8_t channel); + ~DShotRMT(); + DShotRMT(DShotRMT const &); - // ...safety first ...no parameters, no DShot - 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); + // ...safety first ...no parameters, no DShot + 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); - dshot_config_t *get_dshot_info(); - uint8_t *get_dshot_clock_div(); + dshot_config_t *get_dshot_info(); + uint8_t *get_dshot_clock_div(); - private: - rmt_item32_t dshot_tx_rmt_item[DSHOT_PACKET_LENGTH]; - rmt_config_t dshot_tx_rmt_config; - dshot_config_t dshot_config; +private: + rmt_item32_t dshot_tx_rmt_item[DSHOT_PACKET_LENGTH]; + rmt_config_t dshot_tx_rmt_config; + dshot_config_t dshot_config; - rmt_item32_t *encode_dshot_to_rmt(uint16_t parsed_packet); - uint16_t calc_dshot_chksum(const dshot_packet_t &dshot_packet); - uint16_t prepare_rmt_data(const dshot_packet_t &dshot_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 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); };