/
pwm_audio.h
199 lines (182 loc) · 5.77 KB
/
pwm_audio.h
1
2
3
4
5
6
7
8
9
10
11
12
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _PWM_AUDIO_H_
#define _PWM_AUDIO_H_
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
#include "driver/gptimer.h"
#else
#include "driver/timer.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Configuration parameters for pwm_audio_init function
*/
typedef struct {
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
timer_group_t tg_num; /*!< timer group number (0 - 1) */
timer_idx_t timer_num; /*!< timer number (0 - 1) */
#endif
int gpio_num_left; /*!< the LEDC output gpio_num, Left channel */
int gpio_num_right; /*!< the LEDC output gpio_num, Right channel */
ledc_channel_t ledc_channel_left; /*!< LEDC channel (0 - 7), Corresponding to left channel*/
ledc_channel_t ledc_channel_right; /*!< LEDC channel (0 - 7), Corresponding to right channel*/
ledc_timer_t ledc_timer_sel; /*!< Select the timer source of channel (0 - 3) */
ledc_timer_bit_t duty_resolution; /*!< ledc pwm bits */
uint32_t ringbuf_len; /*!< ringbuffer size */
} pwm_audio_config_t;
/**
* @brief pwm audio status
*/
typedef enum {
PWM_AUDIO_STATUS_UN_INIT = 0, /*!< pwm audio uninitialized */
PWM_AUDIO_STATUS_IDLE = 1, /*!< pwm audio idle */
PWM_AUDIO_STATUS_BUSY = 2, /*!< pwm audio busy */
} pwm_audio_status_t;
/**
* @brief pwm audio channel define
*
*/
typedef enum {
PWM_AUDIO_CH_MONO = 0, /*!< 1 channel (mono)*/
PWM_AUDIO_CH_STEREO = 1, /*!< 2 channel (stereo)*/
PWM_AUDIO_CH_MAX,
} pwm_audio_channel_t;
/**
* @brief Initializes and configure the pwm audio.
*
* @param cfg configurations - see pwm_audio_config_t struct
*
* @return
* - ESP_OK Success
* - ESP_FAIL timer_group or ledc initialize failed
* - ESP_ERR_INVALID_ARG if argument wrong
* - ESP_ERR_INVALID_STATE The pwm audio already configure
* - ESP_ERR_NO_MEM Memory allocate failed
*/
esp_err_t pwm_audio_init(const pwm_audio_config_t *cfg);
/**
* @brief Deinitialize LEDC timer_group and output gpio
*
* @return
* - ESP_OK Success
* - ESP_FAIL pwm_audio not initialized
*/
esp_err_t pwm_audio_deinit(void);
/**
* @brief Start to run pwm audio
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE pwm_audio not initialized or it already running
*/
esp_err_t pwm_audio_start(void);
/**
* @brief Stop pwm audio
*
* @attention Only stop timer, and the pwm will keep to output. If you want to stop pwm output, call pwm_audio_deinit function
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE pwm_audio not initialized or it already idle
*/
esp_err_t pwm_audio_stop(void);
/**
* @brief Write data to play
*
* @param inbuf Pointer source data to write
* @param len length of data in bytes
* @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in.
* @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this
* many ticks pass without space becoming available in the DMA
* transmit buffer, then the function will return (note that if the
* data is written to the DMA buffer in pieces, the overall operation
* may still take longer than this timeout.) Pass portMAX_DELAY for no
* timeout.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Write encounter error
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t pwm_audio_write(uint8_t *inbuf, size_t len, size_t *bytes_written, TickType_t ticks_to_wait);
/**
* @brief Set audio parameter, Similar to pwm_audio_set_sample_rate(), but also sets bit width.
*
* @attention After start pwm audio, it can't modify parameters by call function pwm_audio_set_param.
* If you want to change the parameters, must stop pwm audio by call function pwm_audio_stop.
*
* @param rate sample rate (ex: 8000, 44100...)
* @param bits bit width
* @param ch channel number
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t pwm_audio_set_param(int rate, ledc_timer_bit_t bits, int ch);
/**
* @brief Set sample rate
*
* @param rate sample rate (ex: 8000, 44100...)
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t pwm_audio_set_sample_rate(int rate);
/**
* @brief Set volume for pwm audio
*
* @attention when the volume is too small, it will produce serious distortion
*
* @param volume Volume to set (-16 ~ 16).
* Set to 0 for original output;
* Set to less then 0 for attenuation, and -16 is mute;
* Set to more than 0 for enlarge, and 16 is double output
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t pwm_audio_set_volume(int8_t volume);
/**
* @brief Get current volume
*
* @param volume Pointer to volume
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t pwm_audio_get_volume(int8_t *volume);
/**
* @brief Get parameter for pwm audio.
*
* @param rate sample rate, if you don't care about this parameter, set it to NULL
* @param bits bit width, if you don't care about this parameter, set it to NULL
* @param ch channel number, if you don't care about this parameter, set it to NULL
*
* @return
* - Always return ESP_OK
*/
esp_err_t pwm_audio_get_param(int *rate, int *bits, int *ch);
/**
* @brief get pwm audio status
*
* @param status current pwm_audio status
*
* @return
* - ESP_OK Success
*/
esp_err_t pwm_audio_get_status(pwm_audio_status_t *status);
#ifdef __cplusplus
}
#endif
#endif