Home | History | Annotate | Line # | Download | only in xplx
      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