dshot_esc_encoder.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "esp_check.h"
  7. #include "dshot_esc_encoder.h"
  8. static const char *TAG = "dshot_encoder";
  9. /**
  10. * @brief Type of Dshot ESC frame
  11. */
  12. typedef union {
  13. struct {
  14. uint16_t crc: 4; /*!< CRC checksum */
  15. uint16_t telemetry: 1; /*!< Telemetry request */
  16. uint16_t throttle: 11; /*!< Throttle value */
  17. };
  18. uint16_t val;
  19. } dshot_esc_frame_t;
  20. #ifndef __cplusplus
  21. _Static_assert(sizeof(dshot_esc_frame_t) == 0x02, "Invalid size of dshot_esc_frame_t structure");
  22. #endif
  23. typedef struct {
  24. rmt_encoder_t base;
  25. rmt_encoder_t *bytes_encoder;
  26. rmt_encoder_t *copy_encoder;
  27. rmt_symbol_word_t dshot_delay_symbol;
  28. int state;
  29. } rmt_dshot_esc_encoder_t;
  30. static void make_dshot_frame(dshot_esc_frame_t *frame, uint16_t throttle, bool telemetry)
  31. {
  32. frame->throttle = throttle;
  33. frame->telemetry = telemetry;
  34. uint16_t val = frame->val;
  35. uint8_t crc = ((val ^ (val >> 4) ^ (val >> 8)) & 0xF0) >> 4;;
  36. frame->crc = crc;
  37. val = frame->val;
  38. // change the endian
  39. frame->val = ((val & 0xFF) << 8) | ((val & 0xFF00) >> 8);
  40. }
  41. static size_t rmt_encode_dshot_esc(rmt_encoder_t *encoder, rmt_channel_handle_t channel,
  42. const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
  43. {
  44. rmt_dshot_esc_encoder_t *dshot_encoder = __containerof(encoder, rmt_dshot_esc_encoder_t, base);
  45. rmt_encoder_handle_t bytes_encoder = dshot_encoder->bytes_encoder;
  46. rmt_encoder_handle_t copy_encoder = dshot_encoder->copy_encoder;
  47. rmt_encode_state_t session_state = 0;
  48. rmt_encode_state_t state = 0;
  49. size_t encoded_symbols = 0;
  50. // convert user data into dshot frame
  51. dshot_esc_throttle_t *throttle = (dshot_esc_throttle_t *)primary_data;
  52. dshot_esc_frame_t frame = {};
  53. make_dshot_frame(&frame, throttle->throttle, throttle->telemetry_req);
  54. switch (dshot_encoder->state) {
  55. case 0: // send the dshot frame
  56. encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &frame, sizeof(frame), &session_state);
  57. if (session_state & RMT_ENCODING_COMPLETE) {
  58. dshot_encoder->state = 1; // switch to next state when current encoding session finished
  59. }
  60. if (session_state & RMT_ENCODING_MEM_FULL) {
  61. state |= RMT_ENCODING_MEM_FULL;
  62. goto out; // yield if there's no free space for encoding artifacts
  63. }
  64. // fall-through
  65. case 1:
  66. encoded_symbols += copy_encoder->encode(copy_encoder, channel, &dshot_encoder->dshot_delay_symbol,
  67. sizeof(rmt_symbol_word_t), &session_state);
  68. if (session_state & RMT_ENCODING_COMPLETE) {
  69. state |= RMT_ENCODING_COMPLETE;
  70. dshot_encoder->state = 0; // switch to next state when current encoding session finished
  71. }
  72. if (session_state & RMT_ENCODING_MEM_FULL) {
  73. state |= RMT_ENCODING_MEM_FULL;
  74. goto out; // yield if there's no free space for encoding artifacts
  75. }
  76. }
  77. out:
  78. *ret_state = state;
  79. return encoded_symbols;
  80. }
  81. static esp_err_t rmt_del_dshot_encoder(rmt_encoder_t *encoder)
  82. {
  83. rmt_dshot_esc_encoder_t *dshot_encoder = __containerof(encoder, rmt_dshot_esc_encoder_t, base);
  84. rmt_del_encoder(dshot_encoder->bytes_encoder);
  85. rmt_del_encoder(dshot_encoder->copy_encoder);
  86. free(dshot_encoder);
  87. return ESP_OK;
  88. }
  89. static esp_err_t rmt_dshot_encoder_reset(rmt_encoder_t *encoder)
  90. {
  91. rmt_dshot_esc_encoder_t *dshot_encoder = __containerof(encoder, rmt_dshot_esc_encoder_t, base);
  92. rmt_encoder_reset(dshot_encoder->bytes_encoder);
  93. rmt_encoder_reset(dshot_encoder->copy_encoder);
  94. dshot_encoder->state = 0;
  95. return ESP_OK;
  96. }
  97. esp_err_t rmt_new_dshot_esc_encoder(const dshot_esc_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
  98. {
  99. esp_err_t ret = ESP_OK;
  100. rmt_dshot_esc_encoder_t *dshot_encoder = NULL;
  101. ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
  102. dshot_encoder = calloc(1, sizeof(rmt_dshot_esc_encoder_t));
  103. ESP_GOTO_ON_FALSE(dshot_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for musical score encoder");
  104. dshot_encoder->base.encode = rmt_encode_dshot_esc;
  105. dshot_encoder->base.del = rmt_del_dshot_encoder;
  106. dshot_encoder->base.reset = rmt_dshot_encoder_reset;
  107. uint32_t delay_ticks = config->resolution / 1e6 * config->post_delay_us;
  108. rmt_symbol_word_t dshot_delay_symbol = {
  109. .level0 = 0,
  110. .duration0 = delay_ticks / 2,
  111. .level1 = 0,
  112. .duration1 = delay_ticks / 2,
  113. };
  114. dshot_encoder->dshot_delay_symbol = dshot_delay_symbol;
  115. // different dshot protocol have its own timing requirements,
  116. float period_ticks = (float)config->resolution / config->baud_rate;
  117. // 1 and 0 is represented by a 74.850% and 37.425% duty cycle respectively
  118. unsigned int t1h_ticks = (unsigned int)(period_ticks * 0.7485);
  119. unsigned int t1l_ticks = (unsigned int)(period_ticks - t1h_ticks);
  120. unsigned int t0h_ticks = (unsigned int)(period_ticks * 0.37425);
  121. unsigned int t0l_ticks = (unsigned int)(period_ticks - t0h_ticks);
  122. rmt_bytes_encoder_config_t bytes_encoder_config = {
  123. .bit0 = {
  124. .level0 = 1,
  125. .duration0 = t0h_ticks,
  126. .level1 = 0,
  127. .duration1 = t0l_ticks,
  128. },
  129. .bit1 = {
  130. .level0 = 1,
  131. .duration0 = t1h_ticks,
  132. .level1 = 0,
  133. .duration1 = t1l_ticks,
  134. },
  135. .flags.msb_first = 1,
  136. };
  137. ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &dshot_encoder->bytes_encoder), err, TAG, "create bytes encoder failed");
  138. rmt_copy_encoder_config_t copy_encoder_config = {};
  139. ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(&copy_encoder_config, &dshot_encoder->copy_encoder), err, TAG, "create copy encoder failed");
  140. *ret_encoder = &dshot_encoder->base;
  141. return ESP_OK;
  142. err:
  143. if (dshot_encoder) {
  144. if (dshot_encoder->bytes_encoder) {
  145. rmt_del_encoder(dshot_encoder->bytes_encoder);
  146. }
  147. if (dshot_encoder->copy_encoder) {
  148. rmt_del_encoder(dshot_encoder->copy_encoder);
  149. }
  150. free(dshot_encoder);
  151. }
  152. return ret;
  153. }