2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
22 #include "drivers/io_types.h"
23 #include "drivers/pwm_output_counts.h"
24 #include "drivers/timer.h"
27 #define ALL_MOTORS 255
29 #define DSHOT_MAX_COMMAND 47
32 DshotSettingRequest (KISS24). Spin direction, 3d and save Settings reqire 10 requests.. and the TLM Byte must always be high if 1-47 are used to send settings
36 48 (low) - 1047 (high) -> negative direction
37 1048 (low) - 2047 (high) -> positive direction
41 DSHOT_CMD_MOTOR_STOP
= 0,
47 DSHOT_CMD_ESC_INFO
, // V2 includes settings
48 DSHOT_CMD_SPIN_DIRECTION_1
,
49 DSHOT_CMD_SPIN_DIRECTION_2
,
50 DSHOT_CMD_3D_MODE_OFF
,
52 DSHOT_CMD_SETTINGS_REQUEST
, // Currently not implemented
53 DSHOT_CMD_SAVE_SETTINGS
,
54 DSHOT_CMD_SPIN_DIRECTION_NORMAL
= 20,
55 DSHOT_CMD_SPIN_DIRECTION_REVERSED
= 21,
56 DSHOT_CMD_LED0_ON
, // BLHeli32 only
57 DSHOT_CMD_LED1_ON
, // BLHeli32 only
58 DSHOT_CMD_LED2_ON
, // BLHeli32 only
59 DSHOT_CMD_LED3_ON
, // BLHeli32 only
60 DSHOT_CMD_LED0_OFF
, // BLHeli32 only
61 DSHOT_CMD_LED1_OFF
, // BLHeli32 only
62 DSHOT_CMD_LED2_OFF
, // BLHeli32 only
63 DSHOT_CMD_LED3_OFF
, // BLHeli32 only
64 DSHOT_CMD_AUDIO_STREAM_MODE_ON_OFF
= 30, // KISS audio Stream mode on/Off
65 DSHOT_CMD_SILENT_MODE_ON_OFF
= 31, // KISS silent Mode on/Off
71 PWM_TYPE_STANDARD
= 0,
84 } motorPwmProtocolTypes_e
;
86 #define PWM_TIMER_1MHZ MHZ_TO_HZ(1)
89 #define MAX_DMA_TIMERS 8
91 #define MOTOR_DSHOT1200_HZ MHZ_TO_HZ(24)
92 #define MOTOR_DSHOT600_HZ MHZ_TO_HZ(12)
93 #define MOTOR_DSHOT300_HZ MHZ_TO_HZ(6)
94 #define MOTOR_DSHOT150_HZ MHZ_TO_HZ(3)
97 #define MOTOR_BIT_1 14
98 #define MOTOR_BITLENGTH 19
100 #define MOTOR_PROSHOT1000_HZ MHZ_TO_HZ(24)
101 #define PROSHOT_BASE_SYMBOL 24 // 1uS
102 #define PROSHOT_BIT_WIDTH 3
103 #define MOTOR_NIBBLE_LENGTH_PROSHOT 96 // 4uS
107 #define DSHOT_DMA_BUFFER_SIZE 18 /* resolution + frame reset (2us) */
108 #define PROSHOT_DMA_BUFFER_SIZE 6 /* resolution + frame reset (2us) */
112 #if defined(USE_DSHOT) && defined(USE_DSHOT_DMAR)
113 #if !defined(USE_HAL_DRIVER)
115 DMA_Channel_TypeDef
*dmaBurstRef
;
117 DMA_Stream_TypeDef
*dmaBurstRef
;
119 uint16_t dmaBurstLength
;
122 uint32_t dmaBurstBuffer
[DSHOT_DMA_BUFFER_SIZE
* 4];
123 uint16_t timerDmaSources
;
128 const timerHardware_t
*timerHardware
;
131 uint16_t timerDmaSource
;
134 motorDmaTimer_t
*timer
;
135 volatile bool requestTelemetry
;
136 #if defined(STM32F3) || defined(STM32F4) || defined(STM32F7)
137 uint32_t dmaBuffer
[DSHOT_DMA_BUFFER_SIZE
];
139 uint8_t dmaBuffer
[DSHOT_DMA_BUFFER_SIZE
];
141 #if defined(USE_HAL_DRIVER)
142 TIM_HandleTypeDef TimHandle
;
143 DMA_HandleTypeDef hdma_tim
;
144 uint16_t timerDmaIndex
;
148 motorDmaOutput_t
*getMotorDmaOutput(uint8_t index
);
150 struct timerHardware_s
;
151 typedef void pwmWriteFn(uint8_t index
, float value
); // function pointer used to write motors
152 typedef void pwmCompleteWriteFn(uint8_t motorCount
); // function pointer used after motors are written
155 volatile timCCR_t
*ccr
;
160 timerChannel_t channel
;
168 //CAVEAT: This is used in the `motorConfig_t` parameter group, so the parameter group constraints apply
169 typedef struct motorDevConfig_s
{
170 uint16_t motorPwmRate
; // The update rate of motor outputs (50-498Hz)
171 uint8_t motorPwmProtocol
; // Pwm Protocol
172 uint8_t motorPwmInversion
; // Active-High vs Active-Low. Useful for brushed FCs converted for brushless operation
173 uint8_t useUnsyncedPwm
;
174 uint8_t useBurstDshot
;
175 ioTag_t ioTags
[MAX_SUPPORTED_MOTORS
];
178 extern bool useBurstDshot
;
180 void motorDevInit(const motorDevConfig_t
*motorDevConfig
, uint16_t idlePulse
, uint8_t motorCount
);
182 typedef struct servoDevConfig_s
{
183 // PWM values, in milliseconds, common range is 1000-2000 (1ms to 2ms)
184 uint16_t servoCenterPulse
; // This is the value for servos when they should be in the middle. e.g. 1500.
185 uint16_t servoPwmRate
; // The update rate of servo outputs (50-498Hz)
186 ioTag_t ioTags
[MAX_SUPPORTED_SERVOS
];
189 void servoDevInit(const servoDevConfig_t
*servoDevConfig
);
191 void pwmServoConfig(const struct timerHardware_s
*timerHardware
, uint8_t servoIndex
, uint16_t servoPwmRate
, uint16_t servoCenterPulse
);
193 bool isMotorProtocolDshot(void);
196 typedef uint8_t loadDmaBufferFn(uint32_t *dmaBuffer
, int stride
, uint16_t packet
); // function pointer used to encode a digital motor value into the DMA buffer representation
198 uint16_t prepareDshotPacket(motorDmaOutput_t
*const motor
, uint16_t value
);
200 extern loadDmaBufferFn
*loadDmaBuffer
;
202 uint32_t getDshotHz(motorPwmProtocolTypes_e pwmProtocolType
);
203 void pwmWriteDshotCommand(uint8_t index
, uint8_t motorCount
, uint8_t command
);
204 void pwmWriteDshotInt(uint8_t index
, uint16_t value
);
205 void pwmDshotMotorHardwareConfig(const timerHardware_t
*timerHardware
, uint8_t motorIndex
, motorPwmProtocolTypes_e pwmProtocolType
, uint8_t output
);
206 void pwmCompleteDshotMotorUpdate(uint8_t motorCount
);
210 void pwmWriteBeeper(bool onoffBeep
);
211 void pwmToggleBeeper(void);
212 void beeperPwmInit(const ioTag_t tag
, uint16_t frequency
);
214 void pwmOutConfig(timerChannel_t
*channel
, const timerHardware_t
*timerHardware
, uint32_t hz
, uint16_t period
, uint16_t value
, uint8_t inversion
);
216 void pwmWriteMotor(uint8_t index
, float value
);
217 void pwmShutdownPulsesForAllMotors(uint8_t motorCount
);
218 void pwmCompleteMotorUpdate(uint8_t motorCount
);
220 void pwmWriteServo(uint8_t index
, float value
);
222 pwmOutputPort_t
*pwmGetMotors(void);
223 bool pwmIsSynced(void);
224 void pwmDisableMotors(void);
225 void pwmEnableMotors(void);
226 bool pwmAreMotorsEnabled(void);