From fcc6514dde9d59f87c0687c3acb800d700852776 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Tue, 28 Mar 2023 22:55:18 +0800 Subject: [PATCH] ledc: Add an all-in-one HAL function to set fade parameters, and refactor ledc_ll_get_max_duty function --- components/driver/ledc/include/driver/ledc.h | 2 +- components/driver/ledc/ledc.c | 18 ++--- components/hal/esp32/include/hal/ledc_ll.h | 70 +++++++++++--------- components/hal/esp32c2/include/hal/ledc_ll.h | 70 +++++++++++--------- components/hal/esp32c3/include/hal/ledc_ll.h | 70 +++++++++++--------- components/hal/esp32c6/include/hal/ledc_ll.h | 67 ++++++++++--------- components/hal/esp32h2/include/hal/ledc_ll.h | 67 ++++++++++--------- components/hal/esp32s2/include/hal/ledc_ll.h | 70 +++++++++++--------- components/hal/esp32s3/include/hal/ledc_ll.h | 70 +++++++++++--------- components/hal/include/hal/ledc_hal.h | 19 +++++- components/hal/ledc_hal.c | 8 +-- components/hal/ledc_hal_iram.c | 29 +++++++- 12 files changed, 320 insertions(+), 240 deletions(-) diff --git a/components/driver/ledc/include/driver/ledc.h b/components/driver/ledc/include/driver/ledc.h index 6cccf3276c..580288af0f 100644 --- a/components/driver/ledc/include/driver/ledc.h +++ b/components/driver/ledc/include/driver/ledc.h @@ -459,7 +459,7 @@ esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_f * @brief Stop LEDC fading. The duty of the channel is garanteed to be fixed at most one PWM cycle after the function returns. * @note This API can be called if a new fixed duty or a new fade want to be set while the last fade operation is still running in progress. * @note Call this API will abort the fading operation only if it was started by calling ledc_fade_start with LEDC_FADE_NO_WAIT mode. - * @note If a fade was started with LEDC_FADE_WAIT_DONE mode, calling this API afterwards HAS no use in stopping the fade. Fade will continue until it reachs the target duty. + * @note If a fade was started with LEDC_FADE_WAIT_DONE mode, calling this API afterwards has no use in stopping the fade. Fade will continue until it reachs the target duty. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param channel LEDC channel number * diff --git a/components/driver/ledc/ledc.c b/components/driver/ledc/ledc.c index 000af6eec7..44de2e89c6 100644 --- a/components/driver/ledc/ledc.c +++ b/components/driver/ledc/ledc.c @@ -180,8 +180,10 @@ static void _ledc_op_lock_release(ledc_mode_t mode, ledc_channel_t channel) static uint32_t ledc_get_max_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { // The arguments are checked before internally calling this function. + ledc_timer_t timer_sel; + ledc_hal_get_channel_timer(&(p_ledc_obj[speed_mode]->ledc_hal), channel, &timer_sel); uint32_t max_duty; - ledc_hal_get_max_duty(&(p_ledc_obj[speed_mode]->ledc_hal), channel, &max_duty); + ledc_hal_get_max_duty(&(p_ledc_obj[speed_mode]->ledc_hal), timer_sel, &max_duty); return max_duty; } @@ -214,12 +216,8 @@ int duty_val, ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t if (duty_val >= 0) { ledc_hal_set_duty_int_part(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_val); } - ledc_hal_set_duty_direction(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_direction); - ledc_hal_set_duty_num(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_num); - ledc_hal_set_duty_cycle(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_cycle); - ledc_hal_set_duty_scale(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_scale); + ledc_hal_set_fade_param(&(p_ledc_obj[speed_mode]->ledc_hal), channel, 0, duty_direction, duty_cycle, duty_scale, duty_num); #if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED - ledc_hal_set_duty_range_wr_addr(&(p_ledc_obj[speed_mode]->ledc_hal), channel, 0); ledc_hal_set_range_number(&(p_ledc_obj[speed_mode]->ledc_hal), channel, 1); #endif return ESP_OK; @@ -853,7 +851,7 @@ uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num) ESP_LOGW(LEDC_TAG, "LEDC timer not configured, call ledc_timer_config to set timer frequency"); return 0; } - return ((uint64_t) src_clk_freq << 8) / precision / clock_divider; + return ((uint64_t) src_clk_freq << LEDC_LL_FRACTIONAL_BITS) / precision / clock_divider; } static inline void IRAM_ATTR ledc_calc_fade_end_channel(uint32_t *fade_end_status, uint32_t *channel) @@ -1336,11 +1334,7 @@ static esp_err_t _ledc_set_multi_fade(ledc_mode_t speed_mode, ledc_channel_t cha ledc_hal_set_duty_int_part(&(p_ledc_obj[speed_mode]->ledc_hal), channel, start_duty); for (int i = 0; i < list_len; i++) { ledc_fade_param_config_t fade_param = fade_params_list[i]; - ledc_hal_set_duty_direction(&(p_ledc_obj[speed_mode]->ledc_hal), channel, fade_param.dir); - ledc_hal_set_duty_cycle(&(p_ledc_obj[speed_mode]->ledc_hal), channel, fade_param.cycle_num); - ledc_hal_set_duty_scale(&(p_ledc_obj[speed_mode]->ledc_hal), channel, fade_param.scale); - ledc_hal_set_duty_num(&(p_ledc_obj[speed_mode]->ledc_hal), channel, fade_param.step_num); - ledc_hal_set_duty_range_wr_addr(&(p_ledc_obj[speed_mode]->ledc_hal), channel, i); + ledc_hal_set_fade_param(&(p_ledc_obj[speed_mode]->ledc_hal), channel, i, fade_param.dir, fade_param.cycle_num, fade_param.scale, fade_param.step_num); } ledc_hal_set_range_number(&(p_ledc_obj[speed_mode]->ledc_hal), channel, list_len); portEXIT_CRITICAL(&ledc_spinlock); diff --git a/components/hal/esp32/include/hal/ledc_ll.h b/components/hal/esp32/include/hal/ledc_ll.h index 212744f83a..9953191522 100644 --- a/components/hal/esp32/include/hal/ledc_ll.h +++ b/components/hal/esp32/include/hal/ledc_ll.h @@ -225,6 +225,21 @@ static inline void ledc_ll_get_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed *duty_resolution = hw->timer_group[speed_mode].timer[timer_sel].conf.duty_resolution; } +/** + * @brief Get LEDC max duty + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode + * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t + * @param max_duty Pointer to accept the max duty + * + * @return None + */ +static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *max_duty) +{ + *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)); +} + /** * @brief Update channel configure when select low speed mode * @@ -239,22 +254,6 @@ static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_m hw->channel_group[speed_mode].channel[channel_num].conf0.low_speed_update = 1; } -/** - * @brief Get LEDC max duty - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param max_duty Pointer to accept the max duty - * - * @return None - */ -static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *max_duty) -{ - int timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel; - *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)); -} - /** * @brief Set LEDC hpoint value * @@ -330,21 +329,6 @@ static inline void ledc_ll_set_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_ hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc = duty_direction; } -/** - * @brief Get LEDC duty change direction - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_direction Pointer to accept the LEDC duty change direction, increase or decrease - * - * @return None - */ -static inline void ledc_ll_get_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t *duty_direction) -{ - *duty_direction = hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc; -} - /** * @brief Set the number of increased or decreased times * @@ -390,6 +374,30 @@ static inline void ledc_ll_set_duty_scale(ledc_dev_t *hw, ledc_mode_t speed_mode hw->channel_group[speed_mode].channel[channel_num].conf1.duty_scale = duty_scale; } +/** + * @brief Function to set fade parameters all-in-one + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode + * @param channel_num LEDC channel index (0-7), select from ledc_channel_t + * @param dir LEDC duty change direction, increase or decrease + * @param cycle The duty cycles + * @param scale The step scale + * @param step The number of increased or decreased times + * + * @return None + */ +static inline void ledc_ll_set_fade_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step) +{ + typeof(hw->channel_group[speed_mode].channel[channel_num].conf1) conf1_reg; + conf1_reg.val = hw->channel_group[speed_mode].channel[channel_num].conf1.val; + conf1_reg.duty_inc = dir; + conf1_reg.duty_num = step; + conf1_reg.duty_cycle = cycle; + conf1_reg.duty_scale = scale; + hw->channel_group[speed_mode].channel[channel_num].conf1.val = conf1_reg.val; +} + /** * @brief Set the output enable * diff --git a/components/hal/esp32c2/include/hal/ledc_ll.h b/components/hal/esp32c2/include/hal/ledc_ll.h index 3b8d91f6a6..9d2da4b87f 100644 --- a/components/hal/esp32c2/include/hal/ledc_ll.h +++ b/components/hal/esp32c2/include/hal/ledc_ll.h @@ -210,6 +210,21 @@ static inline void ledc_ll_get_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed *duty_resolution = hw->timer_group[speed_mode].timer[timer_sel].conf.duty_res; } +/** + * @brief Get LEDC max duty + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode + * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t + * @param max_duty Pointer to accept the max duty + * + * @return None + */ +static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *max_duty) +{ + *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_res)); +} + /** * @brief Update channel configure when select low speed mode * @@ -224,22 +239,6 @@ static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_m hw->channel_group[speed_mode].channel[channel_num].conf0.para_up = 1; } -/** - * @brief Get LEDC max duty - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param max_duty Pointer to accept the max duty - * - * @return None - */ -static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *max_duty) -{ - uint32_t timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel; - *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_res)); -} - /** * @brief Set LEDC hpoint value * @@ -315,21 +314,6 @@ static inline void ledc_ll_set_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_ hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc = duty_direction; } -/** - * @brief Get LEDC duty change direction - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_direction Pointer to accept the LEDC duty change direction, increase or decrease - * - * @return None - */ -static inline void ledc_ll_get_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t *duty_direction) -{ - *duty_direction = hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc; -} - /** * @brief Set the number of increased or decreased times * @@ -375,6 +359,30 @@ static inline void ledc_ll_set_duty_scale(ledc_dev_t *hw, ledc_mode_t speed_mode hw->channel_group[speed_mode].channel[channel_num].conf1.duty_scale = duty_scale; } +/** + * @brief Function to set fade parameters all-in-one + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, low-speed mode only + * @param channel_num LEDC channel index (0-5), select from ledc_channel_t + * @param dir LEDC duty change direction, increase or decrease + * @param cycle The duty cycles + * @param scale The step scale + * @param step The number of increased or decreased times + * + * @return None + */ +static inline void ledc_ll_set_fade_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step) +{ + typeof(hw->channel_group[speed_mode].channel[channel_num].conf1) conf1_reg; + conf1_reg.val = hw->channel_group[speed_mode].channel[channel_num].conf1.val; + conf1_reg.duty_inc = dir; + conf1_reg.duty_num = step; + conf1_reg.duty_cycle = cycle; + conf1_reg.duty_scale = scale; + hw->channel_group[speed_mode].channel[channel_num].conf1.val = conf1_reg.val; +} + /** * @brief Set the output enable * diff --git a/components/hal/esp32c3/include/hal/ledc_ll.h b/components/hal/esp32c3/include/hal/ledc_ll.h index 0edca33890..7fb7c0b31f 100644 --- a/components/hal/esp32c3/include/hal/ledc_ll.h +++ b/components/hal/esp32c3/include/hal/ledc_ll.h @@ -210,6 +210,21 @@ static inline void ledc_ll_get_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed *duty_resolution = hw->timer_group[speed_mode].timer[timer_sel].conf.duty_resolution; } +/** + * @brief Get LEDC max duty + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode + * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t + * @param max_duty Pointer to accept the max duty + * + * @return None + */ +static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *max_duty) +{ + *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)); +} + /** * @brief Update channel configure when select low speed mode * @@ -224,22 +239,6 @@ static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_m hw->channel_group[speed_mode].channel[channel_num].conf0.low_speed_update = 1; } -/** - * @brief Get LEDC max duty - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param max_duty Pointer to accept the max duty - * - * @return None - */ -static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *max_duty) -{ - uint32_t timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel; - *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)); -} - /** * @brief Set LEDC hpoint value * @@ -315,21 +314,6 @@ static inline void ledc_ll_set_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_ hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc = duty_direction; } -/** - * @brief Get LEDC duty change direction - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_direction Pointer to accept the LEDC duty change direction, increase or decrease - * - * @return None - */ -static inline void ledc_ll_get_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t *duty_direction) -{ - *duty_direction = hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc; -} - /** * @brief Set the number of increased or decreased times * @@ -375,6 +359,30 @@ static inline void ledc_ll_set_duty_scale(ledc_dev_t *hw, ledc_mode_t speed_mode hw->channel_group[speed_mode].channel[channel_num].conf1.duty_scale = duty_scale; } +/** + * @brief Function to set fade parameters all-in-one + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, low-speed mode only + * @param channel_num LEDC channel index (0-5), select from ledc_channel_t + * @param dir LEDC duty change direction, increase or decrease + * @param cycle The duty cycles + * @param scale The step scale + * @param step The number of increased or decreased times + * + * @return None + */ +static inline void ledc_ll_set_fade_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step) +{ + typeof(hw->channel_group[speed_mode].channel[channel_num].conf1) conf1_reg; + conf1_reg.val = hw->channel_group[speed_mode].channel[channel_num].conf1.val; + conf1_reg.duty_inc = dir; + conf1_reg.duty_num = step; + conf1_reg.duty_cycle = cycle; + conf1_reg.duty_scale = scale; + hw->channel_group[speed_mode].channel[channel_num].conf1.val = conf1_reg.val; +} + /** * @brief Set the output enable * diff --git a/components/hal/esp32c6/include/hal/ledc_ll.h b/components/hal/esp32c6/include/hal/ledc_ll.h index 49eaa0a098..d636311c51 100644 --- a/components/hal/esp32c6/include/hal/ledc_ll.h +++ b/components/hal/esp32c6/include/hal/ledc_ll.h @@ -231,6 +231,21 @@ static inline void ledc_ll_get_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed *duty_resolution = hw->timer_group[speed_mode].timer[timer_sel].conf.duty_res; } +/** + * @brief Get LEDC max duty + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, low-speed mode only + * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t + * @param max_duty Pointer to accept the max duty + * + * @return None + */ +static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *max_duty) +{ + *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_res)); +} + /** * @brief Update channel configure when select low speed mode * @@ -245,22 +260,6 @@ static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_m hw->channel_group[speed_mode].channel[channel_num].conf0.para_up = 1; } -/** - * @brief Get LEDC max duty - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, low-speed mode only - * @param channel_num LEDC channel index (0-5), select from ledc_channel_t - * @param max_duty Pointer to accept the max duty - * - * @return None - */ -static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *max_duty) -{ - uint32_t timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel; - *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_res)); -} - /** * @brief Set LEDC hpoint value * @@ -336,21 +335,6 @@ static inline void ledc_ll_set_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_ hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_duty_inc = duty_direction; } -/** - * @brief Get LEDC duty change direction - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, low-speed mode only - * @param channel_num LEDC channel index (0-5), select from ledc_channel_t - * @param duty_direction Pointer to accept the LEDC duty change direction, increase or decrease - * - * @return None - */ -static inline void ledc_ll_get_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t *duty_direction) -{ - *duty_direction = (ledc_duty_direction_t)(hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_duty_inc); -} - /** * @brief Set the number of increased or decreased times * @@ -396,6 +380,25 @@ static inline void ledc_ll_set_duty_scale(ledc_dev_t *hw, ledc_mode_t speed_mode hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_scale = duty_scale; } +/** + * @brief Function to set fade parameters all-in-one + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, low-speed mode only + * @param channel_num LEDC channel index (0-5), select from ledc_channel_t + * @param dir LEDC duty change direction, increase or decrease + * @param cycle The duty cycles + * @param scale The step scale + * @param step The number of increased or decreased times + * + * @return None + */ +static inline void ledc_ll_set_fade_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step) +{ + uint32_t val = (dir << LEDC_CH0_GAMMA_DUTY_INC_S) | (cycle << LEDC_CH0_GAMMA_DUTY_CYCLE_S) | (scale << LEDC_CH0_GAMMA_SCALE_S) | (step << LEDC_CH0_GAMMA_DUTY_NUM_S); + hw->channel_gamma_group[speed_mode].channel[channel_num].wr.val = val; +} + /** * @brief Set the range number of the specified duty configurations to be written from gamma_wr register to gamma ram * @@ -469,7 +472,7 @@ static inline void ledc_ll_set_duty_range_rd_addr(ledc_dev_t *hw, ledc_mode_t sp * * @return None */ -static inline void ledc_ll_get_duty_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *dir, uint32_t *cycle, uint32_t *scale, uint32_t *step) +static inline void ledc_ll_get_fade_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *dir, uint32_t *cycle, uint32_t *scale, uint32_t *step) { uint32_t val = hw->channel_gamma_group[speed_mode].channel[channel_num].rd_data.gamma_rd_data; *dir = (val & LEDC_CH0_GAMMA_DUTY_INC_M) >> LEDC_CH0_GAMMA_DUTY_INC_S; diff --git a/components/hal/esp32h2/include/hal/ledc_ll.h b/components/hal/esp32h2/include/hal/ledc_ll.h index 7c319e374a..0d644590a1 100644 --- a/components/hal/esp32h2/include/hal/ledc_ll.h +++ b/components/hal/esp32h2/include/hal/ledc_ll.h @@ -229,6 +229,21 @@ static inline void ledc_ll_get_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed *duty_resolution = hw->timer_group[speed_mode].timer[timer_sel].conf.duty_res; } +/** + * @brief Get LEDC max duty + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, low-speed mode only + * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t + * @param max_duty Pointer to accept the max duty + * + * @return None + */ +static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *max_duty) +{ + *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_res)); +} + /** * @brief Update channel configure when select low speed mode * @@ -243,22 +258,6 @@ static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_m hw->channel_group[speed_mode].channel[channel_num].conf0.para_up = 1; } -/** - * @brief Get LEDC max duty - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, low-speed mode only - * @param channel_num LEDC channel index (0-5), select from ledc_channel_t - * @param max_duty Pointer to accept the max duty - * - * @return None - */ -static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *max_duty) -{ - uint32_t timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel; - *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_res)); -} - /** * @brief Set LEDC hpoint value * @@ -334,21 +333,6 @@ static inline void ledc_ll_set_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_ hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_duty_inc = duty_direction; } -/** - * @brief Get LEDC duty change direction - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, low-speed mode only - * @param channel_num LEDC channel index (0-5), select from ledc_channel_t - * @param duty_direction Pointer to accept the LEDC duty change direction, increase or decrease - * - * @return None - */ -static inline void ledc_ll_get_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t *duty_direction) -{ - *duty_direction = (ledc_duty_direction_t)(hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_duty_inc); -} - /** * @brief Set the number of increased or decreased times * @@ -394,6 +378,25 @@ static inline void ledc_ll_set_duty_scale(ledc_dev_t *hw, ledc_mode_t speed_mode hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_scale = duty_scale; } +/** + * @brief Function to set fade parameters all-in-one + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, low-speed mode only + * @param channel_num LEDC channel index (0-5), select from ledc_channel_t + * @param dir LEDC duty change direction, increase or decrease + * @param cycle The duty cycles + * @param scale The step scale + * @param step The number of increased or decreased times + * + * @return None + */ +static inline void ledc_ll_set_fade_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step) +{ + uint32_t val = (dir << LEDC_CH0_GAMMA_DUTY_INC_S) | (cycle << LEDC_CH0_GAMMA_DUTY_CYCLE_S) | (scale << LEDC_CH0_GAMMA_SCALE_S) | (step << LEDC_CH0_GAMMA_DUTY_NUM_S); + hw->channel_gamma_group[speed_mode].channel[channel_num].wr.val = val; +} + /** * @brief Set the range number of the specified duty configurations to be written from gamma_wr register to gamma ram * @@ -467,7 +470,7 @@ static inline void ledc_ll_set_duty_range_rd_addr(ledc_dev_t *hw, ledc_mode_t sp * * @return None */ -static inline void ledc_ll_get_duty_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *dir, uint32_t *cycle, uint32_t *scale, uint32_t *step) +static inline void ledc_ll_get_fade_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *dir, uint32_t *cycle, uint32_t *scale, uint32_t *step) { uint32_t val = hw->channel_gamma_group[speed_mode].channel[channel_num].rd_data.gamma_rd_data; *dir = (val & LEDC_CH0_GAMMA_DUTY_INC_M) >> LEDC_CH0_GAMMA_DUTY_INC_S; diff --git a/components/hal/esp32s2/include/hal/ledc_ll.h b/components/hal/esp32s2/include/hal/ledc_ll.h index fbdd6cc2f1..0eb780ec9b 100644 --- a/components/hal/esp32s2/include/hal/ledc_ll.h +++ b/components/hal/esp32s2/include/hal/ledc_ll.h @@ -242,6 +242,21 @@ static inline void ledc_ll_get_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed *duty_resolution = hw->timer_group[speed_mode].timer[timer_sel].conf.duty_resolution; } +/** + * @brief Get LEDC max duty + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode + * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t + * @param max_duty Pointer to accept the max duty + * + * @return None + */ +static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *max_duty) +{ + *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)); +} + /** * @brief Update channel configure when select low speed mode * @@ -256,22 +271,6 @@ static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_m hw->channel_group[speed_mode].channel[channel_num].conf0.low_speed_update = 1; } -/** - * @brief Get LEDC max duty - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param max_duty Pointer to accept the max duty - * - * @return None - */ -static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *max_duty) -{ - uint32_t timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel; - *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)); -} - /** * @brief Set LEDC hpoint value * @@ -347,21 +346,6 @@ static inline void ledc_ll_set_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_ hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc = duty_direction; } -/** - * @brief Get LEDC duty change direction - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_direction Pointer to accept the LEDC duty change direction, increase or decrease - * - * @return None - */ -static inline void ledc_ll_get_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t *duty_direction) -{ - *duty_direction = hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc; -} - /** * @brief Set the number of increased or decreased times * @@ -407,6 +391,30 @@ static inline void ledc_ll_set_duty_scale(ledc_dev_t *hw, ledc_mode_t speed_mode hw->channel_group[speed_mode].channel[channel_num].conf1.duty_scale = duty_scale; } +/** + * @brief Function to set fade parameters all-in-one + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, low-speed mode only + * @param channel_num LEDC channel index (0-7), select from ledc_channel_t + * @param dir LEDC duty change direction, increase or decrease + * @param cycle The duty cycles + * @param scale The step scale + * @param step The number of increased or decreased times + * + * @return None + */ +static inline void ledc_ll_set_fade_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step) +{ + typeof(hw->channel_group[speed_mode].channel[channel_num].conf1) conf1_reg; + conf1_reg.val = hw->channel_group[speed_mode].channel[channel_num].conf1.val; + conf1_reg.duty_inc = dir; + conf1_reg.duty_num = step; + conf1_reg.duty_cycle = cycle; + conf1_reg.duty_scale = scale; + hw->channel_group[speed_mode].channel[channel_num].conf1.val = conf1_reg.val; +} + /** * @brief Set the output enable * diff --git a/components/hal/esp32s3/include/hal/ledc_ll.h b/components/hal/esp32s3/include/hal/ledc_ll.h index 101443a2f0..2e44509563 100644 --- a/components/hal/esp32s3/include/hal/ledc_ll.h +++ b/components/hal/esp32s3/include/hal/ledc_ll.h @@ -211,6 +211,21 @@ static inline void ledc_ll_get_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed *duty_resolution = hw->timer_group[speed_mode].timer[timer_sel].conf.duty_resolution; } +/** + * @brief Get LEDC max duty + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode + * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t + * @param max_duty Pointer to accept the max duty + * + * @return None + */ +static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *max_duty) +{ + *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)); +} + /** * @brief Update channel configure when select low speed mode * @@ -225,22 +240,6 @@ static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_m hw->channel_group[speed_mode].channel[channel_num].conf0.low_speed_update = 1; } -/** - * @brief Get LEDC max duty - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param max_duty Pointer to accept the max duty - * - * @return None - */ -static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *max_duty) -{ - uint32_t timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel; - *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)); -} - /** * @brief Set LEDC hpoint value * @@ -316,21 +315,6 @@ static inline void ledc_ll_set_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_ hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc = duty_direction; } -/** - * @brief Get LEDC duty change direction - * - * @param hw Beginning address of the peripheral registers - * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_direction Pointer to accept the LEDC duty change direction, increase or decrease - * - * @return None - */ -static inline void ledc_ll_get_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t *duty_direction) -{ - *duty_direction = hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc; -} - /** * @brief Set the number of increased or decreased times * @@ -376,6 +360,30 @@ static inline void ledc_ll_set_duty_scale(ledc_dev_t *hw, ledc_mode_t speed_mode hw->channel_group[speed_mode].channel[channel_num].conf1.duty_scale = duty_scale; } +/** + * @brief Function to set fade parameters all-in-one + * + * @param hw Beginning address of the peripheral registers + * @param speed_mode LEDC speed_mode, low-speed mode only + * @param channel_num LEDC channel index (0-7), select from ledc_channel_t + * @param dir LEDC duty change direction, increase or decrease + * @param cycle The duty cycles + * @param scale The step scale + * @param step The number of increased or decreased times + * + * @return None + */ +static inline void ledc_ll_set_fade_param(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step) +{ + typeof(hw->channel_group[speed_mode].channel[channel_num].conf1) conf1_reg; + conf1_reg.val = hw->channel_group[speed_mode].channel[channel_num].conf1.val; + conf1_reg.duty_inc = dir; + conf1_reg.duty_num = step; + conf1_reg.duty_cycle = cycle; + conf1_reg.duty_scale = scale; + hw->channel_group[speed_mode].channel[channel_num].conf1.val = conf1_reg.val; +} + /** * @brief Set the output enable * diff --git a/components/hal/include/hal/ledc_hal.h b/components/hal/include/hal/ledc_hal.h index 4f8731b1ad..1124e82a7b 100644 --- a/components/hal/include/hal/ledc_hal.h +++ b/components/hal/include/hal/ledc_hal.h @@ -157,12 +157,12 @@ typedef struct { * @brief Get LEDC max duty * * @param hal Context of the HAL layer - * @param channel_num LEDC channel index (0-7), select from ledc_channel_t + * @param channel_num LEDC timer index (0-3), select from ledc_timer_t * @param max_duty Pointer to accept the max duty * * @return None */ -#define ledc_hal_get_max_duty(hal, channel_num, max_duty) ledc_ll_get_max_duty((hal)->dev, (hal)->speed_mode, channel_num, max_duty) +#define ledc_hal_get_max_duty(hal, timer_sel, max_duty) ledc_ll_get_max_duty((hal)->dev, (hal)->speed_mode, timer_sel, max_duty) /** * @brief Get LEDC hpoint value @@ -338,6 +338,21 @@ void ledc_hal_set_duty_cycle(ledc_hal_context_t *hal, ledc_channel_t channel_num */ void ledc_hal_set_duty_scale(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t duty_scale); +/** + * @brief Function to set fade parameters all-in-one + * + * @param hal Context of the HAL layer + * @param channel_num LEDC channel index, select from ledc_channel_t + * @param range Range index + * @param dir LEDC duty change direction, increase or decrease + * @param cycle The duty cycles + * @param scale The step scale + * @param step The number of increased or decreased times + * + * @return None + */ +void ledc_hal_set_fade_param(const ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t range, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step); + #if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED /** * @brief Set the range number of the specified duty configurations to be written from gamma_wr register to gamma ram diff --git a/components/hal/ledc_hal.c b/components/hal/ledc_hal.c index 10c90df1c3..d92ddbb5f1 100644 --- a/components/hal/ledc_hal.c +++ b/components/hal/ledc_hal.c @@ -6,11 +6,7 @@ // The HAL layer for LEDC (common part) -#include "esp_attr.h" #include "hal/ledc_hal.h" -#include "soc/soc_caps.h" -#include "sdkconfig.h" -#include "hal/assert.h" #include "esp_rom_sys.h" void ledc_hal_init(ledc_hal_context_t *hal, ledc_mode_t speed_mode) @@ -64,9 +60,11 @@ void ledc_hal_get_clk_cfg(ledc_hal_context_t *hal, ledc_timer_t timer_sel, ledc_ void ledc_hal_get_fade_param(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t range, uint32_t *dir, uint32_t *cycle, uint32_t *scale, uint32_t *step) { ledc_ll_set_duty_range_rd_addr(hal->dev, hal->speed_mode, channel_num, range); +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 // On ESP32C6/H2, gamma ram read/write has the APB and LEDC clock domain sync issue // To make sure the parameter read is from the correct gamma ram addr, add a delay in between to ensure syncronization esp_rom_delay_us(5); - ledc_ll_get_duty_param(hal->dev, hal->speed_mode, channel_num, dir, cycle, scale, step); +#endif + ledc_ll_get_fade_param(hal->dev, hal->speed_mode, channel_num, dir, cycle, scale, step); } #endif diff --git a/components/hal/ledc_hal_iram.c b/components/hal/ledc_hal_iram.c index ede00c26a5..2fd83606da 100644 --- a/components/hal/ledc_hal_iram.c +++ b/components/hal/ledc_hal_iram.c @@ -7,8 +7,9 @@ // The HAL layer for LEDC (common part, in iram) // make these functions in a seperate file to make sure all LL functions are in the IRAM. -#include "esp_attr.h" #include "hal/ledc_hal.h" +#include "hal/assert.h" +#include "esp_rom_sys.h" void ledc_hal_ls_channel_update(ledc_hal_context_t *hal, ledc_channel_t channel_num) { @@ -55,6 +56,32 @@ void ledc_hal_set_duty_scale(ledc_hal_context_t *hal, ledc_channel_t channel_num ledc_ll_set_duty_scale(hal->dev, hal->speed_mode, channel_num, duty_scale); } +void ledc_hal_set_fade_param(const ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t range, uint32_t dir, uint32_t cycle, uint32_t scale, uint32_t step) +{ +#if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED + HAL_ASSERT(range < SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX); + +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 + // To workaround sync issue (C6, H2) + // This is to ensure the fade param write to the gamma_wr register would not mess up the last wr_addr + ledc_ll_set_duty_range_wr_addr(hal->dev, hal->speed_mode, channel_num, range); + esp_rom_delay_us(5); +#endif + + ledc_ll_set_fade_param(hal->dev, hal->speed_mode, channel_num, dir, cycle, scale, step); + ledc_ll_set_duty_range_wr_addr(hal->dev, hal->speed_mode, channel_num, range); +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 + // To workaround sync issue (C6, H2) + // This is to ensure the fade param in gamma_wr register can be written to the correct wr_addr + esp_rom_delay_us(5); +#endif + +#else // !SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED + HAL_ASSERT(range == 0); + ledc_ll_set_fade_param(hal->dev, hal->speed_mode, channel_num, dir, cycle, scale, step); +#endif // SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED +} + #if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED void ledc_hal_set_duty_range_wr_addr(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t duty_range) {