1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "esp_log.h"
8 #include "esp_check.h"
9 #include "esp_err.h"
10 #include "esp_heap_caps.h"
11 #include "driver/gpio.h"
12 #include "driver/sigmadelta_types_legacy.h"
13 #include "soc/sdm_periph.h"
14 #include "hal/sdm_hal.h"
15 #include "hal/sdm_ll.h"
16 #include "hal/gpio_hal.h"
17 #include "esp_rom_gpio.h"
18 
19 static const char *TAG = "sdm(legacy)";
20 
21 #define SIGMADELTA_CHECK(a,str,ret_val) ESP_RETURN_ON_FALSE(a, ret_val, TAG, "%s", str)
22 
23 typedef struct {
24     sdm_hal_context_t hal;        /*!< SIGMADELTA hal context*/
25 } sigmadelta_obj_t;
26 
27 static sigmadelta_obj_t *p_sigmadelta_obj[SIGMADELTA_PORT_MAX] = {0};
28 
29 #define SIGMADELTA_OBJ_CHECK(sigmadelta_port) { \
30     SIGMADELTA_CHECK((sigmadelta_port < SIGMADELTA_PORT_MAX), "sigmadelta port error", ESP_ERR_INVALID_ARG); \
31     SIGMADELTA_CHECK((p_sigmadelta_obj[sigmadelta_port]), "sigmadelta driver has not been initialized", ESP_ERR_INVALID_STATE); \
32 }
33 
_sigmadelta_set_duty(sigmadelta_port_t sigmadelta_port,sigmadelta_channel_t channel,int8_t duty)34 static inline esp_err_t _sigmadelta_set_duty(sigmadelta_port_t sigmadelta_port, sigmadelta_channel_t channel, int8_t duty)
35 {
36     SIGMADELTA_OBJ_CHECK(sigmadelta_port);
37 
38     sdm_ll_set_pulse_density(p_sigmadelta_obj[sigmadelta_port]->hal.dev, channel, duty);
39     return ESP_OK;
40 }
41 
_sigmadelta_set_prescale(sigmadelta_port_t sigmadelta_port,sigmadelta_channel_t channel,uint8_t prescale)42 static inline esp_err_t _sigmadelta_set_prescale(sigmadelta_port_t sigmadelta_port, sigmadelta_channel_t channel, uint8_t prescale)
43 {
44     SIGMADELTA_OBJ_CHECK(sigmadelta_port);
45 
46     sdm_ll_set_prescale(p_sigmadelta_obj[sigmadelta_port]->hal.dev, channel, prescale + 1);
47     return ESP_OK;
48 }
49 
_sigmadelta_set_pin(sigmadelta_port_t sigmadelta_port,sigmadelta_channel_t channel,gpio_num_t gpio_num)50 static inline esp_err_t _sigmadelta_set_pin(sigmadelta_port_t sigmadelta_port, sigmadelta_channel_t channel, gpio_num_t gpio_num)
51 {
52     SIGMADELTA_OBJ_CHECK(sigmadelta_port);
53 
54     gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
55     gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
56     esp_rom_gpio_connect_out_signal(gpio_num, sigma_delta_periph_signals.channels[channel].sd_sig, 0, 0);
57     return ESP_OK;
58 }
59 
_sigmadelta_config(sigmadelta_port_t sigmadelta_port,const sigmadelta_config_t * config)60 static inline esp_err_t _sigmadelta_config(sigmadelta_port_t sigmadelta_port, const sigmadelta_config_t *config)
61 {
62     SIGMADELTA_OBJ_CHECK(sigmadelta_port);
63 
64     _sigmadelta_set_duty(sigmadelta_port, config->channel, config->sigmadelta_duty);
65     _sigmadelta_set_prescale(sigmadelta_port, config->channel, config->sigmadelta_prescale);
66     _sigmadelta_set_pin(sigmadelta_port, config->channel, config->sigmadelta_gpio);
67     return ESP_OK;
68 }
69 
sigmadelta_deinit(sigmadelta_port_t sigmadelta_port)70 esp_err_t sigmadelta_deinit(sigmadelta_port_t sigmadelta_port)
71 {
72     SIGMADELTA_OBJ_CHECK(sigmadelta_port);
73 
74     heap_caps_free(p_sigmadelta_obj[sigmadelta_port]);
75     p_sigmadelta_obj[sigmadelta_port] = NULL;
76     return ESP_OK;
77 }
78 
sigmadelta_init(sigmadelta_port_t sigmadelta_port)79 esp_err_t sigmadelta_init(sigmadelta_port_t sigmadelta_port)
80 {
81     SIGMADELTA_CHECK((sigmadelta_port < SIGMADELTA_PORT_MAX), "sigmadelta_port error", ESP_ERR_INVALID_ARG);
82     SIGMADELTA_CHECK((p_sigmadelta_obj[sigmadelta_port]) == NULL, "sigmadelta driver already initialized", ESP_ERR_INVALID_STATE);
83 
84     p_sigmadelta_obj[sigmadelta_port] = (sigmadelta_obj_t *) heap_caps_calloc(1, sizeof(sigmadelta_obj_t), MALLOC_CAP_DEFAULT);
85 
86     if (p_sigmadelta_obj[sigmadelta_port] == NULL) {
87         ESP_LOGE(TAG, "TAG driver malloc error");
88         return ESP_FAIL;
89     }
90 
91     sdm_hal_init(&(p_sigmadelta_obj[sigmadelta_port]->hal), sigmadelta_port);
92     sdm_ll_enable_clock(p_sigmadelta_obj[sigmadelta_port]->hal.dev, true);
93     return ESP_OK;
94 }
95 
96 // TODO: The following functions are wrappers, for compatibility with current API.
97 
sigmadelta_set_duty(sigmadelta_channel_t channel,int8_t duty)98 esp_err_t sigmadelta_set_duty(sigmadelta_channel_t channel, int8_t duty)
99 {
100     SIGMADELTA_CHECK(channel < SIGMADELTA_CHANNEL_MAX, "sigmadelta channel error", ESP_ERR_INVALID_ARG);
101     return _sigmadelta_set_duty(SIGMADELTA_PORT_0, channel, duty);
102 }
103 
sigmadelta_set_prescale(sigmadelta_channel_t channel,uint8_t prescale)104 esp_err_t sigmadelta_set_prescale(sigmadelta_channel_t channel, uint8_t prescale)
105 {
106     SIGMADELTA_CHECK(channel < SIGMADELTA_CHANNEL_MAX, "sigmadelta channel error", ESP_ERR_INVALID_ARG);
107     return _sigmadelta_set_prescale(SIGMADELTA_PORT_0, channel, prescale);
108 }
109 
sigmadelta_set_pin(sigmadelta_channel_t channel,gpio_num_t gpio_num)110 esp_err_t sigmadelta_set_pin(sigmadelta_channel_t channel, gpio_num_t gpio_num)
111 {
112     SIGMADELTA_CHECK(channel < SIGMADELTA_CHANNEL_MAX, "sigmadelta channel error", ESP_ERR_INVALID_ARG);
113     SIGMADELTA_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "sigmadelta gpio num error", ESP_ERR_INVALID_ARG);
114     return _sigmadelta_set_pin(SIGMADELTA_PORT_0, channel, gpio_num);
115 }
116 
sigmadelta_config(const sigmadelta_config_t * config)117 esp_err_t sigmadelta_config(const sigmadelta_config_t *config)
118 {
119     SIGMADELTA_CHECK(config->channel < SIGMADELTA_CHANNEL_MAX, "sigmadelta channel error", ESP_ERR_INVALID_ARG);
120     SIGMADELTA_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(config->sigmadelta_gpio), "sigmadelta gpio num error", ESP_ERR_INVALID_ARG);
121     esp_err_t ret;
122 
123     if ((p_sigmadelta_obj[SIGMADELTA_PORT_0]) == NULL) {
124         ret = sigmadelta_init(SIGMADELTA_PORT_0);
125         if (ret != ESP_OK) {
126             return ret;
127         }
128     }
129     return _sigmadelta_config(SIGMADELTA_PORT_0, config);
130 }
131