Merge branch 'feature/gpio_sigma_delta_ng' into 'master'

 SDM Driver-NG (Sigma-Delta channel allocator)

Closes IDF-5261 and IDF-2877

See merge request espressif/esp-idf!18626
This commit is contained in:
morris 2022-07-20 21:30:12 +08:00
commit 8944479bcd
122 changed files with 1887 additions and 1352 deletions

View File

@ -28,6 +28,10 @@ components/driver/test_apps/rmt:
disable:
- if: SOC_RMT_SUPPORTED != 1
components/driver/test_apps/sdm:
disable:
- if: SOC_SDM_SUPPORTED != 1
components/driver/test_apps/temperature_sensor:
disable:
- if: SOC_TEMP_SENSOR_SUPPORTED != 1

View File

@ -39,8 +39,8 @@ if(CONFIG_SOC_DEDICATED_GPIO_SUPPORTED)
list(APPEND srcs "gpio/dedic_gpio.c")
endif()
if(CONFIG_SOC_SIGMADELTA_SUPPORTED)
list(APPEND srcs "gpio/sigmadelta_gpio.c")
if(CONFIG_SOC_SDM_SUPPORTED)
list(APPEND srcs "sdm.c" "deprecated/sigma_delta_legacy.c")
endif()
if(CONFIG_SOC_RMT_SUPPORTED)

View File

@ -224,6 +224,32 @@ menu "Driver Configurations"
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
endmenu # GPIO Configuration
menu "Sigma Delta Modulator Configuration"
depends on SOC_SDM_SUPPORTED
config SDM_CTRL_FUNC_IN_IRAM
bool "Place SDM control functions into IRAM"
default n
help
Place SDM control functions (like set_duty) into IRAM,
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
Enabling this option can improve driver performance as well.
config SDM_SUPPRESS_DEPRECATE_WARN
bool "Suppress legacy driver deprecated warning"
default n
help
Wether to suppress the deprecation warnings when using legacy sigma delta driver.
If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
you can enable this option.
config SDM_ENABLE_DEBUG_LOG
bool "Enable debug log"
default n
help
Wether to enable the debug log message for SDM driver.
Note that, this option only controls the SDM driver log, won't affect other drivers.
endmenu # Sigma Delta Modulator Configuration
menu "GPTimer Configuration"
config GPTIMER_CTRL_FUNC_IN_IRAM
bool "Place GPTimer control functions into IRAM"

View File

@ -21,7 +21,6 @@ extern "C" {
/**
* @brief Define memory space of each RMT channel (in words = 4 bytes)
*
*/
#define RMT_MEM_ITEM_NUM SOC_RMT_MEM_WORDS_PER_CHANNEL
@ -40,6 +39,8 @@ typedef struct {
};
} rmt_item32_t;
#if SOC_RMT_SUPPORTED
/**
* @brief RMT hardware memory layout
*/
@ -48,11 +49,11 @@ typedef struct {
volatile rmt_item32_t data32[SOC_RMT_MEM_WORDS_PER_CHANNEL];
} chan[SOC_RMT_CHANNELS_PER_GROUP];
} rmt_mem_t;
#endif // SOC_RMT_SUPPORTED
/**
* @brief RMT channel ID
*
*/
* @brief RMT channel ID
*/
typedef enum {
RMT_CHANNEL_0, /*!< RMT channel number 0 */
RMT_CHANNEL_1, /*!< RMT channel number 1 */
@ -69,7 +70,6 @@ typedef enum {
/**
* @brief RMT Internal Memory Owner
*
*/
typedef enum {
RMT_MEM_OWNER_TX, /*!< RMT RX mode, RMT transmitter owns the memory block*/
@ -79,15 +79,17 @@ typedef enum {
/**
* @brief Clock Source of RMT Channel
*
*/
#if SOC_RMT_SUPPORTED
typedef soc_periph_rmt_clk_src_legacy_t rmt_source_clk_t;
#else
typedef int rmt_source_clk_t;
#endif // SOC_RMT_SUPPORTED
/**
* @brief RMT Data Mode
*
* @note We highly recommended to use MEM mode not FIFO mode since there will be some gotcha in FIFO mode.
*
*/
typedef enum {
RMT_DATA_MODE_FIFO, /*<! RMT memory access in FIFO mode */
@ -97,7 +99,6 @@ typedef enum {
/**
* @brief RMT Channel Working Mode (TX or RX)
*
*/
typedef enum {
RMT_MODE_TX, /*!< RMT TX mode */
@ -117,7 +118,6 @@ typedef enum {
/**
* @brief RMT Carrier Level
*
*/
typedef enum {
RMT_CARRIER_LEVEL_LOW, /*!< RMT carrier wave is modulated for low Level output */
@ -127,7 +127,6 @@ typedef enum {
/**
* @brief RMT Channel Status
*
*/
typedef enum {
RMT_CHANNEL_UNINIT, /*!< RMT channel uninitialized */
@ -136,15 +135,15 @@ typedef enum {
} rmt_channel_status_t;
/**
* @brief Data struct of RMT channel status
*/
* @brief Data struct of RMT channel status
*/
typedef struct {
rmt_channel_status_t status[RMT_CHANNEL_MAX]; /*!< Store the current status of each channel */
} rmt_channel_status_result_t;
/**
* @brief Data struct of RMT TX configure parameters
*/
* @brief Data struct of RMT TX configure parameters
*/
typedef struct {
uint32_t carrier_freq_hz; /*!< RMT carrier frequency */
rmt_carrier_level_t carrier_level; /*!< Level of the RMT output, when the carrier is applied */
@ -159,8 +158,8 @@ typedef struct {
} rmt_tx_config_t;
/**
* @brief Data struct of RMT RX configure parameters
*/
* @brief Data struct of RMT RX configure parameters
*/
typedef struct {
uint16_t idle_threshold; /*!< RMT RX idle threshold */
uint8_t filter_ticks_thresh; /*!< RMT filter tick number */
@ -174,8 +173,8 @@ typedef struct {
} rmt_rx_config_t;
/**
* @brief Data struct of RMT configure parameters
*/
* @brief Data struct of RMT configure parameters
*/
typedef struct {
rmt_mode_t rmt_mode; /*!< RMT mode: transmitter or receiver */
rmt_channel_t channel; /*!< RMT channel */
@ -232,45 +231,43 @@ typedef struct {
}
/**
* @brief RMT interrupt handle
*
*/
* @brief RMT interrupt handle
*/
typedef intr_handle_t rmt_isr_handle_t;
/**
* @brief Type of RMT Tx End callback function
*
*/
* @brief Type of RMT Tx End callback function
*/
typedef void (*rmt_tx_end_fn_t)(rmt_channel_t channel, void *arg);
/**
* @brief Structure encapsulating a RMT TX end callback
*/
* @brief Structure encapsulating a RMT TX end callback
*/
typedef struct {
rmt_tx_end_fn_t function; /*!< Function which is called on RMT TX end */
void *arg; /*!< Optional argument passed to function */
} rmt_tx_end_callback_t;
/**
* @brief User callback function to convert uint8_t type data to rmt format(rmt_item32_t).
*
* This function may be called from an ISR, so, the code should be short and efficient.
*
* @param src Pointer to the buffer storing the raw data that needs to be converted to rmt format.
* @param[out] dest Pointer to the buffer storing the rmt format data.
* @param src_size The raw data size.
* @param wanted_num The number of rmt format data that wanted to get.
* @param[out] translated_size The size of the raw data that has been converted to rmt format,
* it should return 0 if no data is converted in user callback.
* @param[out] item_num The number of the rmt format data that actually converted to,
* it can be less than wanted_num if there is not enough raw data, but cannot exceed wanted_num.
* it should return 0 if no data was converted.
*
* @note
* In fact, item_num should be a multiple of translated_size, e.g. :
* When we convert each byte of uint8_t type data to rmt format data,
* the relation between item_num and translated_size should be `item_num = translated_size*8`.
*/
* @brief User callback function to convert uint8_t type data to rmt format(rmt_item32_t).
*
* This function may be called from an ISR, so, the code should be short and efficient.
*
* @param src Pointer to the buffer storing the raw data that needs to be converted to rmt format.
* @param[out] dest Pointer to the buffer storing the rmt format data.
* @param src_size The raw data size.
* @param wanted_num The number of rmt format data that wanted to get.
* @param[out] translated_size The size of the raw data that has been converted to rmt format,
* it should return 0 if no data is converted in user callback.
* @param[out] item_num The number of the rmt format data that actually converted to,
* it can be less than wanted_num if there is not enough raw data, but cannot exceed wanted_num.
* it should return 0 if no data was converted.
*
* @note
* In fact, item_num should be a multiple of translated_size, e.g. :
* When we convert each byte of uint8_t type data to rmt format data,
* the relation between item_num and translated_size should be `item_num = translated_size*8`.
*/
typedef void (*sample_to_rmt_t)(const void *src, rmt_item32_t *dest, size_t src_size, size_t wanted_num, size_t *translated_size, size_t *item_num);
#ifdef __cplusplus

View File

@ -9,22 +9,16 @@
#include <stdint.h>
#include "esp_err.h"
#include "driver/gpio.h"
#include "hal/sigmadelta_types.h"
#include "driver/sigmadelta_types_legacy.h"
#if !CONFIG_SDM_SUPPRESS_DEPRECATE_WARN
#warning "The legacy sigma-delta driver is deprecated, please use driver/sdm.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Sigma-delta configure struct
*/
typedef struct {
sigmadelta_channel_t channel; /*!< Sigma-delta channel number */
int8_t sigmadelta_duty; /*!< Sigma-delta duty, duty ranges from -128 to 127. */
uint8_t sigmadelta_prescale; /*!< Sigma-delta prescale, prescale ranges from 0 to 255. */
gpio_num_t sigmadelta_gpio; /*!< Sigma-delta output io number, refer to gpio.h for more details. */
} sigmadelta_config_t;
/**
* @brief Configure Sigma-delta channel
*

View File

@ -6,7 +6,9 @@
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#include "driver/gpio.h" // for gpio_num_t type define
#ifdef __cplusplus
extern "C" {
@ -20,8 +22,6 @@ typedef enum {
SIGMADELTA_PORT_MAX, /*!< SIGMADELTA port max */
} sigmadelta_port_t;
_Static_assert(SIGMADELTA_PORT_MAX == SOC_SIGMADELTA_NUM, "Sigma-delta port num incorrect.");
/**
* @brief Sigma-delta channel list
*/
@ -30,7 +30,7 @@ typedef enum {
SIGMADELTA_CHANNEL_1, /*!< Sigma-delta channel 1 */
SIGMADELTA_CHANNEL_2, /*!< Sigma-delta channel 2 */
SIGMADELTA_CHANNEL_3, /*!< Sigma-delta channel 3 */
#if SOC_SIGMADELTA_CHANNEL_NUM > 4
#if SOC_SDM_CHANNELS_PER_GROUP > 4
SIGMADELTA_CHANNEL_4, /*!< Sigma-delta channel 4 */
SIGMADELTA_CHANNEL_5, /*!< Sigma-delta channel 5 */
SIGMADELTA_CHANNEL_6, /*!< Sigma-delta channel 6 */
@ -39,6 +39,16 @@ typedef enum {
SIGMADELTA_CHANNEL_MAX, /*!< Sigma-delta channel max */
} sigmadelta_channel_t;
/**
* @brief Sigma-delta configure struct
*/
typedef struct {
sigmadelta_channel_t channel; /*!< Sigma-delta channel number */
int8_t sigmadelta_duty; /*!< Sigma-delta duty, duty ranges from -128 to 127. */
uint8_t sigmadelta_prescale; /*!< Sigma-delta prescale, prescale ranges from 0 to 255. */
gpio_num_t sigmadelta_gpio; /*!< Sigma-delta output io number, refer to gpio.h for more details. */
} sigmadelta_config_t;
#ifdef __cplusplus
}
#endif

View File

@ -7,18 +7,21 @@
#include "esp_log.h"
#include "esp_check.h"
#include "esp_err.h"
#include "driver/sigmadelta.h"
#include "esp_heap_caps.h"
#include "hal/sigmadelta_hal.h"
#include "driver/gpio.h"
#include "driver/sigmadelta_types_legacy.h"
#include "soc/sdm_periph.h"
#include "hal/sdm_hal.h"
#include "hal/sdm_ll.h"
#include "hal/gpio_hal.h"
#include "esp_rom_gpio.h"
static const char *TAG = "sigma-delta";
static const char *TAG = "sdm(legacy)";
#define SIGMADELTA_CHECK(a,str,ret_val) ESP_RETURN_ON_FALSE(a, ret_val, TAG, "%s", str)
typedef struct {
sigmadelta_hal_context_t hal; /*!< SIGMADELTA hal context*/
sdm_hal_context_t hal; /*!< SIGMADELTA hal context*/
} sigmadelta_obj_t;
static sigmadelta_obj_t *p_sigmadelta_obj[SIGMADELTA_PORT_MAX] = {0};
@ -32,7 +35,7 @@ static inline esp_err_t _sigmadelta_set_duty(sigmadelta_port_t sigmadelta_port,
{
SIGMADELTA_OBJ_CHECK(sigmadelta_port);
sigmadelta_hal_set_duty(&(p_sigmadelta_obj[sigmadelta_port]->hal), channel, duty);
sdm_ll_set_duty(p_sigmadelta_obj[sigmadelta_port]->hal.dev, channel, duty);
return ESP_OK;
}
@ -40,7 +43,7 @@ static inline esp_err_t _sigmadelta_set_prescale(sigmadelta_port_t sigmadelta_po
{
SIGMADELTA_OBJ_CHECK(sigmadelta_port);
sigmadelta_hal_set_prescale(&(p_sigmadelta_obj[sigmadelta_port]->hal), channel, prescale);
sdm_ll_set_prescale(p_sigmadelta_obj[sigmadelta_port]->hal.dev, channel, prescale + 1);
return ESP_OK;
}
@ -85,7 +88,8 @@ esp_err_t sigmadelta_init(sigmadelta_port_t sigmadelta_port)
return ESP_FAIL;
}
sigmadelta_hal_init(&(p_sigmadelta_obj[sigmadelta_port]->hal), sigmadelta_port);
sdm_hal_init(&(p_sigmadelta_obj[sigmadelta_port]->hal), sigmadelta_port);
sdm_ll_enable_clock(p_sigmadelta_obj[sigmadelta_port]->hal.dev, true);
return ESP_OK;
}

View File

@ -41,7 +41,7 @@ typedef bool (*gptimer_alarm_cb_t) (gptimer_handle_t timer, const gptimer_alarm_
/**
* @brief Group of supported GPTimer callbacks
* @note The callbacks are all running under ISR environment
* @note When CONFIG_GPTIMER_ISR_IRAM_SAFE is enabled, the callback itself and functions callbed by it should be placed in IRAM.
* @note When CONFIG_GPTIMER_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
*/
typedef struct {
gptimer_alarm_cb_t on_alarm; /*!< Timer alarm callback */

View File

@ -44,7 +44,7 @@ typedef struct {
* @param[in] user_ctx User data, passed from `pcnt_unit_register_event_callbacks()`
* @return Whether a high priority task has been woken up by this function
*/
typedef bool (*pcnt_watch_cb_t)(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *edata, void *user_ctx);
typedef bool (*pcnt_watch_cb_t)(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx);
/**
* @brief Group of supported PCNT callbacks

View File

@ -0,0 +1,111 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "hal/sdm_types.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of Sigma Delta channel handle
*/
typedef struct sdm_channel_t *sdm_channel_handle_t;
/**
* @brief Sigma Delta channel configuration
*/
typedef struct {
int gpio_num; /*!< GPIO number */
sdm_clock_source_t clk_src; /*!< Clock source */
uint32_t sample_rate_hz; /*!< Sample rate in Hz, it determines how frequent the modulator outputs a pulse */
struct {
uint32_t invert_out: 1; /*!< Whether to invert the output signal */
uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */
} flags; /*!< Extra flags */
} sdm_config_t;
/**
* @brief Create a new Sigma Delta channel
*
* @param[in] config SDM configuration
* @param[out] ret_chan Returned SDM channel handle
* @return
* - ESP_OK: Create SDM channel successfully
* - ESP_ERR_INVALID_ARG: Create SDM channel failed because of invalid argument
* - ESP_ERR_NO_MEM: Create SDM channel failed because out of memory
* - ESP_ERR_NOT_FOUND: Create SDM channel failed because all channels are used up and no more free one
* - ESP_FAIL: Create SDM channel failed because of other error
*/
esp_err_t sdm_new_channel(const sdm_config_t *config, sdm_channel_handle_t *ret_chan);
/**
* @brief Delete the Sigma Delta channel
*
* @param[in] chan SDM channel created by `sdm_new_channel`
* @return
* - ESP_OK: Delete the SDM channel successfully
* - ESP_ERR_INVALID_ARG: Delete the SDM channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Delete the SDM channel failed because the channel is not in init state
* - ESP_FAIL: Delete the SDM channel failed because of other error
*/
esp_err_t sdm_del_channel(sdm_channel_handle_t chan);
/**
* @brief Enable the Sigma Delta channel
*
* @note This function will transit the channel state from init to enable.
* @note This function will acquire a PM lock, if a specific source clock (e.g. APB) is selected in the `sdm_config_t`, while `CONFIG_PM_ENABLE` is enabled.
*
* @param[in] chan SDM channel created by `sdm_new_channel`
* @return
* - ESP_OK: Enable SDM channel successfully
* - ESP_ERR_INVALID_ARG: Enable SDM channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Enable SDM channel failed because the channel is already enabled
* - ESP_FAIL: Enable SDM channel failed because of other error
*/
esp_err_t sdm_channel_enable(sdm_channel_handle_t chan);
/**
* @brief Disable the Sigma Delta channel
*
* @note This function will do the opposite work to the `sdm_channel_enable()`
*
* @param[in] chan SDM channel created by `sdm_new_channel`
* @return
* - ESP_OK: Disable SDM channel successfully
* - ESP_ERR_INVALID_ARG: Disable SDM channel failed because of invalid argument
* - ESP_ERR_INVALID_STATE: Disable SDM channel failed because the channel is not enabled yet
* - ESP_FAIL: Disable SDM channel failed because of other error
*/
esp_err_t sdm_channel_disable(sdm_channel_handle_t chan);
/**
* @brief Set the duty cycle of the PDM output signal.
*
* @note For PDM signals, duty cycle refers to the percentage of high level cycles to the whole statistical period.
* The average output voltage could be Vout = VDD_IO / 256 * duty + VDD_IO / 2
* @note If the duty is set to zero, the output signal is like a 50% duty cycle square wave, with a frequency around (sample_rate_hz / 4).
* @note The duty is proportional to the equivalent output voltage after a low-pass-filter.
* @note This function is allowed to run within ISR context
* @note This function will be placed into IRAM if `CONFIG_SDM_CTRL_FUNC_IN_IRAM` is on, so that it's allowed to be executed when Cache is disabled
*
* @param[in] chan SDM channel created by `sdm_new_channel`
* @param[in] duty Equivalent duty cycle of the PDM output signal, ranges from -128 to 127. But the range of [-90, 90] can provide a better randomness.
* @return
* - ESP_OK: Set duty cycle successfully
* - ESP_ERR_INVALID_ARG: Set duty cycle failed because of invalid argument
* - ESP_FAIL: Set duty cycle failed because of other error
*/
esp_err_t sdm_channel_set_duty(sdm_channel_handle_t chan, int8_t duty);
#ifdef __cplusplus
}
#endif

View File

@ -15,3 +15,5 @@ entries:
if GPIO_CTRL_FUNC_IN_IRAM = y:
gpio: gpio_set_level (noflash)
gpio: gpio_intr_disable (noflash)
if SDM_CTRL_FUNC_IN_IRAM = y:
sdm: sdm_channel_set_duty (noflash)

View File

@ -49,7 +49,7 @@ rmt_group_t *rmt_acquire_group_handle(int group_id)
// initial occupy_mask: 1111...100...0
group->occupy_mask = UINT32_MAX & ~((1 << SOC_RMT_CHANNELS_PER_GROUP) - 1);
// group clock won't be configured at this stage, it will be set when allocate the first channel
group->clk_src = RMT_CLK_SRC_NONE;
group->clk_src = 0;
// enable APB access RMT registers
periph_module_enable(rmt_periph_signals.groups[group_id].module);
periph_module_reset(rmt_periph_signals.groups[group_id].module);
@ -102,7 +102,7 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t
bool clock_selection_conflict = false;
// check if we need to update the group clock source, group clock source is shared by all channels
portENTER_CRITICAL(&group->spinlock);
if (group->clk_src == RMT_CLK_SRC_NONE) {
if (group->clk_src == 0) {
group->clk_src = clk_src;
} else {
clock_selection_conflict = (group->clk_src != clk_src);

311
components/driver/sdm.c Normal file
View File

@ -0,0 +1,311 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <sys/lock.h>
#include "sdkconfig.h"
#if CONFIG_SDM_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "freertos/FreeRTOS.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_pm.h"
#include "driver/gpio.h"
#include "driver/sdm.h"
#include "hal/gpio_hal.h"
#include "hal/sdm_hal.h"
#include "hal/sdm_ll.h"
#include "soc/sdm_periph.h"
#include "esp_private/esp_clk.h"
#if CONFIG_SDM_CTRL_FUNC_IN_IRAM
#define SDM_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define SDM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif
#define SDM_PM_LOCK_NAME_LEN_MAX 16
static const char *TAG = "sdm";
typedef struct sdm_platform_t sdm_platform_t;
typedef struct sdm_group_t sdm_group_t;
typedef struct sdm_channel_t sdm_channel_t;
struct sdm_platform_t {
_lock_t mutex; // platform level mutex lock
sdm_group_t *groups[SOC_SDM_GROUPS]; // sdm group pool
int group_ref_counts[SOC_SDM_GROUPS]; // reference count used to protect group install/uninstall
};
struct sdm_group_t {
int group_id; // Group ID, index from 0
portMUX_TYPE spinlock; // to protect per-group register level concurrent access
sdm_hal_context_t hal; // hal context
sdm_channel_t *channels[SOC_SDM_CHANNELS_PER_GROUP]; // array of sdm channels
sdm_clock_source_t clk_src; // Clock source
};
typedef enum {
SDM_FSM_INIT,
SDM_FSM_ENABLE,
} sdm_fsm_t;
struct sdm_channel_t {
sdm_group_t *group; // which group the sdm channel belongs to
uint32_t chan_id; // allocated channel numerical ID
int gpio_num; // GPIO number
uint32_t sample_rate_hz; // Sample rate, in Hz
portMUX_TYPE spinlock; // to protect per-channels resources concurrently accessed by task and ISR handler
esp_pm_lock_handle_t pm_lock; // PM lock, for glitch filter, as that module can only be functional under APB
sdm_fsm_t fsm; // FSM state
#if CONFIG_PM_ENABLE
char pm_lock_name[SDM_PM_LOCK_NAME_LEN_MAX]; // pm lock name
#endif
};
// sdm driver platform, it's always a singleton
static sdm_platform_t s_platform;
static sdm_group_t *sdm_acquire_group_handle(int group_id)
{
bool new_group = false;
sdm_group_t *group = NULL;
// prevent install sdm group concurrently
_lock_acquire(&s_platform.mutex);
if (!s_platform.groups[group_id]) {
group = heap_caps_calloc(1, sizeof(sdm_group_t), SDM_MEM_ALLOC_CAPS);
if (group) {
new_group = true;
s_platform.groups[group_id] = group; // register to platform
// initialize sdm group members
group->group_id = group_id;
group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
group->clk_src = 0;
// initialize HAL context
sdm_hal_init(&group->hal, group_id);
// enable clock
// note that, this will enables all the channels' output, and channel can't be disable/enable separately
sdm_ll_enable_clock(group->hal.dev, true);
}
} else {
group = s_platform.groups[group_id];
}
if (group) {
// someone acquired the group handle means we have a new object that refer to this group
s_platform.group_ref_counts[group_id]++;
}
_lock_release(&s_platform.mutex);
if (new_group) {
ESP_LOGD(TAG, "new group (%d) at %p", group_id, group);
}
return group;
}
static void sdm_release_group_handle(sdm_group_t *group)
{
int group_id = group->group_id;
bool do_deinitialize = false;
_lock_acquire(&s_platform.mutex);
s_platform.group_ref_counts[group_id]--;
if (s_platform.group_ref_counts[group_id] == 0) {
assert(s_platform.groups[group_id]);
do_deinitialize = true;
s_platform.groups[group_id] = NULL; // deregister from platform
sdm_ll_enable_clock(group->hal.dev, false);
}
_lock_release(&s_platform.mutex);
if (do_deinitialize) {
free(group);
ESP_LOGD(TAG, "del group (%d)", group_id);
}
}
static esp_err_t sdm_register_to_group(sdm_channel_t *chan)
{
sdm_group_t *group = NULL;
int chan_id = -1;
for (int i = 0; i < SOC_SDM_GROUPS; i++) {
group = sdm_acquire_group_handle(i);
ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no mem for group (%d)", i);
// loop to search free unit in the group
portENTER_CRITICAL(&group->spinlock);
for (int j = 0; j < SOC_SDM_CHANNELS_PER_GROUP; j++) {
if (!group->channels[j]) {
chan_id = j;
group->channels[j] = chan;
break;
}
}
portEXIT_CRITICAL(&group->spinlock);
if (chan_id < 0) {
sdm_release_group_handle(group);
group = NULL;
} else {
chan->group = group;
chan->chan_id = chan_id;
break;
}
}
ESP_RETURN_ON_FALSE(chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free channels");
return ESP_OK;
}
static void sdm_unregister_from_group(sdm_channel_t *chan)
{
sdm_group_t *group = chan->group;
int chan_id = chan->chan_id;
portENTER_CRITICAL(&group->spinlock);
group->channels[chan_id] = NULL;
portEXIT_CRITICAL(&group->spinlock);
// channel has a reference on group, release it now
sdm_release_group_handle(group);
}
static esp_err_t sdm_destory(sdm_channel_t *chan)
{
if (chan->pm_lock) {
ESP_RETURN_ON_ERROR(esp_pm_lock_delete(chan->pm_lock), TAG, "delete pm lock failed");
}
if (chan->group) {
sdm_unregister_from_group(chan);
}
free(chan);
return ESP_OK;
}
esp_err_t sdm_new_channel(const sdm_config_t *config, sdm_channel_handle_t *ret_chan)
{
#if CONFIG_SDM_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK;
sdm_channel_t *chan = NULL;
ESP_GOTO_ON_FALSE(config && ret_chan, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
ESP_GOTO_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(config->gpio_num), ESP_ERR_INVALID_ARG, err, TAG, "invalid GPIO number");
chan = heap_caps_calloc(1, sizeof(sdm_channel_t), SDM_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(chan, ESP_ERR_NO_MEM, err, TAG, "no mem for channel");
// register channel to the group
ESP_GOTO_ON_ERROR(sdm_register_to_group(chan), err, TAG, "register to group failed");
sdm_group_t *group = chan->group;
int group_id = group->group_id;
int chan_id = chan->chan_id;
ESP_GOTO_ON_FALSE(group->clk_src == 0 || group->clk_src == config->clk_src, ESP_ERR_INVALID_ARG, err, TAG, "clock source conflict");
uint32_t src_clk_hz = 0;
switch (config->clk_src) {
case SDM_CLK_SRC_APB:
src_clk_hz = esp_clk_apb_freq();
#if CONFIG_PM_ENABLE
sprintf(chan->pm_lock_name, "sdm_%d_%d", group->group_id, chan_id); // e.g. sdm_0_0
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, chan->pm_lock_name, &chan->pm_lock);
ESP_RETURN_ON_ERROR(ret, TAG, "create APB_FREQ_MAX lock failed");
#endif
break;
default:
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "clock source %d is not support", config->clk_src);
break;
}
group->clk_src = config->clk_src;
// GPIO configuration
gpio_config_t gpio_conf = {
.intr_type = GPIO_INTR_DISABLE,
// also enable the input path is `io_loop_back` is on, this is useful for debug
.mode = GPIO_MODE_OUTPUT | (config->flags.io_loop_back ? GPIO_MODE_INPUT : 0),
.pull_down_en = false,
.pull_up_en = true,
.pin_bit_mask = 1ULL << config->gpio_num,
};
ESP_GOTO_ON_ERROR(gpio_config(&gpio_conf), err, TAG, "config GPIO failed");
esp_rom_gpio_connect_out_signal(config->gpio_num, sigma_delta_periph_signals.channels[chan_id].sd_sig, config->flags.invert_out, false);
chan->gpio_num = config->gpio_num;
// set prescale based on sample rate
uint32_t prescale = src_clk_hz / config->sample_rate_hz;
sdm_ll_set_prescale(group->hal.dev, chan_id, prescale);
chan->sample_rate_hz = src_clk_hz / prescale;
// preset the duty cycle to zero
sdm_ll_set_duty(group->hal.dev, chan_id, 0);
// initialize other members of timer
chan->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
chan->fsm = SDM_FSM_INIT; // put the channel into init state
ESP_LOGD(TAG, "new sdm channel (%d,%d) at %p, gpio=%d, sample rate=%uHz", group_id, chan_id, chan, chan->gpio_num, chan->sample_rate_hz);
*ret_chan = chan;
return ESP_OK;
err:
if (chan) {
sdm_destory(chan);
}
return ret;
}
esp_err_t sdm_del_channel(sdm_channel_handle_t chan)
{
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(chan->fsm == SDM_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel not in init state");
sdm_group_t *group = chan->group;
int group_id = group->group_id;
int chan_id = chan->chan_id;
ESP_LOGD(TAG, "del channel (%d,%d)", group_id, chan_id);
// recycle memory resource
ESP_RETURN_ON_ERROR(sdm_destory(chan), TAG, "destory channel failed");
return ESP_OK;
}
esp_err_t sdm_channel_enable(sdm_channel_handle_t chan)
{
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(chan->fsm == SDM_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "channel not in init state");
// acquire power manager lock
if (chan->pm_lock) {
ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(chan->pm_lock), TAG, "acquire pm_lock failed");
}
chan->fsm = SDM_FSM_ENABLE;
return ESP_OK;
}
esp_err_t sdm_channel_disable(sdm_channel_handle_t chan)
{
ESP_RETURN_ON_FALSE(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(chan->fsm == SDM_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "channel not in enable state");
// release power manager lock
if (chan->pm_lock) {
ESP_RETURN_ON_ERROR(esp_pm_lock_release(chan->pm_lock), TAG, "release pm_lock failed");
}
chan->fsm = SDM_FSM_INIT;
return ESP_OK;
}
esp_err_t sdm_channel_set_duty(sdm_channel_handle_t chan, int8_t duty)
{
ESP_RETURN_ON_FALSE_ISR(chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
sdm_group_t *group = chan->group;
int chan_id = chan->chan_id;
portENTER_CRITICAL_SAFE(&chan->spinlock);
sdm_ll_set_duty(group->hal.dev, chan_id, duty);
portEXIT_CRITICAL_SAFE(&chan->spinlock);
return ESP_OK;
}

View File

@ -5,8 +5,8 @@ if(CONFIG_SOC_DEDICATED_GPIO_SUPPORTED)
list(APPEND srcs "test_dedicated_gpio.c")
endif()
if(CONFIG_SOC_SIGMADELTA_SUPPORTED)
list(APPEND srcs "test_sigmadelta.c")
if(CONFIG_SOC_SDM_SUPPORTED)
list(APPEND srcs "test_sigma_delta_legacy.c")
endif()
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,

View File

@ -17,12 +17,12 @@ TEST_CASE("SigmaDelta_config_test", "[sigma_delta]")
.sigmadelta_duty = 45,
.sigmadelta_gpio = 4,
};
for (int i = 0; i < SOC_SIGMADELTA_CHANNEL_NUM; i++) {
for (int i = 0; i < SIGMADELTA_CHANNEL_MAX; i++) {
sigmadelta_cfg.channel = i;
TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg));
}
sigmadelta_cfg.channel = SOC_SIGMADELTA_CHANNEL_NUM;
sigmadelta_cfg.channel = SIGMADELTA_CHANNEL_MAX;
TEST_ASSERT_EQUAL_MESSAGE(ESP_ERR_INVALID_ARG, sigmadelta_config(&sigmadelta_cfg), "wrong channel number should be inspected");
}

View File

@ -1,2 +1,3 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT=n
CONFIG_SDM_SUPPRESS_DEPRECATE_WARN=y

View File

@ -218,7 +218,7 @@ typedef struct {
} test_pcnt_quadrature_context_t;
TEST_PCNT_CALLBACK_ATTR
static bool test_pcnt_quadrature_reach_watch_point(pcnt_unit_handle_t handle, pcnt_watch_event_data_t *event_data, void *user_data)
static bool test_pcnt_quadrature_reach_watch_point(pcnt_unit_handle_t handle, const pcnt_watch_event_data_t *event_data, void *user_data)
{
test_pcnt_quadrature_context_t *user_ctx = (test_pcnt_quadrature_context_t *)user_data;
user_ctx->triggered_watch_values[user_ctx->index++] = event_data->watch_point_value;
@ -338,7 +338,7 @@ typedef struct {
} test_pcnt_zero_cross_context_t;
TEST_PCNT_CALLBACK_ATTR
static bool test_pcnt_on_zero_cross(pcnt_unit_handle_t handle, pcnt_watch_event_data_t *event_data, void *user_data)
static bool test_pcnt_on_zero_cross(pcnt_unit_handle_t handle, const pcnt_watch_event_data_t *event_data, void *user_data)
{
test_pcnt_zero_cross_context_t *user_ctx = (test_pcnt_zero_cross_context_t *)user_data;
user_ctx->mode = event_data->zero_cross_mode;

View File

@ -20,7 +20,7 @@
#if CONFIG_PCNT_ISR_IRAM_SAFE
static bool IRAM_ATTR test_pcnt_iram_safe_callback(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *event_data, void *user_data)
static bool IRAM_ATTR test_pcnt_iram_safe_callback(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *event_data, void *user_data)
{
uint32_t *data = (uint32_t *)user_data;
(*data)++;

View File

@ -0,0 +1,18 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(sdm_test)
if(CONFIG_COMPILER_DUMP_RTL_FILES)
add_custom_target(check_test_app_sections ALL
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
--rtl-dir ${CMAKE_BINARY_DIR}/esp-idf/driver/
--elf-file ${CMAKE_BINARY_DIR}/sdm_test.elf
find-refs
--from-sections=.iram0.text
--to-sections=.flash.text,.flash.rodata
--exit-code
DEPENDS ${elf}
)
endif()

View File

@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |

View File

@ -0,0 +1,7 @@
set(srcs "test_app_main.c"
"test_sdm.c")
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
WHOLE_ARCHIVE)

View File

@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "unity_test_runner.h"
#include "esp_heap_caps.h"
// Some resources are lazy allocated in pulse_cnt driver, the threshold is left for that case
#define TEST_MEMORY_LEAK_THRESHOLD (-200)
static size_t before_free_8bit;
static size_t before_free_32bit;
static void check_leak(size_t before_free, size_t after_free, const char *type)
{
ssize_t delta = after_free - before_free;
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
}
void setUp(void)
{
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void tearDown(void)
{
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
check_leak(before_free_8bit, after_free_8bit, "8BIT");
check_leak(before_free_32bit, after_free_32bit, "32BIT");
}
void app_main(void)
{
// ____ ____ ___ ___ ____ ____ __ __
// / ___| _ \_ _/ _ \ / ___|| _ \| \/ |
// | | _| |_) | | | | | \___ \| | | | |\/| |
// | |_| | __/| | |_| | ___) | |_| | | | |
// \____|_| |___\___/ |____/|____/|_| |_|
printf(" ____ ____ ___ ___ ____ ____ __ __\r\n");
printf(" / ___| _ \\_ _/ _ \\ / ___|| _ \\| \\/ |\r\n");
printf("| | _| |_) | | | | | \\___ \\| | | | |\\/| |\r\n");
printf("| |_| | __/| | |_| | ___) | |_| | | | |\r\n");
printf(" \\____|_| |___\\___/ |____/|____/|_| |_|\r\n");
unity_run_menu();
}

View File

@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "driver/sdm.h"
#include "soc/soc_caps.h"
#include "esp_attr.h"
TEST_CASE("sdm_channel_install_uninstall", "[sdm]")
{
printf("install sdm channels exhaustively\r\n");
sdm_config_t config = {
.clk_src = SDM_CLK_SRC_DEFAULT,
.sample_rate_hz = 1000000,
.gpio_num = 0,
};
sdm_channel_handle_t chans[SOC_SDM_GROUPS][SOC_SDM_CHANNELS_PER_GROUP] = {};
for (int i = 0; i < SOC_SDM_GROUPS; i++) {
for (int j = 0; j < SOC_SDM_CHANNELS_PER_GROUP; j++) {
TEST_ESP_OK(sdm_new_channel(&config, &chans[i][j]));
}
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, sdm_new_channel(&config, &chans[0][0]));
}
printf("delete sdm channels\r\n");
for (int i = 0; i < SOC_SDM_GROUPS; i++) {
for (int j = 0; j < SOC_SDM_CHANNELS_PER_GROUP; j++) {
TEST_ESP_OK(sdm_del_channel(chans[i][j]));
}
}
}
TEST_CASE("sdm_channel_set_duty", "[sdm]")
{
const int sdm_chan_gpios[2] = {0, 2};
sdm_config_t config = {
.clk_src = SDM_CLK_SRC_DEFAULT,
.sample_rate_hz = 1000000,
};
sdm_channel_handle_t chans[2] = {};
for (size_t i = 0; i < 2; i++) {
config.gpio_num = sdm_chan_gpios[i];
TEST_ESP_OK(sdm_new_channel(&config, &chans[i]));
// should see a ~250KHz (sample_rate/4) square wave
TEST_ESP_OK(sdm_channel_set_duty(chans[i], 0));
TEST_ESP_OK(sdm_channel_enable(chans[i]));
}
vTaskDelay(pdMS_TO_TICKS(500));
// can't delete the channel if the channel is in the enable state
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, sdm_del_channel(chans[0]));
TEST_ESP_OK(sdm_channel_set_duty(chans[0], 127));
TEST_ESP_OK(sdm_channel_set_duty(chans[1], -128));
vTaskDelay(pdMS_TO_TICKS(500));
for (size_t i = 0; i < 2; i++) {
TEST_ESP_OK(sdm_channel_disable(chans[i]));
TEST_ESP_OK(sdm_del_channel(chans[i]));
}
}

View File

@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32
@pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.esp32c3
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
[
'iram_safe',
'release',
],
indirect=True,
)
def test_sdm(dut: Dut) -> None:
dut.expect_exact('Press ENTER to see the list of tests')
dut.write('*')
dut.expect_unity_test_output()

View File

@ -0,0 +1,5 @@
CONFIG_COMPILER_DUMP_RTL_FILES=y
CONFIG_SDM_CTRL_FUNC_IN_IRAM=y
# silent the error check, as the error string are stored in rodata, causing RTL check failure
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y

View File

@ -0,0 +1,5 @@
CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

View File

@ -0,0 +1,2 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT=n

View File

@ -74,8 +74,8 @@ if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "i2s_hal.c")
endif()
if(CONFIG_SOC_SIGMADELTA_SUPPORTED)
list(APPEND srcs "sigmadelta_hal.c")
if(CONFIG_SOC_SDM_SUPPORTED)
list(APPEND srcs "sdm_hal.c")
endif()
if(CONFIG_ETH_USE_ESP32_EMAC)

View File

@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/gpio_sd_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sdm_ll_enable_clock(gpio_sd_dev_t *hw, bool en)
{
// The clk enable register does not exist on ESP32.
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
__attribute__((always_inline))
static inline void sdm_ll_set_duty(gpio_sd_dev_t *hw, int channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param prescale The divider of source clock, ranges from 1 to 256
*/
static inline void sdm_ll_set_prescale(gpio_sd_dev_t *hw, int channel, uint32_t prescale)
{
HAL_ASSERT(prescale && prescale <= 256);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale - 1);
}
#ifdef __cplusplus
}
#endif

View File

@ -1,75 +0,0 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The LL layer for ESP32 SIGMADELTA register operations
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sd_struct.h"
#include "hal/sigmadelta_types.h"
#ifdef __cplusplus
extern "C" {
#endif
// Get SIGMADELTA hardware instance with giving sigmadelta num
#define SIGMADELTA_LL_GET_HW(num) (((num) == 0) ? (&SIGMADELTA) : NULL)
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en)
{
// The clk enable register does not exist on ESP32.
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param val The divider of source clock, ranges from 0 to 255
*/
static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/gpio_sd_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sdm_ll_enable_clock(gpio_sd_dev_t *hw, bool en)
{
hw->misc.function_clk_en = en;
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
__attribute__((always_inline))
static inline void sdm_ll_set_duty(gpio_sd_dev_t *hw, int channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param prescale The divider of source clock, ranges from 1 to 256
*/
static inline void sdm_ll_set_prescale(gpio_sd_dev_t *hw, int channel, uint32_t prescale)
{
HAL_ASSERT(prescale && prescale <= 256);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale - 1);
}
#ifdef __cplusplus
}
#endif

View File

@ -1,75 +0,0 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
// The LL layer for ESP32 SIGMADELTA register operations
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sd_struct.h"
#include "hal/sigmadelta_types.h"
#ifdef __cplusplus
extern "C" {
#endif
// Get SIGMADELTA hardware instance with giving sigmadelta num
#define SIGMADELTA_LL_GET_HW(num) (((num) == 0) ? (&SIGMADELTA) : NULL)
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en)
{
hw->misc.function_clk_en = en;
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param val The divider of source clock, ranges from 0 to 255
*/
static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/gpio_sd_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sdm_ll_enable_clock(gpio_sd_dev_t *hw, bool en)
{
hw->misc.function_clk_en = en;
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
__attribute__((always_inline))
static inline void sdm_ll_set_duty(gpio_sd_dev_t *hw, int channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param prescale The divider of source clock, ranges from 1 to 256
*/
static inline void sdm_ll_set_prescale(gpio_sd_dev_t *hw, int channel, uint32_t prescale)
{
HAL_ASSERT(prescale && prescale <= 256);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale - 1);
}
#ifdef __cplusplus
}
#endif

View File

@ -1,75 +0,0 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
// The LL layer for ESP32 SIGMADELTA register operations
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sd_struct.h"
#include "hal/sigmadelta_types.h"
#ifdef __cplusplus
extern "C" {
#endif
// Get SIGMADELTA hardware instance with giving sigmadelta num
#define SIGMADELTA_LL_GET_HW(num) (((num) == 0) ? (&SIGMADELTA) : NULL)
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en)
{
hw->misc.function_clk_en = en;
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param val The divider of source clock, ranges from 0 to 255
*/
static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/gpio_sd_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sdm_ll_enable_clock(gpio_sd_dev_t *hw, bool en)
{
hw->misc.function_clk_en = en;
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
__attribute__((always_inline))
static inline void sdm_ll_set_duty(gpio_sd_dev_t *hw, int channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param prescale The divider of source clock, ranges from 1 to 256
*/
static inline void sdm_ll_set_prescale(gpio_sd_dev_t *hw, int channel, uint32_t prescale)
{
HAL_ASSERT(prescale && prescale <= 256);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale - 1);
}
#ifdef __cplusplus
}
#endif

View File

@ -1,75 +0,0 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The LL layer for ESP32-S2 SIGMADELTA register operations
#pragma once
#include <stdbool.h>
#include "hal/misc.h"
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sd_struct.h"
#include "hal/sigmadelta_types.h"
#ifdef __cplusplus
extern "C" {
#endif
// Get SIGMADELTA hardware instance with giving sigmadelta num
#define SIGMADELTA_LL_GET_HW(num) (((num) == 0) ? (&SIGMADELTA) : NULL)
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en)
{
hw->misc.function_clk_en = en;
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param prescale The divider of source clock, ranges from 0 to 255
*/
static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "hal/assert.h"
#include "hal/misc.h"
#include "soc/gpio_sd_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sdm_ll_enable_clock(gpio_sd_dev_t *hw, bool en)
{
hw->misc.function_clk_en = en;
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
__attribute__((always_inline))
static inline void sdm_ll_set_duty(gpio_sd_dev_t *hw, int channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param prescale The divider of source clock, ranges from 1 to 256
*/
static inline void sdm_ll_set_prescale(gpio_sd_dev_t *hw, int channel, uint32_t prescale)
{
HAL_ASSERT(prescale && prescale <= 256);
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale - 1);
}
#ifdef __cplusplus
}
#endif

View File

@ -1,75 +0,0 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The LL layer for ESP32 SIGMADELTA register operations
#pragma once
#include <stdbool.h>
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sd_struct.h"
#include "hal/sigmadelta_types.h"
#include "hal/misc.h"
#ifdef __cplusplus
extern "C" {
#endif
// Get SIGMADELTA hardware instance with giving sigmadelta num
#define SIGMADELTA_LL_GET_HW(num) (((num) == 0) ? (&SIGMADELTA) : NULL)
/**
* @brief Set Sigma-delta enable
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param en Sigma-delta enable value
*/
static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en)
{
hw->misc.function_clk_en = en;
}
/**
* @brief Set Sigma-delta channel duty.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint8_t)duty);
}
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hw Peripheral SIGMADELTA hardware instance address.
* @param channel Sigma-delta channel number
* @param val The divider of source clock, ranges from 0 to 255
*/
static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale);
}
#ifdef __cplusplus
}
#endif

View File

@ -7,6 +7,7 @@
#pragma once
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
@ -16,7 +17,11 @@ extern "C" {
* @brief RMT group clock source
* @note User should select the clock source based on the power and resolution requirement
*/
#if SOC_RMT_SUPPORTED
typedef soc_periph_rmt_clk_src_t rmt_clock_source_t;
#else
typedef int rmt_clock_source_t;
#endif
/**
* @brief The layout of RMT symbol stored in memory, which is decided by the hardware design

View File

@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The HAL layer for sigma delta modulator.
// There is no parameter check in the hal layer, so the caller must ensure the correctness of the parameters.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct gpio_sd_dev_t *sdm_soc_handle_t; // Sigma-Delta SOC layer handle
/**
* HAL context type of Sigma-Delta driver
*/
typedef struct {
sdm_soc_handle_t dev;
} sdm_hal_context_t;
/**
* @brief Initialize Sigma-Delta hal driver
*
* @param hal Context of the HAL layer
* @param group_id Sigma-Delta group number
*/
void sdm_hal_init(sdm_hal_context_t *hal, int group_id);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_SDM_SUPPORTED
typedef soc_periph_sdm_clk_src_t sdm_clock_source_t; // sigma delta modulator clock source
#else
typedef int sdm_clock_source_t; // sigma delta modulator clock source, fallback to integer type
#endif // SOC_SDM_SUPPORTED
#ifdef __cplusplus
}
#endif

View File

@ -1,71 +0,0 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
******************************************************************************/
// The HAL layer for SIGMADELTA.
// There is no parameter check in the hal layer, so the caller must ensure the correctness of the parameters.
#pragma once
#include "soc/sigmadelta_periph.h"
#include "hal/sigmadelta_types.h"
#include "hal/sigmadelta_ll.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Context that should be maintained by both the driver and the HAL
*/
typedef struct {
gpio_sd_dev_t *dev;
} sigmadelta_hal_context_t;
/**
* @brief Set Sigma-delta channel duty.
*
* @param hal Context of the HAL layer
* @param channel Sigma-delta channel number
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
* The waveform is more like a random one in this range.
*/
#define sigmadelta_hal_set_duty(hal, channel, duty) sigmadelta_ll_set_duty((hal)->dev, channel, duty)
/**
* @brief Set Sigma-delta channel's clock pre-scale value.
*
* @param hal Context of the HAL layer
* @param channel Sigma-delta channel number
* @param prescale The divider of source clock, ranges from 0 to 255
*/
#define sigmadelta_hal_set_prescale(hal, channel, prescale) sigmadelta_ll_set_prescale((hal)->dev, channel, prescale)
/**
* @brief Init the SIGMADELTA hal and set the SIGMADELTA to the default configuration. This function should be called first before other hal layer function is called
*
* @param hal Context of the HAL layer
* @param sigmadelta_num The uart port number, the max port number is (SIGMADELTA_NUM_MAX -1)
*/
void sigmadelta_hal_init(sigmadelta_hal_context_t *hal, int sigmadelta_num);
#ifdef __cplusplus
}
#endif

View File

@ -7,6 +7,7 @@
#pragma once
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
@ -15,7 +16,11 @@ extern "C" {
/**
* @brief temperature sensor clock source
*/
#if SOC_TEMP_SENSOR_SUPPORTED
typedef soc_periph_temperature_sensor_clk_src_t temperature_sensor_clk_src_t;
#else
typedef int temperature_sensor_clk_src_t;
#endif // SOC_TEMP_SENSOR_SUPPORTED
#ifdef __cplusplus
}

16
components/hal/sdm_hal.c Normal file
View File

@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The HAL layer for sigma delta modulator (common part)
#include "hal/sdm_ll.h"
#include "hal/sdm_hal.h"
void sdm_hal_init(sdm_hal_context_t *hal, int group_id)
{
(void) group_id;
hal->dev = &SDM;
}

View File

@ -1,26 +0,0 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The HAL layer for SIGMADELTA (common part)
#include <stdio.h>
#include "soc/soc.h"
#include "hal/sigmadelta_hal.h"
void sigmadelta_hal_init(sigmadelta_hal_context_t *hal, int sigmadelta_num)
{
//Get hardware instance.
hal->dev = SIGMADELTA_LL_GET_HW(sigmadelta_num);
sigmadelta_ll_set_en(hal->dev, 1);
}

View File

@ -3,6 +3,7 @@ set(srcs
"dac_periph.c"
"dport_access.c"
"gpio_periph.c"
"sdm_periph.c"
"i2c_periph.c"
"i2s_periph.c"
"interrupts.c"
@ -14,7 +15,6 @@ set(srcs
"rtc_io_periph.c"
"sdio_slave_periph.c"
"sdmmc_periph.c"
"sigmadelta_periph.c"
"spi_periph.c"
"timer_periph.c"
"touch_sensor_periph.c"

View File

@ -91,7 +91,7 @@ config SOC_RMT_SUPPORTED
bool
default y
config SOC_SIGMADELTA_SUPPORTED
config SOC_SDM_SUPPORTED
bool
default y
@ -487,11 +487,11 @@ config SOC_RTCIO_WAKE_SUPPORTED
bool
default y
config SOC_SIGMADELTA_NUM
config SOC_SDM_GROUPS
int
default 1
config SOC_SIGMADELTA_CHANNEL_NUM
config SOC_SDM_CHANNELS_PER_GROUP
int
default 8

View File

@ -177,7 +177,6 @@ typedef enum {
* @brief Type of RMT clock source
*/
typedef enum {
RMT_CLK_SRC_NONE = 0, /*!< No clock source is selected */
RMT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
RMT_CLK_SRC_REF_TICK = SOC_MOD_CLK_REF_TICK, /*!< Select REF_TICK as the source clock */
RMT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
@ -192,16 +191,6 @@ typedef enum {
RMT_BASECLK_DEFAULT = SOC_MOD_CLK_APB, /*!< RMT source clock default choice is APB */
} soc_periph_rmt_clk_src_legacy_t;
//////////////////////////////////////////////////Temp Sensor///////////////////////////////////////////////////////////
/**
* @brief Type of Temp Sensor clock source
* @note ESP32 does not support temperature sensor
*/
typedef enum {
TEMPERATURE_SENSOR_SRC_NA,
} soc_periph_temperature_sensor_clk_src_t;
///////////////////////////////////////////////////UART/////////////////////////////////////////////////////////////////
/**
@ -243,7 +232,7 @@ typedef enum {
///////////////////////////////////////////////////I2S//////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of
* @brief Array initializer for all supported clock sources of I2S
*/
#define SOC_I2S_CLKS {SOC_MOD_CLK_PLL_D2, SOC_MOD_CLK_APLL}
@ -272,6 +261,21 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB,
} soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SDM
*/
#define SOC_SDM_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Sigma Delta Modulator clock source
*/
typedef enum {
SDM_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
SDM_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default clock choice */
} soc_periph_sdm_clk_src_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,20 +1,13 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_GPIO_SD_REG_H_
#define _SOC_GPIO_SD_REG_H_
#pragma once
#include "soc.h"
#define GPIO_SIGMADELTA0_REG (DR_REG_GPIO_SD_BASE + 0x0000)
/* GPIO_SD0_PRESCALE : R/W ;bitpos:[15:8] ;default: 8'hff ; */
/*description: */
@ -151,8 +144,3 @@
#define GPIO_SD_DATE_V 0xFFFFFFF
#define GPIO_SD_DATE_S 0
#define SIGMADELTA_GPIO_SD_DATE_VERSION 0x1506190
#endif /*_SOC_GPIO_SD_REG_H_ */

View File

@ -1,18 +1,10 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_GPIO_SD_STRUCT_H_
#define _SOC_GPIO_SD_STRUCT_H_
#pragma once
#include <stdint.h>
@ -20,8 +12,8 @@
extern "C" {
#endif
typedef volatile struct gpio_sd_dev_s {
union {
typedef struct gpio_sd_dev_t {
volatile union {
struct {
uint32_t duty: 8;
uint32_t prescale: 8;
@ -29,21 +21,21 @@ typedef volatile struct gpio_sd_dev_s {
};
uint32_t val;
} channel[8];
union {
volatile union {
struct {
uint32_t reserved0: 31;
uint32_t clk_en: 1;
};
uint32_t val;
} cg;
union {
volatile union {
struct {
uint32_t reserved0: 31;
uint32_t spi_swap: 1;
};
uint32_t val;
} misc;
union {
volatile union {
struct {
uint32_t date: 28;
uint32_t reserved28: 4;
@ -51,10 +43,9 @@ typedef volatile struct gpio_sd_dev_s {
uint32_t val;
} version;
} gpio_sd_dev_t;
extern gpio_sd_dev_t SIGMADELTA;
extern gpio_sd_dev_t SDM;
#ifdef __cplusplus
}
#endif
#endif /* _SOC_GPIO_SD_STRUCT_H_ */

View File

@ -82,7 +82,7 @@
#define SOC_RTC_MEM_SUPPORTED 1
#define SOC_I2S_SUPPORTED 1
#define SOC_RMT_SUPPORTED 1
#define SOC_SIGMADELTA_SUPPORTED 1
#define SOC_SDM_SUPPORTED 1
#define SOC_SUPPORT_COEXISTENCE 1
#define SOC_AES_SUPPORTED 1
#define SOC_MPI_SUPPORTED 1
@ -247,9 +247,9 @@
#define SOC_RTCIO_HOLD_SUPPORTED 1
#define SOC_RTCIO_WAKE_SUPPORTED 1
/*-------------------------- SIGMA DELTA CAPS --------------------------------*/
#define SOC_SIGMADELTA_NUM 1U
#define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels
/*-------------------------- Sigma Delta Modulator CAPS -----------------*/
#define SOC_SDM_GROUPS 1U
#define SOC_SDM_CHANNELS_PER_GROUP 8
/*-------------------------- SPI CAPS ----------------------------------------*/
#define SOC_SPI_HD_BOTH_INOUT_SUPPORTED 1 //Support enabling MOSI and MISO phases together under Halfduplex mode

View File

@ -7,7 +7,7 @@ PROVIDE ( UART0 = 0x3ff40000 );
PROVIDE ( SPI1 = 0x3ff42000 );
PROVIDE ( SPI0 = 0x3ff43000 );
PROVIDE ( GPIO = 0x3ff44000 );
PROVIDE ( SIGMADELTA = 0x3ff44f00 );
PROVIDE ( SDM = 0x3ff44f00 );
PROVIDE ( RTCCNTL = 0x3ff48000 );
PROVIDE ( RTCIO = 0x3ff48400 );
PROVIDE ( SENS = 0x3ff48800 );

View File

@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/sdm_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
},
[4] = {
GPIO_SD4_OUT_IDX
},
[5] = {
GPIO_SD5_OUT_IDX
},
[6] = {
GPIO_SD6_OUT_IDX
},
[7] = {
GPIO_SD7_OUT_IDX
}
}
};

View File

@ -1,45 +0,0 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
},
[4] = {
GPIO_SD4_OUT_IDX
},
[5] = {
GPIO_SD5_OUT_IDX
},
[6] = {
GPIO_SD6_OUT_IDX
},
[7] = {
GPIO_SD7_OUT_IDX
}
}
};

View File

@ -3,11 +3,11 @@ set(srcs
"dedic_gpio_periph.c"
"gdma_periph.c"
"gpio_periph.c"
"sdm_periph.c"
"interrupts.c"
"spi_periph.c"
"ledc_periph.c"
"rmt_periph.c"
"sigmadelta_periph.c"
"i2s_periph.c"
"i2c_periph.c"
"uart_periph.c"

View File

@ -71,7 +71,7 @@ config SOC_RMT_SUPPORTED
bool
default y
config SOC_SIGMADELTA_SUPPORTED
config SOC_SDM_SUPPORTED
bool
default y
@ -511,11 +511,11 @@ config SOC_SHA_SUPPORT_SHA256
bool
default y
config SOC_SIGMADELTA_NUM
config SOC_SDM_GROUPS
int
default 1
config SOC_SIGMADELTA_CHANNEL_NUM
config SOC_SDM_CHANNELS_PER_GROUP
int
default 4

View File

@ -158,7 +158,6 @@ typedef enum {
* @brief Type of RMT clock source
*/
typedef enum {
RMT_CLK_SRC_NONE = 0, /*!< No clock source is selected */
RMT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
RMT_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
RMT_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
@ -205,7 +204,7 @@ typedef enum {
///////////////////////////////////////////////////// I2S //////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of
* @brief Array initializer for all supported clock sources of I2S
*/
#define SOC_I2S_CLKS {SOC_MOD_CLK_PLL_F160M}
@ -233,6 +232,21 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
} soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SDM
*/
#define SOC_SDM_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Sigma Delta Modulator clock source
*/
typedef enum {
SDM_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
SDM_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default clock choice */
} soc_periph_sdm_clk_src_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,24 +1,16 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_GPIO_SD_REG_H_
#define _SOC_GPIO_SD_REG_H_
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "soc.h"
#define GPIO_SIGMADELTA0_REG (DR_REG_GPIO_SD_BASE + 0x0000)
/* GPIO_SD0_PRESCALE : R/W ;bitpos:[15:8] ;default: 8'hff ; */
/*description: */
@ -108,7 +100,3 @@ extern "C" {
#ifdef __cplusplus
}
#endif
#endif /*_SOC_GPIO_SD_REG_H_ */

View File

@ -1,24 +1,19 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_GPIO_SD_STRUCT_H_
#define _SOC_GPIO_SD_STRUCT_H_
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef volatile struct gpio_sd_dev_s {
union {
typedef struct gpio_sd_dev_t {
volatile union {
struct {
uint32_t duty: 8;
uint32_t prescale: 8;
@ -30,14 +25,14 @@ typedef volatile struct gpio_sd_dev_s {
uint32_t reserved_14;
uint32_t reserved_18;
uint32_t reserved_1c;
union {
volatile union {
struct {
uint32_t reserved0: 31;
uint32_t clk_en: 1;
};
uint32_t val;
} cg;
union {
volatile union {
struct {
uint32_t reserved0: 30;
uint32_t function_clk_en: 1;
@ -45,7 +40,7 @@ typedef volatile struct gpio_sd_dev_s {
};
uint32_t val;
} misc;
union {
volatile union {
struct {
uint32_t date: 28;
uint32_t reserved28: 4;
@ -53,9 +48,9 @@ typedef volatile struct gpio_sd_dev_s {
uint32_t val;
} version;
} gpio_sd_dev_t;
extern gpio_sd_dev_t SIGMADELTA;
extern gpio_sd_dev_t SDM;
#ifdef __cplusplus
}
#endif
#endif /* _SOC_GPIO_SD_STRUCT_H_ */

View File

@ -42,7 +42,7 @@
#define SOC_RTC_MEM_SUPPORTED 1
#define SOC_I2S_SUPPORTED 1
#define SOC_RMT_SUPPORTED 1
#define SOC_SIGMADELTA_SUPPORTED 1
#define SOC_SDM_SUPPORTED 1
#define SOC_SUPPORT_COEXISTENCE 1
#define SOC_AES_SUPPORTED 1
#define SOC_MPI_SUPPORTED 1
@ -247,9 +247,9 @@
#define SOC_SHA_SUPPORT_SHA224 (1)
#define SOC_SHA_SUPPORT_SHA256 (1)
/*-------------------------- SIGMA DELTA CAPS --------------------------------*/
#define SOC_SIGMADELTA_NUM (1U) // 1 sigma-delta peripheral
#define SOC_SIGMADELTA_CHANNEL_NUM (4) // 4 channels
/*-------------------------- Sigma Delta Modulator CAPS -----------------*/
#define SOC_SDM_GROUPS 1U
#define SOC_SDM_CHANNELS_PER_GROUP 4
/*-------------------------- SPI CAPS ----------------------------------------*/
#define SOC_SPI_PERIPH_NUM 2

View File

@ -8,7 +8,7 @@ PROVIDE ( UART1 = 0x60010000 );
PROVIDE ( SPIMEM1 = 0x60002000 );
PROVIDE ( SPIMEM0 = 0x60003000 );
PROVIDE ( GPIO = 0x60004000 );
PROVIDE ( SIGMADELTA = 0x60004f00 );
PROVIDE ( SDM = 0x60004f00 );
PROVIDE ( RTCCNTL = 0x60008000 );
PROVIDE ( RTCIO = 0x60008400 );
PROVIDE ( EFUSE = 0x60008800 );

View File

@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/sdm_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
}
}
};

View File

@ -1,33 +0,0 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
}
}
};

View File

@ -3,11 +3,11 @@ set(srcs
"dedic_gpio_periph.c"
"gdma_periph.c"
"gpio_periph.c"
"sdm_periph.c"
"interrupts.c"
"spi_periph.c"
"ledc_periph.c"
"rmt_periph.c"
"sigmadelta_periph.c"
"i2s_periph.c"
"i2c_periph.c"
"uart_periph.c"

View File

@ -3,8 +3,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SOC_GPIO_SD_REG_H_
#define _SOC_GPIO_SD_REG_H_
#pragma once
#include "soc/soc.h"
@ -100,7 +99,3 @@ extern "C" {
#ifdef __cplusplus
}
#endif
#endif /*_SOC_GPIO_SD_REG_H_ */

View File

@ -5,8 +5,8 @@
*/
#pragma once
#include <stdint.h>
#include "soc/soc.h"
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -63,7 +63,7 @@ config SOC_RMT_SUPPORTED
bool
default y
config SOC_SIGMADELTA_SUPPORTED
config SOC_SDM_SUPPORTED
bool
default y
@ -487,11 +487,11 @@ config SOC_SHA_SUPPORT_SHA256
bool
default y
config SOC_SIGMADELTA_NUM
config SOC_SDM_GROUPS
int
default 1
config SOC_SIGMADELTA_CHANNEL_NUM
config SOC_SDM_CHANNELS_PER_GROUP
int
default 4

View File

@ -111,6 +111,7 @@ typedef enum {
SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, or RC32K by configuring soc_rtc_slow_clk_src_t */
// For digital domain: peripherals, WIFI, BLE
SOC_MOD_CLK_AHB, /*< AHB_CLK sources from CPU with a configurable divider */
SOC_MOD_CLK_APB, /*< APB_CLK source is derived from AHB clock */
SOC_MOD_CLK_XTAL32K, /*< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */
SOC_MOD_CLK_RC_FAST, /*< RC_FAST_CLK comes from the internal 8MHz rc oscillator, passing a clock gating to the peripherals */
SOC_MOD_CLK_XTAL, /*< XTAL_CLK comes from the external 32MHz crystal */
@ -163,7 +164,6 @@ typedef enum {
* @brief Type of RMT clock source
*/
typedef enum {
RMT_CLK_SRC_NONE = 0, /*!< No clock source is selected */
RMT_CLK_SRC_AHB = SOC_MOD_CLK_AHB, /*!< Select AHB clock as the source clock */
RMT_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
RMT_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
@ -238,6 +238,21 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
} soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SDM
*/
#define SOC_SDM_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Sigma Delta Modulator clock source
*/
typedef enum {
SDM_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
SDM_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default clock choice */
} soc_periph_sdm_clk_src_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,24 +1,19 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_GPIO_SD_STRUCT_H_
#define _SOC_GPIO_SD_STRUCT_H_
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef volatile struct gpio_sd_dev_s {
union {
typedef struct gpio_sd_dev_t {
volatile union {
struct {
uint32_t duty: 8;
uint32_t prescale: 8;
@ -30,14 +25,14 @@ typedef volatile struct gpio_sd_dev_s {
uint32_t reserved_14;
uint32_t reserved_18;
uint32_t reserved_1c;
union {
volatile union {
struct {
uint32_t reserved0: 31;
uint32_t clk_en: 1;
};
uint32_t val;
} cg;
union {
volatile union {
struct {
uint32_t reserved0: 30;
uint32_t function_clk_en: 1;
@ -45,7 +40,7 @@ typedef volatile struct gpio_sd_dev_s {
};
uint32_t val;
} misc;
union {
volatile union {
struct {
uint32_t date: 28;
uint32_t reserved28: 4;
@ -53,9 +48,9 @@ typedef volatile struct gpio_sd_dev_s {
uint32_t val;
} version;
} gpio_sd_dev_t;
extern gpio_sd_dev_t SIGMADELTA;
extern gpio_sd_dev_t SDM;
#ifdef __cplusplus
}
#endif
#endif /* _SOC_GPIO_SD_STRUCT_H_ */

View File

@ -48,7 +48,7 @@
#define SOC_RTC_MEM_SUPPORTED 1
#define SOC_I2S_SUPPORTED 1
#define SOC_RMT_SUPPORTED 1
#define SOC_SIGMADELTA_SUPPORTED 1
#define SOC_SDM_SUPPORTED 1
#define SOC_AES_SUPPORTED 1
#define SOC_MPI_SUPPORTED 1
#define SOC_SHA_SUPPORTED 1
@ -252,9 +252,9 @@
#define SOC_SHA_SUPPORT_SHA224 (1)
#define SOC_SHA_SUPPORT_SHA256 (1)
/*-------------------------- SIGMA DELTA CAPS --------------------------------*/
#define SOC_SIGMADELTA_NUM (1U) // 1 sigma-delta peripheral
#define SOC_SIGMADELTA_CHANNEL_NUM (4) // 4 channels
/*-------------------------- Sigma Delta Modulator CAPS -----------------*/
#define SOC_SDM_GROUPS 1U
#define SOC_SDM_CHANNELS_PER_GROUP 4
/*-------------------------- SPI CAPS ----------------------------------------*/
#define SOC_SPI_PERIPH_NUM 2

View File

@ -8,7 +8,7 @@ PROVIDE ( UART1 = 0x60010000 );
PROVIDE ( SPIMEM1 = 0x60002000 );
PROVIDE ( SPIMEM0 = 0x60003000 );
PROVIDE ( GPIO = 0x60004000 );
PROVIDE ( SIGMADELTA = 0x60004f00 );
PROVIDE ( SDM = 0x60004f00 );
PROVIDE ( RTCCNTL = 0x60008000 );
PROVIDE ( RTCIO = 0x60008400 );
PROVIDE ( HINF = 0x6000B000 );

View File

@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/sdm_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
}
}
};

View File

@ -1,33 +0,0 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
}
}
};

View File

@ -3,6 +3,7 @@ set(srcs
"dac_periph.c"
"dedic_gpio_periph.c"
"gpio_periph.c"
"sdm_periph.c"
"i2c_periph.c"
"i2s_periph.c"
"interrupts.c"
@ -11,7 +12,6 @@ set(srcs
"pcnt_periph.c"
"rmt_periph.c"
"rtc_io_periph.c"
"sigmadelta_periph.c"
"spi_periph.c"
"timer_periph.c"
"touch_sensor_periph.c"

View File

@ -95,7 +95,7 @@ config SOC_RMT_SUPPORTED
bool
default y
config SOC_SIGMADELTA_SUPPORTED
config SOC_SDM_SUPPORTED
bool
default y
@ -523,11 +523,11 @@ config SOC_RTCIO_WAKE_SUPPORTED
bool
default y
config SOC_SIGMADELTA_NUM
config SOC_SDM_GROUPS
int
default 1
config SOC_SIGMADELTA_CHANNEL_NUM
config SOC_SDM_CHANNELS_PER_GROUP
int
default 8

View File

@ -178,7 +178,6 @@ typedef enum {
* @brief Type of RMT clock source
*/
typedef enum {
RMT_CLK_SRC_NONE = 0, /*!< No clock source is selected */
RMT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
RMT_CLK_SRC_REF_TICK = SOC_MOD_CLK_REF_TICK, /*!< Select REF_TICK as the source clock */
RMT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */
@ -222,7 +221,7 @@ typedef enum {
///////////////////////////////////////////////////// I2S //////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of
* @brief Array initializer for all supported clock sources of I2S
*/
#define SOC_I2S_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_APLL}
@ -251,6 +250,21 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB,
} soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SDM
*/
#define SOC_SDM_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Sigma Delta Modulator clock source
*/
typedef enum {
SDM_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
SDM_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default clock choice */
} soc_periph_sdm_clk_src_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,24 +1,16 @@
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_GPIO_SD_REG_H_
#define _SOC_GPIO_SD_REG_H_
/*
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "soc.h"
#define GPIO_SIGMADELTA0_REG (DR_REG_GPIO_SD_BASE + 0x0000)
/* GPIO_SD0_PRESCALE : R/W ;bitpos:[15:8] ;default: 8'hff ; */
/*description: */
@ -164,7 +156,3 @@ extern "C" {
#ifdef __cplusplus
}
#endif
#endif /*_SOC_GPIO_SD_REG_H_ */

View File

@ -1,24 +1,19 @@
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_GPIO_SD_STRUCT_H_
#define _SOC_GPIO_SD_STRUCT_H_
/*
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef volatile struct gpio_sd_dev_s {
union {
typedef struct gpio_sd_dev_t {
volatile union {
struct {
uint32_t duty: 8;
uint32_t prescale: 8;
@ -26,14 +21,14 @@ typedef volatile struct gpio_sd_dev_s {
};
uint32_t val;
} channel[8];
union {
volatile union {
struct {
uint32_t reserved0: 31;
uint32_t clk_en: 1;
};
uint32_t val;
} cg;
union {
volatile union {
struct {
uint32_t reserved0: 30;
uint32_t function_clk_en: 1;
@ -41,7 +36,7 @@ typedef volatile struct gpio_sd_dev_s {
};
uint32_t val;
} misc;
union {
volatile union {
struct {
uint32_t date: 28;
uint32_t reserved28: 4;
@ -49,9 +44,9 @@ typedef volatile struct gpio_sd_dev_s {
uint32_t val;
} version;
} gpio_sd_dev_t;
extern gpio_sd_dev_t SIGMADELTA;
extern gpio_sd_dev_t SDM;
#ifdef __cplusplus
}
#endif
#endif /* _SOC_GPIO_SD_STRUCT_H_ */

View File

@ -62,7 +62,7 @@
#define SOC_XT_WDT_SUPPORTED 1
#define SOC_I2S_SUPPORTED 1
#define SOC_RMT_SUPPORTED 1
#define SOC_SIGMADELTA_SUPPORTED 1
#define SOC_SDM_SUPPORTED 1
#define SOC_SUPPORT_COEXISTENCE 0
#define SOC_AES_SUPPORTED 1
#define SOC_MPI_SUPPORTED 1
@ -235,9 +235,9 @@
#define SOC_RTCIO_WAKE_SUPPORTED 1
/*-------------------------- SIGMA DELTA CAPS --------------------------------*/
#define SOC_SIGMADELTA_NUM 1U
#define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels
/*-------------------------- Sigma Delta Modulator CAPS -----------------*/
#define SOC_SDM_GROUPS 1U
#define SOC_SDM_CHANNELS_PER_GROUP 8
/*-------------------------- SPI CAPS ----------------------------------------*/
#define SOC_SPI_HD_BOTH_INOUT_SUPPORTED 1 //Support enabling MOSI and MISO phases together under Halfduplex mode

View File

@ -7,7 +7,7 @@ PROVIDE ( UART0 = 0x3f400000 );
PROVIDE ( SPIMEM1 = 0x3f402000 );
PROVIDE ( SPIMEM0 = 0x3f403000 );
PROVIDE ( GPIO = 0x3f404000 );
PROVIDE ( SIGMADELTA = 0x3f404f00 );
PROVIDE ( SDM = 0x3f404f00 );
PROVIDE ( RTCCNTL = 0x3f408000 );
PROVIDE ( RTCIO = 0x3f408400 );
PROVIDE ( SENS = 0x3f408800 );

View File

@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/sdm_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
},
[4] = {
GPIO_SD4_OUT_IDX
},
[5] = {
GPIO_SD5_OUT_IDX
},
[6] = {
GPIO_SD6_OUT_IDX
},
[7] = {
GPIO_SD7_OUT_IDX
}
}
};

View File

@ -1,45 +0,0 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
},
[4] = {
GPIO_SD4_OUT_IDX
},
[5] = {
GPIO_SD5_OUT_IDX
},
[6] = {
GPIO_SD6_OUT_IDX
},
[7] = {
GPIO_SD7_OUT_IDX
}
}
};

View File

@ -3,6 +3,7 @@ set(srcs
"dedic_gpio_periph.c"
"gdma_periph.c"
"gpio_periph.c"
"sdm_periph.c"
"i2c_periph.c"
"i2s_periph.c"
"interrupts.c"
@ -14,7 +15,6 @@ set(srcs
"rtc_io_periph.c"
"sdio_slave_periph.c"
"sdmmc_periph.c"
"sigmadelta_periph.c"
"spi_periph.c"
"timer_periph.c"
"touch_sensor_periph.c"

View File

@ -147,7 +147,7 @@ config SOC_RMT_SUPPORTED
bool
default y
config SOC_SIGMADELTA_SUPPORTED
config SOC_SDM_SUPPORTED
bool
default y
@ -607,11 +607,11 @@ config SOC_RTCIO_WAKE_SUPPORTED
bool
default y
config SOC_SIGMADELTA_NUM
config SOC_SDM_GROUPS
bool
default y
config SOC_SIGMADELTA_CHANNEL_NUM
config SOC_SDM_CHANNELS_PER_GROUP
int
default 8

View File

@ -177,7 +177,6 @@ typedef enum {
* @brief Type of RMT clock source
*/
typedef enum {
RMT_CLK_SRC_NONE = 0, /*!< No clock source is selected */
RMT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
RMT_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
RMT_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */
@ -251,7 +250,7 @@ typedef enum {
///////////////////////////////////////////////////// I2S //////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of
* @brief Array initializer for all supported clock sources of I2S
*/
#define SOC_I2S_CLKS {SOC_MOD_CLK_PLL_F160M}
@ -279,6 +278,21 @@ typedef enum {
I2C_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL,
} soc_periph_i2c_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of SDM
*/
#define SOC_SDM_CLKS {SOC_MOD_CLK_APB}
/**
* @brief Sigma Delta Modulator clock source
*/
typedef enum {
SDM_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */
SDM_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default clock choice */
} soc_periph_sdm_clk_src_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,21 +1,13 @@
// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_GPIO_SD_REG_H_
#define _SOC_GPIO_SD_REG_H_
/*
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -162,11 +154,6 @@ extern "C" {
#define GPIO_SD_DATE_V 0xFFFFFFF
#define GPIO_SD_DATE_S 0
#ifdef __cplusplus
}
#endif
#endif /*_SOC_GPIO_REG_H_ */

View File

@ -1,27 +1,19 @@
// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SOC_GPIO_SD_STRUCT_H_
#define _SOC_GPIO_SD_STRUCT_H_
/*
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef volatile struct gpio_sd_dev_s {
union {
typedef struct gpio_sd_dev_t {
volatile union {
struct {
uint32_t duty : 8;
uint32_t prescale : 8;
@ -29,14 +21,14 @@ typedef volatile struct gpio_sd_dev_s {
};
uint32_t val;
} channel[8];
union {
volatile union {
struct {
uint32_t reserved0 : 31;
uint32_t clk_en : 1;
};
uint32_t val;
} cg;
union {
volatile union {
struct {
uint32_t reserved0 : 30;
uint32_t function_clk_en : 1;
@ -44,7 +36,7 @@ typedef volatile struct gpio_sd_dev_s {
};
uint32_t val;
} misc;
union {
volatile union {
struct {
uint32_t date : 28;
uint32_t reserved28 : 4;
@ -52,11 +44,9 @@ typedef volatile struct gpio_sd_dev_s {
uint32_t val;
} version;
} gpio_sd_dev_t;
extern gpio_sd_dev_t SIGMADELTA;
extern gpio_sd_dev_t SDM;
#ifdef __cplusplus
}
#endif
#endif /*_SOC_GPIO_STRUCT_H_ */

View File

@ -51,7 +51,7 @@
#define SOC_XT_WDT_SUPPORTED 1
#define SOC_I2S_SUPPORTED 1
#define SOC_RMT_SUPPORTED 1
#define SOC_SIGMADELTA_SUPPORTED 1
#define SOC_SDM_SUPPORTED 1
#define SOC_SUPPORT_COEXISTENCE 1
#define SOC_TEMP_SENSOR_SUPPORTED 1
#define SOC_AES_SUPPORTED 1
@ -250,9 +250,9 @@
#define SOC_RTCIO_HOLD_SUPPORTED 1
#define SOC_RTCIO_WAKE_SUPPORTED 1
/*-------------------------- SIGMA DELTA CAPS --------------------------------*/
#define SOC_SIGMADELTA_NUM (1) // 1 sigma-delta peripheral
#define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels
/*-------------------------- Sigma Delta Modulator CAPS -----------------*/
#define SOC_SDM_GROUPS 1
#define SOC_SDM_CHANNELS_PER_GROUP 8
/*-------------------------- SPI CAPS ----------------------------------------*/
#define SOC_SPI_PERIPH_NUM 3

View File

@ -7,7 +7,7 @@ PROVIDE ( UART0 = 0x60000000 );
PROVIDE ( SPIMEM1 = 0x60002000 );
PROVIDE ( SPIMEM0 = 0x60003000 );
PROVIDE ( GPIO = 0x60004000 );
PROVIDE ( SIGMADELTA = 0x60004f00 );
PROVIDE ( SDM = 0x60004f00 );
PROVIDE ( EFUSE = 0x60007000 );
PROVIDE ( RTCCNTL = 0x60008000 );
PROVIDE ( RTCIO = 0x60008400 );

View File

@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/sdm_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
},
[4] = {
GPIO_SD4_OUT_IDX
},
[5] = {
GPIO_SD5_OUT_IDX
},
[6] = {
GPIO_SD6_OUT_IDX
},
[7] = {
GPIO_SD7_OUT_IDX
}
}
};

View File

@ -1,45 +0,0 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/sigmadelta_periph.h"
#include "soc/gpio_sig_map.h"
const sigma_delta_signal_conn_t sigma_delta_periph_signals = {
.channels = {
[0] = {
GPIO_SD0_OUT_IDX
},
[1] = {
GPIO_SD1_OUT_IDX
},
[2] = {
GPIO_SD2_OUT_IDX
},
[3] = {
GPIO_SD3_OUT_IDX
},
[4] = {
GPIO_SD4_OUT_IDX
},
[5] = {
GPIO_SD5_OUT_IDX
},
[6] = {
GPIO_SD6_OUT_IDX
},
[7] = {
GPIO_SD7_OUT_IDX
}
}
};

View File

@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
struct {
const int sd_sig;
} channels[SOC_SDM_CHANNELS_PER_GROUP];
} sigma_delta_signal_conn_t;
extern const sigma_delta_signal_conn_t sigma_delta_periph_signals;
#ifdef __cplusplus
}
#endif

View File

@ -1,36 +0,0 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#include "soc/gpio_sd_reg.h"
#include "soc/gpio_sd_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
struct {
const uint32_t sd_sig;
} channels[SOC_SIGMADELTA_CHANNEL_NUM];
} sigma_delta_signal_conn_t;
extern const sigma_delta_signal_conn_t sigma_delta_periph_signals;
#ifdef __cplusplus
}
#endif

View File

@ -100,7 +100,7 @@ RISCV_DOCS = [] # type: list[str]
TWAI_DOCS = ['api-reference/peripherals/twai.rst']
SIGMADELTA_DOCS = ['api-reference/peripherals/sigmadelta.rst']
SDM_DOCS = ['api-reference/peripherals/sdm.rst']
I2S_DOCS = ['api-reference/peripherals/i2s.rst']
@ -167,10 +167,10 @@ conditional_include_dict = {'SOC_BT_SUPPORTED':BT_DOCS,
'SOC_TEMP_SENSOR_SUPPORTED':TEMP_SENSOR_DOCS,
'SOC_TWAI_SUPPORTED':TWAI_DOCS,
'SOC_I2S_SUPPORTED':I2S_DOCS,
'SOC_SIGMADELTA_SUPPORTED':SIGMADELTA_DOCS,
'SOC_RTC_MEM_SUPPORTED': RTC_MEM_DOCS,
'SOC_ADC_SUPPORTED':ADC_DOCS,
'SOC_ADC_DMA_SUPPORTED':ADC_DMA_DOCS,
'SOC_SDM_SUPPORTED':SDM_DOCS,
'esp32':ESP32_DOCS,
'esp32s2':ESP32S2_DOCS,
'esp32s3':ESP32S3_DOCS,

View File

@ -69,10 +69,10 @@ INPUT = \
$(PROJECT_PATH)/components/driver/include/driver/ledc.h \
$(PROJECT_PATH)/components/driver/include/driver/rtc_io.h \
$(PROJECT_PATH)/components/driver/include/driver/sdio_slave.h \
$(PROJECT_PATH)/components/driver/include/driver/sdm.h \
$(PROJECT_PATH)/components/driver/include/driver/sdmmc_host.h \
$(PROJECT_PATH)/components/driver/include/driver/sdmmc_types.h \
$(PROJECT_PATH)/components/driver/include/driver/sdspi_host.h \
$(PROJECT_PATH)/components/driver/include/driver/sigmadelta.h \
$(PROJECT_PATH)/components/driver/include/driver/spi_common.h \
$(PROJECT_PATH)/components/driver/include/driver/spi_master.h \
$(PROJECT_PATH)/components/driver/include/driver/spi_slave.h \
@ -163,7 +163,7 @@ INPUT = \
$(PROJECT_PATH)/components/hal/include/hal/ledc_types.h \
$(PROJECT_PATH)/components/hal/include/hal/rtc_io_types.h \
$(PROJECT_PATH)/components/hal/include/hal/sdio_slave_types.h \
$(PROJECT_PATH)/components/hal/include/hal/sigmadelta_types.h \
$(PROJECT_PATH)/components/hal/include/hal/sdm_types.h \
$(PROJECT_PATH)/components/hal/include/hal/spi_flash_types.h \
$(PROJECT_PATH)/components/hal/include/hal/spi_types.h \
$(PROJECT_PATH)/components/hal/include/hal/timer_types.h \

View File

@ -22,7 +22,7 @@ The DAC driver allows these channels to be set to arbitrary voltages.
The DAC channels can also be driven with DMA-style written sample data by the digital controller, however the driver does not supported this yet.
For other analog output options, see the :doc:`Sigma-delta Modulation module <sigmadelta>` and the :doc:`LED Control module <ledc>`. Both these modules produce high frequency PWM output, which can be hardware low-pass filtered in order to generate a lower frequency analog output.
For other analog output options, see the :doc:`Sigma-delta Modulation module <sdm>` and the :doc:`LED Control module <ledc>`. Both these modules produce high frequency PDM/PWM output, which can be hardware low-pass filtered in order to generate a lower frequency analog output.
Application Example

View File

@ -27,7 +27,7 @@ Peripherals API
:SOC_SDMMC_HOST_SUPPORTED: sdmmc_host
sdspi_host
:SOC_SDIO_SLAVE_SUPPORTED: sdio_slave
:SOC_SIGMADELTA_SUPPORTED: sigmadelta
:SOC_SDM_SUPPORTED: sdm
spi_master
spi_slave
:esp32: secure_element

View File

@ -20,19 +20,19 @@ Functional Overview
Description of the PCNT functionality is divided into the following sections:
- :ref:`allocating-resource` - covers how to allocate PCNT units and channels with properly set of configurations. It also covers how to recycle the resources when they finished working.
- :ref:`set-up-channel-actions` - covers how to configure the PCNT channel to behave on different signal edges and levels.
- :ref:`watch-points` - describes how to configure PCNT watch points (i.e., tell PCNT unit to trigger an event when the count reaches a certain value).
- :ref:`callbacks-register-event` - describes how to hook your specific code to the watch point event callback function.
- :ref:`set-glitch-filter` - describes how to enable and set the timing parameters for the internal glitch filter.
- :ref:`enable-and-disable-unit` - describes how to enable and disable the PCNT unit.
- :ref:`unit-io-control` - describes IO control functions of PCNT unit, like enable glitch filter, start and stop unit, get and clear count value.
- :ref:`managing-power` - describes what functionality will prevent the chip from going into low power mode.
- :ref:`iram-safety` - describes tips on how to make the PCNT interrupt and IO control functions work better along with a disabled cache.
- :ref:`thread-safe` - lists which APIs are guaranteed to be thread safe by the driver.
- :ref:`kconfig-option` - lists the supported Kconfig options that can be used to make a different effect on driver behavior.
- :ref:`pcnt-resource-allocation` - covers how to allocate PCNT units and channels with properly set of configurations. It also covers how to recycle the resources when they finished working.
- :ref:`pcnt-setup-channel-actions` - covers how to configure the PCNT channel to behave on different signal edges and levels.
- :ref:`pcnt-watch-points` - describes how to configure PCNT watch points (i.e., tell PCNT unit to trigger an event when the count reaches a certain value).
- :ref:`pcnt-register-event-callbacks` - describes how to hook your specific code to the watch point event callback function.
- :ref:`pcnt-set-glitch-filter` - describes how to enable and set the timing parameters for the internal glitch filter.
- :ref:`pcnt-enable-disable-unit` - describes how to enable and disable the PCNT unit.
- :ref:`pcnt-unit-io-control` - describes IO control functions of PCNT unit, like enable glitch filter, start and stop unit, get and clear count value.
- :ref:`pcnt-power-management` - describes what functionality will prevent the chip from going into low power mode.
- :ref:`pcnt-iram-safe` - describes tips on how to make the PCNT interrupt and IO control functions work better along with a disabled cache.
- :ref:`pcnt-thread-safe` - lists which APIs are guaranteed to be thread safe by the driver.
- :ref:`pcnt-kconfig-options` - lists the supported Kconfig options that can be used to make a different effect on driver behavior.
.. _allocating-resource:
.. _pcnt-resource-allocation:
Resource Allocation
^^^^^^^^^^^^^^^^^^^
@ -91,7 +91,7 @@ If a previously created PCNT channel is no longer needed, it's recommended to re
pcnt_channel_handle_t pcnt_chan = NULL;
ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan));
.. _set-up-channel-actions:
.. _pcnt-setup-channel-actions:
Set Up Channel Actions
^^^^^^^^^^^^^^^^^^^^^^
@ -108,12 +108,12 @@ The PCNT will increase/decrease/hold its internal count value when the input pul
// keep the counting mode when the control signal is high level, and reverse the counting mode when the control signal is low level
ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
.. _watch-points:
.. _pcnt-watch-points:
Watch Points
^^^^^^^^^^^^
Each PCNT unit can be configured to watch several different values that you're interested in. The value to be watched is also called **Watch Point**. The watch point itself can't exceed the range set in :cpp:type:`pcnt_unit_config_t` by :cpp:member:`pcnt_unit_config_t::low_limit` and :cpp:member:`pcnt_unit_config_t::high_limit`. When the counter reaches either watch point, a watch event will be triggered and notify you by interrupt if any watch event callback has ever registered in :cpp:func:`pcnt_unit_register_event_callbacks`. See :ref:`callbacks-register-event` for how to register event callbacks.
Each PCNT unit can be configured to watch several different values that you're interested in. The value to be watched is also called **Watch Point**. The watch point itself can't exceed the range set in :cpp:type:`pcnt_unit_config_t` by :cpp:member:`pcnt_unit_config_t::low_limit` and :cpp:member:`pcnt_unit_config_t::high_limit`. When the counter reaches either watch point, a watch event will be triggered and notify you by interrupt if any watch event callback has ever registered in :cpp:func:`pcnt_unit_register_event_callbacks`. See :ref:`pcnt-register-event-callbacks` for how to register event callbacks.
The watch point can be added and removed by :cpp:func:`pcnt_unit_add_watch_point` and :cpp:func:`pcnt_unit_remove_watch_point`. The commonly used watch points are: **zero cross**, **maximum / minimum count** and other threshold values. The number of available watch point is limited, :cpp:func:`pcnt_unit_add_watch_point` will return error :c:macro:`ESP_ERR_NOT_FOUND` if it can't find any free hardware resource to save the watch point. You can't add the same watch point for multiple times, otherwise it will return error :c:macro:`ESP_ERR_INVALID_STATE`.
@ -126,7 +126,7 @@ It is recommended to remove the unused watch point by :cpp:func:`pcnt_unit_remov
// add high limit watch point
ESP_ERROR_CHECK(pcnt_unit_add_watch_point(pcnt_unit, EXAMPLE_PCNT_HIGH_LIMIT));
.. _callbacks-register-event:
.. _pcnt-register-event-callbacks:
Register Event Callbacks
^^^^^^^^^^^^^^^^^^^^^^^^
@ -146,7 +146,7 @@ Registering callback function will result in lazy installation of interrupt serv
.. code:: c
static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, pcnt_watch_event_data_t *edata, void *user_ctx)
static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx)
{
BaseType_t high_task_wakeup;
QueueHandle_t queue = (QueueHandle_t)user_ctx;
@ -162,7 +162,7 @@ Registering callback function will result in lazy installation of interrupt serv
QueueHandle_t queue = xQueueCreate(10, sizeof(int));
ESP_ERROR_CHECK(pcnt_unit_register_event_callbacks(pcnt_unit, &cbs, queue));
.. _set-glitch-filter:
.. _pcnt-set-glitch-filter:
Set Glitch Filter
^^^^^^^^^^^^^^^^^
@ -177,7 +177,7 @@ This function should be called when the the unit is in the init state. Otherwise
.. note::
The glitch filter is clocked from APB. For the counter not to miss any pulses, the maximum glitch width should be longer than one APB_CLK cycle (usually 12.5 ns if APB equals 80MHz). As the APB frequency would be changed after DFS (Dynamic Frequency Scaling) enabled, which means the filter won't work as expect in that case. So the driver will install a PM lock for PCNT unit during the first time you enable the glitch filter. For more information related to power management strategy used in PCNT driver, please see :ref:`managing-power`.
The glitch filter is clocked from APB. For the counter not to miss any pulses, the maximum glitch width should be longer than one APB_CLK cycle (usually 12.5 ns if APB equals 80MHz). As the APB frequency would be changed after DFS (Dynamic Frequency Scaling) enabled, which means the filter won't work as expect in that case. So the driver will install a PM lock for PCNT unit during the first time you enable the glitch filter. For more information related to power management strategy used in PCNT driver, please see :ref:`pcnt-power-management`.
.. code:: c
@ -186,7 +186,7 @@ This function should be called when the the unit is in the init state. Otherwise
};
ESP_ERROR_CHECK(pcnt_unit_set_glitch_filter(pcnt_unit, &filter_config));
.. _enable-and-disable-unit:
.. _pcnt-enable-disable-unit:
Enable and Disable Unit
^^^^^^^^^^^^^^^^^^^^^^^
@ -195,7 +195,7 @@ Before doing IO control to the PCNT unit, you need to enable it first, by callin
* switch the PCNT driver state from **init** to **enable**.
* enable the interrupt service if it has been lazy installed in :cpp:func:`pcnt_unit_register_event_callbacks`.
* acquire a proper power management lock if it has been lazy installed in :cpp:func:`pcnt_unit_set_glitch_filter`. See also :ref:`managing-power` for more information.
* acquire a proper power management lock if it has been lazy installed in :cpp:func:`pcnt_unit_set_glitch_filter`. See also :ref:`pcnt-power-management` for more information.
On the contrary, calling :cpp:func:`pcnt_unit_disable` will do the opposite, that is, put the PCNT driver back to the **init** state, disable the interrupts service and release the power management lock.
@ -203,7 +203,7 @@ On the contrary, calling :cpp:func:`pcnt_unit_disable` will do the opposite, tha
ESP_ERROR_CHECK(pcnt_unit_enable(pcnt_unit));
.. _unit-io-control:
.. _pcnt-unit-io-control:
Unit IO Control
^^^^^^^^^^^^^^^
@ -234,7 +234,7 @@ You can check current count value at any time by calling :cpp:func:`pcnt_unit_ge
int pulse_count = 0;
ESP_ERROR_CHECK(pcnt_unit_get_count(pcnt_unit, &pulse_count));
.. _managing-power:
.. _pcnt-power-management:
Power Management
^^^^^^^^^^^^^^^^
@ -243,7 +243,7 @@ When power management is enabled (i.e. :ref:`CONFIG_PM_ENABLE` is on), the syste
However, the driver can prevent the system from changing APB frequency by acquiring a power management lock of type :cpp:enumerator:`ESP_PM_APB_FREQ_MAX`. Whenever you enable the glitch filter by :cpp:func:`pcnt_unit_set_glitch_filter`, the driver will guarantee that the power management lock is acquired after the PCNT unit is enabled by :cpp:func:`pcnt_unit_enable`. Likewise, the driver releases the lock after :cpp:func:`pcnt_unit_disable` is called.
.. _iram-safety:
.. _pcnt-iram-safe:
IRAM Safe
^^^^^^^^^
@ -265,7 +265,7 @@ There's another Kconfig option :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` that can put
- :cpp:func:`pcnt_unit_clear_count`
- :cpp:func:`pcnt_unit_get_count`
.. _thread-safe:
.. _pcnt-thread-safe:
Thread Safety
^^^^^^^^^^^^^
@ -280,13 +280,13 @@ The following functions are allowed to run under ISR context, the driver uses a
Other functions that take the :cpp:type:`pcnt_unit_handle_t` and :cpp:type:`pcnt_channel_handle_t` as the first positional parameter, are not treated as thread safe. This means you should avoid calling them from multiple tasks.
.. _kconfig-option:
.. _pcnt-kconfig-options:
Kconfig Options
^^^^^^^^^^^^^^^
- :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` controls where to place the PCNT control functions (IRAM or Flash), see :ref:`iram-safety` for more information.
- :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` controls whether the default ISR handler can work when cache is disabled, see :ref:`iram-safety` for more information.
- :ref:`CONFIG_PCNT_CTRL_FUNC_IN_IRAM` controls where to place the PCNT control functions (IRAM or Flash), see :ref:`pcnt-iram-safe` for more information.
- :ref:`CONFIG_PCNT_ISR_IRAM_SAFE` controls whether the default ISR handler can work when cache is disabled, see :ref:`pcnt-iram-safe` for more information.
- :ref:`CONFIG_PCNT_ENABLE_DEBUG_LOG` is used to enabled the debug log output. Enable this option will increase the firmware binary size.
Application Examples

View File

@ -0,0 +1,132 @@
Sigma-Delta Modulation (SDM)
============================
Introduction
------------
{IDF_TARGET_NAME} has a second-order sigma-delta modulator, which can generate independent PDM pulses to multiple channels. Please refer to the TRM to check how many hardware channels are available. [1]_
Typically, a Sigma-Delta modulated channel can be used in scenarios like:
- LED dimming
- Simple DAC (8-bit), with the help of an active RC low-pass filter
- Class D amplifier, with the help of a half-bridge or full-bridge circuit plus an LC low-pass filter
Functional Overview
-------------------
The following sections of this document cover the typical steps to install and operate a SDM channel:
- `Resource Allocation <#resource-allocation>`__ - covers which parameters should be set up to get a channel handle and how to recycle the resources when it finishes working.
- `Enable and Disable Channel <#enable-and-disable-channel>`__ - covers how to enable and disable the channel.
- `Set Equivalent Duty Cycle <#set-equivalent-duty-cycle>`__ - describes how to set the equivalent duty cycle of the PDM pulses.
- `Power Management <#power-management>`__ - describes how different source clock selections can affect power consumption.
- `IRAM Safe <#iram-safe>`__ - lists which functions are supposed to work even when the cache is disabled.
- `Thread Safety <#thread-safety>`__ - lists which APIs are guaranteed to be thread safe by the driver.
- `Kconfig Options <#kconfig-options>`__ - lists the supported Kconfig options that can be used to make a different effect on driver behavior.
Resource Allocation
^^^^^^^^^^^^^^^^^^^
A SDM channel is represented by :cpp:type:`sdm_channel_handle_t`. Each channel is capable to output the binary, hardware generated signal with the sigma-delta modulation. The driver manages all available channels in a pool, so that users don't need to manually assign a fixed channel to a GPIO.
To install a SDM channel, you should call :cpp:func:`sdm_new_channel` to get a channel handle. Channel specific configurations are passed in the :cpp:type:`sdm_config_t` structure:
- :cpp:member:`sdm_config_t::gpio_num` sets the GPIO that the PDM pulses will output from
- :cpp:member:`sdm_config_t::clk_src` selects the source clock for the SDM module. Note that, all channels should select the same clock source.
- :cpp:member:`sdm_config_t::sample_rate_hz` sets the sample rate of the SDM module.
- :cpp:member:`sdm_config_t::invert_out` sets whether to invert the output signal.
- :cpp:member:`sdm_config_t::io_loop_back` is for debugging purposes only. It enables both the GPIO's input and output ability through the GPIO matrix peripheral.
The function :cpp:func:`sdm_new_channel` can fail due to various errors such as insufficient memory, invalid arguments, etc. Specifically, when there are no more free channels (i.e. all hardware SDM channels have been used up), then :c:macro:`ESP_ERR_NOT_FOUND` will be returned.
If a previously created SDM channel is no longer required, you should recycle it by calling :cpp:func:`sdm_del_channel`. It allows the underlying HW channel to be used for other purposes. Before deleting a SDM channel handle, you should disable it by :cpp:func:`sdm_channel_disable` in advance or make sure it has not enabled yet by :cpp:func:`sdm_channel_enable`.
Creating a SDM Channel with Sample Rate of 1MHz
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: c
sdm_channel_handle_t chan = NULL;
sdm_config_t config = {
.clk_src = SDM_CLK_SRC_DEFAULT,
.sample_rate_hz = 1 * 1000 * 1000,
.gpio_num = 0,
};
ESP_ERROR_CHECK(sdm_new_channel(&config, &chan));
Enable and Disable Channel
^^^^^^^^^^^^^^^^^^^^^^^^^^
Before doing further IO control to the SDM channel, you should enable it first, by calling :cpp:func:`sdm_channel_enable`. Internally, this function will:
* switch the channel state from **init** to **enable**
* acquire a proper power management lock is a specific clock source (e.g. APB clock) is selected. See also `Power management <#power-management>`__ for more information.
On the contrary, calling :cpp:func:`sdm_channel_disable` will do the opposite, that is, put the channel back to the **init** state and release the power management lock.
Set Equivalent Duty Cycle
^^^^^^^^^^^^^^^^^^^^^^^^^
For the output PDM signals, the duty cycle refers to the percentage of high level cycles to the whole statistical period. The average output voltage from the channel is calculated by ``Vout = VDD_IO / 256 * duty + VDD_IO / 2``. Thus the range of the ``duty`` input parameter of :cpp:func:`sdm_channel_set_duty` is from -128 to 127 (eight bit signed integer). For example,if zero value is set, then the output signal's duty will be about 50%.
Power Management
^^^^^^^^^^^^^^^^
When power management is enabled (i.e. :ref:`CONFIG_PM_ENABLE` is on), the system will adjust the APB frequency before going into light sleep, thus potentially changing the sample rate of the sigma-delta modulator.
However, the driver can prevent the system from changing APB frequency by acquiring a power management lock of type :cpp:enumerator:`ESP_PM_APB_FREQ_MAX`. Whenever the driver creates a SDM channel instance that has selected :cpp:enumerator:`SDM_CLK_SRC_APB` as its clock source, the driver will guarantee that the power management lock is acquired when enable the channel by :cpp:func:`sdm_channel_enable`. Likewise, the driver releases the lock when :cpp:func:`sdm_channel_disable` is called for that channel.
IRAM Safe
^^^^^^^^^
There's a Kconfig option :ref:`CONFIG_SDM_CTRL_FUNC_IN_IRAM` that can put commonly used IO control functions into IRAM as well. So that these functions can also be executable when the cache is disabled. These IO control functions are listed as follows:
- :cpp:func:`sdm_channel_set_duty`
Thread Safety
^^^^^^^^^^^^^
The factory function :cpp:func:`sdm_new_channel` is guaranteed to be thread safe by the driver, which means, user can call it from different RTOS tasks without protection by extra locks.
The following functions are allowed to run under ISR context, the driver uses a critical section to prevent them being called concurrently in both task and ISR.
- :cpp:func:`sdm_channel_set_duty`
Other functions that take the :cpp:type:`sdm_channel_handle_t` as the first positional parameter, are not treated as thread safe. Which means the user should avoid calling them from multiple tasks.
Kconfig Options
^^^^^^^^^^^^^^^
- :ref:`CONFIG_SDM_CTRL_FUNC_IN_IRAM` controls where to place the SDM channel control functions (IRAM or Flash), see `IRAM Safe <#iram-safe>`__ for more information.
- :ref:`CONFIG_SDM_ENABLE_DEBUG_LOG` is used to enabled the debug log output. Enable this option will increase the firmware binary size.
Convert to analog signal (Optional)
-----------------------------------
Typically, if the sigma-delta signal is connected to an LED, you don't have to add any filter between them (because our eyes are a low pass filter naturally). However, if you want to check the real voltage or watch the analog waveform, you need to design an analog low pass filter. Also, it is recommended to use an active filter instead of a passive filter to gain better isolation and not lose too much voltage.
For example, you can take the following `Sallen-Key topology Low Pass Filter`_ as a reference.
.. figure:: ../../../_static/typical_sallenkey_LP_filter.png
:align: center
:alt: Sallen-Key Low Pass Filter
:figclass: align-center
Sallen-Key Low Pass Filter
Application Example
-------------------
* LED driven by a GPIO that is modulated with Sigma-Delta: :example:`peripherals/sigma_delta`.
API Reference
-------------
.. include-build-file:: inc/sdm.inc
.. include-build-file:: inc/sdm_types.inc
.. [1]
Different ESP chip series might have different numbers of SDM channels. Please refer to Chapter `GPIO and IOMUX <{IDF_TARGET_TRM_EN_URL}#iomuxgpio>`__ in {IDF_TARGET_NAME} Technical Reference Manual for more details. The driver won't forbid you from applying for more channels, but it will return error when all available hardware resources are used up. Please always check the return value when doing resource allocation (e.g. :cpp:func:`sdm_new_channel`).
.. _Sallen-Key topology Low Pass Filter: https://en.wikipedia.org/wiki/Sallen%E2%80%93Key_topology

View File

@ -1,53 +0,0 @@
Sigma-delta Modulation
======================
{IDF_TARGET_SIGMA_DELTA_MODULATION_CHANNEL_NUM:default="8", esp32c3="4"}
Introduction
------------
{IDF_TARGET_NAME} has a second-order sigma-delta modulation module. This driver configures the channels of the sigma-delta module.
Functionality Overview
----------------------
There are {IDF_TARGET_SIGMA_DELTA_MODULATION_CHANNEL_NUM} independent sigma-delta modulation channels identified with :cpp:type:`sigmadelta_channel_t`. Each channel is capable to output the binary, hardware generated signal with the sigma-delta modulation.
Selected channel should be set up by providing configuration parameters in :cpp:type:`sigmadelta_config_t` and then applying this configuration with :cpp:func:`sigmadelta_config`.
Another option is to call individual functions, that will configure all required parameters one by one:
* **Prescaler** of the sigma-delta generator - :cpp:func:`sigmadelta_set_prescale`
* **Duty** of the output signal - :cpp:func:`sigmadelta_set_duty`
* **GPIO pin** to output modulated signal - :cpp:func:`sigmadelta_set_pin`
The range of the 'duty' input parameter of :cpp:func:`sigmadelta_set_duty` is from -128 to 127 (eight bit signed integer). If zero value is set, then the output signal's duty will be about 50%, see description of :cpp:func:`sigmadelta_set_duty`.
Convert to analog signal (Optional)
-----------------------------------
Typically, if the sigma-delta signal is connected to an LED, you don't have to add any filter between them (because our eyes are a low pass filter naturally). However, if you want to check the real voltage or watch the analog waveform, you need to design an analog low pass filter. Also, it is recommended to use an active filter instead of a passive filter to gain better isolation and not lose too much voltage.
For example, you can take the following `Sallen-Key topology Low Pass Filter`_ as a reference.
.. figure:: ../../../_static/typical_sallenkey_LP_filter.png
:align: center
:alt: Sallen-Key Low Pass Filter
:figclass: align-center
Sallen-Key Low Pass Filter
Application Example
-------------------
Sigma-delta Modulation example: :example:`peripherals/sigmadelta`.
API Reference
-------------
.. include-build-file:: inc/sigmadelta.inc
.. include-build-file:: inc/sigmadelta_types.inc
.. _Sallen-Key topology Low Pass Filter: https://en.wikipedia.org/wiki/Sallen%E2%80%93Key_topology

Some files were not shown because too many files have changed in this diff Show More