From: Wangjialin Date: Wed, 8 Feb 2017 11:52:18 +0000 (+0800) Subject: Feature: add ledc low speed channels X-Git-Tag: v2.1-rc1~249^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7670e9363904def83ac245037825853ff2c43ead;p=esp-idf Feature: add ledc low speed channels 1. Add low speed channels for LEDC module. 2. Improve fade object allocate mechanism. 3. Improve ledc example, add 2 low speed channels in example. 4. Remove debug code 5. Improve the register bit field name of slow clock. --- diff --git a/components/driver/include/driver/ledc.h b/components/driver/include/driver/ledc.h index af7c6b8078..70e21d9e49 100644 --- a/components/driver/include/driver/ledc.h +++ b/components/driver/include/driver/ledc.h @@ -29,8 +29,7 @@ extern "C" { typedef enum { LEDC_HIGH_SPEED_MODE = 0, /*!< LEDC high speed speed_mode */ - //in this version, we only support high speed speed_mode. We will access low speed speed_mode later - //LEDC_LOW_SPEED_MODE, /*!< LEDC low speed speed_mode */ + LEDC_LOW_SPEED_MODE, /*!< LEDC low speed speed_mode */ LEDC_SPEED_MODE_MAX, /*!< LEDC speed limit */ } ledc_mode_t; @@ -137,8 +136,6 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf); * After ledc_set_duty, ledc_set_fade, we need to call this function to update the settings. * * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, - * now we only support high-speed mode. - * We will access low-speed mode in next version * @param channel LEDC channel(0-7), select from ledc_channel_t * * @return @@ -152,7 +149,7 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel); * @brief LEDC stop. * Disable LEDC output, and set idle level * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param channel LEDC channel(0-7), select from ledc_channel_t * @param idle_level Set output idle level after LEDC stops. * @@ -165,7 +162,7 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl /** * @brief LEDC set channel frequency(Hz) * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param timer_num LEDC timer index(0-3), select from ledc_timer_t * @param freq_hz Set the LEDC frequency * @@ -179,7 +176,7 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t /** * @brief LEDC get channel frequency(Hz) * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param timer_num LEDC timer index(0-3), select from ledc_timer_t * * @return @@ -192,7 +189,7 @@ uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num); * @brief LEDC set duty * Only after calling ledc_update_duty will the duty update. * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param channel LEDC channel(0-7), select from ledc_channel_t * @param duty Set the LEDC duty, the duty range is [0, (2**bit_num) - 1] * @@ -205,7 +202,7 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t /** * @brief LEDC get duty * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param channel LEDC channel(0-7), select from ledc_channel_t * * @return @@ -218,7 +215,7 @@ int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel); * @brief LEDC set gradient * Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect. * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param channel LEDC channel(0-7), select from ledc_channel_t * @param duty Set the start of the gradient duty, the duty range is [0, (2**bit_num) - 1] * @param gradule_direction Set the direction of the gradient @@ -254,7 +251,7 @@ esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, /** * @brief Configure LEDC settings * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param timer_sel Timer index(0-3), there are 4 timers in LEDC module * @param div_num Timer clock divide number, the timer clock is divided from the selected clock source * @param bit_num The count number of one period, counter range is 0 ~ ((2 ** bit_num) - 1) @@ -269,7 +266,7 @@ esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_ /** * @brief Reset LEDC timer * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param timer_sel LEDC timer index(0-3), select from ledc_timer_t * * @return @@ -281,7 +278,7 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel); /** * @brief Pause LEDC timer counter * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param timer_sel LEDC timer index(0-3), select from ledc_timer_t * * @return @@ -294,7 +291,7 @@ esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel); /** * @brief Resume LEDC timer * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param timer_sel LEDC timer index(0-3), select from ledc_timer_t * * @return @@ -306,7 +303,7 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel); /** * @brief Bind LEDC channel with the selected timer * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param channel LEDC channel index(0-7), select from ledc_channel_t * @param timer_idx LEDC timer index(0-3), select from ledc_timer_t * @@ -321,7 +318,6 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint * Call ledc_fade_start() after this to start fading. * * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, - * For now we only support high-speed mode. We will access low-speed mode soon. * @param channel LEDC channel index(0-7), select from ledc_channel_t * @param target_duty Target duty of fading.( 0 - (2 ** bit_num - 1))) * @param scale Controls the increase or decrease step scale. @@ -331,6 +327,7 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_FAIL Fade function init error */ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int scale, int cycle_num); @@ -339,7 +336,6 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel * Call ledc_fade_start() after this to start fading. * * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, - * For now we only support high-speed mode. We will access low-speed mode soon. * @param channel LEDC channel index(0-7), select from ledc_channel_t * @param target_duty Target duty of fading.( 0 - (2 ** bit_num - 1))) * @param max_fade_time_ms The maximum time of the fading ( ms ). @@ -348,6 +344,7 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_FAIL Fade function init error */ esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int max_fade_time_ms); @@ -358,7 +355,6 @@ esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. * * @return - * - ESP_ERR_NO_MEM No enough memory * - ESP_OK Success * - ESP_ERR_INVALID_STATE Fade function already installed. */ @@ -373,6 +369,7 @@ void ledc_fade_func_uninstall(); /** * @brief Start LEDC fading. * + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param channel LEDC channel number * @param wait_done Whether to block until fading done. * @@ -381,7 +378,7 @@ void ledc_fade_func_uninstall(); * - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_ERR_INVALID_ARG Parameter error. */ -esp_err_t ledc_fade_start(ledc_channel_t channel, ledc_fade_mode_t wait_done); +esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t wait_done); #ifdef __cplusplus } diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 6944f1b115..7da353869f 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -41,7 +41,8 @@ typedef struct { xSemaphoreHandle ledc_fade_sem; xSemaphoreHandle ledc_fade_mux; } ledc_fade_t; -static ledc_fade_t* s_ledc_fade_rec = NULL; + +static ledc_fade_t *s_ledc_fade_rec[LEDC_SPEED_MODE_MAX][LEDC_CHANNEL_MAX]; static ledc_isr_handle_t s_ledc_fade_isr_handle = NULL; #define LEDC_VAL_NO_CHANGE (-1) @@ -57,9 +58,24 @@ static ledc_isr_handle_t s_ledc_fade_isr_handle = NULL; #define LEDC_FADE_TARGET_ERR_STR "LEDC fade target duty error" #define LEDC_FADE_INSTALLED_ERR_STR "LEDC fade service already installed" #define LEDC_FADE_MODE_ERR_STR "LEDC fade mode error" +#define LEDC_FADE_INIT_ERROR_STR "LEDC fade channel init error" +static void ledc_ls_timer_update(ledc_mode_t speed_mode, ledc_timer_t timer_sel) +{ + if (speed_mode == LEDC_LOW_SPEED_MODE) { + LEDC.timer_group[speed_mode].timer[timer_sel].conf.low_speed_update = 1; + } +} -esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src) +static IRAM_ATTR void ledc_ls_channel_update(ledc_mode_t speed_mode, ledc_channel_t channel_num) +{ + if (speed_mode == LEDC_LOW_SPEED_MODE) { + LEDC.channel_group[speed_mode].channel[channel_num].conf0.low_speed_update = 1; + } +} + +esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, + ledc_clk_src_t clk_src) { LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); @@ -67,9 +83,7 @@ esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_ LEDC.timer_group[speed_mode].timer[timer_sel].conf.div_num = div_num; LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = clk_src; LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num = bit_num; - if (speed_mode != LEDC_HIGH_SPEED_MODE) { - LEDC.timer_group[speed_mode].timer[timer_sel].conf.low_speed_update = 1; - } + ledc_ls_timer_update(speed_mode, timer_sel); portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; } @@ -86,6 +100,7 @@ static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel ((duty_num & LEDC_DUTY_NUM_HSCH0_V) << LEDC_DUTY_NUM_HSCH0_S) | ((duty_cycle & LEDC_DUTY_CYCLE_HSCH0_V) << LEDC_DUTY_CYCLE_HSCH0_S) | ((duty_scale & LEDC_DUTY_SCALE_HSCH0_V) << LEDC_DUTY_SCALE_HSCH0_S); + ledc_ls_channel_update(speed_mode, channel_num); portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; } @@ -96,6 +111,7 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel LEDC_CHECK(timer_idx <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel = timer_idx; + ledc_ls_channel_update(speed_mode, channel); portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; } @@ -107,6 +123,7 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel) portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 1; LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 0; + ledc_ls_timer_update(speed_mode, timer_sel); portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; } @@ -117,6 +134,7 @@ esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel) LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 1; + ledc_ls_timer_update(speed_mode, timer_sel); portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; } @@ -127,6 +145,7 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel) LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 0; + ledc_ls_timer_update(speed_mode, timer_sel); portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; } @@ -138,10 +157,14 @@ static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, uint32_t intr_type = type; portENTER_CRITICAL(&ledc_spinlock); value = LEDC.int_ena.val; + uint8_t int_en_base = LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S; + if (speed_mode == LEDC_LOW_SPEED_MODE) { + int_en_base = LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S; + } if (intr_type == LEDC_INTR_FADE_END) { - LEDC.int_ena.val = value | BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S + channel); + LEDC.int_ena.val = value | BIT(int_en_base + channel); } else { - LEDC.int_ena.val = ( value & ( ~( BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S + channel) ) ) ); + LEDC.int_ena.val = (value & (~(BIT(int_en_base + channel)))); } portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; @@ -188,12 +211,17 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf) if (div_param > LEDC_DIV_NUM_HSTIMER0_V) { // APB_CLK results in divisor which too high. Try using REF_TICK as clock source. timer_clk_src = LEDC_REF_TICK; - div_param = ( (uint64_t) LEDC_REF_CLK_HZ << 8 ) / freq_hz / precision; + div_param = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision; if (div_param < 256 || div_param > LEDC_DIV_NUM_HSTIMER0_V) { ESP_LOGE(LEDC_TAG, "requested frequency and bit depth can not be achieved, try increasing freq_hz or bit_num. div_param=%d", (uint32_t ) div_param); ret = ESP_FAIL; } + } else { + if (speed_mode == LEDC_LOW_SPEED_MODE) { + //for now, we only select 80mhz for slow clk of LEDC low speed channels. + LEDC.conf.slow_clk_sel = 1; + } } // set timer parameters ledc_timer_set(speed_mode, timer_num, div_param, bit_num, timer_clk_src); @@ -212,8 +240,7 @@ esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc if (speed_mode == LEDC_HIGH_SPEED_MODE) { gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0); } else { - ESP_LOGE(LEDC_TAG, "low speed mode is not implemented"); - return ESP_ERR_NOT_SUPPORTED; + gpio_matrix_out(gpio_num, LEDC_LS_SIG_OUT0_IDX + ledc_channel, 0, 0); } return ESP_OK; } @@ -248,7 +275,11 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) /*set LEDC signal in gpio matrix*/ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); - gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0); + if (speed_mode == LEDC_HIGH_SPEED_MODE) { + gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0); + } else { + gpio_matrix_out(gpio_num, LEDC_LS_SIG_OUT0_IDX + ledc_channel, 0, 0); + } return ret; } @@ -259,6 +290,7 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 1; LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1; + ledc_ls_channel_update(speed_mode, channel); portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; } @@ -271,6 +303,7 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl LEDC.channel_group[speed_mode].channel[channel].conf0.idle_lv = idle_level & 0x1; LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 0; LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 0; + ledc_ls_channel_update(speed_mode, channel); portEXIT_CRITICAL(&ledc_spinlock); return ESP_OK; } @@ -285,7 +318,7 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t ESP_LOGE(LEDC_TAG, "step_num=%u duty_cyle_num=%u duty_scale=%u", step_num, duty_cyle_num, duty_scale); return ESP_ERR_INVALID_ARG; } - if (s_ledc_fade_rec) { + if (s_ledc_fade_rec[speed_mode][channel]) { ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE); } ledc_duty_config(speed_mode, @@ -304,7 +337,7 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t { LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); LEDC_CHECK(channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); - if (s_ledc_fade_rec) { + if (s_ledc_fade_rec[speed_mode][channel]) { ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE); } ledc_duty_config(speed_mode, @@ -334,11 +367,11 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t uint32_t div_num = 0; uint32_t bit_num = LEDC.timer_group[speed_mode].timer[timer_num].conf.bit_num; uint32_t timer_source_clk = LEDC.timer_group[speed_mode].timer[timer_num].conf.tick_sel; - uint32_t precision = ( 0x1 << bit_num ); + uint32_t precision = (0x1 << bit_num); if (timer_source_clk == LEDC_APB_CLK) { - div_num = ( (uint64_t) LEDC_APB_CLK_HZ << 8 ) / freq_hz / precision; + div_num = ((uint64_t) LEDC_APB_CLK_HZ << 8) / freq_hz / precision; } else { - div_num = ( (uint64_t) LEDC_REF_CLK_HZ << 8 ) / freq_hz / precision; + div_num = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision; } if (div_num <= 256 || div_num > LEDC_DIV_NUM_HSTIMER0) { ESP_LOGE(LEDC_TAG, "div param err,div_param=%u", div_num); @@ -351,81 +384,127 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ( 0 )); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, (0)); portENTER_CRITICAL(&ledc_spinlock); uint32_t freq = 0; uint32_t timer_source_clk = LEDC.timer_group[speed_mode].timer[timer_num].conf.tick_sel; uint32_t bit_num = LEDC.timer_group[speed_mode].timer[timer_num].conf.bit_num; uint32_t div_num = LEDC.timer_group[speed_mode].timer[timer_num].conf.div_num; - uint32_t precision = ( 0x1 << bit_num ); + uint32_t precision = (0x1 << bit_num); if (timer_source_clk == LEDC_APB_CLK) { - freq = ( (uint64_t) LEDC_APB_CLK_HZ << 8 ) / precision / div_num; + freq = ((uint64_t) LEDC_APB_CLK_HZ << 8) / precision / div_num; } else { - freq = ( (uint64_t) LEDC_REF_CLK_HZ << 8 ) / precision / div_num; + freq = ((uint64_t) LEDC_REF_CLK_HZ << 8) / precision / div_num; } portEXIT_CRITICAL(&ledc_spinlock); return freq; } -void IRAM_ATTR ledc_fade_isr() +void IRAM_ATTR ledc_fade_isr(void* arg) { - int i; + int channel; portBASE_TYPE HPTaskAwoken = pdFALSE; uint32_t intr_status = LEDC.int_st.val; //read LEDC interrupt status. LEDC.int_clr.val = intr_status; //clear LEDC interrupt status. - for (i = 0; i < 8; i++) { - if (intr_status & BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ST_S + i)) { - int speed_mode = s_ledc_fade_rec[i].speed_mode; - int duty_cur = LEDC.channel_group[speed_mode].channel[i].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; - if (duty_cur == s_ledc_fade_rec[i].target_duty) { - if(s_ledc_fade_rec[i].mode == LEDC_FADE_WAIT_DONE) { - xSemaphoreGiveFromISR(s_ledc_fade_rec[i].ledc_fade_sem, &HPTaskAwoken); - if(HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR() ; + int speed_mode = LEDC_HIGH_SPEED_MODE; + for (channel = 0; channel < LEDC_CHANNEL_MAX; channel++) { + if (intr_status & (BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ST_S + channel) | BIT(LEDC_DUTY_CHNG_END_LSCH0_INT_ST_S + channel))) { + if (intr_status & BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ST_S + channel)) { + speed_mode = LEDC_HIGH_SPEED_MODE; + } else { + speed_mode = LEDC_LOW_SPEED_MODE; + } + if (s_ledc_fade_rec[speed_mode][channel] == NULL) { + //fade object not initialized yet. + continue; + } + int duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; + if (duty_cur == s_ledc_fade_rec[speed_mode][channel]->target_duty) { + if (s_ledc_fade_rec[speed_mode][channel]->mode == LEDC_FADE_WAIT_DONE) { + xSemaphoreGiveFromISR(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, &HPTaskAwoken); + if (HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); } } continue; } - int duty_tar = s_ledc_fade_rec[i].target_duty; - int scale = s_ledc_fade_rec[i].scale; + int duty_tar = s_ledc_fade_rec[speed_mode][channel]->target_duty; + int scale = s_ledc_fade_rec[speed_mode][channel]->scale; if (scale == 0) { continue; } - int cycle = s_ledc_fade_rec[i].cycle_num; - int delta = s_ledc_fade_rec[i].direction == LEDC_DUTY_DIR_DECREASE ? duty_cur - duty_tar : duty_tar - duty_cur; + int cycle = s_ledc_fade_rec[speed_mode][channel]->cycle_num; + int delta = s_ledc_fade_rec[speed_mode][channel]->direction == LEDC_DUTY_DIR_DECREASE ? duty_cur - duty_tar : duty_tar - duty_cur; int step = delta / scale > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : delta / scale; - if (delta > scale) { ledc_duty_config( speed_mode, - i, + channel, LEDC_VAL_NO_CHANGE, duty_cur << LEDC_DUTY_DECIMAL_BIT_NUM, - s_ledc_fade_rec[i].direction, + s_ledc_fade_rec[speed_mode][channel]->direction, step, cycle, scale); } else { ledc_duty_config( speed_mode, - i, + channel, LEDC_VAL_NO_CHANGE, duty_tar << LEDC_DUTY_DECIMAL_BIT_NUM, - s_ledc_fade_rec[i].direction, + s_ledc_fade_rec[speed_mode][channel]->direction, 1, 1, 0); } - LEDC.channel_group[speed_mode].channel[i].conf1.duty_start = 1; + LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1; } } LEDC.int_clr.val = intr_status; //clear LEDC interrupt status. } +static esp_err_t ledc_fade_channel_deinit(ledc_mode_t speed_mode, ledc_channel_t channel) +{ + if (s_ledc_fade_rec[speed_mode][channel]) { + if (s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux) { + vSemaphoreDelete(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux); + s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = NULL; + } + if (s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem) { + vSemaphoreDelete(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem); + s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = NULL; + } + free(s_ledc_fade_rec[speed_mode][channel]); + s_ledc_fade_rec[speed_mode][channel] = NULL; + } + return ESP_OK; +} + +static esp_err_t ledc_fade_channel_init_check(ledc_mode_t speed_mode, ledc_channel_t channel) +{ + if (s_ledc_fade_rec[speed_mode][channel] == NULL) { + s_ledc_fade_rec[speed_mode][channel] = (ledc_fade_t *) calloc(1, sizeof(ledc_fade_t)); + s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = xSemaphoreCreateMutex(); + s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinary(); + } + if (s_ledc_fade_rec[speed_mode][channel] + && s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux + && s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem) { + return ESP_OK; + } else { + ledc_fade_channel_deinit(speed_mode, channel); + return ESP_FAIL; + } +} + esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int max_fade_time_ms) { + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel < LEDC_CHANNEL_MAX, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); + int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel; - int max_duty = ( 1 << ( LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num ) ) - 1; + int max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num)) - 1; LEDC_CHECK(target_duty <= max_duty, LEDC_FADE_TARGET_ERR_STR, ESP_ERR_INVALID_ARG); uint32_t freq = ledc_get_freq(speed_mode, timer_sel); int duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; @@ -441,16 +520,17 @@ esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel cycle_num = total_cycles / duty_delta; } else { cycle_num = 1; - scale = ( duty_delta + total_cycles - 1 ) / total_cycles; + scale = (duty_delta + total_cycles - 1) / total_cycles; } return ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num); } esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int scale, int cycle_num) { - LEDC_CHECK(s_ledc_fade_rec != NULL, LEDC_FADE_SERVICE_ERR_STR, ESP_ERR_INVALID_STATE); LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); LEDC_CHECK(channel < LEDC_CHANNEL_MAX, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); + int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel; int max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num)) - 1; LEDC_CHECK(target_duty <= max_duty, LEDC_FADE_TARGET_ERR_STR, ESP_ERR_INVALID_ARG); @@ -463,18 +543,18 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel if (duty_delta == 0) { return ESP_OK; } - s_ledc_fade_rec[channel].speed_mode = speed_mode; - s_ledc_fade_rec[channel].target_duty = target_duty; - s_ledc_fade_rec[channel].cycle_num = cycle_num; - s_ledc_fade_rec[channel].scale = scale; + s_ledc_fade_rec[speed_mode][channel]->speed_mode = speed_mode; + s_ledc_fade_rec[speed_mode][channel]->target_duty = target_duty; + s_ledc_fade_rec[speed_mode][channel]->cycle_num = cycle_num; + s_ledc_fade_rec[speed_mode][channel]->scale = scale; int step_num; if (duty_cur > target_duty) { - s_ledc_fade_rec[channel].direction = LEDC_DUTY_DIR_DECREASE; - step_num = ( duty_cur - target_duty ) / scale; + s_ledc_fade_rec[speed_mode][channel]->direction = LEDC_DUTY_DIR_DECREASE; + step_num = (duty_cur - target_duty) / scale; step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num; } else { - s_ledc_fade_rec[channel].direction = LEDC_DUTY_DIR_INCREASE; - step_num = ( target_duty - duty_cur ) / scale; + s_ledc_fade_rec[speed_mode][channel]->direction = LEDC_DUTY_DIR_INCREASE; + step_num = (target_duty - duty_cur) / scale; step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num; } portEXIT_CRITICAL(&ledc_spinlock); @@ -483,42 +563,28 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel speed_mode, channel, duty_cur, - s_ledc_fade_rec[channel].direction, + s_ledc_fade_rec[speed_mode][channel]->direction, step_num, - s_ledc_fade_rec[channel].cycle_num, - s_ledc_fade_rec[channel].scale + s_ledc_fade_rec[speed_mode][channel]->cycle_num, + s_ledc_fade_rec[speed_mode][channel]->scale ); ESP_LOGD(LEDC_TAG, "cur duty: %d; target: %d, step: %d, cycle: %d; scale: %d\n", LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM, target_duty, step_num, - s_ledc_fade_rec[channel].cycle_num, - s_ledc_fade_rec[channel].scale + s_ledc_fade_rec[speed_mode][channel]->cycle_num, + s_ledc_fade_rec[speed_mode][channel]->scale ); - LEDC.int_clr.val |= BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S + channel); + int bit_num_ch0 = (speed_mode == LEDC_HIGH_SPEED_MODE) ? LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S : LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S; + LEDC.int_clr.val |= BIT(bit_num_ch0 + channel); ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_FADE_END); return ESP_OK; } esp_err_t ledc_fade_func_install(int intr_alloc_flags) { - LEDC_CHECK(s_ledc_fade_rec == NULL, LEDC_FADE_INSTALLED_ERR_STR, ESP_ERR_INVALID_STATE); - s_ledc_fade_rec = (ledc_fade_t*) calloc(LEDC_CHANNEL_MAX, sizeof(ledc_fade_t)); - if (s_ledc_fade_rec == NULL) { - return ESP_ERR_NO_MEM; - } - int i = 0; - for (i = 0; i < LEDC_CHANNEL_MAX; i++) { - s_ledc_fade_rec[i].ledc_fade_sem = xSemaphoreCreateBinary(); - s_ledc_fade_rec[i].ledc_fade_mux = xSemaphoreCreateMutex(); - if (s_ledc_fade_rec[i].ledc_fade_sem == NULL || s_ledc_fade_rec[i].ledc_fade_mux == NULL) { - ledc_fade_func_uninstall(); - return ESP_ERR_NO_MEM; - } - } //OR intr_alloc_flags with ESP_INTR_FLAG_IRAM because the fade isr is in IRAM - ledc_isr_register(ledc_fade_isr, NULL, intr_alloc_flags | ESP_INTR_FLAG_IRAM, &s_ledc_fade_isr_handle); - return ESP_OK; + return ledc_isr_register(ledc_fade_isr, NULL, intr_alloc_flags | ESP_INTR_FLAG_IRAM, &s_ledc_fade_isr_handle); } void ledc_fade_func_uninstall() @@ -526,42 +592,32 @@ void ledc_fade_func_uninstall() if (s_ledc_fade_rec == NULL) { return; } - if(s_ledc_fade_isr_handle) { + if (s_ledc_fade_isr_handle) { esp_intr_free(s_ledc_fade_isr_handle); s_ledc_fade_isr_handle = NULL; } - int i; - for (i = 0; i < LEDC_CHANNEL_MAX; i++) { - if (s_ledc_fade_rec[i].ledc_fade_sem) { - xSemaphoreHandle sem_tmp = s_ledc_fade_rec[i].ledc_fade_sem; - s_ledc_fade_rec[i].ledc_fade_sem = NULL; - vSemaphoreDelete(sem_tmp); - } - if (s_ledc_fade_rec[i].ledc_fade_mux) { - xSemaphoreHandle mux_tmp = s_ledc_fade_rec[i].ledc_fade_mux; - s_ledc_fade_rec[i].ledc_fade_mux = NULL; - vSemaphoreDelete(mux_tmp); + int channel, mode; + for (mode = 0; mode < LEDC_SPEED_MODE_MAX; mode++) { + for (channel = 0; channel < LEDC_CHANNEL_MAX; channel++) { + ledc_fade_channel_deinit(mode, channel); } } - free(s_ledc_fade_rec); - s_ledc_fade_rec = NULL; return; } -esp_err_t ledc_fade_start(ledc_channel_t channel, ledc_fade_mode_t wait_done) +esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t wait_done) { LEDC_CHECK(s_ledc_fade_rec != NULL, LEDC_FADE_SERVICE_ERR_STR, ESP_ERR_INVALID_STATE); LEDC_CHECK(wait_done < LEDC_FADE_MAX, LEDC_FADE_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - int speed_mode = s_ledc_fade_rec[channel].speed_mode; - xSemaphoreTake(s_ledc_fade_rec[channel].ledc_fade_mux, portMAX_DELAY); + xSemaphoreTake(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux, portMAX_DELAY); if (wait_done == LEDC_FADE_WAIT_DONE) { - s_ledc_fade_rec[channel].mode = LEDC_FADE_WAIT_DONE; + s_ledc_fade_rec[speed_mode][channel]->mode = LEDC_FADE_WAIT_DONE; ledc_update_duty(speed_mode, channel); - xSemaphoreTake(s_ledc_fade_rec[channel].ledc_fade_sem, portMAX_DELAY); + xSemaphoreTake(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, portMAX_DELAY); } else { - s_ledc_fade_rec[channel].mode = LEDC_FADE_NO_WAIT; + s_ledc_fade_rec[speed_mode][channel]->mode = LEDC_FADE_NO_WAIT; ledc_update_duty(speed_mode, channel); } - xSemaphoreGive(s_ledc_fade_rec[channel].ledc_fade_mux); + xSemaphoreGive(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux); return ESP_OK; } diff --git a/components/esp32/include/soc/ledc_struct.h b/components/esp32/include/soc/ledc_struct.h index c52f670770..0745a2ec25 100644 --- a/components/esp32/include/soc/ledc_struct.h +++ b/components/esp32/include/soc/ledc_struct.h @@ -21,7 +21,8 @@ typedef volatile struct { uint32_t timer_sel: 2; /*There are four high speed timers the two bits are used to select one of them for high speed channel. 2'b00: seletc hstimer0. 2'b01: select hstimer1. 2'b10: select hstimer2. 2'b11: select hstimer3.*/ uint32_t sig_out_en: 1; /*This is the output enable control bit for high speed channel*/ uint32_t idle_lv: 1; /*This bit is used to control the output value when high speed channel is off.*/ - uint32_t reserved4: 27; + uint32_t low_speed_update: 1; /*This bit is only useful for low speed timer channels, reserved for high speed timers*/ + uint32_t reserved4: 26; uint32_t clk_en: 1; /*This bit is clock gating control signal. when software configure LED_PWM internal registers it controls the register clock.*/ }; uint32_t val; @@ -204,9 +205,13 @@ typedef volatile struct { } int_clr; union { struct { - uint32_t apb_clk_sel: 1; /*This bit is used to set the frequency of slow_clk. 1'b1:80mhz 1'b0:8mhz*/ + uint32_t apb_clk_sel: 1; /*This bit decides the slow clock for LEDC low speed channels, so we want to replace the field name with slow_clk_sel*/ uint32_t reserved1: 31; }; + struct { + uint32_t slow_clk_sel: 1; /*This bit is used to set the frequency of slow_clk. 1'b1:80mhz 1'b0:8mhz, (only used by LEDC low speed channels/timers)*/ + uint32_t reserved: 31; + }; uint32_t val; } conf; uint32_t reserved_194; diff --git a/examples/peripherals/ledc/README.md b/examples/peripherals/ledc/README.md index 9feea6b25b..09a181a8b6 100644 --- a/examples/peripherals/ledc/README.md +++ b/examples/peripherals/ledc/README.md @@ -14,3 +14,4 @@ * This example use GPIO18/19/4/5 as LEDC ouput, and it will change the duty repeatedly. + * GPIO18/19 are from high speed channel group. GPIO4/5 are from low speed channel group. diff --git a/examples/peripherals/ledc/main/ledc_fade.c b/examples/peripherals/ledc/main/ledc_fade.c index dcdb0462f6..e9e453852d 100644 --- a/examples/peripherals/ledc/main/ledc_fade.c +++ b/examples/peripherals/ledc/main/ledc_fade.c @@ -27,105 +27,124 @@ * * 4. This example use GPIO18/19/4/5 as LEDC ouput, and it will change the duty repeatedly. * + * 5. GPIO18/19 are from high speed channel group. GPIO4/5 are from low speed channel group. * */ +#define LEDC_HS_TIMER LEDC_TIMER_0 +#define LEDC_HS_MODE LEDC_HIGH_SPEED_MODE +#define LEDC_HS_CH0_GPIO (18) +#define LEDC_HS_CH0_CHANNEL LEDC_CHANNEL_0 +#define LEDC_HS_CH1_GPIO (19) +#define LEDC_HS_CH1_CHANNEL LEDC_CHANNEL_1 -#define LEDC_IO_0 (18) -#define LEDC_IO_1 (19) -#define LEDC_IO_2 (4) -#define LEDC_IO_3 (5) +#define LEDC_LS_TIMER LEDC_TIMER_1 +#define LEDC_LS_MODE LEDC_LOW_SPEED_MODE +#define LEDC_LS_CH2_GPIO (4) +#define LEDC_LS_CH2_CHANNEL LEDC_CHANNEL_2 +#define LEDC_LS_CH3_GPIO (5) +#define LEDC_LS_CH3_CHANNEL LEDC_CHANNEL_3 + +#define LEDC_TEST_CH_NUM (4) +typedef struct { + int channel; + int io; + int mode; + int timer_idx; +} ledc_info_t; + +void app_main() +{ + int ch; + ledc_info_t ledc_ch[LEDC_TEST_CH_NUM] = { + { + .channel = LEDC_HS_CH0_CHANNEL, + .io = LEDC_HS_CH0_GPIO, + .mode = LEDC_HS_MODE, + .timer_idx = LEDC_HS_TIMER + }, + { + .channel = LEDC_HS_CH1_CHANNEL, + .io = LEDC_HS_CH1_GPIO, + .mode = LEDC_HS_MODE, + .timer_idx = LEDC_HS_TIMER + }, + { + .channel = LEDC_LS_CH2_CHANNEL, + .io = LEDC_LS_CH2_GPIO, + .mode = LEDC_LS_MODE, + .timer_idx = LEDC_LS_TIMER + }, + { + .channel = LEDC_LS_CH3_CHANNEL, + .io = LEDC_LS_CH3_GPIO, + .mode = LEDC_LS_MODE, + .timer_idx = LEDC_LS_TIMER + } + }; -esp_err_t app_main() -{ ledc_timer_config_t ledc_timer = { - //set timer counter bit number - .bit_num = LEDC_TIMER_13_BIT, - //set frequency of pwm - .freq_hz = 5000, - //timer mode, - .speed_mode = LEDC_HIGH_SPEED_MODE, - //timer index - .timer_num = LEDC_TIMER_0 + .bit_num = LEDC_TIMER_13_BIT, //set timer counter bit number + .freq_hz = 5000, //set frequency of pwm + .speed_mode = LEDC_HS_MODE, //timer mode, + .timer_num = LEDC_HS_TIMER //timer index }; + //configure timer0 for high speed channels ledc_timer_config(&ledc_timer); - ledc_channel_config_t ledc_channel = { - //set LEDC channel 0 - .channel = LEDC_CHANNEL_0, - //set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1) - .duty = 100, - //GPIO number - .gpio_num = LEDC_IO_0, - //GPIO INTR TYPE, as an example, we enable fade_end interrupt here. - .intr_type = LEDC_INTR_FADE_END, - //set LEDC mode, from ledc_mode_t - .speed_mode = LEDC_HIGH_SPEED_MODE, - //set LEDC timer source, if different channel use one timer, - //the frequency and bit_num of these channels should be the same - .timer_sel = LEDC_TIMER_0 - }; - //set the configuration - ledc_channel_config(&ledc_channel); + //configure timer1 for low speed channels + ledc_timer.speed_mode = LEDC_LS_MODE; + ledc_timer.timer_num = LEDC_LS_TIMER; + ledc_timer_config(&ledc_timer); - //config ledc channel1 - ledc_channel.channel = LEDC_CHANNEL_1; - ledc_channel.gpio_num = LEDC_IO_1; - ledc_channel_config(&ledc_channel); - //config ledc channel2 - ledc_channel.channel = LEDC_CHANNEL_2; - ledc_channel.gpio_num = LEDC_IO_2; - ledc_channel_config(&ledc_channel); - //config ledc channel3 - ledc_channel.channel = LEDC_CHANNEL_3; - ledc_channel.gpio_num = LEDC_IO_3; - ledc_channel_config(&ledc_channel); + for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) { + ledc_channel_config_t ledc_channel = { + //set LEDC channel 0 + .channel = ledc_ch[ch].channel, + //set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1) + .duty = 0, + //GPIO number + .gpio_num = ledc_ch[ch].io, + //GPIO INTR TYPE, as an example, we enable fade_end interrupt here. + .intr_type = LEDC_INTR_FADE_END, + //set LEDC mode, from ledc_mode_t + .speed_mode = ledc_ch[ch].mode, + //set LEDC timer source, if different channel use one timer, + //the frequency and bit_num of these channels should be the same + .timer_sel = ledc_ch[ch].timer_idx, + }; + //set the configuration + ledc_channel_config(&ledc_channel); + } //initialize fade service. ledc_fade_func_install(0); - - while(1) { + while (1) { printf("LEDC fade up\n"); - ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 1000, 2000); - ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 7000, 2000); - ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 5000, 2000); - ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3, 3000, 2000); - ledc_fade_start(LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT); - ledc_fade_start(LEDC_CHANNEL_1, LEDC_FADE_NO_WAIT); - ledc_fade_start(LEDC_CHANNEL_2, LEDC_FADE_NO_WAIT); - ledc_fade_start(LEDC_CHANNEL_3, LEDC_FADE_NO_WAIT); + for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) { + ledc_set_fade_with_time(ledc_ch[ch].mode, ledc_ch[ch].channel, 4000, 2000); + ledc_fade_start(ledc_ch[ch].mode, ledc_ch[ch].channel, LEDC_FADE_NO_WAIT); + } vTaskDelay(3000 / portTICK_PERIOD_MS); printf("LEDC fade down\n"); - ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 100, 2000); - ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 300, 2000); - ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 500, 2000); - ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3, 700, 2000); - ledc_fade_start(LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT); - ledc_fade_start(LEDC_CHANNEL_1, LEDC_FADE_NO_WAIT); - ledc_fade_start(LEDC_CHANNEL_2, LEDC_FADE_NO_WAIT); - ledc_fade_start(LEDC_CHANNEL_3, LEDC_FADE_NO_WAIT); + for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) { + ledc_set_fade_with_time(ledc_ch[ch].mode, ledc_ch[ch].channel, 0, 2000); + ledc_fade_start(ledc_ch[ch].mode, ledc_ch[ch].channel, LEDC_FADE_NO_WAIT); + } vTaskDelay(3000 / portTICK_PERIOD_MS); printf("LEDC set duty without fade\n"); - ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 1000); - ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 7000); - ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 5000); - ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3, 3000); - ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0); - ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1); - ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2); - ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3); - vTaskDelay(2000 / portTICK_PERIOD_MS); + for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) { + ledc_set_duty(ledc_ch[ch].mode, ledc_ch[ch].channel, 2000); + ledc_update_duty(ledc_ch[ch].mode, ledc_ch[ch].channel); + } + vTaskDelay(1000 / portTICK_PERIOD_MS); printf("LEDC set duty without fade\n"); - ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0); - ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0); - ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0); - ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3, 0); - ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0); - ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1); - ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2); - ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3); - vTaskDelay(2000 / portTICK_PERIOD_MS); + for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) { + ledc_set_duty(ledc_ch[ch].mode, ledc_ch[ch].channel, 0); + ledc_update_duty(ledc_ch[ch].mode, ledc_ch[ch].channel); + } + vTaskDelay(1000 / portTICK_PERIOD_MS); } }