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/>.
28 #include "pwm_output.h"
30 #include "pwm_mapping.h"
32 void pwmBrushedMotorConfig(const timerHardware_t
*timerHardware
, uint8_t motorIndex
, uint16_t motorPwmRate
, uint16_t idlePulse
);
33 void pwmBrushlessMotorConfig(const timerHardware_t
*timerHardware
, uint8_t motorIndex
, uint16_t motorPwmRate
, uint16_t idlePulse
);
34 void pwmOneshotMotorConfig(const timerHardware_t
*timerHardware
, uint8_t motorIndex
);
35 void pwmServoConfig(const timerHardware_t
*timerHardware
, uint8_t servoIndex
, uint16_t servoPwmRate
, uint16_t servoCenterPulse
);
40 Note: this documentation is only valid for STM32F10x, for STM32F30x please read the code itself.
42 1) multirotor PPM input
44 PWM5..8 used for motors
45 PWM9..10 used for servo or else motors
46 PWM11..14 used for motors
48 2) multirotor PPM input with more servos
50 PWM5..8 used for motors
51 PWM9..10 used for servo or else motors
52 PWM11..14 used for servos
54 2) multirotor PWM input
55 PWM1..8 used for input
56 PWM9..10 used for servo or else motors
57 PWM11..14 used for motors
59 3) airplane / flying wing w/PWM
60 PWM1..8 used for input
61 PWM9 used for motor throttle +PWM10 for 2nd motor
62 PWM11.14 used for servos
64 4) airplane / flying wing with PPM
66 PWM5..8 used for servos
67 PWM9 used for motor throttle +PWM10 for 2nd motor
68 PWM11.14 used for servos
78 #if defined(NAZE) || defined(OLIMEXINO) || defined(NAZE32PRO) || defined(STM32F3DISCOVERY) || defined(EUSTM32F103RC) || defined(PORT103R)
79 static const uint16_t multiPPM
[] = {
80 PWM1
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
81 PWM9
| (MAP_TO_SERVO_OUTPUT
<< 8), // Swap to servo if needed
82 PWM10
| (MAP_TO_SERVO_OUTPUT
<< 8), // Swap to servo if needed
83 PWM11
| (MAP_TO_SERVO_OUTPUT
<< 8),
84 PWM12
| (MAP_TO_SERVO_OUTPUT
<< 8),
85 PWM13
| (MAP_TO_MOTOR_OUTPUT
<< 8),
86 PWM14
| (MAP_TO_MOTOR_OUTPUT
<< 8),
87 PWM5
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
88 PWM6
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
89 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
90 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
94 static const uint16_t multiPWM
[] = {
95 PWM1
| (MAP_TO_PWM_INPUT
<< 8), // input #1
96 PWM2
| (MAP_TO_PWM_INPUT
<< 8),
97 PWM3
| (MAP_TO_PWM_INPUT
<< 8),
98 PWM4
| (MAP_TO_PWM_INPUT
<< 8),
99 PWM5
| (MAP_TO_PWM_INPUT
<< 8),
100 PWM6
| (MAP_TO_PWM_INPUT
<< 8),
101 PWM7
| (MAP_TO_PWM_INPUT
<< 8),
102 PWM8
| (MAP_TO_PWM_INPUT
<< 8), // input #8
103 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #1 or servo #1 (swap to servo if needed)
104 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #2 or servo #2 (swap to servo if needed)
105 PWM11
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #1 or #3
106 PWM12
| (MAP_TO_MOTOR_OUTPUT
<< 8),
107 PWM13
| (MAP_TO_MOTOR_OUTPUT
<< 8),
108 PWM14
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #4 or #6
112 static const uint16_t airPPM
[] = {
113 PWM1
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
114 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #1
115 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #2
116 PWM11
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #1
117 PWM12
| (MAP_TO_SERVO_OUTPUT
<< 8),
118 PWM13
| (MAP_TO_SERVO_OUTPUT
<< 8),
119 PWM14
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #4
120 PWM5
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #5
121 PWM6
| (MAP_TO_SERVO_OUTPUT
<< 8),
122 PWM7
| (MAP_TO_SERVO_OUTPUT
<< 8),
123 PWM8
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #8
127 static const uint16_t airPWM
[] = {
128 PWM1
| (MAP_TO_PWM_INPUT
<< 8), // input #1
129 PWM2
| (MAP_TO_PWM_INPUT
<< 8),
130 PWM3
| (MAP_TO_PWM_INPUT
<< 8),
131 PWM4
| (MAP_TO_PWM_INPUT
<< 8),
132 PWM5
| (MAP_TO_PWM_INPUT
<< 8),
133 PWM6
| (MAP_TO_PWM_INPUT
<< 8),
134 PWM7
| (MAP_TO_PWM_INPUT
<< 8),
135 PWM8
| (MAP_TO_PWM_INPUT
<< 8), // input #8
136 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #1
137 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #2
138 PWM11
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #1
139 PWM12
| (MAP_TO_SERVO_OUTPUT
<< 8),
140 PWM13
| (MAP_TO_SERVO_OUTPUT
<< 8),
141 PWM14
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #4
147 static const uint16_t multiPPM
[] = {
148 PWM1
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
149 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
150 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
151 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8),
152 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8),
153 PWM11
| (MAP_TO_MOTOR_OUTPUT
<< 8),
154 PWM12
| (MAP_TO_MOTOR_OUTPUT
<< 8),
155 PWM2
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
156 PWM3
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
157 PWM4
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
158 PWM5
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
159 PWM6
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
162 static const uint16_t multiPWM
[] = {
163 PWM1
| (MAP_TO_PWM_INPUT
<< 8), // input #1
164 PWM2
| (MAP_TO_PWM_INPUT
<< 8),
165 PWM3
| (MAP_TO_PWM_INPUT
<< 8),
166 PWM4
| (MAP_TO_PWM_INPUT
<< 8),
167 PWM5
| (MAP_TO_PWM_INPUT
<< 8),
168 PWM6
| (MAP_TO_PWM_INPUT
<< 8), // input #6
169 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #1 or servo #1 (swap to servo if needed)
170 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #2 or servo #2 (swap to servo if needed)
171 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #1 or #3
172 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8),
173 PWM11
| (MAP_TO_MOTOR_OUTPUT
<< 8),
174 PWM12
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #4 or #6
178 static const uint16_t airPPM
[] = {
179 PWM1
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
180 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8),
181 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8),
182 PWM9
| (MAP_TO_SERVO_OUTPUT
<< 8),
183 PWM10
| (MAP_TO_SERVO_OUTPUT
<< 8),
184 PWM11
| (MAP_TO_SERVO_OUTPUT
<< 8),
185 PWM12
| (MAP_TO_SERVO_OUTPUT
<< 8),
186 PWM2
| (MAP_TO_SERVO_OUTPUT
<< 8),
187 PWM3
| (MAP_TO_SERVO_OUTPUT
<< 8),
188 PWM4
| (MAP_TO_SERVO_OUTPUT
<< 8),
189 PWM5
| (MAP_TO_SERVO_OUTPUT
<< 8),
190 PWM6
| (MAP_TO_SERVO_OUTPUT
<< 8),
194 static const uint16_t airPWM
[] = {
195 PWM1
| (MAP_TO_PWM_INPUT
<< 8), // input #1
196 PWM2
| (MAP_TO_PWM_INPUT
<< 8),
197 PWM3
| (MAP_TO_PWM_INPUT
<< 8),
198 PWM4
| (MAP_TO_PWM_INPUT
<< 8),
199 PWM5
| (MAP_TO_PWM_INPUT
<< 8),
200 PWM6
| (MAP_TO_PWM_INPUT
<< 8), // input #6
201 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #1
202 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #2
203 PWM9
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #1
204 PWM10
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #2
205 PWM11
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #3
206 PWM12
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #4
212 static const uint16_t multiPPM
[] = {
213 PWM1
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
214 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8),
215 PWM14
| (MAP_TO_MOTOR_OUTPUT
<< 8),
216 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8),
217 PWM13
| (MAP_TO_MOTOR_OUTPUT
<< 8),
221 static const uint16_t multiPWM
[] = {
222 PWM1
| (MAP_TO_PWM_INPUT
<< 8),
223 PWM2
| (MAP_TO_PWM_INPUT
<< 8),
224 PWM3
| (MAP_TO_PWM_INPUT
<< 8),
225 PWM4
| (MAP_TO_PWM_INPUT
<< 8),
226 PWM9
| (MAP_TO_PWM_INPUT
<< 8),
227 PWM10
| (MAP_TO_PWM_INPUT
<< 8),
228 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8),
229 PWM14
| (MAP_TO_MOTOR_OUTPUT
<< 8),
230 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8),
231 PWM13
| (MAP_TO_MOTOR_OUTPUT
<< 8),
235 static const uint16_t airPPM
[] = {
239 static const uint16_t airPWM
[] = {
245 static const uint16_t multiPPM
[] = {
246 PWM1
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
247 PWM2
| (MAP_TO_MOTOR_OUTPUT
<< 8),
248 PWM3
| (MAP_TO_MOTOR_OUTPUT
<< 8),
249 PWM4
| (MAP_TO_MOTOR_OUTPUT
<< 8),
250 PWM5
| (MAP_TO_MOTOR_OUTPUT
<< 8),
251 PWM6
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
252 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
253 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
254 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
255 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
256 PWM11
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
260 static const uint16_t multiPWM
[] = {
265 static const uint16_t airPPM
[] = {
266 PWM1
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
267 PWM2
| (MAP_TO_MOTOR_OUTPUT
<< 8),
268 PWM3
| (MAP_TO_MOTOR_OUTPUT
<< 8),
269 PWM4
| (MAP_TO_MOTOR_OUTPUT
<< 8),
270 PWM5
| (MAP_TO_MOTOR_OUTPUT
<< 8),
271 PWM6
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
272 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
273 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
274 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
275 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
276 PWM11
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
280 static const uint16_t airPWM
[] = {
286 #if defined(SPARKY) || defined(ALIENWIIF3)
287 static const uint16_t multiPPM
[] = {
288 PWM11
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
290 PWM1
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM15
291 PWM2
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM15
292 PWM3
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM1
293 PWM4
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM3
294 PWM5
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM3
295 PWM6
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM2
296 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM3
297 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM17
298 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM3
299 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8), // TIM2
303 static const uint16_t multiPWM
[] = {
304 PWM1
| (MAP_TO_MOTOR_OUTPUT
<< 8),
305 PWM2
| (MAP_TO_MOTOR_OUTPUT
<< 8),
306 PWM3
| (MAP_TO_MOTOR_OUTPUT
<< 8),
307 PWM4
| (MAP_TO_MOTOR_OUTPUT
<< 8),
308 PWM5
| (MAP_TO_MOTOR_OUTPUT
<< 8),
309 PWM6
| (MAP_TO_MOTOR_OUTPUT
<< 8),
310 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8),
311 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8),
312 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8),
313 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8),
317 static const uint16_t airPPM
[] = {
322 static const uint16_t airPWM
[] = {
329 static const uint16_t multiPPM
[] = {
330 PWM1
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
332 PWM9
| (MAP_TO_SERVO_OUTPUT
<< 8),
333 PWM10
| (MAP_TO_SERVO_OUTPUT
<< 8),
334 PWM11
| (MAP_TO_SERVO_OUTPUT
<< 8),
335 PWM12
| (MAP_TO_SERVO_OUTPUT
<< 8),
336 PWM13
| (MAP_TO_MOTOR_OUTPUT
<< 8),
337 PWM14
| (MAP_TO_MOTOR_OUTPUT
<< 8),
338 PWM15
| (MAP_TO_MOTOR_OUTPUT
<< 8),
339 PWM16
| (MAP_TO_MOTOR_OUTPUT
<< 8),
340 PWM5
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
341 PWM6
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
342 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
343 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8), // Swap to servo if needed
347 static const uint16_t multiPWM
[] = {
348 PWM1
| (MAP_TO_PWM_INPUT
<< 8),
349 PWM2
| (MAP_TO_PWM_INPUT
<< 8),
350 PWM3
| (MAP_TO_PWM_INPUT
<< 8),
351 PWM4
| (MAP_TO_PWM_INPUT
<< 8),
352 PWM5
| (MAP_TO_PWM_INPUT
<< 8),
353 PWM6
| (MAP_TO_PWM_INPUT
<< 8),
354 PWM7
| (MAP_TO_PWM_INPUT
<< 8),
355 PWM8
| (MAP_TO_PWM_INPUT
<< 8),
356 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8),
357 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8),
358 PWM11
| (MAP_TO_MOTOR_OUTPUT
<< 8),
359 PWM12
| (MAP_TO_MOTOR_OUTPUT
<< 8),
360 PWM13
| (MAP_TO_MOTOR_OUTPUT
<< 8),
361 PWM14
| (MAP_TO_MOTOR_OUTPUT
<< 8),
362 PWM15
| (MAP_TO_MOTOR_OUTPUT
<< 8),
363 PWM16
| (MAP_TO_MOTOR_OUTPUT
<< 8),
367 static const uint16_t airPPM
[] = {
368 PWM1
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
369 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #1
370 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #2
371 PWM11
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #1
372 PWM12
| (MAP_TO_SERVO_OUTPUT
<< 8),
373 PWM13
| (MAP_TO_SERVO_OUTPUT
<< 8),
374 PWM14
| (MAP_TO_SERVO_OUTPUT
<< 8),
375 PWM15
| (MAP_TO_SERVO_OUTPUT
<< 8),
376 PWM16
| (MAP_TO_SERVO_OUTPUT
<< 8),
377 PWM5
| (MAP_TO_SERVO_OUTPUT
<< 8),
378 PWM6
| (MAP_TO_SERVO_OUTPUT
<< 8),
379 PWM7
| (MAP_TO_SERVO_OUTPUT
<< 8),
380 PWM8
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #10
384 static const uint16_t airPWM
[] = {
385 PWM1
| (MAP_TO_PWM_INPUT
<< 8), // input #1
386 PWM2
| (MAP_TO_PWM_INPUT
<< 8),
387 PWM3
| (MAP_TO_PWM_INPUT
<< 8),
388 PWM4
| (MAP_TO_PWM_INPUT
<< 8),
389 PWM5
| (MAP_TO_PWM_INPUT
<< 8),
390 PWM6
| (MAP_TO_PWM_INPUT
<< 8),
391 PWM7
| (MAP_TO_PWM_INPUT
<< 8),
392 PWM8
| (MAP_TO_PWM_INPUT
<< 8), // input #8
393 PWM9
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #1
394 PWM10
| (MAP_TO_MOTOR_OUTPUT
<< 8), // motor #2
395 PWM11
| (MAP_TO_SERVO_OUTPUT
<< 8), // servo #1
396 PWM12
| (MAP_TO_SERVO_OUTPUT
<< 8),
397 PWM13
| (MAP_TO_SERVO_OUTPUT
<< 8),
398 PWM14
| (MAP_TO_SERVO_OUTPUT
<< 8),
399 PWM15
| (MAP_TO_SERVO_OUTPUT
<< 8),
400 PWM16
| (MAP_TO_SERVO_OUTPUT
<< 8), // server #6
406 static const uint16_t multiPPM
[] = {
407 PWM9
| (MAP_TO_PPM_INPUT
<< 8), // PPM input
409 PWM1
| (MAP_TO_MOTOR_OUTPUT
<< 8),
410 PWM2
| (MAP_TO_MOTOR_OUTPUT
<< 8),
411 PWM3
| (MAP_TO_MOTOR_OUTPUT
<< 8),
412 PWM4
| (MAP_TO_MOTOR_OUTPUT
<< 8),
413 PWM5
| (MAP_TO_MOTOR_OUTPUT
<< 8),
414 PWM6
| (MAP_TO_MOTOR_OUTPUT
<< 8),
415 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8),
416 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8),
420 static const uint16_t multiPWM
[] = {
421 PWM1
| (MAP_TO_MOTOR_OUTPUT
<< 8),
422 PWM2
| (MAP_TO_MOTOR_OUTPUT
<< 8),
423 PWM3
| (MAP_TO_MOTOR_OUTPUT
<< 8),
424 PWM4
| (MAP_TO_MOTOR_OUTPUT
<< 8),
425 PWM5
| (MAP_TO_MOTOR_OUTPUT
<< 8),
426 PWM6
| (MAP_TO_MOTOR_OUTPUT
<< 8),
427 PWM7
| (MAP_TO_MOTOR_OUTPUT
<< 8),
428 PWM8
| (MAP_TO_MOTOR_OUTPUT
<< 8),
432 static const uint16_t airPPM
[] = {
437 static const uint16_t airPWM
[] = {
443 static const uint16_t * const hardwareMaps
[] = {
450 pwmOutputConfiguration_t
*pwmInit(drv_pwm_config_t
*init
)
453 const uint16_t *setup
;
455 int channelIndex
= 0;
457 static pwmOutputConfiguration_t pwmOutputConfiguration
;
459 memset(&pwmOutputConfiguration
, 0, sizeof(pwmOutputConfiguration
));
461 // this is pretty hacky shit, but it will do for now. array of 4 config maps, [ multiPWM multiPPM airPWM airPPM ]
463 i
= 2; // switch to air hardware config
464 if (init
->usePPM
|| init
->useSerialRx
)
465 i
++; // next index is for PPM
467 setup
= hardwareMaps
[i
];
469 for (i
= 0; i
< USABLE_TIMER_CHANNEL_COUNT
&& setup
[i
] != 0xFFFF; i
++) {
470 uint8_t timerIndex
= setup
[i
] & 0x00FF;
471 uint8_t type
= (setup
[i
] & 0xFF00) >> 8;
473 const timerHardware_t
*timerHardwarePtr
= &timerHardware
[timerIndex
];
475 #ifdef OLIMEXINO_UNCUT_LED2_E_JUMPER
476 // PWM2 is connected to LED2 on the board and cannot be connected unless you cut LED2_E
477 if (timerIndex
== PWM2
)
483 if (init
->useUART2
&& (timerIndex
== PWM3
|| timerIndex
== PWM4
))
487 #if defined(STM32F303xC) && defined(USE_USART3)
488 // skip UART3 ports (PB10/PB11)
489 if (init
->useUART3
&& timerHardwarePtr
->gpio
== UART3_GPIO
&& (timerHardwarePtr
->pin
== UART3_TX_PIN
|| timerHardwarePtr
->pin
== UART3_RX_PIN
))
493 #ifdef SOFTSERIAL_1_TIMER
494 if (init
->useSoftSerial
&& timerHardwarePtr
->tim
== SOFTSERIAL_1_TIMER
)
497 #ifdef SOFTSERIAL_2_TIMER
498 if (init
->useSoftSerial
&& timerHardwarePtr
->tim
== SOFTSERIAL_2_TIMER
)
502 #ifdef LED_STRIP_TIMER
503 // skip LED Strip output
504 if (init
->useLEDStrip
) {
505 if (timerHardwarePtr
->tim
== LED_STRIP_TIMER
)
507 #if defined(STM32F303xC) && defined(WS2811_GPIO) && defined(WS2811_PIN_SOURCE)
508 if (timerHardwarePtr
->gpio
== WS2811_GPIO
&& timerHardwarePtr
->gpioPinSource
== WS2811_PIN_SOURCE
)
516 if (init
->useVbat
&& timerHardwarePtr
->gpio
== VBAT_ADC_GPIO
&& timerHardwarePtr
->pin
== VBAT_ADC_GPIO_PIN
) {
522 if (init
->useRSSIADC
&& timerHardwarePtr
->gpio
== RSSI_ADC_GPIO
&& timerHardwarePtr
->pin
== RSSI_ADC_GPIO_PIN
) {
527 #ifdef CURRENT_METER_ADC_GPIO
528 if (init
->useCurrentMeterADC
&& timerHardwarePtr
->gpio
== CURRENT_METER_ADC_GPIO
&& timerHardwarePtr
->pin
== CURRENT_METER_ADC_GPIO_PIN
) {
534 if (init
->sonarGPIOConfig
&& timerHardwarePtr
->gpio
== init
->sonarGPIOConfig
->gpio
&&
536 timerHardwarePtr
->pin
== init
->sonarGPIOConfig
->triggerPin
||
537 timerHardwarePtr
->pin
== init
->sonarGPIOConfig
->echoPin
544 // hacks to allow current functionality
545 if (type
== MAP_TO_PWM_INPUT
&& !init
->useParallelPWM
)
548 if (type
== MAP_TO_PPM_INPUT
&& !init
->usePPM
)
552 if (init
->useServos
&& !init
->airplane
) {
554 // remap PWM9+10 as servos
555 if ((timerIndex
== PWM9
|| timerIndex
== PWM10
) && timerHardwarePtr
->tim
== TIM1
)
556 type
= MAP_TO_SERVO_OUTPUT
;
559 #if defined(COLIBRI_RACE)
560 // remap PWM1+2 as servos
561 if ((timerIndex
== PWM6
|| timerIndex
== PWM7
|| timerIndex
== PWM8
|| timerIndex
== PWM9
) && timerHardwarePtr
->tim
== TIM2
)
562 type
= MAP_TO_SERVO_OUTPUT
;
567 if (timerIndex
== PWM10
&& timerHardwarePtr
->tim
== TIM1
)
568 type
= MAP_TO_SERVO_OUTPUT
;
572 // remap PWM1+2 as servos
573 if ((timerIndex
== PWM1
|| timerIndex
== PWM2
) && timerHardwarePtr
->tim
== TIM15
)
574 type
= MAP_TO_SERVO_OUTPUT
;
577 #if defined(SPRACINGF3)
578 // remap PWM15+16 as servos
579 if ((timerIndex
== PWM15
|| timerIndex
== PWM16
) && timerHardwarePtr
->tim
== TIM15
)
580 type
= MAP_TO_SERVO_OUTPUT
;
583 #if defined(NAZE32PRO) || (defined(STM32F3DISCOVERY) && !defined(CHEBUZZF3))
584 // remap PWM 5+6 or 9+10 as servos - softserial pin pairs require timer ports that use the same timer
585 if (init
->useSoftSerial
) {
586 if (timerIndex
== PWM5
|| timerIndex
== PWM6
)
587 type
= MAP_TO_SERVO_OUTPUT
;
589 if (timerIndex
== PWM9
|| timerIndex
== PWM10
)
590 type
= MAP_TO_SERVO_OUTPUT
;
595 // remap PWM 7+8 as servos
596 if (timerIndex
== PWM7
|| timerIndex
== PWM8
)
597 type
= MAP_TO_SERVO_OUTPUT
;
601 if (init
->useChannelForwarding
&& !init
->airplane
) {
602 #if defined(NAZE) && defined(LED_STRIP_TIMER)
603 // if LED strip is active, PWM5-8 are unavailable, so map AUX1+AUX2 to PWM13+PWM14
604 if (init
->useLEDStrip
) {
605 if (timerIndex
>= PWM13
&& timerIndex
<= PWM14
) {
606 type
= MAP_TO_SERVO_OUTPUT
;
610 // remap PWM5..8 as servos when used in extended servo mode
611 if (timerIndex
>= PWM5
&& timerIndex
<= PWM8
)
612 type
= MAP_TO_SERVO_OUTPUT
;
617 if (init
->useParallelPWM
) {
618 // Skip PWM inputs that conflict with timers used outputs.
619 if ((type
== MAP_TO_SERVO_OUTPUT
|| type
== MAP_TO_MOTOR_OUTPUT
) && (timerHardwarePtr
->tim
== TIM2
|| timerHardwarePtr
->tim
== TIM3
)) {
622 if (type
== MAP_TO_PWM_INPUT
&& timerHardwarePtr
->tim
== TIM4
) {
629 if (type
== MAP_TO_PPM_INPUT
) {
631 if (init
->useOneshot
|| isMotorBrushed(init
->motorPwmRate
)) {
632 ppmAvoidPWMTimerClash(timerHardwarePtr
, TIM4
);
636 if (init
->useOneshot
|| isMotorBrushed(init
->motorPwmRate
)) {
637 ppmAvoidPWMTimerClash(timerHardwarePtr
, TIM2
);
640 ppmInConfig(timerHardwarePtr
);
641 } else if (type
== MAP_TO_PWM_INPUT
) {
642 pwmInConfig(timerHardwarePtr
, channelIndex
);
644 } else if (type
== MAP_TO_MOTOR_OUTPUT
) {
645 if (init
->useOneshot
) {
646 pwmOneshotMotorConfig(timerHardwarePtr
, pwmOutputConfiguration
.motorCount
);
647 } else if (isMotorBrushed(init
->motorPwmRate
)) {
648 pwmBrushedMotorConfig(timerHardwarePtr
, pwmOutputConfiguration
.motorCount
, init
->motorPwmRate
, init
->idlePulse
);
650 pwmBrushlessMotorConfig(timerHardwarePtr
, pwmOutputConfiguration
.motorCount
, init
->motorPwmRate
, init
->idlePulse
);
652 pwmOutputConfiguration
.motorCount
++;
653 } else if (type
== MAP_TO_SERVO_OUTPUT
) {
655 pwmServoConfig(timerHardwarePtr
, pwmOutputConfiguration
.servoCount
, init
->servoPwmRate
, init
->servoCenterPulse
);
656 pwmOutputConfiguration
.servoCount
++;
661 return &pwmOutputConfiguration
;