Skip to content

Implement SigmaDelta based on ESP-IDF API #6053

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 34 additions & 77 deletions cores/esp32/esp32-hal-sigmadelta.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,121 +12,78 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include "esp32-hal.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp32-hal-matrix.h"
#include "soc/gpio_sd_reg.h"
#include "soc/gpio_sd_struct.h"

#include "esp_system.h"
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/ets_sys.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
#else // ESP32 Before IDF 4.0
#include "rom/ets_sys.h"
#endif

#include "esp32-hal.h"
#include "soc/soc_caps.h"
#include "driver/sigmadelta.h"

#if CONFIG_DISABLE_HAL_LOCKS
#define SD_MUTEX_LOCK()
#define SD_MUTEX_UNLOCK()
#else
#define SD_MUTEX_LOCK() do {} while (xSemaphoreTake(_sd_sys_lock, portMAX_DELAY) != pdPASS)
#define SD_MUTEX_UNLOCK() xSemaphoreGive(_sd_sys_lock)
xSemaphoreHandle _sd_sys_lock;
#endif
static uint8_t duty_set[SOC_SIGMADELTA_CHANNEL_NUM] = {0};
static uint32_t prescaler_set[SOC_SIGMADELTA_CHANNEL_NUM] = {0};

static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
if(old_apb == new_apb){
return;
}
uint32_t iarg = (uint32_t)arg;
uint8_t channel = iarg;
if(ev_type == APB_BEFORE_CHANGE){
SIGMADELTA.cg.clk_en = 0;
} else {
if(ev_type == APB_AFTER_CHANGE){
old_apb /= 1000000;
new_apb /= 1000000;
SD_MUTEX_LOCK();
uint32_t old_prescale = SIGMADELTA.channel[channel].prescale + 1;
SIGMADELTA.channel[channel].prescale = ((new_apb * old_prescale) / old_apb) - 1;
SIGMADELTA.cg.clk_en = 0;
SIGMADELTA.cg.clk_en = 1;
SD_MUTEX_UNLOCK();
uint32_t old_prescale = prescaler_set[channel] + 1;
uint32_t new_prescale = ((new_apb * old_prescale) / old_apb) - 1;
sigmadelta_set_prescale(channel,new_prescale);
prescaler_set[channel] = new_prescale;
}
}

uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-312500
uint32_t sigmaDeltaSetup(uint8_t pin, uint8_t channel, uint32_t freq) //chan 0-x according to SOC, freq 1220-312500
{
if(channel > 7) {
if(channel >= SOC_SIGMADELTA_CHANNEL_NUM){
return 0;
}
#if !CONFIG_DISABLE_HAL_LOCKS
static bool tHasStarted = false;
if(!tHasStarted) {
tHasStarted = true;
_sd_sys_lock = xSemaphoreCreateMutex();
}
#endif

uint32_t apb_freq = getApbFrequency();
uint32_t prescale = (apb_freq/(freq*256)) - 1;
if(prescale > 0xFF) {
prescale = 0xFF;
}
SD_MUTEX_LOCK();
#ifndef CONFIG_IDF_TARGET_ESP32
SIGMADELTA.misc.function_clk_en = 1;
#endif
SIGMADELTA.channel[channel].prescale = prescale;
SIGMADELTA.cg.clk_en = 0;
SIGMADELTA.cg.clk_en = 1;
SD_MUTEX_UNLOCK();

sigmadelta_config_t sigmadelta_cfg = {
.channel = channel,
.sigmadelta_prescale = prescale,
.sigmadelta_duty = 0,
.sigmadelta_gpio = pin,
};
sigmadelta_config(&sigmadelta_cfg);

prescaler_set[channel] = prescale;
uint32_t iarg = channel;
addApbChangeCallback((void*)iarg, _on_apb_change);

return apb_freq/((prescale + 1) * 256);
}

void sigmaDeltaWrite(uint8_t channel, uint8_t duty) //chan 0-7 duty 8 bit
void sigmaDeltaWrite(uint8_t channel, uint8_t duty) //chan 0-x according to SOC duty 8 bit
{
if(channel > 7) {
if(channel >= SOC_SIGMADELTA_CHANNEL_NUM){
return;
}
duty -= 128;
SD_MUTEX_LOCK();
SIGMADELTA.channel[channel].duty = duty;
SD_MUTEX_UNLOCK();
}
duty -= 128;

uint8_t sigmaDeltaRead(uint8_t channel) //chan 0-7
{
if(channel > 7) {
return 0;
}
SD_MUTEX_LOCK();
uint8_t duty = SIGMADELTA.channel[channel].duty + 128;
SD_MUTEX_UNLOCK();
return duty;
sigmadelta_set_duty(channel,duty);
duty_set[channel] = duty;
}

void sigmaDeltaAttachPin(uint8_t pin, uint8_t channel) //channel 0-7
uint8_t sigmaDeltaRead(uint8_t channel) //chan 0-x according to SOC
{
if(channel > 7) {
return;
if(channel >= SOC_SIGMADELTA_CHANNEL_NUM){
return 0;
}
pinMode(pin, OUTPUT);
pinMatrixOutAttach(pin, GPIO_SD0_OUT_IDX + channel, false, false);
return duty_set[channel]+128;
}

void sigmaDeltaDetachPin(uint8_t pin)
{
pinMatrixOutDetach(pin, false, false);
}
}
3 changes: 1 addition & 2 deletions cores/esp32/esp32-hal-sigmadelta.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ extern "C" {
#include <stdbool.h>

//channel 0-7 freq 1220-312500 duty 0-255
uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq);
uint32_t sigmaDeltaSetup(uint8_t pin, uint8_t channel, uint32_t freq);
void sigmaDeltaWrite(uint8_t channel, uint8_t duty);
uint8_t sigmaDeltaRead(uint8_t channel);
void sigmaDeltaAttachPin(uint8_t pin, uint8_t channel);
void sigmaDeltaDetachPin(uint8_t pin);


Expand Down
6 changes: 2 additions & 4 deletions libraries/ESP32/examples/AnalogOut/SigmaDelta/SigmaDelta.ino
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
void setup()
{
//setup channel 0 with frequency 312500 Hz
sigmaDeltaSetup(0, 312500);
//attach pin 18 to channel 0
sigmaDeltaAttachPin(18,0);
//setup on pin 18, channel 0 with frequency 312500 Hz
sigmaDeltaSetup(18,0, 312500);
//initialize channel 0 to off
sigmaDeltaWrite(0, 0);
}
Expand Down