1
6
7
16
17
18
21
22
23
29
30
31
32
33
34
36
37
38
39
46
47
48
49
50
51
52
53
54
55
56
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
103
104
105
106
107
108
110
111
112
113
114
115
116
120
121
122
123
124
125
126
127
128
129
130
134
135
136
137
138
139
140
141
142
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
175
176
177
180
181
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
209
210
211
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
241
248
249
250
255
256
257
258
259
260
261
262
263
264
268
269
270
271
272
273
274
286
287
288
289
290
291
300
301
302
303
306
307
308
313
314
315
316
317
318
319
328
329
330
335
336
337
338
341
342
343
344
345
346
347
348
349
350
351
352
355
356
357
360
361
364
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
435
436
437
438
439
440
441
442
443
444
447
448
449
450
451
452
453
454
455
456
457
460
461
462
463
464
465
466
467
468
469
472
473
474
475
476
477
478
479
480
481
485
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
506
509
510
511
512
513
514
515
516
519
520
521
522
523
524
525
526
527
528
529
530
549
556
557
558
559
560
561
562
563
564
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
642
643
644
645
649
650
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
678
679
680
683
684
685
688
689
692
693
694
695
696
697
698
699
700
701
704
705
706
707
708
709
710
711
715
716
717
718
719
720
724
727
728
729
730
731
732
733
737
738
739
740
741
742
743
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
864
865
866
867
868
869
873
874
878
879
880
881
882
883
884
885
886
887
888
889
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
920
921
926
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1027
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1048
1056
1057
1058
1059
1063
1064
1068
1069
1070
1071
1080
1081
1090
1091
1092
1093
1094
1095
1096
1097
1105
1106
1107
1113
1114
1115
1116
1117
1118
1119
1120
1123
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1154
1155
1156
1157
1160
1161
1162
1163
1164
1168
1169
1170
1171
1172
1173
1174
1175
1190
1191
1192
1193
1194
1195
1196
1199
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1228
1231
1232
1233
1234
1237
1240
1241
1242
1243
1246
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1296
1300
1301
1302
1303
1304
1305
1306
1307
1308
1313
1316
1319
1320
1324
1325
1326
1330
1331
1332
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1358
1359
1360
1361
1362
1363
1364
1365
1368
1373
1376
1381
1382
1383
1384
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1483
1484
1485
1486
1490
1491
1492
1500
1501
1502
1503
1507
1508
1512
1513
1514
1515
1524
1525
1539
1540
1541
1542
1543
1544
1547
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1566
1567
1568
1580
1581
1590
1594
1595
1596
1597
1598
1602
1603
1604
1617
1618
1619
1624
1625
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1713
1714
1715
1716
1717
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1753
1757
1761
1765
1766
1767
1768
1769
1770
1771
1772
1773
1779
1780
1781
1782
1785
1786
1787
1788
1789
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1824
1825
1826
1827
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1846
1855
1856
1865
1866
1867
1868
1871
1872
1874
1875
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1893
1894
1895
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1972
1973
1974
/* ... */
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include <esp_types.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "sdkconfig.h"8 includes
#if CONFIG_I2S_ENABLE_DEBUG_LOG
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG/* ... */
#endif
#include "soc/lldesc.h"
#include "driver/gpio.h"
#include "esp_private/gpio.h"
#include "hal/gpio_hal.h"
#include "driver/i2s_types_legacy.h"
#include "hal/i2s_hal.h"6 includes
#if SOC_I2S_SUPPORTS_APLL
#include "hal/clk_tree_ll.h"
#endif
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"/* ... */
#endif
#if SOC_I2S_SUPPORTS_DAC
#include "hal/dac_ll.h"
#include "hal/dac_types.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "esp_private/sar_periph_ctrl.h"
#include "adc1_private.h"
#include "driver/adc_i2s_legacy.h"
#include "driver/adc_types_legacy.h"/* ... */
#endif
#if CONFIG_IDF_TARGET_ESP32
#include "esp_clock_output.h"
#endif
#if SOC_GDMA_SUPPORTED
#include "esp_private/gdma.h"
#endif
#include "clk_ctrl_os.h"
#include "esp_intr_alloc.h"
#include "esp_err.h"
#include "esp_check.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_pm.h"
#include "esp_efuse.h"
#include "esp_rom_gpio.h"9 includes
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#include "esp_cache.h"
#endif
#include "esp_private/i2s_platform.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/esp_clk.h"
static const char *TAG = "i2s(legacy)";
#define I2S_ENTER_CRITICAL_ISR(i2s_num) portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num])
#define I2S_EXIT_CRITICAL_ISR(i2s_num) portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num])
#define I2S_ENTER_CRITICAL(i2s_num) portENTER_CRITICAL(&i2s_spinlock[i2s_num])
#define I2S_EXIT_CRITICAL(i2s_num) portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
#if SOC_PERIPH_CLK_CTRL_SHARED
#define I2S_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define I2S_CLOCK_SRC_ATOMIC()
#endif
#if !SOC_RCC_IS_INDEPENDENT
#define I2S_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define I2S_RCC_ATOMIC()
#endif
#define I2S_DMA_BUFFER_MAX_SIZE 4092
#if SOC_I2S_SUPPORTS_ADC_DAC
#define I2S_COMM_MODE_ADC_DAC -1
#endif
/* ... */
typedef struct {
uint32_t sample_rate_hz;
i2s_clock_src_t clk_src;
i2s_mclk_multiple_t mclk_multiple;
#if SOC_I2S_SUPPORTS_PDM_TX
uint32_t up_sample_fp;
uint32_t up_sample_fs; /* ... */
#endif
#if SOC_I2S_SUPPORTS_PDM_RX
i2s_pdm_dsr_t dn_sample_mode;
#endif
}{ ... } i2s_clk_config_t;
/* ... */
typedef struct {
char **buf;
int buf_size;
volatile int rw_pos;
volatile void *curr_ptr;
SemaphoreHandle_t mux;
QueueHandle_t queue;
lldesc_t **desc;
}{ ... } i2s_dma_t;
/* ... */
typedef struct {
i2s_port_t i2s_num;
int queue_size;
QueueHandle_t i2s_queue;
uint32_t last_buf_size;
i2s_dma_t *tx;
i2s_dma_t *rx;
#if SOC_GDMA_SUPPORTED
gdma_channel_handle_t rx_dma_chan;
gdma_channel_handle_t tx_dma_chan; /* ... */
#else
intr_handle_t i2s_isr_handle;
#endif
uint32_t dma_desc_num;
uint32_t dma_frame_num;
bool tx_desc_auto_clear;
bool use_apll;
int fixed_mclk;
i2s_mclk_multiple_t mclk_multiple;
#if CONFIG_IDF_TARGET_ESP32
esp_clock_output_mapping_handle_t mclk_out_hdl;
#endif
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock;
#endif
i2s_hal_context_t hal;
i2s_dir_t dir;
i2s_role_t role;
i2s_comm_mode_t mode;
i2s_hal_slot_config_t slot_cfg;
i2s_clk_config_t clk_cfg;
uint32_t active_slot;
uint32_t total_slot;
}{ ... } i2s_obj_t;
static i2s_obj_t *p_i2s[SOC_I2S_NUM] = {
[0 ... SOC_I2S_NUM - 1] = NULL,
}{...};
static portMUX_TYPE i2s_spinlock[SOC_I2S_NUM] = {
[0 ... SOC_I2S_NUM - 1] = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED,
}{...};
/* ... */
#if SOC_GDMA_SUPPORTED
static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
{
i2s_obj_t *p_i2s = (i2s_obj_t *) user_data;
BaseType_t need_awoke = 0;
BaseType_t tmp = 0;
int dummy;
i2s_event_t i2s_event;
lldesc_t *finish_desc;
if (p_i2s->rx) {
finish_desc = (lldesc_t *)event_data->rx_eof_desc_addr;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_cache_msync((void *)finish_desc->buf, p_i2s->rx->buf_size, ESP_CACHE_MSYNC_FLAG_INVALIDATE);
#endif
i2s_event.size = finish_desc->size;
if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) {
xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &tmp);
need_awoke |= tmp;
if (p_i2s->i2s_queue) {
i2s_event.type = I2S_EVENT_RX_Q_OVF;
xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &tmp);
need_awoke |= tmp;
}{...}
}{...}
xQueueSendFromISR(p_i2s->rx->queue, &finish_desc->buf, &tmp);
need_awoke |= tmp;
if (p_i2s->i2s_queue) {
i2s_event.type = I2S_EVENT_RX_DONE;
xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &tmp);
need_awoke |= tmp;
}{...}
}{...}
return need_awoke;
}{...}
static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
{
i2s_obj_t *p_i2s = (i2s_obj_t *) user_data;
BaseType_t need_awoke = 0;
BaseType_t tmp = 0;
int dummy;
i2s_event_t i2s_event;
lldesc_t *finish_desc;
if (p_i2s->tx) {
finish_desc = (lldesc_t *)event_data->tx_eof_desc_addr;
i2s_event.size = finish_desc->size;
if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) {
xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &tmp);
need_awoke |= tmp;
if (p_i2s->i2s_queue) {
i2s_event.type = I2S_EVENT_TX_Q_OVF;
i2s_event.size = p_i2s->tx->buf_size;
xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &tmp);
need_awoke |= tmp;
}{...}
}{...}
if (p_i2s->tx_desc_auto_clear) {
uint8_t *sent_buf = (uint8_t *)finish_desc->buf;
memset(sent_buf, 0, p_i2s->tx->buf_size);
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_cache_msync(sent_buf, p_i2s->tx->buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
#endif
}{...}
xQueueSendFromISR(p_i2s->tx->queue, &finish_desc->buf, &tmp);
need_awoke |= tmp;
if (p_i2s->i2s_queue) {
i2s_event.type = I2S_EVENT_TX_DONE;
xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &tmp);
need_awoke |= tmp;
}{...}
}{...}
return need_awoke;
}{...}
/* ... */
#else
static void IRAM_ATTR i2s_intr_handler_default(void *arg)
{
i2s_obj_t *p_i2s = (i2s_obj_t *) arg;
uint32_t status = i2s_hal_get_intr_status(&(p_i2s->hal));
if (status == 0) {
return;
}{...}
i2s_event_t i2s_event;
int dummy;
BaseType_t need_awoke = 0;
BaseType_t tmp = 0;
uint32_t finish_desc = 0;
if ((status & I2S_LL_EVENT_TX_DSCR_ERR) || (status & I2S_LL_EVENT_RX_DSCR_ERR)) {
ESP_EARLY_LOGE(TAG, "dma error, interrupt status: 0x%08" PRIx32, status);
if (p_i2s->i2s_queue) {
i2s_event.type = I2S_EVENT_DMA_ERROR;
if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) {
xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &tmp);
need_awoke |= tmp;
}{...}
xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &tmp);
need_awoke |= tmp;
}{...}
}{...}
if ((status & I2S_LL_EVENT_TX_EOF) && p_i2s->tx) {
i2s_hal_get_out_eof_des_addr(&(p_i2s->hal), &finish_desc);
i2s_event.size = ((lldesc_t *)finish_desc)->size;
if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) {
xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &tmp);
need_awoke |= tmp;
if (p_i2s->i2s_queue) {
i2s_event.type = I2S_EVENT_TX_Q_OVF;
xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &tmp);
need_awoke |= tmp;
}{...}
}{...}
if (p_i2s->tx_desc_auto_clear == true) {
memset((void *)(((lldesc_t *)finish_desc)->buf), 0, p_i2s->tx->buf_size);
}{...}
xQueueSendFromISR(p_i2s->tx->queue, &(((lldesc_t *)finish_desc)->buf), &tmp);
need_awoke |= tmp;
if (p_i2s->i2s_queue) {
i2s_event.type = I2S_EVENT_TX_DONE;
xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &tmp);
need_awoke |= tmp;
}{...}
}{...}
if ((status & I2S_LL_EVENT_RX_EOF) && p_i2s->rx) {
i2s_hal_get_in_eof_des_addr(&(p_i2s->hal), &finish_desc);
i2s_event.size = ((lldesc_t *)finish_desc)->size;
if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) {
xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &tmp);
need_awoke |= tmp;
if (p_i2s->i2s_queue) {
i2s_event.type = I2S_EVENT_RX_Q_OVF;
xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &tmp);
need_awoke |= tmp;
}{...}
}{...}
xQueueSendFromISR(p_i2s->rx->queue, &(((lldesc_t *)finish_desc)->buf), &tmp);
need_awoke |= tmp;
if (p_i2s->i2s_queue) {
i2s_event.type = I2S_EVENT_RX_DONE;
xQueueSendFromISR(p_i2s->i2s_queue, (void *)&i2s_event, &tmp);
need_awoke |= tmp;
}{...}
}{...}
i2s_hal_clear_intr_status(&(p_i2s->hal), status);
if (need_awoke == pdTRUE) {
portYIELD_FROM_ISR();
}{...}
}{ ... }
/* ... */#endif
static esp_err_t i2s_dma_intr_init(i2s_port_t i2s_num, int intr_flag)
{
#if SOC_GDMA_SUPPORTED
gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S};
switch (i2s_num) {
#if SOC_I2S_NUM > 2
case I2S_NUM_2:
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S2;
break;/* ... */
#endif
#if SOC_I2S_NUM > 1
case I2S_NUM_1:
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S1;
break;/* ... */
#endif
case I2S_NUM_0:
trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0;
break;...
default:
ESP_LOGE(TAG, "Unsupported I2S port number");
return ESP_ERR_NOT_SUPPORTED;...
}{...}
gdma_channel_alloc_config_t dma_cfg = {};
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX;
ESP_RETURN_ON_ERROR(gdma_new_ahb_channel(&dma_cfg, &p_i2s[i2s_num]->tx_dma_chan), TAG, "Register tx dma channel error");
ESP_RETURN_ON_ERROR(gdma_connect(p_i2s[i2s_num]->tx_dma_chan, trig), TAG, "Connect tx dma channel error");
gdma_tx_event_callbacks_t cb = {.on_trans_eof = i2s_dma_tx_callback};
gdma_register_tx_event_callbacks(p_i2s[i2s_num]->tx_dma_chan, &cb, p_i2s[i2s_num]);
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
dma_cfg.direction = GDMA_CHANNEL_DIRECTION_RX;
ESP_RETURN_ON_ERROR(gdma_new_ahb_channel(&dma_cfg, &p_i2s[i2s_num]->rx_dma_chan), TAG, "Register rx dma channel error");
ESP_RETURN_ON_ERROR(gdma_connect(p_i2s[i2s_num]->rx_dma_chan, trig), TAG, "Connect rx dma channel error");
gdma_rx_event_callbacks_t cb = {.on_recv_eof = i2s_dma_rx_callback};
gdma_register_rx_event_callbacks(p_i2s[i2s_num]->rx_dma_chan, &cb, p_i2s[i2s_num]);
}{...}
#else/* ... */
ESP_RETURN_ON_ERROR(esp_intr_alloc(i2s_periph_signal[i2s_num].irq, intr_flag, i2s_intr_handler_default, p_i2s[i2s_num], &p_i2s[i2s_num]->i2s_isr_handle), TAG, "Register I2S Interrupt error");/* ... */
#endif
return ESP_OK;
}{ ... }
static void i2s_tx_reset(i2s_port_t i2s_num)
{
p_i2s[i2s_num]->tx->curr_ptr = NULL;
p_i2s[i2s_num]->tx->rw_pos = 0;
i2s_hal_tx_reset(&(p_i2s[i2s_num]->hal));
#if SOC_GDMA_SUPPORTED
gdma_reset(p_i2s[i2s_num]->tx_dma_chan);
#else
i2s_hal_tx_reset_dma(&(p_i2s[i2s_num]->hal));
#endif
i2s_hal_tx_reset_fifo(&(p_i2s[i2s_num]->hal));
}{ ... }
/* ... */
static void i2s_rx_reset(i2s_port_t i2s_num)
{
p_i2s[i2s_num]->rx->curr_ptr = NULL;
p_i2s[i2s_num]->rx->rw_pos = 0;
i2s_hal_rx_reset(&(p_i2s[i2s_num]->hal));
#if SOC_GDMA_SUPPORTED
gdma_reset(p_i2s[i2s_num]->rx_dma_chan);
#else
i2s_hal_rx_reset_dma(&(p_i2s[i2s_num]->hal));
#endif
i2s_hal_rx_reset_fifo(&(p_i2s[i2s_num]->hal));
}{ ... }
static void i2s_tx_start(i2s_port_t i2s_num)
{
#if SOC_GDMA_SUPPORTED
gdma_start(p_i2s[i2s_num]->tx_dma_chan, (uint32_t) p_i2s[i2s_num]->tx->desc[0]);
#else
i2s_hal_tx_enable_dma(&(p_i2s[i2s_num]->hal));
i2s_hal_tx_enable_intr(&(p_i2s[i2s_num]->hal));
i2s_hal_tx_start_link(&(p_i2s[i2s_num]->hal), (uint32_t) p_i2s[i2s_num]->tx->desc[0]);/* ... */
#endif
i2s_hal_tx_start(&(p_i2s[i2s_num]->hal));
}{ ... }
static void i2s_rx_start(i2s_port_t i2s_num)
{
#if SOC_GDMA_SUPPORTED
gdma_start(p_i2s[i2s_num]->rx_dma_chan, (uint32_t) p_i2s[i2s_num]->rx->desc[0]);
#else
i2s_hal_rx_enable_dma(&(p_i2s[i2s_num]->hal));
i2s_hal_rx_enable_intr(&(p_i2s[i2s_num]->hal));
i2s_hal_rx_start_link(&(p_i2s[i2s_num]->hal), (uint32_t) p_i2s[i2s_num]->rx->desc[0]);/* ... */
#endif
i2s_hal_rx_start(&(p_i2s[i2s_num]->hal));
}{ ... }
static void i2s_tx_stop(i2s_port_t i2s_num)
{
i2s_hal_tx_stop(&(p_i2s[i2s_num]->hal));
#if SOC_GDMA_SUPPORTED
gdma_stop(p_i2s[i2s_num]->tx_dma_chan);
#else
i2s_hal_tx_stop_link(&(p_i2s[i2s_num]->hal));
i2s_hal_tx_disable_intr(&(p_i2s[i2s_num]->hal));
i2s_hal_tx_disable_dma(&(p_i2s[i2s_num]->hal));/* ... */
#endif
}{ ... }
static void i2s_rx_stop(i2s_port_t i2s_num)
{
i2s_hal_rx_stop(&(p_i2s[i2s_num]->hal));
#if SOC_GDMA_SUPPORTED
gdma_stop(p_i2s[i2s_num]->rx_dma_chan);
#else
i2s_hal_rx_stop_link(&(p_i2s[i2s_num]->hal));
i2s_hal_rx_disable_intr(&(p_i2s[i2s_num]->hal));
i2s_hal_rx_disable_dma(&(p_i2s[i2s_num]->hal));/* ... */
#endif
}{ ... }
esp_err_t i2s_start(i2s_port_t i2s_num)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
I2S_ENTER_CRITICAL(i2s_num);
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_tx_reset(i2s_num);
i2s_tx_start(i2s_num);
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_rx_reset(i2s_num);
i2s_rx_start(i2s_num);
}{...}
#if !SOC_GDMA_SUPPORTED
esp_intr_enable(p_i2s[i2s_num]->i2s_isr_handle);
#endif
I2S_EXIT_CRITICAL(i2s_num);
return ESP_OK;
}{ ... }
esp_err_t i2s_stop(i2s_port_t i2s_num)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
I2S_ENTER_CRITICAL(i2s_num);
#if !SOC_GDMA_SUPPORTED
esp_intr_disable(p_i2s[i2s_num]->i2s_isr_handle);
#endif
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_tx_stop(i2s_num);
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_rx_stop(i2s_num);
}{...}
#if !SOC_GDMA_SUPPORTED
i2s_hal_clear_intr_status(&(p_i2s[i2s_num]->hal), I2S_INTR_MAX);
#endif
I2S_EXIT_CRITICAL(i2s_num);
return ESP_OK;
}{ ... }
/* ... */
static inline uint32_t i2s_get_buf_size(i2s_port_t i2s_num)
{
i2s_hal_slot_config_t *slot_cfg = &p_i2s[i2s_num]->slot_cfg;
uint32_t bytes_per_sample = ((slot_cfg->data_bit_width + 15) / 16) * 2;
uint32_t bytes_per_frame = bytes_per_sample * p_i2s[i2s_num]->active_slot;
p_i2s[i2s_num]->dma_frame_num = (p_i2s[i2s_num]->dma_frame_num * bytes_per_frame > I2S_DMA_BUFFER_MAX_SIZE) ?
I2S_DMA_BUFFER_MAX_SIZE / bytes_per_frame : p_i2s[i2s_num]->dma_frame_num;
uint32_t bufsize = p_i2s[i2s_num]->dma_frame_num * bytes_per_frame;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
uint32_t alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
uint32_t aligned_frame_num = p_i2s[i2s_num]->dma_frame_num;
/* ... */
for (int sign = 1; bufsize % alignment != 0; aligned_frame_num += sign) {
bufsize = aligned_frame_num * bytes_per_frame;
if (bufsize > I2S_DMA_BUFFER_MAX_SIZE) {
sign = -1;
aligned_frame_num = p_i2s[i2s_num]->dma_frame_num;
bufsize = aligned_frame_num * bytes_per_frame;
}{...}
}{...}
if (bufsize / bytes_per_frame != p_i2s[i2s_num]->dma_frame_num) {
ESP_LOGW(TAG, "dma frame num is adjusted to %"PRIu32" to align the dma buffer with %"PRIu32
", bufsize = %"PRIu32, bufsize / bytes_per_frame, alignment, bufsize);
}{...}
#else/* ... */
if (bufsize > I2S_DMA_BUFFER_MAX_SIZE) {
uint32_t frame_num = I2S_DMA_BUFFER_MAX_SIZE / bytes_per_frame;
bufsize = frame_num * bytes_per_frame;
ESP_LOGW(TAG, "dma frame num is out of dma buffer size, limited to %"PRIu32, frame_num);
}{...}
#endif/* ... */
return bufsize;
}{ ... }
static esp_err_t i2s_delete_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj)
{
ESP_RETURN_ON_FALSE(dma_obj, ESP_ERR_INVALID_ARG, TAG, "I2S DMA object can't be NULL");
uint32_t buf_cnt = p_i2s[i2s_num]->dma_desc_num;
for (int cnt = 0; cnt < buf_cnt; cnt++) {
if (dma_obj->desc && dma_obj->desc[cnt]) {
free(dma_obj->desc[cnt]);
dma_obj->desc[cnt] = NULL;
}{...}
if (dma_obj->buf && dma_obj->buf[cnt]) {
free(dma_obj->buf[cnt]);
dma_obj->buf[cnt] = NULL;
}{...}
}{...}
return ESP_OK;
}{ ... }
static esp_err_t i2s_alloc_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj)
{
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_FALSE(dma_obj, ESP_ERR_INVALID_ARG, err, TAG, "I2S DMA object can't be NULL");
uint32_t buf_cnt = p_i2s[i2s_num]->dma_desc_num;
for (int cnt = 0; cnt < buf_cnt; cnt++) {
dma_obj->buf[cnt] = heap_caps_aligned_calloc(4, 1, sizeof(char) * dma_obj->buf_size,
MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
ESP_GOTO_ON_FALSE(dma_obj->buf[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma buffer");
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_cache_msync(dma_obj->buf[cnt], dma_obj->buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
#endif
dma_obj->desc[cnt] = heap_caps_aligned_calloc(4, 1, sizeof(lldesc_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
ESP_GOTO_ON_FALSE(dma_obj->desc[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma description entry");
}{...}
for (int cnt = 0; cnt < buf_cnt; cnt++) {
dma_obj->desc[cnt]->owner = 1;
dma_obj->desc[cnt]->eof = 1;
dma_obj->desc[cnt]->sosf = 0;
dma_obj->desc[cnt]->length = dma_obj->buf_size;
dma_obj->desc[cnt]->size = dma_obj->buf_size;
dma_obj->desc[cnt]->buf = (uint8_t *) dma_obj->buf[cnt];
dma_obj->desc[cnt]->offset = 0;
dma_obj->desc[cnt]->empty = (uint32_t)((cnt < (buf_cnt - 1)) ? (dma_obj->desc[cnt + 1]) : dma_obj->desc[0]);
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_cache_msync(dma_obj->desc[cnt], sizeof(lldesc_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
#endif
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_ll_rx_set_eof_num(p_i2s[i2s_num]->hal.dev, dma_obj->buf_size);
}{...}
ESP_LOGD(TAG, "DMA Malloc info, datalen=blocksize=%d, dma_desc_num=%"PRIu32, dma_obj->buf_size, buf_cnt);
return ESP_OK;
err:
i2s_delete_dma_buffer(i2s_num, dma_obj);
return ret;
}{ ... }
static esp_err_t i2s_realloc_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj)
{
ESP_RETURN_ON_FALSE(dma_obj, ESP_ERR_INVALID_ARG, TAG, "I2S DMA object can't be NULL");
i2s_delete_dma_buffer(i2s_num, dma_obj);
ESP_RETURN_ON_ERROR(i2s_alloc_dma_buffer(i2s_num, dma_obj), TAG, "Failed to allocate dma buffer");
return ESP_OK;
}{ ... }
static esp_err_t i2s_destroy_dma_object(i2s_port_t i2s_num, i2s_dma_t **dma)
{
ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_ARG, TAG, "I2S not initialized yet");
if (!(*dma)) {
return ESP_OK;
}{...}
i2s_delete_dma_buffer(i2s_num, (*dma));
if ((*dma)->desc) {
free((*dma)->desc);
(*dma)->desc = NULL;
}{...}
if ((*dma)->buf) {
free((*dma)->buf);
(*dma)->buf = NULL;
}{...}
vSemaphoreDelete((*dma)->mux);
vQueueDelete((*dma)->queue);
free(*dma);
*dma = NULL;
ESP_LOGD(TAG, "DMA queue destroyed");
return ESP_OK;
}{ ... }
static esp_err_t i2s_create_dma_object(i2s_port_t i2s_num, i2s_dma_t **dma)
{
ESP_RETURN_ON_FALSE(dma, ESP_ERR_INVALID_ARG, TAG, "DMA object secondary pointer is NULL");
ESP_RETURN_ON_FALSE((*dma == NULL), ESP_ERR_INVALID_ARG, TAG, "DMA object has been created");
uint32_t buf_cnt = p_i2s[i2s_num]->dma_desc_num;
*dma = (i2s_dma_t *) calloc(1, sizeof(i2s_dma_t));
ESP_RETURN_ON_FALSE(*dma, ESP_ERR_NO_MEM, TAG, "DMA object allocate failed");
(*dma)->buf = (char **)heap_caps_calloc(buf_cnt, sizeof(char *), MALLOC_CAP_DMA);
if (!(*dma)->buf) {
goto err;
}{...}
(*dma)->desc = (lldesc_t **)heap_caps_calloc(buf_cnt, sizeof(lldesc_t *), MALLOC_CAP_DMA);
if (!(*dma)->desc) {
goto err;
}{...}
(*dma)->queue = xQueueCreate(buf_cnt - 1, sizeof(char *));
if (!(*dma)->queue) {
goto err;
}{...}
(*dma)->mux = xSemaphoreCreateMutex();
if (!(*dma)->mux) {
goto err;
}{...}
return ESP_OK;
err:
ESP_LOGE(TAG, "I2S DMA object create failed, preparing to uninstall");
i2s_destroy_dma_object(i2s_num, dma);
return ESP_ERR_NO_MEM;
}{ ... }
/* ... */
static uint32_t i2s_config_source_clock(i2s_port_t i2s_num, bool use_apll, uint32_t mclk)
{
#if SOC_I2S_SUPPORTS_APLL
if (use_apll) {
int div = (int)((CLK_LL_APLL_MIN_HZ / mclk) + 1);
/* ... */
div = div < 2 ? 2 : div;
uint32_t expt_freq = mclk * div;
uint32_t real_freq = 0;
esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq);
if (ret == ESP_ERR_INVALID_ARG) {
ESP_LOGE(TAG, "set APLL coefficients failed");
return 0;
}{...}
if (ret == ESP_ERR_INVALID_STATE) {
ESP_LOGW(TAG, "APLL is occupied already, it is working at %"PRIu32" Hz", real_freq);
}{...}
ESP_LOGD(TAG, "APLL expected frequency is %"PRIu32" Hz, real frequency is %"PRIu32" Hz", expt_freq, real_freq);
return real_freq;
}{...}
return I2S_LL_DEFAULT_CLK_FREQ;/* ... */
#else
if (use_apll) {
ESP_LOGW(TAG, "APLL not supported on current chip, use I2S_CLK_SRC_DEFAULT as default clock source");
}{...}
return I2S_LL_DEFAULT_CLK_FREQ;/* ... */
#endif
}{ ... }
#if SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC
static esp_err_t i2s_calculate_adc_dac_clock(int i2s_num, i2s_hal_clock_info_t *clk_info)
{
/* ... */
i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg;
i2s_hal_slot_config_t *slot_cfg = &p_i2s[i2s_num]->slot_cfg;
uint32_t slot_bits = slot_cfg->slot_bit_width;
clk_info->bclk = clk_cfg->sample_rate_hz * I2S_LL_AD_BCK_FACTOR;
clk_info->bclk_div = slot_bits;
clk_info->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ?
p_i2s[i2s_num]->fixed_mclk : clk_info->bclk * clk_info->bclk_div;
clk_info->bclk_div = clk_info->mclk / clk_info->bclk;
clk_info->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_info->mclk);
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large, the mclk division is below minimum value 2");
ESP_RETURN_ON_FALSE(clk_info->mclk_div < 256, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small, the mclk division exceed the maximum value 255");
return ESP_OK;
}{ ... }
/* ... */#endif
#if SOC_I2S_SUPPORTS_PDM_TX
static esp_err_t i2s_calculate_pdm_tx_clock(int i2s_num, i2s_hal_clock_info_t *clk_info)
{
i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg;
int fp = clk_cfg->up_sample_fp;
int fs = clk_cfg->up_sample_fs;
clk_info->bclk = clk_cfg->sample_rate_hz * I2S_LL_PDM_BCK_FACTOR * fp / fs;
clk_info->bclk_div = 8;
clk_info->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ?
p_i2s[i2s_num]->fixed_mclk : clk_info->bclk * clk_info->bclk_div;
clk_info->bclk_div = clk_info->mclk / clk_info->bclk;
clk_info->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_info->mclk);
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large, the mclk division is below minimum value 2");
ESP_RETURN_ON_FALSE(clk_info->mclk_div < 256, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small, the mclk division exceed the maximum value 255");
return ESP_OK;
}{ ... }
/* ... */#endif
#if SOC_I2S_SUPPORTS_PDM_RX
static esp_err_t i2s_calculate_pdm_rx_clock(int i2s_num, i2s_hal_clock_info_t *clk_info)
{
i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg;
i2s_pdm_dsr_t dsr = clk_cfg->dn_sample_mode;
clk_info->bclk = clk_cfg->sample_rate_hz * I2S_LL_PDM_BCK_FACTOR * (dsr == I2S_PDM_DSR_16S ? 2 : 1);
clk_info->bclk_div = 8;
clk_info->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ?
p_i2s[i2s_num]->fixed_mclk : clk_info->bclk * clk_info->bclk_div;
clk_info->bclk_div = clk_info->mclk / clk_info->bclk;
clk_info->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_info->mclk);
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large, the mclk division is below minimum value 2");
ESP_RETURN_ON_FALSE(clk_info->mclk_div < 256, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small, the mclk division exceed the maximum value 255");
return ESP_OK;
}{ ... }
/* ... */#endif
static esp_err_t i2s_calculate_common_clock(int i2s_num, i2s_hal_clock_info_t *clk_info)
{
i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg;
i2s_hal_slot_config_t *slot_cfg = &p_i2s[i2s_num]->slot_cfg;
uint32_t rate = clk_cfg->sample_rate_hz;
uint32_t slot_num = p_i2s[i2s_num]->total_slot < 2 ? 2 : p_i2s[i2s_num]->total_slot;
uint32_t slot_bits = slot_cfg->slot_bit_width;
if (p_i2s[i2s_num]->role == I2S_ROLE_MASTER) {
clk_info->bclk = rate * slot_num * slot_bits;
clk_info->mclk = rate * clk_cfg->mclk_multiple;
clk_info->bclk_div = clk_info->mclk / clk_info->bclk;
}{...} else {
clk_info->bclk_div = 8;
clk_info->bclk = rate * slot_num * slot_bits;
clk_info->mclk = clk_info->bclk * clk_info->bclk_div;
}{...}
clk_info->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_info->mclk);
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
ESP_RETURN_ON_FALSE(clk_info->mclk <= clk_info->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
return ESP_OK;
}{ ... }
static esp_err_t i2s_calculate_clock(i2s_port_t i2s_num, i2s_hal_clock_info_t *clk_info)
{
#if SOC_I2S_SUPPORTS_ADC_DAC
if ((int)p_i2s[i2s_num]->mode == I2S_COMM_MODE_ADC_DAC) {
ESP_RETURN_ON_ERROR(i2s_calculate_adc_dac_clock(i2s_num, clk_info), TAG, "ADC/DAC clock calculate failed");
return ESP_OK;
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_PDM
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_PDM) {
#if SOC_I2S_SUPPORTS_PDM_TX
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
ESP_RETURN_ON_ERROR(i2s_calculate_pdm_tx_clock(i2s_num, clk_info), TAG, "PDM TX clock calculate failed");
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_PDM_RX
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
ESP_RETURN_ON_ERROR(i2s_calculate_pdm_rx_clock(i2s_num, clk_info), TAG, "PDM RX clock calculate failed");
}{...}
#endif/* ... */
return ESP_OK;
}{...}
#endif/* ... */
ESP_RETURN_ON_ERROR(i2s_calculate_common_clock(i2s_num, clk_info), TAG, "Common clock calculate failed");
ESP_LOGD(TAG, "[sclk] %"PRIu32" [mclk] %"PRIu32" [mclk_div] %d [bclk] %"PRIu32" [bclk_div] %d",
clk_info->sclk, clk_info->mclk, clk_info->mclk_div, clk_info->bclk, clk_info->bclk_div);
return ESP_OK;
}{ ... }
/* ... */
#if SOC_I2S_SUPPORTS_ADC_DAC
static void i2s_dac_set_slot_legacy(void)
{
i2s_dev_t *dev = p_i2s[0]->hal.dev;
i2s_hal_slot_config_t *slot_cfg = &p_i2s[0]->slot_cfg;
i2s_ll_tx_reset(dev);
i2s_ll_tx_set_slave_mod(dev, false);
i2s_ll_tx_set_sample_bit(dev, slot_cfg->slot_bit_width, slot_cfg->data_bit_width);
i2s_ll_tx_enable_mono_mode(dev, slot_cfg->slot_mode == I2S_SLOT_MODE_MONO);
i2s_ll_tx_enable_msb_shift(dev, false);
i2s_ll_tx_set_ws_width(dev, slot_cfg->slot_bit_width);
i2s_ll_tx_enable_msb_right(dev, false);
i2s_ll_tx_enable_right_first(dev, true);
i2s_ll_tx_force_enable_fifo_mod(dev, true);
}{ ... }
esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode)
{
ESP_RETURN_ON_FALSE((dac_mode < I2S_DAC_CHANNEL_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s dac mode error");
if (dac_mode == I2S_DAC_CHANNEL_DISABLE) {
dac_ll_power_down(DAC_CHAN_0);
dac_ll_power_down(DAC_CHAN_1);
dac_ll_digi_enable_dma(false);
}{...} else {
dac_ll_digi_enable_dma(true);
}{...}
if (dac_mode & I2S_DAC_CHANNEL_RIGHT_EN) {
dac_ll_power_on(DAC_CHAN_0);
dac_ll_rtc_sync_by_adc(false);
}{...}
if (dac_mode & I2S_DAC_CHANNEL_LEFT_EN) {
dac_ll_power_on(DAC_CHAN_1);
dac_ll_rtc_sync_by_adc(false);
}{...}
return ESP_OK;
}{ ... }
static void i2s_adc_set_slot_legacy(void)
{
i2s_dev_t *dev = p_i2s[0]->hal.dev;
i2s_hal_slot_config_t *slot_cfg = &p_i2s[0]->slot_cfg;
i2s_ll_rx_set_slave_mod(dev, false);
i2s_ll_rx_set_sample_bit(dev, slot_cfg->slot_bit_width, slot_cfg->data_bit_width);
i2s_ll_rx_enable_mono_mode(dev, true);
i2s_ll_rx_enable_msb_shift(dev, false);
i2s_ll_rx_set_ws_width(dev, slot_cfg->slot_bit_width);
i2s_ll_rx_enable_msb_right(dev, false);
i2s_ll_rx_enable_right_first(dev, false);
i2s_ll_rx_select_std_slot(dev, I2S_STD_SLOT_LEFT, false);
i2s_ll_rx_force_enable_fifo_mod(dev, true);
}{ ... }
static int _i2s_adc_unit = -1;
static int _i2s_adc_channel = -1;
static esp_err_t _i2s_adc_mode_recover(void)
{
ESP_RETURN_ON_FALSE(((_i2s_adc_unit != -1) && (_i2s_adc_channel != -1)), ESP_ERR_INVALID_ARG, TAG, "i2s ADC recover error, not initialized...");
return adc_i2s_mode_init(_i2s_adc_unit, _i2s_adc_channel);
}{ ... }
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel)
{
ESP_RETURN_ON_FALSE((adc_unit < ADC_UNIT_2), ESP_ERR_INVALID_ARG, TAG, "i2s ADC unit error, only support ADC1 for now");
_i2s_adc_unit = adc_unit;
_i2s_adc_channel = adc_channel;
return adc_i2s_mode_init(adc_unit, adc_channel);
}{ ... }
esp_err_t i2s_adc_enable(i2s_port_t i2s_num)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
ESP_RETURN_ON_FALSE((p_i2s[i2s_num] != NULL), ESP_ERR_INVALID_STATE, TAG, "Not initialized yet");
ESP_RETURN_ON_FALSE(((int)p_i2s[i2s_num]->mode == I2S_COMM_MODE_ADC_DAC) && (p_i2s[i2s_num]->dir & I2S_DIR_RX),
ESP_ERR_INVALID_STATE, TAG, "i2s built-in adc not enabled");
adc1_dma_mode_acquire();
_i2s_adc_mode_recover();
i2s_rx_reset(i2s_num);
return i2s_start(i2s_num);
}{ ... }
esp_err_t i2s_adc_disable(i2s_port_t i2s_num)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
ESP_RETURN_ON_FALSE((p_i2s[i2s_num] != NULL), ESP_ERR_INVALID_STATE, TAG, "Not initialized yet");
ESP_RETURN_ON_FALSE(((int)p_i2s[i2s_num]->mode == I2S_COMM_MODE_ADC_DAC) && (p_i2s[i2s_num]->dir & I2S_DIR_RX),
ESP_ERR_INVALID_STATE, TAG, "i2s built-in adc not enabled");
i2s_hal_rx_stop(&(p_i2s[i2s_num]->hal));
adc1_lock_release();
return ESP_OK;
}{ ... }
#endif/* ... */
static esp_err_t i2s_check_cfg_validity(i2s_port_t i2s_num, const i2s_config_t *cfg)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
ESP_RETURN_ON_FALSE(p_i2s[i2s_num] == NULL, ESP_ERR_INVALID_STATE, TAG, "this i2s port is in use");
ESP_RETURN_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, TAG, "I2S configuration must not be NULL");
ESP_RETURN_ON_FALSE((cfg->dma_desc_num >= 2 && cfg->dma_desc_num <= 128), ESP_ERR_INVALID_ARG, TAG, "I2S buffer count less than 128 and more than 2");
ESP_RETURN_ON_FALSE((cfg->dma_frame_num >= 8 && cfg->dma_frame_num <= 1024), ESP_ERR_INVALID_ARG, TAG, "I2S buffer length at most 1024 and more than 8");
#if SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX
if (cfg->mode & I2S_MODE_PDM) {
ESP_RETURN_ON_FALSE(i2s_num == I2S_NUM_0, ESP_ERR_INVALID_ARG, TAG, "I2S PDM mode only support on I2S0");
#if !SOC_I2S_SUPPORTS_PDM_TX
ESP_RETURN_ON_FALSE(!(cfg->mode & I2S_MODE_TX), ESP_ERR_INVALID_ARG, TAG, "PDM does not support TX on this chip");
#endif
#if !SOC_I2S_SUPPORTS_PDM_RX
ESP_RETURN_ON_FALSE(!(cfg->mode & I2S_MODE_RX), ESP_ERR_INVALID_ARG, TAG, "PDM does not support RX on this chip");
#endif
}{...}
#else/* ... */
ESP_RETURN_ON_FALSE(!(cfg->mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "I2S PDM mode not supported on current chip");
#endif
#if SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC
if (cfg->mode & (I2S_MODE_ADC_BUILT_IN | I2S_MODE_DAC_BUILT_IN)) {
ESP_RETURN_ON_FALSE(i2s_num == I2S_NUM_0, ESP_ERR_INVALID_ARG, TAG, "I2S built-in ADC/DAC only support on I2S0");
}{...}
#else/* ... */
ESP_RETURN_ON_FALSE((cfg->mode & I2S_MODE_TX) || (cfg->mode & I2S_MODE_RX), ESP_ERR_INVALID_ARG, TAG, "I2S no TX/RX mode selected");
ESP_RETURN_ON_FALSE(cfg->communication_format && (cfg->communication_format < I2S_COMM_FORMAT_STAND_MAX), ESP_ERR_INVALID_ARG, TAG, "invalid communication formats");/* ... */
#endif
return ESP_OK;
}{ ... }
static void i2s_set_slot_legacy(i2s_port_t i2s_num)
{
bool is_tx_slave = p_i2s[i2s_num]->role == I2S_ROLE_SLAVE;
bool is_rx_slave = is_tx_slave;
if (p_i2s[i2s_num]->dir == (I2S_DIR_TX | I2S_DIR_RX)) {
i2s_ll_share_bck_ws(p_i2s[i2s_num]->hal.dev, true);
/* ... */
is_rx_slave = true;
}{...} else {
i2s_ll_share_bck_ws(p_i2s[i2s_num]->hal.dev, false);
}{...}
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_STD) {
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_hal_std_set_tx_slot(&(p_i2s[i2s_num]->hal), is_tx_slave, (i2s_hal_slot_config_t *)(&p_i2s[i2s_num]->slot_cfg));
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_hal_std_set_rx_slot(&(p_i2s[i2s_num]->hal), is_rx_slave, (i2s_hal_slot_config_t *)(&p_i2s[i2s_num]->slot_cfg));
}{...}
}{...}
#if SOC_I2S_SUPPORTS_PDM
else if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_PDM) {
#if SOC_I2S_SUPPORTS_PDM_TX
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_hal_pdm_set_tx_slot(&(p_i2s[i2s_num]->hal), is_tx_slave, (i2s_hal_slot_config_t *)(&p_i2s[i2s_num]->slot_cfg));
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_PDM_RX
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_hal_pdm_set_rx_slot(&(p_i2s[i2s_num]->hal), is_rx_slave, (i2s_hal_slot_config_t *)(&p_i2s[i2s_num]->slot_cfg));
}{...}
#endif/* ... */
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_TDM
else if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_TDM) {
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_hal_tdm_set_tx_slot(&(p_i2s[i2s_num]->hal), is_tx_slave, (i2s_hal_slot_config_t *)(&p_i2s[i2s_num]->slot_cfg));
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_hal_tdm_set_rx_slot(&(p_i2s[i2s_num]->hal), is_rx_slave, (i2s_hal_slot_config_t *)(&p_i2s[i2s_num]->slot_cfg));
}{...}
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_ADC_DAC
else if ((int)p_i2s[i2s_num]->mode == I2S_COMM_MODE_ADC_DAC) {
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_dac_set_slot_legacy();
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_adc_set_slot_legacy();
}{...}
}{...}
#endif/* ... */
}{ ... }
static void i2s_set_clock_legacy(i2s_port_t i2s_num)
{
i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg;
i2s_hal_clock_info_t clk_info;
i2s_calculate_clock(i2s_num, &clk_info);
I2S_CLOCK_SRC_ATOMIC() {
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_hal_set_tx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src);
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_hal_set_rx_clock(&(p_i2s[i2s_num]->hal), &clk_info, clk_cfg->clk_src);
}{...}
}{...}
}{ ... }
float i2s_get_clk(i2s_port_t i2s_num)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg;
return (float)clk_cfg->sample_rate_hz;
}{ ... }
esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_channel_t ch)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_ARG, TAG, "I2S%d has not installed yet", i2s_num);
if (p_i2s[i2s_num]->dir & I2S_MODE_TX) {
xSemaphoreTake(p_i2s[i2s_num]->tx->mux, portMAX_DELAY);
}{...}
if (p_i2s[i2s_num]->dir & I2S_MODE_RX) {
xSemaphoreTake(p_i2s[i2s_num]->rx->mux, portMAX_DELAY);
}{...}
i2s_stop(i2s_num);
i2s_clk_config_t *clk_cfg = &p_i2s[i2s_num]->clk_cfg;
i2s_hal_slot_config_t *slot_cfg = &p_i2s[i2s_num]->slot_cfg;
clk_cfg->sample_rate_hz = rate;
slot_cfg->data_bit_width = bits_cfg & 0xFFFF;
ESP_RETURN_ON_FALSE((slot_cfg->data_bit_width % 8 == 0), ESP_ERR_INVALID_ARG, TAG, "Invalid bits per sample");
slot_cfg->slot_bit_width = (bits_cfg >> 16) > slot_cfg->data_bit_width ?
(bits_cfg >> 16) : slot_cfg->data_bit_width;
ESP_RETURN_ON_FALSE((slot_cfg->slot_bit_width % 8 == 0), ESP_ERR_INVALID_ARG, TAG, "Invalid bits per channel");
ESP_RETURN_ON_FALSE(((int)slot_cfg->slot_bit_width <= (int)I2S_BITS_PER_SAMPLE_32BIT), ESP_ERR_INVALID_ARG, TAG, "Invalid bits per sample");
slot_cfg->slot_mode = ((ch & 0xFFFF) == I2S_CHANNEL_MONO) ? I2S_SLOT_MODE_MONO : I2S_SLOT_MODE_STEREO;
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_STD) {
if (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) {
if (slot_cfg->std.slot_mask == I2S_STD_SLOT_BOTH) {
slot_cfg->std.slot_mask = I2S_STD_SLOT_LEFT;
#if SOC_I2S_HW_VERSION_1
slot_cfg->std.ws_pol = !slot_cfg->std.ws_pol;/* ... */
#endif
}{...}
}{...} else {
slot_cfg->std.slot_mask = I2S_STD_SLOT_BOTH;
}{...}
}{...}
#if SOC_I2S_SUPPORTS_TDM
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_TDM) {
uint32_t slot_mask = ch >> 16;
if (slot_mask == 0) {
slot_mask = (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? 1 : 2;
}{...}
ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->total_slot >= (32 - __builtin_clz(slot_mask)), ESP_ERR_INVALID_ARG, TAG,
"The max channel number can't be greater than CH%"PRIu32, p_i2s[i2s_num]->total_slot);
p_i2s[i2s_num]->active_slot = __builtin_popcount(slot_mask);
}{...} else
#endif
{
p_i2s[i2s_num]->active_slot = (slot_cfg->slot_mode == I2S_SLOT_MODE_MONO) ? 1 : 2;
}{...}
i2s_set_slot_legacy(i2s_num);
i2s_set_clock_legacy(i2s_num);
uint32_t buf_size = i2s_get_buf_size(i2s_num);
bool need_realloc = buf_size != p_i2s[i2s_num]->last_buf_size;
if (need_realloc) {
esp_err_t ret = ESP_OK;
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
p_i2s[i2s_num]->tx->buf_size = buf_size;
ret = i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->tx);
xQueueReset(p_i2s[i2s_num]->tx->queue);
ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d tx DMA buffer malloc failed", i2s_num);
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
p_i2s[i2s_num]->rx->buf_size = buf_size;
ret = i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->rx);
xQueueReset(p_i2s[i2s_num]->rx->queue);
ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d rx DMA buffer malloc failed", i2s_num);
}{...}
}{...}
p_i2s[i2s_num]->last_buf_size = buf_size;
i2s_start(i2s_num);
if (p_i2s[i2s_num]->dir & I2S_MODE_TX) {
xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
}{...}
if (p_i2s[i2s_num]->dir & I2S_MODE_RX) {
xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
}{...}
return ESP_OK;
}{ ... }
esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
i2s_hal_slot_config_t *slot_cfg = &p_i2s[i2s_num]->slot_cfg;
uint32_t mask = 0;
#if SOC_I2S_SUPPORTS_TDM
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_TDM) {
mask = slot_cfg->tdm.slot_mask;
}{...}
#endif/* ... */
return i2s_set_clk(i2s_num, rate, slot_cfg->data_bit_width, slot_cfg->slot_mode | (mask << 16));
}{ ... }
#if SOC_I2S_SUPPORTS_PCM
esp_err_t i2s_pcm_config(i2s_port_t i2s_num, const i2s_pcm_cfg_t *pcm_cfg)
{
ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet");
if (p_i2s[i2s_num]->dir & I2S_MODE_TX) {
xSemaphoreTake(p_i2s[i2s_num]->tx->mux, portMAX_DELAY);
}{...}
if (p_i2s[i2s_num]->dir & I2S_MODE_RX) {
xSemaphoreTake(p_i2s[i2s_num]->rx->mux, portMAX_DELAY);
}{...}
i2s_stop(i2s_num);
I2S_ENTER_CRITICAL(i2s_num);
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_ll_tx_set_pcm_type(p_i2s[i2s_num]->hal.dev, pcm_cfg->pcm_type);
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_ll_rx_set_pcm_type(p_i2s[i2s_num]->hal.dev, pcm_cfg->pcm_type);
}{...}
I2S_EXIT_CRITICAL(i2s_num);
i2s_start(i2s_num);
if (p_i2s[i2s_num]->dir & I2S_MODE_TX) {
xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
}{...}
if (p_i2s[i2s_num]->dir & I2S_MODE_RX) {
xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
}{...}
return ESP_OK;
}{...}
/* ... */#endif
#if SOC_I2S_SUPPORTS_PDM_RX
esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t downsample)
{
ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet");
ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode == I2S_COMM_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode");
xSemaphoreTake(p_i2s[i2s_num]->rx->mux, portMAX_DELAY);
i2s_stop(i2s_num);
p_i2s[i2s_num]->clk_cfg.dn_sample_mode = downsample;
i2s_ll_rx_set_pdm_dsr(p_i2s[i2s_num]->hal.dev, downsample);
i2s_start(i2s_num);
xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
return i2s_set_clk(i2s_num, p_i2s[i2s_num]->clk_cfg.sample_rate_hz, p_i2s[i2s_num]->slot_cfg.data_bit_width, p_i2s[i2s_num]->slot_cfg.slot_mode);
}{ ... }
/* ... */#endif
#if SOC_I2S_SUPPORTS_PDM_TX
esp_err_t i2s_set_pdm_tx_up_sample(i2s_port_t i2s_num, const i2s_pdm_tx_upsample_cfg_t *upsample_cfg)
{
ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet");
ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->mode == I2S_COMM_MODE_PDM) && (p_i2s[i2s_num]->dir & I2S_DIR_TX),
ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode");
xSemaphoreTake(p_i2s[i2s_num]->tx->mux, portMAX_DELAY);
i2s_stop(i2s_num);
p_i2s[i2s_num]->clk_cfg.up_sample_fp = upsample_cfg->fp;
p_i2s[i2s_num]->clk_cfg.up_sample_fs = upsample_cfg->fs;
i2s_ll_tx_set_pdm_fpfs(p_i2s[i2s_num]->hal.dev, upsample_cfg->fp, upsample_cfg->fs);
i2s_ll_tx_set_pdm_over_sample_ratio(p_i2s[i2s_num]->hal.dev, upsample_cfg->fp / upsample_cfg->fs);
i2s_start(i2s_num);
xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
return i2s_set_clk(i2s_num, p_i2s[i2s_num]->clk_cfg.sample_rate_hz, p_i2s[i2s_num]->slot_cfg.data_bit_width, p_i2s[i2s_num]->slot_cfg.slot_mode);
}{ ... }
/* ... */#endif
static esp_err_t i2s_dma_object_init(i2s_port_t i2s_num)
{
uint32_t buf_size = i2s_get_buf_size(i2s_num);
p_i2s[i2s_num]->last_buf_size = buf_size;
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
ESP_RETURN_ON_ERROR(i2s_create_dma_object(i2s_num, &p_i2s[i2s_num]->tx), TAG, "I2S TX DMA object create failed");
p_i2s[i2s_num]->tx->buf_size = buf_size;
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
ESP_RETURN_ON_ERROR(i2s_create_dma_object(i2s_num, &p_i2s[i2s_num]->rx), TAG, "I2S RX DMA object create failed");
p_i2s[i2s_num]->rx->buf_size = buf_size;
}{...}
return ESP_OK;
}{ ... }
static void i2s_mode_identify(i2s_port_t i2s_num, const i2s_config_t *i2s_config)
{
p_i2s[i2s_num]->mode = I2S_COMM_MODE_STD;
if (i2s_config->mode & I2S_MODE_MASTER) {
p_i2s[i2s_num]->role = I2S_ROLE_MASTER;
}{...} else if (i2s_config->mode & I2S_MODE_SLAVE) {
p_i2s[i2s_num]->role = I2S_ROLE_SLAVE;
}{...}
if (i2s_config->mode & I2S_MODE_TX) {
p_i2s[i2s_num]->dir |= I2S_DIR_TX;
}{...}
if (i2s_config->mode & I2S_MODE_RX) {
p_i2s[i2s_num]->dir |= I2S_DIR_RX;
}{...}
#if SOC_I2S_SUPPORTS_PDM
if (i2s_config->mode & I2S_MODE_PDM) {
p_i2s[i2s_num]->mode = I2S_COMM_MODE_PDM;
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_TDM
if (i2s_config->channel_format == I2S_CHANNEL_FMT_MULTIPLE) {
p_i2s[i2s_num]->mode = I2S_COMM_MODE_TDM;
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_ADC_DAC
if ((i2s_config->mode & I2S_MODE_DAC_BUILT_IN) ||
(i2s_config->mode & I2S_MODE_ADC_BUILT_IN)) {
p_i2s[i2s_num]->mode = (i2s_comm_mode_t)I2S_COMM_MODE_ADC_DAC;
}{...}
#endif/* ... */
}{ ... }
static esp_err_t i2s_config_transfer(i2s_port_t i2s_num, const i2s_config_t *i2s_config)
{
#define SLOT_CFG(m) p_i2s[i2s_num]->slot_cfg.m
#define CLK_CFG() p_i2s[i2s_num]->clk_cfg
p_i2s[i2s_num]->slot_cfg.data_bit_width = i2s_config->bits_per_sample;
p_i2s[i2s_num]->slot_cfg.slot_bit_width = (int)i2s_config->bits_per_chan < (int)i2s_config->bits_per_sample ?
i2s_config->bits_per_sample : i2s_config->bits_per_chan;
p_i2s[i2s_num]->slot_cfg.slot_mode = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ?
I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO;
CLK_CFG().sample_rate_hz = i2s_config->sample_rate;
CLK_CFG().mclk_multiple = i2s_config->mclk_multiple == 0 ? I2S_MCLK_MULTIPLE_256 : i2s_config->mclk_multiple;
CLK_CFG().clk_src = I2S_CLK_SRC_DEFAULT;
p_i2s[i2s_num]->fixed_mclk = i2s_config->fixed_mclk;
p_i2s[i2s_num]->use_apll = false;
#if SOC_I2S_SUPPORTS_APLL
CLK_CFG().clk_src = i2s_config->use_apll ? I2S_CLK_SRC_APLL : I2S_CLK_SRC_DEFAULT;
p_i2s[i2s_num]->use_apll = i2s_config->use_apll;/* ... */
#endif
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_STD) {
SLOT_CFG(std).ws_width = i2s_config->bits_per_sample;
SLOT_CFG(std).ws_pol = false;
if (i2s_config->channel_format == I2S_CHANNEL_FMT_RIGHT_LEFT) {
SLOT_CFG(std).slot_mask = I2S_STD_SLOT_BOTH;
}{...} else if (i2s_config->channel_format == I2S_CHANNEL_FMT_ALL_LEFT ||
i2s_config->channel_format == I2S_CHANNEL_FMT_ONLY_LEFT) {
SLOT_CFG(std).slot_mask = I2S_STD_SLOT_LEFT;
}{...} else {
SLOT_CFG(std).slot_mask = I2S_STD_SLOT_RIGHT;
}{...}
if (i2s_config->communication_format == I2S_COMM_FORMAT_STAND_I2S) {
SLOT_CFG(std).bit_shift = true;
}{...}
if (i2s_config->communication_format & I2S_COMM_FORMAT_STAND_PCM_SHORT) {
SLOT_CFG(std).bit_shift = true;
SLOT_CFG(std).ws_width = 1;
SLOT_CFG(std).ws_pol = true;
}{...}
#if SOC_I2S_HW_VERSION_1
SLOT_CFG(std).msb_right = true;
#elif SOC_I2S_HW_VERSION_2
SLOT_CFG(std).left_align = i2s_config->left_align;
SLOT_CFG(std).big_endian = i2s_config->big_edin;
SLOT_CFG(std).bit_order_lsb = i2s_config->bit_order_msb; /* ... */
#endif
p_i2s[i2s_num]->active_slot = (int)p_i2s[i2s_num]->slot_cfg.slot_mode == I2S_SLOT_MODE_MONO ? 1 : 2;
p_i2s[i2s_num]->total_slot = 2;
goto finish;
}{...}
#if SOC_I2S_SUPPORTS_PDM_TX
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_PDM) {
SLOT_CFG(pdm_tx).sd_prescale = 0;
SLOT_CFG(pdm_tx).sd_scale = I2S_PDM_SIG_SCALING_MUL_1;
SLOT_CFG(pdm_tx).hp_scale = I2S_PDM_SIG_SCALING_MUL_1;
SLOT_CFG(pdm_tx).lp_scale = I2S_PDM_SIG_SCALING_MUL_1;
SLOT_CFG(pdm_tx).sinc_scale = I2S_PDM_SIG_SCALING_MUL_1;
#if SOC_I2S_HW_VERSION_2
SLOT_CFG(pdm_tx).line_mode = I2S_PDM_TX_ONE_LINE_CODEC;
SLOT_CFG(pdm_tx).hp_en = true;
SLOT_CFG(pdm_tx).hp_cut_off_freq_hzx10 = 490;
SLOT_CFG(pdm_tx).sd_dither = 0;
SLOT_CFG(pdm_tx).sd_dither2 = 1;/* ... */
#endif
CLK_CFG().up_sample_fp = 960;
CLK_CFG().up_sample_fs = i2s_config->sample_rate / 100;
p_i2s[i2s_num]->active_slot = (int)p_i2s[i2s_num]->slot_cfg.slot_mode == I2S_SLOT_MODE_MONO ? 1 : 2;
p_i2s[i2s_num]->total_slot = 2;
goto finish;
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_PDM_RX
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_PDM) {
CLK_CFG().dn_sample_mode = I2S_PDM_DSR_8S;
p_i2s[i2s_num]->active_slot = (int)p_i2s[i2s_num]->slot_cfg.slot_mode == I2S_SLOT_MODE_MONO ? 1 : 2;
p_i2s[i2s_num]->total_slot = 2;
goto finish;
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_TDM
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_TDM) {
SLOT_CFG(tdm).slot_mask = i2s_config->chan_mask >> 16;
SLOT_CFG(tdm).ws_width = 0;
p_i2s[i2s_num]->slot_cfg.slot_mode = I2S_SLOT_MODE_STEREO;
SLOT_CFG(tdm).ws_pol = false;
if (i2s_config->communication_format == I2S_COMM_FORMAT_STAND_I2S) {
SLOT_CFG(tdm).bit_shift = true;
}{...} else if (i2s_config->communication_format == I2S_COMM_FORMAT_STAND_PCM_SHORT) {
SLOT_CFG(tdm).bit_shift = true;
SLOT_CFG(tdm).ws_width = 1;
SLOT_CFG(tdm).ws_pol = true;
}{...} else if (i2s_config->communication_format == I2S_COMM_FORMAT_STAND_PCM_LONG) {
SLOT_CFG(tdm).bit_shift = true;
SLOT_CFG(tdm).ws_width = p_i2s[i2s_num]->slot_cfg.slot_bit_width;
SLOT_CFG(tdm).ws_pol = true;
}{...}
SLOT_CFG(tdm).left_align = i2s_config->left_align;
SLOT_CFG(tdm).big_endian = i2s_config->big_edin;
SLOT_CFG(tdm).bit_order_lsb = i2s_config->bit_order_msb;
SLOT_CFG(tdm).skip_mask = i2s_config->skip_msk;
p_i2s[i2s_num]->active_slot = __builtin_popcount(SLOT_CFG(tdm).slot_mask);
uint32_t mx_slot = 32 - __builtin_clz(SLOT_CFG(tdm).slot_mask);
mx_slot = mx_slot < 2 ? 2 : mx_slot;
p_i2s[i2s_num]->total_slot = mx_slot < i2s_config->total_chan ? mx_slot : i2s_config->total_chan;
goto finish;
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_ADC_DAC
if ((int)p_i2s[i2s_num]->mode == I2S_COMM_MODE_ADC_DAC) {
p_i2s[i2s_num]->slot_cfg.slot_mode = (p_i2s[i2s_num]->dir & I2S_DIR_TX) ?
I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO;
p_i2s[i2s_num]->active_slot = (p_i2s[i2s_num]->dir & I2S_DIR_TX) ? 2 : 1;
p_i2s[i2s_num]->total_slot = 2;
}{...}
#endif/* ... */
#undef SLOT_CFG
#undef CLK_CFG
finish:
return ESP_OK;
}{ ... }
static esp_err_t i2s_init_legacy(i2s_port_t i2s_num, int intr_alloc_flag)
{
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_lock = ESP_PM_APB_FREQ_MAX;
ESP_RETURN_ON_ERROR(esp_pm_lock_create(pm_lock, 0, "i2s_driver", &p_i2s[i2s_num]->pm_lock), TAG, "I2S pm lock error");/* ... */
#endif
#if SOC_I2S_SUPPORTS_APLL
if (p_i2s[i2s_num]->use_apll) {
periph_rtc_apll_acquire();
}{...}
#endif/* ... */
if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_STD) {
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_hal_std_enable_tx_channel(&(p_i2s[i2s_num]->hal));
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_hal_std_enable_rx_channel(&(p_i2s[i2s_num]->hal));
}{...}
}{...}
#if SOC_I2S_SUPPORTS_PDM
else if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_PDM) {
#if SOC_I2S_SUPPORTS_PDM_TX
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_hal_pdm_enable_tx_channel(&(p_i2s[i2s_num]->hal));
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_PDM_RX
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_hal_pdm_enable_rx_channel(&(p_i2s[i2s_num]->hal));
}{...}
#endif/* ... */
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_TDM
else if (p_i2s[i2s_num]->mode == I2S_COMM_MODE_TDM) {
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_hal_tdm_enable_tx_channel(&(p_i2s[i2s_num]->hal));
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
i2s_hal_tdm_enable_rx_channel(&(p_i2s[i2s_num]->hal));
}{...}
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_ADC_DAC
if ((int)p_i2s[i2s_num]->mode == I2S_COMM_MODE_ADC_DAC) {
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
sar_periph_ctrl_adc_continuous_power_acquire();
adc_set_i2s_data_source(ADC_I2S_DATA_SRC_ADC);
i2s_ll_enable_builtin_adc_dac(p_i2s[i2s_num]->hal.dev, true);
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
i2s_ll_enable_builtin_adc_dac(p_i2s[i2s_num]->hal.dev, true);
}{...}
}{...} else {
adc_set_i2s_data_source(ADC_I2S_DATA_SRC_IO_SIG);
i2s_ll_enable_builtin_adc_dac(p_i2s[i2s_num]->hal.dev, false);
}{...}
#endif/* ... */
i2s_set_slot_legacy(i2s_num);
i2s_set_clock_legacy(i2s_num);
ESP_RETURN_ON_ERROR(i2s_dma_intr_init(i2s_num, intr_alloc_flag), TAG, "I2S interrupt initialize failed");
ESP_RETURN_ON_ERROR(i2s_dma_object_init(i2s_num), TAG, "I2S dma object create failed");
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
ESP_RETURN_ON_ERROR(i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->tx), TAG, "Allocate I2S dma tx buffer failed");
}{...}
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
ESP_RETURN_ON_ERROR(i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->rx), TAG, "Allocate I2S dma rx buffer failed");
}{...}
return ESP_OK;
}{ ... }
esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
{
ESP_RETURN_ON_FALSE(i2s_num < SOC_I2S_NUM, ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_STATE, TAG, "I2S port %d has not installed", i2s_num);
i2s_obj_t *obj = p_i2s[i2s_num];
i2s_stop(i2s_num);
#if CONFIG_IDF_TARGET_ESP32
if (obj->mclk_out_hdl) {
esp_clock_output_stop(obj->mclk_out_hdl);
}{...}
#endif/* ... */
#if SOC_I2S_SUPPORTS_ADC_DAC
if ((int)(obj->mode) == I2S_COMM_MODE_ADC_DAC) {
if (obj->dir & I2S_DIR_TX) {
i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE);
}{...}
if (obj->dir & I2S_DIR_RX) {
adc_set_i2s_data_source(ADC_I2S_DATA_SRC_IO_SIG);
sar_periph_ctrl_adc_continuous_power_release();
}{...}
}{...}
#endif/* ... */
#if SOC_GDMA_SUPPORTED
if (obj->tx_dma_chan) {
gdma_disconnect(obj->tx_dma_chan);
gdma_del_channel(obj->tx_dma_chan);
}{...}
if (obj->rx_dma_chan) {
gdma_disconnect(obj->rx_dma_chan);
gdma_del_channel(obj->rx_dma_chan);
}{...}
#else/* ... */
if (obj->i2s_isr_handle) {
esp_intr_free(obj->i2s_isr_handle);
}{...}
#endif/* ... */
i2s_destroy_dma_object(i2s_num, &obj->tx);
i2s_destroy_dma_object(i2s_num, &obj->rx);
if (obj->i2s_queue) {
vQueueDelete(obj->i2s_queue);
obj->i2s_queue = NULL;
}{...}
#if SOC_I2S_SUPPORTS_APLL
if (obj->use_apll) {
I2S_CLOCK_SRC_ATOMIC() {
if (obj->dir & I2S_DIR_TX) {
i2s_hal_set_tx_clock(&obj->hal, NULL, I2S_CLK_SRC_DEFAULT);
}{...}
if (obj->dir & I2S_DIR_RX) {
i2s_hal_set_rx_clock(&obj->hal, NULL, I2S_CLK_SRC_DEFAULT);
}{...}
}{...}
periph_rtc_apll_release();
}{...}
#endif/* ... */
#ifdef CONFIG_PM_ENABLE
if (obj->pm_lock) {
esp_pm_lock_delete(obj->pm_lock);
obj->pm_lock = NULL;
}{...}
#endif/* ... */
#if SOC_I2S_HW_VERSION_2
I2S_CLOCK_SRC_ATOMIC() {
if (obj->dir & I2S_DIR_TX) {
i2s_ll_tx_disable_clock(obj->hal.dev);
}{...}
if (obj->dir & I2S_DIR_RX) {
i2s_ll_rx_disable_clock(obj->hal.dev);
}{...}
}{...}
#endif/* ... */
i2s_platform_release_occupation(I2S_CTLR_HP, i2s_num);
free(obj);
p_i2s[i2s_num] = NULL;
return ESP_OK;
}{ ... }
esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue)
{
#if CONFIG_I2S_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_ERROR(i2s_check_cfg_validity(i2s_num, i2s_config), TAG, "I2S configuration is invalid");
i2s_obj_t *i2s_obj = calloc(1, sizeof(i2s_obj_t));
ESP_RETURN_ON_FALSE(i2s_obj, ESP_ERR_NO_MEM, TAG, "no mem for I2S driver");
if (i2s_platform_acquire_occupation(I2S_CTLR_HP, i2s_num, "i2s_legacy") != ESP_OK) {
free(i2s_obj);
ESP_LOGE(TAG, "register I2S object to platform failed");
return ESP_ERR_INVALID_STATE;
}{...}
p_i2s[i2s_num] = i2s_obj;
i2s_hal_init(&i2s_obj->hal, i2s_num);
i2s_mode_identify(i2s_num, i2s_config);
ESP_GOTO_ON_ERROR(i2s_config_transfer(i2s_num, i2s_config), err, TAG, "I2S install failed");
i2s_obj->dma_desc_num = i2s_config->dma_desc_num;
i2s_obj->dma_frame_num = i2s_config->dma_frame_num;
i2s_obj->tx_desc_auto_clear = i2s_config->tx_desc_auto_clear;
ESP_GOTO_ON_ERROR(i2s_init_legacy(i2s_num, i2s_config->intr_alloc_flags), err, TAG, "I2S init failed");
if (i2s_queue) {
i2s_obj->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t));
ESP_GOTO_ON_FALSE(i2s_obj->i2s_queue, ESP_ERR_NO_MEM, err, TAG, "I2S queue create failed");
*((QueueHandle_t *) i2s_queue) = i2s_obj->i2s_queue;
ESP_LOGD(TAG, "queue free spaces: %" PRIu32, (uint32_t)uxQueueSpacesAvailable(i2s_obj->i2s_queue));
}{...} else {
i2s_obj->i2s_queue = NULL;
}{...}
ESP_GOTO_ON_ERROR(i2s_start(i2s_num), err, TAG, "I2S start failed");
return ESP_OK;
err:
i2s_driver_uninstall(i2s_num);
return ret;
}{ ... }
esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait)
{
char *data_ptr;
char *src_byte;
size_t bytes_can_write;
*bytes_written = 0;
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->tx), ESP_ERR_INVALID_ARG, TAG, "TX mode is not enabled");
xSemaphoreTake(p_i2s[i2s_num]->tx->mux, portMAX_DELAY);
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_acquire(p_i2s[i2s_num]->pm_lock);
#endif
src_byte = (char *)src;
while (size > 0) {
if (p_i2s[i2s_num]->tx->rw_pos == p_i2s[i2s_num]->tx->buf_size || p_i2s[i2s_num]->tx->curr_ptr == NULL) {
if (xQueueReceive(p_i2s[i2s_num]->tx->queue, &p_i2s[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) {
break;
}{...}
p_i2s[i2s_num]->tx->rw_pos = 0;
}{...}
ESP_LOGD(TAG, "size: %d, rw_pos: %d, buf_size: %d, curr_ptr: %p", size, p_i2s[i2s_num]->tx->rw_pos, p_i2s[i2s_num]->tx->buf_size, p_i2s[i2s_num]->tx->curr_ptr);
data_ptr = (char *)p_i2s[i2s_num]->tx->curr_ptr;
data_ptr += p_i2s[i2s_num]->tx->rw_pos;
bytes_can_write = p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos;
if (bytes_can_write > size) {
bytes_can_write = size;
}{...}
memcpy(data_ptr, src_byte, bytes_can_write);
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_cache_msync((void *)(p_i2s[i2s_num]->tx->curr_ptr), p_i2s[i2s_num]->tx->buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
#endif
size -= bytes_can_write;
src_byte += bytes_can_write;
p_i2s[i2s_num]->tx->rw_pos += bytes_can_write;
(*bytes_written) += bytes_can_write;
}{...}
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_release(p_i2s[i2s_num]->pm_lock);
#endif
xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
return ESP_OK;
}{ ... }
esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait)
{
char *data_ptr;
int bytes_can_write;
int tail;
int src_bytes;
int aim_bytes;
int zero_bytes;
*bytes_written = 0;
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
ESP_RETURN_ON_FALSE((size > 0), ESP_ERR_INVALID_ARG, TAG, "size must greater than zero");
ESP_RETURN_ON_FALSE((aim_bits >= src_bits), ESP_ERR_INVALID_ARG, TAG, "aim_bits mustn't be less than src_bits");
ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->tx), ESP_ERR_INVALID_ARG, TAG, "TX mode is not enabled");
if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) {
ESP_LOGE(TAG, "bits mustn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits);
return ESP_ERR_INVALID_ARG;
}{...}
if (src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) {
ESP_LOGE(TAG, "bits mustn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits);
return ESP_ERR_INVALID_ARG;
}{...}
if ((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) {
ESP_LOGE(TAG, "size must be a even number while src_bits is even, src_bits %d size %d", src_bits, size);
return ESP_ERR_INVALID_ARG;
}{...}
if (src_bits == I2S_BITS_PER_SAMPLE_24BIT && (size % 3 != 0)) {
ESP_LOGE(TAG, "size must be a multiple of 3 while src_bits is 24, size %d", size);
return ESP_ERR_INVALID_ARG;
}{...}
src_bytes = src_bits / 8;
aim_bytes = aim_bits / 8;
zero_bytes = aim_bytes - src_bytes;
xSemaphoreTake(p_i2s[i2s_num]->tx->mux, portMAX_DELAY);
size = size * aim_bytes / src_bytes;
ESP_LOGD(TAG, "aim_bytes %d src_bytes %d size %d", aim_bytes, src_bytes, size);
while (size > 0) {
if (p_i2s[i2s_num]->tx->rw_pos == p_i2s[i2s_num]->tx->buf_size || p_i2s[i2s_num]->tx->curr_ptr == NULL) {
if (xQueueReceive(p_i2s[i2s_num]->tx->queue, &p_i2s[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) {
break;
}{...}
p_i2s[i2s_num]->tx->rw_pos = 0;
}{...}
data_ptr = (char *)p_i2s[i2s_num]->tx->curr_ptr;
data_ptr += p_i2s[i2s_num]->tx->rw_pos;
bytes_can_write = p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos;
if (bytes_can_write > (int)size) {
bytes_can_write = size;
}{...}
tail = bytes_can_write % aim_bytes;
bytes_can_write = bytes_can_write - tail;
memset(data_ptr, 0, bytes_can_write);
for (int j = 0; j < bytes_can_write; j += (aim_bytes - zero_bytes)) {
j += zero_bytes;
memcpy(&data_ptr[j], (const char *)(src + *bytes_written), aim_bytes - zero_bytes);
(*bytes_written) += (aim_bytes - zero_bytes);
}{...}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
esp_cache_msync((void *)p_i2s[i2s_num]->tx->curr_ptr, p_i2s[i2s_num]->tx->buf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
#endif
size -= bytes_can_write;
p_i2s[i2s_num]->tx->rw_pos += bytes_can_write;
}{...}
xSemaphoreGive(p_i2s[i2s_num]->tx->mux);
return ESP_OK;
}{ ... }
esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait)
{
char *data_ptr;
char *dest_byte;
int bytes_can_read;
*bytes_read = 0;
dest_byte = (char *)dest;
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->rx), ESP_ERR_INVALID_ARG, TAG, "RX mode is not enabled");
xSemaphoreTake(p_i2s[i2s_num]->rx->mux, portMAX_DELAY);
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_acquire(p_i2s[i2s_num]->pm_lock);
#endif
while (size > 0) {
if (p_i2s[i2s_num]->rx->rw_pos == p_i2s[i2s_num]->rx->buf_size || p_i2s[i2s_num]->rx->curr_ptr == NULL) {
if (xQueueReceive(p_i2s[i2s_num]->rx->queue, &p_i2s[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) {
break;
}{...}
p_i2s[i2s_num]->rx->rw_pos = 0;
}{...}
data_ptr = (char *)p_i2s[i2s_num]->rx->curr_ptr;
data_ptr += p_i2s[i2s_num]->rx->rw_pos;
bytes_can_read = p_i2s[i2s_num]->rx->buf_size - p_i2s[i2s_num]->rx->rw_pos;
if (bytes_can_read > (int)size) {
bytes_can_read = size;
}{...}
memcpy(dest_byte, data_ptr, bytes_can_read);
size -= bytes_can_read;
dest_byte += bytes_can_read;
p_i2s[i2s_num]->rx->rw_pos += bytes_can_read;
(*bytes_read) += bytes_can_read;
}{...}
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_release(p_i2s[i2s_num]->pm_lock);
#endif
xSemaphoreGive(p_i2s[i2s_num]->rx->mux);
return ESP_OK;
}{ ... }
/* ... */
static void gpio_matrix_out_check_and_set(gpio_num_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv)
{
if (gpio != -1) {
gpio_func_sel(gpio, PIN_FUNC_GPIO);
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
esp_rom_gpio_connect_out_signal(gpio, signal_idx, out_inv, oen_inv);
}{...}
}{ ... }
static void gpio_matrix_in_check_and_set(gpio_num_t gpio, uint32_t signal_idx, bool inv)
{
if (gpio != -1) {
gpio_func_sel(gpio, PIN_FUNC_GPIO);
gpio_set_direction(gpio, GPIO_MODE_INPUT);
esp_rom_gpio_connect_in_signal(gpio, signal_idx, inv);
}{...}
}{ ... }
static esp_err_t i2s_check_set_mclk(i2s_port_t i2s_num, gpio_num_t gpio_num)
{
if (gpio_num == -1) {
return ESP_OK;
}{...}
#if CONFIG_IDF_TARGET_ESP32
soc_clkout_sig_id_t clkout_sig = (i2s_num == I2S_NUM_0) ? CLKOUT_SIG_I2S0 : CLKOUT_SIG_I2S1;
ESP_RETURN_ON_ERROR(esp_clock_output_start(clkout_sig, gpio_num, &p_i2s[i2s_num]->mclk_out_hdl), TAG, "mclk configure failed");/* ... */
#else
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "mck_io_num invalid");
gpio_matrix_out_check_and_set(gpio_num, i2s_periph_signal[i2s_num].mck_out_sig, 0, 0);/* ... */
#endif
ESP_LOGD(TAG, "I2S%d, MCLK output by GPIO%d", i2s_num, gpio_num);
return ESP_OK;
}{ ... }
esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
uint32_t buf_cnt = p_i2s[i2s_num]->dma_desc_num;
if (p_i2s[i2s_num]->rx && p_i2s[i2s_num]->rx->buf != NULL && p_i2s[i2s_num]->rx->buf_size != 0) {
for (int i = 0; i < buf_cnt; i++) {
memset(p_i2s[i2s_num]->rx->buf[i], 0, p_i2s[i2s_num]->rx->buf_size);
}{...}
}{...}
if (p_i2s[i2s_num]->tx && p_i2s[i2s_num]->tx->buf != NULL && p_i2s[i2s_num]->tx->buf_size != 0) {
int bytes_left = (p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos) % 4;
if (bytes_left) {
size_t zero_bytes = 0;
size_t bytes_written;
i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY);
}{...}
for (int i = 0; i < buf_cnt; i++) {
memset(p_i2s[i2s_num]->tx->buf[i], 0, p_i2s[i2s_num]->tx->buf_size);
}{...}
}{...}
return ESP_OK;
}{ ... }
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin)
{
ESP_RETURN_ON_FALSE((i2s_num < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "i2s_num error");
if (pin == NULL) {
#if SOC_I2S_SUPPORTS_DAC
return i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
#else
return ESP_ERR_INVALID_ARG;
#endif
}{...}
ESP_RETURN_ON_FALSE((pin->bck_io_num == -1 || GPIO_IS_VALID_GPIO(pin->bck_io_num)),
ESP_ERR_INVALID_ARG, TAG, "bck_io_num invalid");
ESP_RETURN_ON_FALSE((pin->ws_io_num == -1 || GPIO_IS_VALID_GPIO(pin->ws_io_num)),
ESP_ERR_INVALID_ARG, TAG, "ws_io_num invalid");
ESP_RETURN_ON_FALSE((pin->data_out_num == -1 || GPIO_IS_VALID_GPIO(pin->data_out_num)),
ESP_ERR_INVALID_ARG, TAG, "data_out_num invalid");
ESP_RETURN_ON_FALSE((pin->data_in_num == -1 || GPIO_IS_VALID_GPIO(pin->data_in_num)),
ESP_ERR_INVALID_ARG, TAG, "data_in_num invalid");
if (p_i2s[i2s_num]->role == I2S_ROLE_SLAVE) {
if (p_i2s[i2s_num]->dir & I2S_DIR_RX) {
gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].s_rx_ws_sig, 0);
gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].s_rx_bck_sig, 0);
}{...} else {
gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].s_tx_ws_sig, 0);
gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].s_tx_bck_sig, 0);
}{...}
}{...} else {
ESP_RETURN_ON_ERROR(i2s_check_set_mclk(i2s_num, pin->mck_io_num), TAG, "mclk config failed");
if (p_i2s[i2s_num]->dir & I2S_DIR_TX) {
gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].m_tx_ws_sig, 0, 0);
gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].m_tx_bck_sig, 0, 0);
}{...} else {
gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].m_rx_ws_sig, 0, 0);
gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].m_rx_bck_sig, 0, 0);
}{...}
}{...}
gpio_matrix_out_check_and_set(pin->data_out_num, i2s_periph_signal[i2s_num].data_out_sig, 0, 0);
gpio_matrix_in_check_and_set(pin->data_in_num, i2s_periph_signal[i2s_num].data_in_sig, 0);
return ESP_OK;
}{ ... }
#if !CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK
/* ... */
static __attribute__((constructor)) void check_i2s_driver_conflict(void)
{
extern __attribute__((weak)) esp_err_t i2s_del_channel(void *handle);
if ((void *)i2s_del_channel != NULL) {
ESP_EARLY_LOGE(TAG, "CONFLICT! The new i2s driver can't work along with the legacy i2s driver");
abort();
}{...}
ESP_EARLY_LOGW(TAG, "legacy i2s driver is deprecated, please migrate to use driver/i2s_std.h, driver/i2s_pdm.h or driver/i2s_tdm.h");
}{ ... }
#endif/* ... */