examples: replace legacy timer group with gptimer

This commit is contained in:
morris
2022-01-02 16:19:06 +08:00
parent 02f6b83f47
commit 6bf3af7c8e
20 changed files with 523 additions and 1454 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,16 +7,12 @@
#ifndef __IOT_LED_H__
#define __IOT_LED_H__
#include "driver/ledc.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "driver/ledc.h"
#define HW_TIMER_GROUP (0) /**< Hardware timer group */
#define HW_TIMER_ID (0) /**< Hardware timer number */
#define HW_TIMER_DIVIDER (16) /**< Hardware timer clock divider */
#define HW_TIMER_SCALE (TIMER_BASE_CLK / HW_TIMER_DIVIDER) /**< Convert counter value to seconds */
#define GAMMA_CORRECTION 0.8 /**< Gamma curve parameter */
#define GAMMA_TABLE_SIZE 256 /**< Gamma table size, used for led fade*/
#define DUTY_SET_CYCLE (20) /**< Set duty cycle */

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,26 +7,14 @@
#ifndef __IOT_LIGHT_H__
#define __IOT_LIGHT_H__
#include "driver/ledc.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "driver/ledc.h"
/********************************** NOTE *********************************/
/* When we create a light object, a hardware timer will be enabled, this */
/* timer is used to realize fade and blink operation. The default timer */
/* occupied is timer 0 of timer group 0, user can change this config in */
/* menuconfig. */
/*************************************************************************/
typedef void *light_handle_t;
#define HW_TIMER_GROUP (0) /**< Hardware timer group */
#define HW_TIMER_ID (0) /**< Hardware timer number */
#define HW_TIMER_DIVIDER (16) /**< Hardware timer clock divider */
#define HW_TIMER_SCALE (TIMER_BASE_CLK / HW_TIMER_DIVIDER) /**< Convert counter value to seconds */
#define DUTY_SET_CYCLE (20) /**< Set duty cycle */
#define DUTY_SET_GAMMA (0.6) /**< Set the Gamma value for the fade curve, default value is 0.6 */

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,13 +7,12 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "errno.h"
#include "math.h"
#include <errno.h>
#include <math.h>
#include "soc/ledc_reg.h"
#include "soc/timer_group_struct.h"
#include "soc/ledc_struct.h"
#include "driver/timer.h"
#include "driver/gptimer.h"
#include "driver/ledc.h"
#include "iot_led.h"
#include "esp_log.h"
@@ -27,6 +26,8 @@
#define GET_FIXED_INTEGER_PART(X, Q) (X >> Q)
#define GET_FIXED_DECIMAL_PART(X, Q) (X & ((0x1U << Q) - 1))
#define GPTIMER_RESOLUTION_HZ 1000000 // 1MHz, 1 tick=1us
typedef struct {
int cur;
int final;
@@ -35,16 +36,11 @@ typedef struct {
size_t num;
} ledc_fade_data_t;
typedef struct {
timer_group_t timer_group;
timer_idx_t timer_id;
} hw_timer_idx_t;
typedef struct {
ledc_fade_data_t fade_data[LEDC_CHANNEL_MAX];
ledc_mode_t speed_mode;
ledc_timer_t timer_num;
hw_timer_idx_t timer_id;
gptimer_handle_t gptimer;
} iot_light_t;
static const char *TAG = "iot_light";
@@ -52,40 +48,27 @@ static DRAM_ATTR iot_light_t *g_light_config = NULL;
static DRAM_ATTR uint16_t *g_gamma_table = NULL;
static DRAM_ATTR bool g_hw_timer_started = false;
static void iot_timer_create(hw_timer_idx_t *timer_id, bool auto_reload,
uint32_t timer_interval_ms, void *isr_handle)
static IRAM_ATTR bool fade_timercb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx);
static void iot_timer_start(gptimer_handle_t gptimer)
{
/* Select and initialize basic parameters of the timer */
timer_config_t config = {
.divider = HW_TIMER_DIVIDER,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_PAUSE,
.alarm_en = TIMER_ALARM_EN,
.intr_type = TIMER_INTR_LEVEL,
.auto_reload = auto_reload,
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = DUTY_SET_CYCLE / 1000 * GPTIMER_RESOLUTION_HZ,
.flags.auto_reload_on_alarm = true,
};
timer_init(timer_id->timer_group, timer_id->timer_id, &config);
/* Timer's counter will initially start from value below.
Also, if auto_reload is set, this value will be automatically reload on alarm */
timer_set_counter_value(timer_id->timer_group, timer_id->timer_id, 0x00000000ULL);
/* Configure the alarm value and the interrupt on alarm. */
timer_set_alarm_value(timer_id->timer_group, timer_id->timer_id, timer_interval_ms * HW_TIMER_SCALE / 1000);
timer_enable_intr(timer_id->timer_group, timer_id->timer_id);
timer_isr_register(timer_id->timer_group, timer_id->timer_id, isr_handle,
(void *) timer_id->timer_id, ESP_INTR_FLAG_IRAM, NULL);
}
static void iot_timer_start(hw_timer_idx_t *timer_id)
{
timer_start(timer_id->timer_group, timer_id->timer_id);
gptimer_event_callbacks_t cbs = {
.on_alarm = fade_timercb,
};
gptimer_register_event_callbacks(gptimer, &cbs, NULL);
gptimer_set_alarm_action(gptimer, &alarm_config);
gptimer_start(gptimer);
g_hw_timer_started = true;
}
static IRAM_ATTR void iot_timer_stop(hw_timer_idx_t *timer_id)
static IRAM_ATTR void iot_timer_stop(gptimer_handle_t gptimer)
{
timer_group_set_counter_enable_in_isr(timer_id->timer_group, timer_id->timer_id, TIMER_PAUSE);
gptimer_stop(gptimer);
g_hw_timer_started = false;
}
@@ -265,18 +248,10 @@ static IRAM_ATTR uint32_t gamma_value_to_duty(int value)
return (cur + (next - cur) * tmp_r / (0x1U << LEDC_FIXED_Q));
}
static IRAM_ATTR void fade_timercb(void *para)
static IRAM_ATTR bool fade_timercb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
int timer_idx = (int) para;
int idle_channel_num = 0;
/* Retrieve the interrupt status */
timer_group_get_intr_status_in_isr(HW_TIMER_GROUP);
timer_group_clr_intr_status_in_isr(HW_TIMER_GROUP, timer_idx);
/* After the alarm has been triggered
we need enable it again, so it is triggered the next time */
timer_group_enable_alarm_in_isr(HW_TIMER_GROUP, timer_idx);
for (int channel = 0; channel < LEDC_CHANNEL_MAX; channel++) {
ledc_fade_data_t *fade_data = g_light_config->fade_data + channel;
@@ -320,8 +295,10 @@ static IRAM_ATTR void fade_timercb(void *para)
}
if (idle_channel_num >= LEDC_CHANNEL_MAX) {
iot_timer_stop(&g_light_config->timer_id);
iot_timer_stop(timer);
}
return false;
}
esp_err_t iot_led_init(ledc_timer_t timer_num, ledc_mode_t speed_mode, uint32_t freq_hz)
@@ -352,13 +329,12 @@ esp_err_t iot_led_init(ledc_timer_t timer_num, ledc_mode_t speed_mode, uint32_t
g_light_config->timer_num = timer_num;
g_light_config->speed_mode = speed_mode;
hw_timer_idx_t hw_timer = {
.timer_group = HW_TIMER_GROUP,
.timer_id = HW_TIMER_ID,
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = GPTIMER_RESOLUTION_HZ,
};
g_light_config->timer_id = hw_timer;
iot_timer_create(&hw_timer, 1, DUTY_SET_CYCLE, fade_timercb);
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &g_light_config->gptimer));
} else {
ESP_LOGE(TAG, "g_light_config has been initialized");
}
@@ -372,12 +348,12 @@ esp_err_t iot_led_deinit(void)
free(g_gamma_table);
}
if (g_light_config) {
gptimer_del_timer(g_light_config->gptimer);
free(g_light_config);
}
timer_disable_intr(g_light_config->timer_id.timer_group, g_light_config->timer_id.timer_id);
return ESP_OK;
}
@@ -449,7 +425,7 @@ esp_err_t iot_led_set_channel(ledc_channel_t channel, uint8_t value, uint32_t fa
}
if (g_hw_timer_started != true) {
iot_timer_start(&g_light_config->timer_id);
iot_timer_start(g_light_config->gptimer);
}
return ESP_OK;
@@ -469,7 +445,7 @@ esp_err_t iot_led_start_blink(ledc_channel_t channel, uint8_t value, uint32_t pe
fade_data->step = (fade_flag) ? fade_data->cur / fade_data->num * -1 : 0;
if (g_hw_timer_started != true) {
iot_timer_start(&g_light_config->timer_id);
iot_timer_start(g_light_config->gptimer);
}
return ESP_OK;

View File

@@ -1,12 +1,12 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "math.h"
#include "sys/time.h"
#include <math.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
@@ -14,7 +14,7 @@
#include "soc/ledc_reg.h"
#include "soc/timer_group_struct.h"
#include "soc/ledc_struct.h"
#include "driver/timer.h"
#include "driver/gptimer.h"
#include "driver/ledc.h"
#include "iot_light.h"
@@ -27,6 +27,8 @@ static const char *TAG = "light";
#define POINT_ASSERT(tag, param) IOT_CHECK(tag, (param) != NULL, ESP_FAIL)
#define LIGHT_NUM_MAX 4
#define GPTIMER_RESOLUTION_HZ 1000000 // 1MHz, 1 tick=1us
typedef enum {
LIGHT_CH_NUM_1 = 1, /*!< Light channel number */
LIGHT_CH_NUM_2 = 2, /*!< Light channel number */
@@ -36,11 +38,6 @@ typedef enum {
LIGHT_CH_NUM_MAX, /*!< user shouldn't use this */
} light_channel_num_t;
typedef struct {
timer_group_t timer_group;
timer_idx_t timer_id;
} hw_timer_idx_t;
typedef struct {
gpio_num_t io_num;
ledc_mode_t mode;
@@ -62,8 +59,8 @@ typedef struct {
uint32_t full_duty;
uint32_t freq_hz;
ledc_timer_bit_t timer_bit;
hw_timer_idx_t hw_timer;
light_channel_t *channel_group[0];
gptimer_handle_t gptimer;
light_channel_t *channel_group[];
} light_t;
static bool g_fade_installed = false;
@@ -71,43 +68,6 @@ static bool g_hw_timer_started = false;
static light_t *g_light_group[LIGHT_NUM_MAX] = {NULL};
static esp_err_t iot_light_duty_set(light_handle_t light_handle, uint8_t channel_id, uint32_t duty);
static void iot_timer_create(hw_timer_idx_t *timer_id, bool auto_reload, double timer_interval_sec, timer_isr_handle_t *isr_handle)
{
/* Select and initialize basic parameters of the timer */
timer_config_t config = {
.divider = HW_TIMER_DIVIDER,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_PAUSE,
.alarm_en = TIMER_ALARM_EN,
.intr_type = TIMER_INTR_LEVEL,
.auto_reload = auto_reload,
};
timer_init(timer_id->timer_group, timer_id->timer_id, &config);
/* Timer's counter will initially start from value below.
Also, if auto_reload is set, this value will be automatically reload on alarm */
timer_set_counter_value(timer_id->timer_group, timer_id->timer_id, 0x00000000ULL);
/* Configure the alarm value and the interrupt on alarm. */
timer_set_alarm_value(timer_id->timer_group, timer_id->timer_id, timer_interval_sec * HW_TIMER_SCALE);
timer_enable_intr(timer_id->timer_group, timer_id->timer_id);
timer_isr_register(timer_id->timer_group, timer_id->timer_id, (void *)isr_handle,
(void *) timer_id->timer_id, ESP_INTR_FLAG_IRAM, NULL);
}
static void iot_timer_start(hw_timer_idx_t *timer_id)
{
timer_start(timer_id->timer_group, timer_id->timer_id);
g_hw_timer_started = true;
}
static void iot_timer_stop(hw_timer_idx_t *timer_id)
{
timer_disable_intr(timer_id->timer_group, timer_id->timer_id);
timer_pause(timer_id->timer_group, timer_id->timer_id);
g_hw_timer_started = false;
}
static IRAM_ATTR void iot_ledc_ls_channel_update(ledc_mode_t speed_mode, ledc_channel_t channel_num)
{
if (speed_mode == LEDC_LOW_SPEED_MODE) {
@@ -155,17 +115,8 @@ static IRAM_ATTR esp_err_t iot_ledc_update_duty(ledc_mode_t speed_mode, ledc_cha
return ESP_OK;
}
static IRAM_ATTR void breath_timer_callback(void *para)
static IRAM_ATTR bool breath_timer_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
int timer_idx = (int) para;
/* Retrieve the interrupt status */
timer_group_get_intr_status_in_isr(HW_TIMER_GROUP);
timer_group_clr_intr_status_in_isr(HW_TIMER_GROUP, timer_idx);
/* After the alarm has been triggered
we need enable it again, so it is triggered the next time */
timer_group_enable_alarm_in_isr(HW_TIMER_GROUP, timer_idx);
for (int i = 0; i < LIGHT_NUM_MAX; i++) {
if (g_light_group[i] != NULL) {
light_t *light = g_light_group[i];
@@ -194,6 +145,7 @@ static IRAM_ATTR void breath_timer_callback(void *para)
}
}
}
return false;
}
static light_channel_t *light_channel_create(gpio_num_t io_num, ledc_channel_t channel, ledc_mode_t mode, ledc_timer_t timer)
@@ -268,12 +220,26 @@ light_handle_t iot_light_create(ledc_timer_t timer, ledc_mode_t speed_mode, uint
light_ptr->freq_hz = freq_hz;
light_ptr->mode = speed_mode;
light_ptr->timer_bit = timer_bit;
light_ptr->hw_timer.timer_group = HW_TIMER_GROUP;
light_ptr->hw_timer.timer_id = HW_TIMER_ID;
if (g_hw_timer_started == false) {
iot_timer_create(&(light_ptr->hw_timer), 1, (double)DUTY_SET_CYCLE / 1000, (void *)breath_timer_callback);
iot_timer_start(&(light_ptr->hw_timer));
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_APB,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = GPTIMER_RESOLUTION_HZ,
};
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &light_ptr->gptimer));
gptimer_alarm_config_t alarm_config = {
.alarm_count = DUTY_SET_CYCLE / 1000 * GPTIMER_RESOLUTION_HZ,
.reload_count = 0,
.flags.auto_reload_on_alarm = true,
};
gptimer_event_callbacks_t cbs = {
.on_alarm = breath_timer_callback,
};
gptimer_register_event_callbacks(light_ptr->gptimer, &cbs, NULL);
gptimer_set_alarm_action(light_ptr->gptimer, &alarm_config);
gptimer_start(light_ptr->gptimer);
g_hw_timer_started = true;
}
for (int i = 0; i < channel_num; i++) {
@@ -317,7 +283,9 @@ esp_err_t iot_light_delete(light_handle_t light_handle)
ledc_fade_func_uninstall();
g_fade_installed = false;
iot_timer_stop(&(light->hw_timer));
g_hw_timer_started = false;
gptimer_stop(light->gptimer);
gptimer_del_timer(light->gptimer);
FREE_MEM:
free(light_handle);
return ESP_OK;