diff --git a/boards/px4/fmu-v5/src/CMakeLists.txt b/boards/px4/fmu-v5/src/CMakeLists.txt index 1c58a593cc..f1244df578 100644 --- a/boards/px4/fmu-v5/src/CMakeLists.txt +++ b/boards/px4/fmu-v5/src/CMakeLists.txt @@ -38,7 +38,7 @@ add_library(drivers_board manifest.c sdio.c spi.cpp - timer_config.c + timer_config.cpp usb.c ) add_dependencies(drivers_board arch_board_hw_info) diff --git a/boards/px4/fmu-v5/src/board_config.h b/boards/px4/fmu-v5/src/board_config.h index 85fa80ac9f..157fda67cb 100644 --- a/boards/px4/fmu-v5/src/board_config.h +++ b/boards/px4/fmu-v5/src/board_config.h @@ -357,86 +357,17 @@ #define BOARD_INDICATE_ARMED_STATE(on_armed) px4_arch_configgpio((on_armed) ? GPIO_nARMED : GPIO_nARMED_INIT) /* PWM - * - * 8 PWM outputs are configured. - * - * Pins: - * - * FMU_CH1 : PE14 : TIM1_CH4 - * FMU_CH2 : PA10 : TIM1_CH3 - * FMU_CH3 : PE11 : TIM1_CH2 - * FMU_CH4 : PE9 : TIM1_CH1 - * FMU_CH5 : PD13 : TIM4_CH2 - * FMU_CH6 : PD14 : TIM4_CH3 - * FMU_CH7 : PH6 : TIM12_CH1 - * FMU_CH8 : PH9 : TIM12_CH2 - * */ -#define GPIO_TIM12_CH2OUT /* PH9 T12C2 FMU8 */ GPIO_TIM12_CH2OUT_2 -#define GPIO_TIM12_CH1OUT /* PH6 T12C1 FMU7 */ GPIO_TIM12_CH1OUT_2 -#define GPIO_TIM4_CH3OUT /* PD14 T4C3 FMU6 */ GPIO_TIM4_CH3OUT_2 -#define GPIO_TIM4_CH2OUT /* PD13 T4C2 FMU5 */ GPIO_TIM4_CH2OUT_2 -#define GPIO_TIM1_CH1OUT /* PE9 T1C1 FMU4 */ GPIO_TIM1_CH1OUT_2 -#define GPIO_TIM1_CH2OUT /* PE11 T1C2 FMU3 */ GPIO_TIM1_CH2OUT_2 -#define GPIO_TIM1_CH3OUT /* PA10 T1C3 FMU2 */ GPIO_TIM1_CH3OUT_1 -#define GPIO_TIM1_CH4OUT /* PE14 T1C4 FMU1 */ GPIO_TIM1_CH4OUT_2 - #define DIRECT_PWM_OUTPUT_CHANNELS 8 - -#define GPIO_TIM12_CH2IN /* PH9 T12C2 FMU8 */ GPIO_TIM12_CH2IN_2 -#define GPIO_TIM12_CH1IN /* PH6 T12C1 FMU7 */ GPIO_TIM12_CH1IN_2 -#define GPIO_TIM4_CH3IN /* PD14 T4C3 FMU6 */ GPIO_TIM4_CH3IN_2 -#define GPIO_TIM4_CH2IN /* PD13 T4C2 FMU5 */ GPIO_TIM4_CH2IN_2 -#define GPIO_TIM1_CH1IN /* PE9 T1C1 FMU4 */ GPIO_TIM1_CH1IN_2 -#define GPIO_TIM1_CH2IN /* PE11 T1C2 FMU3 */ GPIO_TIM1_CH2IN_2 -#define GPIO_TIM1_CH3IN /* PA10 T1C3 FMU2 */ GPIO_TIM1_CH3IN_1 -#define GPIO_TIM1_CH4IN /* PE14 T1C4 FMU1 */ GPIO_TIM1_CH4IN_2 - #define DIRECT_INPUT_TIMER_CHANNELS 8 #define BOARD_HAS_LED_PWM 1 #define BOARD_LED_PWM_DRIVE_ACTIVE_LOW 1 -#define LED_TIM3_CH1OUT /* PC6 T3C1 GREEN */ GPIO_TIM3_CH1OUT_3 -#define LED_TIM3_CH2OUT /* PC7 T3C2 BLUE */ GPIO_TIM3_CH2OUT_3 -#define LED_TIM3_CH4OUT /* PB1 T3C4 RED */ GPIO_TIM3_CH4OUT_1 - #define BOARD_HAS_UI_LED_PWM 1 #define BOARD_UI_LED_PWM_DRIVE_ACTIVE_LOW 1 -#define UI_LED_TIM5_CH1OUT /* PH10 T5C1 RED */ GPIO_TIM5_CH1OUT_2 -#define UI_LED_TIM5_CH2OUT /* PH11 T5C2 GREEN */ GPIO_TIM5_CH2OUT_2 -#define UI_LED_TIM5_CH3OUT /* PH12 T5C3 BLUE */ GPIO_TIM5_CH3OUT_2 - - -/* User GPIOs - * - * GPIO0-5 are the PWM servo outputs. - */ - -#define _MK_GPIO_INPUT(def) (((def) & (GPIO_PORT_MASK | GPIO_PIN_MASK)) | (GPIO_INPUT|GPIO_PULLUP)) - -#define GPIO_GPIO7_INPUT /* PH9 T12C2 FMU8 */ _MK_GPIO_INPUT(GPIO_TIM12_CH2IN) -#define GPIO_GPIO6_INPUT /* PH6 T12C1 FMU7 */ _MK_GPIO_INPUT(GPIO_TIM12_CH1IN) -#define GPIO_GPIO5_INPUT /* PD14 T4C3 FMU6 */ _MK_GPIO_INPUT(GPIO_TIM4_CH3IN) -#define GPIO_GPIO4_INPUT /* PD13 T4C2 FMU5 */ _MK_GPIO_INPUT(GPIO_TIM4_CH2IN) -#define GPIO_GPIO3_INPUT /* PE9 T1C1 FMU4 */ _MK_GPIO_INPUT(GPIO_TIM1_CH1IN) -#define GPIO_GPIO2_INPUT /* PE11 T1C2 FMU3 */ _MK_GPIO_INPUT(GPIO_TIM1_CH2IN) -#define GPIO_GPIO1_INPUT /* PA10 T1C3 FMU2 */ _MK_GPIO_INPUT(GPIO_TIM1_CH3IN) -#define GPIO_GPIO0_INPUT /* PE14 T1C4 FMU1 */ _MK_GPIO_INPUT(GPIO_TIM1_CH4IN) - -#define _MK_GPIO_OUTPUT(def) (((def) & (GPIO_PORT_MASK | GPIO_PIN_MASK)) | (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR)) - -#define GPIO_GPIO7_OUTPUT /* PH9 T12C2 FMU8 */ _MK_GPIO_OUTPUT(GPIO_TIM12_CH2OUT) -#define GPIO_GPIO6_OUTPUT /* PH6 T12C1 FMU7 */ _MK_GPIO_OUTPUT(GPIO_TIM12_CH1OUT) -#define GPIO_GPIO5_OUTPUT /* PD14 T4C3 FMU6 */ _MK_GPIO_OUTPUT(GPIO_TIM4_CH3OUT) -#define GPIO_GPIO4_OUTPUT /* PD13 T4C2 FMU5 */ _MK_GPIO_OUTPUT(GPIO_TIM4_CH2OUT) -#define GPIO_GPIO3_OUTPUT /* PE9 T1C1 FMU4 */ _MK_GPIO_OUTPUT(GPIO_TIM1_CH1OUT) -#define GPIO_GPIO2_OUTPUT /* PE11 T1C2 FMU3 */ _MK_GPIO_OUTPUT(GPIO_TIM1_CH2OUT) -#define GPIO_GPIO1_OUTPUT /* PA10 T1C3 FMU2 */ _MK_GPIO_OUTPUT(GPIO_TIM1_CH3OUT) -#define GPIO_GPIO0_OUTPUT /* PE14 T1C4 FMU1 */ _MK_GPIO_OUTPUT(GPIO_TIM1_CH4OUT) - /* Power supply control and monitoring GPIOs */ @@ -515,7 +446,7 @@ /* PWM input driver. Use FMU AUX5 pins attached to timer4 channel 2 */ #define PWMIN_TIMER 4 #define PWMIN_TIMER_CHANNEL /* T4C2 */ 2 -#define GPIO_PWM_IN /* PD13 */ GPIO_TIM4_CH2IN +#define GPIO_PWM_IN /* PD13 */ GPIO_TIM4_CH2IN_2 /* Shared pins Both FMU and PX4IO control/monitor * FMU Initializes these pins to passive input until it is known @@ -623,19 +554,6 @@ #define BOARD_HAS_ON_RESET 1 -/* The list of GPIO that will be initialized */ - -#define PX4_GPIO_PWM_INIT_LIST { \ - GPIO_GPIO7_INPUT, \ - GPIO_GPIO6_INPUT, \ - GPIO_GPIO5_INPUT, \ - GPIO_GPIO4_INPUT, \ - GPIO_GPIO3_INPUT, \ - GPIO_GPIO2_INPUT, \ - GPIO_GPIO1_INPUT, \ - GPIO_GPIO0_INPUT, \ - } - #define PX4_GPIO_INIT_LIST { \ PX4_ADC_GPIO, \ GPIO_HW_REV_DRIVE, \ diff --git a/boards/px4/fmu-v5/src/init.c b/boards/px4/fmu-v5/src/init.c index 2278a988c5..2f982d426c 100644 --- a/boards/px4/fmu-v5/src/init.c +++ b/boards/px4/fmu-v5/src/init.c @@ -65,6 +65,7 @@ #include #include "up_internal.h" +#include #include #include #include @@ -136,10 +137,9 @@ __EXPORT void board_peripheral_reset(int ms) ************************************************************************************/ __EXPORT void board_on_reset(int status) { - /* configure the GPIO pins to outputs and keep them low */ - - const uint32_t gpio[] = PX4_GPIO_PWM_INIT_LIST; - px4_gpio_init(gpio, arraySize(gpio)); + for (int i = 0; i < DIRECT_PWM_OUTPUT_CHANNELS; ++i) { + px4_arch_configgpio(PX4_MAKE_GPIO_INPUT(io_timer_channel_get_as_pwm_input(i))); + } if (status >= 0) { up_mdelay(6); diff --git a/boards/px4/fmu-v5/src/timer_config.c b/boards/px4/fmu-v5/src/timer_config.c deleted file mode 100644 index 6d6978d06b..0000000000 --- a/boards/px4/fmu-v5/src/timer_config.c +++ /dev/null @@ -1,320 +0,0 @@ -/**************************************************************************** - * - * Copyright (C) 2012 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/* - * @file timer_config.c - * - * Configuration data for the stm32 pwm_servo, input capture and pwm input driver. - * - * Note that these arrays must always be fully-sized. - */ - -#include - -#include -#include -#include - -#include -#include - -#include "board_config.h" - -__EXPORT const io_timers_t io_timers[MAX_IO_TIMERS] = { - { - .base = STM32_TIM1_BASE, - .clock_register = STM32_RCC_APB2ENR, - .clock_bit = RCC_APB2ENR_TIM1EN, - .clock_freq = STM32_APB2_TIM1_CLKIN, - .vectorno = STM32_IRQ_TIM1CC, - .dshot = { - .dma_base = STM32_DMA2_BASE, - .dmamap = DMAMAP_TIM1_UP, - } - }, - { - .base = STM32_TIM4_BASE, - .clock_register = STM32_RCC_APB1ENR, - .clock_bit = RCC_APB1ENR_TIM4EN, - .clock_freq = STM32_APB1_TIM4_CLKIN, - .vectorno = STM32_IRQ_TIM4, - }, - { - .base = STM32_TIM12_BASE, - .clock_register = STM32_RCC_APB1ENR, - .clock_bit = RCC_APB1ENR_TIM12EN, - .clock_freq = STM32_APB1_TIM12_CLKIN, - .vectorno = STM32_IRQ_TIM12, - }, - { - .base = STM32_TIM2_BASE, - .clock_register = STM32_RCC_APB1ENR, - .clock_bit = RCC_APB1ENR_TIM2EN, - .clock_freq = STM32_APB1_TIM2_CLKIN, - .vectorno = STM32_IRQ_TIM2, - }, - { - .base = STM32_TIM9_BASE, - .clock_register = STM32_RCC_APB2ENR, - .clock_bit = RCC_APB2ENR_TIM9EN, - .clock_freq = STM32_APB2_TIM9_CLKIN, - .vectorno = STM32_IRQ_TIM9, - } -}; - -__EXPORT const io_timers_channel_mapping_t io_timers_channel_mapping = { - .element = { - { - .first_channel_index = 0, - .channel_count = 4, - }, - { - .first_channel_index = 4, - .channel_count = 2, - }, - { - .first_channel_index = 6, - .channel_count = 2, - }, - { - .first_channel_index = 8, - .channel_count = 3, - }, - { - .first_channel_index = 11, - .channel_count = 1, - } - } -}; - -__EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { - { - .gpio_out = GPIO_TIM1_CH4OUT, - .gpio_in = GPIO_TIM1_CH4IN, - .timer_index = 0, - .timer_channel = 4, - .ccr_offset = STM32_GTIM_CCR4_OFFSET, - .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF - }, - { - .gpio_out = GPIO_TIM1_CH3OUT, - .gpio_in = GPIO_TIM1_CH3IN, - .timer_index = 0, - .timer_channel = 3, - .ccr_offset = STM32_GTIM_CCR3_OFFSET, - .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF - }, - { - .gpio_out = GPIO_TIM1_CH2OUT, - .gpio_in = GPIO_TIM1_CH2IN, - .timer_index = 0, - .timer_channel = 2, - .ccr_offset = STM32_GTIM_CCR2_OFFSET, - .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF - }, - { - .gpio_out = GPIO_TIM1_CH1OUT, - .gpio_in = GPIO_TIM1_CH1IN, - .timer_index = 0, - .timer_channel = 1, - .ccr_offset = STM32_GTIM_CCR1_OFFSET, - .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF - }, - { - .gpio_out = GPIO_TIM4_CH2OUT, - .gpio_in = GPIO_TIM4_CH2IN, - .timer_index = 1, - .timer_channel = 2, - .ccr_offset = STM32_GTIM_CCR2_OFFSET, - .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF - }, - { - .gpio_out = GPIO_TIM4_CH3OUT, - .gpio_in = GPIO_TIM4_CH3IN, - .timer_index = 1, - .timer_channel = 3, - .ccr_offset = STM32_GTIM_CCR3_OFFSET, - .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF - }, - { - .gpio_out = GPIO_TIM12_CH1OUT, - .gpio_in = GPIO_TIM12_CH1IN, - .timer_index = 2, - .timer_channel = 1, - .ccr_offset = STM32_GTIM_CCR1_OFFSET, - .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF - }, - { - .gpio_out = GPIO_TIM12_CH2OUT, - .gpio_in = GPIO_TIM12_CH2IN, - .timer_index = 2, - .timer_channel = 2, - .ccr_offset = STM32_GTIM_CCR2_OFFSET, - .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF - } -}; - -#if defined(BOARD_HAS_LED_PWM) || defined(BOARD_HAS_UI_LED_PWM) -__EXPORT const struct io_timers_t led_pwm_timers[MAX_LED_TIMERS] = { -# if defined(BOARD_HAS_UI_LED_PWM) - { - .base = STM32_TIM5_BASE, - .clock_register = STM32_RCC_APB1ENR, - .clock_bit = RCC_APB1ENR_TIM5EN, - .clock_freq = STM32_APB1_TIM5_CLKIN, - .vectorno = 0, - }, -# endif -# if defined(BOARD_HAS_LED_PWM) && !defined(BOARD_HAS_CONTROL_STATUS_LEDS) - { - .base = STM32_TIM3_BASE, - .clock_register = STM32_RCC_APB1ENR, - .clock_bit = RCC_APB1ENR_TIM3EN, - .clock_freq = STM32_APB1_TIM3_CLKIN, - .vectorno = 0, - }, -# endif -}; - -/* Support driving active low (preferred) or active high LED - * on both the onboard status LEDs or the [n]UI_LED_[_EXTERNAL] - * - * Use open drain to drive the LED. This will ensure that - * if the LED has a 5 Volt supply that the LED will be - * off when high. - */ -#define CCER_C1_NUM_BITS 4 -#define ACTIVE_LOW(c) (GTIM_CCER_CC1P << (((c)-1) * CCER_C1_NUM_BITS)) -#define ACTIVE_HIGH(c) 0 - -#if defined(BOARD_LED_PWM_DRIVE_ACTIVE_LOW) -# define POLARITY(c) ACTIVE_LOW(c) -# define DRIVE_TYPE(p) ((p)|GPIO_OPENDRAIN) -#else -# define POLARITY(c) ACTIVE_HIGH((c)) -# define DRIVE_TYPE(p) (p) -#endif - -#if defined(BOARD_UI_LED_PWM_DRIVE_ACTIVE_LOW) -# define UI_POLARITY(c) ACTIVE_LOW(c) -# define UI_DRIVE_TYPE(p) ((p)|GPIO_OPENDRAIN) -#else -# define UI_POLARITY(c) ACTIVE_HIGH((c)) -# define UI_DRIVE_TYPE(p) (p) -#endif - -__EXPORT const struct timer_io_channels_t led_pwm_channels[MAX_TIMER_LED_CHANNELS] = { -# if defined(BOARD_HAS_UI_LED_PWM) -# if defined(BOARD_UI_LED_SWAP_RG) - { - .gpio_out = UI_DRIVE_TYPE(UI_LED_TIM5_CH2OUT), - .gpio_in = 0, - .timer_index = 0, - .timer_channel = 2, - .masks = UI_POLARITY(2), - }, - { - .gpio_out = UI_DRIVE_TYPE(UI_LED_TIM5_CH1OUT), - .gpio_in = 0, - .timer_index = 0, - .timer_channel = 1, - .masks = UI_POLARITY(1), - }, - { - .gpio_out = UI_DRIVE_TYPE(UI_LED_TIM5_CH3OUT), - .gpio_in = 0, - .timer_index = 0, - .timer_channel = 3, - .masks = UI_POLARITY(3), - }, -# else - { - .gpio_out = UI_DRIVE_TYPE(UI_LED_TIM5_CH1OUT), - .gpio_in = 0, - .timer_index = 0, - .timer_channel = 1, - .masks = UI_POLARITY(1), - }, - { - .gpio_out = UI_DRIVE_TYPE(UI_LED_TIM5_CH2OUT), - .gpio_in = 0, - .timer_index = 0, - .timer_channel = 2, - .masks = UI_POLARITY(2), - }, - { - .gpio_out = UI_DRIVE_TYPE(UI_LED_TIM5_CH3OUT), - .gpio_in = 0, - .timer_index = 0, - .timer_channel = 3, - .masks = UI_POLARITY(3), - }, -# endif -# endif -# if defined(BOARD_HAS_LED_PWM) && !defined(BOARD_HAS_CONTROL_STATUS_LEDS) - { - .gpio_out = DRIVE_TYPE(LED_TIM3_CH4OUT), - .gpio_in = 0, -# if defined(BOARD_HAS_UI_LED_PWM) - .timer_index = 1, -# else - .timer_index = 0, -# endif - .timer_channel = 4, - .masks = POLARITY(4), - }, - { - .gpio_out = DRIVE_TYPE(LED_TIM3_CH1OUT), - .gpio_in = 0, -# if defined(BOARD_HAS_UI_LED_PWM) - .timer_index = 1, -# else - .timer_index = 0, -# endif - .timer_channel = 1, - .masks = POLARITY(1), - }, - { - .gpio_out = DRIVE_TYPE(LED_TIM3_CH2OUT), - .gpio_in = 0, -# if defined(BOARD_HAS_UI_LED_PWM) - .timer_index = 1, -# else - .timer_index = 0, -# endif - .timer_channel = 2, - .masks = POLARITY(2), - }, -# endif -}; -#endif // BOARD_HAS_LED_PWM || BOARD_HAS_UI_LED_PWM diff --git a/boards/px4/fmu-v5/src/timer_config.cpp b/boards/px4/fmu-v5/src/timer_config.cpp new file mode 100644 index 0000000000..c6e21851f3 --- /dev/null +++ b/boards/px4/fmu-v5/src/timer_config.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include + +constexpr io_timers_t io_timers[MAX_IO_TIMERS] = { + initIOTimer(Timer::Timer1, DMA{DMA::Index2, DMA::Stream5, DMA::Channel6}), + initIOTimer(Timer::Timer4), + initIOTimer(Timer::Timer12), + initIOTimer(Timer::Timer2), + initIOTimer(Timer::Timer9), +}; + +constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel4}, {GPIO::PortE, GPIO::Pin14}), + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel3}, {GPIO::PortA, GPIO::Pin10}), + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel2}, {GPIO::PortE, GPIO::Pin11}), + initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel1}, {GPIO::PortE, GPIO::Pin9}), + initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel2}, {GPIO::PortD, GPIO::Pin13}), + initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel3}, {GPIO::PortD, GPIO::Pin14}), + initIOTimerChannel(io_timers, {Timer::Timer12, Timer::Channel1}, {GPIO::PortH, GPIO::Pin6}), + initIOTimerChannel(io_timers, {Timer::Timer12, Timer::Channel2}, {GPIO::PortH, GPIO::Pin9}), +}; + +constexpr io_timers_channel_mapping_t io_timers_channel_mapping = + initIOTimerChannelMapping(io_timers, timer_io_channels); + +#if defined(BOARD_HAS_LED_PWM) || defined(BOARD_HAS_UI_LED_PWM) +constexpr io_timers_t led_pwm_timers[MAX_LED_TIMERS] = { +# if defined(BOARD_HAS_UI_LED_PWM) + initIOTimer(Timer::Timer5), +# endif +# if defined(BOARD_HAS_LED_PWM) && !defined(BOARD_HAS_CONTROL_STATUS_LEDS) + initIOTimer(Timer::Timer3), +# endif +}; + +/* Support driving active low (preferred) or active high LED + * on both the onboard status LEDs or the [n]UI_LED_[_EXTERNAL] + * + * Use open drain to drive the LED. This will ensure that + * if the LED has a 5 Volt supply that the LED will be + * off when high. + */ +#define CCER_C1_NUM_BITS 4 +#define ACTIVE_LOW(c) (GTIM_CCER_CC1P << (((c)-1) * CCER_C1_NUM_BITS)) +#define ACTIVE_HIGH(c) 0 + +#if defined(BOARD_LED_PWM_DRIVE_ACTIVE_LOW) +# define POLARITY(c) ACTIVE_LOW(c) +# define DRIVE_TYPE(p) ((p)|GPIO_OPENDRAIN) +#else +# define POLARITY(c) ACTIVE_HIGH((c)) +# define DRIVE_TYPE(p) (p) +#endif + +#if defined(BOARD_UI_LED_PWM_DRIVE_ACTIVE_LOW) +# define UI_POLARITY(c) ACTIVE_LOW(c) +# define UI_DRIVE_TYPE(p) ((p)|GPIO_OPENDRAIN) +#else +# define UI_POLARITY(c) ACTIVE_HIGH((c)) +# define UI_DRIVE_TYPE(p) (p) +#endif + +static inline constexpr timer_io_channels_t initIOTimerChannelUILED(const io_timers_t io_timers_conf[MAX_LED_TIMERS], + Timer::TimerChannel timer, GPIO::GPIOPin pin, int ui_polarity) +{ + timer_io_channels_t ret = initIOTimerChannel(io_timers_conf, timer, pin); + ret.gpio_out = UI_DRIVE_TYPE(ret.gpio_out); + ret.masks = UI_POLARITY(ui_polarity); + return ret; +} + +static inline constexpr timer_io_channels_t initIOTimerChannelControlLED(const io_timers_t + io_timers_conf[MAX_LED_TIMERS], + Timer::TimerChannel timer, GPIO::GPIOPin pin, int polarity) +{ + timer_io_channels_t ret = initIOTimerChannel(io_timers_conf, timer, pin); + ret.gpio_out = DRIVE_TYPE(ret.gpio_out); + ret.masks = POLARITY(polarity); + return ret; +} + +constexpr timer_io_channels_t led_pwm_channels[MAX_TIMER_LED_CHANNELS] = { +# if defined(BOARD_HAS_UI_LED_PWM) +# if defined(BOARD_UI_LED_SWAP_RG) + initIOTimerChannelUILED(led_pwm_timers, {Timer::Timer5, Timer::Channel2}, {GPIO::PortH, GPIO::Pin11}, 2), + initIOTimerChannelUILED(led_pwm_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortH, GPIO::Pin10}, 1), + initIOTimerChannelUILED(led_pwm_timers, {Timer::Timer5, Timer::Channel3}, {GPIO::PortH, GPIO::Pin12}, 3), +# else + initIOTimerChannelUILED(led_pwm_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortH, GPIO::Pin10}, 1), + initIOTimerChannelUILED(led_pwm_timers, {Timer::Timer5, Timer::Channel2}, {GPIO::PortH, GPIO::Pin11}, 2), + initIOTimerChannelUILED(led_pwm_timers, {Timer::Timer5, Timer::Channel3}, {GPIO::PortH, GPIO::Pin12}, 3), +# endif +# endif +# if defined(BOARD_HAS_LED_PWM) && !defined(BOARD_HAS_CONTROL_STATUS_LEDS) + initIOTimerChannelControlLED(led_pwm_timers, {Timer::Timer3, Timer::Channel4}, {GPIO::PortB, GPIO::Pin1}, 4), + initIOTimerChannelControlLED(led_pwm_timers, {Timer::Timer3, Timer::Channel1}, {GPIO::PortC, GPIO::Pin6}, 1), + initIOTimerChannelControlLED(led_pwm_timers, {Timer::Timer3, Timer::Channel2}, {GPIO::PortC, GPIO::Pin7}, 2), +# endif +}; +#endif // BOARD_HAS_LED_PWM || BOARD_HAS_UI_LED_PWM