#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/pwm.h"

#define BUTTON_A_GPIO GPIO_NUM_5
#define BUTTON_B_GPIO GPIO_NUM_6
#define BUTTON_C_GPIO GPIO_NUM_7
#define LED_GPIO GPIO_NUM_16

#define PWM_CHANNEL PWM_CHANNEL_0
#define PWM_FREQ 1000
#define PWM_RES 100

static bool led_on = false;
static int led_brightness = 0;

static void button_a_handler(void *arg) {
    int level = gpio_get_level(BUTTON_A_GPIO);
    if (level == 1) {
        led_brightness++;
        if (led_brightness > PWM_RES) {
            led_brightness = PWM_RES;
        }
        pwm_set_duty(PWM_CHANNEL, led_brightness);
        pwm_start();
    }
    else {
        vTaskDelay(500 / portTICK_RATE_MS);
        while (gpio_get_level(BUTTON_A_GPIO) == 0 && led_brightness > 0) {
            led_brightness--;
            pwm_set_duty(PWM_CHANNEL, led_brightness);
            pwm_start();
            vTaskDelay(500 / portTICK_RATE_MS);
        }
    }
}

static void button_b_handler(void *arg) {
    int level = gpio_get_level(BUTTON_B_GPIO);
    if (level == 1) {
        led_brightness--;
        if (led_brightness < 0) {
            led_brightness = 0;
        }
        pwm_set_duty(PWM_CHANNEL, led_brightness);
        pwm_start();
    }
    else {
        vTaskDelay(500 / portTICK_RATE_MS);
        while (gpio_get_level(BUTTON_B_GPIO) == 0 && led_brightness < PWM_RES) {
            led_brightness++;
            pwm_set_duty(PWM_CHANNEL, led_brightness);
            pwm_start();
            vTaskDelay(500 / portTICK_RATE_MS);
        }
    }
}

static void button_c_handler(void *arg) {
    int level = gpio_get_level(BUTTON_C_GPIO);
    if (level == 1) {
        led_on = !led_on;
        if (led_on) {
            pwm_set_duty(PWM_CHANNEL, led_brightness);
            pwm_start();
        }
        else {
            pwm_stop();
        }
    }
}

void app_main() {
    // 初始化GPIO
    gpio_pad_select_gpio(BUTTON_A_GPIO);
    gpio_set_direction(BUTTON_A_GPIO, GPIO_MODE_INPUT);
    gpio_set_pull_mode(BUTTON_A_GPIO, GPIO_PULLUP_ONLY);
    gpio_install_isr_service(0);
    gpio_isr_handler_add(BUTTON_A_GPIO, button_a_handler, NULL);

    gpio_pad_select_gpio(BUTTON_B_GPIO);
    gpio_set_direction(BUTTON_B_GPIO, GPIO_MODE_INPUT);
    gpio_set_pull_mode(BUTTON_B_GPIO, GPIO_PULLUP_ONLY);
    gpio_isr_handler_add(BUTTON_B_GPIO, button_b_handler, NULL);

    gpio_pad_select_gpio(BUTTON_C_GPIO);
    gpio_set_direction(BUTTON_C_GPIO, GPIO_MODE_INPUT);
    gpio_set_pull_mode(BUTTON_C_GPIO, GPIO_PULLUP_ONLY);
    gpio_isr_handler_add(BUTTON_C_GPIO, button_c_handler, NULL);

    gpio_pad_select_gpio(LED_GPIO);
    gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);

    // 初始化PWM
    pwm_init(PWM_CHANNEL, NULL);
    pwm_set_freq(PWM_CHANNEL, PWM_FREQ);
    pwm_set_resolution(PWM_CHANNEL, PWM_RES);

    while (1) {
        vTaskDelay(
portMAX_DELAY);
}
}

//该程序使用了3个GPIO输入引脚和1个GPIO输出引脚,以及1个PWM通道。
//
//程序中定义了三个按钮的GPIO引脚,以及一个LED的GPIO引脚和PWM通道。然后在`app_main`函数中初始化GPIO和PWM,并创建三个GPIO中断处理函数分别处理三个按钮的按下和长按操作。
//
//对于按钮A和B,按下按钮时会逐步增加或减小LED的亮度,而长按按钮时,每500毫秒亮度会逐步减小或增加。对于按钮C,按下时切换LED的开和关。
//
//最后,在`app_main`函数中通过一个死循环让程序一直运行。
//
//请注意,本程序的实现可能与您的ESP32板的具体规格有关,需要根据您的板的规格进行调整。