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 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
| 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)
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]
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)
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.
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.
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)
+----------------------------+
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) |
| 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
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
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
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).
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 |
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)
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[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[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[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));
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)
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 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)
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
; 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í.
; SOF = 5 → 0 (posun o 1 radek dolu)
LD BC, 01CFH
LD A, 00H ; SOF-L = 0
OUT (C), A
; 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."
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.
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).
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.
Protože se data nekopiruji (jen se mění offset), je scroll velmi rychly — staci 2-3 OUT instrukce nezavisle na velikosti obrazovky.
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á).
| 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á |
LD BC, 06CFH ; CF06H: border color
LD A, 01H ; modry border
OUT (C), A
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.
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).
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.
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).
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.
| 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 |
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.
; 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
; 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
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ě.
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).
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.
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.