xplx.asm revision 1.1 1 ;
2 ; Copyright (c) 2018 Yosuke Sugahara. All rights reserved.
3 ;
4 ; Redistribution and use in source and binary forms, with or without
5 ; modification, are permitted provided that the following conditions
6 ; are met:
7 ; 1. Redistributions of source code must retain the above copyright
8 ; notice, this list of conditions and the following disclaimer.
9 ; 2. Redistributions in binary form must reproduce the above copyright
10 ; notice, this list of conditions and the following disclaimer in the
11 ; documentation and/or other materials provided with the distribution.
12 ;
13 ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 ; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
20 ; AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 ; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 ; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 ; SUCH DAMAGE.
24 ;
25 ;
26 ; LUNA XP multiplexed device firmware
27 ;
28 ; used language:
29 ; zasm 4.1
30 ; http://k1.spdns.de/Develop/Projects/zasm
31 ;
32 ; XP memory map
33 ;
34 ; type : SH, PR, IN, NC
35 ; SH: host shared memory, 64kB, PA 00000 - 0FFFF
36 ; PR: private memory, 32kB, PA 28000-2FFFF
37 ; IN: HD647180 internal 512 bytes memory
38 ; NC: not connected (00 or FF or image readable, maybe)
39 ;
40 ; start end type desc
41 ; 0000 00FF SH RESET/RST etc.
42 ; 0100 01FF SH shared variables
43 ; 0200 0FFF SH resident program
44 ; 1000 7FFF SH PAM/PCM buffer 28K
45 ; 8000 8FFF SH PSG buffer 4K
46 ; 9000 9FFF SH LPR buffer 4K
47 ; A000 DFFF SH FDC buffer 16K
48 ; E000 EFFF PR program/stack
49 ; F000 FDFF NC bus error (00 or FF)
50 ; FE00 FFDF IN PAM player
51 ; FFE0 FFFF IN interrupt vector
52 ;
53 ; shared variable area
54 ; 0100 XPBUS
55 ; 0110 TIME
56 ; 0120 PAM
57 ; 0130 PCM
58 ; 0140 PSG
59 ; 0150 SPK
60 ; 0160 LPR
61 ; 0170 FDC
62 ; 0180 SIO0
63 ; 0190 SIO1
64 ; device ID = bit 7-4
65 ;
66 ; XP internal device usage
67 ; PRT0 device dispatcher/TIME
68 ; PRT1 PCM
69 ; PT2 unused
70 ; ASCI0 SIO0
71 ; ASCI1 SIO1 ?
72 ;
73 ; READY-CMD-RESULT-RUN
74 ; XP
75 ; READY
76 ; != 0
77 ; 0
78 ; CMD
79 ;
80 ; 0
81 ; XP READY=0 CMD=0 XP 0
82 ; RESULT
83 ;
84 ; RESULT=x READY=1
85 ; 0
86 ; RUN
87 ; != 0
88 ; 0
89 ; RESULT=x RUN=0 READY=1
90 ;
91 ;
92 ; READY
93 ; CMD
94 ; READY
95 ; RUN
96 ; CMD
97 ;
98 ; RESULT
99 ; RUN
100 ; READY
101 ;
102 ;
103 ;
104 ; while (READY == 0); //
105 ; RESULT=0; //
106 ; CMD=x; //
107 ; while (RESULT == 0); //
108 ; if (RESULT==ERROR) error(); //
109 ;
110
111 ;
112 ; XPBUS
113 ; +0.b READY
114 ; +1.b CMD
115 ; +2.b RESULT
116 ; +3.b RUN
117 ;
118 ; +4.b STAT_RESET
119 ; 0
120 ; +1
121 ; 1
122 ; +5.3 align
123 ; +8.w PRT0_TIMER
124 ; ==256(1200Hz)
125 ; +A.w INTR1_DEV
126 ; bitmap of INTR1 device ID
127 ; +C.w INTR5_DEV
128 ; bitmap of INTR5 device ID
129 ;
130 ; TIME
131 ; +0.b READY
132 ; +1.b CMD
133 ; +2.b RESULT
134 ; +3.b RUN
135 ;
136 ; +4.w TIMECOUNTER
137 ;
138 ; PAM
139 ; +0.b READY
140 ; +1.b CMD
141 ; +2.b RESULT
142 ; +3.b RUN
143 ;
144 ; +4.b ENC
145 ;
146 ; +5.b REPT
147 ; REPT
148 ; +6.w CYCLE_CLK
149 ;
150 ;
151 ; +8.b REPT_CLK
152 ; 1 REPT
153 ;
154 ; +9.b REPT_MAX
155 ; REPT
156 ;
157 ;
158 ; +E.w STAT_PTR
159 ;
160 ; PCM
161 ; +0.b READY
162 ; +1.b CMD
163 ; +2.b RESULT
164 ; +3.b RUN
165 ; +4.b ENC
166 ; +6.w PRT1_TIMER
167 ; PCM >=10(30.72kHz,200clk)
168 ;
169 ; +E.w STAT_PTR
170 ;
171 ; PSG
172 ; +0.b READY
173 ; +1.b CMD
174 ; +2.b RESULT
175 ; +3.b RUN
176 ;
177 ; SPK
178 ; +0.b READY
179 ; +1.b CMD
180 ; +2.b RESULT
181 ; +3.b RUN
182 ;
183 ; +4.b VOL
184 ; PSG
185 ; +6.w FREQ
186 ; PSG FREQ
187 ; +8.w TIME
188 ; 1200Hz
189 ; +A.w REMAIN
190 ;
191 ;
192 ; LPR
193 ; TBD.
194 ; FDC
195 ; TBD.
196 ;
197 ; SIO0
198 ; +0.b READY
199 ; +1.b CMD
200 ; +2.b RESULT
201 ; +3.b RUN
202 ; ;
203 ; ;
204 ; +4.b TXCMD
205 ; +5.b TXSTAT
206 ; +6.b TX
207 ; +A.b RXCMD
208 ; +B.b RXSTAT
209 ; +C.b RX
210 ;
211 ; SIO1
212 ; +0.b READY
213 ; +1.b CMD
214 ; +2.b RESULT
215 ; +3.b RUN
216 ; ;
217 ; ;
218 ; +4.b TXCMD
219 ; +5.b TXSTAT
220 ; +6.b TX
221 ; +A.b RXCMD
222 ; +B.b RXSTAT
223 ; +C.b RX
224
225 .Z180
226
227 ; ######## device ID
228
229 #define DEVID_XPBUS 0
230 #define DEVID_TIME 1
231 #define DEVID_PAM 2
232 #define DEVID_PCM 3
233 #define DEVID_PSG 4
234 #define DEVID_SPK 5
235 #define DEVID_LPR 6
236 #define DEVID_FDC 7
237 #define DEVID_SIO0 8
238 #define DEVID_SIO1 9
239 ; ######## define
240
241 #define PAM_CMD_START 1
242 #define PAM_CMD_QUERY 2
243
244 #define PAM_ENC_PAM2A 1
245 #define PAM_ENC_PAM2B 2
246 #define PAM_ENC_PAM3A 3
247 #define PAM_ENC_PAM3B 4
248 #define PAM_ENC_PAM1P 5
249
250 #define PCM_CMD_START 1
251
252 #define PCM_ENC_PCM1 1
253 #define PCM_ENC_PCM2 2
254 #define PCM_ENC_PCM3 3
255
256 #define SPK_CMD_START 1
257 #define SPK_CMD_STOP 2
258 #define SPK_CMD_KEEP 3
259
260
261 ; #### RESULT
262 #define XPLX_R_OK 1
263 #define XPLX_R_ERROR_PARAM 254
264 #define XPLX_R_UNKNOWN_CMD 255
265
266
267 ; ######## switch
268 ; 0 = USE STAT_PTR for userland test mode
269 ; 1 = USE HOSTINTR for kernel (normal)
270 #define USE_INTR 1
271
272 ; ######## constants
273 ; xp to host level 1 interrupt port
274 HOSTINTR1 .EQU 0B0H
275 ; xp to host level 5 interrupt port
276 HOSTINTR5 .EQU 0A0H
277
278 ; PAM use HOSTINTR5
279 PAM_HOSTINTR .EQU HOSTINTR5
280 ; PCM use HOSTINTR5
281 PCM_HOSTINTR .EQU HOSTINTR5
282
283 ; I/O PORT
284 TMDR0L .EQU 0CH
285 TMDR0H .EQU 0DH
286 RLDR0L .EQU 0EH
287 RLDR0H .EQU 0FH
288 TCR .EQU 10H
289 TMDR1L .EQU 14H
290 TMDR1H .EQU 15H
291 RLDR1L .EQU 16H
292 RLDR1H .EQU 17H
293
294 PSG_ADR .EQU 83H ; PSG address (out)
295 PSG_DAT .EQU 82H ; data output
296 PSG_IN .EQU 83H ; data input (in)
297
298 INITIAL_SP: .EQU 01000H
299 PRIVATE_SP: .EQU 0F000H
300
301 ; ######## macros
302
303 ADD_HL_A: .MACRO
304 ADD A,L
305 LD L,A
306 JR NC,$ + 3
307 INC H
308 .ENDM
309
310 WAIT3 .MACRO
311 NOP
312 .ENDM
313
314 WAIT4 .MACRO
315 LD A,A
316 .ENDM
317
318 WAIT6 .MACRO
319 NOP
320 NOP
321 .ENDM
322
323 WAIT7 .MACRO
324 LD A,A ; 4+3=7
325 NOP
326 .ENDM
327
328 WAIT8 .MACRO
329 LD A,A ; 4*2=8
330 LD A,A
331 .ENDM
332
333 WAIT9 .MACRO
334 NOP ; 3*3=9
335 NOP
336 NOP
337 .ENDM
338
339 WAIT10 .MACRO
340 LD A,A ; 4+3*2=10
341 NOP
342 NOP
343 .ENDM
344
345 WAIT11 .MACRO
346 LD A,A ; 4*2+3=11
347 LD A,A
348 NOP
349 .ENDM
350
351 WAIT12 .MACRO
352 LD A,A ; 4*3=12
353 LD A,A
354 LD A,A
355 .ENDM
356
357 WAIT13 .MACRO
358 LD A,A ; 4+3*3=13
359 NOP
360 NOP
361 NOP
362 .ENDM
363
364 WAIT16 .MACRO
365 LD A,A
366 LD A,A
367 LD A,A
368 LD A,A
369 .ENDM
370
371 WAIT17 .MACRO
372 LD A,A ; 4*2+3*3=17
373 LD A,A
374 NOP
375 NOP
376 NOP
377 .ENDM
378
379 WAIT19 .MACRO
380 LD A,A ; 4*4+3=19
381 LD A,A
382 LD A,A
383 LD A,A
384 NOP
385 .ENDM
386
387 ; ######## RESET/RST
388 .ORG 0000H
389 RESET:
390 JP ENTRY
391
392 .ORG 0038H
393 INT0:
394 JP INTR_INT0
395
396 .ORG 0066H
397 NMI:
398 RETN
399
400 .ORG 0080H
401 DEBUG0:: .DB 0
402 DEBUG1:: .DB 0
403 DEBUG2:: .DB 0
404 DEBUG3:: .DB 0
405 DEBUG4:: .DB 0
406 DEBUG5:: .DB 0
407 DEBUG6:: .DB 0
408 DEBUG7:: .DB 0
409 DEBUG8:: .DB 0
410 DEBUG9:: .DB 0
411 DEBUG10:: .DB 0
412
413 .ORG 00FCH
414 XPLX_MAGIC:: ; MAGIC
415 .DB "XPLX"
416
417 ; ######## shared variables
418 ; XPBUS
419 .ORG 0100H
420 XPLX_VAR_BASE::
421 XPBUS_READY::
422 .DB 0
423 XPBUS_CMD::
424 .DB 0
425 XPBUS_RESULT::
426 .DB 0
427 XPBUS_RUN::
428 .DB 0
429
430 XPBUS_STAT_RESET:: ; reset count
431 .DB 0
432 .DB 0,0,0 ; reserved
433
434 XPBUS_PRT0_TIMER:: ; PRT0 TIMER TLDR (devices dispatch)
435 .DW 256
436 XPBUS_INTR1_DEV:: ; HOSTINTR1 device
437 .DW 0
438 XPBUS_INTR5_DEV:: ; HOSTINTR5 device
439 .DW 0
440
441 ; TIME
442 .ORG 0110H
443 TIME_READY::
444 .DB 0
445 TIME_CMD::
446 .DB 0
447 TIME_RESULT::
448 .DB 0
449 TIME_RUN::
450 .DB 0
451 TIME_TIMECOUNTER:: ; timecounter (TBD.)
452 .DW 0
453
454 ; PAM
455 .ORG 0120H
456 PAM_READY::
457 .DB 0
458 PAM_CMD::
459 .DB 0
460 PAM_RESULT::
461 .DB 0
462 PAM_RUN::
463 .DB 0
464
465 PAM_ENC::
466 .DB 0
467 PAM_REPT::
468 .DB 0
469 PAM_CYCLE_CLK::
470 .DW 0
471 PAM_REPT_CLK::
472 .DB 0
473 PAM_REPT_MAX::
474 .DB 0
475
476 .DB 0,0,0,0 ; reserved
477 PAM_STAT_PTR::
478 .DW 0
479
480 ; PCM
481 .ORG 0130H
482 PCM_READY::
483 .DB 0
484 PCM_CMD::
485 .DB 0
486 PCM_RESULT::
487 .DB 0
488 PCM_RUN::
489 .DB 0
490
491 PCM_ENC::
492 .DB 0
493 .DB 0 ; reserved
494 PCM_PRT1_TIMER:: ; PRT1 TIMER TLDR (PCM)
495 .DW 0
496
497 .DB 0,0,0,0,0,0 ; reserved
498 PCM_STAT_PTR::
499 .DW 0
500
501 ; PSG
502 .ORG 0140H
503 PSG_READY::
504 .DB 0
505 PSG_CMD::
506 .DB 0
507 PSG_RESULT::
508 .DB 0
509 PSG_RUN::
510 .DB 0
511
512 ; SPK
513 .ORG 0150H
514 SPK_READY::
515 .DB 0
516 SPK_CMD::
517 .DB 0
518 SPK_RESULT::
519 .DB 0
520 SPK_RUN::
521 .DB 0
522
523 SPK_VOL::
524 .DB 0
525 .DB 0 ; reserved
526 SPK_FREQ::
527 .DW 0
528 SPK_TIME::
529 .DW 0
530 SPK_REMAIN::
531 .DW 0
532
533 ; LPR
534 .ORG 0160H
535 LPR_READY::
536 .DB 0
537 LPR_CMD::
538 .DB 0
539 LPR_RESULT::
540 .DB 0
541 LPR_RUN::
542 .DB 0
543 ; TBD.
544
545 LPR_CMD_START .EQU 1
546
547 ; FDC
548 .ORG 0170H
549 FDC_READY::
550 .DB 0
551 FDC_CMD::
552 .DB 0
553 FDC_RESULT::
554 .DB 0
555 FDC_RUN::
556 .DB 0
557 ; TBD.
558
559 FDC_CMD_START .EQU 1
560
561 ; SIO0
562 .ORG 0180H
563 SIO0_READY::
564 .DB 0
565 SIO0_CMD::
566 .DB 0
567 SIO0_RESULT::
568 .DB 0
569 SIO0_RUN::
570 .DB 0
571
572 SIO0_TXCMD::
573 .DB 0
574 SIO0_TXSTAT::
575 .DB 0
576 SIO0_TX::
577 .DB 0
578 .DS 3
579 SIO0_RXCMD::
580 .DB 0
581 SIO0_RXSTAT::
582 .DB 0
583 SIO0_RX::
584 .DB 0
585
586 ; SIO1
587 .ORG 0190H
588 SIO1_READY::
589 .DB 0
590 SIO1_CMD::
591 .DB 0
592 SIO1_RESULT::
593 .DB 0
594 SIO1_RUN::
595 .DB 0
596
597 SIO1_TXCMD::
598 .DB 0
599 SIO1_TXSTAT::
600 .DB 0
601 SIO1_TX::
602 .DB 0
603 .DS 3
604 SIO1_RXCMD::
605 .DB 0
606 SIO1_RXSTAT::
607 .DB 0
608 SIO1_RX::
609 .DB 0
610
611
612 ; ######## Bootstrap program
613 .ORG 0200H
614 ENTRY:
615 DI
616 LD SP,INITIAL_SP
617
618 ; inc reset count
619 LD HL, XPBUS_STAT_RESET
620 INC (HL)
621
622 ; initial devices
623 ; READY=0
624 XOR A
625 LD (XPBUS_READY),A
626 LD (TIME_READY),A
627 LD (PAM_READY),A
628 LD (PCM_READY),A
629 LD (PSG_READY),A
630 LD (SPK_READY),A
631 LD (LPR_READY),A
632 LD (FDC_READY),A
633 LD (SIO0_READY),A
634 LD (SIO1_READY),A
635
636 LD A,1
637 LD (DEBUG0),A
638
639 ; init XP internal devices
640 ; internal I/O address = 00H - 3FH
641 LD A,00H ; IOA7[7]=0 IOSTP[5]=0
642 ICR .EQU 3FH
643 OUT0 (ICR),A
644
645 ; memory wait = 0
646 ; I/O wait = 3
647 ; no DMA
648 LD A,20H ; MWI[76]=0 IWI[54]=2(3wait) DMS[32]=0 DIM[10]=0
649 DCNTL .EQU 32H
650 OUT0 (DCNTL),A
651 ; disable refresh
652 LD A,03H ; REFE[7]=0 REFW[6]=0 CYC[10]=3(80state)
653 RCR .EQU 36H
654 OUT0 (RCR),A
655
656 LD A,2
657 LD (DEBUG0),A
658
659 ; prepare memory map
660 ; MMU
661 CBR .EQU 38H
662 BBR .EQU 39H
663 CBAR .EQU 3AH
664 ; Common0: VA=0000H -> PA=00000H SH
665 ; Bank : VA=E000H -> PA=28000H PR
666 ; Common1: VA=F000H -> PA=FF000H IN
667 LD A,0FEH
668 OUT0 (CBAR),A
669 LD A,0F0H
670 OUT0 (CBR),A
671 LD A,1AH
672 OUT0 (BBR),A
673
674 LD A,3
675 LD (DEBUG0),A
676
677 ; internal RAM addressing
678 ; for no-wait access
679 ; PA=FxxxxH
680 ; PA=0xxxxH
681 ;
682 ; built-in RAM VA=FE00H PA=FFE00H
683 LD A,0F0H
684 RMCR .EQU 51H
685 OUT0 (RMCR),A
686 ; disable external interrupt
687 ; TODO: if use "Host to XP" interrupt, change here
688 LD A,00H ; TRAP[7]=0 ITE2[2]=0 ITE1[1]=0 ITE0[0]=0
689 ITC .EQU 34H
690 OUT0 (ITC),A
691 ; Interrupt Vector Low = E
692 ; I = FFH
693 ; Interrupt Vector Address = FFE0H
694 LD A,0E0H
695 IL .EQU 33H
696 OUT0 (IL),A
697 LD A,0FFH
698 LD I,A
699 ; interrupt mode 1
700 IM 1
701
702 LD A,4
703 LD (DEBUG0),A
704
705 CALL INIT_PSG
706
707 ; TODO
708 ; INIT FDC
709 ; INIT LPR
710 ; INIT SIO
711
712 ; INIT PRT0,1
713 ; TIE1[5]=TIE0[4]=0
714 ; TOC1[3]=TOC0[2]=0
715 ; TDE1[1]=TDE0[0]=0
716 LD A,00H
717 OUT0 (TCR),A
718 ; prepare PRT0
719 LD HL,(XPBUS_PRT0_TIMER)
720 OUT0 (RLDR0L),L
721 OUT0 (TMDR0L),L
722 OUT0 (RLDR0H),H
723 OUT0 (TMDR0H),H
724 ; TIE0, TID0 ON
725 ; TIE0[4]=1 TDE0[0]=1
726 LD A,11H
727 OUT0 (TCR),A
728
729 ; copy to private memory
730 LD HL,PROG_ORG
731 LD DE,PRIVATE_RAM
732 LD BC,PROG_ORG_LEN
733 LDIR
734 ; interrupt vector copy to internal memory
735 LD HL,VECTOR_ORG
736 LD DE,VECTOR
737 LD BC,VECTOR_ORG_LEN
738 LDIR
739
740 LD A,5
741 LD (DEBUG0),A
742 ; jump to XPBUS
743 JP XPBUS
744
745 ; initialize PSG registers
746 ; break all regs
747 INIT_PSG:
748 ; init PSG
749 ; PSG R0-R6 All 00H
750 LD A,0
751 LD B,7
752 LD C,PSG_DAT
753 LD D,0
754 PSG_CLEAR_06:
755 OUT (PSG_ADR),A
756 OUT (C),D
757 INC A
758 DJNZ PSG_CLEAR_06
759 ; PSG mixer
760 ; tone = off, noise = off
761 ; IOA, IOB = output
762 LD A,7
763 LD D,0FFH
764 OUT (PSG_ADR),A
765 OUT (C),D
766 ; PSG volume and envelope
767 ; PSG R8-R15 all 0
768 LD A,8
769 LD B,8
770 LD D,0
771 PSG_CLEAR_8F:
772 OUT (PSG_ADR),A
773 OUT (C),D
774 INC A
775 DJNZ PSG_CLEAR_8F
776 ; TODO: PSG I/O Port
777 RET
778
779 ; ######## buffers
780 .PHASE 1000H
781 PAM_BUF::
782 PCM_BUF::
783 .DEPHASE
784 .PHASE 08000H
785 PAM_BUF_LEN:: .EQU $-PAM_BUF
786 PCM_BUF_LEN:: .EQU $-PCM_BUF
787 PSG_BUF::
788 .DEPHASE
789 .PHASE 09000H
790 PSG_BUF_LEN:: .EQU $-PSG_BUF
791 LPR_BUF::
792 .DEPHASE
793 .PHASE 0A000H
794 LPR_BUF_LEN:: .EQU $-LPR_BUF
795 FDC_BUF::
796 .DEPHASE
797
798 ; ######## private memory program
799 .PHASE 0E000H
800 FDC_BUF_LEN:: .EQU $-FDC_BUF
801
802 PROG_ORG: .EQU $$
803 PRIVATE_RAM:
804
805 XPBUS:
806 LD A,6
807 LD (DEBUG0),A
808
809 LD SP,PRIVATE_SP
810
811 ; devices READY=1
812 LD A,1
813 LD (XPBUS_READY),A
814 LD (TIME_READY),A
815 LD (PAM_READY),A
816 LD (PCM_READY),A
817 LD (PSG_READY),A
818 LD (SPK_READY),A
819 LD (LPR_READY),A
820 LD (FDC_READY),A
821 LD (SIO0_READY),A
822 LD (SIO1_READY),A
823
824 ; wait for PRT0
825 EI
826 XPBUS_LOOP:
827 HALT
828 JR XPBUS_LOOP
829
830 INTR_PRT0:
831 ; #### Periodic devices
832 ; 1200Hz
833 ; DISPATCH
834 ; o. A
835 ; o. AF, HL
836 ; o. EI
837 ; o. EI
838 ; o. PCM
839 ; o. PAM 0.83 msec
840
841 PUSH AF
842 PUSH HL
843
844 LD A,7
845 LD (DEBUG0),A
846 ; reset PRT0 interrupt
847 IN0 F,(TCR)
848 IN0 F,(TMDR0L)
849 ; first EI, for PRT1
850 EI
851
852 TIMECOUNTER_INCR:
853 ; timecounter
854 LD HL,(TIME_TIMECOUNTER)
855 INC HL
856 LD (TIME_TIMECOUNTER),HL
857
858 ; #### XPBUS devices dispatcher
859
860 DEVICES_DISPATCH:
861 LD A,(XPBUS_CMD)
862 OR A
863 CALL NZ,XPBUS_DISPATCH
864
865 LD A,(PAM_CMD)
866 OR A
867 CALL NZ,PAM_DISPATCH
868
869 LD A,(PCM_CMD)
870 OR A
871 CALL NZ,PCM_DISPATCH
872
873 LD A,(PSG_CMD)
874 OR A
875 CALL NZ,PSG_DISPATCH
876
877 LD A,(SPK_CMD)
878 OR A
879 CALL NZ,SPK_DISPATCH
880
881 LD A,(LPR_CMD)
882 OR A
883 CALL NZ,LPR_DISPATCH
884
885 LD A,(FDC_CMD)
886 OR A
887 CALL NZ,FDC_DISPATCH
888
889 LD A,(SIO0_CMD)
890 OR A
891 CALL NZ,SIO0_DISPATCH
892
893 LD A,(SIO1_CMD)
894 OR A
895 CALL NZ,SIO1_DISPATCH
896
897 LD A,8
898 LD (DEBUG0),A
899
900 POP HL
901 POP AF
902 RETI
903
904 ; #### XPBUS
905
906 XPBUS_DISPATCH:
907 ; not implemented
908 XOR A
909 LD (XPBUS_CMD),A
910 LD A,XPLX_R_UNKNOWN_CMD
911 LD (XPBUS_RESULT),A
912 RET
913
914 ; #### TIME
915
916 TIME_DISPATCH:
917 ; not implemented
918 XOR A
919 LD (TIME_CMD),A
920 LD A,XPLX_R_UNKNOWN_CMD
921 LD (TIME_RESULT),A
922 RET
923
924 ; #### PAM
925
926 ; #### PCM driver core
927
928 ; PCM
929 ;
930
931 ; #### PCM play start
932 PCM_DISPATCH:
933 CP PCM_CMD_START
934 JR Z,PCM_START
935
936 LD A,XPLX_R_UNKNOWN_CMD
937 PCM_ERROR:
938 LD (PCM_RESULT),A
939 RET
940
941 PCM_START:
942 ; if READY==0 return
943 LD A,(PCM_READY)
944 OR A
945 RET Z
946 ; check ENC
947 LD A,(PCM_ENC)
948 DEC A
949 JR Z,PCM_START_OK ; PCM1 = 1
950 DEC A
951 JR Z,PCM_START_OK ; PCM2 = 2
952 DEC A
953 JR Z,PCM_START_OK ; PCM3 = 3
954
955 LD A,XPLX_R_ERROR_PARAM
956 JR PCM_ERROR
957
958 PCM_START_OK:
959 ; A = 0
960 LD (PCM_READY),A
961 LD (PCM_CMD),A
962
963
964 ; prepare vector
965 DI
966 ; set PRT1 vector
967 LD HL,PCM_INTR
968 LD (VEC_PRT1),HL
969 ; prepare register
970 EXX
971
972 CALL INIT_PSG
973
974 ; make interrupt handler
975 LD A,(PCM_ENC)
976 DEC A
977 JR Z,PCM_SET_PCM1
978 DEC A
979 JR Z,PCM_SET_PCM2
980 PCM_SET_PCM3:
981 LD HL,PCM3
982 JR PCM_SET
983 PCM_SET_PCM2:
984 LD HL,PCM2
985 JR PCM_SET
986 PCM_SET_PCM1:
987 LD HL,PCM1
988 PCM_SET:
989 LD (PCM_INTR_JMP),HL
990
991 LD HL,PCM_BUF
992 LD BC,0800H + PSG_ADR
993 LD DE,0709H
994
995 EXX
996
997 ; TIE1, TDE1 OFF
998 IN0 A,(TCR)
999 AND 0DDH ; TIE1[5]=0 TDE1[1]=0
1000 OUT0 (TCR),A
1001 ; prepare PRT1
1002 LD HL,(PCM_PRT1_TIMER)
1003 OUT0 (RLDR1L),L
1004 OUT0 (RLDR1H),H
1005 OUT0 (TMDR1L),L
1006 OUT0 (TMDR1H),H
1007 ; TIE1, TID1 ON
1008 OR 22H ; TIE1[5]=1 TDE1[5]=1
1009 OUT0 (TCR),A
1010
1011 EI
1012
1013 LD A,1
1014 LD (PCM_RUN),A
1015
1016 RET
1017
1018
1019
1020 ; #### PCM interrupt handler
1021
1022 PCM_INTR:
1023 ; PRT1 interrupt
1024 EX AF,AF
1025 EXX
1026 ; interrupt acknowledge
1027 ; reset PRT1 Interrupt
1028 IN0 F,(TCR)
1029 IN0 F,(TMDR1L)
1030
1031 ;
1032 PCM_INTR_JMP: .EQU $+1
1033 JP PCM1
1034
1035 PCM_INTR_NEXT:
1036 RLCA
1037 JR C,PCM_RELOAD
1038 ; inc ptr after reload check
1039 INC HL
1040 RLCA
1041 JR C,PCM_STAT
1042 RLCA
1043 JR NC,PCM_NORMAL
1044
1045 ; PCM RESET attention
1046 ; in: HL = EXIT address
1047 PCM_RESET:
1048 ; PRT1 intr stop
1049 IN0 A,(TCR)
1050 ; TIE1,TDE1 OFF
1051 AND 0DDH ; TIE1[5]=0 TDE1[1]=0
1052 OUT0 (TCR),A
1053 ; PLAY STOP
1054 XOR A
1055 LD (PCM_RUN),A
1056 LD A,XPLX_R_OK
1057 LD (PCM_RESULT),A
1058 LD (PCM_READY),A
1059
1060 JR PCM_EXIT
1061
1062 ; PCM common code
1063
1064 PCM_RELOAD:
1065 LD HL,PCM_BUF
1066 PCM_STAT:
1067 #if USE_INTR
1068 OUT (PCM_HOSTINTR),A
1069 #else
1070 LD (PCM_STAT_PTR),HL
1071 #endif
1072 PCM_NORMAL:
1073 PCM_EXIT:
1074 EXX
1075 EX AF,AF
1076 EI
1077 RETI
1078
1079 ; #### PCM core code
1080
1081 PCM1:
1082 ; PSG REG=8
1083 OUT (C),B
1084 ; read attention or CH0
1085 LD A,(HL)
1086 OUT (PSG_DAT),A
1087 JP PCM_INTR_NEXT
1088
1089 PCM2:
1090 LD D,(HL)
1091 INC HL
1092 LD A,(HL)
1093
1094 OUT (C),B
1095 OUT0 (PSG_DAT),D
1096 OUT (C),E
1097 OUT (PSG_DAT),A
1098 JP PCM_INTR_NEXT
1099
1100 PCM3:
1101 LD E,(HL)
1102 INC HL
1103 LD D,(HL)
1104 INC HL
1105 LD A,(HL)
1106
1107 PUSH HL
1108 LD HL,090AH
1109 OUT (C),B
1110 OUT0 (PSG_DAT),E
1111 OUT (C),H
1112 OUT0 (PSG_DAT),D
1113 OUT (C),L
1114 OUT (PSG_DAT),A
1115 POP HL
1116 JP PCM_INTR_NEXT
1117
1118 ; #### SPK
1119 SPK_DISPATCH:
1120 CP SPK_CMD_START
1121 JR Z,SPK_START
1122 CP SPK_CMD_STOP
1123 JR Z,SPK_STOP
1124 CP SPK_CMD_KEEP
1125 JR Z,SPK_KEEP
1126
1127 LD A,XPLX_R_UNKNOWN_CMD
1128 LD (SPK_RESULT),A
1129 RET
1130
1131 SPK_START:
1132 LD A,(SPK_READY)
1133 OR A
1134 RET Z
1135
1136 XOR A
1137 LD (SPK_READY),A
1138 ; next to CMD_KEEP
1139 LD A,SPK_CMD_KEEP
1140 LD (SPK_CMD),A
1141 LD A,1
1142 LD (SPK_RUN),A
1143
1144 ; set REMAIN
1145 LD HL,(SPK_TIME)
1146 LD (SPK_REMAIN),HL
1147
1148 DI
1149 ; PSG CH3 FREQ
1150 LD HL,(SPK_FREQ)
1151 LD A,4
1152 OUT0 (PSG_ADR),A
1153 OUT0 (PSG_DAT),L
1154 LD A,5
1155 OUT0 (PSG_ADR),A
1156 OUT0 (PSG_DAT),H
1157 ; PSG CH3 VOL
1158 LD A,10
1159 OUT (PSG_ADR),A
1160 LD A,(SPK_VOL)
1161 OUT (PSG_DAT),A
1162 ; save PSG R7
1163 LD A,7
1164 OUT0 (PSG_ADR),A
1165 IN A,(PSG_IN)
1166 LD (SPK_PSGR7),A
1167 ; PSG CH3 TONE ON
1168 AND 0FBH
1169 OUT (PSG_DAT),A
1170
1171 JR SPK_EXIT
1172
1173 SPK_STOP:
1174 LD A,(SPK_READY)
1175 OR A
1176 RET Z
1177
1178 SPK_STOP_CORE:
1179 XOR A
1180 LD (SPK_READY),A
1181 LD (SPK_CMD),A
1182
1183 DI
1184 ; restore PSG R7
1185 LD A,7
1186 OUT (PSG_ADR),A
1187 LD A,(SPK_PSGR7)
1188 OUT (PSG_DAT),A
1189 ; PSG CH3 VOL=0
1190 LD A,10
1191 OUT (PSG_ADR),A
1192 XOR A
1193 OUT (PSG_DAT),A
1194
1195 LD (SPK_RUN),A
1196
1197 JR SPK_EXIT
1198
1199 SPK_KEEP:
1200 ; REMAIN == 0, then stop
1201 LD HL,(SPK_REMAIN)
1202 LD A,H
1203 OR L
1204 JR Z,SPK_STOP_CORE
1205
1206 DEC HL
1207 LD (SPK_REMAIN),HL
1208
1209 SPK_EXIT:
1210 EI
1211 LD A,XPLX_R_OK
1212 LD (SPK_RESULT),A
1213 LD (SPK_READY),A
1214 RET
1215
1216 SPK_PSGR7:
1217 .DB 0
1218
1219 ; ######## PSG
1220 PSG_DISPATCH:
1221 ; not implemented
1222 XOR A
1223 LD (PSG_CMD),A
1224 LD A,XPLX_R_UNKNOWN_CMD
1225 LD (PSG_RESULT),A
1226 RET
1227 ; ######## LPR
1228 LPR_DISPATCH:
1229 ; not implemented
1230 XOR A
1231 LD (LPR_CMD),A
1232 LD A,XPLX_R_UNKNOWN_CMD
1233 LD (LPR_RESULT),A
1234 RET
1235 ; ######## FDC
1236 FDC_DISPATCH:
1237 ; not implemented
1238 XOR A
1239 LD (FDC_CMD),A
1240 LD A,XPLX_R_UNKNOWN_CMD
1241 LD (FDC_RESULT),A
1242 RET
1243
1244 ; ######## SIO
1245 SIO0_DISPATCH:
1246 ; not implemented
1247 XOR A
1248 LD (SIO0_CMD),A
1249 LD A,XPLX_R_UNKNOWN_CMD
1250 LD (SIO0_RESULT),A
1251 RET
1252
1253 SIO1_DISPATCH:
1254 ; not implemented
1255 XOR A
1256 LD (SIO1_CMD),A
1257 LD A,XPLX_R_UNKNOWN_CMD
1258 LD (SIO1_RESULT),A
1259 RET
1260
1261 INTR_INT0:
1262 INTR_ASCI0:
1263 INTR_ASCI1:
1264 ; TBD
1265 EI
1266 RETI
1267
1268 ; #### PAM play start
1269
1270 PAM_DISPATCH:
1271 CP PAM_CMD_START
1272 JR Z,PAM_START
1273 CP PAM_CMD_QUERY
1274 JR Z,PAM_QUERY
1275
1276 XOR A
1277 LD (PAM_CMD),A
1278 LD A,XPLX_R_UNKNOWN_CMD
1279 LD (PAM_RESULT),A
1280 RET
1281
1282 ; PAM ENC -> PAM Driver MAP address
1283 ; OUT: HL = MAP address
1284 ; if error, direct return to main routine
1285 PAM_ENC_MAP:
1286 LD A,(PAM_ENC)
1287 OR A
1288 JR Z,PAM_ERROR_ENC
1289 DEC A
1290
1291 CP PAM_DRIVER_MAP_LEN / 16 ; 16 bytes / entry
1292 JP NC,PAM_ERROR_ENC
1293
1294 ADD A,A ; A *= 16
1295 ADD A,A
1296 ADD A,A
1297 ADD A,A
1298
1299 LD HL,PAM_DRIVER_MAP
1300 ADD_HL_A
1301 RET
1302
1303 PAM_ERROR_ENC:
1304 POP HL ; discard caller PC
1305 PAM_ERROR_PARAM:
1306 LD A,XPLX_R_ERROR_PARAM
1307 LD (PAM_RESULT),A
1308 RET ; return to main
1309
1310 PAM_QUERY:
1311 CALL PAM_ENC_MAP ; get ENC to MAP
1312
1313 LD A,(PAM_READY)
1314 OR A
1315 RET Z
1316
1317 XOR A
1318 LD (PAM_READY),A
1319 LD (PAM_CMD),A
1320
1321 PUSH BC
1322 PUSH DE
1323
1324 LD BC,12 ; MAP offset 12 = CYCLE_CLK
1325 ADD HL,BC
1326
1327 ; CYCLE_CLK, REPT_CLK, REPT_MAX
1328 LD DE,PAM_CYCLE_CLK
1329 LD BC,4
1330 LDIR
1331
1332 POP DE
1333 POP BC
1334
1335 LD A,XPLX_R_OK
1336 LD (PAM_RESULT),A
1337 LD (PAM_READY),A
1338 RET
1339
1340
1341 PAM_START:
1342 CALL PAM_ENC_MAP ; get ENC to MAP
1343
1344 LD A,15
1345 ADD_HL_A ; HL points REPT_MAX
1346
1347 LD A,(PAM_REPT)
1348 CP (HL)
1349 JR Z,PAM_START_OK ; == OK
1350 JR C,PAM_START_OK ; < OK
1351 JR PAM_ERROR_PARAM
1352
1353 PAM_START_OK:
1354 LD A,(PAM_READY)
1355 OR A
1356 RET Z
1357
1358 XOR A
1359 LD (PAM_READY),A
1360 LD (PAM_CMD),A
1361
1362 ; never normal return
1363 ; PAM never EI
1364 DI
1365 CALL INIT_PSG
1366
1367 CALL PAM_ENC_MAP ; re- get ENC to MAP
1368
1369 ; copy to internal RAM
1370 LD DE,PAM_DRIVER
1371
1372 LD SP,HL ; SP = top of Map entry
1373 POP HL ; HEAD
1374 POP BC ; HEAD_LEN
1375 LDIR
1376
1377 LD A,(PAM_REPT)
1378 INC A ; DEC is not change CY
1379
1380
1381 PAM_REPT_LOOP:
1382 POP HL ; REPT
1383 POP BC ; REPT_LEN
1384
1385 DEC A ; DEC is not change CY
1386 JR Z,PAM_REPT_END
1387
1388 LDIR
1389
1390 DEC SP
1391 DEC SP
1392 DEC SP
1393 DEC SP
1394 JR PAM_REPT_LOOP
1395 PAM_REPT_END:
1396
1397 POP HL ; TAIL
1398 POP BC ; TAIL_LEN
1399 LDIR
1400
1401 ; buffer pointer
1402 LD HL,PAM_BUF
1403 #if USE_INTR
1404 #else
1405 LD (PAM_STAT_PTR),HL
1406 #endif
1407 ; prefetch
1408 LD SP,HL ; 4
1409 POP DE
1410
1411 ; I/O WAIT 3 -> 2
1412 ; PSG address / write 300ns
1413 ; 1.8432 clock 1 wait
1414 ; 2 wait out 12 clock
1415 ; POP 9+3=12 clock
1416 ; 2 wait
1417 ; PSG read 400ns 2 wait
1418 ; HOSTINTR I/O out wait
1419 ; HOSTINTR
1420 ;
1421 ;
1422 LD A,10H ; IWI[54]=1(2wait)
1423 OUT0 (DCNTL),A
1424
1425 LD A,1
1426 LD (PAM_RUN),A
1427
1428 LD A,8
1429 OUT (PSG_ADR),A
1430 LD C,PSG_DAT
1431
1432 JP PAM_DRIVER
1433
1434 PAM_RESET:
1435 ; XPBUS
1436 LD SP,PRIVATE_SP
1437
1438 ; I/O WAIT 2 -> 3
1439 LD A,20H ; IWI[54]=2(3wait)
1440 OUT0 (DCNTL),A
1441
1442 CALL INIT_PSG
1443
1444 XOR A
1445 LD (PAM_RUN),A
1446
1447 LD A,XPLX_R_OK
1448 LD (PAM_RESULT),A
1449 LD (PAM_READY),A
1450
1451 JP XPBUS
1452
1453 PAM_DRIVER_MAP:
1454 ; 16 bytes / entry
1455 DW PAM2A_HEAD_ORG
1456 DW PAM2A_HEAD_LEN
1457 DW PAM2A_REPT_ORG
1458 DW PAM2A_REPT_LEN
1459 DW PAM2A_TAIL_ORG
1460 DW PAM2A_TAIL_LEN
1461 DW 204 ;CYCLE_CLK
1462 DB 36 ;REPT_CLK
1463 DB 37 ;REPT_MAX
1464
1465 DW PAM2B_HEAD_ORG
1466 DW PAM2B_HEAD_LEN
1467 DW PAM2B_REPT_ORG
1468 DW PAM2B_REPT_LEN
1469 DW PAM2B_TAIL_ORG
1470 DW PAM2B_TAIL_LEN
1471 DW 152 ;CYCLE_CLK
1472 DB 24 ;REPT_CLK
1473 DB 57 ;REPT_MAX
1474
1475 DW PAM3A_HEAD_ORG
1476 DW PAM3A_HEAD_LEN
1477 DW PAM3A_REPT_ORG
1478 DW PAM3A_REPT_LEN
1479 DW PAM3A_TAIL_ORG
1480 DW PAM3A_TAIL_LEN
1481 DW 298 ;CYCLE_CLK
1482 DB 51 ;REPT_CLK
1483 DB 24 ;REPT_MAX
1484
1485 DW PAM3B_HEAD_ORG
1486 DW PAM3B_HEAD_LEN
1487 DW PAM3B_REPT_ORG
1488 DW PAM3B_REPT_LEN
1489 DW PAM3B_TAIL_ORG
1490 DW PAM3B_TAIL_LEN
1491 DW 136 ;CYCLE_CLK
1492 DB 36 ;REPT_CLK
1493 DB 38 ;REPT_MAX
1494
1495
1496
1497 PAM_DRIVER_MAP_LEN: .EQU $-PAM_DRIVER_MAP
1498
1499 .DEPHASE
1500
1501
1502
1503 ; ######## PAM drivers
1504 .PHASE 0FE00H
1505 ; all PAM drivers have same address=0FE00H
1506 PAM_DRIVER:
1507 .DEPHASE
1508
1509 ; #### PAM2A
1510
1511 .PHASE 0FE00H
1512 PAM2A_HEAD_ORG: .EQU $$
1513 PAM2A_HEAD:
1514 PAM2A:
1515 ; PAM2A
1516 ; 12+0:12+12 = 1:2 PAM
1517 ; PAM 36clk 170.667kHz
1518 ; output PAM wave = normal 5 + antinoise 1
1519
1520 ; 1 PAM cycle = 204 clk
1521
1522 ; 6.144E6 / (204 + 36*n)
1523
1524 ; sampling freqs:
1525 ; 0: 30118
1526 ; 37: 4000
1527
1528 ; no STAT for first time
1529 JP PAM2A_LOOP
1530
1531 PAM2A_RELOAD:
1532 OUT (C),E
1533 OUT (C),D
1534 LD SP,PAM_BUF ;9
1535 WAIT3
1536
1537 PAM2A_STAT:
1538 #if USE_INTR
1539 OUT (C),E
1540 OUT (C),D
1541 OUT (PAM_HOSTINTR),A ;10+2
1542 #else
1543 ; STAT_PTR
1544 OUT (C),E
1545 OUT (C),D
1546 LD (PAM_STAT_PTR),SP ;19+3
1547 #endif
1548
1549 PAM2A_NORMAL:
1550 OUT (C),E
1551 OUT (C),D
1552 ; prefetch
1553 POP DE ;9+3
1554
1555 OUT (C),L
1556 OUT (C),H
1557 ;
1558 ; wait 12 PAM
1559 ;
1560 PAM2A_LOOP:
1561 ; prefetched DE
1562 OUT (C),E
1563 OUT (C),D
1564 ; HL = DE for save current sample
1565 LD L,E ;4
1566 LD H,D ;4
1567 ; A = attention
1568 LD A,E ;4
1569
1570 PAM2A_HEAD_LEN: .EQU $-PAM2A_HEAD
1571
1572 PAM2A_REPT_ORG: .EQU $$
1573 PAM2A_REPT:
1574 OUT (C),E
1575 OUT (C),D
1576 WAIT12
1577 PAM2A_REPT_LEN: .EQU $-PAM2A_REPT
1578
1579 PAM2A_TAIL_ORG: .EQU $$
1580 PAM2A_TAIL:
1581 ;
1582 ; ""
1583 ; ""
1584 OUT (C),E
1585 OUT (C),D
1586 RLCA
1587 ; attention bit
1588 ; bit7=1, reload
1589 ; must be JP
1590 JP C,PAM2A_RELOAD ; jump=9 no=6
1591
1592 WAIT3
1593 OUT (C),E
1594 OUT (C),D
1595 RLCA ; 3
1596 ; bit6=1, stat
1597 ; must be JP
1598 JP C,PAM2A_STAT ; jump=9 no=6
1599
1600 WAIT3
1601 OUT (C),E
1602 OUT (C),D
1603 RLCA ; 3
1604 ; bit5=0, normal
1605 ; must be JP
1606 JP NC,PAM2A_NORMAL ; jump=9 no=6
1607 ; attention=001, reset
1608 JP PAM_RESET
1609 PAM2A_TAIL_LEN: .EQU $-PAM2A_TAIL
1610
1611 ; cycle
1612 ; 5 * (12*3) + 12*2 = 204
1613
1614 .DEPHASE
1615
1616 ; #### PAM2B
1617
1618 .PHASE 0FE00H
1619 ; all PAM drivers have same address=0FE00H
1620 PAM2B_HEAD_ORG: .EQU $$
1621 PAM2B_HEAD:
1622 PAM2B:
1623 ; PAM2B
1624 ; averaged 1:1 PAM
1625 ; wait (4,7), (3,9), (9,12), (12,0)
1626 ; phase wait 28:28
1627 ; clk 35, 36, 45, 36
1628 ; PAM 176, 171, 137, 171 kHz
1629 ; output PAM wave = 4
1630
1631 ; 1 PAM cycle = 152 clk
1632
1633 ; 6.144E6 / (152 + 24*n)
1634
1635 ; sampling freqs:
1636 ; 0: 40421
1637 ; 57: 4042
1638
1639 ; no STAT for first time
1640 JP PAM2B_LOOP
1641
1642 PAM2B_RELOAD:
1643 OUT (C),E
1644 LD SP,PAM_BUF ;9
1645
1646 PAM2B_STAT:
1647 #if USE_INTR
1648 OUT (C),D
1649 OUT (PAM_HOSTINTR),A ;10+2
1650 #else
1651 ; STAT_PTR
1652 OUT (C),D
1653 LD (PAM_STAT_PTR),SP ;19+3
1654 #endif
1655
1656 PAM2B_NORMAL:
1657 OUT (C),E
1658 ; prefetch
1659 POP DE ;9+3
1660 OUT (C),B
1661 PAM2B_LOOP:
1662 ; prefetched DE
1663 OUT (C),E
1664 ; A = attention
1665 LD A,E ;4
1666 OUT (C),D
1667 ; B = save D
1668 LD B,D ;4
1669 WAIT3
1670
1671 PAM2B_HEAD_LEN: .EQU $-PAM2B_HEAD
1672
1673 PAM2B_REPT_ORG: .EQU $$
1674 PAM2B_REPT:
1675 OUT (C),E
1676 OUT (C),D
1677 PAM2B_REPT_LEN: .EQU $-PAM2B_REPT
1678
1679 PAM2B_TAIL_ORG: .EQU $$
1680 PAM2B_TAIL:
1681 ;
1682 ; ""
1683 ; ""
1684 OUT (C),E
1685 RLCA ;3
1686 OUT (C),D
1687 ; attention bit
1688 ; bit7=1, reload
1689 ; must be JP
1690 JP C,PAM2B_RELOAD ; jump=9 no=6
1691
1692 RLCA ; 3
1693 OUT (C),E
1694 ; bit6=1, stat
1695 ; must be JP
1696 JP C,PAM2B_STAT ; jump=9 no=6
1697
1698 RLCA ; 3
1699 OUT (C),D
1700 WAIT3
1701 ; bit5=0, normal
1702 ; must be JP
1703 JP NC,PAM2B_NORMAL ; jump=9 no=6
1704 ; attention=001, reset
1705 JP PAM_RESET
1706 PAM2B_TAIL_LEN: .EQU $-PAM2B_TAIL
1707
1708 ; cycle
1709 ; 4 * 12*2 + (4+7 + 3+9 + 9+12 + 12+0) = 152
1710
1711 .DEPHASE
1712
1713 ; #### PAM3A
1714
1715 .PHASE 0FE00H
1716 PAM3A_HEAD_ORG: .EQU $$
1717 PAM3A_HEAD:
1718 PAM3A:
1719 ; PAM3A
1720 ; 12+0:12+3:12+12 = 4:5:8 PAM
1721 ; PAM 51clk 120.471kHz
1722 ; output PAM wave = normal 5 + antinoise 1
1723
1724 ; 1 PAM cycle = 298 clk
1725
1726 ; 6.144E6 / (298 + 51*n)
1727
1728 ; sampling freqs:
1729 ; 0: 20617
1730 ; 24: 4037
1731
1732 ; prefetch
1733 POP AF
1734 LD B,A
1735 ; no STAT for first time
1736 JP PAM3A_LOOP
1737
1738 PAM3A_RELOAD:
1739 OUT (C),L
1740 OUT (C),H
1741 WAIT3
1742 OUT (C),B
1743 LD SP,PAM_BUF ;9
1744 WAIT3
1745
1746 PAM3A_STAT:
1747 #if USE_INTR
1748 OUT (C),L
1749 OUT (C),H
1750 WAIT3
1751 OUT (C),B
1752 OUT (PAM_HOSTINTR),A ;10+2
1753 #else
1754 ; STAT_PTR
1755 OUT (C),L
1756 OUT (C),H
1757 WAIT3
1758 OUT (C),B
1759 LD (PAM_STAT_PTR),SP ;19+3
1760 #endif
1761
1762 PAM3A_NORMAL:
1763 OUT (C),L
1764 OUT (C),H
1765 WAIT3
1766 OUT (C),B
1767 ; prefetch
1768 POP DE ;9+3
1769
1770 OUT (C),L
1771 OUT (C),H
1772 WAIT3
1773 OUT (C),B
1774 ; prefetch
1775 POP AF ;9+3
1776
1777 OUT (C),L
1778 OUT (C),H
1779 WAIT3
1780 OUT (C),B
1781 ;
1782 ; wait 12 PAM
1783 ; 4clk
1784 LD B,A ;4
1785 PAM3A_LOOP:
1786 ; prefetched DE, A=B
1787
1788 PAM3A_HEAD_LEN: .EQU $-PAM3A_HEAD
1789
1790 PAM3A_REPT_ORG: .EQU $$
1791 PAM3A_REPT:
1792 OUT (C),E
1793 OUT (C),D
1794 WAIT3
1795 OUT (C),B
1796 WAIT12
1797 PAM3A_REPT_LEN: .EQU $-PAM3A_REPT
1798
1799 PAM3A_TAIL_ORG: .EQU $$
1800 PAM3A_TAIL:
1801 ;
1802 ; ""
1803 ; ""
1804 OUT (C),E
1805 OUT (C),D
1806 EX DE,HL ;3
1807 OUT (C),B
1808 RLCA
1809 ; attention bit
1810 ; bit7=1, reload
1811 ; must be JP
1812 JP C,PAM3A_RELOAD ; jump=9 no=6
1813
1814 WAIT3
1815 OUT (C),L
1816 OUT (C),H
1817 WAIT3
1818 OUT (C),B
1819 RLCA ; 3
1820 ; bit6=1, stat
1821 ; must be JP
1822 JP C,PAM3A_STAT ; jump=9 no=6
1823
1824 WAIT3
1825 OUT (C),L
1826 OUT (C),H
1827 WAIT3
1828 OUT (C),B
1829 RLCA ; 3
1830 ; bit5=0, normal
1831 ; must be JP
1832 JP NC,PAM3A_NORMAL ; jump=9 no=6
1833 ; attention=001, reset
1834 JP PAM_RESET
1835 PAM3A_TAIL_LEN: .EQU $-PAM3A_TAIL
1836
1837 ; cycle
1838 ; 5 * (12*3+3+12) + (12*3+3+4) = 298
1839
1840 .DEPHASE
1841
1842 ; #### PAM3B
1843
1844 .PHASE 0FE00H
1845 PAM3B_HEAD_ORG: .EQU $$
1846 PAM3B_HEAD:
1847 PAM3B:
1848 ; PAM3B
1849 ; approx 1:1:1
1850 ; wait (9,9,12), (12,12,10)
1851 ; phase wait 21:21:22
1852 ; clk 66, 70
1853 ; PAM 93, 88 kHz
1854 ; output PAM wave = 2
1855
1856 ; 1 PAM cycle = 136 clk
1857
1858 ; 6.144E6 / (136 + 36*n)
1859
1860 ; sampling freqs:
1861 ; 0: 45176
1862 ; 38: 4085
1863
1864 ; prefetch
1865 POP AF
1866 LD B,A
1867 RLCA
1868 ; no STAT for first time
1869 JP PAM3B_LOOP
1870
1871 PAM3B_RELOAD:
1872 OUT (C),D
1873 LD SP,PAM_BUF ;9
1874
1875 PAM3B_STAT:
1876 #if USE_INTR
1877 OUT (C),B
1878 OUT (PAM_HOSTINTR),A ;10+2
1879 #else
1880 ; STAT_PTR
1881 OUT (C),B
1882 LD (PAM_STAT_PTR),SP ;19+3
1883 #endif
1884
1885 PAM3B_NORMAL:
1886 OUT (C),E
1887 ; prefetch
1888 POP HL ;9+3
1889
1890 OUT (C),D
1891 ; prefetch
1892 POP AF ;9+3
1893
1894 OUT (C),B
1895 EX DE,HL ;3
1896 LD B,A ;4
1897 RLCA ;3
1898 PAM3B_LOOP:
1899 ; prefetched DE,B A=RLCA-ed flag
1900
1901 PAM3B_HEAD_LEN: .EQU $-PAM3B_HEAD
1902
1903 PAM3B_REPT_ORG: .EQU $$
1904 PAM3B_REPT:
1905 OUT (C),E
1906 OUT (C),D
1907 OUT (C),B
1908 PAM3B_REPT_LEN: .EQU $-PAM3B_REPT
1909
1910 PAM3B_TAIL_ORG: .EQU $$
1911 PAM3B_TAIL:
1912 ;
1913 ; ""
1914 ; ""
1915 OUT (C),E
1916 ; attention bit
1917 ; bit7=1, reload
1918 ; must be JP
1919 JP C,PAM3B_RELOAD ; jump=9 no=6
1920
1921 RLCA ; 3
1922 OUT (C),D
1923 ; bit6=1, stat
1924 ; must be JP
1925 JP C,PAM3B_STAT ; jump=9 no=6
1926
1927 RLCA ; 3
1928 OUT (C),B
1929 WAIT3
1930 ; bit5=0, normal
1931 ; must be JP
1932 JP NC,PAM3B_NORMAL ; jump=9 no=6
1933 ; attention=001, reset
1934 JP PAM_RESET
1935 PAM3B_TAIL_LEN: .EQU $-PAM3B_TAIL
1936
1937
1938 .DEPHASE
1939
1940 ; #### PAM1P
1941
1942 .PHASE 0FE00H
1943 PAM1P_HEAD_ORG: .EQU $$
1944 PAM1P_HEAD:
1945 PAM1P:
1946 ; PAM1P
1947 ; PAM1P PCM
1948 ; PAM
1949 ; Polyphase PCM
1950
1951 ; 1 cycle = 87 clk
1952 ; 6.144E6 / (87 + 3*n)
1953
1954 ; sampling freqs:
1955 ; 0: 70621
1956 ; 255: 7420
1957
1958 LD HL,PAM_BUF ;9
1959
1960 LD C,PSG_ADR
1961 ; initial CH0
1962 LD A,8
1963 OUT (PSG_ADR),A
1964 ; rotated next CH
1965 LD B,9
1966 LD DE,080AH
1967
1968 ; no STAT for first time
1969 JP PAM1P_LOOP
1970
1971 PAM1P_RELOAD:
1972 LD HL,PAM_BUF ;9
1973
1974 PAM1P_STAT:
1975 #if USE_INTR
1976 OUT (PAM_HOSTINTR),A ;10+2
1977 #else
1978 ; STAT_PTR
1979 LD (PAM_STAT_PTR),HL ;16+3
1980 #endif
1981
1982 PAM1P_NORMAL:
1983 ; rotate B,E,D
1984 LD A,B ;4
1985 LD B,E ;4
1986 LD E,D ;4
1987 LD D,A ;4
1988 OUT (C),B ;10+2
1989
1990 PAM1P_LOOP:
1991
1992 LD A,(HL) ;6+3
1993 INC HL ;4
1994
1995 OUT (PSG_DAT),A ;10+2
1996
1997 PAM1P_HEAD_LEN: .EQU $-PAM1P_HEAD
1998
1999 PAM1P_REPT_ORG: .EQU $$
2000 PAM1P_REPT:
2001 WAIT3
2002 PAM1P_REPT_LEN: .EQU $-PAM1P_REPT
2003
2004 PAM1P_TAIL_ORG: .EQU $$
2005 PAM1P_TAIL:
2006 ;
2007 ; ""
2008 ; ""
2009 RLCA ;3
2010 ; attention bit
2011 ; bit7=1, reload
2012 ; must be JP
2013 JP C,PAM1P_RELOAD ; jump=9 no=6
2014
2015 RLCA ; 3
2016 ; bit6=1, stat
2017 ; must be JP
2018 JP C,PAM1P_STAT ; jump=9 no=6
2019
2020 RLCA ; 3
2021 WAIT3
2022 ; bit5=0, normal
2023 ; must be JP
2024 JP NC,PAM1P_NORMAL ; jump=9 no=6
2025 ; attention=001, reset
2026 JP PAM_RESET
2027 PAM1P_TAIL_LEN: .EQU $-PAM1P_TAIL
2028
2029 ; cycle
2030 ; 63 + 12 + 12 = 87
2031
2032 .DEPHASE
2033
2034 PROG_ORG_LEN: .EQU $$-PROG_ORG
2035
2036 ; #### interrupt vector
2037 .PHASE 0FFE0H
2038 VECTOR_ORG: .EQU $$
2039 VECTOR:
2040
2041 VEC_INT1:
2042 DW INTR_IGN
2043 VEC_INT2:
2044 DW INTR_IGN
2045 VEC_PRT0:
2046 DW INTR_PRT0
2047 VEC_PRT1:
2048 DW INTR_IGN
2049 VEC_DMAC0:
2050 DW INTR_IGN
2051 VEC_DMAC1:
2052 DW INTR_IGN
2053 VEC_SIO:
2054 DW INTR_IGN
2055 VEC_ASCI0:
2056 DW INTR_ASCI0
2057 VEC_ASCI1:
2058 DW INTR_ASCI1
2059 VEC_PT2IN:
2060 DW INTR_IGN
2061 VEC_PT2OUT:
2062 DW INTR_IGN
2063 VEC_PT2OVF:
2064 DW INTR_IGN
2065 ;
2066 ;
2067 INTR_IGN:
2068 EI
2069 RETI
2070
2071 VECTOR_ORG_LEN: .EQU $$-VECTOR_ORG
2072
2073 .DEPHASE
2074 XPLX_FIRMWARE_LEN:: .EQU $
2075