43 #ifndef STM32F0XX // No high-res delay on F0 yet
48 #if defined(PIOS_INCLUDE_DMASHOT)
128 TIM_OC1PreloadConfig(chan->
timer, TIM_OCPreload_Enable);
132 TIM_OC2PreloadConfig(chan->
timer, TIM_OCPreload_Enable);
136 TIM_OC3PreloadConfig(chan->
timer, TIM_OCPreload_Enable);
140 TIM_OC4PreloadConfig(chan->
timer, TIM_OCPreload_Enable);
144 TIM_ARRPreloadConfig(chan->
timer, ENABLE);
145 TIM_CtrlPWMOutputs(chan->
timer, ENABLE);
146 TIM_Cmd(chan->
timer, ENABLE);
150 if (output_channels == NULL) {
153 memset(output_channels, 0, servo_cfg->
num_channels *
sizeof(*output_channels));
167 for (i = 0; (i < servo_cfg->
num_channels) && (i < max_dio); i++) {
209 case (uintptr_t) GPIOA:
212 case (uintptr_t) GPIOB:
215 case (uintptr_t) GPIOC:
241 float period = 1.02f * bank->
max_pulse + 10.0f;
242 float num_ticks = period / 1e6f * max_tim_clock;
244 bank->
prescaler = num_ticks / 0xffff + 0.5f;
249 TIM_SelectOnePulseMode(bank->
timer, TIM_OPMode_Single);
251 uint16_t inverted_polarity = (servo_cfg->
tim_oc_init.TIM_OCPolarity == TIM_OCPolarity_Low) ?
252 TIM_OCPolarity_High : TIM_OCPolarity_Low;
253 TIM_OC1PolarityConfig(bank->
timer, inverted_polarity);
254 TIM_OC2PolarityConfig(bank->
timer, inverted_polarity);
255 TIM_OC3PolarityConfig(bank->
timer, inverted_polarity);
256 TIM_OC4PolarityConfig(bank->
timer, inverted_polarity);
266 bank->
prescaler = max_tim_clock / 1000000 - 1;
268 float num_ticks = (float)max_tim_clock / (
float)
rate;
270 bank->
prescaler = num_ticks / 0xffff + 0.5f;
277 TIM_SelectOnePulseMode(bank->
timer, TIM_OPMode_Repetitive);
280 TIM_Cmd(bank->
timer, ENABLE);
304 int PIOS_Servo_SetMode(
const uint16_t *out_rate,
const int banks,
const uint16_t *channel_max,
const uint16_t *channel_min)
310 #if defined(PIOS_INCLUDE_DMASHOT)
316 dshot_in_use =
false;
318 struct timer_bank timer_banks[PIOS_SERVO_MAX_BANKS];
320 memset(&timer_banks, 0,
sizeof(timer_banks));
334 for (
int j = 0;
j < banks_found;
j++) {
339 if ((bank < 0) && (banks_found < PIOS_SERVO_MAX_BANKS)) {
340 bank = banks_found++;
345 timer_banks[bank].
max_pulse =
MAX(timer_banks[bank].max_pulse, channel_max[
i]);
346 timer_banks[bank].
max_pulse =
MAX(timer_banks[bank].max_pulse, channel_min[i]);
351 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = servo_cfg->
tim_base_init;
352 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
353 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
354 for (
int i = 0;
i < banks_found;
i++) {
356 if (timer_banks[
i].max_pulse == 0)
362 if (!max_tim_clock) {
366 uint16_t
rate = out_rate[
i];
399 TIM_TimeBaseStructure.TIM_Prescaler = timer_banks[
i].
prescaler;
400 TIM_TimeBaseStructure.TIM_Period = timer_banks[
i].
period;
403 TIM_TimeBaseInit(timer_banks[i].timer, &TIM_TimeBaseStructure);
413 TIM_TimeBaseStructure.TIM_Prescaler = timer_banks[
i].
prescaler;
414 TIM_TimeBaseStructure.TIM_Period = timer_banks[
i].
period;
417 TIM_TimeBaseInit(timer_banks[i].timer, &TIM_TimeBaseStructure);
424 #if defined(PIOS_INCLUDE_DMASHOT)
471 if (timer_banks[
i].timer == chan->
timer) {
477 #if defined(PIOS_INCLUDE_DMASHOT)
496 if (channel_max[
j] >= channel_min[
j]) {
507 #if defined (PIOS_INCLUDE_DMASHOT)
524 raw_position = chan->
timer->ARR - raw_position;
530 TIM_SetCompare1(chan->
timer, raw_position);
533 TIM_SetCompare2(chan->
timer, raw_position);
536 TIM_SetCompare3(chan->
timer, raw_position);
539 TIM_SetCompare4(chan->
timer, raw_position);
547 uint16_t max_val, uint16_t min_val)
561 switch (output_channels[servo].
mode) {
576 uint16_t spread = max_val - min_val;
578 uint64_t val = min_val;
582 val += spread * fraction;
594 if (resetting && (fraction < 0xff00)) {
606 switch (output_channels[servo].
mode) {
636 switch (output_channels[servo].
mode) {
643 else if (position < 0)
655 float us_to_count = output_channels[
servo].
i.
pwm_res / 1000000.0f;
656 position = position * us_to_count;
668 #ifdef STM32F0XX // No high-res delay on F0 yet
676 bool triggered =
false;
691 switch (chan->
mode) {
697 #if defined(PIOS_INCLUDE_DMASHOT)
707 dshot_mode = chan->
mode;
708 }
else if (dshot_mode != chan->
mode) {
716 dshot_bits[info->
gpio] |= info->
pin;
720 uint16_t message = info->
value << 5;
723 if ((info->
value > 0) && (info->
value < 48)) {
728 ((message >> 4 ) & 0xf) ^
729 ((message >> 8 ) & 0xf) ^
730 ((message >> 12) & 0xf);
732 for (
int j = 0;
j < 16;
j++) {
733 if (! (message & 0x8000)) {
734 dshot_msg_zeroes[
j][info->
gpio] |= info->
pin;
743 #if defined(PIOS_INCLUDE_DMASHOT)
751 uint16_t time_0, time_1, time_tot;
765 switch (dshot_mode) {
794 register uint16_t a = dshot_bits[
DS_GPIOA];
795 register uint16_t b = dshot_bits[
DS_GPIOB];
796 register uint16_t c = dshot_bits[
DS_GPIOC];
801 for (
int i = 0;
i < 16;
i++) {
805 #if defined(STM32F40_41xxx) || defined(STM32F446xx)
806 #define CLEAR_BITS(gpio, bits) do { (gpio)->BSRRH = bits; } while (0)
807 #define SET_BITS(gpio, bits) do { (gpio)->BSRRL = bits; } while (0)
812 #define CLEAR_BITS(gpio, bits) do { (gpio)->BSRR = ((uint32_t) bits) << 16; } while (0)
813 #define SET_BITS(gpio, bits) do { (gpio)->BSRR = bits; } while (0)
822 uint32_t next_tick = start_cycle + time_0;
837 next_tick = start_cycle + time_1;
840 start_cycle += time_tot;
885 if (!(chan->
timer->CR1 & TIM_CR1_CEN)) {
887 TIM_GenerateEvent(chan->
timer, TIM_EventSource_Update);
888 TIM_Cmd(chan->
timer, ENABLE);
894 dshot_in_use =
false;
905 #if defined(STM32F0XX)
911 #elif defined(STM32F10X_MD)
915 if (timer == TIM1 || timer == TIM8)
921 #elif defined(STM32F30X)
925 if (timer == TIM2 || timer == TIM3 || timer == TIM4)
931 #elif defined(STM32F40_41xxx) || defined(STM32F446xx)
935 if (timer == TIM1 || timer == TIM8 || timer == TIM9 || timer == TIM10 || timer == TIM11)
942 #error Unsupported microcontroller
959 if (timer == TIM6 || timer == TIM7) {
974 return apb_clock * 2;
int32_t PIOS_IRQ_Enable(void)
Main PiOS header to include all the compiled in PiOS options.
void PIOS_DMAShot_Prepare()
Makes sure the DMAShot driver has allocated all internal structs.
bool PIOS_Servo_IsDshot(uint8_t servo)
static uint32_t channel_mask
void PIOS_DMAShot_InitializeTimers(TIM_OCInitTypeDef *ocinit)
Initializes and configures the registered timers for DMAShot operation.
void PIOS_TIM_InitTimerPin(uintptr_t tim_id, int idx)
static uint32_t PIOS_INLINEDELAY_NsToCycles(uint32_t ns)
#define DIO_MAKE_TAG(port, pin)
void PIOS_DMAShot_Validate()
Validates any timer and servo registrations.
static int DSHOT_Update()
void * PIOS_malloc(size_t size)
bool PIOS_DMAShot_RegisterTimer(TIM_TypeDef *timer, uint32_t clockrate, uint32_t dshot_freq)
Tells the DMAShot driver about a timer that needs to be set up.
bool PIOS_DMAShot_RegisterServo(const struct pios_tim_channel *servo_channel)
Tells the DMAShot driver about a servo that needs to be set up.
const struct pios_tim_channel * channels
void PIOS_Servo_Set(uint8_t servo, float position)
void PIOS_Servo_SetFraction(uint8_t servo, uint16_t fraction, uint16_t max_val, uint16_t min_val)
static struct flyingpicmd_cfg_fa cfg
int PIOS_Servo_GetPins(dio_tag_t *dios, int max_dio)
bool PIOS_DMAShot_IsConfigured()
Checks whether DMAShot has been configured.
static uint32_t timer_apb_clock(TIM_TypeDef *timer)
void PIOS_Servo_DisableChannel(int channel)
static void ChannelSetup_DShot(int j, uint16_t rate)
void PIOS_Servo_PrepareForReset()
Determines the APB clock used by a given timer.
void PIOS_DMAShot_InitializeGPIOs()
Initializes the GPIO on the registered servos for DMAShot operation.
#define PIOS_PERIPHERAL_APB1_CLOCK
void PIOS_DMAShot_InitializeDMAs()
Initializes and configures the known DMA channels for DMAShot operation.
union output_channel::@19 i
TIM_OCInitTypeDef tim_oc_init
static struct output_channel * output_channels
int PIOS_Servo_SetMode(const uint16_t *out_rate, const int banks, const uint16_t *channel_max, const uint16_t *channel_min)
PIOS_Servo_SetMode Sets the PWM output frequency and resolution. An output rate of 0 indicates Synchr...
Servo private structures.
int32_t PIOS_Servo_Init(const struct pios_servo_cfg *cfg)
#define CLEAR_BITS(gpio, bits)
static void PIOS_INLINEDELAY_TillCycleCnt(uint32_t whence)
int32_t PIOS_IRQ_Disable(void)
static int BankSetup_OneShot(struct timer_bank *bank, int32_t max_tim_clock)
int32_t PIOS_TIM_InitChannels(uintptr_t *tim_id, const struct pios_tim_channel *channels, uint8_t num_channels, const struct pios_tim_callbacks *callbacks, uintptr_t context)
#define SET_BITS(gpio, bits)
static int BankSetup_DShot(struct timer_bank *bank)
static uintptr_t servo_tim_id
static uint32_t PIOS_INLINEDELAY_GetCycleCnt()
void PIOS_DMAShot_WriteValue(const struct pios_tim_channel *servo_channel, uint16_t throttle)
Sets the throttle value of a specific servo.
void PIOS_TIM_SetBankToGPOut(uintptr_t tim_id, TIM_TypeDef *timer)
#define PIOS_PERIPHERAL_APB2_CLOCK
TIM_TimeBaseInitTypeDef tim_base_init
#define PIOS_SERVO_MAX_BANKS
dshot_gpio
The counter rate for the channel, used to calculate compare values.
void PIOS_Servo_Update(void)
bool PIOS_DMAShot_IsReady()
Checks whether DMAShot is ready for use (i.e. at least one DMA configured timer). ...
struct dshot_info __attribute__
static int BankSetup_PWM(struct timer_bank *bank, int32_t max_tim_clock, uint16_t rate)
static uint32_t max_timer_clock(TIM_TypeDef *timer)
Determines the maximum clock rate for a given timer (i.e. no prescale)
#define PIOS_Assert(test)
void PIOS_DMAShot_TriggerUpdate()
Triggers the configured DMA channels to fire and send throttle values to the timer DMAR and optional ...
static void PIOS_Servo_SetRaw(uint8_t servo, uint32_t raw_position)
static const struct pios_servo_cfg * servo_cfg