-
Notifications
You must be signed in to change notification settings - Fork 1
/
NeoVGA.spin2
1977 lines (1632 loc) · 63.5 KB
/
NeoVGA.spin2
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
CON
SUBMODE_NTSC = 0
SUBMODE_PAL = 1<<8 ' Can be combined with others...
SUBMODE_FORCE_ALTPILLAR = 1<<9 ' TODO NYI Can be combined with others...
SUBMODE_FORCE_REC601 = 1<<10 ' Force Rec601 color space for YPbPr
SUBMODE_FORCE_REC709 = 1<<11 ' Force Rec709 color space for YPbPr
#0,MODE_RGBHV,MODE_RGBS,MODE_SoG,MODE_YPBPR,MODE_COMPOSITE,MODE_SVIDEO,MODE_SVID_AND_COMP,MODE_DVI,MODE_DVI_VGA,MODE_HDMI,MODE_HDMI_VGA,MODE_LCD6
MODE_VGA = MODE_RGBHV
#0,SUBMODE_AUTO,SUBMODE_1X,SUBMODE_2X,SUBMODE_3X,SUBMODE_4X,SUBMODE_5X, ... ' Analog line-multiply modes
SUBMODE_TMDS_640x480,SUBMODE_TMDS_768x480,SUBMODE_TMDS_800x480,SUBMODE_TMDS_854x480
#0, LCD_ILI9342
' MADCTL values for ILI submode
ILI_HFLIP = %00000100 << 8 ' Doesn't work in bypass mode
ILI_VFLIP = %00010000 << 8
ILI_BGR = %00001000 << 8 ' Toggle this if colors are wrong
TMDS_REVERSE_FLAG = 64<<8
MAX_INIT = 64
WIDTH = 320
WIDTH_ALT = 256 ' Not used in NeoYume
HEIGHT = 224
BORDER_TOP = 8
BORDER_BOTTOM = 8
HEIGHT_TOTAL = HEIGHT+BORDER_BOTTOM+BORDER_TOP
VDPBIT_INTERLACE = 1
VDPBIT_ALTRES = 0
VDP_INVERT_ALTRES = false
VDPR_OFFSET = 3 ' lines that rendering has to run ahead
PUB start(pins,extrapins,mode,submode,buffer,extrastride,buflines,linectr,vdpmode,audio_mb_period) : cogn | cmode,timing,initf,stride
case mode
MODE_RGBHV..MODE_YPBPR: ' All arbitrary-resolution analog modes
case submode&255
SUBMODE_1X: timing := @timing_native
SUBMODE_3X: timing := @timing_line3x
other: timing := @timing_line2x
case mode
MODE_RGBHV:
cmode := @cmode_rgbhv_tmds
initf := @init_rgbhv
MODE_RGBS:
cmode := @cmode_rgbs
initf := @init_rgbs
MODE_SoG:
cmode := @cmode_sync_on_green
initf := @init_soggy
MODE_YPBPR:
if submode&SUBMODE_FORCE_REC709 || (long[timing][1] >= 3 && not(submode&SUBMODE_FORCE_REC601))
cmode := @cmode_ypbpr709
debug("YPbPr matrix set to Rec709")
else
cmode := @cmode_ypbpr601
debug("YPbPr matrix set to Rec601")
initf := @init_soggy
MODE_COMPOSITE..MODE_SVID_AND_COMP: ' NTSC/PAL encoded modes
timing := @timing_native ' Always
if submode&SUBMODE_PAL
cmode := @cmode_pal
else
cmode := @cmode_ntsc
case mode
MODE_COMPOSITE: initf := @init_composite
MODE_SVIDEO: initf := @init_svideo
MODE_SVID_AND_COMP: initf := @init_compsvid
MODE_DVI..MODE_HDMI_VGA: ' All TMDS modes
cmode := @cmode_rgbhv_tmds
case mode
MODE_DVI: initf := @init_dvi
MODE_DVI_VGA: initf := @init_dvivga
MODE_HDMI: initf := @init_hdmi
MODE_HDMI_VGA: initf := @init_hdmivga
case submode&255
SUBMODE_TMDS_768x480: timing := @timing_tmds_768x480
SUBMODE_TMDS_800x480: timing := @timing_tmds_800x480
SUBMODE_TMDS_854x480: timing := @timing_tmds_854x480
other: timing := @timing_tmds_640x480
MODE_LCD6:
cmode := @cmode_lcd6
initf := @init_ili9342
timing := @timing_lcd6_320x240
other:
abort -1
clkset(computeClockMode(long[timing]),long[timing])
stride := WIDTH*4+extrastride
return startx(pins,extrapins,buffer,stride,buffer+stride*buflines,linectr,vdpmode,timing,cmode,initf,audio_mb_period)
PUB startx(pins,extrapins,buffer_base,buffer_stride,buffer_wrap,linectr,vdpmode,timing,color,initfunc,audio_mb_period) : cogn
cogn := coginit(HUBEXEC_NEW,@video_init,@pins)
waitms(1) ' wait so stack frame isn't rugpulled
DAT ' Color modes
cmode_rgbhv_tmds ' RGBHV and TMDS hybrid mode
long $00_00_00_00 ' DAC blanking value
long TMDS_BLANK ' Blanking color
long TMDS_HSYNC ' HSync color
long TMDS_VSYNC ' VSync color
long TMDS_HVSYNC ' HSync+VSync color
long 0 ' Color burst color (NTSC/PAL only)
long 0 ' Color burst frequency (NTSC/PAL only)
long $5A_00_00_00 ' CY
long $00_5A_00_00 ' CI
long $00_00_5A_00 ' CQ
long 0 ' CQ XOR value (NTSC/PAL only)
cmode_rgbs ' RGB + CSync mode
long $00_00_00_00 ' DAC blanking value
long $00_00_00_00 ' Blanking color
long $00_00_00_01 ' HSync color
long $00_00_00_01 ' VSync color
long $00_00_00_00 ' HSync+VSync color
long 0 ' Color burst color (NTSC/PAL only)
long 0 ' Color burst frequency (NTSC/PAL only)
long $5A_00_00_00 ' CY
long $00_5A_00_00 ' CI
long $00_00_5A_00 ' CQ
long 0 ' CQ XOR value (NTSC/PAL only)
cmode_sync_on_green ' RGB SoG mode
long $00_00_00_00 ' DAC blanking value
long Y_BLANK ' Blanking color
long Y_SYNC ' HSync color
long Y_SYNC ' VSync color
long Y_BLANK ' HSync+VSync color
long 0 ' Color burst color (NTSC/PAL only)
long 0 ' Color burst frequency (NTSC/PAL only)
long $5A_00_00<<8 + BLANK_LEVEL ' CY
long $00_5A_00<<8 + BLANK_LEVEL ' CI
long $00_00_5A<<8 + BLANK_LEVEL ' CQ
long 0 ' CQ XOR value (NTSC/PAL only)
cmode_ypbpr601 ' YPbPr (with Rec. 601 matrix for SDTV)
long $00_00_00_00 ' DAC blanking value
long Y_BLANK ' Blanking color
long Y_SYNC ' HSync color
long Y_SYNC ' VSync color
long Y_BLANK ' HSync+VSync color
long 0 ' Color burst color (NTSC/PAL only)
long 0 ' Color burst frequency (NTSC/PAL only)
long ( 45&$FF) << 24 + (-38&$FF) << 16 + ( -7&$FF) << 8 + 128 ' CY
long ( 27&$FF) << 24 + ( 53&$FF) << 16 + ( 10&$FF) << 8 + BLANK_LEVEL ' CI
long (-15&$FF) << 24 + (-30&$FF) << 16 + ( 45&$FF) << 8 + 128 ' CQ
long 0 ' CQ XOR value (NTSC/PAL only)
cmode_ypbpr709 ' YPbPr (with Rec. 709 matrix for HDTV)
long $00_00_00_00 ' DAC blanking value
long Y_BLANK ' Blanking color
long Y_SYNC ' HSync color
long Y_SYNC ' VSync color
long Y_BLANK ' HSync+VSync color
long 0 ' Color burst color (NTSC/PAL only)
long 0 ' Color burst frequency (NTSC/PAL only)
long ( 45&$FF) << 24 + (-41&$FF) << 16 + ( -4&$FF) << 8 + 128 ' CY
long ( 19&$FF) << 24 + ( 64&$FF) << 16 + ( 7&$FF) << 8 + BLANK_LEVEL ' CI
long (-10&$FF) << 24 + (-35&$FF) << 16 + ( 45&$FF) << 8 + 128 ' CQ
long 0 ' CQ XOR value (NTSC/PAL only)
cmode_ntsc
long $00_00_00_00
long %01 ' Blanking color
long %11 ' HSync color
long %11 ' VSync color
long %01 ' HSync+VSync color
long COLOR_BURST_NTSC ' Color burst color (NTSC/PAL only)
long round(4_294_967_296.0*3_579_545.0/float(VIDEO_CLKFREQ)) ' Color burst frequency (NTSC/PAL only)
long CY_NTSC ' CY
long CI_NTSC ' CI
long CQ_NTSC ' CQ
long 0 ' CQ XOR value (NTSC/PAL only)
cmode_pal
long $00_00_00_00
long %01 ' Blanking color
long %11 ' HSync color
long %11 ' VSync color
long %01 ' HSync+VSync color
long COLOR_BURST_PAL ' Color burst color (NTSC/PAL only)
long round(4_294_967_296.0*4_433_618.0/float(VIDEO_CLKFREQ)) ' Color burst frequency (NTSC/PAL only)
long CY_PAL ' CY
long CU_PAL ' CI
long CV_PAL_EVEN ' CQ
long CV_PAL_ODD^CV_PAL_EVEN ' CQ XOR value (NTSC/PAL only)
cmode_lcd6 ' 6 bit color-sequential LCD interface with H/V Sync
long $00_00_00_00 ' DAC blanking value
long $00_00_00_00 ' Blanking color
long $00_00_00_01 ' HSync color
long $00_00_00_02 ' VSync color
long $00_00_00_03 ' HSync+VSync color
long 0 ' Color burst color (NTSC/PAL only)
long 0 ' Color burst frequency (NTSC/PAL only)
long 0 ' CY
long 0 ' CI
long 0 ' CQ
long 0 ' CQ XOR value (NTSC/PAL only)
DAT ' Timings
timing_native
long VIDEO_CLKFREQ ' CLKFREQ
long 1 ' active line multiplier
long 3 ' V front porch
long 9 ' V sync
long 12 ' V back porch
long 0 ' extra pillar
long 320 ' blank line
long 8 ' H front porch
long 28 ' H sync
long 28 ' H back porch
long round(2147483648.0/float(CLK_MULTIPLIER*4)) ' Sync NCO
long round(2147483648.0/float(CLK_MULTIPLIER*4)) ' Pixel NCO
long round(2147483648.0/float(CLK_MULTIPLIER*4)*256.0/320.0) ' Alt-res NCO
long 3 ' Breezeway (NTSC/PAL only - subtracts from H.BP)
long 16 ' Burst (NTSC/PAL only - subtracts from H.BP)
timing_line2x
long VIDEO_CLKFREQ ' CLKFREQ
long 2 ' active line multiplier
long 12 ' V front porch
long 2 ' V sync
long 34 ' V back porch
long 0 ' extra pillar
long 320 ' blank line
long 8 ' H front porch
long 48 ' H sync
long 24 ' H back porch
long round(2147483648.0/13.45/2.0) ' Sync NCO
long round(2147483648.0/13.45/2.0) ' Pixel NCO
long round(2147483648.0/13.45/2.0*256.0/320.0) ' Alt-res NCO
long 0 ' Breezeway (NTSC/PAL only - subtracts from H.BP)
long 0 ' Burst (NTSC/PAL only - subtracts from H.BP)
timing_line3x
long VIDEO_CLKFREQ ' CLKFREQ
long 3 ' active line multiplier
long 18 ' V front porch
long 3 ' V sync
long 51 ' V back porch
long 0 ' extra pillar
long 320 ' blank line
long 8 ' H front porch
long 48 ' H sync
long 24 ' H back porch
long round(2147483648.0/13.45/2.0*1.5) ' Sync NCO
long round(2147483648.0/13.45/2.0*1.5) ' Pixel NCO
long round(2147483648.0/13.45/2.0*1.5*256.0/320.0) ' Alt-res NCO
long 0 ' Breezeway (NTSC/PAL only - subtracts from H.BP)
long 0 ' Burst (NTSC/PAL only - subtracts from H.BP)
timing_owieouch
long VIDEO_CLKFREQ ' CLKFREQ
long 2 ' active line multiplier
long 12 ' V front porch
long 2 ' V sync
long 34 ' V back porch
long 160 ' extra pillar
long 640 ' blank line
long 56 ' H front porch
long 96 ' H sync
long 283 ' H back porch
long $0CCCCCCD ' Sync NCO
long $0CCCCCCD ' Pixel NCO
long 2 ' Alt-res NCO
long 0 ' Breezeway (NTSC/PAL only - subtracts from H.BP)
long 0 ' Burst (NTSC/PAL only - subtracts from H.BP)
timing_tmds_640x480
long VIDEO_CLKFREQ ' CLKFREQ
long 2 ' active line multiplier
long 12 ' V front porch
long 2 ' V sync
long 34 ' V back porch
long 0 ' extra pillar
long 640 ' blank line
long 56 ' H front porch
long 96 ' H sync
long 283 ' H back porch
long $0CCCCCCD ' Sync NCO
long 0 ' Pixel NCO
long 2 ' Alt-res NCO
long 0 ' Unused
long 2 ' Guard Bands (HDMI only - subtracts from H.BP)
timing_tmds_768x480
long VIDEO_CLKFREQ ' CLKFREQ
long 2 ' active line multiplier
long 12 ' V front porch
long 2 ' V sync
long 34 ' V back porch
long 64 ' extra pillar
long 768 ' blank line
long 56 ' H front porch
long 96 ' H sync
long 155 ' H back porch
long $0CCCCCCD ' Sync NCO
long 0 ' Pixel NCO
long 2 ' Alt-res NCO
long 0 ' Unused
long 2 ' Guard Bands (HDMI only - subtracts from H.BP)
timing_tmds_800x480
long VIDEO_CLKFREQ ' CLKFREQ
long 2 ' active line multiplier
long 12 ' V front porch
long 2 ' V sync
long 34 ' V back porch
long 80 ' extra pillar
long 800 ' blank line
long 56 ' H front porch
long 96 ' H sync
long 123 ' H back porch
long $0CCCCCCD ' Sync NCO
long 0 ' Pixel NCO
long 2 ' Alt-res NCO
long 0 ' Unused
long 2 ' Guard Bands (HDMI only - subtracts from H.BP)
timing_tmds_854x480
long VIDEO_CLKFREQ ' CLKFREQ
long 2 ' active line multiplier
long 12 ' V front porch
long 2 ' V sync
long 34 ' V back porch
long 107 ' extra pillar
long 854 ' blank line
long 56 ' H front porch
long 96 ' H sync
long 69 ' H back porch
long $0CCCCCCD ' Sync NCO
long 0 ' Pixel NCO
long 2 ' Alt-res NCO
long 0 ' Unused
long 2 ' Guard Bands (HDMI only - subtracts from H.BP)
timing_lcd6_320x240
long VIDEO_CLKFREQ ' CLKFREQ
long 1 ' active line multiplier
long 3 ' V front porch
long 9 ' V sync
long 12 ' V back porch
long 0 ' extra pillar
long 320*3 ' blank line
long 5*3 ' H front porch
long 15*3 ' H sync
long 59*3 ' H back porch
long $071c71c8 ' Sync NCO
long 0 ' Pixel NCO
long 3 ' Alt-res NCO
long 18 + (18>>1)<<16 ' pixel clock pulses
long 1
DAT ' Cog-resident code
org
video_cog_code
hsync_ntsc ' also PAL
setq nco_sync
xcont hsync_tip,hsync_color
xcont hsync_breeze,blank_color
xor cq_val,cq_xor
setcq cq_val ' here because we know tip must be in progress
xcont hsync_burst,burst_color
xcont hsync_bpshort,blank_color
jmp #vline_update
vsync_ntsc ' SDTV serrated sync
' TODO
ret
scanfunc_2x_rgb24 ' scan out 2 pixels with 2x doubling -> 40 streamer cycles
' actual function takes 18cy (inc. call overhead)
' so 11 instructions can go between calls
rflong scantmp
andn scantmp,#255 ' mask alpha/control channel (DMA would do this for us)
xcont pixel_multiplier,scantmp
rflong scantmp
andn scantmp,#255
_ret_ xcont pixel_multiplier,scantmp
line_scancomp_alt
cmp extra_pillar,#0 wz
if_nz xcont extra_pillar,border_color
xcont altres_pillar,border_color
mov scantimecomp,#WIDTH_ALT/2
mov scanfunc,active_scanfunc
call scantask
.comploop cmpsub scantimecomp,#1 wc
if_c call scanfunc
if_c call audio_poll_func
if_c jmp #.comploop
xcont altres_pillar,border_color
cmp extra_pillar,#0 wz
if_nz xcont extra_pillar,border_color
call audio_poll_func
_ret_ xcont hsync_fp,blank_color
line_scancomp ' Software-scaled line with scan-compensated task
cmp extra_pillar,#0 wz
if_nz xcont extra_pillar,border_color
mov scantimecomp,#WIDTH/2
mov scanfunc,active_scanfunc
call scantask
.comploop cmpsub scantimecomp,#1 wc
if_c call scanfunc
if_c call audio_poll_func
if_c jmp #.comploop
cmp extra_pillar,#0 wz
if_nz xcont extra_pillar,border_color
_ret_ xcont hsync_fp,blank_color
dummy_func
ret
vsync_pin long -1
border_color long $00_00_00_00
altres_pillar long (WIDTH - WIDTH_ALT)/2
linecmd long WIDTH
linecmd_alt long WIDTH_ALT
bitbangcmd long 1
packetblank long 32
bit31 long 1<<31
min31 long $C000_0000
max31 long $3FFF_FFFF
hsync_func long hsync_normal
vbi_hsync_func long hsync_normal
vsync_func long vsync_normal
line_func long line_native
altline_func long line_native_altnco
borderline_func long line_border
blankline_func long line_blank
audio_poll_func long dummy_func
scanfunc long dummy_func
scantask long dummy_func
active_scanfunc long scanfunc_2x_rgb24
' Audio poller upper - pin number is patched in on demand
audio_poll_repo
cmp audio_inbuf_level,#4 wc
.pptchd if_c testp #0-0 wc ' TESTP is a D-only instr
if_c altd audio_inbuf_level,.inbuf_incr
.pptchs if_c rdpin 0-0,#0-0
ret wcz
.inbuf_incr long audio_inbuffer + (1<<9)
'|||| 48K rate here!!! | Disable copy protection
spdif_status long %00_00_0010_00000000_00000000_00000100
'|||| 24 bit sample length (load bearing)
long %00000000_00000000_00000000_0000_1011
' Sample rate is overwritten by init code when appropriate
' application parameters (must by synced with startx arglist)
app_params
vpins res 1 ' furled up analog+digital
extravpins res 1 ' used for VSYNC etc
scanbuffer_base res 1
scanbuffer_stride res 1
scanbuffer_wrap res 1 ' base + (stride*lines)
linectr_ptr res 1
vdpmode_ptr res 1
timing_ptr res 1
color_ptr res 1
initfunc_ptr res 1
audio_period res 1
app_params_end
' Timing variables
timing_vars
dummy_clkfreq res 1 ' handled by Spin code
line_multiplier res 1 ' 0 will create SDTV-style serrated VSync with real interlacing
fp_lines res 1
sync_lines res 1
bp_lines res 1
extra_pillar res 1 ' permanent pillarbox (left and right) in nco_sync units
blankline res 1 ' blank line in nco_sync units
hsync_fp res 1
hsync_tip res 1
hsync_bp res 1
nco_sync res 1
nco_main res 1 ' only for analog modes!
pixel_multiplier ' alias
nco_alt res 1 ' only for analog modes!
hsync_breeze res 1 ' NTSC/PAL only - subtracts from bp
hsync_guardband ' alias - HDMI only
hsync_burst res 1 ' NTSC/PAL only - subtracts from bp
timing_vars_end
' Color space variables
color_vars
dac_blanking res 1 ' DAC blanking values
blank_color res 1
hsync_color res 1
vsync_color res 1
hvsync_color res 1
burst_color res 1 ' NTSC/PAL only
burst_freq res 1 ' NTSC/PAL only
cy_val res 1
ci_val res 1
cq_val res 1
cq_xor res 1 ' NTSC/PAL only
color_vars_end
subline_incmod res 1
borderline res 1
hsync_bpshort res 1 ' NTSC/PAL: BP - (breeze+burst)
blankline_packets res 1 ' rest of blanking line after packets (HDMI only)
lines_left res 1 ' lines left in current section
scanptr res 1
vdp_mode res 1
bob_lines res 1
scantimecomp res 1 ' Time compensator for threaded scan conversion
subline res 1
virtual_line res 1
virtual_frame res 1
temp1 res 1
temp2 res 1
temp3 res 1
temp4 res 1
scantmp res 1
spleft res 1
spright res 1
' audio-related, all needs zero-ing before use
audio_clear_start
audio_hist res 4
audio_inbuffer res 4
audio_inbuf_level res 1
resample_ratio_frac res 1
resample_ratio_int res 1
resample_antidrift_period res 1
resample_phase_frac res 1
resample_phase_int res 1
resample_antidrift_phase res 1
spdif_phase res 1
hdmi_regen_counter res 1
audio_clear_end
hdmi_regen_period res 1
' Unrelated TERC4-related nonsense
serbyte res 1
u1 ' alias for resampler
serch0 res 1
u2 ' alias for resampler
serch1 res 1
u3 ' alias for resampler
serch2 res 1
' Byte 0 is HSync flag(00/FF), Byte 1 is VSync(00/FF), Byte 2 is Island start bit (FF/FE) - must match the timeslot the packet will be sent in
packet_extra res 1 ' can't be in overlay because common code writes it
fit $0B0
org $0B0
video_ovl_area
DAT ' LUT resident code
' 200 to 2FF is reserved for palette (not used here)
' 300 to 35F is used as buffer space (3 encoded HDMI packets fit)
' so code starts at 360, space for 160 instructions
org $300
packet_aviinfo res 32
packet_audio res 32
packet_aclk res 32
packet_aclk_v res 32
fit $380
org $380
video_lut_code
video_entry
'xinit blankline,blank_color
frame_loop
'debug(udec(virtual_frame),uhex_long(linecmd,extra_pillar,hsync_fp,hsync_tip,hsync_bp,nco_sync,nco_main))
neg virtual_line,#32-VDPR_OFFSET ' TODO: Magic number
mov subline,subline_incmod
mov lines_left,fp_lines
.front_porch
call vbi_hsync_func
cmp lines_left,#1 wz
if_z setbyte packet_extra,#$FF,#1 ' Last line of FP builds packet for 1st line of Sync
call blankline_func
djnz lines_left,#.front_porch
mov lines_left,sync_lines
.vsync
cmp lines_left,#1 wz
if_z setbyte packet_extra,#$00,#1 ' Last line of Sync builds packet for 1st line of BP
call vsync_func
djnz lines_left,#.vsync
mov lines_left,bp_lines
.back_porch
call vbi_hsync_func
call blankline_func
djnz lines_left,#.back_porch
rdlong vdp_mode,vdpmode_ptr ' read VDP mode here, once.
neg virtual_line,#BORDER_TOP - VDPR_OFFSET ' TODO SHOULD FLE INSTEAD
mov subline,#0
mov lines_left,#BORDER_TOP
mul lines_left,line_multiplier
' Bob interlace for line2x modes
testb vdp_mode,#VDPBIT_INTERLACE wc
testbn virtual_frame,#0 andc
if_c add lines_left,bob_lines
if_c sub subline,bob_lines
.top_border
call hsync_func
call borderline_func
djnz lines_left,#.top_border
mov lines_left,#HEIGHT
mul lines_left,line_multiplier
mov scanptr,scanbuffer_base
add virtual_frame,#1
.visible
call hsync_func
rdfast bit31,scanptr ' fire up FIFO
cmp subline,#0 wz
if_z add scanptr,scanbuffer_stride
cmp scanptr,scanbuffer_wrap wc
if_ae mov scanptr,scanbuffer_base
testb vdp_mode,#VDPBIT_ALTRES wc
if VDP_INVERT_ALTRES
if_c mov pa,line_func
if_nc mov pa,altline_func
else
if_nc mov pa,line_func
if_c mov pa,altline_func
end
call pa
'call borderline_func
djnz lines_left,#.visible
mov lines_left,#BORDER_BOTTOM
mul lines_left,line_multiplier
' Bob interlace for line2x modes
testb vdp_mode,#VDPBIT_INTERLACE wc
testb virtual_frame,#0 andc ' got incremented inbetween
if_c sub lines_left,bob_lines
.bottom_border
call hsync_func
call borderline_func
djnz lines_left,#.bottom_border
jmp #frame_loop
vline_update ' update line count to client and scanptr
setq #1
wrlong virtual_line,linectr_ptr
incmod subline,subline_incmod wc
if_c add virtual_line,#1
ret
line_native ' native scanline
cmp extra_pillar,#0 wz
if_nz xcont extra_pillar,border_color
setq nco_main
xcont linecmd,#0 ' No color needed for DMA
if_nz setq nco_sync
if_nz xcont extra_pillar,border_color
setq nco_sync
_ret_ xcont hsync_fp,blank_color
line_native_altnco ' alt-res scanline with NCO switch
cmp extra_pillar,#0 wz
if_nz xcont extra_pillar,border_color
setq nco_alt
xcont linecmd_alt,#0 ' No color needed for DMA
if_nz setq nco_sync
if_nz xcont extra_pillar,border_color
setq nco_sync
_ret_ xcont hsync_fp,blank_color
line_native_altpillar ' alt-res scanline with pillarbox
cmp extra_pillar,#0 wz
if_nz xcont extra_pillar,border_color
setq nco_main
xcont altres_pillar,border_color
xcont linecmd_alt,#0 ' No color needed for DMA
xcont altres_pillar,border_color
if_nz setq nco_sync
if_nz xcont extra_pillar,border_color
setq nco_sync
_ret_ xcont hsync_fp,blank_color
fp_audio_pollloop ' this will poll audio unitl the front porch begins
xcont hsync_fp,blank_color
audio_pollloop
call audio_poll_func
_ret_ jnxmt #audio_pollloop
line_border ' border line
setq nco_sync
xcont borderline,border_color
mov scanfunc,#dummy_func
call scantask
jmp #fp_audio_pollloop
line_blank ' blanking line
setq nco_sync
xcont blankline,blank_color
mov scanfunc,#dummy_func
call scantask
jmp #fp_audio_pollloop
hsync_normal
setq nco_sync
xzero hsync_tip,hsync_color ' when this latches, FP is beginning
tjs vsync_pin,#.no_v
drvh vsync_pin ' should only be 4 cycles late
.no_v xcont hsync_bp,blank_color
jmp #vline_update
vsync_normal ' Vsync line including sync etc
setq nco_sync
xzero hsync_tip,hvsync_color ' when this latches, FP is beginning
tjs vsync_pin,#.no_v
drvl vsync_pin ' should only be 4 cycles late
.no_v xcont hsync_bp,vsync_color
call #vline_update ' update client on time
xcont blankline,vsync_color
_ret_ xcont hsync_fp,vsync_color
fit $400
DAT ' HDMI overlay code
org video_ovl_area
hdmi_overlay
' TERC4 encoder table
' bit 0 on ch0 is HSync, so VGA sync bit is set to match
terctable long TERC_0 * $401004 + %10
long TERC_1 * $401004 + %11
long TERC_2 * $401004 + %10
long TERC_3 * $401004 + %11
long TERC_4 * $401004 + %10
long TERC_5 * $401004 + %11
long TERC_6 * $401004 + %10
long TERC_7 * $401004 + %11
long TERC_8 * $401004 + %10
long TERC_9 * $401004 + %11
long TERC_A * $401004 + %10
long TERC_B * $401004 + %11
long TERC_C * $401004 + %10
long TERC_D * $401004 + %11
long TERC_E * $401004 + %10
long TERC_F * $401004 + %11
tmds_ch1_mask long $3FF << 12
tmds_ch2_mask long $3FF << 22
spdif_parity_mask long $7_FFFFFF
'' HDMI-related small functions
'island_tx_h
'mov pa,##TMDS_GUARDDAT_H
island_tx
' guard character in PA, length in PB, data at PTRA
xcont hsync_guardband,pa
rep @.loop,pb ' PB is latched, we can clobber it
rdlut pb,ptra++
xcont bitbangcmd,pb
.loop
_ret_ xcont hsync_guardband,pa
audio_island_tx_hv
mov pa,##TMDS_GUARDDAT_HV
mov temp1,hvsync_color
loc ptrb,#\packet_aclk_v
jmp #audio_island_tx
audio_island_tx_h
mov pa,##TMDS_GUARDDAT_H
mov temp1,hsync_color
loc ptrb,#\packet_aclk
audio_island_tx
cmpsub hdmi_regen_counter,hdmi_regen_period wc
if_nc xcont packetblank,temp1
loc ptra,#\packet_audio
xcont hsync_guardband,pa
rep @.loop,#32
rdlut pb,ptra++
xcont bitbangcmd,pb
.loop
if_nc jmp #.no2nd
rep @.loop2,#32
rdlut pb,ptrb++
xcont bitbangcmd,pb
.loop2
.no2nd
_ret_ xcont hsync_guardband,pa
hsync_hdmi_vbi ' Hsync during V blanking
call audio_poll_func
xzero hsync_tip,hsync_color ' this is the data preamble
tjs vsync_pin,#.no_v
drvh vsync_pin ' should only be 4 cycles late
.no_v
call #audio_island_tx_h
xcont hsync_bp,blank_color
call audio_poll_func
jmp #vline_update
hsync_hdmi_previd ' Hsync during active video
call audio_poll_func
xzero hsync_tip,hsync_color
call #audio_island_tx_h
xcont hsync_bpshort,##TMDS_PREVID
call audio_poll_func
xcont hsync_guardband,##TMDS_GUARDVID ' take note that this is a mere 20 cycles
jmp #vline_update
vsync_hdmi
call audio_poll_func
xzero hsync_tip,hvsync_color
tjs vsync_pin,#.no_v
drvl vsync_pin ' should only be 4 cycles late
.no_v
call #audio_island_tx_hv
cmp lines_left,sync_lines wz
if_nz jmp #.no_infopkt
' send extra data on first line of Vsync (arbitrary convenient time)
xcont hsync_bp,##TMDS_PREDAT_V ' Preamble in backporch
call audio_poll_func
call #vline_update ' update client on time
mov pb,#INFO_PACKETS*32
loc ptra,#\packet_aviinfo
callpa ##TMDS_GUARDDAT_V,#island_tx
xcont blankline_packets,vsync_color ' Shortened
.vsyn_task mov scanfunc,#dummy_func
call scantask
call audio_poll_func
xcont hsync_fp,vsync_color
jmp #audio_pollloop
.no_infopkt
xcont hsync_bp,vsync_color
call #vline_update ' update client on time
xcont blankline,vsync_color
jmp #.vsyn_task
'' Packet-related functions
build_audio
'debug("Welcome to build_audio la-la-land")
call scanfunc
call audio_poll_func
sub scantimecomp,#2
call scanfunc
mov packet_header,#$02
loc ptrb,#\packet_audio ' Where we will put thy hallowed packet
mov temp3,#0
.sploop
tjz resample_phase_int,#.dosp
.feed
tjz audio_inbuf_level,#.spdone
sub scantimecomp,#2 ' feed loop
call scanfunc
mov audio_hist+0,audio_hist+1
mov audio_hist+1,audio_hist+2
mov audio_hist+2,audio_hist+3
mov audio_hist+3,audio_inbuffer+0
mov audio_inbuffer+0,audio_inbuffer+1
mov audio_inbuffer+1,audio_inbuffer+2
mov audio_inbuffer+2,audio_inbuffer+3
sub audio_inbuf_level,#1
call scanfunc
djnz resample_phase_int,#.feed ' always fall through if ratio < 2
.dosp ' Create an output sample using cubic resampling
sub scantimecomp,#6+6 ' dosp (cubic)
call scanfunc
getword u1,resample_phase_frac,#1
mov u2,u1
mul u2,u1
shr u2,#16
mov u3,u2
mul u3,u1
shr u3,#16
call scanfunc
mov temp1,u3
sub temp1,u2
sub temp1,u2
add temp1,u1
sar temp1,#2
getword temp4,audio_hist+0,#1
muls temp4,temp1
neg spleft,temp4
muls temp1,audio_hist+0 ' muls ignores upper half
neg spright,temp1
call scanfunc
mov temp1,u3
mul temp1,#3
mov temp2,u2
mul temp2,#5
subr temp1,temp2
mov temp2,temp1 ' +u2*5 -u3*3 (for later)
sub temp1,##$20000
sar temp1,#2
getword temp4,audio_hist+1,#1
muls temp4,temp1
sub spleft,temp4
call scanfunc
muls temp1,audio_hist+1 ' muls ignores upper half
sub spright,temp1
neg temp1,temp2 ' -u2*5 +u3*3
add temp1,u2
sub temp1,u1
sar temp1,#2
getword temp4,audio_hist+2,#1
muls temp4,temp1
sub spleft,temp4
muls temp1,audio_hist+2 ' muls ignores upper half
sub spright,temp1
call scanfunc
neg temp1,u3
add temp1,u2
sar temp1,#2
getword temp4,audio_hist+3,#1
muls temp4,temp1
sub spleft,temp4
muls temp1,audio_hist+3 ' muls ignores upper half
sub spright,temp1
call scanfunc
fges spleft,min31
fles spleft,max31
fges spright,min31
fles spright,max31
call scanfunc
shr spleft,#7
shr spright,#7
zerox spleft,#23
zerox spright,#23