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