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