Následující podprogramy pro SHARP MZ-800 představují
kompletní obsluhu magnetofonu.Umožňují zapsat hlavičku
(SvHead) i tělo (SvBody) souboru zvolenou rychlostí
a s automatickým nastavením rychlosti hlavičku (LdHead)
i tělo (LdBody) opět přečíst.Při čtení i zápisu je
zároveň prováděna obsluha zvukového výstupu a borderu.
Při znalosti činnosti obvodů 8253,8255 a jejich zapojení
v počítači by měla být činnost podprogramů zřejmá
z komentářů.Pozor,podprogramy jsou psány pro mód 800
(grafický mód) počítače.Při jejich aplikaci v módu 700
(textový mód) je nutné nahradit I/O adresování obvodů
8253 a 8255 adresováním paměťovým a v časově kritických
místech (LdBit,SvBit) používat adresování registrem DE.
Také je nutné vyslat 01h na adresu E008h.

 ;
 ;*********************************************
 ;* Podprogramy pro spolupráci s magnetofonem *
 ;* (automatické nastavování čtecí rychlosti) *
 ;*               SHARP MZ-800                *
 ;*      (c)1987 Michal Kreidl Software       *
 ;*********************************************
 ;
        FHead=10F0H	 ;adresa hlavičky
        FSize=FHead+12H	 ;údaj o délce souboru
        FAddr=FHead+14H	 ;údaj o uložení souboru
 ;
        OnTime=80	 ;pauza před zápisem
        OfTime=40	 ;pauza po zápise
        BrdClr=10	 ;barva borderu
 ;
	Speed1=551	 ;rychlost 1/1 (rychlosti)
	Speed2=311	 ;rychlost 2/1 (podle Turbo)
	Speed3=231	 ;rychlost 3/1 (Copy)
 ;
 ; adresy portů MZ-800
 ;
        TimReg=0CEH	 ;čtení vert.zatem.impulsů
        BrdReg=6CFH	 ;nastavení borderu
        PortPA=0D0H	 ;PA 8255
        PortPB=0D1H	 ;PB 8255
        PortPC=0D2H	 ;PC 8255
        Mod55=0D3H	 ;řídící registr 8255
        Count0=0D4H	 ;čítač 0 8253
        Mod53=0D7H	 ;řídící registr 8255
        PortA=0FEH	 ;čtení OUT čítače 0
 ;
 ; Přečtení hlavičky souboru
 ;
 LdHead:LD   A,40	 ;počet bitů značky
        LD   HL,FHead	 ;hlavička
        LD   BC,128	 ;délka hlavičky
        JR   LdBlok	 
 ;
 ; Přečtení těla souboru
 ;
 LdBody:LD   A,20	 ;počet bitů značky
        LD   HL,(FAddr)	 ;uložení těla souboru
        LD   BC,(FSize)	 ;délka těla souboru
 ;
 ; Přečtení bloku délky BC na adresu HL
 ; v A je 40 pro hlavičku,20 pro tělo
 ;
 LdBlok:PUSH BC		 ;uchování délky,
        PUSH HL		 ;adresy uložení
        PUSH AF		 ;a počtu bitů značky
        LD   DE,Play	 ;adresa hlášení 'PLAY'
        CALL MotOn	 ;zapnutí motoru
        POP  DE		 ;D=počet bitů značky
        LD   A,30H	 ;nastavení čítače 0
        OUT  (Mod53),A	 ;do módu 0
        LD   A,1	 ;zapnutí zvuku
        OUT  (Mod55),A	 ;(SET b0)
 FndBlk:LD   HL,0	 ;vzorkovací čas pro určení
        LD   (SampTm),HL ;hodnoty bitu bude zatím 0
        LD   B,0	 ;přeskočení 256 bitů
 LdWait:CALL LdBit
        DJNZ LdWait
 SetSpd:LD   HL,0	 ;nulování součtu časů
        LD   E,L	 ;v L,H,E ( E nejvyšší )
        LD   BC,180H	 ;počet měřených šířek
 TmLoop:CALL LdBit	 ;změření šířky
        JR   C,LdMark	 ;zjištěn bit 1
        PUSH BC
        LD   BC,(LoadTm) ;zmeřená délka krát -1
        ADD  HL,BC	 ;přičtení k součtu
        POP  BC
        JR   C,NoOvrf	 ;pokud je přenos z 16.bitu
        DEC  E		 ;zvětšení E o -1
 NoOvrf:DEC  BC		 ;
        LD   A,B
        OR   C		 ;až do přečtení daného počtu
        JR   NZ,TmLoop	 ;se měření opakuje
        LD   L,H
        LD   H,E	 ;vydělení součtu 256-ti
        LD   (SampTm),HL ;dá čas vzorkování
        JR   SetSpd	 ;měření s hledáním 1.bitu značky
 LdMark:LD   B,D	 ;počet bitů 1 značky
        DEC  B		 ;-1,který již byl přečten
 LdTM1: CALL LdBit	 ;čtení bitu,má být 1
        JR   NC,FndBlk	 ;značka neúplná
        DJNZ LdTM1	 ;přečtení všech bitů 1
        LD   B,D	 ;počet bitů 0 značky
 LdTM0: CALL LdBit	 ;čtení bitu,má být 0
        JR   C,FndBlk	 ;značka neúplná
        DJNZ LdTM0	 ;přečtení všech bitů 
        CALL LdBit	 ;za značkou ještě bit 1
        JR   NC,FndBlk
        POP  HL		 ;adresa uložení
        POP  BC		 ;délka bloku
        LD   DE,0	 ;kontrolní součet
 LdLoop:CALL LdByte	 ;čtení
        LD   (HL),A	 ;a uložení bytu
        CPI		 ;posun HL,zmenšení a test BC
        JP   PE,LdLoop	 ;přečtení všech bytů
        EX   DE,HL	 ;do HL kontrolní součet
        CALL LdByte	 ;čtení vyššího byte součtu
        CP   H		 ;porovnání s vypočteným
        JP   NZ,LdErr	 ;nesouhlas
        CALL LdByte	 ;čtení nižšího bytu
        CP   L		 ;porovnání
        JP   NZ,LdErr	 ;nesouhlas
        JP   MotOff	 ;vypnutí motoru
 ;
 ; Zápis hlavičky souboru
 ;
 SvHead:LD   A,40	 ;počet bitů značky
        LD   HL,FHead	 ;adresa hlavičky
        LD   BC,128	 ;délka hlavičky
        JR   SvBlok
 ;
 ; Zápis těla souboru
 ;
 SvBody:LD   A,20	 ;počet bitů značky
        LD   HL,(FAddr)	 ;uložení souboru
        LD   BC,(FSize)	 ;délka souboru
 ;
 ; Zápis bloku délky BC z adresy HL
 ; v A je 40 pro hlavičku a 20 pro tělo
 ;
 SvBlok:PUSH BC		 ;uchování délky,
        PUSH HL		 ;adresy uložení
        PUSH AF		 ;a počtu bitů značky
        LD   DE,Record	 ;adresa hlášení 'RECORD'
        CALL MotOn	 ;zapnutí motoru
        POP  DE		 ;v D počet bitů značky
        LD   B,OnTime	 ;délka čekání před zápisem
        CALL Wait	 ;čekání,v B zůstane 0
        LD   A,36H	 ;nastavení čítače 0
        OUT  (Mod53),A	 ;do módu 3
        LD   A,1	 ;zapnutí zvuku
        OUT  (Mod55),A	 ;(SET b0)
 SvLead:OR   A
        CALL SvBit	 ;zápis bitu 0
        CALL TestTm	 ;test na změnu VBLK
        JR   Z,SvLead	 ;žádná změna
        DJNZ SvLead	 ;změna proběhne 256 krát
        LD   B,D	 ;počet bitů 1 značky
 SvTM1: SCF
        CALL SvBit	 ;zápis bitu 1
        DJNZ SvTM1	 ;zápis všech bitů 1
        LD   B,D	 ;počet bitů 0 značky
 SvTM0: OR   A
        CALL SvBit	 ;zápis bitu 0
        DJNZ SvTM0	 ;zápis všech bitů 0
        SCF
        CALL SvBit	 ;bit 1 za značkou
        POP  HL		 ;adresa uložení
        POP  BC		 ;délka bloku
        LD   DE,0	 ;kontrolní součet
 SvLoop:LD   A,(HL)	 ;byte z adresy HL
        CALL SvByte	 ;zápis bytu
        CPI		 ;posun HL,snížení a test BC
        JP   PE,SvLoop	 ;zápis všech bytů bloku
        EX   DE,HL	 ;kontrolní součet do HL
        LD   A,H
        CALL SvByte	 ;zápis vyššího bytu součtu
        LD   A,L
        CALL SvByte	 ;zápis nižšího bytu součtu
        SCF
        CALL SvBit	 ;na závěr bit 1
        XOR  A		 ;vypnutí zvuku
        OUT  (Mod55),A	 ;(RES b0)
        LD   B,OfTime	 ;délka čekání po zápisu
        CALL Wait	 ;čekání
        JP   MotOff	 ;vypnutí motoru
 ;
 ; Přečtení/změření bitu,hodnotu bitu uloží do CF,
 ; délku do (LoadTm)
 ; Při zjišťování hodnoty bitu porovnává změřenou
 ; délku se vzorkovacím časem (SampTm)
 ;
 LdBit: EXX
        LD   C,20H	 ;maska signálu čtení CMT
 WtLow: IN   A,(PortPC)	 ;čtení
        AND  C		 ;a výběr signálu CMT
        JP   NZ,WtLow	 ;čeká na signál 0
        OUT  (Mod53),A	 ;vzorkování hodnoty čítače 0
        IN   A,(Count0)
        LD   L,A
        IN   A,(Count0)	 ;přečtení obsahu čítače 0
        LD   H,A	 ;do HL
        LD   (LoadTm),HL ;úschova pro účely měření
        LD   BC,(SampTm) ;vzorkovací čas
        SBC  HL,BC	 ;porovnání se změřeným časem
        EX   AF,AF'	 ;úschova CF
        LD   A,1
        OUT  (Count0),A	 ;uložení 1 do čítače,
        XOR  A		 ;což způsobí rychlé dočítání
        OUT  (Count0),A	 ;a přechod výstupu na 1
        CALL Border	 ;obsluha borderu,test BREAK
        LD   BC,20H	 ;maska signálu čtení CMT,B=0
 WtHigh:IN   A,(PortPC)	 ;čtení
        AND  C		 ;a výběr signálu CMT
        JR   NZ,High	 ;čeká na signál 1,
        DJNZ WtHigh	 ;ale jen 256 krát
        CALL TstBrk	 ;test BREAK
        JR   WtHigh	 ;čekání pokračuje
 High:  LD   A,-1	 ;nastavení čítače na FFFFh
        OUT  (Count0),A
        OUT  (Count0),A	 ;začíná měření
        EX   AF,AF'	 ;v CF hodnota bitu
        EXX
        RET
 ;
 ; Přečtení bytu do A,počíta kontrolní součet v DE
 ;
 LdByte:PUSH BC
        CALL LdBit	 ;před bytem bit 1
        JP   NC,LdErr	 ;není-li,pak chyba
        LD   B,8	 ;byte má 8 bitů
 LBLoop:CALL LdBit	 ;čtení bitu
        JR   NC,LdSum0	 ;pro bit 1
        INC  DE		 ;zvýšení kontrolního součtu
 LdSum0:RL   C		 ;připojení bitu k bytu v C
        DJNZ LBLoop	 ;8 krát
        LD   A,C	 ;byte do A
        POP  BC
        RET
 ;
 ; Zápis bitu z CF,rychlost je dána časem v (SaveTm)
 ;
 SvBit: EXX
  	LD   HL,(SaveTm) ;délka impulsu bitu 0
        JR   NC,SvLow
        ADD  HL,HL	 ;pro bit 1 je dvojnásobná
 SvLow: LD   A,L	 ;uložení této délky
        OUT  (Count0),A  ;jako předvolby do čítače 0
        LD   A,H
        OUT  (Count0),A
        LD   H,10H	 ;maska výstupu čítače
 WtCnt1:IN   A,(PortA)	 ;čtení
        AND  H		 ;a výběr výstupu čítače
        JP   Z,WtCnt1	 ;čeká na 1
        LD   A,3	 ;výstup na CMT : 1
        OUT  (Mod55),A	 ;(SET b1)
        CALL Border	 ;obsluha borderu,test BREAK
        LD   H,10H	 ;maska bitu 4
        IN   A,(PortPC)	 ;test běhu motoru 
        AND  H
        JP   Z,SvErr	 ;stojí-li motor,chyba
 WtCnt0:IN   A,(PortA)	 ;čtení
        AND  H		 ;a výběr výstupu čítače
        JP   NZ,WtCnt0	 ;čeká na 0
        LD   A,2	 ;výstup na CMT : 0
        OUT  (Mod55),A	 ;(RES b1)
        EXX
        RET
 ;
 ; Zápis bytu A,počítá kontrolní součet v DE
 ;
 SvByte:PUSH BC
        LD   C,A	 ;byte do A
        SCF
        CALL SvBit	 ;před byte bit 1
        LD   B,8	 ;byte má 8 bitů
 SBLoop:RL   C		 ;výběr bitu
        JR   NC,SvSum0	 ;pro bit 1
        INC  DE		 ;zvýšení kontrolního součtu
 SvSum0:CALL SvBit	 ;zápis bitu
        DJNZ SBLoop	 ;8 krát
        POP  BC
        RET
 ;
 ; Obsluha borderu,test BREAK
 ;
 Border:LD   HL,BrdDiv	 ;Adresa proměnné,které
        RRC  (HL)	 ;slouží k řízení borderu
        SBC  A,A	 ;border 0/FFh
        AND  BrdClr	 ;border 0/barva
        LD   BC,BrdReg
        OUT  (C),A	 ;obarvení borderu
 TstBrk:IN   A,(PortPB)	 ;čtení klávesnice
        AND  81H	 ;výběr SHIFT+BREAK
        RET  NZ		 ;není
        JP   BrkErr	 ;BREAK
 ;
 ; Vyslání hrany do obvodů ovládání motoru
 ;
 MotRem:LD   A,6	 ;0 na ovládání
        OUT  (Mod55),A	 ;(RES b3)
        INC  A		 ;1 na ovládání
        OUT  (Mod55),A	 ;(SET b3)
 ;
 ; Testuje běh motoru,běh:ZF=0
 ;
 MotTst:IN   A,(PortPC)	 ;čtení
        AND  10H	 ;a výběr bitu motoru
        RET
 ;
 ; Zapnutí motoru
 ;
 MotOn: DI		 ;zákaz přerušení
        LD   A,8	 ;aktivace sloupce
        OUT  (PortPA),A	 ;klávesnice s BREAK
        LD   A,33H	 ;nastavení pom.proměnné
        LD   (BrdDiv),A	 ;pro řízení borderu
        CALL MotTst	 ;test motoru
        RET  NZ	 	 ;běží-li,konec
        CALL MotRem	 ;pokus o rozběh
        RET  NZ 	 ;běží-li,konec
        CALL Messag	 ;tisk hlášení z adresy DE
 WtMot: CALL TstBrk	 ;test BREAK
        CALL MotRem	 ;pokus o rozběh
        JR   Z,WtMot	 ;dokud se motor nerozběhne
        RET
 ;
 ; Zastavení motoru
 ;
 MotOff:LD   A,36H	 ;blokování čítače 0
        OUT  (Mod53),A
        XOR  A	 	 ;vypnutí zvuku
        OUT  (Mod55),A	 ;(RES b0)
        LD   BC,BrdReg
        OUT  (C),A	 ;černý border
 WtOff: CALL MotRem	 ;pokus o zastavení motoru
        JR   NZ,WtOff	 ;dokud motor nestojí
        EI		 ;povolení přerušení
        RET
 ;
 ; Test změny úrovně vert.zatem.impulsu,změna:ZF=0
 ;
 TestTm:IN   A,(TimReg)	 ;čtení časovacích signálů
        LD   C,A	 
        XOR  E	 	 ;porovnání s předchozím stavem
        LD   E,C	 ;uchování stavu pro další test
        AND  40H	 ;výběr VBLK
        RET
 ;
 ; Zpoždění B*10ms
 ;
 Wait:  CALL TestTm	 ;test změny VBLK
        JR   Z,Wait	 ;žádná změna
        DJNZ Wait	 ;změna musí proběhnout B krát
        RET
 ;
 Play:  DEFM 'Press PLAY',0DH
 Record:DEFM 'Press RECORD',0DH
 ;
 SaveTm:DEFW Speed1	 ;rychlost zápisu
 ;
 BrdDiv:DEFS 1
 LoadTm:DEFS 2
 SampTm:DEFS 2
 ; 
 ; Dále je nutné doplnit rutiny pro ošetření chyb,
 ; tyto rutiny musí volat MotOff
 ;
 LdErr:			 ;chyba při čtení
 SvErr:			 ;chyba při zápisu
 BrkErr:		 ;BREAK
 ;
 ; Pokud jsou vyžadována hlášení PLAY,RECORD,musí
 ; existovat rutina pro vytištění textu z adresy DE
 ;
 Messag:
 ;
do monitoru.

TB X dd  ;Nastaveni tabulatoru.
     Tabulatory se nastavuji proto, aby pri tisku textu byly odpovidajici
cas