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
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
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
613
614
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
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
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
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
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
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
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
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
|
/**
* \file
*
* \brief SAM I2S - Inter-IC Sound Controller
*
* Copyright (c) 2014-2016 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef I2S_H_INCLUDED
#define I2S_H_INCLUDED
/**
* \defgroup asfdoc_sam0_i2s_group SAM Inter-IC Sound Controller (I2S) Driver
*
* This driver for Atmel® | SMART ARM®-based microcontrollers provides
* an interface for the configuration and management of the device's Inter-IC
* Sound Controller functionality.
*
* The following driver API modes are covered by this manual:
* - Polled APIs
* \if I2S_CALLBACK_MODE
* - Callback APIs
* \endif
*
* The following peripheral is used by this module:
* - I<SUP>2</SUP>S (Inter-IC Sound Controller)
*
* The following devices can use this module:
* - Atmel | SMART SAM D21
* - Atmel | SMART SAM DA1
*
* The outline of this documentation is as follows:
* - \ref asfdoc_sam0_i2s_prerequisites
* - \ref asfdoc_sam0_i2s_module_overview
* - \ref asfdoc_sam0_i2s_special_considerations
* - \ref asfdoc_sam0_i2s_extra_info
* - \ref asfdoc_sam0_i2s_examples
* - \ref asfdoc_sam0_i2s_api_overview
*
* \section asfdoc_sam0_i2s_prerequisites Prerequisites
*
* There are no prerequisites for this module.
*
* \section asfdoc_sam0_i2s_module_overview Module Overview
*
* The I<SUP>2</SUP>S provides bidirectional, synchronous, digital audio link with
* external audio devices through these signal pins:
* - Serial Data (SDm)
* - Frame Sync (FSn)
* - Serial Clock (SCKn)
* - Master Clock (MCKn)
*
* The I<SUP>2</SUP>S consists of two Clock Units and two Serializers, which can be
* separately configured and enabled, to provide varies functionalities as follow:
* - Communicate to Audio CODECs as Master or Slave, or provides clock and
* frame sync signals as Controller
* - Communicate to DAC or ADC through dedicated I<SUP>2</SUP>S serial interface
* - Communicate to multi-slot or multiple stereo DACs or ADCs, via
* Time Division Multiplexed (TDM) format
* - Reading mono or stereo MEMS microphones, using the Pulse Density
* Modulation (PDM) interface
*
* The I<SUP>2</SUP>S supports compact stereo data word, where left channel data bits are
* in lower half and right channel data bits are in upper half. It reduces the
* number of data words for stereo audio data and the DMA bandwidth.
*
* In master mode, the frame is configured by number of slots and slot size, and
* allows range covering 16fs to 1024fs MCK, to provide oversampling clock to an
* external audio CODEC or digital signal processor (DSP).
*
* A block diagram of the I<SUP>2</SUP>S can be seen in
* \ref asfdoc_sam0_i2s_module_block_diagram "the figure below".
*
* \anchor asfdoc_sam0_i2s_module_block_diagram
* \image html i2s_blocks.svg "I2S Block Diagram"
*
* This driver for I<SUP>2</SUP>S module provides an interface to:
* - Initialize and control I<SUP>2</SUP>S module
* - Configure and control the I<SUP>2</SUP>S Clock Unit and Serializer
* - Transmit/receive data through I<SUP>2</SUP>S Serializer
*
* \subsection asfdoc_sam0_i2s_module_overview_clocks Clocks
*
* To use I<SUP>2</SUP>S module, the I<SUP>2</SUP>S bus interface clock (clk_i2s)
* must be enabled via Power Manager.
*
* For each I<SUP>2</SUP>S Clock Unit, a generic clock (gclk_i2s_n) is connnected.
* When I<SUP>2</SUP>S works in master mode the generic clock is used. It should
* be prepared before clock unit is used. In master mode the input generic clock
* will be used as MCK for SCKn and FSn generation, in addition, the MCK could be
* devided and output to I<SUP>2</SUP>S MCKn pin, as oversampling clock to
* external audio device.
*
* The I<SUP>2</SUP>S Serializer uses clock and control signal from Clock Unit to handle
* transfer. Select different clock unit with different configurations allows
* the I<SUP>2</SUP>S to work as master or slave, to work on non-related clocks.
*
* When using the driver with ASF, enabling the register interface is normally
* done by the \c init function.
* The Generic Clock Controller (GCLK) source for the asynchronous domain is
* normally configured and set through the _configuration
* struct_ / _init_ function.
* If GCLK source != 0 is used, this source has to be configured and enabled
* through invoking the system_gclk driver function when needed, or modifying
* conf_clock.h to enable it at the beginning.
*
* \subsection asfdoc_sam0_i2s_module_overview_frame Audio Frame Generation
*
* Audio sample data for all channels are sent in frames, one frame can consist
* 1 - 8 slots where each slot can be configured to a size 8-bit, 16-bit, 24-bit,
* or 32-bit. The audio frame synch clock is generated by the I<SUP>2</SUP>S
* Clock unit in the master/controller mode. The frame rate (or frame sync
* frequency) is calculated as follows:
*
* FS = SCK / number_of_slots / number_of_bits_in_slot
*
* The serial clock (SCK) source is either an external source (slave mode) or
* generated by the I<SUP>2</SUP>S clock unit (controller or master mode) using
* the MCK as source.
*
* SCK = MCK / sck_div
* \note SCK generation division value is MCKDIV in register.
*
* MCK is either an external source or generated using the GCLK input from a
* generic clock generator.
*
* \subsection asfdoc_sam0_i2s_module_overview_mode Master, Controller, and Slave Modes
*
* The I<SUP>2</SUP>S module has three modes: master, controller, and slave.
*
* \subsubsection asfdoc_sam0_i2s_module_overview_mode_mst Master
* In master mode the module will control the data flow on the I<SUP>2</SUP>S bus and can
* be responsible for clock generation. The Serializers are enabled and will
* transmit/receive data. On a bus with only master and slave the SCK, and FS
* clock signal will be outputted on the SCK and FS pin on the master module.
* MCK can optionally be outputted on the MCK pin, if there is a controller
* module on the bus the SCK, FS, and optionally the MCK clock is sourced from
* the same pins. Serial data will be trancieved on the SD pin in both
* scenarios.
*
* \subsubsection asfdoc_sam0_i2s_module_overview_mode_ctl Controller
* In controller mode the module will generate the clock signals, but the
* Serializers are disabled and no data will be transmitted/received by the
* module in this mode. The clock signals is outputted on the SCK, FS and
* optionally the MCK pin.
*
* \subsubsection asfdoc_sam0_i2s_module_overview_mode_slv Slave
* In slave mode the module will use the SCK and FS clock source from the master
* or the controller which is received on the SCK and FS pin. The MCK can
* optionally be sourced externally on the MCK pin. The Serializers are enabled
* and will tranceive data on the SD pin. All data flow is controlled by the
* master.
*
* \subsubsection asfdoc_sam0_i2s_module_overview_mode_chg Switch Modes
* The mode switching between master, controller, and slave modes are actually
* done by modifying the source mode of I<SUP>2</SUP>S pins.
* The source mode of I<SUP>2</SUP>S pins are selected by writing corresponding
* bits in CLKCTRLn.
* Since source mode switching changes the direction of pin, the mode must be
* changed when the I<SUP>2</SUP>S Clock Unit is stopped.
*
* \subsection asfdoc_sam0_i2s_module_overview_data Data Stream Reception/Transmission
*
* The I<SUP>2</SUP>S module support several data stream formats:
* - I<SUP>2</SUP>S format
* - Time Division Multiplexed (TDM) format
* - Pulse Density Modulation (PDM) format (reception only)
*
* Basically the I<SUP>2</SUP>S module can send several words within each frame,
* it's more like TDM format. With adjust to the number of data words in a frame,
* the FS width, the FS to data bits delay, etc., the module is able to handle
* I<SUP>2</SUP>S compliant data stream.
*
* Also the Serializer can receive PDM format data stream, which allows the
* I<SUP>2</SUP>S module receive 1 PDM data on each SCK edge.
*
* \subsubsection asfdoc_sam0_i2s_module_overview_data_i2s I2S Stream Reception/Transmission
*
* For 2-channel I<SUP>2</SUP>S compliant data stream format the I<SUP>2</SUP>S
* module uses the FS line as word select (WS) signal and will send left channel
* data word on low WS level and right channel data word on high WS level as
* specified in the I<SUP>2</SUP>S standard. The supported word sizes are 8-,
* 16-, 18-, 20-, 24-, and 32- bit.
*
* Thus for I<SUP>2</SUP>S stream, the following settings should be applied to the module:
* - Data starting delay after FS transition : one SCK period
* - FS width : half of frame
* - Data bits adjust in word : left-adjusted
* - Bit transmitting order : MSB first
*
* Following is an example for I<SUP>2</SUP>S application connections and waveforms. See
* the figure below.
*
* \anchor asfdoc_sam0_i2s_module_i2s_example_diagram
* \image html i2s_example.svg "I2S Example Diagram"
*
* \subsubsection asfdoc_sam0_i2s_module_overview_data_tdm TDM Stream Reception/Transmission
* In TDM format, the module sends several data words in each frame. For this
* data stream format most of the configurations could be adjusted:
* - Main Frame related settings are as follow:
* - Frame Sync (FS) options:
* - The active edge of the FS (or if FS is inverted before use)
* - The width of the FS
* - The delay between FS to first data bit
* - Data alignment in slot
* - The number of slots and slot size can be adjusted, it has been mentioned
* in \ref asfdoc_sam0_i2s_module_overview_frame
* - The data word size is controlled by Serializer, it can be chosen among
* 8, 16, 18, 20, 24, and 32 bits.
*
* The general TDM waveform generation is as follows:
*
* \anchor asfdoc_sam0_i2s_module_tdm_wave_diagram
* \image html tdm_wave.svg "TDM Waveform Generation"
*
* Some other settings could also be found to set up clock, data formatting and
* pin multiplexer (MUX).
* Refer to \ref i2s_clock_unit_config "Clock Unit Configurations"
* and \ref i2s_serializer_config "Serializer Configurations" for more
* details.
*
* Following is examples for different application use cases.
*
* See \ref asfdoc_sam0_i2s_module_tdm_timeslot_example_diagram "here" for
* the Time Slot Application connection and waveform example.
*
* \anchor asfdoc_sam0_i2s_module_tdm_timeslot_example_diagram
* \image html tdm_timeslot_example.svg "Codec Example Diagram"
*
* See \ref asfdoc_sam0_i2s_module_tdm_codec_example_diagram "here" for the
* Codec Application connection and waveform example.
*
* \anchor asfdoc_sam0_i2s_module_tdm_codec_example_diagram
* \image html tdm_codec_example.svg "Time Slot Example Diagram"
*
* \subsubsection asfdoc_sam0_i2s_module_overview_data_pdm PDM Reception
* The I<SUP>2</SUP>S Serializer integrates PDM reception feature, to use this feature,
* simply select PDM2 mode in Serializer configuration. In PDM2 mode, it assumes
* two microphones are input for stereo stream. The left microphone bits will
* be stored in lower half and right microphone bits in upper half of the data
* word, like in compact stereo format.
*
* See \ref asfdoc_sam0_i2s_module_pdm_example_diagram "following figure" for an
* example of PDM Microphones Application with both left and right channel
* microphone connected.
*
* \anchor asfdoc_sam0_i2s_module_pdm_example_diagram
* \image html pdm_example.svg "Time PDM2 Example Diagram"
*
* \subsubsection asfdoc_sam0_i2s_module_overview_data_fmt MONO and Compact Data
* The I<SUP>2</SUP>S Serializer can accept some pre-defined data format and generates
* the data stream in specified way.
*
* When transmitting data, the Serializer can work in MONO mode: assum input
* is single channel mono data on left channel and copy it to right channel
* automatically.
*
* Also the I<SUP>2</SUP>S Serializer can support compact stereo data word. The data word
* size of the Serializer can be set to \ref I2S_DATA_SIZE_16BIT_COMPACT
* "16-bit compact" or \ref I2S_DATA_SIZE_8BIT_COMPACT "8-bit compact", with
* these option I<SUP>2</SUP>S Serializer will compact left channel data and right channel
* data together, the left channel data will take lower bytes and right channel
* data take higher bytes.
*
* \subsection asfdoc_sam0_i2s_module_overview_loop Loop-back Mode
* The I<SUP>2</SUP>S can be configured to loop back the Transmitter to Receiver. In this
* mode Serializer's input will be connected to another Serializer's output
* internally.
*
* \subsection asfdoc_sam0_i2s_module_overview_sleep Sleep Modes
* The I<SUP>2</SUP>S will continue to operate in any sleep mode, where the selected source
* clocks are running.
*
* \section asfdoc_sam0_i2s_special_considerations Special Considerations
*
* There is no special considerations for I<SUP>2</SUP>S module.
*
* \section asfdoc_sam0_i2s_extra_info Extra Information
*
* For extra information see \ref asfdoc_sam0_i2s_extra. This includes:
* - \ref asfdoc_sam0_i2s_extra_acronyms
* - \ref asfdoc_sam0_i2s_extra_dependencies
* - \ref asfdoc_sam0_i2s_extra_errata
* - \ref asfdoc_sam0_i2s_extra_history
*
* \section asfdoc_sam0_i2s_examples Examples
*
* For a list of examples related to this driver, see
* \ref asfdoc_sam0_i2s_exqsg.
*
*
* \section asfdoc_sam0_i2s_api_overview API Overview
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <compiler.h>
#include <system.h>
#if I2S_CALLBACK_MODE == true
# include <system_interrupt.h>
#if !defined(__DOXYGEN__)
extern struct i2s_module *_i2s_instances[I2S_INST_NUM];
#endif
/** Forward definition of the device instance */
struct i2s_module;
/** Type of the callback functions. */
typedef void (*i2s_serializer_callback_t)
(struct i2s_module *const module);
/**
* \brief I<SUP>2</SUP>S Serializer Callback enum
*/
enum i2s_serializer_callback {
/** Callback for buffer read/write finished */
I2S_SERIALIZER_CALLBACK_BUFFER_DONE,
/** Callback for Serializer overrun/underrun */
I2S_SERIALIZER_CALLBACK_OVER_UNDER_RUN,
# if !defined(__DOXYGEN__)
I2S_SERIALIZER_CALLBACK_N
# endif
};
#endif /* #if I2S_CALLBACK_MODE == true */
/**
* \name Module Status Flags
*
* I<SUP>2</SUP>S status flags, returned by \ref i2s_get_status() and cleared by
* \ref i2s_clear_status().
*
* @{
*/
/** Module Serializer x (0~1) Transmit Underrun. */
#define I2S_STATUS_TRANSMIT_UNDERRUN(x) (1u << ((x)+0))
/** Module Serializer x (0~1) is ready to accept new data to be transmitted. */
#define I2S_STATUS_TRANSMIT_READY(x) (1u << ((x)+2))
/** Module Serializer x (0~1) Receive Overrun. */
#define I2S_STATUS_RECEIVE_OVERRUN(x) (1u << ((x)+4))
/** Module Serializer x (0~1) has received a new data. */
#define I2S_STATUS_RECEIVE_READY(x) (1u << ((x)+6))
/** Module is busy on synchronization. */
#define I2S_STATUS_SYNC_BUSY (1u << 8)
/** @} */
/**
* Master Clock (MCK) source selection.
*/
enum i2s_master_clock_source {
/** Master Clock (MCK) is from general clock */
I2S_MASTER_CLOCK_SOURCE_GCLK,
/** Master Clock (MCK) is from MCK input pin */
I2S_MASTER_CLOCK_SOURCE_MCKPIN
};
/**
* Serial Clock (SCK) source selection.
*/
enum i2s_serial_clock_source {
/** Serial Clock (SCK) is divided from Master Clock */
I2S_SERIAL_CLOCK_SOURCE_MCKDIV,
/** Serial Clock (SCK) is input from SCK input pin */
I2S_SERIAL_CLOCK_SOURCE_SCKPIN
};
/**
* Data delay from Frame Sync (FS).
*/
enum i2s_data_delay {
/** Left Justified (no delay) */
I2S_DATA_DELAY_0,
/** I<SUP>2</SUP>S data delay (1-bit delay) */
I2S_DATA_DELAY_1,
/** Left Justified (no delay) */
I2S_DATA_DELAY_LEFT_JUSTIFIED = I2S_DATA_DELAY_0,
/** I<SUP>2</SUP>S data delay (1-bit delay) */
I2S_DATA_DELAY_I2S = I2S_DATA_DELAY_1
};
/**
* Frame Sync (FS) source.
*/
enum i2s_frame_sync_source {
/** Frame Sync (FS) is divided from I<SUP>2</SUP>S Serial Clock */
I2S_FRAME_SYNC_SOURCE_SCKDIV,
/** Frame Sync (FS) is input from FS input pin */
I2S_FRAME_SYNC_SOURCE_FSPIN
};
/**
* Frame Sync (FS) output pulse width.
*/
enum i2s_frame_sync_width {
/** Frame Sync (FS) Pulse is one slot width */
I2S_FRAME_SYNC_WIDTH_SLOT,
/** Frame Sync (FS) Pulse is half a frame width */
I2S_FRAME_SYNC_WIDTH_HALF_FRAME,
/** Frame Sync (FS) Pulse is one bit width */
I2S_FRAME_SYNC_WIDTH_BIT,
/** 1-bit wide Frame Sync (FS) per Data sample, only used when Data transfer
* is requested */
I2S_FRAME_SYNC_WIDTH_BURST
};
/**
* Time Slot Size in number of I<SUP>2</SUP>S serial clocks (bits).
*/
enum i2s_slot_size {
/** 8-bit slot */
I2S_SLOT_SIZE_8_BIT,
/** 16-bit slot */
I2S_SLOT_SIZE_16_BIT,
/** 24-bit slot */
I2S_SLOT_SIZE_24_BIT,
/** 32-bit slot */
I2S_SLOT_SIZE_32_BIT
};
/**
* DMA channels usage for I<SUP>2</SUP>S.
*/
enum i2s_dma_usage {
/** Single DMA channel for all I<SUP>2</SUP>S channels */
I2S_DMA_USE_SINGLE_CHANNEL_FOR_ALL,
/** One DMA channel per data channel */
I2S_DMA_USE_ONE_CHANNEL_PER_DATA_CHANNEL
};
/**
* I<SUP>2</SUP>S data format, to extend mono data to two channels.
*/
enum i2s_data_format {
/** Normal mode, keep data to its right channel */
I2S_DATA_FORMAT_STEREO,
/** Assume input is mono data for left channel, the data is duplicated to
* right channel */
I2S_DATA_FORMAT_MONO
};
/**
* I<SUP>2</SUP>S data bit order.
*/
enum i2s_bit_order {
/** Transfer Data Most Significant Bit first
* (Default for I<SUP>2</SUP>S protocol)
*/
I2S_BIT_ORDER_MSB_FIRST,
/** Transfer Data Least Significant Bit first */
I2S_BIT_ORDER_LSB_FIRST
};
/**
* I<SUP>2</SUP>S data bit padding.
*/
enum i2s_bit_padding {
/** Padding with 0 */
I2S_BIT_PADDING_0,
/** Padding with 1 */
I2S_BIT_PADDING_1,
/** Padding with MSBit */
I2S_BIT_PADDING_MSB,
/** Padding with LSBit */
I2S_BIT_PADDING_LSB,
};
/**
* I<SUP>2</SUP>S data word adjust.
*/
enum i2s_data_adjust {
/** Data is right adjusted in word */
I2S_DATA_ADJUST_RIGHT,
/** Data is left adjusted in word */
I2S_DATA_ADJUST_LEFT
};
/**
* I<SUP>2</SUP>S data word size.
*/
enum i2s_data_size {
/** 32-bit */
I2S_DATA_SIZE_32BIT,
/** 24-bit */
I2S_DATA_SIZE_24BIT,
/** 20-bit */
I2S_DATA_SIZE_20BIT,
/** 18-bit */
I2S_DATA_SIZE_18BIT,
/** 16-bit */
I2S_DATA_SIZE_16BIT,
/** 16-bit compact stereo */
I2S_DATA_SIZE_16BIT_COMPACT,
/** 8-bit */
I2S_DATA_SIZE_8BIT,
/** 8-bit compact stereo */
I2S_DATA_SIZE_8BIT_COMPACT
};
/**
* I<SUP>2</SUP>S data slot adjust.
*/
enum i2s_slot_adjust {
/** Data is right adjusted in slot */
I2S_SLOT_ADJUST_RIGHT,
/** Data is left adjusted in slot */
I2S_SLOT_ADJUST_LEFT
};
/**
* I<SUP>2</SUP>S data padding.
*/
enum i2s_data_padding {
/** Padding 0 in case of under-run */
I2S_DATA_PADDING_0,
/** Padding last data in case of under-run */
I2S_DATA_PADDING_SAME_AS_LAST,
/** Padding last data in case of under-run
* (abbr. \c I2S_DATA_PADDING_SAME_AS_LAST) */
I2S_DATA_PADDING_LAST = I2S_DATA_PADDING_SAME_AS_LAST,
/** Padding last data in case of under-run
* (abbr. \c I2S_DATA_PADDING_SAME_AS_LAST) */
I2S_DATA_PADDING_SAME = I2S_DATA_PADDING_SAME_AS_LAST
};
/**
* I<SUP>2</SUP>S line default value when slot disabled.
*/
enum i2s_line_default_state {
/** Output default value is 0 */
I2S_LINE_DEFAULT_0,
/** Output default value is 1 */
I2S_LINE_DEFAULT_1,
/** Output default value is high impedance */
I2S_LINE_DEFAULT_HIGH_IMPEDANCE = 3,
/** Output default value is high impedance
* (abbr. \c I2S_LINE_DEFAULT_HIGH_IMPEDANCE) */
I2S_LINE_DEFAULT_HIZ = I2S_LINE_DEFAULT_HIGH_IMPEDANCE
};
/**
* I<SUP>2</SUP>S Serializer mode.
*/
enum i2s_serializer_mode {
/** Serializer is used to receive data */
I2S_SERIALIZER_RECEIVE,
/** Serializer is used to transmit data */
I2S_SERIALIZER_TRANSMIT,
/** Serializer is used to receive PDM data on each clock edge */
I2S_SERIALIZER_PDM2
};
/**
* I<SUP>2</SUP>S clock unit selection.
*/
enum i2s_clock_unit {
/** Clock Unit channel 0 */
I2S_CLOCK_UNIT_0,
/** Clock Unit channel 1 */
I2S_CLOCK_UNIT_1,
/** Number of Clock Unit channels */
I2S_CLOCK_UNIT_N
};
/**
* I<SUP>2</SUP>S Serializer selection.
*/
enum i2s_serializer {
/** Serializer channel 0 */
I2S_SERIALIZER_0,
/** Serializer channel 1 */
I2S_SERIALIZER_1,
/** Number of Serializer channels */
I2S_SERIALIZER_N
};
/**
* Configure for I<SUP>2</SUP>S pin.
*/
struct i2s_pin_config {
/** GPIO index to access the pin */
uint8_t gpio;
/** Pin function MUX */
uint8_t mux;
/** Enable this pin for I<SUP>2</SUP>S module */
bool enable;
};
/**
* Configure for I<SUP>2</SUP>S clock (SCK).
*/
struct i2s_clock_config {
/** Divide generic clock to master clock output (1~32, 0,1 means no div) */
uint8_t mck_out_div;
/** Divide generic clock to serial clock (1~32, 0,1 means no div) */
uint8_t sck_div;
/** Clock source selection */
enum gclk_generator gclk_src;
/** Master clock source selection: generated or input from pin */
enum i2s_master_clock_source mck_src;
/** Serial clock source selection: generated or input from pin */
enum i2s_serial_clock_source sck_src;
/** Invert master clock output */
bool mck_out_invert;
/** Invert serial clock output */
bool sck_out_invert;
/** Generate MCK clock output */
bool mck_out_enable;
};
/**
* Configure for I<SUP>2</SUP>S frame sync (FS).
*/
struct i2s_frame_sync_config {
/** Frame Sync (FS) generated or input from pin */
enum i2s_frame_sync_source source;
/** Frame Sync (FS) width */
enum i2s_frame_sync_width width;
/** Invert Frame Sync (FS) signal before use */
bool invert_use;
/** Invert Frame Sync (FS) signal before output */
bool invert_out;
};
/**
* Configure for I<SUP>2</SUP>S frame.
*/
struct i2s_frame_config {
/** Number of slots in a frame (1~8, 0,1 means minimum 1) */
uint8_t number_slots;
/** Size of each slot in frame */
enum i2s_slot_size slot_size;
/** Data delay from Frame Sync (FS) to first data bit */
enum i2s_data_delay data_delay;
/** Frame sync (FS) */
struct i2s_frame_sync_config frame_sync;
};
/**
* Configure for I<SUP>2</SUP>S clock unit.
*/
struct i2s_clock_unit_config {
/** Configure clock generation */
struct i2s_clock_config clock;
/** Configure frame generation */
struct i2s_frame_config frame;
/** Configure master clock pin */
struct i2s_pin_config mck_pin;
/** Configure serial clock pin */
struct i2s_pin_config sck_pin;
/** Configure frame sync pin */
struct i2s_pin_config fs_pin;
};
/**
* Configure for I<SUP>2</SUP>S Serializer.
*/
struct i2s_serializer_config {
/** Configure Serializer data pin */
struct i2s_pin_config data_pin;
/** Set to \c true to loop-back output to input pin for test */
bool loop_back;
/** Set to \c true to assumes mono input and duplicate it (left channel) to
* right channel */
bool mono_mode;
/** Disable data slot */
bool disable_data_slot[8];
/** Set to \c true to transfer LSB first, \c false to transfer MSB first */
bool transfer_lsb_first;
/** Data Word Formatting Adjust,
* set to \c true to adjust bits in word to left */
bool data_adjust_left_in_word;
/** Data Slot Formatting Adjust,
* set to \c true to adjust words in slot to left */
bool data_adjust_left_in_slot;
/** Data Word Size */
enum i2s_data_size data_size;
/** Data Formatting Bit Extension */
enum i2s_bit_padding bit_padding;
/** Data padding when under-run */
enum i2s_data_padding data_padding;
/** DMA usage */
enum i2s_dma_usage dma_usage;
/** Clock unit selection */
enum i2s_clock_unit clock_unit;
/** Line default state where slot is disabled */
enum i2s_line_default_state line_default_state;
/** Serializer Mode */
enum i2s_serializer_mode mode;
};
/**
* \brief I<SUP>2</SUP>S Serializer instance struct.
*/
struct i2s_serializer_module {
#if I2S_CALLBACK_MODE == true
/** Callbacks list for Serializer */
i2s_serializer_callback_t callback[I2S_SERIALIZER_CALLBACK_N];
/** Job buffer */
void *job_buffer;
/** Requested data words to read/write */
uint32_t requested_words;
/** Transferred data words for read/write */
uint32_t transferred_words;
/** Callback mask for registered callbacks */
uint8_t registered_callback_mask;
/** Callback mask for enabled callbacks */
uint8_t enabled_callback_mask;
/** Status of the ongoing or last transfer job */
enum status_code job_status;
#endif
/** Serializer mode */
enum i2s_serializer_mode mode;
/** Serializer data word size */
enum i2s_data_size data_size;
};
/**
* \brief I<SUP>2</SUP>S Software Module instance struct.
*/
struct i2s_module {
/** Module HW register access base */
I2s *hw;
/** Module Serializer used */
struct i2s_serializer_module serializer[2];
};
/**
* \brief Determines if the hardware module(s) are currently synchronizing to the bus.
*
* Checks to see if the underlying hardware peripheral module(s) are currently
* synchronizing across multiple clock domains to the hardware bus, This
* function can be used to delay further operations on a module until such time
* that it is ready, to prevent blocking delays for synchronization in the
* user application.
*
* \param[in] module_inst Pointer to the software module instance struct
*
* \return Synchronization status of the underlying hardware module(s).
*
* \retval false If the module has completed synchronization
* \retval true If the module synchronization is ongoing
*/
static inline bool i2s_is_syncing(
const struct i2s_module *const module_inst)
{
/* Sanity check arguments */
Assert(module_inst);
Assert(module_inst->hw);
return (module_inst->hw->SYNCBUSY.reg > 0);
}
/**
* \name Driver Initialization
* @{
*/
enum status_code i2s_init(
struct i2s_module *const module_inst,
I2s *hw);
/** @} */
/**
* \name Enable/Disable/Reset
* @{
*/
/**
* \brief Enable the I<SUP>2</SUP>S module.
*
* Enables a I<SUP>2</SUP>S module that has been previously initialized.
*
* \param[in] module_inst Pointer to the software module instance struct
*/
static inline void i2s_enable(const struct i2s_module *const module_inst)
{
Assert(module_inst);
Assert(module_inst->hw);
while (module_inst->hw->SYNCBUSY.reg & I2S_SYNCBUSY_ENABLE) {
/* Sync wait */
}
module_inst->hw->CTRLA.reg |= I2S_SYNCBUSY_ENABLE;
}
/**
* \brief Disables the I<SUP>2</SUP>S module.
*
* Disables a I<SUP>2</SUP>S module.
*
* \param[in] module_inst Pointer to the software module instance struct
*/
static inline void i2s_disable(const struct i2s_module *const module_inst)
{
Assert(module_inst);
Assert(module_inst->hw);
while (module_inst->hw->SYNCBUSY.reg & I2S_SYNCBUSY_ENABLE) {
/* Sync wait */
}
module_inst->hw->INTENCLR.reg = I2S_INTENCLR_MASK;
module_inst->hw->INTFLAG.reg = I2S_INTFLAG_MASK;
module_inst->hw->CTRLA.reg &= ~I2S_SYNCBUSY_ENABLE;
}
/**
* \brief Resets the I<SUP>2</SUP>S module.
*
* Resets the I<SUP>2</SUP>S module, restoring all hardware module registers to their
* default values and disabling the module. The I<SUP>2</SUP>S module will not be
* accessible while the reset is being performed.
*
* \param[in] module_inst Pointer to the software module instance struct
*/
static inline void i2s_reset(const struct i2s_module *const module_inst)
{
Assert(module_inst);
Assert(module_inst->hw);
/* Disable the module if it is running */
if (module_inst->hw->CTRLA.reg & I2S_CTRLA_ENABLE) {
i2s_disable(module_inst);
while (i2s_is_syncing(module_inst)) {
/* Sync wait */
}
}
/* Reset the HW module */
module_inst->hw->CTRLA.reg = I2S_CTRLA_SWRST;
}
/** @} */
/**
* \name Clock Unit Initialization and Configuration
* @{
*/
/**
* \brief Initializes config with predefined default values for I<SUP>2</SUP>S clock unit.
*
* This function will initialize a given I<SUP>2</SUP>S Clock Unit configuration structure
* to a set of known default values. This function should be called on any new
* instance of the configuration structures before being modified by the user
* application.
*
* The default configuration is as follows:
* - The clock unit does not generate output clocks (MCK, SCK, and FS)
* - The pins (MCK, SCK, and FS) and MUX configurations are not set
*
* \param[out] config Pointer to a I<SUP>2</SUP>S module clock unit configuration struct
* to set
*/
static inline void i2s_clock_unit_get_config_defaults(
struct i2s_clock_unit_config *const config)
{
Assert(config);
config->clock.mck_out_enable = false;
config->clock.gclk_src = GCLK_GENERATOR_0;
config->clock.mck_src = I2S_MASTER_CLOCK_SOURCE_GCLK;
config->clock.mck_out_div = 1;
config->clock.mck_out_invert = false;
config->clock.sck_src = I2S_SERIAL_CLOCK_SOURCE_MCKDIV;
config->clock.sck_div = 1;
config->clock.sck_out_invert = false;
config->frame.number_slots = 1;
config->frame.slot_size = I2S_SLOT_SIZE_32_BIT;
config->frame.data_delay = I2S_DATA_DELAY_I2S;
config->frame.frame_sync.source = I2S_FRAME_SYNC_SOURCE_SCKDIV;
config->frame.frame_sync.width = I2S_FRAME_SYNC_WIDTH_HALF_FRAME;
config->frame.frame_sync.invert_use = false;
config->frame.frame_sync.invert_out = false;
config->mck_pin.enable = false;
config->mck_pin.mux = 0;
config->mck_pin.gpio = 0;
config->sck_pin.enable = false;
config->sck_pin.mux = 0;
config->sck_pin.gpio = 0;
config->fs_pin.enable = false;
config->fs_pin.mux = 0;
config->fs_pin.gpio = 0;
}
enum status_code i2s_clock_unit_set_config(
struct i2s_module *const module_inst,
const enum i2s_clock_unit clock_unit,
const struct i2s_clock_unit_config *config);
/** @} */
/**
* \name Clock Unit Enable/Disable
* @{
*/
/**
* \brief Enable the Specified Clock Unit of I<SUP>2</SUP>S module.
*
* Enables a Clock Unit in I<SUP>2</SUP>S module that has been previously initialized.
*
* \param[in] module_inst Pointer to the software module instance struct
* \param[in] clock_unit I<SUP>2</SUP>S Clock Unit to enable
*/
static inline void i2s_clock_unit_enable(
const struct i2s_module *const module_inst,
const enum i2s_clock_unit clock_unit)
{
uint32_t cken_bit;
Assert(module_inst);
Assert(module_inst->hw);
cken_bit = I2S_CTRLA_CKEN0 << clock_unit;
while (module_inst->hw->SYNCBUSY.reg & cken_bit) {
/* Sync wait */
}
module_inst->hw->CTRLA.reg |= cken_bit;
}
/**
* \brief Disable the Specified Clock Unit of I<SUP>2</SUP>S module.
*
* Disables a Clock Unit in I<SUP>2</SUP>S module that has been previously initialized.
*
* \param[in] module_inst Pointer to the software module instance struct
* \param[in] clock_unit I<SUP>2</SUP>S Clock Unit to disable
*/
static inline void i2s_clock_unit_disable(
const struct i2s_module *const module_inst,
const enum i2s_clock_unit clock_unit)
{
uint32_t cken_bit;
Assert(module_inst);
Assert(module_inst->hw);
cken_bit = I2S_CTRLA_CKEN0 << clock_unit;
while (module_inst->hw->SYNCBUSY.reg & cken_bit) {
/* Sync wait */
}
module_inst->hw->CTRLA.reg &= ~cken_bit;
}
/** @} */
/**
* \name Serializer Initialization and Configuration
* @{
*/
/**
* \brief Initializes config with predefined default values for I<SUP>2</SUP>S Serializer.
*
* This function will initialize a given I<SUP>2</SUP>S Clock Unit configuration structure
* to a set of known default values. This function should be called on any new
* instance of the configuration structures before being modified by the user
* application.
*
* The default configuration is as follows:
* - Output data does not internally loopback to input line
* - Does not extend mono data (left channel) to right channel
* - None of the data slot is disabled
* - MSB of I<SUP>2</SUP>S data is transferred first
* - In data word data is adjusted right
* - In slot data word is adjusted left
* - The data size is 16-bit width
* - I<SUP>2</SUP>S will padd 0 to not defined bits
* - I<SUP>2</SUP>S will padd 0 to not defined words
* - I<SUP>2</SUP>S will use single DMA channel for all data channels
* - I<SUP>2</SUP>S will use clock unit 0 to serve as clock
* - The default data line state is 0, when there is no data
* - I<SUP>2</SUP>S will transmit data to output line
* - The data pin and MUX configuration are not set
*
* \param[out] config Pointer to a I<SUP>2</SUP>S module Serializer configuration struct
* to set
*/
static inline void i2s_serializer_get_config_defaults(
struct i2s_serializer_config *const config)
{
config->loop_back = false;
config->mono_mode = false;
config->disable_data_slot[0] = false;
config->disable_data_slot[1] = false;
config->disable_data_slot[2] = false;
config->disable_data_slot[3] = false;
config->disable_data_slot[4] = false;
config->disable_data_slot[5] = false;
config->disable_data_slot[6] = false;
config->disable_data_slot[7] = false;
config->transfer_lsb_first = false;
config->data_adjust_left_in_word = false;
config->data_adjust_left_in_slot = true;
config->data_size = I2S_DATA_SIZE_16BIT;
config->bit_padding = I2S_BIT_PADDING_0;
config->data_padding = I2S_DATA_PADDING_0;
config->dma_usage = I2S_DMA_USE_SINGLE_CHANNEL_FOR_ALL;
config->clock_unit = I2S_CLOCK_UNIT_0;
config->line_default_state = I2S_LINE_DEFAULT_0;
config->mode = I2S_SERIALIZER_TRANSMIT;
config->data_pin.enable = false;
config->data_pin.gpio = 0;
config->data_pin.mux = 0;
}
enum status_code i2s_serializer_set_config(
struct i2s_module *const module_inst,
const enum i2s_serializer serializer,
const struct i2s_serializer_config *config);
/** @} */
/**
* \name Serializer Enable/Disable
* @{
*/
/**
* \brief Enable the Specified Serializer of I<SUP>2</SUP>S module.
*
* Enables a Serializer in I<SUP>2</SUP>S module that has been previously initialized.
*
* \param[in] module_inst Pointer to the software module instance struct
* \param[in] serializer I<SUP>2</SUP>S Serializer to enable
*/
static inline void i2s_serializer_enable(
const struct i2s_module *const module_inst,
const enum i2s_serializer serializer)
{
uint32_t seren_bit;
Assert(module_inst);
Assert(module_inst->hw);
seren_bit = I2S_CTRLA_SEREN0 << serializer;
while (module_inst->hw->SYNCBUSY.reg & seren_bit) {
/* Sync wait */
}
module_inst->hw->CTRLA.reg |= seren_bit;
}
/**
* \brief Disable the Specified Serializer of I<SUP>2</SUP>S module.
*
* Disables a Serializer in I<SUP>2</SUP>S module that has been previously initialized.
*
* \param[in] module_inst Pointer to the software module instance struct
* \param[in] serializer I<SUP>2</SUP>S Serializer to disable
*/
static inline void i2s_serializer_disable(
const struct i2s_module *const module_inst,
const enum i2s_serializer serializer)
{
uint32_t seren_bit;
Assert(module_inst);
Assert(module_inst->hw);
seren_bit = I2S_CTRLA_SEREN0 << serializer;
while (module_inst->hw->SYNCBUSY.reg & seren_bit) {
/* Sync wait */
}
module_inst->hw->CTRLA.reg &= ~seren_bit;
}
/** @} */
/**
* \name Status Management
* @{
*/
uint32_t i2s_get_status(
const struct i2s_module *const module_inst);
void i2s_clear_status(
const struct i2s_module *const module_inst,
uint32_t status);
enum status_code i2s_enable_status_interrupt(
struct i2s_module *const module_inst,
uint32_t status);
void i2s_disable_status_interrupt(
struct i2s_module *const module_inst,
uint32_t status);
/** @}*/
/**
* \name Data Read/Write
* @{
*/
/**
* \brief Write a data word to the specified Serializer of I<SUP>2</SUP>S module
*
* \param[in] module_inst Pointer to the software module instance struct
* \param[in] serializer The Serializer to write to
* \param[in] data The data to write
*
*/
static inline void i2s_serializer_write_wait(
const struct i2s_module *const module_inst,
enum i2s_serializer serializer,
uint32_t data)
{
uint32_t sync_bit, ready_bit;
Assert(module_inst);
Assert(module_inst->hw);
ready_bit = I2S_INTFLAG_TXRDY0 << serializer;
while (!(module_inst->hw->INTFLAG.reg & ready_bit)) {
/* Wait until ready to transmit */
}
sync_bit = I2S_SYNCBUSY_DATA0 << serializer;
while (module_inst->hw->SYNCBUSY.reg & sync_bit) {
/* Wait sync */
}
/* Write data */
module_inst->hw->DATA[serializer].reg = data;
module_inst->hw->INTFLAG.reg = ready_bit;
}
/**
* \brief Read a data word from the specified Serializer of I<SUP>2</SUP>S module
*
* \param[in] module_inst Pointer to the software module instance struct
* \param[in] serializer The Serializer to read
*/
static inline uint32_t i2s_serializer_read_wait(
const struct i2s_module *const module_inst,
enum i2s_serializer serializer)
{
uint32_t sync_bit, ready_bit;
uint32_t data;
Assert(module_inst);
Assert(module_inst->hw);
ready_bit = I2S_INTFLAG_RXRDY0 << serializer;
while (!(module_inst->hw->INTFLAG.reg & ready_bit)) {
/* Wait until ready to transmit */
}
sync_bit = I2S_SYNCBUSY_DATA0 << serializer;
while (module_inst->hw->SYNCBUSY.reg & sync_bit) {
/* Wait sync */
}
/* Read data */
data = module_inst->hw->DATA[serializer].reg;
module_inst->hw->INTFLAG.reg = ready_bit;
return data;
}
enum status_code i2s_serializer_write_buffer_wait(
const struct i2s_module *const module_inst,
enum i2s_serializer serializer,
void *buffer, uint32_t size);
enum status_code i2s_serializer_read_buffer_wait(
const struct i2s_module *const module_inst,
enum i2s_serializer serializer,
void *buffer, uint32_t size);
/** @} */
#ifdef __cplusplus
}
#endif
/** @} */
/**
* \page asfdoc_sam0_i2s_extra Extra Information for I2S Driver
*
* \section asfdoc_sam0_i2s_extra_acronyms Acronyms
* Below is a table listing the acronyms used in this module, along with their
* intended meanings.
*
* <table>
* <tr>
* <th>Acronym</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>I<SUP>2</SUP>S, IIS</td>
* <td>Inter-IC Sound Controller</td>
* </tr>
* <tr>
* <td>MCK</td>
* <td>Master Clock</td>
* </tr>
* <tr>
* <td>SCK</td>
* <td>Serial Clock</td>
* </tr>
* <tr>
* <td>FS</td>
* <td>Frame Sync</td>
* </tr>
* <tr>
* <td>SD</td>
* <td>Serial Data</td>
* </tr>
* <tr>
* <td>ADC</td>
* <td>Analog-to-Digital Converter</td>
* </tr>
* <tr>
* <td>DAC</td>
* <td>Digital-to-Analog Converter</td>
* </tr>
* <tr>
* <td>TDM</td>
* <td>Time Division Multiplexed</td>
* </tr>
* <tr>
* <td>PDM</td>
* <td>Pulse Density Modulation</td>
* </tr>
* <tr>
* <td>LSB</td>
* <td>Least Significant Bit</td>
* </tr>
* <tr>
* <td>MSB</td>
* <td>Most Significant Bit</td>
* </tr>
* <tr>
* <td>DSP</td>
* <td>Digital Signal Processor</td>
* </tr>
* </table>
*
*
* \section asfdoc_sam0_i2s_extra_dependencies Dependencies
* This driver has the following dependencies:
*
* - \ref asfdoc_sam0_system_pinmux_group "System Pin Multiplexer Driver"
*
*
* \section asfdoc_sam0_i2s_extra_errata Errata
* There are no errata related to this driver.
*
*
* \section asfdoc_sam0_i2s_extra_history Module History
* An overview of the module history is presented in the table below, with
* details on the enhancements and fixes made to the module since its first
* release. The current version of this corresponds to the newest version in
* the table.
*
* <table>
* <tr>
* <th>Changelog</th>
* </tr>
* <tr>
* <td>Initial Release</td>
* </tr>
* </table>
*/
/**
* \page asfdoc_sam0_i2s_exqsg Examples for I2S Driver
*
* This is a list of the available Quick Start guides (QSGs) and example
* applications for \ref asfdoc_sam0_i2s_group. QSGs are simple examples with
* step-by-step instructions to configure and use this driver in a selection of
* use cases. Note that QSGs can be compiled as a standalone application or be
* added to the user application.
*
* - \subpage asfdoc_sam0_i2s_basic_use_case
* \if I2S_CALLBACK_MODE
* - \subpage asfdoc_sam0_i2s_callback_use_case
* \endif
* - \subpage asfdoc_sam0_i2s_dma_use_case
*
* \page asfdoc_sam0_i2s_document_revision_history Document Revision History
*
* <table>
* <tr>
* <th>Doc. Rev.</th>
* <th>Date</th>
* <th>Comments</th>
* </tr>
* <tr>
* <td>42255B</td>
* <td>12/2015</td>
* <td>Added support for SAM DA1</td>
* </tr>
* <tr>
* <td>42255A</td>
* <td>01/2014</td>
* <td>Initial release</td>
* </tr>
* </table>
*/
#endif /* #ifndef I2S_H_INCLUDED */
|