; ********************************************** ; Přehrávač dvouhlasé hudby na 1-bitovém výstupu ; pro počítač PMD-85. ; ********************************************** ; pozn.: je použito následující vlastnosti ; hardware PMD-85: zápis hodnoty 04h ; na port 0F6h způsobí aktivaci speakru, ; zápis stejné hodnoty na port 0F7 pak ; deaktivaci speakru. Proto není nutné ; během generování tónu měnit hodnotu ; registru ACC a šetří se čas. ; pozn.: děličky ověřeny na fyzickém PMD-85 ; měřením frekvence dne 28.4.2018 ; ********************************************** kbdled .equ 0f6h ; port PC 8255 kbdcwr .equ 0f7h ; port CWR 8255 .org 0 ; adresa začátku programu ; ************************* ; přehrávač dvouhlasé hudby ; ************************* player: lxi h,skladba ; začátek zápisu skladby mov a,m ; načíst koeficient transpozice inx h sta nt2trn+1 ; a uložit do programu mvi a,7 ; načíst tempo skladby sub m ; upravit polaritu TEMPA ani 7 ; oříznout rozsah rrc rrc rrc ; a ve vhodné formě (x32) sta plynxm+1 ; uložit do programu inx h ; smyčka přehrávače plynxt: push h mov e,m ; DE = relativní délka noty mvi d,0 mov l,d ; nulovat akumulátor součinu plynxm: mvi h,0 ; zde je uloženo TEMPO skladby mvi c,3 plynx2: dad h jnc plynx3 dad d plynx3: dcr c jnz plynx2 mov b,l ; B = rel. délka noty x TEMPO pop h inx h mov a,b ; konec skladby při nulové ana a ; délce noty jz quiet mov c,m ; výška 1. noty inx h mov a,m ; výška 2. noty inx h push h call nt2div ; 1. notu překódovat na děličku shld snd00b+1 ; a tu uložit do přehrávače shld snd01b+1 shld snd10b+1 shld snd11b+1 mov a,c call nt2div ; 2. notu překódovat na děličku shld snd00c+1 ; a tu uložit do přehrávače shld snd01c+1 shld snd10c+1 shld snd11c+1 call sound ; generování souzvuku pop h jmp plynxt ; další dvě noty.. quiet: xra a ; deaktivace speakru out kbdled ret ; a ukončení přehrávače ; ************************************** ; generování dvou kvaziparalelních tónů ; vstup: reg. B = délka not ; výška not nastavena v programu ; ************************************** sound: lxi h,0 ; uschovat registr SP dad sp shld sndqui+1 mvi a,4 ; modulace speakru lxi h,0 ; akumulátor tónu 1 lxi d,0 ; akumulátor tónu 2 mov c,d ; LOW byte délky not ; oba kanály jsou nastaveny na log. 0 snd00a: out kbdcwr ; kanál 1 je nulový snd00b: lxi sp,0 ; výška tónu 1 dad sp jc snd01c ; kanál 1 nahodit snd00c: lxi sp,0 ; výška tónu 2 out kbdcwr ; kanál 2 je nulový xchg dad sp xchg jc snd10d ; kanál 2 nahodit snd00d: dcr c ; odpočet délky tónu jnz snd00a dcr b jnz snd00a sndqui: lxi sp,0 ; obnovit hodnotu reg. SP ret ; kanál 1 nahozen, kanál 2 nulový snd01a: out kbdled ; kanál 1 je nahozen snd01b: lxi sp,0 ; výška tónu 1 dad sp jc snd00c ; kanál 1 shodit snd01c: lxi sp,0 ; výška tónu 2 out kbdcwr ; kanál 2 je nulový xchg dad sp xchg jc snd11d ; kanál 2 nahodit snd01d: dcr c ; odpočet délky tónu jnz snd01a dcr b jnz snd01a jmp sndqui ; společný konec ; kanál 1 nulový, kanál 2 nahozen snd10a: out kbdcwr ; kanál 1 je nulový snd10b: lxi sp,0 ; výška tónu 1 dad sp jc snd11c ; kanál 1 nahodit snd10c: lxi sp,0 ; výška tónu 2 out kbdled ; kanál 2 je nahozen xchg dad sp xchg jc snd00d ; kanál 2 shodit snd10d: dcr c ; odpočet délky tónu jnz snd10a dcr b jnz snd10a jmp sndqui ; společný konec ; kanál 1 nahozen, kanál 2 nahozen snd11a: out kbdled ; kanál 1 je nahozen snd11b: lxi sp,0 ; výška tónu 1 dad sp jc snd10c ; kanál 1 shodit snd11c: lxi sp,0 ; výška tónu 2 out kbdled ; kanál 2 je nahozen xchg dad sp xchg jc snd01d ; kanál 2 shodit snd11d: dcr c ; odpočet délky tónu jnz snd11a dcr b jnz snd11a jmp sndqui ; společný konec ; ************************************ ; překódování čísla noty na děličku ; vstup: ACC = číslo noty ; výstup: HL = dělička ; (implicitně 00h překládá jako pauzu) ; ************************************ nt2div: ana a jz nt2pau ; pauzu netransponuju nt2trn: adi 0 ; případná transpozice add a ; byte => word nt2pau: mov l,a ; HL = (word)číslo noty mvi h,0 lxi d,ladeni ; tabulka ladění dad d mov e,m ; E = LSB děličky noty inx h mov d,m ; D = MSB děličky noty xchg ; HL = dělička pro notu ret ; ****************************************************** ; Tabulka dělicích poměrů generátoru tónu pro jednotlivé ; tóny v rozsahu 88-klávesového klavíru. ; Další (i nižší) tóny lze libovolně přidávat do seznamu ; za poslední uvedenou notu c5 až do pořadového čísla ; 0FFh včetně. ; ****************************************************** ; Pro PMD-85 platí následující, experimentálně ověřený ; koeficient převodu frekvence tónu na hodnotu děličky: ; divider = 7.302 x f ; ****************************************************** ladeni: ; PAUZA ; 00h .dw 0000h ; N'' (velká dvoučárkovaná, subkontra) ; 01h..03h .dw 00C8h,00D4h,00E1h ; N' (velká jednočárkovaná, kontra) ; 04h..0Fh .dw 00EEh,00FCh,010Ch,011Bh,012Ch,013Eh .dw 0151h,0165h,017Bh,0191h,01A9h,01C2h ; N (velká) ; 10h..1Bh .dw 01DDh,01F9h,0218h,0237h,0259h,027Dh .dw 02A3h,02CBh,02F6h,0323h,0352h,0385h ; n (malá) ; 1Ch..27h .dw 03BBh,03F3h,0430h,046Fh,04B3h,04FBh .dw 0546h,0597h,05ECh,0646h,06A5h,070Bh ; n' (malá jednočárkovaná, komorní a) ; 28h..33h .dw 0776h,07E7h,0860h,08DFh,0966h,09F6h .dw 0A8Dh,0B2Eh,0BD8h,0C8Ch,0D4Bh,0E16h ; n'' (malá dvoučárkovaná) ; 34h..3Fh .dw 0EECh,0FCFh,10C0h,11BFh,12CDh,13ECh .dw 151Bh,165Ch,17B1h,1919h,1A97h,1C2Ch ; n''' (malá trojčárkovaná) ; 40h..4Bh .dw 1DD9h,1F9Fh,2181h,237Fh,259Bh,27D8h .dw 2A36h,2CB9h,2F62h,3233h,352Fh,3859h ; n'''' (malá čtyřčárkovaná) ; 4Ch..57h .dw 3BB3h,3F3Fh,4302h,46FEh,4B37h,4FB0h .dw 546Dh,5972h,5EC4h,6467h,6A5Fh,70B2h ; n''''' (malá pětičárkovaná) ; 58h .dw 7766h ; *************************************************** ; zápis skladby ve formátu: ; 0. bajt: transpozice o počet půltónů nahoru ; 1. bajt: tempo (1 = nejpomalejší, 7 = nejrychlejší) ; následují trojice bajtů s významem: ; - relativní délka noty, výška tónu 1, výška tónu 2 ; - je-li relativní délka noty = 0, ukončí se skladba ; - relativní délka noty může například mít formu: ; 01h = 1/32 nota ; 02h = 1/16 nota ; 04h = 1/8 nota ; 08h = 1/4 nota ; 10h = 1/2 nota ; 20h = 1/1 nota ; *************************************************** skladba: .db 0 ; transpozice .db 2 ; tempo .db 12,36h,3Ah .db 02,2Eh,36h .db 02,31h,38h .db 12,36h,3Ah .db 02,2Eh,36h .db 02,31h,38h .db 04,36h,3Ah .db 04,38h,3Bh .db 02,36h,3Ah .db 02,35h,38h .db 04,31h,36h .db 08,2Fh,38h .db 04,2Eh,36h .db 04,2Ch,35h .db 08,2Ch,33h .db 08,29h,31h .db 08,2Ah,33h .db 08,31h,35h .db 24,2Eh,36h .db 04,00h,00h .db 02,2Eh,36h .db 02,31h,38h .db 12,36h,3Ah .db 02,2Eh,36h .db 02,31h,38h .db 12,36h,3Ah .db 02,2Eh,36h .db 02,31h,38h .db 04,36h,3Ah .db 04,38h,3Bh .db 02,36h,3Ah .db 02,35h,38h .db 04,31h,36h .db 08,2Fh,38h .db 04,2Eh,36h .db 04,2Ch,35h .db 08,2Ch,33h .db 08,29h,31h .db 08,2Ah,33h .db 08,31h,35h .db 24,2Eh,36h .db 04,2Eh,33h .db 04,31h,3Ah .db 16,36h,3Ah .db 16,36h,3Ah .db 04,36h,3Ah .db 04,38h,3Bh .db 04,36h,3Ah .db 04,33h,36h .db 16,35h,38h .db 08,33h,36h .db 08,33h,36h .db 04,33h,36h .db 04,35h,38h .db 04,33h,36h .db 04,31h,35h .db 24,2Eh,31h .db 04,2Eh,36h .db 04,31h,38h .db 16,36h,3Ah .db 16,36h,3Ah .db 04,36h,3Ah .db 04,38h,3Bh .db 02,36h,3Ah .db 02,35h,38h .db 04,33h,36h .db 08,35h,38h .db 04,33h,36h .db 04,31h,35h .db 08,2Fh,33h .db 08,2Ch,31h .db 08,2Fh,33h .db 08,31h,35h .db 16,2Eh,36h .db 00 .end