arduino-audio-tools
Loading...
Searching...
No Matches
I2SDriverZephyr.h
Go to the documentation of this file.
1#pragma once
2
4#include "AudioToolsConfig.h"
5
6#if defined(IS_ZEPHYR)
7
8#include <string.h>
9#include <zephyr/device.h>
10#include <zephyr/drivers/i2s.h>
11#include <zephyr/kernel.h>
12
15
16// Note: The following headers are needed for the ESP32 MCLK routing,
17#if defined(CONFIG_SOC_ESP32)
18#include <zephyr/drivers/gpio.h>
19#define I2S0O_CLK_OUT_IDX 80
20extern "C" {
21void esp_rom_gpio_connect_out_signal(uint32_t gpio_num, uint32_t signal_idx,
22 bool out_inv, bool oen_inv);
23}
24#endif
25
26#define IS_I2S_IMPLEMENTED
27
28namespace audio_tools {
29
37 friend class I2SStream;
38
39 public:
42 I2SConfigZephyr c(mode);
43 return c;
44 }
45
48 if (is_started) {
49 if (info.equals(cfg)) return true;
50
53 cfg.channels = info.channels;
55
56 end();
57 if (begin(cfg)) {
58 return true;
59 }
60
62 return begin(cfg);
63 }
64
66 cfg.channels = info.channels;
68 return true;
69 }
70
72 bool begin(RxTxMode mode = TX_MODE) { return begin(defaultConfig(mode)); }
73
76 TRACEI();
77
78 if (is_started) end();
79
80 const size_t slab_size = static_cast<size_t>(cfg.buffer_count) *
81 static_cast<size_t>(cfg.buffer_size);
82 if (slab_size == 0) {
83 LOGE("Invalid Zephyr I2S slab size");
84 return false;
85 }
86
89 LOGE("Could not resize Zephyr I2S slabs");
90 return false;
91 }
92
93 if (!initSlabs(cfg)) {
94 LOGE("Failed to initialize Zephyr I2S slabs");
95 return false;
96 }
97
98 this->cfg = cfg;
99 this->cfg.logInfo();
100
101 if (!resolveDevice()) {
102 LOGE("No Zephyr I2S device found");
103 return false;
104 }
105
108 if (i2s_configure(i2s_dev, I2S_DIR_TX, &tx_cfg) != 0) {
109 LOGE("i2s_configure failed for TX");
110 return false;
111 }
112 }
113
116 if (i2s_configure(i2s_dev, I2S_DIR_RX, &rx_cfg) != 0) {
117 LOGE("i2s_configure failed for RX");
118 return false;
119 }
120 }
121
122 if (!startConfiguredStreams()) {
123 end();
124 return false;
125 }
126 // Special hack for the ESP32 to enable MCLK output at runtime, since
127 // Zephyr's I2S driver doesn't do this automatically.
129 is_started = true;
130 return true;
131 }
132
134 void end() {
135 if (i2s_dev == nullptr || !is_started) {
136 is_started = false;
137 return;
138 }
139
142 i2s_config disable_cfg = tx_cfg;
143 disable_cfg.frame_clk_freq = 0U;
145 }
146
149 i2s_config disable_cfg = rx_cfg;
150 disable_cfg.frame_clk_freq = 0U;
152 }
153
154 is_started = false;
155 }
156
159
161 size_t writeBytes(const void* src, size_t size_bytes) {
162 if (!is_started || i2s_dev == nullptr) return 0;
163 if (cfg.rx_tx_mode == RX_MODE) return 0;
164
165 int result = i2s_buf_write(i2s_dev, const_cast<void*>(src), size_bytes);
166 return (result == 0) ? size_bytes : 0;
167 }
168
169 size_t readBytes(void* dest, size_t size_bytes) {
170 if (!is_started || i2s_dev == nullptr) return 0;
171 if (cfg.rx_tx_mode == TX_MODE) return 0;
172
173 size_t result_size = size_bytes;
174 int result = i2s_buf_read(i2s_dev, dest, &result_size);
175 return (result == 0) ? result_size : 0;
176 }
177
179
181
182 protected:
184 i2s_config tx_cfg{};
185 i2s_config rx_cfg{};
186 const device* i2s_dev = nullptr;
187 bool is_started = false;
192 bool slabs_initialized = false;
193
196 void enableMclkRuntime(void) {
197#if defined(CONFIG_SOC_ESP32)
198 // 0 = Target physical GPIO pin (Change to 2 if your MCLK is wired to
199 // GPIO2) 80 = The permanent hardware signal ID for I2S0 Clock Out on
200 // classic ESP32
202#endif
203 }
204
206 i2s_config i2s_cfg = {0};
207 i2s_cfg.word_size = cfg.bits_per_sample;
208 i2s_cfg.channels = cfg.channels;
210 i2s_cfg.options =
214 i2s_cfg.frame_clk_freq = cfg.sample_rate;
215 i2s_cfg.mem_slab = mem_slab;
216 i2s_cfg.block_size = I2S_BUFFER_SIZE;
217 i2s_cfg.timeout = -1;
218 return i2s_cfg;
219 }
220
229
231 if (cfg.rx_tx_mode == TX_MODE) {
233 }
234
235 if (cfg.rx_tx_mode == RX_MODE) {
237 }
238
240 if (result == 0) return true;
241 if (result != -ENOSYS) return false;
242
245 }
246
248 if (i2s_dev != nullptr) {
249 return true;
250 }
251
252 if (cfg.dev != nullptr) {
253 LOGI("Using provided I2S device");
254 i2s_dev = cfg.dev;
255 LOGI("Using i2s device %s",
256 i2s_dev->name != nullptr ? i2s_dev->name : "n/a");
257 return true;
258 }
259
260 LOGE("I2S device is not set in configuration");
261 return false;
262 }
263};
264
265using I2SDriver = I2SDriverZephyr;
266
267} // namespace audio_tools
268
269#endif
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define I2S_BUFFER_SIZE
Definition AudioToolsConfig.h:112
#define I2S_BUFFER_COUNT
Definition AudioToolsConfig.h:116
Configuration for i2s.
Definition I2SConfigZephyr.h:19
int buffer_count
Definition I2SConfigZephyr.h:38
RxTxMode rx_tx_mode
public settings
Definition I2SConfigZephyr.h:35
device * dev
Definition I2SConfigZephyr.h:40
bool is_master
Definition I2SConfigZephyr.h:36
void logInfo(const char *source="")
Definition I2SConfigZephyr.h:43
int buffer_size
Definition I2SConfigZephyr.h:39
Definition I2SDriverBase.h:7
Basic I2S API for Zephyr based targets.
Definition I2SDriverZephyr.h:36
k_mem_slab tx_slab
Definition I2SDriverZephyr.h:190
k_mem_slab rx_slab
Definition I2SDriverZephyr.h:191
I2SConfigZephyr defaultConfig(RxTxMode mode)
Provides the default configuration.
Definition I2SDriverZephyr.h:41
Vector< uint8_t > rx_slab_buffer
Definition I2SDriverZephyr.h:189
int available()
Definition I2SDriverZephyr.h:178
bool resolveDevice()
Definition I2SDriverZephyr.h:247
bool slabs_initialized
Definition I2SDriverZephyr.h:192
bool is_started
Definition I2SDriverZephyr.h:187
bool initSlabs(const I2SConfigZephyr &cfg)
Definition I2SDriverZephyr.h:221
bool setAudioInfo(AudioInfo info)
Potentially updates the sample rate (if supported)
Definition I2SDriverZephyr.h:47
const device * i2s_dev
Definition I2SDriverZephyr.h:186
i2s_config buildI2SConfig(const I2SConfigZephyr &cfg, k_mem_slab *mem_slab)
Definition I2SDriverZephyr.h:205
Vector< uint8_t > tx_slab_buffer
Definition I2SDriverZephyr.h:188
i2s_config rx_cfg
Definition I2SDriverZephyr.h:185
int availableForWrite()
Definition I2SDriverZephyr.h:180
I2SConfigZephyr config()
provides the actual configuration
Definition I2SDriverZephyr.h:158
bool begin(I2SConfigZephyr cfg)
starts the DAC with the current config
Definition I2SDriverZephyr.h:75
void end()
stops the I2S interface
Definition I2SDriverZephyr.h:134
i2s_config tx_cfg
Definition I2SDriverZephyr.h:184
bool startConfiguredStreams()
Definition I2SDriverZephyr.h:230
size_t writeBytes(const void *src, size_t size_bytes)
writes the data to the I2S interface
Definition I2SDriverZephyr.h:161
I2SConfigZephyr cfg
Definition I2SDriverZephyr.h:183
size_t readBytes(void *dest, size_t size_bytes)
Definition I2SDriverZephyr.h:169
bool begin(RxTxMode mode=TX_MODE)
starts the DAC with the default config
Definition I2SDriverZephyr.h:72
void enableMclkRuntime(void)
Definition I2SDriverZephyr.h:196
We support the Stream interface for the I2S access. In addition we allow a separate mute pin which mi...
Definition I2SStream.h:40
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
T * data()
Definition Vector.h:316
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:26
@ RXTX_MODE
Definition AudioTypes.h:26
@ TX_MODE
Definition AudioTypes.h:26
@ RX_MODE
Definition AudioTypes.h:26
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
I2SDriverESP32 I2SDriver
Definition I2SDriverESP32.h:403
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:508
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
bool equals(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:83
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57