examples: replace legacy timer group with gptimer
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user