diff --git a/components/esp8266/CMakeLists.txt b/components/esp8266/CMakeLists.txt index 887f9b6e6..32bef0a54 100644 --- a/components/esp8266/CMakeLists.txt +++ b/components/esp8266/CMakeLists.txt @@ -46,6 +46,7 @@ else() "driver/i2c.c" "driver/i2s.c" "driver/pwm.c" + "driver/sigma_delta.c" "driver/spi.c" "driver/hspi_logic_layer.c" "driver/uart.c" diff --git a/components/esp8266/driver/sigma_delta.c b/components/esp8266/driver/sigma_delta.c new file mode 100644 index 000000000..d0ba4bded --- /dev/null +++ b/components/esp8266/driver/sigma_delta.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023 <qb4.dev@gmail.com> + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include <esp_err.h> +#include <esp_log.h> + +#include <esp8266/eagle_soc.h> +#include <esp8266/pin_mux_register.h> +#include <esp8266/gpio_register.h> +#include <esp8266/gpio_struct.h> + +#include <driver/gpio.h> +#include "driver/sigma_delta.h" + +static const char *TAG = "sigma-delta"; + +#define SIGMA_DELTA_CHECK(a, str, ret_val) \ + if (!(a)) { \ + ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } + +#define GPIO_SIGMA_DELTA_TARGET_MASK (SIGMA_DELTA_TARGET << SIGMA_DELTA_TARGET_S) +#define GPIO_SIGMA_DELTA_TARGET_GET(x) (((x) & GPIO_SIGMA_DELTA_TARGET_MASK) >> SIGMA_DELTA_TARGET_S) +#define GPIO_SIGMA_DELTA_TARGET_SET(x) (((x) << SIGMA_DELTA_TARGET_S) & GPIO_SIGMA_DELTA_TARGET_MASK) + +#define GPIO_SIGMA_DELTA_PRESCALE_MASK (SIGMA_DELTA_PRESCALAR << SIGMA_DELTA_PRESCALAR_S) +#define GPIO_SIGMA_DELTA_PRESCALE_GET(x) (((x) & GPIO_SIGMA_DELTA_PRESCALE_MASK) >> SIGMA_DELTA_PRESCALAR_S) +#define GPIO_SIGMA_DELTA_PRESCALE_SET(x) (((x) << SIGMA_DELTA_PRESCALAR_S) & GPIO_SIGMA_DELTA_PRESCALE_MASK) + +#define GPIO_AS_PIN_SOURCE 0 +#define SIGMA_AS_PIN_SOURCE 1 + +esp_err_t sigma_delta_init(uint8_t prescaler,uint8_t target) +{ + GPIO.sigma_delta = SIGMA_DELTA_ENABLE | + GPIO_SIGMA_DELTA_TARGET_SET(target) | + GPIO_SIGMA_DELTA_PRESCALE_SET(prescaler); + + ESP_LOGI(TAG,"enabled with prescale=%d and target=%d", prescaler, target); + return ESP_OK; +} + +esp_err_t sigma_delta_set_prescale(uint8_t prescale) +{ + GPIO.sigma_delta = (GPIO.sigma_delta & (~GPIO_SIGMA_DELTA_PRESCALE_MASK)) | + GPIO_SIGMA_DELTA_PRESCALE_SET(prescale); + return ESP_OK; +} + +esp_err_t sigma_delta_get_prescale(uint8_t *prescale) +{ + SIGMA_DELTA_CHECK(prescale, "prescale is null", ESP_ERR_INVALID_ARG); + *prescale = GPIO_SIGMA_DELTA_PRESCALE_GET(GPIO.sigma_delta); + return ESP_OK; +} + +esp_err_t sigma_delta_set_target(uint8_t target) +{ + GPIO.sigma_delta = (GPIO.sigma_delta & (~GPIO_SIGMA_DELTA_TARGET_MASK)) | + GPIO_SIGMA_DELTA_TARGET_SET(target); + return ESP_OK; +} + +esp_err_t sigma_delta_get_target(uint8_t *target) +{ + SIGMA_DELTA_CHECK(target, "target is null", ESP_ERR_INVALID_ARG); + *target = GPIO_SIGMA_DELTA_TARGET_GET(GPIO.sigma_delta); + return ESP_OK; +} + +esp_err_t sigma_delta_deinit(void) +{ + GPIO.sigma_delta = 0x00; + + ESP_LOGI(TAG,"disabled"); + return ESP_OK; +} + +esp_err_t sigma_delta_set_output(gpio_num_t gpio_num) +{ + GPIO.pin[gpio_num].source = SIGMA_AS_PIN_SOURCE; + return ESP_OK; +} + +esp_err_t sigma_delta_clear_output(gpio_num_t gpio_num) +{ + GPIO.pin[gpio_num].source = GPIO_AS_PIN_SOURCE; + return ESP_OK; +} diff --git a/components/esp8266/include/driver/sigma_delta.h b/components/esp8266/include/driver/sigma_delta.h new file mode 100644 index 000000000..e52b857ed --- /dev/null +++ b/components/esp8266/include/driver/sigma_delta.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2023 <qb4.dev@gmail.com> + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Setup sigma-delta signal generator + * The target frequency is defined as: + * - for 0<target<128 freq = 80,000,000/prescaler * target /256 Hz + * - for 128<target<256 freq = 80,000,000/prescaler * (256-target) /256 + * + * @note The target and prescaler will both affect the freq. + * CPU_FREQ has no influence on the sigma-delta frequency. + * + * @param[in] prescaler clock divider, range 0-255 + * @param[in] target duty cycle,range 0-255 + * @return + * - ESP_OK Success + */ +esp_err_t sigma_delta_init(uint8_t prescale,uint8_t target); + +/** + * @brief Set sigma-delta signal generator prescale + * + * @param[in] prescale clock divider, range 0-255 + * @return + * - ESP_OK Success + */ +esp_err_t sigma_delta_set_prescale(uint8_t prescale); + +/** + * @brief Get sigma-delta signal generator prescale + * + * @param[out] prescale clock divider + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG when prescale is NULL + */ +esp_err_t sigma_delta_get_prescale(uint8_t *prescale); + +/** + * @brief Set sigma-delta signal generator target + * + * @param[in] target duty cycle,range 0-255 + * @return + * - ESP_OK Success + */ +esp_err_t sigma_delta_set_target(uint8_t target); + +/** + * @brief Get sigma-delta signal generator target + * + * @param[out] target duty cycle + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG when target is NULL + */ +esp_err_t sigma_delta_get_target(uint8_t *target); + +/** + * @brief Disable sigma-delta signal generator + * + * @return + * - ESP_OK Success + */ +esp_err_t sigma_delta_deinit(void); + +/** + * @brief Set sigma-delta signal generator output + * on selected GPIO + * + * @note GPIO should already been configured as output + * + * @param[in] gpio_num selected gpio pin + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO number error + */ +esp_err_t sigma_delta_set_output(gpio_num_t gpio_num); + +/** + * @brief Clear sigma-delta signal generator output + * on selected GPIO + * + * @param[in] gpio_num selected gpio pin + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO number error + */ +esp_err_t sigma_delta_clear_output(gpio_num_t gpio_num); + +#ifdef __cplusplus +} +#endif