Narsil č. 13

Motorola 68000 (11)

↑

MOTOROLA 68000 (11. část)

Dneska si budeme povídat o programování časovačů na ST/STE.

1) Obecné pojednání

2) Přístup přes hardware registry, XBIOS (bude příště)

3) Přehrávání samplů řešené na ST přes TIMER A (až příště)

4) ŕádkový rozklad pomocí TIMER B, umožňující více než 16 barev na obrazovce (až příště).

1) Počítače ATARI už od počátku disponují integrovaným obvodem MFP 68901, který zajišťuje vlastně všechna podstatná přerušení počítače na straně periférií, kromě této vlastnosti, spravuje také 4 nezávisle časovače. Ano, opravdu 4, ne jen jeden jako tomu je u PC.

Teoreticky jsou všechny časovače libovolně programovatelné, avšak z důvodu předurčení, TIMERu C pro 200 Hz přerušení a TIMERu D pro generování rychlosti RS232, nám vlastně zbývají programovatelné pouze časovače A a B.

Skutečnost je poněkud odlišná, protože každý z programátorů v asembleru jedná opravdu tvrdě po svém, takže se někdy nedivte, pokud někdo přece jen C či D překopne po svém.

2) Časovače A a B mají prakticky identické možnosti, pro své ovládání potřebují tři pamětové registry: TIMER A

            Ovládácí registr
            Bit 7 6 5 4 3 2 1 0  TACR
 $FFFA19    R/W         x x-x-x-x-- druh provozu
                        |
                        |---------- resetuj Timer A
         
 TACR & TBCR
 Bit 3 2 1 0  funkce
     0 0 0 0  Timer STOP, žádná funkce se neprovádí
     0 0 0 1  Delay Modus, delička dělí 4
     0 0 1 0  Delay Modus, dělička dělí 10
     0 0 1 1  Delay Modus, dělička dělí 16
     0 1 0 0  Delay Modus, dělička dělí 50
     0 1 0 1  Delay Modus, dělička dělí 64
     0 1 1 0  Delay Modus, dělička dělí 100
     0 1 1 1  Delay Modus, dělička dělí 200
     1 0 0 0  Event Count Mode, bude popsán později
     0 0 0 1  Mód šířky pulzu, dělička dělí 4
     0 0 1 0  Mód šířky pulzu, dělička dělí 10
     0 0 1 1  Mód šířky pulzu, delička dělí 16
     0 1 0 0  Mód šířky pulzu, dělička dělí 50
     0 1 0 1  Mód šířky pulzu, dělička dělí 64
     0 1 1 0  Mód šířky pulzu, dělička dělí 100
     0 1 1 1  Mód šířky pulzu, dělička dělí 200

Abys mohl správně spočítat frekvenci časovače, musíš použít jednoduchého výpočtu.

Master Clock MFP 2,457,600/sec poděl číslem, které určíš nastavením druhu provozu v kontrolním registru. Prerušení se potom spustí po době vzniklé podělením tímto číslem a následovným podělením nastavením počítadla.

Příklad: Chceme vytvoři kvůli přehrávání samplů na ST kmitočer 12 Khz, pak tedy zvolím Delay Modu, dělička dělí 4, vyjde číslo 614,400. Abychom tedy dosáhli frekvence 12000 Hz (přibližně), musíme nastavit počítadlo na 51, protože 614,400 / 51 = 12047 Hz.

Počítadlo TIMERu A je na adrese $FFFA1F a může být v rozsahu 0-255.

Timer B má stejné funkce ale jeho umístění adres je na $FFFA1B pro TBCR a $FFFA21 pro počítadlo.

Jak TIMER A, tak TIMER B má narozdíl od C a D navíc především mód Event Count, ten použijete (u TIMERu B), pokud si na obyčejném ST chcete vytvořit efekt s rozkladem řádků obrazovky, tj. měnění barev během vykreslování apod. Po zvolení tohoto módu je totiž každé číslo v časovači interpretováno jako jeden řádek, tudíž počkáte-li při VBL (bohužel musíte tento časovač v tomto módu startovat jedině ve VBL, protože jinak to vypadá dost hnusně a nefunkčně) například 100, odstartuje se časovač až na stém řádku obrazovky, poté můžete změnit počítadlo třeba na 10 a každých 10 řádků se bude generovat přerušení, ostatně, tyto věci budou patrné i z ukázky.

Pozor! Pokud používate tohoto způsobu, je nutné aby počet pročekaných řádků odpovídal přesně počtu řádků na obrazovce (většinou 200).

TIMER A má též Event Count Mode, avšak jeho praktické využití je až u strojů STE, protože pomocí něj se dá velmi jednoduše indikovat ukončení přehrávání DMA zvuku. Na Falconu je tento mód ještě více vypracován, takže přerušení může proběhnout třeba i na začátku samplu či recordu apod.

TIMER C a D pracují pouze v Delay Modusu a proto se také jejich módy ovládájí pouze přes jeden registr:

            Ovládácí registr
            Bit 7 6 5 4 3 2 1 0  TCDCR
 $FFFA1D    R/W - x x x - x x x
                  | | |   | | |
                  | | |   ------- druh provozu D
                  --------------- druh provozu C
         
 Kontrolní registr pro Timer C a Timer D
 Bit  2 1 0  funkce časovače C
 Bit  6 5 4  funkce časovače D
      0 0 0  Function STOP, žádná funkce
      0 0 1  Delay Modus, dělička dělí 4
      0 1 0  Delay Modus, dělička dělí 10
      0 1 1  Delay Modus, dělička dělí 16
      1 0 0  Delay Modus, dělička dělí 50
      1 0 1  Delay Modus, dělička dělí 64
      1 1 0  Delay Modus, dělička dělí 100
      1 1 1  Delay Modus, dělička dělí 200

PočítadLo TIMERu C je na adrese $fffa23 a TIMERu D na adrese $fffa25.

Dalším velmi důležitým registrem je na adrese $fffa17, jedná se o tzv. Vektor Registr, kterým můžete zamaskovat jedno z přerušení MFP 68901. Pro nás, kódery, je však mnohem důležitější 3. bit tohoto registru, kterým můžete zvolit tzv. AEI (Automatic End of Interrupt) nebo SEI (Software End of Interrupt). Pomocí tohoto bitu se může vaše přerušení zkrátit o několik instrukcí a jak jsem osobně zjistil, je v některých případech absolutně nutné mít aktivní AEI.

            Bit  7 6 5 4 3 2 1 0
 $fffa17    R/W  X X X X X - - -  VR
                 | | | | |
                 | | | | -------  0=AEI / 1=SEI
                 ---------------  Interruptvektor

Abychom samotný časovač konečně spustili, musíme nakonec ještě nastavit samotné vektory přerušení a povolit přerušení v kontrolních registrech samotného MFP.

Vektor pro Timer D je na adrese $110.

Vektor pro Timer C je na adrese $114.

Vektor pro Timer A je na adrese $134.

Vektor pro Timer B je na adrese $120.

Po nastavení vektoru už je vše připraveno pro spuštění, ale aby k němu skutečně došlo, je nutné nastavit ještě:

IERA

            Bit  7 6 5 4 3 2 1 0
 $FFFA07    R/W  x x x x x x x x Inter. Enable Reg.
                 | | | | | | | | 0 = Int. vypnut
                 | | | | | | | | 1 = Int. možný
                 | | | | | | | - Timer B
                     ----------- Timer A
         
 IERB
            Bit  7 6 5 4 3 2 1 0
 $FFFA09    R/W  x x x x x x x x Inter. Enable Reg.
                 | | | | | | | | 0 = Int. vypnut
                 | | | | | | | | 1 = Int. možný
                 | | | --------- Timer D
                     ----------- Timer C

Dále musíte nastavit Interrupt Mask Registry, ty nastavíme stejným způsobem jako IERA a IERB, tj. povolená přerušení nastavíme na bitovou jedničku a zakázaná na nulu. Pozor! Tyto kanály mají na starosti více přerušení než jen časovače, proto pro nastavování používejte funkcí BSET, BCLR nebo OR a EOR, v žádném případě, pokud nevíte co přesně děláte, nepoužívejte MOVE či CLR.

IMRA má adresu $FFFA13.

IMRB má adresu $FFFA15.

Nastavení bitu na jedna opět přerušení povoluje, na nulu zakazuje.

Dalšímy registry jsou tzv. Interrupt Pending Bit, jejichž význam zcela přesně nechápu a bohužel jsem je ani nikdy nepoužil. Každopádně, měli by mít význam v tom případě, má-li nastat přerušení a neexistuje-li pro takovou situaci upotřebení, pak můsíme tento kanál softwarově vymazat, a to tak, že pošleme na registr byte ve kterém budou všechny bity nastaveny až na ten, který si přejeme zrušit.

Adresa IPRA je $FFFA0D.

Adresa IPRB je $FFFA0B.

Posledním důležitým registrem je Interrupt In Service Bit, který se nastaví při odstartování přerušení vašeho časovače. Pokud pracujete v režimu Automatic End of Interrupt, nemusíte se o tento bit starat, pracuje-li v režimu SEI, budete muset před ukončením bit vymazat. V módu SEI musíte před ukončením opět nastavovat časovač (tím si nejsem zcela jistý, ale vyplyne to z příkladů, které budou uvedeny v příštím čísle).

Tak se zatím mějte . . .

HEAD