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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
|
/*
* Copyright (C) 2017-2024 Alibaba Group Holding Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
/******************************************************************************
* @file drv/i2s.h
* @brief header file for i2s driver
* @version V1.0
* @date 16. Mar 2020
* @model i2s
******************************************************************************/
#ifndef _DRV_I2S_H_
#define _DRV_I2S_H_
#include <stdint.h>
#include <stdbool.h>
#include <drv/common.h>
#include <drv/dma.h>
#include "drv/ringbuf.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
I2S_MODE_MASTER, ///< I2s transmitter master mode
I2S_MODE_SLAVE, ///< I2s transmitter slave mode
} csi_i2s_mode_t;
typedef enum {
I2S_PROTOCOL_I2S, ///< I2S protocol
I2S_PROTOCOL_MSB_JUSTIFIED, ///< MSB (left) justified protocol
I2S_PROTOCOL_LSB_JUSTIFIED, ///< LSB (right) justified protocol
I2S_PROTOCOL_PCM, ///< PCM protocol
} csi_i2s_protocol_t;
typedef enum {
I2S_LEFT_POLARITY_LOW, ///< Low level represents the left channel
I2S_LEFT_POLARITY_HIGH, ///< High level represents the left channel
} csi_i2s_ws_left_polarity_t;
typedef enum {
I2S_SAMPLE_RATE_8000 = 8000U, ///< I2S sample rate is 8000
I2S_SAMPLE_RATE_11025 = 11025U,
I2S_SAMPLE_RATE_12000 = 12000U,
I2S_SAMPLE_RATE_16000 = 16000U,
I2S_SAMPLE_RATE_22050 = 22050U,
I2S_SAMPLE_RATE_24000 = 24000U,
I2S_SAMPLE_RATE_32000 = 32000U,
I2S_SAMPLE_RATE_44100 = 44100U,
I2S_SAMPLE_RATE_48000 = 48000U,
I2S_SAMPLE_RATE_96000 = 96000U,
I2S_SAMPLE_RATE_192000 = 192000U,
I2S_SAMPLE_RATE_256000 = 256000U,
} csi_i2s_sample_rate_t;
typedef enum {
I2S_SAMPLE_WIDTH_16BIT = 16U, ///< I2S sample width is 16bit
I2S_SAMPLE_WIDTH_24BIT = 24U,
I2S_SAMPLE_WIDTH_32BIT = 32U,
} csi_i2s_sample_width_t;
typedef enum {
I2S_SCLK_16FS = 16U, ///< SCLK frequency is 16 times that of I2S sample rate
I2S_SCLK_32FS = 32U,
I2S_SCLK_48FS = 48U,
I2S_SCLK_64FS = 64U,
} csi_i2s_sclk_freq_t;
typedef enum {
I2S_MCLK_256FS = 256U, ///< MCLK frequency is 256 times that of I2S sample rate
I2S_MCLK_384FS = 384U,
} csi_i2s_mclk_freq_t;
typedef struct {
csi_i2s_mode_t mode; ///< I2S work mode
csi_i2s_protocol_t protocol; ///< Protocols used by I2S
csi_i2s_ws_left_polarity_t polarity; ///< left channel polarity
csi_i2s_sample_rate_t rate; ///< I2S sample rate
csi_i2s_sample_width_t width; ///< I2S sample width
csi_i2s_sclk_freq_t sclk_nfs; ///< SCLK frequency is N times that of I2S sample rate
csi_i2s_mclk_freq_t mclk_nfs; ///< MCLK frequency is N times that of I2S sample rate
} csi_i2s_format_t;
typedef enum {
I2S_LEFT_CHANNEL,
I2S_RIGHT_CHANNEL,
I2S_LEFT_RIGHT_CHANNEL,
} csi_i2s_sound_channel_t;
typedef enum {
I2S_EVENT_SEND_COMPLETE,
I2S_EVENT_RECEIVE_COMPLETE,
I2S_EVENT_TX_BUFFER_EMPTY,
I2S_EVENT_RX_BUFFER_FULL,
I2S_EVENT_ERROR_OVERFLOW,
I2S_EVENT_ERROR_UNDERFLOW,
I2S_EVENT_ERROR,
} csi_i2s_event_t;
typedef struct csi_i2s csi_i2s_t;
struct csi_i2s {
csi_dev_t dev; ///< I2S hw-device info
void (*callback)(csi_i2s_t *i2s, csi_i2s_event_t event, void *arg); ///< I2S event callback for user
void *arg; ///< user private param passed to user callback
csi_ringbuf_t *tx_buf; ///< I2S send buffer
csi_ringbuf_t *rx_buf; ///< I2S receive buffer
csi_dma_ch_t *tx_dma; ///< send dma channel handle
csi_dma_ch_t *rx_dma; ///< receive dma channel handle
uint32_t tx_period; ///< I2S send period num data will callback
uint32_t rx_period; ///< I2S receive period num data will callback
csi_state_t state; ///< I2S communication state
void *priv;
};
/**
\brief Init i2s
\param[in] i2s I2s handle to operate
\param[in] idx I2s interface idx
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_init(csi_i2s_t *i2s, uint32_t idx);
/**
\brief Uninit i2s
\param[in] i2s I2s handle to operate
\return none
*/
void csi_i2s_uninit(csi_i2s_t *i2s);
/**
\brief Enable i2s
\param[in] i2s I2s handle to operate
\param[in] en True enable, False disable
\return None
*/
void csi_i2s_enable(csi_i2s_t *i2s, bool enable);
/**
\brief I2s config format
\param[in] i2s I2s handle to operate
\param[in] format I2s config param \ref csi_i2s_format_t
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_format(csi_i2s_t *i2s, csi_i2s_format_t *format);
/**
\brief Set the i2s tx mono
\param[in] i2s I2s handle to operate
\param[in] ch Mono channel selection
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_tx_select_sound_channel(csi_i2s_t *i2s, csi_i2s_sound_channel_t ch);
/**
\brief Set the i2s rx mono
\param[in] i2s I2s handle to operate
\param[in] ch Mono channel selection
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_rx_select_sound_channel(csi_i2s_t *i2s, csi_i2s_sound_channel_t ch);
/**
\brief Link DMA channel to i2s device
\param[in] i2s I2s handle to operate
\param[in] rx_dma The DMA channel for receive, when it is NULL means to unused dma
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_rx_link_dma(csi_i2s_t *i2s, csi_dma_ch_t *rx_dma);
/**
\brief Link DMA channel to i2s device
\param[in] i2s I2s handle to operate
\param[in] tx_dma The DMA channel for send, when it is NULL means to unused dma
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_tx_link_dma(csi_i2s_t *i2s, csi_dma_ch_t *tx_dma);
/**
\brief I2s rx buffer config
\param[in] i2s I2s handle to operate
\param[in] buffer I2s rx buffer
\return None
*/
void csi_i2s_rx_set_buffer(csi_i2s_t *i2s, csi_ringbuf_t *buffer);
/**
\brief I2s tx buffer config
\param[in] i2s I2s handle to operate
\param[in] buffer I2s tx buffer
\return None
*/
void csi_i2s_tx_set_buffer(csi_i2s_t *i2s, csi_ringbuf_t *buffer);
/**
\brief I2s rx set period.The value of period is to report a receive completion event
after each period value data is received
\param[in] i2s I2s handle to operate
\param[in] period I2s rx period
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_rx_set_period(csi_i2s_t *i2s, uint32_t period);
/**
\brief I2s tx set period.The value of period is to report a receive completion event
after each period value data is send
\param[in] i2s I2s handle to operate
\param[in] period I2s tx period
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_tx_set_period(csi_i2s_t *i2s, uint32_t period);
/**
\brief Get rx csi_ringbuf buffer free space
\param[in] i2s I2s handle to operate
\return Buffer free space (bytes)
*/
uint32_t csi_i2s_rx_buffer_avail(csi_i2s_t *i2s);
/**
\brief Get rx csi_ringbuf buffer used space
\param[in] i2s I2s handle to operate
\return Buffer used space (bytes)
*/
uint32_t csi_i2s_rx_buffer_remain(csi_i2s_t *i2s);
/**
\brief Reset the rx csi_ringbuf, discard all data in the buffer
\param[in] i2s I2s handle to operate
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_rx_buffer_reset(csi_i2s_t *i2s);
/**
\brief Get tx csi_ringbuf buffer free space
\param[in] i2s I2s handle to operate
\return Buffer free space (bytes)
*/
uint32_t csi_i2s_tx_buffer_avail(csi_i2s_t *i2s);
/**
\brief Get tx csi_ringbuf buffer used space
\param[in] i2s I2s handle to operate
\return Buffer used space (bytes)
*/
uint32_t csi_i2s_tx_buffer_remain(csi_i2s_t *i2s);
/**
\brief Reset the tx csi_ringbuf, discard all data in the buffer
\param[in] i2s Handle to operate
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_tx_buffer_reset(csi_i2s_t *i2s);
/**
\brief Send an amount of data to buffer in blocking mode
\param[in] i2s Operate handle
\param[in] data Pointer to send data buffer
\param[in] size Send data size
\return The num of data witch is send successful
*/
int32_t csi_i2s_send(csi_i2s_t *i2s, const void *data, uint32_t size);
/**
\brief Receive an amount of data to buffer in blocking mode
\param[in] i2s Operate handle
\param[out] data Pointer to receive data buffer
\param[in] size Receive data size
\return The size of data receive successfully
*/
int32_t csi_i2s_receive(csi_i2s_t *i2s, void *data, uint32_t size);
/**
\brief Write data to the buffer
With asynchronous sending
The data is first written to the buffer and then output through the i2s interface
Return value is the number of data that was successfully written to the buffer
\param[in] i2s Operate handle
\param[in] data Pointer to send data buffer
\param[in] size Send data size
\return The data size that write to buffer
*/
uint32_t csi_i2s_send_async(csi_i2s_t *i2s, const void *data, uint32_t size);
/**
\brief Read data from the buffer
Using asynchronous receive, i2s writes the received data to the buffer
This function reads data from the buffer, returns the number of successful reads
Returns 0 if there is no data in the buffer
\param[in] i2s Operate handle
\param[out] data Pointer to receive data buffer
\param[in] size Receive data size
\return The size of data read successfully
*/
uint32_t csi_i2s_receive_async(csi_i2s_t *i2s, void *data, uint32_t size);
/**
\brief Start i2s pause asynchronous send
\param[in] i2s Operate handle
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_send_pause(csi_i2s_t *i2s);
/**
\brief Start i2s resume asynchronous send
\param[in] i2s Operate handle
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_send_resume(csi_i2s_t *i2s);
/**
\brief Start i2s asynchronous send
\param[in] i2s Operate handle
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_send_start(csi_i2s_t *i2s);
/**
\brief Start i2s asynchronous receive
\param[in] i2s Operate handle
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_receive_start(csi_i2s_t *i2s);
/**
\brief Stop i2s asynchronous send
\param[in] i2s Operate handle
\return None
*/
void csi_i2s_send_stop(csi_i2s_t *i2s);
/**
\brief Stop i2s asynchronous receive
\param[in] i2s Operate handle
\return None
*/
void csi_i2s_receive_stop(csi_i2s_t *i2s);
/**
\brief Attach the callback handler to i2s
\param[in] i2s Operate handle
\param[in] cb Callback function
\param[in] arg User private param
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_attach_callback(csi_i2s_t *i2s, void *callback, void *arg);
/**
\brief Detach the callback handler
\param[in] i2s Operate handle
\return None
*/
void csi_i2s_detach_callback(csi_i2s_t *i2s);
/**
\brief Get i2s status
\param[in] i2s I2s handle to operate
\param[out] state I2s state
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_get_state(csi_i2s_t *i2s, csi_state_t *state);
/**
\brief Enable i2s power manage
\param[in] i2s I2s handle to operate
\return error code \ref csi_error_t
*/
csi_error_t csi_i2s_enable_pm(csi_i2s_t *i2s);
/**
\brief Disable i2s power manage
\param[in] i2s I2s handle to operate
\return None
*/
void csi_i2s_disable_pm(csi_i2s_t *i2s);
#ifdef __cplusplus
}
#endif
#endif /* _DRV_I2S_H_ */
|