forked from BelaPlatform/Bela
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpru_rtaudio_irq.p
2435 lines (2157 loc) · 91.3 KB
/
pru_rtaudio_irq.p
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
.origin 0
.entrypoint START
#include "../include/PruArmCommon.h"
#include "board_specific.h"
// The jump from QBEQ WRITE_ONE_BUFFER, r1, 0 is too long when all the devices
// are enabled. The code in there can probably be simplified and/or
// refeactored, maybe using JAL somewhere.
// In the meantime, we have the following switches to enable real-time selection of
// each device. If a device is not `define`d here, then it will not work.
// At least one needs to be selected. Maximum 2 can be selected without having
// the "jump too long" error mentioned above
//#define ENABLE_CTAG_FACE // enables run-time selection of the CTAG Face codec.
//#define ENABLE_CTAG_BEAST // enables run-time selection of the CTAG Beast codecs
#define ENABLE_BELA_TLV32 // enables run-time selection of the Bela TLV32 codec
#define ENABLE_BELA_GENERIC_TDM // enables run-time selection of custom TDM options
//#define ENABLE_MUXER // enables run-time selection of the Multiplexer capelet
// there are some issues with this code and this codec.
// See https://github.com/BelaPlatform/Bela/issues/480
#define CTAG_IGNORE_UNUSED_INPUT_TDM_SLOTS
#define SCRATCHPAD_ID_BANK0 10
#define SCRATCHPAD_ID_BANK1 11
#define SCRATCHPAD_ID_BANK2 12
#define SPI_SYSCONFIG 0x10
#define SPI_SYSSTATUS 0x14
#define SPI_IRQSTATUS 0x18
#define SPI_IRQENABLE 0x1C
#define SPI_MODULCTRL 0x28
#define SPI_CH0CONF 0x2C
#define SPI_CH0STAT 0x30
#define SPI_CH0CTRL 0x34
#define SPI_CH0TX 0x38
#define SPI_CH0RX 0x3C
#define SPI_CH1CONF 0x40
#define SPI_CH1STAT 0x44
#define SPI_CH1CTRL 0x48
#define SPI_CH1TX 0x4C
#define SPI_CH1RX 0x50
#define SPI_XFERLEVEL 0x7C
// SPI interrupts
#define SPI_INTR_BIT_TX0_EMPTY 0
#define SPI_INTR_BIT_TX0_UNDERFLOW 1
#define SPI_INTR_BIT_RX0_FULL 2
#define SPI_INTR_BIT_RX0_OVERFLOW 3
#define SPI_INTR_BIT_TX1_EMPTY 4
#define SPI_INTR_BIT_TX1_UNDERFLOW 5
#define SPI_INTR_BIT_RX1_FULL 6
#define SPI_INTR_BIT_TX2_EMPTY 8
#define SPI_INTR_BIT_TX2_UNDERFLOW 9
#define SPI_INTR_BIT_RX2_FULL 10
#define SPI_INTR_BIT_TX3_EMPTY 12
#define SPI_INTR_BIT_TX3_UNDERFLOW 13
#define SPI_INTR_BIT_RX3_FULL 14
#define SPI_INTR_BIT_EOW 17 // end of word
#define GPIO_OE 0x134
#define GPIO_DATAIN 0x138
#define GPIO_CLEARDATAOUT 0x190
#define GPIO_SETDATAOUT 0x194
// See am335x TRM 4.4.1.2.2 Event Interface Mapping (R31): PRU System Events:
// "The output channels [of R31] 0-15 are connected to the PRU-ICSS INTC system events 16-31, respectively. This allows the PRU to assert one of the system events 16-31 by writing to its own R31 register."
// PRU_SYSTEM_EVENT_RTDM is 20
// We will be writing to output channel 4, which is system event 20 of the PRU-ICSS INTC
#define PRU_SYSTEM_EVENT_RTDM_WRITE_VALUE (1 << 5) | (PRU_SYSTEM_EVENT_RTDM - 16)
#define C_ADC_DAC_MEM C24 // PRU0 mem
#define DAC_TRM 0 // SPI transmit and receive
#define DAC_WL 32 // Word length
#define DAC_CLK_MODE 1 // SPI mode
#define DAC_CLK_DIV 1 // Clock divider (48MHz / 2^n)
#define AD5668_COMMAND_OFFSET 24
#define AD5668_ADDRESS_OFFSET 20
#define AD5668_DATA_OFFSET 4
#define AD5668_REF_OFFSET 0
#define ADC_TRM 0 // SPI transmit and receive
#define ADC_WL 16 // Word length
#define ADC_CLK_MODE 0 // SPI mode
#define ADC_CLK_DIV 1 // Clock divider (48MHz / 2^n)
#define AD7699_CFG_MASK 0xF120 // Mask for config update, unipolar, full BW
#define AD7699_CHANNEL_OFFSET 9 // 7 bits offset of a 14-bit left-justified word
#define AD7699_SEQ_OFFSET 3 // sequencer (0 = disable, 3 = scan all)
#define SHARED_COMM_MEM_BASE 0x00010000 // Location where comm flags are written
// General constants for local PRU peripherals (used for interrupt configuration)
#define PRU_ICSS_INTC_LOCAL 0x00020000
#define PRU_ICSS_CFG_LOCAL 0x00026000
// General constant for PRU system events
// #define PRU_SYS_EV_MCSPI_INTR 44 // SINTERRUPTN
// PRU INTC system events (address relative to INTC_REG_SECR1)
#define PRU_SECR1_SYS_EV_MCSPI_INTR 12 // system event 44 (SINTERRUPTN)
#define PRU_SECR1_SYS_EV_MCASP_RX_INTR 22 // system event 54 (mcasp_r_intr_pend)
#define PRU_SECR1_SYS_EV_MCASP_TX_INTR 23 // system event 55 (mcasp_x_intr_pend)
// PRU interrupt controller registers
#define INTC_REG_GER 0x10 // Global host interrupt enable register
#define INTC_REG_SISR 0x20 // System event status indexed set register (allows setting the status of an event) - write only
#define INTC_REG_SICR 0x24 // System event status indexed clear register (allows clearing the status of an event) - write only
#define INTC_REG_EISR 0x28 // System event enable indexed set register (allows enabling an event) - write only
#define INTC_REG_EICR 0x2C // System event enable indexed clear register (allows disabling an event) - write only
#define INTC_REG_HIEISR 0x34 // Host interrupt enable indexed set register (allows enabling a host interrupt output)
#define INTC_REG_HIDISR 0x38 // Host interrupt enable indexed clear register (allows disabling a host interrupt output)
#define INTC_REG_SRSR0 0x200 // System event status raw/set register0 (show the pending enabled status of the system events 0 to 31)
#define INTC_REG_SRSR1 0x204 // System event status raw/set register0 (show the pending enabled status of the system events 32 to 63)
#define INTC_REG_SECR0 0x280 // System event status enabled/clear register0 (show the pending enabled status of the system events 0 to 31)
#define INTC_REG_SECR1 0x284 // System event status enabled/clear register1 (show the pending enabled status of the system events 32 to 63)
#define INTC_REG_ESR0 0x300 // System event enable set register0 (enables system events 0 to 31 to trigger outputs)
#define INTC_REG_ESR1 0x304 // System event enable set register1 (enables system events 32 to 64 to trigger outputs)
#define INTC_REG_ECR0 0x380 // System event enable clear register0 (disables system events 0 to 31 to map to channels)
#define INTC_REG_ECR1 0x384 // System event enable clear register1 (disables system events 32 to 63 to map to channels)
#define INTC_REG_CMR0 0x400 // Channel map register for system events 0 to 3
#define INTC_REG_CMR1 0x404 // Channel map register for system events 4 to 7
#define INTC_REG_CMR2 0x408 // Channel map register for system events 8 to 11
#define INTC_REG_CMR3 0x40C // Channel map register for system events 12 to 15
#define INTC_REG_CMR4 0x410 // Channel map register for system events 16 to 19
#define INTC_REG_CMR5 0x414 // Channel map register for system events 20 to 23
#define INTC_REG_CMR6 0x418 // Channel map register for system events 24 to 27
#define INTC_REG_CMR7 0x41C // Channel map register for system events 28 to 31
#define INTC_REG_CMR8 0x420 // Channel map register for system events 32 to 35
#define INTC_REG_CMR9 0x424 // Channel map register for system events 36 to 39
#define INTC_REG_CMR10 0x428 // Channel map register for system events 40 to 43
#define INTC_REG_CMR11 0x42C // Channel map register for system events 44 to 47
#define INTC_REG_CMR12 0x430 // Channel map register for system events 48 to 51
#define INTC_REG_CMR13 0x434 // Channel map register for system events 52 to 55
#define INTC_REG_CMR14 0x438 // Channel map register for system events 56 to 59
#define INTC_REG_CMR15 0x43C // Channel map register for system events 60 to 63
#define INTC_REG_HMR0 0x800 // Host interrupt map register for channels 0 - 3
#define INTC_REG_HMR1 0x804 // Host interrupt map register for channels 4 - 7
#define INTC_REG_HMR2 0x808 // Host interrupt map register for channels 8 - 9
#define INTC_REG_SIPR0 0xD00 // System event polarity register0 (define the polarity of the system events 0 to 31)
#define INTC_REG_SIPR1 0xD04 // System event polarity register0 (define the polarity of the system events 32 to 63)
#define INTC_REG_SITR0 0xD80 // System event type register0 (define the type of the system events 0 to 31)
#define INTC_REG_SITR1 0xD84 // System event type register0 (define the type of the system events 32 to 63)
#define INTC_REG_HIER 0x1500 // Host interrupt enable registers (enable / disable individual host interrupts)
// PRU INTC bits
#define PRU_INTR_BIT_CH0 30
#define PRU_INTR_BIT_CH1 31
// PRU CFG registers
#define CFG_REG_REV_ID 0x0
#define CFG_REG_SYSCFG 0x4
#define CFG_REG_REG_GPCFG0 0x8
#define CFG_REG_GPCFG1 0xC
#define CFG_REG_CGR 0x10
#define CFG_REG_ISRP 0x14
#define CFG_REG_ISP 0x18
#define CFG_REG_IESP 0x1C
#define CFG_REG_IECP 0x20
#define CFG_REG_PMAO 0x28
#define CFG_REG_MII_RT 0x2C
#define CFG_REG_IEPCLK 0x30
#define CFG_REG_SPP 0x34
#define CFG_REG_PIN_MX 0x40
#define MCASP_PWRIDLESYSCONFIG 0x04
#define MCASP_PFUNC 0x10
#define MCASP_PDIR 0x14
#define MCASP_PDOUT 0x18
#define MCASP_PDSET 0x1C
#define MCASP_PDIN 0x1C
#define MCASP_PDCLR 0x20
#define MCASP_GBLCTL 0x44
#define MCASP_AMUTE 0x48
#define MCASP_DLBCTL 0x4C
#define MCASP_DITCTL 0x50
#define MCASP_RGBLCTL 0x60
#define MCASP_RMASK 0x64
#define MCASP_RFMT 0x68
#define MCASP_AFSRCTL 0x6C
#define MCASP_ACLKRCTL 0x70
#define MCASP_AHCLKRCTL 0x74
#define MCASP_RTDM 0x78
#define MCASP_RINTCTL 0x7C
#define MCASP_RSTAT 0x80
#define MCASP_RSLOT 0x84
#define MCASP_RCLKCHK 0x88
#define MCASP_REVTCTL 0x8C
#define MCASP_XGBLCTL 0xA0
#define MCASP_XMASK 0xA4
#define MCASP_XFMT 0xA8
#define MCASP_AFSXCTL 0xAC
#define MCASP_ACLKXCTL 0xB0
#define MCASP_AHCLKXCTL 0xB4
#define MCASP_XTDM 0xB8
#define MCASP_XINTCTL 0xBC
#define MCASP_XSTAT 0xC0
#define MCASP_XSLOT 0xC4
#define MCASP_XCLKCHK 0xC8
#define MCASP_XEVTCTL 0xCC
#define MCASP_SRCTL0 0x180
#define MCASP_SRCTL1 0x184
#define MCASP_SRCTL2 0x188
#define MCASP_SRCTL3 0x18C
#define MCASP_SRCTL4 0x190
#define MCASP_SRCTL5 0x194
#define MCASP_SRCTL6 0x198
#define MCASP_SRCTL7 0x19C
#define MCASP_SRCTL8 0x1A0
#define MCASP_SRCTL9 0x1A4
#define MCASP_SRCTL10 0x1A8
#define MCASP_SRCTL11 0x1AC
#define MCASP_SRCTL12 0x1B0
#define MCASP_SRCTL13 0x1B4
#define MCASP_SRCTL14 0x1B8
#define MCASP_SRCTL15 0x1BC
#define MCASP_WFIFOCTL 0x1000
#define MCASP_WFIFOSTS 0x1004
#define MCASP_RFIFOCTL 0x1008
#define MCASP_RFIFOSTS 0x100C
#define MCASP_XSTAT_XUNDRN_BIT 0 // Bit to test if there was an underrun
#define MCASP_XSTAT_XSYNCERR_BIT 1 // Bit to test if there was an unexpected transmit frame sync
#define MCASP_XSTAT_XCKFAIL_BIT 2 // Bit to test if there was a transmit clock failure
#define MCASP_XSTAT_XDMAERR_BIT 7 // Bit to test if there was a transmit DMA error
#define MCASP_XSTAT_ERROR_BIT 8 // Bit to test if there was a transmit error
#define MCASP_XSTAT_XDATA_BIT 5 // Bit to test for transmit ready
#define MCASP_RSTAT_RDATA_BIT 5 // Bit to test for receive ready
#define MCASP_DATA_MASK 0xFFFF // 16 bit data
#define MCASP_AHCLKRCTL_VALUE 0x8001 // Internal clock, not inv, /2; irrelevant?
#define MCASP_AHCLKXCTL_VALUE 0x8001 // External clock from AHCLKX
#define MCASP_RINTCTL_VALUE 0x80 // Enable receive start of frame interrupt
#define MCASP_XINTCTL_VALUE 0x80 // Enable transmit start of frame interrupt
#define CTAG_MCASP_DATA_FORMAT_VALUE 0x180F4 // MSB first, 1 bit delay, 32 bits, DAT bus, ROR 16bits
#define CTAG_MCASP_ACLKRCTL_VALUE 0x80 // External clk, polarity (rising edge)
#define CTAG_FACE_MCASP_DATA_FORMAT_TX_VALUE CTAG_MCASP_DATA_FORMAT_VALUE
#define CTAG_FACE_MCASP_DATA_FORMAT_RX_VALUE CTAG_MCASP_DATA_FORMAT_VALUE
#define CTAG_FACE_MCASP_ACLKRCTL_VALUE CTAG_MCASP_ACLKRCTL_VALUE
#define CTAG_FACE_MCASP_ACLKXCTL_VALUE CTAG_MCASP_ACLKRCTL_VALUE
#define CTAG_FACE_MCASP_AHCLKRCTL_VALUE MCASP_AHCLKRCTL_VALUE
#define CTAG_FACE_MCASP_AHCLKXCTL_VALUE MCASP_AHCLKXCTL_VALUE
#define CTAG_FACE_MCASP_AFSRCTL_VALUE 0x410 // 8 Slot TDM, external fsclk, polarity (rising edge), single word
#define CTAG_FACE_MCASP_AFSXCTL_VALUE 0x410 // 8 Slot TDM, external fsclk, polarity (rising edge), single word
#define CTAG_FACE_MCASP_RTDM_VALUE 0xFF // Enable TDM slots 0 to 7
#define CTAG_FACE_MCASP_XTDM_VALUE 0xFF // Enable TDM slots 0 to 7
#define CTAG_FACE_MCASP_RINTCTL_VALUE MCASP_RINTCTL_VALUE
#define CTAG_FACE_MCASP_XINTCTL_VALUE MCASP_XINTCTL_VALUE
#define CTAG_BEAST_MCASP_DATA_FORMAT_TX_VALUE CTAG_MCASP_DATA_FORMAT_VALUE
#define CTAG_BEAST_MCASP_DATA_FORMAT_RX_VALUE CTAG_MCASP_DATA_FORMAT_VALUE
#define CTAG_BEAST_MCASP_ACLKRCTL_VALUE CTAG_MCASP_ACLKRCTL_VALUE
#define CTAG_BEAST_MCASP_ACLKXCTL_VALUE CTAG_MCASP_ACLKRCTL_VALUE
#define CTAG_BEAST_MCASP_AHCLKRCTL_VALUE MCASP_AHCLKRCTL_VALUE
#define CTAG_BEAST_MCASP_AHCLKXCTL_VALUE MCASP_AHCLKXCTL_VALUE
#define CTAG_BEAST_MCASP_AFSRCTL_VALUE 0x810 // 16 Slot TDM, external fsclk, polarity (rising edge), single word
#define CTAG_BEAST_MCASP_AFSXCTL_VALUE 0x810 // 16 Slot TDM, external fsclk, polarity (rising edge), single word
#define CTAG_BEAST_MCASP_RTDM_VALUE 0xFFFF // Enable TDM slots 0 to 15
#define CTAG_BEAST_MCASP_XTDM_VALUE 0xFFFF // Enable TDM slots 0 to 15
#define CTAG_BEAST_MCASP_RINTCTL_VALUE MCASP_RINTCTL_VALUE
#define CTAG_BEAST_MCASP_XINTCTL_VALUE MCASP_XINTCTL_VALUE
#define C_MCASP_MEM C28 // Shared PRU mem
// Flags for the flags register
#define FLAG_BIT_BUFFER1 0
#define FLAG_BIT_USE_SPI 1
#define FLAG_BIT_USE_DIGITAL 2
#define FLAG_BIT_MCASP_TX_FIRST_FRAME 3 // Wether we are in first frame of second (0 = first frame)
#define FLAG_BIT_MCASP_RX_FIRST_FRAME 4
#define FLAG_BIT_MCASP_TX_PROCESSED 5
#define FLAG_BIT_MCASP_RX_PROCESSED 6
#define FLAG_BIT_MCSPI_FIRST_FOUR_CH 7
#define FLAG_BIT_MUX_CONFIG0 8 // Mux capelet configuration:
#define FLAG_BIT_MUX_CONFIG1 9 // 00 = off, 01 = 2 ch., 10 = 4 ch., 11 = 8 ch.
#define FLAG_MASK_MUX_CONFIG 0x0300
#define FLAG_BIT_BELA_MINI 10
#define FLAG_BIT_CTAG 11
#define FLAG_BIT_CTAG_FACE 12
#define FLAG_BIT_CTAG_BEAST 13
#define FLAG_BIT_BELA_MULTI_TLV 14
// reg_flags should hold the number of audio in/out channels, up to 32
#define FLAG_BIT_AUDIO_IN_CHANNELS0 16
#define FLAG_BIT_AUDIO_IN_CHANNELS1 17
#define FLAG_BIT_AUDIO_IN_CHANNELS2 18
#define FLAG_BIT_AUDIO_IN_CHANNELS3 19
#define FLAG_BIT_AUDIO_IN_CHANNELS4 20
#define FLAG_BIT_AUDIO_IN_CHANNELS5 21
#define FLAG_BIT_AUDIO_OUT_CHANNELS0 22
#define FLAG_BIT_AUDIO_OUT_CHANNELS1 23
#define FLAG_BIT_AUDIO_OUT_CHANNELS2 24
#define FLAG_BIT_AUDIO_OUT_CHANNELS3 25
#define FLAG_BIT_AUDIO_OUT_CHANNELS4 26
#define FLAG_BIT_AUDIO_OUT_CHANNELS5 27
// Registers used throughout
// r1, r2, r3 are used for temporary storage
#define MEM_DIGITAL_BASE 0x11000 //Base address for DIGITAL : Shared RAM + 0x400
#define MEM_DIGITAL_BUFFER1_OFFSET 0x400 //Start pointer to DIGITAL_BUFFER1, which is 256 words after.
// 256 is the maximum number of frames allowed
#define reg_digital_current r6 // Pointer to current storage location of DIGITAL
#define reg_num_channels r9 // Number of SPI ADC/DAC channels to use
#define reg_frame_current r10 // Current frame count in SPI ADC/DAC transfer
#define reg_frame_mcasp_total r11 // Total frame count for McASP
#define reg_dac_data r12 // Current dword for SPI DAC
#define reg_adc_data r13 // Current dword for SPI ADC
#define reg_frame_spi_total r15 // Current dword for SPI ADC/DAC
#define reg_dac_buf0 r16 // Start pointer to SPI DAC buffer 0
#define reg_dac_buf1 r17 // Start pointer to SPI DAC buffer 1
#define reg_dac_current r18 // Pointer to current storage location of SPI DAC
#define reg_adc_current r19 // Pointer to current storage location of SPI ADC
#define reg_mcasp_buf0 r20 // Start pointer to McASP DAC buffer 0
#define reg_mcasp_buf1 r21 // Start pointer to McASP DAC buffer 1
#define reg_mcasp_dac_current r22 // Pointer to current storage location of McASP DAC
#define reg_mcasp_adc_current r23 // Pointer to current storage location of McASP ADC
#define reg_flags r24 // Buffer ID (0 and 1) and other flags
#define reg_comm_addr r25 // Memory address for communicating with ARM
#define reg_spi_addr r26 // Base address for SPI
// r27, r28 used in macros
#define reg_mcasp_addr r29 // Base address for McASP
#define reg_pru1_mux_pins r30 // Register mapped directly to P8 pins (PRU1 only)
#define REG_MCASP_BUF0_INIT 0
//0 P8_07 36 0x890/090 66 gpio2[2]
//1 P8_08 37 0x894/094 67 gpio2[3]
//2 P8_09 39 0x89c/09c 69 gpio2[5]
//3 P8_10 38 0x898/098 68 gpio2[4]
//4 P8_11 13 0x834/034 45 gpio1[13]
//5 P8_12 12 0x830/030 44 gpio1[12]
//6 P9_12 30 0x878/078 60 gpio1[28]
//7 P9_14 18 0x848/048 50 gpio1[18]
//8 P8_15 15 0x83c/03c 47 gpio1[15]
//9 P8_16 14 0x838/038 46 gpio1[14]
//10 P9_16 19 0x84c/04c 51 gpio1[19]
//11 P8_18 35 0x88c/08c 65 gpio2[1]
//12 P8_27 56 0x8e0/0e0 86 gpio2[22]
//13 P8_28 58 0x8e8/0e8 88 gpio2[24]
//14 P8_29 57 0x8e4/0e4 87 gpio2[23]
//15 P8_30 59 0x8ec/0ec 89 gpio2[25]
.macro SEND_ERROR_TO_ARM
.mparam error
MOV r27, error
SBBO r27, reg_comm_addr, COMM_ERROR_OCCURRED, 4
MOV r31.b0, PRU_SYSTEM_EVENT_RTDM_WRITE_VALUE
.endm
.macro IF_NOT_BELA_TLV32_OR_BELA_MULTI_TLV_JMP_TO
.mparam DEST
QBBS DEST, reg_flags, FLAG_BIT_CTAG
.endm
.macro IF_NOT_BELA_MINI_JMP_TO
.mparam DEST
QBBC DEST, reg_flags, FLAG_BIT_BELA_MINI
.endm
.macro IF_NOT_BELA_MULTI_TLV_JMP_TO
.mparam DEST
QBBC DEST, reg_flags, FLAG_BIT_BELA_MULTI_TLV
.endm
.macro IF_NOT_BELA_TLV32_JMP_TO
.mparam DEST
QBBS DEST, reg_flags, FLAG_BIT_BELA_MULTI_TLV
QBBS DEST, reg_flags, FLAG_BIT_CTAG
DONE:
.endm
.macro IF_HAS_ANALOG_DAC_JMP_TO
.mparam DEST
QBBS DONE, reg_flags, FLAG_BIT_BELA_MINI
QBA DEST
DONE:
.endm
#define IF_HAS_BELA_SPI_ADC_CS_JMP_TO IF_HAS_ANALOG_DAC_JMP_TO
.macro IF_NOT_CTAG_JMP_TO
.mparam DEST
QBBC DEST, reg_flags, FLAG_BIT_CTAG
.endm
.macro IF_NOT_CTAG_FACE_JMP_TO
.mparam DEST
QBBC DEST, reg_flags, FLAG_BIT_CTAG_FACE
.endm
.macro IF_NOT_CTAG_BEAST_JMP_TO
.mparam DEST
QBBC DEST, reg_flags, FLAG_BIT_CTAG_BEAST
.endm
.macro MCASP_SET_RX
.mparam mcasp_data_format_rx, mcasp_afsrctl_value, mcasp_aclkrctl_value, mcasp_ahclkrctl_value, mcasp_rtdm_value, mcasp_rintctl_value, mcasp_data_mask
MCASP_REG_WRITE MCASP_RFMT, mcasp_data_format_rx // Set data format
MCASP_REG_WRITE MCASP_AFSRCTL, mcasp_afsrctl_value // Set receive frameclock
MCASP_REG_WRITE MCASP_ACLKRCTL, mcasp_aclkrctl_value // Set receive bitclock
MCASP_REG_WRITE MCASP_AHCLKRCTL, mcasp_ahclkrctl_value
MCASP_REG_WRITE MCASP_RTDM, mcasp_rtdm_value
MCASP_REG_WRITE MCASP_RINTCTL, mcasp_rintctl_value // Enable receive start of frame interrupt
MCASP_REG_WRITE MCASP_RMASK, mcasp_data_mask // xx bit data transmit
.endm
.macro MCASP_SET_TX
.mparam mcasp_data_format, mcasp_afsxctl_value, mcasp_aclkxctl_value, mcasp_ahclkxctl_value, mcasp_xtdm_value, mcasp_xintctl_value, mcasp_data_mask
MCASP_REG_WRITE MCASP_XFMT, mcasp_data_format // Set data format
MCASP_REG_WRITE MCASP_AFSXCTL, mcasp_afsxctl_value // Set transmit frameclock
MCASP_REG_WRITE MCASP_ACLKXCTL, mcasp_aclkxctl_value // Set transmit bitclock
MCASP_REG_WRITE MCASP_AHCLKXCTL, mcasp_ahclkxctl_value
MCASP_REG_WRITE MCASP_XTDM, mcasp_xtdm_value
MCASP_REG_WRITE MCASP_XINTCTL, mcasp_xintctl_value
MCASP_REG_WRITE MCASP_XMASK, mcasp_data_mask // xx bit data transmit
.endm
.macro READ_GPIO_BITS
.mparam gpio_data, gpio_num_bit, digital_bit, digital
QBBC DONE, digital, digital_bit //if the pin is set as an output, nothing to do here
QBBC CLEAR, gpio_data, gpio_num_bit
SET digital, digital_bit+16
QBA DONE
CLEAR:
CLR digital, digital_bit+16
QBA DONE
DONE:
.endm
.macro SET_GPIO_BITS
.mparam gpio_oe, gpio_setdataout, gpio_cleardataout, gpio_num_bit, digital_bit, digital //sets the bits in GPIO_OE, GPIO_SETDATAOUT and GPIO_CLEARDATAOUT
//Remember that the GPIO_OE Output data enable register behaves as follows for each bit:
//0 = The corresponding GPIO pin is configured as an output.
//1 = The corresponding GPIO pin is configured as an input.
QBBS SETINPUT, digital, digital_bit
CLR gpio_oe, gpio_num_bit //if it is an output, configure pin as output
QBBC CLEARDATAOUT, digital, digital_bit+16 // check the output value. If it is 0, branch
SET gpio_setdataout, gpio_num_bit //if it is 1, set output to high
QBA DONE
CLEARDATAOUT:
SET gpio_cleardataout, gpio_num_bit // set output to low
QBA DONE
SETINPUT: //if it is an input, set the relevant bit
SET gpio_oe, gpio_num_bit
QBA DONE
DONE:
.endm
.macro READ_ACTIVE_CHANNELS_INTO_FLAGS
LBBO r27, reg_comm_addr, COMM_ACTIVE_CHANNELS, 4
// the high word contains the number of outputs
LSR r28, r27, 16
LSL r28, r28, FLAG_BIT_AUDIO_OUT_CHANNELS0
OR reg_flags, reg_flags, r28
// the low word contains the number of inputs
MOV r28, 0xFFFF
AND r28, r27, r28
LSL r28, r28, FLAG_BIT_AUDIO_IN_CHANNELS0
OR reg_flags, reg_flags, r28
.endm
// Read the number of audio channels from the flags register
.macro GET_NUM_AUDIO_IN_CHANNELS
.mparam DEST
LSR DEST, reg_flags, FLAG_BIT_AUDIO_IN_CHANNELS0
AND DEST, DEST, (64-1)
.endm
.macro GET_NUM_AUDIO_OUT_CHANNELS
.mparam DEST
LSR DEST, reg_flags, FLAG_BIT_AUDIO_OUT_CHANNELS0
AND DEST, DEST, (64-1)
.endm
.macro CONFIGURE_FIFO
.mparam fifo_address, reg_value
// The descriptions for WFIFOCTL and RWFIFOCTL seem to indicate that you
// need to set the lower bits first and only then set the enable bit.
// So we mask out the enable bit, write the value, wait a bit for the value
// to be recorded by the McASP, unmask the bit, write again
MOV r27, reg_value
// this has to be r27 (and not r28), or it will be overwritten
// by MCASP_REG_WRITE_EXT
CLR r27, r27, 16
MCASP_REG_WRITE_EXT fifo_address, r27
MOV r28, 1000
WAIT:
SUB r28, r28, 1
QBNE WAIT, r28, 0
MCASP_REG_WRITE_EXT fifo_address, reg_value
.endm
.macro COMPUTE_TDM_MASK
.mparam reg_io
QBEQ DONE, reg_io, 0
MOV r27, 0x1 // mask = (1 << numchannels) - 1
LSL r27, r27, reg_io
SUB reg_io, r27, 1
DONE:
.endm
// reg_io should contain number of channels when the macro is called, and will
// contain the output value by the end
.macro COMPUTE_SIZE_OF_BUFFER
.mparam reg_io, reg_total_frames
// if there are 0 channels, return immediately (reg_io will already contain 0!)
QBEQ DONE, reg_io, 0
LSL r27, reg_total_frames, 1 // r27 = 2[bytes]*n[frames]
MOV r28, reg_io
// from now on reg_io contains the output value
MOV reg_io, 0
SIZE_LOOP: // compute r27 * N[ch]
ADD reg_io, reg_io, r27
SUB r28, r28, 1
QBNE SIZE_LOOP, r28, 0
// now reg_out = N[ch]*2[bytes]*n[frames]
DONE:
.endm
.macro COMPUTE_SIZE_OF_MCASP_DAC_BUFFER
.mparam reg_out
// The memory needed for one McASP DAC buffer is N[ch]*2[bytes]*n[frames]
GET_NUM_AUDIO_OUT_CHANNELS reg_out
COMPUTE_SIZE_OF_BUFFER reg_out, reg_frame_mcasp_total
.endm
// this can only be used after reg_mcasp_buf0 and reg_mcasp_buf1 have been initialized
.macro COMPUTE_SIZE_OF_MCASP_DAC_BUFFER_FAST
.mparam reg_out
QBGT GREATER, reg_mcasp_buf1, reg_mcasp_buf0
SUB reg_out, reg_mcasp_buf1, reg_mcasp_buf0
QBA DONE
GREATER:
SUB reg_out, reg_mcasp_buf0, reg_mcasp_buf1
DONE:
.endm
.macro COMPUTE_SIZE_OF_MCASP_ADC_BUFFER
.mparam reg_out
// The memory needed for one McASP DAC buffer is N[ch]*2[bytes]*n[frames]
GET_NUM_AUDIO_IN_CHANNELS reg_out
COMPUTE_SIZE_OF_BUFFER reg_out, reg_frame_mcasp_total
.endm
QBA START_INTERMEDIATE // when first starting, go to START, skipping this section.
DIGITAL:
//IMPORTANT: do NOT use r28 in this macro, as it contains the return address for JAL
//r27 is now the input word passed in render(), one word per frame
//[31:16]: data(1=high, 0=low), [15:0]: direction (0=output, 1=input) )
#ifdef IS_AM572x
// same code as below with different mappings and without comments for brevity
// GPIO6-start
MOV r2, GPIO6 | GPIO_OE
LBBO r2, r2, 0, 4
MOV r8, 0
MOV r7, 0
SET_GPIO_BITS r2, r8, r7, 5, 0, r27
SET_GPIO_BITS r2, r8, r7, 6, 1, r27
SET_GPIO_BITS r2, r8, r7, 18, 2, r27
SET_GPIO_BITS r2, r8, r7, 4, 3, r27
MOV r3, GPIO6 | GPIO_OE
SBBO r2, r3, 0, 4
//GPIO6-end
//GPIO4-start
MOV r3, GPIO4 | GPIO_OE
LBBO r3, r3, 0, 4
MOV r5, 0
MOV r4, 0
SET_GPIO_BITS r3, r5, r4, 3, 8, r27
SET_GPIO_BITS r3, r5, r4, 29, 9, r27
SET_GPIO_BITS r3, r5, r4, 26, 10, r27
SET_GPIO_BITS r3, r5, r4, 9, 11, r27
SET_GPIO_BITS r3, r5, r4, 23, 12, r27
SET_GPIO_BITS r3, r5, r4, 19, 13, r27
SET_GPIO_BITS r3, r5, r4, 22, 14, r27
SET_GPIO_BITS r3, r5, r4, 20, 15, r27
MOV r2, GPIO4 | GPIO_OE //use r2 as a temp registerp
SBBO r3, r2, 0, 4 //takes two cycles (10ns)
//GPIO4-end
#else // IS_AM572x
//Preparing the gpio_oe, gpio_cleardataout and gpio_setdataout for each module
//r2 will hold GPIO1_OE
//load current status of GPIO_OE in r2
MOV r2, GPIO1 | GPIO_OE
//it takes 190ns to go through the next instruction
LBBO r2, r2, 0, 4
//GPIO1-start
//process oe and datain and prepare dataout for GPIO1
//r7 will contain GPIO1_CLEARDATAOUT
//r8 will contain GPIO1_SETDATAOUT
MOV r8, 0
MOV r7, 0
//map GPIO to gpio1 pins,
//r2 is gpio1_oe, r8 is gpio1_setdataout, r7 is gpio1_cleardataout, r27 is the input word
//the following operations will read from r27 and update r2,r7,r8
QBBS BELA_SET_GPIO_BITS_0_MINI, reg_flags, FLAG_BIT_BELA_MINI
QBA BELA_SET_GPIO_BITS_0_NOT_MINI
BELA_SET_GPIO_BITS_0_MINI:
SET_GPIO_BITS r2, r8, r7, 18, 0, r27
SET_GPIO_BITS r2, r8, r7, 27, 1, r27
SET_GPIO_BITS r2, r8, r7, 26, 2, r27
SET_GPIO_BITS r2, r8, r7, 25, 3, r27
SET_GPIO_BITS r2, r8, r7, 28, 4, r27
SET_GPIO_BITS r2, r8, r7, 20, 5, r27
SET_GPIO_BITS r2, r8, r7, 15, 6, r27
SET_GPIO_BITS r2, r8, r7, 14, 8, r27
SET_GPIO_BITS r2, r8, r7, 12, 9, r27
SET_GPIO_BITS r2, r8, r7, 9, 10, r27
SET_GPIO_BITS r2, r8, r7, 8, 11, r27
SET_GPIO_BITS r2, r8, r7, 10, 14, r27
SET_GPIO_BITS r2, r8, r7, 11, 15, r27
QBA SET_GPIO_BITS_0_DONE
BELA_SET_GPIO_BITS_0_NOT_MINI:
SET_GPIO_BITS r2, r8, r7, 13, 4, r27
SET_GPIO_BITS r2, r8, r7, 12, 5, r27
SET_GPIO_BITS r2, r8, r7, 28, 6, r27
SET_GPIO_BITS r2, r8, r7, 18, 7, r27
SET_GPIO_BITS r2, r8, r7, 15, 8, r27
SET_GPIO_BITS r2, r8, r7, 14, 9, r27
SET_GPIO_BITS r2, r8, r7, 19, 10, r27
SET_GPIO_BITS_0_DONE:
//set the output enable register for gpio1.
MOV r3, GPIO1 | GPIO_OE //use r3 as a temp register
SBBO r2, r3, 0, 4 //takes two cycles (10ns)
//GPIO1-end
// r2 is now unused
//GPIO2-start
//r3 will hold GPIO2_OE
//load current status of GPIO_OE in r3
MOV r3, GPIO2 | GPIO_OE
//it takes 200ns to go through the next instructions
LBBO r3, r3, 0, 4
//process oe and datain and prepare dataout for GPIO2
//r4 will contain GPIO2_CLEARDATAOUT
//r5 will contain GPIO2_SETDATAOUT
MOV r5, 0
MOV r4, 0
//map GPIO to gpio2 pins
//r3 is gpio2_oe, r5 is gpio2_setdataout, r4 is gpio2_cleardataout, r27 is the input word
//the following operations will read from r27 and update r3,r4,r5
QBBS BELA_SET_GPIO_BITS_1_MINI, reg_flags, FLAG_BIT_BELA_MINI
QBA BELA_SET_GPIO_BITS_1_NOT_MINI
BELA_SET_GPIO_BITS_1_MINI:
SET_GPIO_BITS r3, r5, r4, 0, 7, r27
SET_GPIO_BITS r3, r5, r4, 22, 12, r27
SET_GPIO_BITS r3, r5, r4, 24, 13, r27
QBA SET_GPIO_BITS_1_DONE
BELA_SET_GPIO_BITS_1_NOT_MINI:
SET_GPIO_BITS r3, r5, r4, 2, 0, r27
SET_GPIO_BITS r3, r5, r4, 3, 1, r27
SET_GPIO_BITS r3, r5, r4, 5, 2, r27
SET_GPIO_BITS r3, r5, r4, 4, 3, r27
SET_GPIO_BITS r3, r5, r4, 1, 11, r27
SET_GPIO_BITS r3, r5, r4, 22, 12, r27
SET_GPIO_BITS r3, r5, r4, 24, 13, r27
SET_GPIO_BITS r3, r5, r4, 23, 14, r27
SET_GPIO_BITS r3, r5, r4, 25, 15, r27
SET_GPIO_BITS_1_DONE:
//set the output enable register for gpio2.
MOV r2, GPIO2 | GPIO_OE //use r2 as a temp registerp
SBBO r3, r2, 0, 4 //takes two cycles (10ns)
//GPIO2-end
//r3 is now unused
#endif // IS_AM572x
QBA START_INTERMEDIATE_DONE
START_INTERMEDIATE: // intermediate step to jump to START
QBA START
START_INTERMEDIATE_DONE:
#ifdef IS_AM572x
MOV r2, GPIO6 | GPIO_DATAIN
MOV r3, GPIO4 | GPIO_DATAIN
LBBO r2, r2, 0, 4
LBBO r3, r3, 0, 4
//GPIO6
READ_GPIO_BITS r2, 5, 0, r27
READ_GPIO_BITS r2, 6, 1, r27
READ_GPIO_BITS r2, 18, 2, r27
READ_GPIO_BITS r2, 4, 3, r27
//GPIO4
READ_GPIO_BITS r3, 3, 8, r27
READ_GPIO_BITS r3, 29, 9, r27
READ_GPIO_BITS r3, 26, 10, r27
READ_GPIO_BITS r3, 9, 11, r27
READ_GPIO_BITS r3, 23, 12, r27
READ_GPIO_BITS r3, 19, 13, r27
READ_GPIO_BITS r3, 22, 14, r27
READ_GPIO_BITS r3, 20, 15, r27
MOV r2, GPIO6 | GPIO_CLEARDATAOUT
MOV r3, GPIO4 | GPIO_CLEARDATAOUT
SBBO r7, r2, 0, 8
SBBO r4, r3, 0, 8
#else // IS_AM572x
//load current inputs in r2, r3
//r2 will contain GPIO1_DATAIN
//r3 will contain GPIO2_DATAIN
//load the memory locations
MOV r2, GPIO1 | GPIO_DATAIN
MOV r3, GPIO2 | GPIO_DATAIN
//takes 375 nns to go through the next two instructions
//read the datain
LBBO r2, r2, 0, 4
LBBO r3, r3, 0, 4
//now read from r2 and r3 only the channels that are set as input in the lower word of r27
// and set their value in the high word of r27
QBBS BELA_READ_GPIO_BITS_MINI, reg_flags, FLAG_BIT_BELA_MINI
QBA BELA_READ_GPIO_BITS_NOT_MINI
BELA_READ_GPIO_BITS_MINI:
//GPIO1
READ_GPIO_BITS r2, 18, 0, r27
READ_GPIO_BITS r2, 27, 1, r27
READ_GPIO_BITS r2, 26, 2, r27
READ_GPIO_BITS r2, 25, 3, r27
READ_GPIO_BITS r2, 28, 4, r27
READ_GPIO_BITS r2, 20, 5, r27
READ_GPIO_BITS r2, 15, 6, r27
READ_GPIO_BITS r2, 14, 8, r27
READ_GPIO_BITS r2, 12, 9, r27
READ_GPIO_BITS r2, 9, 10, r27
READ_GPIO_BITS r2, 8, 11, r27
READ_GPIO_BITS r2, 10, 14, r27
READ_GPIO_BITS r2, 11, 15, r27
//GPIO2
READ_GPIO_BITS r3, 0, 7, r27
READ_GPIO_BITS r3, 22, 12, r27
READ_GPIO_BITS r3, 24, 13, r27
QBA READ_GPIO_BITS_DONE
BELA_READ_GPIO_BITS_NOT_MINI:
READ_GPIO_BITS r2, 13, 4, r27
READ_GPIO_BITS r2, 12, 5, r27
READ_GPIO_BITS r2, 28, 6, r27
READ_GPIO_BITS r2, 18, 7, r27
READ_GPIO_BITS r2, 15, 8, r27
READ_GPIO_BITS r2, 14, 9, r27
READ_GPIO_BITS r2, 19, 10, r27
//GPIO2
READ_GPIO_BITS r3, 2, 0, r27
READ_GPIO_BITS r3, 3, 1, r27
READ_GPIO_BITS r3, 5, 2, r27
READ_GPIO_BITS r3, 4, 3, r27
READ_GPIO_BITS r3, 1, 11, r27
READ_GPIO_BITS r3, 22, 12, r27
READ_GPIO_BITS r3, 24, 13, r27
READ_GPIO_BITS r3, 23, 14, r27
READ_GPIO_BITS r3, 25, 15, r27
READ_GPIO_BITS_DONE:
//r2, r3 are now unused
//now all the setdataout and cleardataout are ready to be written to the GPIO register.
//CLEARDATAOUT and SETDATAOUT are consecutive positions in memory, so we just write 8 bytes to CLEARDATAOUT.
//We can do this because we chose cleardata and setdata registers for a given GPIO to be consecutive
//load the memory addresses to be written to
MOV r2, GPIO1 | GPIO_CLEARDATAOUT //use r2 as a temp register
MOV r3, GPIO2 | GPIO_CLEARDATAOUT //use r3 as a temp register
//write 8 bytes for each GPIO
//takes 30ns in total to go through the following two instructions
SBBO r7, r2, 0, 8 //store r7 and r8 in GPIO1_CLEARDATAOUT and GPIO1_SETDATAOUT
//takes 145ns to be effective when going low, 185ns when going high
SBBO r4, r3, 0, 8 //store r4 and r5 in GPIO2_CLEARDATAOUT and GPIO2_SETDATAOUT
//takes 95ns to be effective when going low, 130ns when going high
//reversing the order of the two lines above will swap the performances between the GPIO modules
//i.e.: the first line will always take 145ns/185ns and the second one will always take 95ns/130ns,
//regardless of whether the order is gpio1-gpio2 or gpio2-gpio1
#endif // IS_AM572x
JMP r28.w0 // go back to ADC_WRITE_AND_PROCESS_GPIO
.macro HANG //useful for debugging
DALOOP:
set r30.t14
clr r30.t14
QBA DALOOP
.endm
// Bring CS line low to write to DAC
.macro DAC_CS_ASSERT
MOV r27, DAC_CS_PIN
MOV r28, DAC_GPIO + GPIO_CLEARDATAOUT
SBBO r27, r28, 0, 4
.endm
// Bring CS line high at end of DAC transaction
.macro DAC_CS_UNASSERT
MOV r27, DAC_CS_PIN
MOV r28, DAC_GPIO + GPIO_SETDATAOUT
SBBO r27, r28, 0, 4
.endm
// Write to DAC TX register
.macro DAC_TX
.mparam data
SBBO data, reg_spi_addr, SPI_CH0TX, 4
.endm
// Wait for SPI to finish (uses RXS indicator)
.macro DAC_WAIT_FOR_FINISH
LOOP:
LBBO r27, reg_spi_addr, SPI_CH0STAT, 4
QBBC LOOP, r27, 0
.endm
// Read the RX word to clear
.macro DAC_DISCARD_RX
LBBO r27, reg_spi_addr, SPI_CH0RX, 4
.endm
// Complete DAC write with chip select
.macro DAC_WRITE
.mparam reg
QBBS SKIP_DAC_WRITE_1, reg_flags, FLAG_BIT_BELA_MINI
DAC_CS_ASSERT
SKIP_DAC_WRITE_1:
DAC_TX reg
DAC_WAIT_FOR_FINISH
QBBS SKIP_DAC_WRITE_2, reg_flags, FLAG_BIT_BELA_MINI
DAC_CS_UNASSERT
SKIP_DAC_WRITE_2:
DAC_DISCARD_RX
.endm
.macro DAC_WRITE_ALL_ZEROS
.mparam tempreg
//command 0x3: write and update DAC channel n
//address 0xf: write to all channels
//data: 0
MOV tempreg, ((0x3 << AD5668_COMMAND_OFFSET) | (0xf << AD5668_ADDRESS_OFFSET) )
DAC_WRITE tempreg
.endm
// Transform channel order on DAC
// (in) 01234567 --> (out) 64201357
// This is to make the pin order on the Bela cape
// make sense
.macro DAC_CHANNEL_REORDER
.mparam out, in
QBBS DAC_CHANNEL_REORDER_HIGH, in, 2
// Input channels 0,1,2,3 --> 6,4,2,0
// out = (3 - in) << 1
XOR out, in, 0x03
LSL out, out, 1
QBA DAC_CHANNEL_REORDER_DONE
DAC_CHANNEL_REORDER_HIGH:
// Input channels 4,5,6,7 --> 1,3,5,7
// out = ((in & 0x03) << 1) + 1
AND out, in, 0x03
LSL out, out, 1
ADD out, out, 1
DAC_CHANNEL_REORDER_DONE:
.endm
// Bring CS line low to write to ADC
.macro ADC_CS_ASSERT
#ifndef IS_AM572x
IF_HAS_BELA_SPI_ADC_CS_JMP_TO BELA_CS
MOV r27, ADC_CS_PIN_BELA_MINI
MOV r28, ADC_GPIO_BELA_MINI + GPIO_CLEARDATAOUT
QBA DONE
#endif // IS_AM572x
BELA_CS:
MOV r27, ADC_CS_PIN
MOV r28, ADC_GPIO + GPIO_CLEARDATAOUT
DONE:
SBBO r27, r28, 0, 4
.endm
// Bring CS line high at end of ADC transaction
.macro ADC_CS_UNASSERT
#ifndef IS_AM572x
IF_HAS_BELA_SPI_ADC_CS_JMP_TO BELA_CS
MOV r27, ADC_CS_PIN_BELA_MINI
MOV r28, ADC_GPIO_BELA_MINI + GPIO_SETDATAOUT
QBA DONE
#endif // IS_AM572x
BELA_CS:
MOV r27, ADC_CS_PIN
MOV r28, ADC_GPIO + GPIO_SETDATAOUT
DONE:
SBBO r27, r28, 0, 4
.endm
// Write to ADC TX register
.macro ADC_TX
.mparam data
SBBO data, reg_spi_addr, SPI_CH1TX, 4
.endm
// Wait for SPI to finish (uses RXS indicator)
.macro ADC_WAIT_FOR_FINISH
LOOP:
LBBO r27, reg_spi_addr, SPI_CH1STAT, 4
QBBC LOOP, r27, 0
.endm
// Read the RX word to clear; store output
.macro ADC_RX
.mparam data
LBBO data, reg_spi_addr, SPI_CH1RX, 4
.endm
// Complete ADC write+read with chip select
.macro ADC_WRITE
.mparam in, out
ADC_CS_ASSERT
ADC_TX in
ADC_WAIT_FOR_FINISH
ADC_RX out
ADC_CS_UNASSERT
.endm
// Complete ADC write+read with chip select and also performs IO for digital
.macro ADC_WRITE_GPIO
.mparam in, out, do_gpio
ADC_CS_ASSERT
ADC_TX in
QBBC GPIO_DONE, reg_flags, FLAG_BIT_USE_DIGITAL //skip if DIGITAL is disabled
QBLT CASE_4_OR_8_CHANNELS, reg_num_channels, 2
CASE_2_CHANNELS:
AND r27, reg_frame_current, 0x1
QBNE GPIO_DONE, r27, 0
JMP DO_GPIO
CASE_4_OR_8_CHANNELS:
AND r27, do_gpio, 0x3 // only do a DIGITAL every 2 SPI I/O
QBNE GPIO_DONE, r27, 0
DO_GPIO:
//from here to GPIO_DONE takes 1.8us, while usually ADC_WAIT_FOR_FINISH only waits for 1.14us.
//TODO: it would be better to split the DIGITAL stuff in two parts:
//- one taking place during DAC_WRITE which sets the GPIO_OE
//- and the other during ADC_WRITE which actually reads DATAIN and writes CLEAR/SET DATAOUT
//r27 is actually r27, so do not use r27 from here to ...
LBBO r27, reg_digital_current, 0, 4
JAL r28.w0, DIGITAL // note that this is not called as a macro, but with JAL. r28 will contain the return address
SBBO r27, reg_digital_current, 0, 4
//..here you can start using r27 again
ADD reg_digital_current, reg_digital_current, 4 //increment pointer
GPIO_DONE:
ADC_WAIT_FOR_FINISH
ADC_RX out
ADC_CS_UNASSERT
.endm
// Write PRU interrupt controller register beyond 0xFF boundary.
// Temporarily use r0 to store address of PRU interrupt controller.
.macro PRU_ICSS_INTC_REG_WRITE_EXT
.mparam reg, value
MOV r0, PRU_ICSS_INTC_LOCAL
MOV r27, value
MOV r28, reg
ADD r28, r0, r28
SBBO r27, r28, 0, 4
.endm
// Read PRU interrupt controller register beyond 0xFF boundary.
// Temporarily use r0 to store address of PRU interrupt controller.
.macro PRU_ICSS_INTC_REG_READ_EXT
.mparam reg, value
MOV r0, PRU_ICSS_INTC_LOCAL
MOV r28, reg
ADD r28, r0, r28
LBBO value, r28, 0, 4
.endm
// Write PRU config register beyond 0xFF boundary.
// Temporarily use r0 to store address of PRU config module.
.macro PRU_ICSS_CFG_REG_WRITE_EXT
.mparam reg, value
MOV r0, PRU_ICSS_CFG_LOCAL
MOV r27, value
MOV r28, reg
ADD r28, r0, r28
SBBO r27, r28, 0, 4
.endm
// Read PRU config register beyond 0xFF boundary.
// Temporarily use r0 to store address of PRU config module.
.macro PRU_ICSS_CFG_REG_READ_EXT
.mparam reg, value
MOV r0, PRU_ICSS_CFG_LOCAL
MOV r28, reg
ADD r28, r0, r28
LBBO value, r28, 0, 4
.endm
// Write a McASP register
.macro MCASP_REG_WRITE
.mparam reg, value
MOV r27, value
SBBO r27, reg_mcasp_addr, reg, 4
.endm