diff --git a/components/driver/gpio.c b/components/driver/gpio.c index 4bdd716f36..1a38620dbb 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -292,6 +292,7 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig) } if ((pGPIOConfig->mode) & GPIO_MODE_DEF_OUTPUT) { output_en = 1; + gpio_matrix_out(io_num, SIG_GPIO_OUT_IDX, 0, 0); gpio_output_enable(io_num); } else { gpio_output_disable(io_num); diff --git a/components/driver/include/driver/sigmadelta.h b/components/driver/include/driver/sigmadelta.h new file mode 100644 index 0000000000..db167837b8 --- /dev/null +++ b/components/driver/include/driver/sigmadelta.h @@ -0,0 +1,108 @@ +// 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 + +// 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 __DRIVER_SIGMADELTA_H__ +#define __DRIVER_SIGMADELTA_H__ +#include +#include "soc/gpio_sd_struct.h" +#include "soc/gpio_sd_reg.h" +#include "driver/gpio.h" + +#ifdef _cplusplus +extern "C" { +#endif + +/** + * @brief Sigma-delta channel list + */ +typedef enum{ + SIGMADELTA_CHANNEL_0 = 0, /*!< Sigma-delta channel0 */ + SIGMADELTA_CHANNEL_1 = 1, /*!< Sigma-delta channel1 */ + SIGMADELTA_CHANNEL_2 = 2, /*!< Sigma-delta channel2 */ + SIGMADELTA_CHANNEL_3 = 3, /*!< Sigma-delta channel3 */ + SIGMADELTA_CHANNEL_4 = 4, /*!< Sigma-delta channel4 */ + SIGMADELTA_CHANNEL_5 = 5, /*!< Sigma-delta channel5 */ + SIGMADELTA_CHANNEL_6 = 6, /*!< Sigma-delta channel6 */ + SIGMADELTA_CHANNEL_7 = 7, /*!< Sigma-delta channel7 */ + SIGMADELTA_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. */ + uint8_t sigmadelta_gpio; /*!< Sigma-delta output io number, refer to gpio.h for more details. */ +} sigmadelta_config_t; + +/** + * @brief Configure Sigma-delta channel + * + * @param config Pointer of Sigma-delta channel configuration struct + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t sigmadelta_config(sigmadelta_config_t *config); + +/** + * @brief Set Sigma-delta channel duty. + * + * This function is used to set Sigma-delta channel duty, + * If you add a capacitor between the output pin and ground, + * the average output voltage Vdc = VDDIO / 256 * duty + VDDIO/2, VDDIO is power supply voltage. + * + * @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. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t sigmadelta_set_duty(sigmadelta_channel_t channel, int8_t duty); + +/** + * @brief Set Sigma-delta channel's clock pre-scale value. + * The source clock is APP_CLK, 80MHz. The clock frequency of the sigma-delta channel is APP_CLK / pre_scale + * + * @param channel Sigma-delta channel number + * @param prescale The divider of source clock, ranges from 0 to 255 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t sigmadelta_set_prescale(sigmadelta_channel_t channel, uint8_t prescale); + +/** + * @brief Set Sigma-delta signal output pin + * + * @param channel Sigma-delta channel number + * @param gpio_num GPIO number of output pin. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t sigmadelta_set_pin(sigmadelta_channel_t channel, gpio_num_t gpio_num); + +#ifdef _cplusplus +} +#endif + +#endif diff --git a/components/driver/sigmadelta.c b/components/driver/sigmadelta.c new file mode 100644 index 0000000000..09969e6631 --- /dev/null +++ b/components/driver/sigmadelta.c @@ -0,0 +1,61 @@ +// 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 + +// 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 "esp_log.h" +#include "soc/soc.h" +#include "driver/periph_ctrl.h" +#include "driver/sigmadelta.h" + +static const char* SIGMADELTA_TAG = "SIGMADELTA"; +#define SIGMADELTA_CHANNEL_ERR_STR "SIGMADELTA CHANNEL ERROR" +#define SIGMADELTA_IO_ERR_STR "SIGMADELTA GPIO NUM ERROR" + +#define SIGMADELTA_CHECK(a,str,ret_val) if(!(a)) { \ + ESP_LOGE(SIGMADELTA_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \ + return (ret_val); \ + } + +esp_err_t sigmadelta_config(sigmadelta_config_t *config) +{ + SIGMADELTA_CHECK(config->channel < SIGMADELTA_CHANNEL_MAX, SIGMADELTA_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + SIGMADELTA_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(config->sigmadelta_gpio), SIGMADELTA_IO_ERR_STR, ESP_ERR_INVALID_ARG); + sigmadelta_set_duty(config->channel, config->sigmadelta_duty); + sigmadelta_set_prescale(config->channel, config->sigmadelta_prescale); + sigmadelta_set_pin(config->channel, config->sigmadelta_gpio); + return ESP_OK; +} + +esp_err_t sigmadelta_set_duty(sigmadelta_channel_t channel, int8_t duty) +{ + SIGMADELTA_CHECK(channel < SIGMADELTA_CHANNEL_MAX, SIGMADELTA_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + SIGMADELTA.channel[channel].duty = duty; + return ESP_OK; +} + +esp_err_t sigmadelta_set_prescale(sigmadelta_channel_t channel, uint8_t prescale) +{ + SIGMADELTA_CHECK(channel < SIGMADELTA_CHANNEL_MAX, SIGMADELTA_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + SIGMADELTA.channel[channel].prescale = prescale; + return ESP_OK; +} + +esp_err_t sigmadelta_set_pin(sigmadelta_channel_t channel, gpio_num_t gpio_num) +{ + SIGMADELTA_CHECK(channel < SIGMADELTA_CHANNEL_MAX, SIGMADELTA_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + SIGMADELTA_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), SIGMADELTA_IO_ERR_STR, ESP_ERR_INVALID_ARG); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); + gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); + gpio_matrix_out(gpio_num, GPIO_SD0_OUT_IDX + channel, 0, 0); + return ESP_OK; +} + diff --git a/components/esp32/include/soc/gpio_sig_map.h b/components/esp32/include/soc/gpio_sig_map.h index dad22f92f8..4d2943fb9f 100644 --- a/components/esp32/include/soc/gpio_sig_map.h +++ b/components/esp32/include/soc/gpio_sig_map.h @@ -418,5 +418,5 @@ #define SIG_IN_FUNC226_IDX 226 #define SIG_IN_FUNC227_IDX 227 #define SIG_IN_FUNC228_IDX 228 - +#define SIG_GPIO_OUT_IDX 256 #endif /* _SOC_GPIO_SIG_MAP_H_ */ diff --git a/docs/api/sigmadelta.rst b/docs/api/sigmadelta.rst new file mode 100644 index 0000000000..acfdaaa27d --- /dev/null +++ b/docs/api/sigmadelta.rst @@ -0,0 +1,51 @@ +Sigma-delta Modulation +======== + +Overview +-------- + +ESP32 has a second-order sigma-delta modulation module. +This driver configures the channels of the sigma-delta module. + +Application Example +------------------- + +Sigma-delta Modulation example: `examples/14_sigmadelta `_. + +API Reference +------------- + +Header Files +^^^^^^^^^^^^ + + * `driver/sigmadelta.h `_ + + +Macros +^^^^^^ + + +Type Definitions +^^^^^^^^^^^^^^^^ + + +Enumerations +^^^^^^^^^^^^ + +.. doxygenenum:: sigmadelta_channel_t + +Structures +^^^^^^^^^^ + +.. doxygenstruct:: sigmadelta_config_t + :members: + + +Functions +^^^^^^^^^ + +.. doxygenfunction:: sigmadelta_config +.. doxygenfunction:: sigmadelta_set_duty +.. doxygenfunction:: sigmadelta_set_prescale +.. doxygenfunction:: sigmadelta_set_pin + diff --git a/docs/index.rst b/docs/index.rst old mode 100755 new mode 100644 index 901187d80f..ba25b49691 --- a/docs/index.rst +++ b/docs/index.rst @@ -108,6 +108,7 @@ Contents: Remote Control Timer Pulse Counter + Sigma-delta Modulation SPI Flash and Partition APIs Logging Non-Volatile Storage diff --git a/examples/19_sigmadelta/Makefile b/examples/19_sigmadelta/Makefile new file mode 100644 index 0000000000..75f7111ab2 --- /dev/null +++ b/examples/19_sigmadelta/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := sigmadelta + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/19_sigmadelta/main/component.mk b/examples/19_sigmadelta/main/component.mk new file mode 100644 index 0000000000..4d3b30caf3 --- /dev/null +++ b/examples/19_sigmadelta/main/component.mk @@ -0,0 +1,5 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/examples/19_sigmadelta/main/sigmadelta_test.c b/examples/19_sigmadelta/main/sigmadelta_test.c new file mode 100644 index 0000000000..92bc6e0a83 --- /dev/null +++ b/examples/19_sigmadelta/main/sigmadelta_test.c @@ -0,0 +1,54 @@ +/* Sigma-delta Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "driver/sigmadelta.h" + +/* + * This test code intended to configure sigma-delta and set GPIO4 as signal output pin. + * If you connect this GPIO4 with an LED, you will see the LED blinking slowly. + */ + +/** + * @brief Sigma-delta initialization. + */ +static void sigmadelta_init(void) +{ + sigmadelta_config_t sigmadelta_cfg = { + /* Sigma-delta channel0*/ + .channel = SIGMADELTA_CHANNEL_0, + /* Sigma-delta set duty 10*/ + .sigmadelta_duty = 10, + /* Set prescale 30 */ + .sigmadelta_prescale = 80, + /*select GPIO4 as output_io */ + .sigmadelta_gpio = 4, + }; + sigmadelta_config(&sigmadelta_cfg); +} + +/** + * @brief Sigma-delta test to change duty of output signal. + */ +void app_main() +{ + sigmadelta_init(); + int8_t duty = 0; + int inc = 1; + while(1) { + sigmadelta_set_duty(SIGMADELTA_CHANNEL_0, duty); + /*by changing delay time, you can change the blink frequency of LED. */ + vTaskDelay(10 / portTICK_RATE_MS); + + duty += inc; + if(duty == 127 || duty == -127) inc = (-1) * inc; + } +}