Create set-home.md
[u360gts.git] / src / main / drivers / pwm_mapping.c
blobd92d130a615ca66c0c4f153227c83ece18024f1b
1 /*
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/>.
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <string.h>
21 #include <stdlib.h>
23 #include "platform.h"
25 #include "gpio.h"
26 #include "timer.h"
28 #include "pwm_output.h"
29 #include "pwm_rx.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);
38 Configuration maps
40 Note: this documentation is only valid for STM32F10x, for STM32F30x please read the code itself.
42 1) multirotor PPM input
43 PWM1 used for PPM
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
49 PWM1 used for PPM
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
65 PWM1 used for PPM
66 PWM5..8 used for servos
67 PWM9 used for motor throttle +PWM10 for 2nd motor
68 PWM11.14 used for servos
71 enum {
72 MAP_TO_PPM_INPUT = 1,
73 MAP_TO_PWM_INPUT,
74 MAP_TO_MOTOR_OUTPUT,
75 MAP_TO_SERVO_OUTPUT,
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
91 0xFFFF
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
109 0xFFFF
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
124 0xFFFF
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
142 0xFFFF
144 #endif
146 #ifdef CC3D
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
160 0xFFFF
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
175 0xFFFF
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),
191 0xFFFF
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
207 0xFFFF
209 #endif
211 #ifdef CJMCU
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),
218 0xFFFF
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),
232 0xFFFF
235 static const uint16_t airPPM[] = {
236 0xFFFF
239 static const uint16_t airPWM[] = {
240 0xFFFF
242 #endif
244 #ifdef COLIBRI_RACE
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
257 0xFFFF
260 static const uint16_t multiPWM[] = {
261 // TODO
262 0xFFFF
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
277 0xFFFF
280 static const uint16_t airPWM[] = {
281 // TODO
282 0xFFFF
284 #endif
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
300 0xFFFF
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),
314 0xFFFF
317 static const uint16_t airPPM[] = {
318 // TODO
319 0xFFFF
322 static const uint16_t airPWM[] = {
323 // TODO
324 0xFFFF
326 #endif
328 #ifdef SPRACINGF3
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
344 0xFFFF
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),
364 0xFFFF
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
381 0xFFFF
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
401 0xFFFF
403 #endif
405 #if defined(MOTOLAB)
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),
417 0xFFFF
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),
429 0xFFFF
432 static const uint16_t airPPM[] = {
433 // TODO
434 0xFFFF
437 static const uint16_t airPWM[] = {
438 // TODO
439 0xFFFF
441 #endif
443 static const uint16_t * const hardwareMaps[] = {
444 multiPWM,
445 multiPPM,
446 airPWM,
447 airPPM,
450 pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
452 int i = 0;
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 ]
462 if (init->airplane)
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)
478 continue;
479 #endif
481 #ifdef STM32F10X
482 // skip UART2 ports
483 if (init->useUART2 && (timerIndex == PWM3 || timerIndex == PWM4))
484 continue;
485 #endif
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))
490 continue;
491 #endif
493 #ifdef SOFTSERIAL_1_TIMER
494 if (init->useSoftSerial && timerHardwarePtr->tim == SOFTSERIAL_1_TIMER)
495 continue;
496 #endif
497 #ifdef SOFTSERIAL_2_TIMER
498 if (init->useSoftSerial && timerHardwarePtr->tim == SOFTSERIAL_2_TIMER)
499 continue;
500 #endif
502 #ifdef LED_STRIP_TIMER
503 // skip LED Strip output
504 if (init->useLEDStrip) {
505 if (timerHardwarePtr->tim == LED_STRIP_TIMER)
506 continue;
507 #if defined(STM32F303xC) && defined(WS2811_GPIO) && defined(WS2811_PIN_SOURCE)
508 if (timerHardwarePtr->gpio == WS2811_GPIO && timerHardwarePtr->gpioPinSource == WS2811_PIN_SOURCE)
509 continue;
510 #endif
513 #endif
515 #ifdef VBAT_ADC_GPIO
516 if (init->useVbat && timerHardwarePtr->gpio == VBAT_ADC_GPIO && timerHardwarePtr->pin == VBAT_ADC_GPIO_PIN) {
517 continue;
519 #endif
521 #ifdef RSSI_ADC_GPIO
522 if (init->useRSSIADC && timerHardwarePtr->gpio == RSSI_ADC_GPIO && timerHardwarePtr->pin == RSSI_ADC_GPIO_PIN) {
523 continue;
525 #endif
527 #ifdef CURRENT_METER_ADC_GPIO
528 if (init->useCurrentMeterADC && timerHardwarePtr->gpio == CURRENT_METER_ADC_GPIO && timerHardwarePtr->pin == CURRENT_METER_ADC_GPIO_PIN) {
529 continue;
531 #endif
533 #ifdef SONAR
534 if (init->sonarGPIOConfig && timerHardwarePtr->gpio == init->sonarGPIOConfig->gpio &&
536 timerHardwarePtr->pin == init->sonarGPIOConfig->triggerPin ||
537 timerHardwarePtr->pin == init->sonarGPIOConfig->echoPin
540 continue;
542 #endif
544 // hacks to allow current functionality
545 if (type == MAP_TO_PWM_INPUT && !init->useParallelPWM)
546 continue;
548 if (type == MAP_TO_PPM_INPUT && !init->usePPM)
549 continue;
551 #ifdef USE_SERVOS
552 if (init->useServos && !init->airplane) {
553 #if defined(NAZE)
554 // remap PWM9+10 as servos
555 if ((timerIndex == PWM9 || timerIndex == PWM10) && timerHardwarePtr->tim == TIM1)
556 type = MAP_TO_SERVO_OUTPUT;
557 #endif
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;
563 #endif
565 #if defined(CC3D)
566 // remap 10 as servo
567 if (timerIndex == PWM10 && timerHardwarePtr->tim == TIM1)
568 type = MAP_TO_SERVO_OUTPUT;
569 #endif
571 #if defined(SPARKY)
572 // remap PWM1+2 as servos
573 if ((timerIndex == PWM1 || timerIndex == PWM2) && timerHardwarePtr->tim == TIM15)
574 type = MAP_TO_SERVO_OUTPUT;
575 #endif
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;
581 #endif
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;
588 } else {
589 if (timerIndex == PWM9 || timerIndex == PWM10)
590 type = MAP_TO_SERVO_OUTPUT;
592 #endif
594 #if defined(MOTOLAB)
595 // remap PWM 7+8 as servos
596 if (timerIndex == PWM7 || timerIndex == PWM8)
597 type = MAP_TO_SERVO_OUTPUT;
598 #endif
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;
608 } else
609 #endif
610 // remap PWM5..8 as servos when used in extended servo mode
611 if (timerIndex >= PWM5 && timerIndex <= PWM8)
612 type = MAP_TO_SERVO_OUTPUT;
614 #endif
616 #ifdef CC3D
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)) {
620 continue;
622 if (type == MAP_TO_PWM_INPUT && timerHardwarePtr->tim == TIM4) {
623 continue;
627 #endif
629 if (type == MAP_TO_PPM_INPUT) {
630 #ifdef CC3D
631 if (init->useOneshot || isMotorBrushed(init->motorPwmRate)) {
632 ppmAvoidPWMTimerClash(timerHardwarePtr, TIM4);
634 #endif
635 #ifdef SPARKY
636 if (init->useOneshot || isMotorBrushed(init->motorPwmRate)) {
637 ppmAvoidPWMTimerClash(timerHardwarePtr, TIM2);
639 #endif
640 ppmInConfig(timerHardwarePtr);
641 } else if (type == MAP_TO_PWM_INPUT) {
642 pwmInConfig(timerHardwarePtr, channelIndex);
643 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);
649 } else {
650 pwmBrushlessMotorConfig(timerHardwarePtr, pwmOutputConfiguration.motorCount, init->motorPwmRate, init->idlePulse);
652 pwmOutputConfiguration.motorCount++;
653 } else if (type == MAP_TO_SERVO_OUTPUT) {
654 #ifdef USE_SERVOS
655 pwmServoConfig(timerHardwarePtr, pwmOutputConfiguration.servoCount, init->servoPwmRate, init->servoCenterPulse);
656 pwmOutputConfiguration.servoCount++;
657 #endif
661 return &pwmOutputConfiguration;