DSHOT/Bitbang - Hold the line at idle for 1 extra bit period.
[betaflight.git] / src / main / drivers / dshot_bitbang_impl.h
blob2ce301ef9acfedf1f0599b640b8425054d4af57e
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #pragma once
23 #include "common/time.h"
24 #include "drivers/motor.h"
26 #define USE_DMA_REGISTER_CACHE
28 #define DEBUG_COUNT_INTERRUPT
29 #define DEBUG_MONITOR_PACER
31 #define MAX_SUPPORTED_MOTOR_PORTS 4 // Max direct dshot port groups, limited by number of usable timer (TIM1 and TIM8) x number of channels per timer (4), 3 is enough to cover motor pins on GPIOA, GPIOB and GPIOC.
33 #define DSHOT_BITBANG_TELEMETRY_OVER_SAMPLE 3
35 #define DSHOT_BITBANG_DIRECTION_OUTPUT 0
36 #define DSHOT_BITBANG_DIRECTION_INPUT 1
38 #define DSHOT_BITBANG_INVERTED true
39 #define DSHOT_BITBANG_NONINVERTED false
41 // XXX MOTOR_xSHOTyyyy_HZ is not usable as generic frequency for timers.
42 // XXX Trying to fiddle with constants here.
44 // Symbol rate [symbol/sec]
45 #define MOTOR_DSHOT600_SYMBOL_RATE (600 * 1000)
46 #define MOTOR_DSHOT300_SYMBOL_RATE (300 * 1000)
47 #define MOTOR_DSHOT150_SYMBOL_RATE (150 * 1000)
49 #define MOTOR_DSHOT_SYMBOL_TIME_NS(rate) (1000000000 / (rate))
51 #define MOTOR_DSHOT_BIT_PER_SYMBOL 1
53 #define MOTOR_DSHOT_STATE_PER_SYMBOL 3 // Initial high, 0/1, low
54 #define MOTOR_DSHOT_BIT_HOLD_STATES 3 // 3 extra states at the end of transmission required to allow ESC to sample the last bit correctly.
56 #define MOTOR_DSHOT_FRAME_BITS 16
59 #define MOTOR_DSHOT_FRAME_TIME_NS(rate) ((MOTOR_DSHOT_FRAME_BITS / MOTOR_DSHOT_BIT_PER_SYMBOL) * MOTOR_DSHOT_SYMBOL_TIME_NS(rate))
61 #define MOTOR_DSHOT_TELEMETRY_WINDOW_US (30000 + MOTOR_DSHOT_FRAME_TIME_NS(rate) * (1.1)) / 1000
63 #define MOTOR_DSHOT_CHANGE_INTERVAL_NS(rate) (MOTOR_DSHOT_SYMBOL_TIME_NS(rate) / MOTOR_DSHOT_STATE_PER_SYMBOL)
65 #define MOTOR_DSHOT_GCR_CHANGE_INTERVAL_NS(rate) (MOTOR_DSHOT_CHANGE_INTERVAL_NS(rate) * 5 / 4)
67 #define MOTOR_DSHOT_BUF_LENGTH (((MOTOR_DSHOT_FRAME_BITS / MOTOR_DSHOT_BIT_PER_SYMBOL) * MOTOR_DSHOT_STATE_PER_SYMBOL) + MOTOR_DSHOT_BIT_HOLD_STATES)
68 #ifdef USE_DSHOT_CACHE_MGMT
69 // MOTOR_DSHOT_BUF_LENGTH is multiples of uint32_t
70 // Number of bytes required for buffer
71 #define MOTOR_DSHOT_BUF_BYTES (MOTOR_DSHOT_BUF_LENGTH * sizeof(uint32_t))
72 // Number of bytes required to cache align buffer
73 #define MOTOR_DSHOT_BUF_CACHE_ALIGN_BYTES ((MOTOR_DSHOT_BUF_BYTES + 0x20) & ~0x1f)
74 // Size of array to create a cache aligned buffer
75 #define MOTOR_DSHOT_BUF_CACHE_ALIGN_LENGTH (MOTOR_DSHOT_BUF_CACHE_ALIGN_BYTES / sizeof(uint32_t))
76 #else
77 #define MOTOR_DSHOT_BUF_CACHE_ALIGN_LENGTH MOTOR_DSHOT_BUF_LENGTH
78 #endif
80 #ifdef USE_HAL_DRIVER
81 #define BB_GPIO_PULLDOWN GPIO_PULLDOWN
82 #define BB_GPIO_PULLUP GPIO_PULLUP
83 #else
84 #define BB_GPIO_PULLDOWN GPIO_PuPd_DOWN
85 #define BB_GPIO_PULLUP GPIO_PuPd_UP
86 #endif
88 #ifdef USE_DMA_REGISTER_CACHE
89 typedef struct dmaRegCache_s {
90 #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
91 uint32_t CR;
92 uint32_t FCR;
93 uint32_t NDTR;
94 uint32_t PAR;
95 uint32_t M0AR;
96 #elif defined(STM32G4)
97 uint32_t CCR;
98 uint32_t CNDTR;
99 uint32_t CPAR;
100 uint32_t CMAR;
101 #else
102 #error No MCU dependent code here
103 #endif
104 } dmaRegCache_t;
105 #endif
107 // Per pacer timer
109 typedef struct bbPacer_s {
110 TIM_TypeDef *tim;
111 uint16_t dmaSources;
112 } bbPacer_t;
114 // Per GPIO port and timer channel
116 typedef struct bbPort_s {
117 int portIndex;
118 GPIO_TypeDef *gpio;
119 const timerHardware_t *timhw;
120 #ifdef USE_HAL_DRIVER
121 uint32_t llChannel;
122 #endif
124 uint16_t dmaSource;
126 dmaResource_t *dmaResource; // DMA resource for this port & timer channel
127 uint32_t dmaChannel; // DMA channel or peripheral request
129 uint8_t direction;
131 #ifdef USE_DMA_REGISTER_CACHE
132 // DMA resource register cache
133 dmaRegCache_t dmaRegOutput;
134 dmaRegCache_t dmaRegInput;
135 #endif
137 // For direct manipulation of GPIO_MODER register
138 uint32_t gpioModeMask;
139 uint32_t gpioModeInput;
140 uint32_t gpioModeOutput;
142 // Idle value
143 uint32_t gpioIdleBSRR;
145 #ifdef USE_HAL_DRIVER
146 LL_TIM_InitTypeDef timeBaseInit;
147 #else
148 TIM_TimeBaseInitTypeDef timeBaseInit;
149 #endif
151 // Output
152 uint16_t outputARR;
153 #ifdef USE_HAL_DRIVER
154 LL_DMA_InitTypeDef outputDmaInit;
155 #else
156 DMA_InitTypeDef outputDmaInit;
157 #endif
158 uint32_t *portOutputBuffer;
159 uint32_t portOutputCount;
161 // Input
162 uint16_t inputARR;
163 #ifdef USE_HAL_DRIVER
164 LL_DMA_InitTypeDef inputDmaInit;
165 #else
166 DMA_InitTypeDef inputDmaInit;
167 #endif
168 uint16_t *portInputBuffer;
169 uint32_t portInputCount;
170 bool inputActive;
172 // Misc
173 #ifdef DEBUG_COUNT_INTERRUPT
174 uint32_t outputIrq;
175 uint32_t inputIrq;
176 #endif
177 resourceOwner_t owner;
178 } bbPort_t;
180 // Per motor output
182 typedef struct bbMotor_s {
183 dshotProtocolControl_t protocolControl;
184 int pinIndex; // pinIndex of this motor output within a group that bbPort points to
185 int portIndex;
186 IO_t io; // IO_t for this output
187 uint8_t output;
188 uint32_t iocfg;
189 bbPort_t *bbPort;
190 bool configured;
191 bool enabled;
192 } bbMotor_t;
194 #define MAX_MOTOR_PACERS 4
195 extern FAST_DATA_ZERO_INIT bbPacer_t bbPacers[MAX_MOTOR_PACERS]; // TIM1 or TIM8
196 extern FAST_DATA_ZERO_INIT int usedMotorPacers;
198 extern FAST_DATA_ZERO_INIT bbPort_t bbPorts[MAX_SUPPORTED_MOTOR_PORTS];
199 extern FAST_DATA_ZERO_INIT int usedMotorPorts;
201 extern FAST_DATA_ZERO_INIT bbMotor_t bbMotors[MAX_SUPPORTED_MOTORS];
203 extern uint8_t bbPuPdMode;
205 // DMA buffers
206 // Note that we are not sharing input and output buffers,
207 // as output buffer is only modified for middle bits
209 // DMA output buffer:
210 // DShot requires 3 [word/bit] * 16 [bit] = 48 [word]
211 extern uint32_t bbOutputBuffer[MOTOR_DSHOT_BUF_CACHE_ALIGN_LENGTH * MAX_SUPPORTED_MOTOR_PORTS];
213 // DMA input buffer
214 // (30us + <frame time> + <slack>) / <input sampling clock period>
215 // <frame time> = <DShot symbol time> * 16
216 // Temporary size for DS600
217 // <frame time> = 26us
218 // <sampling period> = 0.44us
219 // <slack> = 10%
220 // (30 + 26 + 3) / 0.44 = 134
221 // In some cases this was not enough, so we add 6 extra samples
222 #define DSHOT_BB_PORT_IP_BUF_LENGTH 140
223 #ifdef USE_DSHOT_CACHE_MGMT
224 // Each sample is a uint16_t
225 // Number of bytes required for buffer
226 #define DSHOT_BB_PORT_IP_BUF_BYTES (DSHOT_BB_PORT_IP_BUF_LENGTH * sizeof(uint16_t))
227 // Number of bytes required to cache align buffer
228 #define DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_BYTES ((DSHOT_BB_PORT_IP_BUF_BYTES + 0x20) & ~0x1f)
229 // Size of array to create a cache aligned buffer
230 #define DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_LENGTH (DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_BYTES / sizeof(uint16_t))
231 #else
232 #define DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_LENGTH DSHOT_BB_PORT_IP_BUF_LENGTH
233 #endif
234 extern uint16_t bbInputBuffer[DSHOT_BB_PORT_IP_BUF_CACHE_ALIGN_LENGTH * MAX_SUPPORTED_MOTOR_PORTS];
236 void bbGpioSetup(bbMotor_t *bbMotor);
237 void bbTimerChannelInit(bbPort_t *bbPort);
238 void bbDMAPreconfigure(bbPort_t *bbPort, uint8_t direction);
239 void bbDMAIrqHandler(dmaChannelDescriptor_t *descriptor);
240 void bbSwitchToOutput(bbPort_t * bbPort);
241 void bbSwitchToInput(bbPort_t * bbPort);
243 void bbTIM_TimeBaseInit(bbPort_t *bbPort, uint16_t period);
244 void bbTIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState);
245 void bbDMA_ITConfig(bbPort_t *bbPort);
246 void bbDMA_Cmd(bbPort_t *bbPort, FunctionalState NewState);
247 int bbDMA_Count(bbPort_t *bbPort);