1
6
7
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
41
42
43
44
45
46
47
48
53
54
55
56
57
62
63
64
65
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
90
91
92
93
94
95
96
97
98
99
100
101
102
105
106
107
108
109
110
111
112
/* ... */
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/sdm.h"
#include "driver/gptimer.h"6 includes
#define MHZ (1000000)
#define CONST_PI (3.1416f)
#define EXAMPLE_SIGMA_DELTA_GPIO_NUM (0)
#define EXAMPLE_OVER_SAMPLE_RATE (10 * MHZ)
#define EXAMPLE_TIMER_RESOLUTION (1 * MHZ)
#define EXAMPLE_CALLBACK_INTERVAL_US (100)
#define EXAMPLE_ALARM_COUNT (EXAMPLE_CALLBACK_INTERVAL_US * (EXAMPLE_TIMER_RESOLUTION / MHZ))
#define EXAMPLE_SINE_WAVE_FREQ_HZ (100)
#define EXAMPLE_SINE_WAVE_AMPLITUDE (127.0f)
#define EXAMPLE_SINE_WAVE_POINT_NUM (MHZ / (EXAMPLE_CALLBACK_INTERVAL_US * EXAMPLE_SINE_WAVE_FREQ_HZ))10 defines
ESP_STATIC_ASSERT(EXAMPLE_SINE_WAVE_POINT_NUM > 1, "Sine wave frequency is too high");
ESP_STATIC_ASSERT(EXAMPLE_CALLBACK_INTERVAL_US >= 7, "Timer callback interval is too short");
static const char *TAG = "sdm_dac";
static int8_t sine_wave[EXAMPLE_SINE_WAVE_POINT_NUM];
static bool IRAM_ATTR example_timer_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
static uint32_t cnt = 0;
sdm_channel_handle_t sdm_chan = (sdm_channel_handle_t)user_ctx;
sdm_channel_set_pulse_density(sdm_chan, sine_wave[cnt++]);
if (cnt >= EXAMPLE_SINE_WAVE_POINT_NUM) {
cnt = 0;
}{...}
return false;
}{ ... }
static gptimer_handle_t example_init_gptimer(void* args)
{
gptimer_handle_t timer_handle;
gptimer_config_t timer_cfg = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = EXAMPLE_TIMER_RESOLUTION,
}{...};
ESP_ERROR_CHECK(gptimer_new_timer(&timer_cfg, &timer_handle));
ESP_LOGI(TAG, "Timer allocated with resolution %d Hz", EXAMPLE_TIMER_RESOLUTION);
gptimer_alarm_config_t alarm_cfg = {
.alarm_count = EXAMPLE_ALARM_COUNT,
.reload_count = 0,
.flags.auto_reload_on_alarm = true,
}{...};
ESP_ERROR_CHECK(gptimer_set_alarm_action(timer_handle, &alarm_cfg));
gptimer_event_callbacks_t cbs = {
.on_alarm = example_timer_callback,
}{...};
ESP_ERROR_CHECK(gptimer_register_event_callbacks(timer_handle, &cbs, args));
ESP_LOGI(TAG, "Timer callback registered, interval %d us", EXAMPLE_CALLBACK_INTERVAL_US);
ESP_ERROR_CHECK(gptimer_set_raw_count(timer_handle, 0));
ESP_ERROR_CHECK(gptimer_enable(timer_handle));
ESP_LOGI(TAG, "Timer enabled");
return timer_handle;
}{ ... }
static sdm_channel_handle_t example_init_sdm(void)
{
sdm_channel_handle_t sdm_chan = NULL;
sdm_config_t config = {
.clk_src = SDM_CLK_SRC_DEFAULT,
.gpio_num = EXAMPLE_SIGMA_DELTA_GPIO_NUM,
.sample_rate_hz = EXAMPLE_OVER_SAMPLE_RATE,
}{...};
ESP_ERROR_CHECK(sdm_new_channel(&config, &sdm_chan));
ESP_ERROR_CHECK(sdm_channel_enable(sdm_chan));
ESP_LOGI(TAG, "Sigma-delta output is attached to GPIO %d", EXAMPLE_SIGMA_DELTA_GPIO_NUM);
return sdm_chan;
}{ ... }
void app_main(void)
{
for (int i = 0; i < EXAMPLE_SINE_WAVE_POINT_NUM; i++) {
sine_wave[i] = (int8_t)((sin(2 * (float)i * CONST_PI / EXAMPLE_SINE_WAVE_POINT_NUM)) * EXAMPLE_SINE_WAVE_AMPLITUDE);
}{...}
sdm_channel_handle_t sdm_chan = example_init_sdm();
gptimer_handle_t timer_handle = example_init_gptimer(sdm_chan);
ESP_LOGI(TAG, "Output start");
ESP_ERROR_CHECK(gptimer_start(timer_handle));
}{ ... }