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 274HOSTINTR1 .EQU 0B0H 275; xp to host level 5 interrupt port 276HOSTINTR5 .EQU 0A0H 277 278; PAM use HOSTINTR5 279PAM_HOSTINTR .EQU HOSTINTR5 280; PCM use HOSTINTR5 281PCM_HOSTINTR .EQU HOSTINTR5 282 283; I/O PORT 284TMDR0L .EQU 0CH 285TMDR0H .EQU 0DH 286RLDR0L .EQU 0EH 287RLDR0H .EQU 0FH 288TCR .EQU 10H 289TMDR1L .EQU 14H 290TMDR1H .EQU 15H 291RLDR1L .EQU 16H 292RLDR1H .EQU 17H 293 294PSG_ADR .EQU 83H ; PSG address (out) 295PSG_DAT .EQU 82H ; data output 296PSG_IN .EQU 83H ; data input (in) 297 298INITIAL_SP: .EQU 01000H 299PRIVATE_SP: .EQU 0F000H 300 301; ######## macros 302 303ADD_HL_A: .MACRO 304 ADD A,L 305 LD L,A 306 JR NC,$ + 3 307 INC H 308 .ENDM 309 310WAIT3 .MACRO 311 NOP 312 .ENDM 313 314WAIT4 .MACRO 315 LD A,A 316 .ENDM 317 318WAIT6 .MACRO 319 NOP 320 NOP 321 .ENDM 322 323WAIT7 .MACRO 324 LD A,A ; 4+3=7 325 NOP 326 .ENDM 327 328WAIT8 .MACRO 329 LD A,A ; 4*2=8 330 LD A,A 331 .ENDM 332 333WAIT9 .MACRO 334 NOP ; 3*3=9 335 NOP 336 NOP 337 .ENDM 338 339WAIT10 .MACRO 340 LD A,A ; 4+3*2=10 341 NOP 342 NOP 343 .ENDM 344 345WAIT11 .MACRO 346 LD A,A ; 4*2+3=11 347 LD A,A 348 NOP 349 .ENDM 350 351WAIT12 .MACRO 352 LD A,A ; 4*3=12 353 LD A,A 354 LD A,A 355 .ENDM 356 357WAIT13 .MACRO 358 LD A,A ; 4+3*3=13 359 NOP 360 NOP 361 NOP 362 .ENDM 363 364WAIT16 .MACRO 365 LD A,A 366 LD A,A 367 LD A,A 368 LD A,A 369 .ENDM 370 371WAIT17 .MACRO 372 LD A,A ; 4*2+3*3=17 373 LD A,A 374 NOP 375 NOP 376 NOP 377 .ENDM 378 379WAIT19 .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 389RESET: 390 JP ENTRY 391 392 .ORG 0038H 393INT0: 394 JP INTR_INT0 395 396 .ORG 0066H 397NMI: 398 RETN 399 400 .ORG 0080H 401DEBUG0:: .DB 0 402DEBUG1:: .DB 0 403DEBUG2:: .DB 0 404DEBUG3:: .DB 0 405DEBUG4:: .DB 0 406DEBUG5:: .DB 0 407DEBUG6:: .DB 0 408DEBUG7:: .DB 0 409DEBUG8:: .DB 0 410DEBUG9:: .DB 0 411DEBUG10:: .DB 0 412 413 .ORG 00FCH 414XPLX_MAGIC:: ; MAGIC 415 .DB "XPLX" 416 417; ######## shared variables 418; XPBUS 419 .ORG 0100H 420XPLX_VAR_BASE:: 421XPBUS_READY:: 422 .DB 0 423XPBUS_CMD:: 424 .DB 0 425XPBUS_RESULT:: 426 .DB 0 427XPBUS_RUN:: 428 .DB 0 429 430XPBUS_STAT_RESET:: ; reset count 431 .DB 0 432 .DB 0,0,0 ; reserved 433 434XPBUS_PRT0_TIMER:: ; PRT0 TIMER TLDR (devices dispatch) 435 .DW 256 436XPBUS_INTR1_DEV:: ; HOSTINTR1 device 437 .DW 0 438XPBUS_INTR5_DEV:: ; HOSTINTR5 device 439 .DW 0 440 441; TIME 442 .ORG 0110H 443TIME_READY:: 444 .DB 0 445TIME_CMD:: 446 .DB 0 447TIME_RESULT:: 448 .DB 0 449TIME_RUN:: 450 .DB 0 451TIME_TIMECOUNTER:: ; timecounter (TBD.) 452 .DW 0 453 454; PAM 455 .ORG 0120H 456PAM_READY:: 457 .DB 0 458PAM_CMD:: 459 .DB 0 460PAM_RESULT:: 461 .DB 0 462PAM_RUN:: 463 .DB 0 464 465PAM_ENC:: 466 .DB 0 467PAM_REPT:: 468 .DB 0 469PAM_CYCLE_CLK:: 470 .DW 0 471PAM_REPT_CLK:: 472 .DB 0 473PAM_REPT_MAX:: 474 .DB 0 475 476 .DB 0,0,0,0 ; reserved 477PAM_STAT_PTR:: 478 .DW 0 479 480; PCM 481 .ORG 0130H 482PCM_READY:: 483 .DB 0 484PCM_CMD:: 485 .DB 0 486PCM_RESULT:: 487 .DB 0 488PCM_RUN:: 489 .DB 0 490 491PCM_ENC:: 492 .DB 0 493 .DB 0 ; reserved 494PCM_PRT1_TIMER:: ; PRT1 TIMER TLDR (PCM) 495 .DW 0 496 497 .DB 0,0,0,0,0,0 ; reserved 498PCM_STAT_PTR:: 499 .DW 0 500 501; PSG 502 .ORG 0140H 503PSG_READY:: 504 .DB 0 505PSG_CMD:: 506 .DB 0 507PSG_RESULT:: 508 .DB 0 509PSG_RUN:: 510 .DB 0 511 512; SPK 513 .ORG 0150H 514SPK_READY:: 515 .DB 0 516SPK_CMD:: 517 .DB 0 518SPK_RESULT:: 519 .DB 0 520SPK_RUN:: 521 .DB 0 522 523SPK_VOL:: 524 .DB 0 525 .DB 0 ; reserved 526SPK_FREQ:: 527 .DW 0 528SPK_TIME:: 529 .DW 0 530SPK_REMAIN:: 531 .DW 0 532 533; LPR 534 .ORG 0160H 535LPR_READY:: 536 .DB 0 537LPR_CMD:: 538 .DB 0 539LPR_RESULT:: 540 .DB 0 541LPR_RUN:: 542 .DB 0 543 ; TBD. 544 545LPR_CMD_START .EQU 1 546 547; FDC 548 .ORG 0170H 549FDC_READY:: 550 .DB 0 551FDC_CMD:: 552 .DB 0 553FDC_RESULT:: 554 .DB 0 555FDC_RUN:: 556 .DB 0 557; TBD. 558 559FDC_CMD_START .EQU 1 560 561; SIO0 562 .ORG 0180H 563SIO0_READY:: 564 .DB 0 565SIO0_CMD:: 566 .DB 0 567SIO0_RESULT:: 568 .DB 0 569SIO0_RUN:: 570 .DB 0 571 572SIO0_TXCMD:: 573 .DB 0 574SIO0_TXSTAT:: 575 .DB 0 576SIO0_TX:: 577 .DB 0 578 .DS 3 579SIO0_RXCMD:: 580 .DB 0 581SIO0_RXSTAT:: 582 .DB 0 583SIO0_RX:: 584 .DB 0 585 586; SIO1 587 .ORG 0190H 588SIO1_READY:: 589 .DB 0 590SIO1_CMD:: 591 .DB 0 592SIO1_RESULT:: 593 .DB 0 594SIO1_RUN:: 595 .DB 0 596 597SIO1_TXCMD:: 598 .DB 0 599SIO1_TXSTAT:: 600 .DB 0 601SIO1_TX:: 602 .DB 0 603 .DS 3 604SIO1_RXCMD:: 605 .DB 0 606SIO1_RXSTAT:: 607 .DB 0 608SIO1_RX:: 609 .DB 0 610 611 612; ######## Bootstrap program 613 .ORG 0200H 614ENTRY: 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 642ICR .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 649DCNTL .EQU 32H 650 OUT0 (DCNTL),A 651 ; disable refresh 652 LD A,03H ; REFE[7]=0 REFW[6]=0 CYC[10]=3(80state) 653RCR .EQU 36H 654 OUT0 (RCR),A 655 656 LD A,2 657 LD (DEBUG0),A 658 659 ; prepare memory map 660 ; MMU 661CBR .EQU 38H 662BBR .EQU 39H 663CBAR .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 684RMCR .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 689ITC .EQU 34H 690 OUT0 (ITC),A 691 ; Interrupt Vector Low = E 692 ; I = FFH 693 ; Interrupt Vector Address = FFE0H 694 LD A,0E0H 695IL .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 747INIT_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 754PSG_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 771PSG_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 781PAM_BUF:: 782PCM_BUF:: 783 .DEPHASE 784 .PHASE 08000H 785PAM_BUF_LEN:: .EQU $-PAM_BUF 786PCM_BUF_LEN:: .EQU $-PCM_BUF 787PSG_BUF:: 788 .DEPHASE 789 .PHASE 09000H 790PSG_BUF_LEN:: .EQU $-PSG_BUF 791LPR_BUF:: 792 .DEPHASE 793 .PHASE 0A000H 794LPR_BUF_LEN:: .EQU $-LPR_BUF 795FDC_BUF:: 796 .DEPHASE 797 798; ######## private memory program 799 .PHASE 0E000H 800FDC_BUF_LEN:: .EQU $-FDC_BUF 801 802PROG_ORG: .EQU $$ 803PRIVATE_RAM: 804 805XPBUS: 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 826XPBUS_LOOP: 827 HALT 828 JR XPBUS_LOOP 829 830INTR_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 852TIMECOUNTER_INCR: 853 ; timecounter 854 LD HL,(TIME_TIMECOUNTER) 855 INC HL 856 LD (TIME_TIMECOUNTER),HL 857 858; #### XPBUS devices dispatcher 859 860DEVICES_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 906XPBUS_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 916TIME_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 932PCM_DISPATCH: 933 CP PCM_CMD_START 934 JR Z,PCM_START 935 936 LD A,XPLX_R_UNKNOWN_CMD 937PCM_ERROR: 938 LD (PCM_RESULT),A 939 RET 940 941PCM_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 958PCM_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 980PCM_SET_PCM3: 981 LD HL,PCM3 982 JR PCM_SET 983PCM_SET_PCM2: 984 LD HL,PCM2 985 JR PCM_SET 986PCM_SET_PCM1: 987 LD HL,PCM1 988PCM_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 1022PCM_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 ; ��������������������������������������� 1032PCM_INTR_JMP: .EQU $+1 1033 JP PCM1 1034 1035PCM_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 1047PCM_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 1064PCM_RELOAD: 1065 LD HL,PCM_BUF 1066PCM_STAT: 1067#if USE_INTR 1068 OUT (PCM_HOSTINTR),A 1069#else 1070 LD (PCM_STAT_PTR),HL 1071#endif 1072PCM_NORMAL: 1073PCM_EXIT: 1074 EXX 1075 EX AF,AF 1076 EI 1077 RETI 1078 1079; #### PCM core code 1080 1081PCM1: 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 1089PCM2: 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 1100PCM3: 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 1119SPK_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 1131SPK_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 1173SPK_STOP: 1174 LD A,(SPK_READY) 1175 OR A 1176 RET Z 1177 1178SPK_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 1199SPK_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 1209SPK_EXIT: 1210 EI 1211 LD A,XPLX_R_OK 1212 LD (SPK_RESULT),A 1213 LD (SPK_READY),A 1214 RET 1215 1216SPK_PSGR7: 1217 .DB 0 1218 1219; ######## PSG 1220PSG_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 1228LPR_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 1236FDC_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 1245SIO0_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 1253SIO1_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 1261INTR_INT0: 1262INTR_ASCI0: 1263INTR_ASCI1: 1264 ; TBD 1265 EI 1266 RETI 1267 1268; #### PAM play start 1269 1270PAM_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 1285PAM_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 1303PAM_ERROR_ENC: 1304 POP HL ; discard caller PC 1305PAM_ERROR_PARAM: 1306 LD A,XPLX_R_ERROR_PARAM 1307 LD (PAM_RESULT),A 1308 RET ; return to main 1309 1310PAM_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 1341PAM_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 1353PAM_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 1381PAM_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 1395PAM_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 1434PAM_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 1453PAM_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 1497PAM_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 1506PAM_DRIVER: 1507 .DEPHASE 1508 1509; #### PAM2A 1510 1511 .PHASE 0FE00H 1512PAM2A_HEAD_ORG: .EQU $$ 1513PAM2A_HEAD: 1514PAM2A: 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 1531PAM2A_RELOAD: 1532 OUT (C),E 1533 OUT (C),D 1534 LD SP,PAM_BUF ;9 1535 WAIT3 1536 1537PAM2A_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 1549PAM2A_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 ; ������������������������������ 1560PAM2A_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 1570PAM2A_HEAD_LEN: .EQU $-PAM2A_HEAD 1571 1572PAM2A_REPT_ORG: .EQU $$ 1573PAM2A_REPT: 1574 OUT (C),E 1575 OUT (C),D 1576 WAIT12 1577PAM2A_REPT_LEN: .EQU $-PAM2A_REPT 1578 1579PAM2A_TAIL_ORG: .EQU $$ 1580PAM2A_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 1609PAM2A_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 1620PAM2B_HEAD_ORG: .EQU $$ 1621PAM2B_HEAD: 1622PAM2B: 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 1642PAM2B_RELOAD: 1643 OUT (C),E 1644 LD SP,PAM_BUF ;9 1645 1646PAM2B_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 1656PAM2B_NORMAL: 1657 OUT (C),E 1658 ; prefetch 1659 POP DE ;9+3 1660 OUT (C),B 1661PAM2B_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 1671PAM2B_HEAD_LEN: .EQU $-PAM2B_HEAD 1672 1673PAM2B_REPT_ORG: .EQU $$ 1674PAM2B_REPT: 1675 OUT (C),E 1676 OUT (C),D 1677PAM2B_REPT_LEN: .EQU $-PAM2B_REPT 1678 1679PAM2B_TAIL_ORG: .EQU $$ 1680PAM2B_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 1706PAM2B_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 1716PAM3A_HEAD_ORG: .EQU $$ 1717PAM3A_HEAD: 1718PAM3A: 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 1738PAM3A_RELOAD: 1739 OUT (C),L 1740 OUT (C),H 1741 WAIT3 1742 OUT (C),B 1743 LD SP,PAM_BUF ;9 1744 WAIT3 1745 1746PAM3A_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 1762PAM3A_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 1785PAM3A_LOOP: 1786 ; prefetched DE, A=B 1787 1788PAM3A_HEAD_LEN: .EQU $-PAM3A_HEAD 1789 1790PAM3A_REPT_ORG: .EQU $$ 1791PAM3A_REPT: 1792 OUT (C),E 1793 OUT (C),D 1794 WAIT3 1795 OUT (C),B 1796 WAIT12 1797PAM3A_REPT_LEN: .EQU $-PAM3A_REPT 1798 1799PAM3A_TAIL_ORG: .EQU $$ 1800PAM3A_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 1835PAM3A_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 1845PAM3B_HEAD_ORG: .EQU $$ 1846PAM3B_HEAD: 1847PAM3B: 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 1871PAM3B_RELOAD: 1872 OUT (C),D 1873 LD SP,PAM_BUF ;9 1874 1875PAM3B_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 1885PAM3B_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 1898PAM3B_LOOP: 1899 ; prefetched DE,B A=RLCA-ed flag 1900 1901PAM3B_HEAD_LEN: .EQU $-PAM3B_HEAD 1902 1903PAM3B_REPT_ORG: .EQU $$ 1904PAM3B_REPT: 1905 OUT (C),E 1906 OUT (C),D 1907 OUT (C),B 1908PAM3B_REPT_LEN: .EQU $-PAM3B_REPT 1909 1910PAM3B_TAIL_ORG: .EQU $$ 1911PAM3B_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 1935PAM3B_TAIL_LEN: .EQU $-PAM3B_TAIL 1936 1937 1938 .DEPHASE 1939 1940; #### PAM1P 1941 1942 .PHASE 0FE00H 1943PAM1P_HEAD_ORG: .EQU $$ 1944PAM1P_HEAD: 1945PAM1P: 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 1971PAM1P_RELOAD: 1972 LD HL,PAM_BUF ;9 1973 1974PAM1P_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 1982PAM1P_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 1990PAM1P_LOOP: 1991 1992 LD A,(HL) ;6+3 1993 INC HL ;4 1994 1995 OUT (PSG_DAT),A ;10+2 1996 1997PAM1P_HEAD_LEN: .EQU $-PAM1P_HEAD 1998 1999PAM1P_REPT_ORG: .EQU $$ 2000PAM1P_REPT: 2001 WAIT3 2002PAM1P_REPT_LEN: .EQU $-PAM1P_REPT 2003 2004PAM1P_TAIL_ORG: .EQU $$ 2005PAM1P_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 2027PAM1P_TAIL_LEN: .EQU $-PAM1P_TAIL 2028 2029 ; cycle 2030 ; 63 + 12 + 12 = 87 2031 2032 .DEPHASE 2033 2034PROG_ORG_LEN: .EQU $$-PROG_ORG 2035 2036; #### interrupt vector 2037 .PHASE 0FFE0H 2038VECTOR_ORG: .EQU $$ 2039VECTOR: 2040 2041VEC_INT1: 2042 DW INTR_IGN 2043VEC_INT2: 2044 DW INTR_IGN 2045VEC_PRT0: 2046 DW INTR_PRT0 2047VEC_PRT1: 2048 DW INTR_IGN 2049VEC_DMAC0: 2050 DW INTR_IGN 2051VEC_DMAC1: 2052 DW INTR_IGN 2053VEC_SIO: 2054 DW INTR_IGN 2055VEC_ASCI0: 2056 DW INTR_ASCI0 2057VEC_ASCI1: 2058 DW INTR_ASCI1 2059VEC_PT2IN: 2060 DW INTR_IGN 2061VEC_PT2OUT: 2062 DW INTR_IGN 2063VEC_PT2OVF: 2064 DW INTR_IGN 2065 ; ��������������������������������������������� 2066 ; ������������������������������������������������ 2067INTR_IGN: 2068 EI 2069 RETI 2070 2071VECTOR_ORG_LEN: .EQU $$-VECTOR_ORG 2072 2073 .DEPHASE 2074XPLX_FIRMWARE_LEN:: .EQU $ 2075