12 — HW Scroll

Základní informace

MZ-800 podporuje hardwarovy scroll — posun zobrazeneho obsahu obrazovky bez nutnosti kopirovat data v paměti. Scroll je realizovany přímo v GDG čipu konverzi VRAM adres: GDG při generování obrazu pricitava programovatelny offset (SOF) k display adrese, cimz zobrazuje jinou část VRAM na danem řádku obrazovky.

Klíčové vlastnosti: - Směr: vertikální (nahoru/dolu) — osa Y je programovatelna, osa X je fixni - Granularita: po 8 pixelech (1 bajt v 320x200, resp. 1 bajt v 640x200) — jemnejsi scroll po 1 pixelů HW nepodporuje - Kruhovy buffer: VRAM je používaná jako kruhova paměť — po dosazeni konce se pokracuje od zacatku (wrap-around) - Rozdělení obrazovky: pomoci SSA/SEA lze obrazovku rozdelit na scrollovatelnou a nepohyblivou část (screen split) - Kompatibilita: funguje ve všech grafických režimech (320x200, 640x200) i v MZ-700 textovém režimu

Scroll registry — port CFH (subporty)

Scroll se ovlada přes subporty registru CFH. Přístup se provádí instrukcemi OUT (C),A kde C = CFH a B = číslo subregistru (01-07).

; Obecny vzor zapisu do scroll subportu
LD B, <cislo_subregistru>   ; 01-07
LD C, 0CFH
LD A, <hodnota>
OUT (C), A
; Alternativne: LD BC, <subregistr_CFH>  ; napr. 01CFH

Prehled subregistru

Subport Název Bitu Rozsah Prirustek Popis
CF01H SOF-L 8 00H-FFH Scroll Offset, dolnich 8 bitu
CF02H SOF-H 2 00H-03H Scroll Offset, horní 2 bity
CF03H SW 7 05H-7DH 05H Scroll Width (šířka scrollovaci oblasti)
CF04H SSA 7 00H-78H 05H Scroll Start Address
CF05H SEA 7 05H-7DH 05H Scroll End Address
CF06H BCOL 4 0H-FH Border Color (IGRB)
CF07H CKSW 1 0/1 Clock Switch (50/60 Hz)

Důležité vztahy: - SW = SEA - SSA - SW > SSA (podm. ze SM — SW musí byt větší než SSA) - SOF <= SW (SOF nesmi presahnout šířku scroll oblasti)

Bitové mapy registru

SOF (CF01H + CF02H) — 10 bitu:

CF01H (SOF-L):  [SOF7] [SOF6] [SOF5] [SOF4] [SOF3] [SOF2] [SOF1] [SOF0]
CF02H (SOF-H):  [  . ] [  . ] [  . ] [  . ] [  . ] [  . ] [SOF9] [SOF8]

SSA (CF04H) — 7 bitu:

                [  . ] [SSA6] [SSA5] [SSA4] [SSA3] [SSA2] [SSA1] [SSA0]

Bit 0 je součástí registru, ale protože prirustek je vždy 5, prakticky se používají jen nasobky 5. Bit 7 není součástí registru.

SEA (CF05H) — 7 bitu:

                [  . ] [SEA6] [SEA5] [SEA4] [SEA3] [SEA2] [SEA1] [SEA0]

SW (CF03H) — 7 bitu:

                [  . ] [ SW6] [ SW5] [ SW4] [ SW3] [ SW2] [ SW1] [ SW0]

Scroll Offset Register (SOF)

Format a rozsah

SOF je 10-bitový registr sestaveny ze dvou I/O portů:

SOF = (CF02H[1:0] << 8) | CF01H[7:0]
Rozsah: 0 - 1000 (0x000 - 0x3E8)
Prirustek: 5 (odpovida jednomu radku)

Prevod SOF na VRAM adresu

SOF udava počet 8-bajtovych bloku (320x200) resp. 16-bajtovych bloku (640x200), o které se posune zacatek zobrazení ve VRAM:

Režim Vzorec 1 řádek Celá obrazovka
320x200 VRAM_offset = SOF x 8 SOF += 5 (5 x 8 = 40 B) SOF = 1000
640x200 VRAM_offset = SOF x 16 SOF += 5 (5 x 16 = 80 B) SOF = 1000

Příklad: v režimu 320x200, SOF=5 posune zobrazení o 40 bajtů = 1 řádek nahoru. SOF=10 posune o 2 řádky, SOF=40 (0x28) posune o 8 řádek.

SOF a počet řádku

Service Manual (strana 15) uvádí vzorec pro N-řádkový scroll:

SOF_N = 0x0F x N     (kde 0x0F = 15? — SM pise "0F x 3" pro 3 radky)

Presneji: protože prirustek je 5, pro N řádku: SOF = 5 x N. Pro N-ty další řádek po 5-radkovem scrollu: SOF' = SOF_5 + 0x0F = 5x5 + 15 = 5x6 — cili prirustek 5.

Scroll Start/End Address (SSA, SEA)

Význam

SSA a SEA definuji vertikální rozsah scrollovaci oblasti na obrazovce:

         +----------------------------+
  000    |         Oblast A           |  <- nepohybliva (nad SSA)
         |                            |
  SSA -->+----------------------------+
         |                            |
         |       Scroll oblast B      |  <- scrollovana pomoci SOF
         |                            |
  SEA -->+----------------------------+
         |         Oblast C           |  <- nepohybliva (pod SEA)
         +----------------------------+

Prevod SSA/SEA na řádky

SSA a SEA se inkrementuji po 5 (každý krok = 1 řádek v rozlišení 8 pixelů):

Hodnota Řádek Poznámka
SSA=00H 0 První řádek obrazovky
SSA=05H 1 Druhý řádek (1 x 8 pixelů)
SSA=0AH 2 Třetí řádek
SSA=19H 5 Sesty řádek (40. raster linka)
SEA=5AH 18 Osmnacty řádek (144. raster linka)
SEA=7DH 25 Poslední řádek (200. raster linka)

Prevod na VRAM adresy

Režim Vzorec
320x200 SSA_addr = SSA x 64
640x200 SSA_addr = SSA x 128

Příklad: SSA=19H (25 dec) → SSA_addr = 25 x 64 = 1600 = 640H

Scroll Width (SW)

SW je 7-bitový registr, který musí odpovidat rozdílu SEA - SSA:

SW = SEA - SSA

Pro celou obrazovku: SSA=00H, SEA=7DH → SW = 7DH (125).

Důležité omezení: - SOF <= SW — scroll offset nesmi byt větší než šířka scroll oblasti, jinak je chování nedefinovane (SM: "Display is not assured with SOF set greater than SW") - SW > SSA — podminka ze Service Manualu

Mechanismus konverze adres

Blokový diagram (SM strana 14)

Service Manual obsahuje detailní blokový diagram scroll HW. Klíčové signály:

Vstupni registry:
  SSA [7 bitu] — scroll start address
  SEA [7 bitu] — scroll end address
  SW  [7 bitu] — scroll width = SEA - SSA
  SOF [10 bitu] — scroll offset

Interni signaly:
  DA  [13 bitu] — Display Address (pozice na obrazovce, 0 az 1F400)
  DMA [13 bitu] — Display Memory Address (skutecna VRAM adresa)
  MA  [13 bitu] — CPU (Memory) Address

Mezivypocty:
  SEA-SOF [10 bitu] — kolik radku zbava do konce scroll oblasti
  SOF-SW  [10 bitu] — korekce pro wrap-around

Algoritmus adresové konverze

GDG pro každý pixel na obrazovce provádí následující rozhodnuti:

1. Pokud DA < SSA:
   → DMA = DA (oblast A — bez scrollu, primo)

2. Pokud SSA <= DA < SEA:
   → Scroll oblast — pricist SOF:
     a) Spocitej: DA + SOF
     b) Pokud DA + SOF < SEA (= SEA-SOF > DA):
        → DMA = DA + SOF (primy posun)
     c) Pokud DA + SOF >= SEA (= SEA-SOF <= DA):
        → DMA = DA + SOF - SW (wrap-around — navrat na zacatek)

3. Pokud DA >= SEA:
   → DMA = DA (oblast C — bez scrollu, primo)

V HW je to realizovano komparatorem (SSA > DA?) a scitackou s multiplexorem (selektor mezi SOF a SOF-SW).

Tabulka display adres ze SM (strana 14)

SM ukazuje jak se display adresa (DA) sklada z bitu SSA, SEA a SOF:

Display address:  m    l    k    j    i    h    g  |  f    e    d  |  c    b    a
SSA:             SSA  SSA  SSA  SSA  SSA  SSA  SSA |  —    —    — |  —    —    —
                  6    5    4    3    2    1    0  |              |
SEA:             SEA  SEA  SEA  SEA  SEA  SEA  SEA |  —    —    — |  —    —    —
                  6    5    4    3    2    1    0  |              |
SOF:             SOF  SOF  SOF  SOF  SOF  SOF  SOF | SOF  SOF  SOF| SOF
                  9    8    7    6    5    4    3  |  2    1    0 |

Přiřazení řádku k adresam (Screen left end address):

Řádek Display Address (binární: m-a) Poznámka
0 00 0000 0000 000 První řádek
1 00 0000 0000 101 = 5
2 00 0000 0001 010 = 10
3 00 0000 0001 111 = 15
8 00 0000 0101 000 Druhý "řádek" (8. raster)
16 00 0000 1010 000
24 00 0001 1111 000
192 11 1100 0000 000 25. řádek
199 11 1110 0011 000 Poslední řádek

HDL implementace

Registry v GDG_core

GDG_core.vhd deklaruje následující sbernice pro scroll:

signal bus_SOF      : std_logic_vector(9 downto 0);   -- SOF (primy)
signal bus_nSOF     : std_logic_vector(9 downto 0);   -- SOF (invertovany)
signal bus_SEA      : std_logic_vector(6 downto 0);   -- SEA (primy)
signal bus_nSEA     : std_logic_vector(5 downto 0);   -- SEA (invertovany)
signal bus_nSSA     : std_logic_vector(6 downto 0);   -- SSA (invertovany)
signal bus_nSW      : std_logic_vector(6 downto 0);   -- SW (invertovany)
signal bus_SOFmxSW  : std_logic_vector(9 downto 0);   -- SOF mux SW vysledek
signal bus_nSOFmxSW : std_logic_vector(9 downto 0);   -- SOF mux SW inv.
signal bus_SEA_minus_SOF : std_logic_vector(9 downto 0);  -- SEA - SOF
signal bus_SOF_minus_SW  : std_logic_vector(9 downto 0);  -- SOF - SW (pro wrap)

Chip-select dekódování

Každý subregistr ma vlastní chip-select signál v sbernici bus_CS_0nCF(7 downto 1):

Subport CS signál Latch clock Typ latche
CF01H bus_CS_0nCF(1) NOT bus_CS_0nCF(1) F604 (inv. clock)
CF02H bus_CS_0nCF(2) bus_CS_0nCF(2) F601 (přímý clock)
CF03H bus_CS_0nCF(3) NOT bus_CS_0nCF(3) F604
CF04H bus_CS_0nCF(4) NOT bus_CS_0nCF(4) F604
CF05H bus_CS_0nCF(5) NOT bus_CS_0nCF(5) F604
CF06H bus_CS_0nCF(6) kombinacni F604
CF07H bus_CS_0nCF(7) bus_CS_0nCF(7) F615

SOF latche

SOF[7:0] (dolnich 8 bitu) se zapisuje přes CF01H do F604 latchu:

-- SOF bit 0 (radek 5578):
xF604_101_14: F604_D_Latch_C
  port map (nCLK => net_F604_88_5_clk,  -- = NOT bus_CS_0nCF(1)
            I => bus_nDT(0), O => bus_nSOF(0), nO => bus_SOF(0));

SOF[9:8] (horní 2 bity) se zapisuje přes CF02H do F601 latchu:

-- SOF bit 8 (radek 7536):
xF601_65_3: F601_D_Latch
  port map (CLK => bus_CS_0nCF(2),
            I => bus_nDT(0), O => bus_nSOF(8), nO => bus_SOF(8));

-- SOF bit 9 (radek 7718):
xF601_76_2: F601_D_Latch
  port map (CLK => bus_CS_0nCF(2),
            I => bus_nDT(1), O => bus_nSOF(9), nO => bus_SOF(9));

Všechny latche jsou transparentni (D-latch, ne flip-flop) — data se projeví okamžitě během aktivniho chip-selectu.

SSA latche

SSA[6:0] se zapisuje přes CF04H (7 bitu, všechny přes F604):

-- SSA bit 0 (radek 7729):
xF604_70_2: F604_D_Latch_C
  port map (nCLK => net_F604_88_2_clk,  -- = NOT bus_CS_0nCF(4)
            I => bus_nDT(0), O => bus_nSSA(0));

SEA latche

SEA[5:0] + SEA[6] se zapisuje přes CF05H (F604 latche):

-- SEA bit 0 (radek 7935):
xF604_97_1: F604_D_Latch_C
  port map (nCLK => net_F604_97_1_clk,  -- = NOT bus_CS_0nCF(5)
            I => bus_nDT(0), O => ?, nO => bus_SEA(0));

Adresová scitacka — SOF + Selector → DMA

Jadro scroll mechanismu je 10-bitová scitacka realizovana deseti instancemi F521 (1-bit full adder). Scita bus_SOFmxSW s bus_Selector a výsledek jde do bus_DMA:

-- Bit 0 (radek 7479):
xF521_98_3: F521_Full_Adder
  port map (A => bus_Selector(5), B => bus_SOFmxSW(2), ..., O => bus_DMA(2));

-- Bit 8 (radek 3303):
xF521_86_23: F521_Full_Adder
  port map (A => bus_Selector(11), B => bus_SOFmxSW(8), ..., O => bus_DMA(8));

Kde: - bus_Selector — aktualni pozice na obrazovce (Display Address) - bus_SOFmxSW — bud SOF nebo SOF-SW, podle toho zda doslo k wrap-around - bus_DMA — vysledna VRAM adresa (Display Memory Address)

Vypocet SEA - SOF

Odcitacka SEA - SOF je realizovana dalsimi deseti F521 adder instancemi v režimu odcitani (pricteni invertovaneho SOF + carry=1):

-- Bit 0 (radek 6131):
xF521_91_11: F521_Full_Adder
  port map (A => '0', B => bus_nSOF(0), CI => '1', O => bus_SEA_minus_SOF(0));
  -- Dolni 3 bity: A='0', protoze SEA nema bity 0-2

-- Bit 3 (radek 6536):
xF521_91_8: F521_Full_Adder
  port map (A => bus_SEA(0), B => bus_nSOF(3), ..., O => bus_SEA_minus_SOF(3));
  -- SEA(0) je bit 0 SEA registru, namapovany na pozici 3 (x8 nasobek)

Výsledek bus_SEA_minus_SOF se používá v komparatoru, který rozhoduje, zda je třeba provest wrap-around (pricist SOF-SW místo SOF).

SSA/SEA gating logika

SSA a SEA se používají v komparacni logice, která kontroluje, zda aktualni display pozice lezi uvnitř scroll oblasti:

-- Porovnani SSA s display adresou (radky 5137, 5182):
net_F302_56_16_in2 <= bus_nSSA(5) NOR bus_Selector(11);
net_F303_60_16_in1 <= NOT ( bus_nSSA(5) AND bus_Selector(11) );
net_F302_77_16_out <= bus_nSSA(6) NAND net_F302_77_16_in2;

Tyto signály řídí multiplexor, který vybírá: - Přímo DA (mimo scroll oblast) - DA + SOF (scroll bez wrap-around) - DA + SOF - SW (scroll s wrap-around)

Scroll sekvence

Inicializace — celá obrazovka

Před pouzitim scrollu je třeba nastavit všechny 4 registry:

; Cela obrazovka scrollovatelna
LD BC, 04CFH        ; CF04H: SSA = 0 (zaciname od vrsku)
LD A, 00H
OUT (C), A

LD BC, 05CFH        ; CF05H: SEA = 7DH (konec = spodek)
LD A, 7DH
OUT (C), A

LD BC, 03CFH        ; CF03H: SW = SEA - SSA = 7DH
LD A, 7DH
OUT (C), A

LD BC, 01CFH        ; CF01H: SOF-L = 0 (zadny posun)
LD A, 00H
OUT (C), A

LD BC, 02CFH        ; CF02H: SOF-H = 0
LD A, 00H
OUT (C), A

Scroll nahoru o 1 řádek

; SOF = 0 → 5 (posun o 1 radek nahoru)
LD BC, 01CFH
LD A, 05H           ; SOF-L = 5
OUT (C), A
; SOF-H zustava 0 (neni treba menit pro male posuny)

Efekt: řádek na adrese VRAM[0..39] zmizi z vrsku obrazovky a objevi se dole (wrap-around). Řádek který byl druhý (VRAM[40..79]) se nyni zobrazuje jako první.

Scroll dolu o 1 řádek

; SOF = 5 → 0 (posun o 1 radek dolu)
LD BC, 01CFH
LD A, 00H           ; SOF-L = 0
OUT (C), A

Scroll o 8 řádek nahoru

; SOF = 0 → 0x28 (40 dec = 8 radku x 5)
LD BC, 01CFH
LD A, 28H           ; SOF-L = 40
OUT (C), A

SM strana 13: "Programming SOF = $28 makes the display screen shifted eight lines up. Data on the highest line is therefore shifted to the bottom line."

Rozdělení obrazovky (Screen Split)

Princip

Nastavenim SSA a SEA na jiné hodnoty než 00H/7DH lze obrazovku rozdelit na tri části:

+----------------------------+
|  Oblast A (nepohybliva)    |  radky 0 az (SSA-1)
|                            |
+============================+  SSA
|                            |
|  Oblast B (scrollovana)    |  radky SSA az (SEA-1)
|  — ovladana pomoci SOF     |
|                            |
+============================+  SEA
|  Oblast C (nepohybliva)    |  radky SEA az 24
+----------------------------+

Oblast A a C se nescrolluji — zobrazuji staticky obsah VRAM. Pouze oblast B reaguje na změny SOF.

Příklad ze SM (strana 13)

Predpokladejme ze chceme: - Oblast A: řádky 0-4 (nepohybliva) - Oblast B: řádky 5-17 (scrollovana) - Oblast C: řádky 18-24 (nepohybliva)

Vrch oblasti B je na 5. radce (40. raster linka), vrch oblasti C je na 18. radce (144. raster linka):

LD BC, 04CFH        ; SSA = 19H (5. radek, 25 dec, 25*8=200. pixel)
LD A, 19H
OUT (C), A

LD BC, 05CFH        ; SEA = 5AH (18. radek, 90 dec, 90*8=720. pixel)
LD A, 5AH
OUT (C), A

LD BC, 03CFH        ; SW = SEA - SSA = 5AH - 19H = 41H
LD A, 41H
OUT (C), A

LD BC, 01CFH        ; SOF = 0 (inicializace)
LD A, 00H
OUT (C), A
LD BC, 02CFH
LD A, 00H
OUT (C), A

Scroll oblasti B o 1 řádek: SOF = 05H. Scroll oblasti B o další řádek: SOF = 0AH.

Omezení: SOF <= SW. V tomto příkladu SW=41H (65 dec), maximální SOF je tedy 65 — což odpovídá 13 řádkům posunu (13 x 5 = 65). Oblast B ma 13 řádku, takže SOF může pokryt přesně celou oblast (plný cyklus wrap-around).

Wrap-around (kruhovy buffer)

Princip

VRAM je používaná jako kruhovy buffer. Když SOF posune zobrazení za konec scroll oblasti (SEA), GDG automaticky pokracuje od zacatku (SSA):

Bez scrollu (SOF=0):               Se scrollem (SOF=5, 1 radek):
  Radek 0:  VRAM[0..39]              Radek 0:  VRAM[40..79]  (byl 2.)
  Radek 1:  VRAM[40..79]             Radek 1:  VRAM[80..119] (byl 3.)
  ...                                ...
  Radek 198: VRAM[7920..7959]        Radek 198: VRAM[7960..7999]
  Radek 199: VRAM[7960..7999]        Radek 199: VRAM[0..39]  ← wrap!

Poslední řádek při SOF=5 zobrazuje data z VRAM[0..39] — to jsou data, která "odscrolovala" z vrsku. Software typicky tato data prepise novym obsahem před nastavenim SOF.

Plynuly scroll — typická sekvence

  1. Zápis novy obsah do řádku na VRAM adrese, která se objevi dole
  2. Nastav SOF += 5
  3. Opakuj

Protože se data nekopiruji (jen se mění offset), je scroll velmi rychly — staci 2-3 OUT instrukce nezavisle na velikosti obrazovky.

Border Color Register (CF06H)

Format

CF06H:  [  x ] [  x ] [  x ] [  x ] [  I ] [  G ] [  R ] [  B ]

Bit 3: I (intenzita)
Bit 2: G (zelena)
Bit 1: R (cervena)
Bit 0: B (modra)

Horní 4 bity jsou ignorovany. Po resetu: BCOL = 0 (černá).

Barvy borderu

Kod IGRB Barva Kod IGRB Barva
0H 0000 Černá 8H 1000 Seda
1H 0001 Modra 9H 1001 Sv. modra
2H 0010 Červená AH 1010 Sv. červená
3H 0011 Purpurova BH 1011 Sv. purpurova
4H 0100 Zelená CH 1100 Sv. zelená
5H 0101 Azurová DH 1101 Sv. azurová
6H 0110 Zluta EH 1110 Sv. zluta
7H 0111 Bílá FH 1111 Jasne bílá

Důležité vlastnosti

Příklad

LD BC, 06CFH        ; CF06H: border color
LD A, 01H           ; modry border
OUT (C), A

Propagace změn — mid-scanline efekty

Okamžitá propagace

Všechny scroll registry se propagovany okamžitě — GDG nepoužívá žádný double-buffering nebo "latch at line start" mechanismus. Změna SOF uprostřed viditelneho řádku způsobí torn line efekt.

SOF propagace (ověřeno simulací)

Měření z doc 15 ukazuje přesně chování:

SOF zmeneno z 0 na 5 uprostřed viditelneho řádku (io_write na CLK0=600):

Col[ 0] CLK0= 330 RAS=0x60
Col[ 1] CLK0= 346 RAS=0x61
  ...
Col[16] CLK0= 586 RAS=0x70
Col[17] CLK0= 602 RAS=0x71   <- posledni sloupec s SOF=0
Col[18] CLK0= 618 RAS=0x9A   *** SKOK ***  (0x71 → 0x9A = +41)
Col[19] CLK0= 634 RAS=0x9B
  ...
Col[39] CLK0= 954 RAS=0xAF

SOF změna se projevila na Col[18] — první sloupec, jehoz DRAM fetch zacal po dokonceni I/O write operace (~18-20 CLK0 latence).

Vizuální dopad torn line

Col 0 ---- Col 17 | Col 18 ---- Col 39
  SOF=0 data      |   SOF=5 data
  (stary scroll)  |   (novy scroll)

Řádek zobrazuje data ze dvou různých pozic VRAM — analogie "torn frame" efektu.

Bezpečná změna — během blanking

Pro změnu bez artefaktu je třeba zapisovat SOF během H-blank nebo V-blank periody:

; Cekani na V-blank (bezpecne pro scroll update)
WAIT_VBL:
    IN A, (0CEH)        ; Status Register
    BIT 6, A            ; Bit 6 = VBLN (0 = V-blank aktivni)
    JR NZ, WAIT_VBL
; Ted jsme v V-blank — bezpecny cas pro zmenu SOF
LD BC, 01CFH
LD A, <novy_SOF_L>
OUT (C), A
LD BC, 02CFH
LD A, <novy_SOF_H>
OUT (C), A

Bezpečné okno H-blank: ~508 CLK0 (~28.6 us, ~101 T-statu CPU). Bezpečné okno V-blank: celý V-blank interval (~1.5 ms v PAL).

Registr CF01H vs CF02H — neatomicky zápis

SOF se sklada ze dvou registru (CF01H a CF02H). Každý zápis se projeví okamžitě a nezavisle. Pokud software mění SOF po castech, mezi obema zápisy existuje kratke okno (~20 CLK0) s nekonzistentni hodnotou SOF (novy SOF-L, stary SOF-H).

Pro vetsinu operaci to není problem — změna o 1-2 řádky mění jen SOF-L. Ale velke skoky (změna SOF-H) by mely byt provadeny během blanking.

Porovnání latenci s ostatnimi registry

Registr Port Delay Mid-line efekt Mechanismus
Paleta F0H 10-14 CLK0 Ano F601 latch → NAND mux → F666 FF
Border CF06H 6 CLK0 Ano Latch → RBGI MUX → F666 FF
SOF-L CF01H ~18 CLK0 Ano (torn line) Latch → DRAM addr generace
SOF-H CF02H ~18 CLK0 Ano (torn line) Latch → DRAM addr generace

Clock Switch (CKSW) — CF07H

Format

CF07H:  [  S ] [  x ] [  x ] [  x ] [  x ] [  x ] [  x ] [  x ]

Bit 7: S — prepinac frekvence
  0 = 50 Hz (PAL, vychozi v Evrope)
  1 = 60 Hz (NTSC)

Pouze bit 7 je aktivní, ostatní bity jsou ignorovany. Podrobnosti viz doc 04-superimpose-cksw.md.

Praktické programování

Plynuly scroll celé obrazovky

; Inicializace scroll registru
    LD BC, 04CFH        ; SSA = 0
    XOR A
    OUT (C), A
    LD BC, 05CFH        ; SEA = 7DH
    LD A, 7DH
    OUT (C), A
    LD BC, 03CFH        ; SW = 7DH
    LD A, 7DH
    OUT (C), A
    LD HL, 0            ; aktualni SOF = 0

SCROLL_LOOP:
    ; Cekej na V-blank
.wait:
    IN A, (0CEH)
    BIT 6, A
    JR NZ, .wait

    ; Zvys SOF o 1 radek
    LD DE, 5
    ADD HL, DE

    ; Kontrola wrap-around
    LD A, H
    CP 04H              ; SOF >= 0x400 (1024)?
    JR C, .no_wrap
    ; SOF presahl maximum — odecti 1000 (3E8H)
    LD DE, -1000
    ADD HL, DE
.no_wrap:

    ; Zapis SOF
    LD A, L
    LD BC, 01CFH
    OUT (C), A           ; SOF-L
    LD A, H
    LD BC, 02CFH
    OUT (C), A           ; SOF-H

    ; ... (zapis novy radek na uvolnenou pozici) ...

    JR SCROLL_LOOP

Staticke zahlavi + scrollovany obsah

; Zahlavi = radky 0-2 (nepohyblive)
; Obsah = radky 3-24 (scrollovany)
    LD BC, 04CFH        ; SSA = 0FH (3. radek, 3*5=15)
    LD A, 0FH
    OUT (C), A
    LD BC, 05CFH        ; SEA = 7DH (konec)
    LD A, 7DH
    OUT (C), A
    LD BC, 03CFH        ; SW = 7DH - 0FH = 6EH
    LD A, 6EH
    OUT (C), A
    ; SOF = 0 (inicializace)
    LD BC, 01CFH
    XOR A
    OUT (C), A
    LD BC, 02CFH
    OUT (C), A

Korekce dokumentace

SSA maximum

V HTML dokumentaci (sharp_mz-800_2_WHID_65040-032.htm) je SSA maximum uvedeno jako 7DH, ale Service Manual (strana 14) uvádí 78H. Porty.txt uvádí rozsah 0-78H. Protože poslední platný řádek je 24 (= 120 dec = 78H), maximum SSA=78H je správně.

SOF prirustek

Některé zdroje uvadeji prirustek SOF jako "0FH" (15). To odpovídá posunu o 3 řádky (3 x 5 = 15). Základní prirustek pro 1 řádek je vždy 5 (jak plyne z délky řádku 40 B / 80 B děleno 8 B resp. 16 B na SOF krok).

SW > SSA

SM strana 14 uvádí podmienku SW > SSA. To je nestandardni omezení — při SSA blizke SEA by SW bylo male a mohlo by byt mensi než SSA. V praxi to znamená ze při velkem SSA (napr. 78H) a malem SW je chování nedefinovane.

Stav ověření

Service Manual: Strany 13-15 (scroll), strana 14 (blokový diagram), strana 26 (I/O register map). Všechny údaje konzistentni.

HDL analýza: Potvrzeno: - bus_SOF[9:0] — 10 latchu na CF01H/CF02H - bus_nSSA[6:0] — 7 latchu na CF04H - bus_SEA[6:0] — 7 latchu (+ invertované bus_nSEA[5:0]) na CF05H - bus_nSW[6:0] — 7 latchu na CF03H - Adresová scitacka: 10x F521 full adder (bus_DMA = bus_Selector + bus_SOFmxSW) - SEA-SOF odcitacka: 10x F521 full adder - SSA/SEA komparacni logika pro gating

Simulace (cocotb): Overena propagace SOF (doc 15): - SOF=0 vs SOF=5: DRAM adresy se liší (RAS posun ~0x40) - Mid-line změna: diskontinuita na Col[18] po io_write na CLK0=600 - Následující řádky po změně: plynule (žádné diskontinuity)

Reálně HW: Ještě neověřeno.