OMEN zdárně pokračuje

Konstrukce do druhé knihy úspěšně pokračují. Sledujte:

OMEN Alpha má už čtvrtou revizi (tentokrát mírně vylepšená systémová sběrnice, vyhozená LEDka a vyvedené vývody SID, SOD).

Na Tindie jsem Alphu vyprodal během dvou týdnů, teď čekám na nové součástky a novou várku desek. Máte-li zájem o desky, sady nebo hotové kity, napište se na waitlist.

Nahodil jsem jednoduchý manuál k Alfě, kde jsem si zavzpomínal na vizuální estetiku cyklostylovaných manuálů k PMD a podobným, s nimiž jsem kdysi trávil volné chvíle.

OMEN Bravo, tedy jednodeskáč s 65C02, po prvotním fiasku (ano, jsem debil a navrhnul jsem oscilátor blbě!) běžel na první zapojení.

OMEN Kilo, jednodeskáč s 68B09 aka nejlepším osmibitem své doby, dopadl stejným fiaskem. Ale tentokrát za to nemůžu já, ale moje skladové zásoby tohoto procesoru. Jsou mrtvé. Všechny. Takže čekám na nové…

Všechny tyhle OMENy mají stejné rozložení signálů na systémové sběrnici. Tedy, ona není úplně systémová, protože není kompletní adresová sběrnice, ale řekněme aplikační. Takže další přídavné moduly, co vznikají (displej, I2C/SPI rozhraní, zvukový generátor, SD karta, paměťové moduly, …), by měly být kompatibilní se všemi základními deskami. No a aby se připojovalo snáze, připravil jsem i malý backplane PCB, kam si je můžete popřipojovat.

Jeden z majitelů Alphy mě upozornil na problém: v PCB nejsou otvory na šroubky. Přiznám se, že mě to ani nenapadlo, protože mám v hlavě pořád vizi toho, že se budou tyhle desky montovat do krabiček, vytištěných na 3D tiskárně, a desky se uchytí jen takovými pacičkami, ale asi je pravda, že by se otvor či dva hodily…

Ve volných chvílích jsem napsal překladač pro BASIC. Vložíte BASIC, vypadne vám assemblerový zdroják. Zatím tedy jen pro 8080/8085. Na základní hraní, helejte, dobrý. Sice nemá moc optimalizací a je jen celočíselný, ale na druhou stranu má náznak procedur, lokálních proměnných, struktur datových i programových…

No a aktuální The Big Thing je online překladač céčka pro 6502, 8080 a Z80. Ne, nepíšu to celé sám a znovu, jen (a slovo „jen“ je v hodně velkých uvozovkách) jsem přeložil existující cc65 a z88dk pomocí Emscripten do JavaScriptu. Tři dny trvalo, než to začalo fungovat, bestie! Ale když se to rozběhlo, funguje to moc hezky.

A mimochodem, víte, proč cpu vývojové věci do JavaScriptu? Není to proto, že můžou běžet v prohlížeči, ale hlavně proto, že budou fungovat na Linuxu. Macu i na Windows. Cože? Že můžu napsat totéž v C a pak na každé platformě přeložit pomocí make? No, věřte mi, že za posledních dvacet let jsem potkal spoustu takového software, a pravda byla taková, že pokud někdo neudělal binárky pro jednotlivé platformy, tak pravděpodobnost toho, že to půjde bezproblémově přeložit a spustit, byla někde okolo 1:7…

Rubriky: Hardware | Štítky: , | Napsat komentář

Alpha: Sériové rozhraní

Gratuluji ke zprovoznění počítače. Jen je trošku hloupé, že počítač vlastně umí dělat jen to, co mu vypálíte do EEPROM, a nemůžete s ním nijak komunikovat. To teď napravíme. Přidáme první vstupně – výstupní obvod, totiž sériové rozhraní.

Použijeme obvod 6850, přesněji verzi 68B50 (verze B umí pracovat i na frekvenci 2 MHz). Jedná se o obvod,označovaný ACIA – Asynchronous Communications Interface Adapter. Pod slovy „asynchronní komunikační rozhraní“je trochu cudně skryto, že jde o standardní sériové rozhraní, jaké známe z „COM portů“ a dalších sériových portů na počítači. My k jeho výstupům připojíme nějaký převodník USB-to-Serial, a tím získáme možnost komunikovat s Alphou přes terminálový program z počítače.

Při testech se ukázalo, že i verze MC6850, tedy bez „B“, zvládne provoz touto rychlostí, ale může se to lišit kus odkusu…

ACIA 6850

Obvod 6850 je sériový komunikační obvod. Jeho hlavním úkolem je převést zaslaný bajt na sériový signál (tj. správně odvysílat start bit, datové bity, případně paritní bit, a nakonec stop bit) a opačně, tj. načíst správně časovaný sériový signál a připravit ho k předání procesoru.

Asynchronní v popisu znamená, že spolu s daty není přenášen hodinový signál ani není činnost přesně časována –když přijde bajt, je vyslán, když přijdou vstupní sériová data, jsou načtena. Synchronizace, tj. to, že bude načteno opravdu to, co načteno být má, zajišťují právě start a stop bity – podle jejich správného průběhu pozná obvod, že jsou data v pořádku.

Vysílání dat po výstupu TXDATA (Tx = transmit) a příjem na vstupu RXDATA (Rx = receive) je časován pomocí systémových hodin. U našeho počítače je systémový kmitočet roven 1,8432 MHz. Tento kmitočet je v ACIA vnitřně dělen (dělitel je programově nastavitelný na hodnoty 1, 16 a 64). Použijeme dělení 16, což znamená, že komunikační rychlost bude 1843200 / 16 = 115200 bitů za sekundu (baud).

Obvod 6850 s procesorem komunikuje pomocí osmibitové datové sběrnice (D0-D7), několika CS vstupů (CS = ChipSelect), které určují, kdy se s obvodem komunikuje (CS0 = 1, CS1 = 1, /CS2 = 0 – ve všech ostatních případech je datová sběrnice odpojena), vstupu E (Enable, obvod komunikuje jen pokud je E=1), vstupu R/W, který udává, zda se z obvodu čte (1) nebo se do něj zapisuje (0) a vstupu RS, který udává, jestli se čtou/zapisují data (1), nebo řídicí hodnoty(0).

Kromě těchto signálů nabízí i signál /IRQ (Interrupt Request – požadavek na přerušení). Pomocí přerušení může ACIA dát vědět procesoru, že například přišla nějaká data po sériovém portu, nebo že data k odeslání byla odeslána apod. My přerušení nepoužijeme.

Z hlediska programátora se tedy obvod 6850 jeví jako dva registry (vybrané pomocí vstupu RS), z nichž jeden je datový, druhý „systémový“. Funkci osvětlí tabulka:

VSTUPY REGISTRY
RS R/W TYP REGISTRU FUNKCE
0 0 Zápis Řídicí registr (Control Register, CR)
0 1 Čtení Stavový registr (Status Register, SR)
1 0 Zápis Data k vyslání (Transmit Data Register, TDR)
1 1 Čtení Přijatá data (Receive Data Register, RDR)

Všimněte si, že do řídicího registru je možné pouze zapisovat, nelze z něj číst, naopak stavový registr lze pouze číst,nelze do něj zapisovat. Není to totiž potřeba. Totéž s datovými registry – při čtení se čte to, co obvod přijal (a nezajímá nás to, co jsme odeslali). Při zápisu je jasné, že chceme data vyslat, nedávalo by smysl zapisovat do přijatých dat.

Řídicí registr CR

Osmibitový registr CR řídí čtyři funkce obvodu:

  • Bity 0 a 1 nastavují dělicí poměr hodin, viz výše.
    CR1 CR0 DĚLITEL
    0 0 1
    0 1 16
    1 0 64
    1 1 RESET

    Poslední kombinace nenastavuje dělitele, ale celý obvod resetuje do výchozího nastavení, tj. vyprázdní registry anuluje příznaky. My použijeme kombinaci 01, tj. dělení 16. Kdyby bylo potřeba rychlost snížit, použijeme kombinaci 10, tj. dělení 64, a obvod bude komunikovat rychlostí 28800 Bd.

  • Bity 2, 3 a 4 nastavují délku vysílaných a přijímaných dat (sedmibitové nebo osmibitové), zda se pracuje s paritou a kolik je stop bitů. Tyto informace najdete např. i v nastavení Hyperterminálu, když půjdete hledat detaily připojení. Pro naše účely použijeme kombinaci 101, tj. osmibitový přenos, bez parity, 1 stop bit.
  • Bity 5 a 6 určují, jestli vysílač po odvysílaném bajtu bude žádat o přerušení a v jakém stavu bude výstup RTS
  • Bit 7 určuje, jestli přijímač bude vyvolávat přerušení v případě chyby.

Pro bližší popis odkazuju zájemce opět k datasheetu, my použijeme hodnotu 15h (0 00 101 01 binárně), tj. osmibitový přenos, bez parity, přerušení zakázané a přenosová rychlost 115200 Baud (Baud je jednotka „bitů za sekundu“ –včetně start a stop bitů).

Stavový registr SR

Svět není dokonalý, život není fér a asynchronní sériové přenosy nejsou nijak sladěné s biorytmy našeho procesoru.Pokud pošlu bajt do 6850, začne ho obvod vysílat. Ovšem předtím je dobré podívat se, jestli už dokončil vysílání toho předchozího. Při příjmu je zase dobré se podívat, jestli nějaký bajt už načetl, a pokud ho načetl, tak ho zpracovat, aby se uvolnilo místo pro další bajt. Popřípadě získat informaci o tom, jestli nedošlo k chybě. Tyhle informace jako když najdete ve stavovém registru SR.

Pokud načtete bajt ze SR, tak vás jednotlivé bity informují o následujícím:

  • Bit 0 – Receiver Data Register Full (RDRF). Pokud je nastaven na 1, znamená to, že obvod načetl bajt po sériové lince do přijímače a bylo by záhodno ho zpracovat. Jakmile procesor přečte stav datového registru, je bit RDRF nastaven na 0. Nula znamená, že žádný nový bajt nepřišel.
  • Bit 1 – Transmitter Data Register Empty (TDRE). Jakmile zapíšete do datového registru bajt, nastaví se TDRE na 0 a obvod začne bajt vysílat po sériové lince. Jakmile ho vyšle, nastaví tento bit na 1. Programátor by si měl před tím, než nějaký bajt pošle, zkontrolovat, že může – tedy že bit TDRE = 1.
  • Bity 2, 3 pracují s řídicími signály CTS, DCD, a já je tady s klidným svědomím opomenu.
  • Bit 4 – Framing Error (FE) znamená, že přijatá data byla špatně časována, např. že nepřišel požadovaný STOP bit.
  • Bit 5 – Receiver Overrun (OVRN). Overrun, neboli hezky česky přeběh, je stav, kdy přijímač přijal bajt, ale procesor ještě nezpracoval předchozí přijatý. Ten nově přijatý je tedy zahozený (protože jej není kam dát, žádný vnitřní buffer není) a nastaví se OVRN na 1, aby bylo jasné, že došlo k chybě.
  • Bit 6 – Parity Error (PE). Pokud využíváme přenos s paritou, zkontroluje 6850 paritní bit. Pokud byl chybný, nastaví příznak PE.
  • Bit 7 – Interrupt Request (IRQ) říká, že obvod požádal o přerušení z nějakého závažného důvodu. Buď byl přijat bajt a je povolené přerušení při přijetí dat, nebo byl odeslán bajt a je povoleno přerušení při odeslání, nebo vypadla nosná (DCD).

6850 a ALPHA

Jak připojit tento obvod k naší konstrukci? Tak, je jasné, že datová sběrnice přijde na datovou sběrnici procesoru. Co se vstupy CS, R/W a RS?

Vstup E povoluje obvodu komunikovat s procesorem (v logické 1). My budeme chtít tento obvod připojit jako periferii,tedy vstupně-výstupní obvod. Vývod IO/M shodou okolností říká právě to, jestli procesor chce pracovat s pamětí (0),nebo s periferií (1). Můžeme ho tedy přímo připojit na vstup E, tím se zajistí, že obvod ACIA bude reagovat jen na požadavky pro zápis a čtení do / z periferií a bude ignorovat operace s pamětí.

R/W určuje, jestli se bude zapisovat (0) nebo číst (1). V našem systému má podobnou funkci signál /WR – je 0, pokud procesor hodlá zapisovat, jinak je 1, takže může sloužit jako signál čtení (i když není /RD aktivní). Je to v pořádku, stačí to?

Podívejme se na to: Pokud bude procesor chtít zapisovat, pošle správný signál, ve všech ostatních případech bude číst. Nevadí to něčemu? Nevadí, protože bude odpojený od sběrnice díky vstupům CS a E.

Jenže moment: Podívejte se pořádně na průběhy signálů – signál IO/M je nastaven dřív, než proběhne cyklus ALE,a /WR je přitom neaktivní (=1). Takže ACIA začne číst a posílat hodnoty po datové sběrnici, takže by teoreticky mohl ovlivnit latchování adresy. Teď oceníme oddělovač sběrnice ze začátku této kapitoly.

Odpověď tedy zní: Nestačí to! Měli bychom signál E držet neaktivní, pokud ALE=1, protože obvod nemá oddělené povolovací vstupy pro zápis a čtení (jako mají třeba paměti). Popřípadě použít /CS2 pro ALE. Ale díky oddělovači to není třeba řešit.

Pracovat se s 6850 bude tedy pomocí instrukcí IN a OUT. Ty používají osmibitovou adresu, takže se teď ještě musíme postarat nějak o to, aby obvod správně z adresy poznal, že procesor komunikuje s ním. Navrhuju, pokud proti tomu nic nemáte, použít vstupy CS0, CS1 a /CS2 a připojit je na adresní vodiče A7, A6 a A5 takto:

A7 A6 A5 A4 A3 A2 A1 A0
CS0 CS1 /CS2 RS

Obvod bude vybraný pouze tehdy, pokud budou nejvyšší tři bity adresy rovny 110. Na stavu ostatních bitů nebude záležet. Jakákoli adresa, která splní masku „110x xxxx“ vyhoví. Vyhovují tedy adresy C0h – DFh.

Na nejnižší bit A0 jsem připojil vstup RS. Ten vybírá mezi datovým (1) a řídicím / stavovým registrem (0). Adresy, které budou mít v nejnižším bitu 1, budou přistupovat k datovému registru (C1h, C3h, C5h, … DDh, DFh). Ostatní adresy budou přistupovat k řídicímu či stavovému registru (C0h, C2h, C4h, … DCh, DEh). Programátor si může vybrat kteroukoli z nich, jsou ekvivalentní.

Přesto doporučuju použít ty adresy, které mají v bitech A1-A4 logické 1. Do budoucna to ušetří případné mrzení s připojováním dalších periferií.

Proto si zapište- ACIA v počítači Alpha je zapojena takto:

Adresa Zápis Čtení
0DEh Řídicí registr Stavový registr
0DFh Data k odeslání Přijatá data

Musíme také přivést hodinový signál na vstupy RXCLK a TXCLK. Oba spojíme, protože chceme vysílat stejnou frekvencí jako přijímat. Připojíme je na vývod CLK z procesoru.Signál /RTS budeme ignorovat, vstupy /CTS a /DCD, sloužící k řízení přenosu, připojíme na zem.

Vývody RXDATA (vstup) a TXDATA (výstup) jsou už to sériové rozhraní… připojte je k převodníku USB-to-UART, samosebou kříženě (TxD na vstup RXDATA, RxD na výstup TXDATA). Počítač je připraven komunikovat, stačí ho jen naprogramovat!

Jak pracovat s 6850?

Na začátku musíme nastavit řídicí registr tak, jak potřebujeme. Už jsme si řekli, že to bude hodnota 15h. Tím je obvod nastaven a připraven k přijímání a vysílání dat. Rozšíříme tedy naší inicializační sekci:

Na začátku jsou pojmenované adresy ACIA (bázová adresa obvodu 6850 v našem počítači), ACIAC(ontrol), ACIAS(tatus) a ACIAD(ata). Vyhneme se tak programátorskému moru, „magickým konstantám“.

Do registru A uložíme požadované řídicí slovo (15h) a instrukcí OUT ho zapíšete na adresu ACIAControl (tj. 0DEh).Vnější logika našeho počítače se postará o to, že data neskončí v paměti, ale tam, kde mají, tj. v obvodu 6850.

Co dál? Obvod je nastaven, teď je zapotřebí vypsat ono obligátní HELLO WORLD. Někde v paměti tedy bude tenhle řetězec a my ho budeme bajt po bajtu procházet a vysílat na sériový výstup.

Když se řekne „vysílat“, tak si na to uděláme podprogram. Bude se jmenovat třeba SEROUT (jako že SERial OUTput) ajeho funkce bude, že vyšle hodnotu v registru A. Předtím si ale zkontroluje, jestli je vysílač volný. Musí si tedy načíst hodnotu stavového registru SR a zkontrolovat bit 1 (TDRE). Pokud je nulový, musí počkat, až bude 1.

Na začátku si uložím obsah registru A. Mám v něm ten bajt, co chci vyslat, ale budu ten registr potřebovat, protože si do něj načtu hodnotu stavového registru. Takže si jeho hodnotu uložím na zásobník.

Na dalším řádku načtu hodnotu stavového registru do registru A. Pak provedu logický součin (AND) s hodnotou 2.Hodnota 2 totiž binárně vypadá takto: 00000010 – jsou to tedy samé nuly, jen na pozici bitu 1, který potřebuju testovat, je jednička. Výsledkem logického součinu bude buď hodnota 2, pokud je bit 1 nastaven, nebo 0, pokud je nulový.

Připomeňme si: pokud je bit 1 stavového registru nulový, znamená to, že obvod 6850 ještě vysílá předchozí data a my musíme počkat, dokud to nedokončí. Tedy pokud je (hodnota stavového registru AND 02) rovna nule, čekáme. A přesně to zajišťuje další instrukce JZ. Pokud je příznak Z=1 (tedy předchozí operace skončila s výsledkem 0), tak JZ skáče. Tady se skáče opět na načtení stavového bajtu a vše se opakuje, dokud není výsledek nenulový. V tu chvíli už víme, že má 6850 volno a můžeme vysílat.

Pokud je tedy volno, přečteme si ze zásobníku zpět hodnotu, co byla původně v registru A a pomocí OUT ji zapíšeme do datového registru 6850 – ACIAData.

Správná otázka je: Co se stane, když náhodou bude obvod 6850 vadný, nebo nebude zapojený správně a bude vracet pořád hodnotu 0? V takovém případě, ano, tušíte správně, jste právě vygenerovali nekonečnou smyčku, ve které se bude procesor točit do skonání věků – pardon, do vypnutí napájení, do RESETu nebo do přerušení.

Výpis řetězce

Už zbývá jen detail – dát to všechno dohromady. Máme inicializovaný obvod ACIA, máme někde podprogram, který umí poslat znak na sériové rozhraní, teď už jen stačí vytvořit smyčku, která bude posílat jednotlivé znaky nejznámějšího nápisu v historii programování.

Buď můžeme zvolit postup mechanický, tedy postupně volat SEROUT s hodnotami pro znaky H, E, L, L, O… v registru A, nebo si ty znaky můžeme někam nějak zapsat a ve smyčce je postupně načítat.

Nejjednodušší způsob je uložit si nápis někam do paměti jako posloupnost znaků. K tomu slouží direktiva DB. Na začátku programu si do registrů HL uložíte adresu prvního znaku nápisu. Pak stačí jen opakovat následující postup:

  1. Přečíst hodnotu z adresy, na kterou ukazuje HL, do registru A: MOV A, M
  2. Zavolat SEROUT: CALL SEROUT
  3. Zvýšit hodnotu HL o 1: INX H
  4. Opakovat od bodu 1: JMP 1

Ale pozor – takto zapsáno to je nekonečná smyčka, která bude posílat stále dokola kompletní obsah paměti. Potřebujeme říct, kdy má přestat.

Používají se v zásadě tři postupy. První je ten, že za poslední znak dáme ještě znak 0. Někdy se tomu říká také ASCIIZ (ASCII s ukončovací nulou – Zero), někdy se tomu říká CSTR (protože takový způsob ukládání řetězců volí jazyk C).Pokud v bodu 1 načteme hodnotu 0, tak je vypsaný celý řetězec a můžeme skončit. Nevýhoda: Součástí řetězce nesmí být samotný kód 0.

Druhý způsob je ten, že jako první hodnotu řetězce dáme jeden byte, který bude obsahovat délku řetězce v bajtech.Tomuto způsobu se také někdy říká PSTR, protože takto ukládá řetězce Pascal. Algoritmus je o něco složitější:

  1. Přečíst hodnotu z adresy HL do registru C: MOV C, M
  2. Zvýšit hodnotu HL o 1: INX H
  3. Přečíst hodnotu z adresy, na kterou ukazuje HL, do registru A: MOV A, M
  4. Zavolat SEROUT: CALL SEROUT
  5. Zvýšit hodnotu HL o 1: INX H
  6. Snížit hodnotu C (Counter) o 1: DCR C
  7. Pokud je hodnota nenulová, skočit na bod 3: JNZ 3

Ve skutečnosti zkušený programátor vynechá bod 5 a v bodě 7 skáče na bod 2 – tím ušetří jeden bajt. Je jedno, jestli se hodnota HL zvýší před skokem, nebo po skoku, efekt je stejný. Nevýhoda: řetězec může mít maximálně 256 znaků.

Třetí způsob využívá toho, že se většinou u takových počítačů používá jen prostá znaková sada ASCII, která má definované znaky jen v rozsahu 00 – 7Fh. Tedy žádné speciální, semigrafické, přehlásky, … Pokud je tomu tak, tak se použije způsob, podobný tomu prvnímu, ale s tím rozdílem, že místo toho, abychom za poslední znak přidali 0, tak my zapíšeme poslední znak tak, že mu nastavíme nejvyšší bit na 1 (tedy ho posuneme do rozmezí 80h-FFh). Výhoda je, že řetězec nezabírá ani o jediný byte navíc. Nevýhoda je, kromě toho, že nelze použít speciální znaky, třeba i složitější obsluha, ale zas tak hrozné to není. Představme si podprogram STROUT, který tento postup implementuje:

Načtený bajt nejprve ošetříme a případný nastavený bit 7 znulujeme. Pak výsledek pošleme na výstup.

Znovu si načteme stejný bajt, a tentokrát se podíváme na nejvyšší bit. Pokud je nenulový, máme vše za sebou a vracíme se pryč (RNZ). Jinak standardní postup: Přejít na další adresu a celé opakovat znovu!

Všechny tři postupy mají svá pro a proti a své výhody a omezení. Který způsob použijete, to záleží na vás. V dobách osmibitů se hojně používal poslední (s negovaným bitem 7), ale pokud počítáte s tím, že například budete zobrazovat i jiné znaky než standardní sedmibitové ASCII, musíte zvolit jiný postup. Koncová nula je široce používaná dnes, právě díky tomu, že takto implementuje řetězce standardní Céčko. Takový řetězec může mít libovolnou délku, ale nesmí sám obsahovat nulu. Navíc to každý řetězec prodlouží o jeden byte.

Hotový program

Na začátku proběhne inicializace – studený (cold) start. Nastaví se zásobník (bez něj by nefungovaly podprogramy) a obvod ACIA. Po inicializaci startuje vlastní obslužný program (teplý start). Tedy program: uloží do HL adresu řetězce, zavolá funkci STROUT a jede se znovu.

Zvolil jsem nakonec ukládání řetězců „tradičně osmibitově“. Na posledním řádku vidíte znaky k výpisu. Znak 0Dh je řídicí znak pro terminál, konkrétně CR – návrat kurzoru na začátek řádku. 0Ah je přechod na nová řádek. A protože znak přechodu na nový řádek je poslední, musí být jeho hodnota zvýšena o 80h (což je ekvivalent nastavení bitu 7)

Assembler ASM80 s těmito triky počítá, tak nabízí pseudoinstrukce .pstr, .cstr a .istr – příklad:

Všechny tři uloží do paměti řetězec HELLO WORLD, ale první ho uloží v „Pascal style“, tedy první byte bude délka a za ním znaky. Druhý ho uloží v „C style“ s nulou na konci. Třetí ho uloží v „inverted style“ – tedy poslední znak s nastaveným bitem 7.

Rubriky: ASM80.com, Hardware, Software | Štítky: , , , , | Komentáře nejsou povolené u textu s názvem Alpha: Sériové rozhraní

Alpha: První program

Nejjednodušší program bude obligátní „blikání LEDkou“. Po pravdě řečeno – zatím nemáme moc jiných způsobů, jak sepřesvědčit, že systém funguje, kromě zmíněného připojení rezistorů k datové sběrnici, simulace instrukce NOP a sledování změn na adresové sběrnici. Ale máme LED na výstupu SOD!

Zapojte tedy obě paměti k procesoru a zkusíme si naprogramovat první program. Bude to nějak takto:

A máme to, rachota skončila, můžeme pokračovat…

Vlastně ne, teď to teprve začne. Musíme tohle všechno naprogramovat v assembleru. Začneme inicializací.

Nejprve řekneme assembleru, že program bude začínat na adrese 0. Bývá dobrým zvykem si tento bod nějak pojmenovat – třeba návěštím RESET.

První instrukce je DI. Ta zakáže přerušení. Náš systém sice přerušení nepoužívá, ale patří k dobrému zvyku na začátku práce, než jsou nastavené všechny potřebné věci, zakázat přerušení. Kdyby nějaké přišlo dřív, než je nastavený například ukazatel zásobníku, systém by zhavaroval.

Další instrukce nastaví ukazatel zásobníku na konec paměti RAM. Ta u Alphy zabírá paměťový prostor 8000h – FFFFh. Takže nastavíme SP na hodnotu „o jedna vyšší než poslední volná adresa“ – tedy FFFFh+1 = 0000H. Instrukce LXI SP poslouží výborně.

Po této inicializaci máme procesor připravený na práci. Nemusíme inicializovat nic víc – ostatně v našem systému nic víc není. Můžeme tedy napsat tu smyčku:

Nejprve nastavujeme SOD na 1. K tomu slouží instrukce SIM. Připomeňme si: tato instrukce vezme hodnotu v registru A a podle ní nastaví SOD a masku přerušení (ta nás teď nezajímá). Pro nastavení musí být druhý nejvyšší bit (D6) roven 1. Pokud tomu tak je, procesor pošle hodnotu nejvyššího bitu (D7) na výstup SOD.

Následuje volání čekací smyčky. Tu zatím neřešíme, ta bude „někde, nějak, později“. Prostě jen skočíme na adresu,kde bude čekací rutina, a ta se pomocí instrukce RET zase vrátí zpátky.

Následuje analogicky nastavení SOD na hodnotu 0, opět volání čekací rutiny, a po ní skok zase na začátek celého procesu.

Tím je jádro programu hotové. Jak na tu čekací smyčku?

K čekání se mohou použít různé způsoby. Například instrukce NOP – zabere 4 takty, což u našeho systému představuje zhruba 2,17 mikrosekund. Pokud jich použijeme tisíc, bude to 2,17 milisekund, pokud sto tisíc, bude to 217 milisekund, tedy skoro čtvrt sekundy. To by šlo použít.

Teda, šlo, kdybychom mohli do paměti uložit sto tisíc instrukcí. Nemůžeme. 32768 je maximum. Co s tím?

Opět použijeme smyčku. Prázdnou, uvnitř se nebude dít nic. Jen budeme odečítat od zadané hodnoty k nule, a až dojdeme k té nule, smyčka skončí. Nějak takto:

Použijeme dvojici registrů D, E. Do ní si uložíme časovací konstantu, a pak budeme jen ve smyčce snižovat hodnotu DE o 1 a kontrolovat, jestli je výsledek 0. Pokud ano, tak skončíme, pokud ne, točíme se znovu.

Smyčka DLOOP začíná snížením hodnoty v dvojici registrů D a E – DCX D. Teď musíme zkontrolovat, jestli je výsledek 0. Bohužel (šestnáctibitová) instrukce DCX nenastaví příznak zero (to dělají jen instrukce osmibitové). Použije se opěttrik, totiž logický součet (OR) hodnot v registrech D a E. Výsledek bude 0, pokud D i E budou nulové. A protože nemáme takto obecnou instrukci, musíme si nejprve hodnotu z jednoho registru zkopírovat do akumulátoru a pakudělat OR s druhým registrem. Instrukce ORA podle výsledku nastaví příznak Z a my tedy můžeme podle toho skákat – instrukcí JNZ, což je vlastně JUMP if NOT ZERO.

A teď otázka za sto bodů: Jak dlouho ta smyčka bude probíhat? Jasně, záleží to na té konstantě a bude to přímo úměrné. Ale kolik to bude? Dalo by se to spočítat?

Inu, dalo. Vezměte si k ruce tabulku s instrukcemi a jejich trváním a napište si, kolik která instrukce zabere taktů:

Pokud bude konstanta = 1, proběhne tento cyklus přesně jednou. Zabere to tedy 10 + {6 + 4 + 4 + 7} + 10 = 41 T

Pokud bude konstanta = 2, proběhne tento cyklus takto:

10 + {6 + 4 + 4 + 10} + {6 + 4 + 4 + 7} + 10 = 65 T

Pokud bude konstanta = 3, poběží následujícím způsobem:

10 + {6 + 4 + 4 + 10} + {6 + 4 + 4 + 10} + {6 + 4 + 4 + 7} + 10 = 89 T

Je tedy vidět, že základní čekací doba je 41 T, a pokud zvýšíme konstantu o 1, zvýší to čekání o 24 T. Vzorec tedy je:

T = 41 + (N – 1) x 24

a z toho: N = (T – 41) / 24 + 1

Pokud bude konstanta rovna 100, bude čekání 41 + 99 x 24 = 2417 T.

Je to logické. První a poslední instrukce (LXI, RET) proběhnou vždy jen jednou (20T). Vnitřní smyčka jsou čtyři instrukce, a doba jejich provádění se liší podle toho, jestli už se dosáhlo nuly. Pokud ne, tak instrukce JNZ skáče a trvá 10T. Pokud ano, instrukce JNZ neskáče a trvá jen 7T. Průchod smyčkou tedy trvá 24T (6 + 4 + 4 + 10), pokud jde o poslední průchod, tak pouze 21T.

Vzorec můžeme samozřejmě zapsat jako T = 24 * N + 17

Co se stane, když bude konstanta rovna 0? No, hned první DCX D odečte jedničku od 0000h, operace přeteče a výsledek bude FFFFh. Smyčka se tedy vykoná nikoli nula krát, ale 65536x!

Kolik vlastně taktů potřebujeme takto „propálit“, aby bylo zpoždění třeba půl sekundy? Víme, že procesor pracuje s taktem 1,8432 MHz, to znamená, že za sekundu vykoná 1 843 200 taktů. Na půlsekundové zpoždění tedy potřebujeme polovinu, ergo 921600 taktů. Zanedbáme takty, které zabere volání podprogramu instrukcí CALL, časování není zde úplně kritické.

Magická konstanta N bude tedy:

N = (921600 – 41) / 24 + 1 = 38399 (zaokrouhleně)

A co kdybychom chtěli blikat ještě pomaleji, třeba se sekundovými čekacími smyčkami? No, je to prosté, použijeme dvojnásobnou konstan… aha! Dvojnásobná hodnota je 76798, a to se nám do registrů nevejde. Tak zavoláme půlsekundové čekání dvakrát!

Anebooo – co když do smyčky mezi DCX D a MOV naházíme několik NOPů? Třeba pět:

Pět NOPů, každý po 4T, to máme 20 T. O tuto hodnotu se zvýší čas nutný k průchodu smyčkou. Vzorec se tedy změní na:

T = 61 + (N – 1) x 44

Půlsekundové zpoždění s touto rutinou bude vyžadovat konstantu 20945, sekundové pak 41890. Platíme za to tím, že program zabere v paměti víc místa.

Všimli jste si drobné nevýhody celé rutiny? Pracuje s registry D, E a A. Co když ale v A jsou nějaké informace, které chceme zachovat?

Lze samozřejmě použít PUSH PSW a POP PSW, tedy uložit registr A a opět ho obnovit. A asi i rovnou uložit DE. Ale jsme v assembleru: neděláme nic, co není nutné!

Můžeme rozložit dekrement dvojice registrů D a E na dvě vnořené smyčky. V té vnitřní se bude dekrementovat hodnota v registru E, v té vnější hodnota v registru D. Díky tomu, že instrukce dekrementace osmibitového registru správně nastavuje příznaky, můžeme rovnou testovat, zda je výsledek operace 0:

Vzorec se trošku zesložití – zachována zůstane konstanta 20 T na první a poslední instrukci. Nejvnitřnější smyčka zabere 14 T / 11 T (pro E nulové): 14 x (E – 1) + 11

Vnější smyčka zabere (počet taktů vnitřní smyčky) + 14 T / 11 T pro D = 0. Nesmíme ale zapomenout na to, že hodnota E se uvažuje pouze při prvním průběhu, při dalších už je E = 256 (ve skutečnosti 0, ale ta se chová jako 256).Pokud je E=256, zabere vnitřní smyčka 3581 T.

Tedy:

(14 x (E – 1) + 11) + 11 (to je první průběh smyčkou E + hodnota pro poslední průběh smyčkou D) plus

(D – 1) x (14 + 3581) (průběh plnou smyčkou E + vlastní smyčka D)

T = 20 + 14 x (E – 1) + 11 + 11 + (D – 1) x (14 + 3581) = 42 + 14 x (E – 1) + 3595 x (D – 1)

Zásadní rozdíl proti předchozí verzi je, že registry D a E jsou dekrementovány nezávisle, takže pokud nastavíte hodnotu DE = 0001h, bude se to ve skutečnosti chovat, jako by v registru D byla hodnota 256. Nejnižší možná hodnota, při níž proběhne rutina lineárně bez jakýchkoli skoků je tedy 0101h. Pak zabere rovných 42 T. Pokud bude hodnota 0000h, bude to jako D=256 a E=256, tedy provedení bude trvat 920337 T. Což je o něco méně než půl sekundy…

Překlad a spuštění

Program máme napsaný, teď nastal čas ho přeložit. Spusťte si ASM80 (https://www.asm80.com) a kliknutím na New file založte nový soubor. Do něj napište výše uvedené příkazy. Uložte jej pod názvem test.a80 – přípona .a80 je důležitá, podle ní překladač pozná, že jde o program pro procesor 8080/8085). Klikněte na Compile.

V seznamu souborů vlevo se objeví dva nové soubory: test.a80.lst a test.a80.hex. První je výpis programu včetně operačních kódů a umístění v paměti, takzvaný listing:

Druhý (HEX) je kód, určený k naprogramování paměti. Stáhněte si jej (pravý klik na název, Download) a použijte k nahrání do paměti EEPROM. Konkrétní postup se liší podle zvoleného programátoru.

Paměť zapojte zpátky do systému a zapněte napájení. Pokud jste neudělali při zapojení nikde chybu, měla by dioda po chvilce blikat s frekvencí 1 Hz. Úvodní prodleva je dána velikostí RC článku na vstupu RESET.

Funguje? Gratuluji, právě jste si postavili vlastníma rukama osmibitový počítač a naprogramovali ho!

Námět na cvičení: Tato úloha by šla přepsat tak, aby nevyžadovala paměť RAM. Konstrukci tak můžete oživit jen s třemi IO: procesor, adresový latch a paměť ROM. Stačí místo volání podprogramu (CALL) zkopírovat čekací rutinu na dané místo. Dvakrát.

Rubriky: ASM80.com, Hardware, Software | Štítky: , , , | 1 komentář

Alpha: paměť

Samotný procesorový obvod, jak jsme si ho navrhli v minulé kapitole, k ničemu není. Respektive – můžete ho zapojit,připojit datovou sběrnici přes rezistory (třeba 10k) na zem a sledovat, jak se na nejvyšším bitu adresy (A15) mění 1 a 0, protože procesor stále dokola čte celou paměť od 0000 do FFFFh, všude najde operační kód 00 (to jsou ty rezistory připojené k zemi), ten znamená „nedělej nic a načti další instrukci“, takže se obsah registru PC (Program Counter) zvýší o 1 a celý cyklus se opakuje. Když si k A15 připojíte LEDku přes rezistor, měla by bliknout cca 7x za sekundu. To znamená, že celý paměťový rozsah zvládne na dané frekvenci projít procesor za sekundu sedmkrát.

Právě jste stvořili úžasný 16bitový čítač. Ale to asi nebude to, co chceme. Musíme zajistit, aby procesor měl covykonávat. Musíme mu dát paměť, kde bude program a data.

Procesor po spuštění nemá žádný mechanismus, jak třeba vzít program odněkud odjinud a nahrát ho do paměti. O tose musíte postarat sami. A nejčastější způsob je ten, že použijete paměť ROM (spíš EPROM či EEPROM / FLASH), vníž je uložený nějaký základní ovládací program.

Tím programem byl nejdřív takzvaný bootstrap, tedy krátký program (512 byte třeba), který dokázal načíst datatřeba z pásky, ze čtečky karet, z pevného disku, zkrátka odněkud, nahrát je do paměti a spustit. S podobnýmpostupem se můžeme setkat třeba u Arduina: zde je v procesoru uložený bootstrap loader, který čeká, jestlináhodou počítač neposílá nějaká (přesně daná) data. Pokud ano, přepne se do programovacího módu a nahrajepřicházející data do paměti.

Později se z bootstrapu stal Monitor. Monitor byl už o něco větší program, který už komunikoval s obsluhou a uměl provést jednoduché příkazy, např. pro prohlížení paměti, její změnu, načtení programu z externích pamětí a jeho spuštění. Pokud pamatujete na počítač PMD-85 v první verzi, tak se po zapnutí ohlásil právě monitor. Vy jste pomocí MGLD mohli nahrát do paměti něco z magnetofonu, spustit to pomocí JUMP, nebo z externího rompacku stáhnout a spustit BASIC G

U některých počítačů, většinou domácích, už se monitor ani nepoužíval, už startoval rovnou vyšší jazyk (BASIC).

Profesionální počítače, určené třeba pro práci s CP/M, se zase pomalu vrátily k malým obslužným programům. Neříkalo se jim bootstrap, na to byly příliš velké, a ani Monitor, protože nekomunikovaly s obsluhou. Ujala se zkratka BIOS podle jedné ze základních částí CP/M (Basic Input Output System). BIOS je spíš kolekce rutin aprogramů, která ovládá hardware konkrétního počítače. Systém nemusí řešit, kde přesně a jak je připojen disk, to ví právě rutina v BIOSu. Po startu se spustí CP/M loader právě z BIOSu.

U jednodeskových počítačů se používal model „Monitor“. Takový monitor se vešel i do 1 kB ROM. K tomu nabídl jednodeskáč třeba 1 kB RAM, a bylo!

Chtěl jsem dodržet ducha doby, ale na rovinu přiznávám, že tehdejší paměti, třeba 2kB EPROM a 1 kB SRAM, jsou už dnes dílem nesehnatelné, dílem sice sehnatelné, ale zato se s nimi mizerně pracuje… Opravdu vás nechci nutit shánět ultrafialovou mazačku EPROM!

Proto nepoužijeme EPROM, použijeme EEPROM, tu můžeme vymazat jednodušeji. I naprogramovat…

Budič sběrnice

Ale ještě předtím by bylo fajn udělat jednu úpravu. Totiž posílit a oddělit datovou sběrnici. Procesory obecně nemají příliš silné výstupní obvody, a když na datovou sběrnici připojíte víc obvodů, přetížíte ji. Se dvěma paměťovými obvody, obvodem ACIA a bufferem na adresu budeme už na hraně. Proto před tím, než budeme cokoli přidávat, připojíme posilovač.

Mimochodem: Pravidlo pro nízkou spotřebu a malé zatížení sběrnice zní: Používat CMOS kde to jde. Vyhněte seobvodům TTL (74, 74LS, 74ALS apod.) a hledejte CMOS verze (74HC, 74HCT, 74ACT). Totéž platí i pro periferní obvody – například dále probíraný obvod PIO 8255 lze sehnat i v CMOS verzi 82C55, která má nižší spotřebu a téměř nezatěžuje sběrnici. CMOS verze bývají většinou plně kompatibilní se svojí předlohou, občas bývají mírně vylepšené…

Použijeme obvod 74HCT245, což je osmice obousměrných bufferů a budičů. Vstupem DIR se určuje směr toku dat (0= z B do A, 1= z A do B), vstupem G se přepíná obvod do stavu vysoké impedance (pokud je vstup G=1, je obvod odpojen a výstupy A i B ve stavu vysoké impedance).

Spojil jsem vstup G se signálem ALE, díky tomu je ve chvíli, kdy procesor na sběrnici posílá spodní část adresy, obvod odpojen a neruší. Takže kdyby nějaký periferní obvod chtěl posílat data ve chvíli, kdy procesor řeší latchování nižší části adresy (ALE=1), je datová sběrnice oddělená.

Díky tomuto zapojení jsou k datové sběrnici připojeny maximálně dva obvody, a díky signálu ALE jsou zapojeny „proti sobě“, tedy vždy je aktivní jen jeden z nich. Celá „procesorová“ část vypadá tedy takto:

(EEP)ROM

Já vím, není to nic úplně jednoduchého, co by se vám válelo doma, ale doporučuji buď koupit programátor pamětí EEPROM, nebo si ho postavit z Arduino MEGA. Není potřeba vymýšlet kolo, návody už existují a většinou stačí jen propojit vývody z MEGY s vývody paměti: http://danceswithferrets.org/geekblog/?page_id=903 – já to dělám zrovna tak, použiju nepájivé kontaktní pole, to propojím s Arduinem Mega, do pole pak zasouvám paměti a programuju jako po másle.

Použijeme EEPROM o velikosti 32 kB. Tyto paměti se vyrábějí pod označením 28C256 (podle výrobce např.AT28C256). Jsou dobře dostupné a mají i vhodné pouzdro DIP.

Datové vývody D0-D7 není třeba představovat. A0 až A14 je naše známá sběrnice s adresou (15 bitů = 32 kB) a tři signály slouží k ovládání paměti. /WE povoluje zápis (my ho v systému připojíme natvrdo k log. 1 a tím zápis zakážeme – paměť naprogramujeme v programátoru.) /CE (Chip Enable) říká paměti, že má reagovat na pokyny -pokud je 0, paměť reaguje, pokud 1, paměť se odpojí. A konečně /OE (Output Enable) povoluje čtení z paměti, tzn. žena výstupech IO0-IO7 je vystavena hodnota, uložená v paměti na adrese dané adresovými vstupy.

No jo, ale co když budeme potřebovat třeba jen 8 kB ROM? V takovém případě zkrátka připojíte vstupy A13 a A14 na log. 0 (zem), a v paměti budou tři čtvrtiny prostoru nevyužité. Takový způsob zapojení se někdy používá i záměrně – v jedné paměti máte např. čtyři alternativní firmwary, a buď pomocí mechanických přepínačů, nebo pomocí nějaké vnitřní logiky, si můžete volit, který firmware chcete použít. (I některé počítače to tak měly – vzpomínáte na ZXSpectrum 128 a jeho dva BASICy?)

RAM

Paměť RAM použijeme typu 62256. Její vývody jsou rozložené takto:

Letmým pohledem zjistíme, že jsou obě paměti zapojeny naprosto stejně! Až na určité rozdíly ve značení. Místo /CE(Chip Enable) je signál /CS (Chip Select), ale význam je stejný.

Paměťový subsystém a adresace

Máme tedy dva kusy paměti, každý s velikostí 32 kB, a jeden procesor s adresním prostorem 64 kB. Úplně se nabízí rozdělit dostupný prostor na dvě poloviny, jedna bude od 0 do 32767, druhá od 32768 do 65535, v jedné bude ROM, ve druhé RAM. Otázka pro bystré hlavy: Kde bude která paměť?

Odpověď se skrývá v předchozích odstavcích: procesor po RESETU začne provádět program od adresy 0000h, takže na téhle adrese by měla být ROM. Ergo ROM bude na adresách 0000h – 7FFFh, RAM na adresách 8000h – FFFFh.

A teď: jak budeme připojovat? Oba obvody připojíme naprosto stejně: datovou sběrnici na datovou sběrnici procesoru, adresovací signály A0 až A14 na odpovídající vývody procesoru. Vývod A15 z procesoru necháme zatím stranou, ten použijeme později.

Signál /OE (Output Enable) připojíme na signál /RD. Připomeňme si: Signálem /RD říká procesor, že bude číst. Vstup/OE u paměti slouží k tomu, že povolí výstup uložených informací na datovou sběrnici. To je vlastně přesně to, co potřebujeme: když chce procesor číst, pošle signál /RD, a ten „otevře“ výstup naší paměti.

Analogicky připojíme vstup /WE (Write Enable) u paměti RAM k signálu /WR u procesoru. Jen u RAM, u EEPROM ne. Asi nechceme, aby náhodná chyba v programu přepisovala obsah paměti EEPROM…

Poslední vstup, který zbývá, je Chip Select (/CS, u RAM značen jako /CE, ale funkce je stejná). To je „univerzální povolovací vstup“. Pokud je neaktivní (log. 1), tak paměť ignoruje vše, co se na ostatních vývodech děje. Pokud je aktivní (log. 0), vykonává operace čtení a zápisu podle výše popsaných signálů.

Protože jsme spojili paralelně datové výstupy obou pamětí, bylo by fajn nějak zajistit, aby v jeden okamžik posílala svoje informace jen jedna paměť. Která? No to záleží na stavu vodiče A15.

Vodič A15 je v log. 0 tehdy, když procesor přistupuje na adresy 0000h – 7FFFH, v log. 1 pokud přistupuje na horní polovinu prostoru. Pokud je tedy A15 = 0, měla by být vybrána paměť EEPROM, pokud je A15 = 1, měla by být vybrána paměť RAM.

Ovšem ne vždy! Jen tehdy, když procesor přistupuje k paměti! Vzpomeňte si – k tomu slouží signál IO/M. Pokud procesor chce přistupovat k paměti, je tento signál v log. 0.

Tedy shrnuto:

Stav /CE …pokud je
/CE u paměti EEPROM (/ROMCS) aktivní (0) A15 = 0 a zároveň IO/M = 0
/CE u paměti RAM (/RAMCS) aktivní (0) A15 = 1 a zároveň IO/M = 0

Pro paměť EEPROM jde tedy o logickou funkci A15 OR IO/M, pro paměť RAM to je (NOT A15) OR IO/M. Abychom zbytečně nepoužívali hradla OR a NOT, použijeme jedno pouzdro 74HCT00 – tedy 4 x NAND, a to takto:

/ROMCS = (NOT A15) NAND (NOT IO/M)

/RAMCS = A15 NAND (NOT IO/M)

Jedno hradlo bude invertovat IO/M, druhé bude invertovat A15, třetí vytvoří signál /ROMCS, čtvrté /RAMCS.

A máme to! Kompletní schéma je zde:

Můžete si zkusit vytvořit první program, nahrát si ho do EEPROM a nechat blikat LEDku na výstupu SOD.

Rubriky: Hardware | Štítky: , , , , | 2 komentáře

Alpha: Koncepce počítače s procesorem 8080/8085

Připravuju pokračování své knihy Hradla, volty, jednočipy. Tentokrát se budu zabývat konstrukcí osmibitových počítačů. Kniha by měla vyjít v roce 2019 opět v Edici CZ.NIC.

Když jsem přemýšlel o tom, jak knihu pojmout, bylo mi jasné, že suchý výklad nebude stačit. Tedy, on by stačil, ale já nejsem zrovna příznivcem teoretických učebnic bez přesahu do praxe. Bylo mi tedy jasné, že nějakou konstrukci chci.

Ano, můžu vzít nějaký reálný osmibit a ukazovat na něm, jak se věci mají, možná čtenáře i ponouknout ke stavbě repliky, ale touto cestou se mi moc jít nechtělo. Říkám si, že na vlastní konstrukci, která bude tak jednoduchá, jak jen to lze, půjde ilustrovat požadované věci mnohem líp.

Zvolil jsem tedy cestu konstrukce naprosto jednoduchých počítačů, které mají splňovat několik bodů:

  1. Budou používat součástky, které se dají běžně koupit.
  2.  Nebudou se ortodoxně držet konstrukcí z 80. let – tedy když chci použít paměť, použiju moderní, třeba 128x8bit statickou RAM, což je jeden čip, a nebudu konstruovat zapojení z osmi čipů dynamické RAM a dalších tří IO kolem dokola.
  3. Budou v duchu starých osmibitových časů, tedy jednoduché periferie – klávesnice, displej, reproduktor – a minimální softwarové vybavení.
  4. Bude jednoduché psát pro ně software.
  5. Klidně vynechám samotný starý procesor a potřebné funkce si naemuluju v moderním jednočipu. Nebo použiju jednočip místo periferií. No stress.

Takže jsem sednul a připravil několik konstrukcí, které jsou vhodné i pro začátečníky a na kterých se dají vysvětlit principy stavby systémů s osmibitovými mikroprocesory.

Teď vám nabízím první konstrukci a jako ukázku postupně vydám několik zkrácených kapitol z rukopisu. A pokud se chcete předzásobit, tak se mrkněte na seznam součástek pro stavbu.

Koncepce počítače s procesorem 8080/8085

K tomu, abyste si postavili počítač, není potřeba nic moc extra. Stačí vám jen nepájivé kontaktní pole, propojovací vodiče, napájecí zařízení a pár součástek: procesor, paměť a nějaké periferie.

Ovšem budu upřímný: v případě procesoru 8080 to tak moc neplatí. Tedy ne že by to nešlo, samozřejmě že to jde, ale problém je v tom, že procesor 8080 vyžaduje tři napájecí napětí a také nějaké podpůrné obvody.

Z různých technologických důvodů nemá procesor 8080 na čipu integrované některé důležité součásti, především řízení sběrnice a generování hodinových pulsů. Slouží k tomu dvojice externích obvodů 8224 a 8228, a ačkoli je možné se bez nich obejít a postavit si vlastní alternativy, tak takový postup nedoporučuju.

Obvod 8224 slouží ke generování hodinového kmitočtu, ve správné fázi a se správnými poměry period, a k tomu synchronizuje RESET a některé další signály. Obvod bere připojený kmitočet a dělí ho devíti. To je pak pracovní kmitočet procesoru. Pokud má připojený generátor frekvenci 18 MHz, bude 8080 pracovat na frekvenci 2 MHz.

Obvod 8228 generuje z takzvaného stavového slova, které procesor posílá po datové sběrnici, a několika řídicích signálů plné řídicí signály /MEMR, /MEMW, /IOR a /IOW. Navíc dokáže fungovat jako jednoduchý řadič přerušení – má pouze jednu úroveň a při vzniku požadavku pošle na sběrnici instrukci RST 7 (tedy skok na adresu 0038h, jak si povíme později).

Teprve až tato svatá trojice, jak se těmto třem obvodům někdy přezdívá, tvoří samotný „mikroprocesor 8080“.

V tom nejjednodušším systému, kde není zapotřebí řešit přerušení ani pozastavování činnosti či přebírání sběrnice, stačí nepoužité vstupy HOLD a INT připojit na log. 0, vstup RDYIN na log. 1 a výstupy INTE, WAIT, HLDA a INTA ignorovat. Celý procesor pak komunikuje se zbytkem systému pomocí čtyř řídicích signálů /MEMR, /MEMW, /IOR a /IOW, které říkají, že procesor chce číst z paměti (MEMory Read), zapisovat do paměti (MEMory Write), popřípadě číst nebo zapisovat z/do vstupně-výstupních obvodů (Input/Output Read, Input/Output Write).

Vlastní počítač? Jak by mohl vypadat?

Ačkoli byl 8080 široce používaná „klasika“, pro novou konstrukci bych ho nedoporučil – minimálně kvůli třem napájecím napětím. Sáhl bych po lehce rychlejším a vylepšeném procesoru 8085, respektive jeho CMOS verzi 80C85 (vyrábělo hned několik výrobců). Procesor 8085 si vystačí s pouhým jedním napájecím napětím (standardních +5 voltů) a nepotřebuje speciální obvody pro generování hodin (stačí mu obyčejný hodinový puls, nebo dokonce jen připojit krystal s kondenzátory). Navíc má dva vývody pro sériový vstup a výstup a celkem pět přerušovacích vstupů – kromě INTR ještě vstup TRAP (nemaskovatelné přerušení) a tři vstupy RST (RST5.5, RST6.5 a RST7.5).

Ani 8085 nedokáže pracovat úplně bez vnějších obvodů: návrháři totiž kvůli nutnosti vejít se do pouzdra se 40 vývody sáhli k takzvanému multiplexovanému adresování. Procesor má vyvedených osm vyšších bitů adresy (A8-A15) a nižších 8 bitů se vede po datové sběrnici (vývody AD0-AD7). Adresu posílá procesor nadvakrát. K řízení slouží signál ALE (Address Latch Enable). Pokud je v log. 1, znamená to, že procesor posílá po AD0-AD7 dolních 8 bitů adresy. Pokud je v log. 0, fungují tyto vývody jako datová sběrnice.

Návrhář systému proto musí zajistit vnější obvod (osmibitový latch), který se postará o to, aby zachytil spodních 8 bitů adresy. Typicky lze použít třeba obvod 74573 (starší konstrukce používaly např. dva obvody 7475).

Vývody 8085

Vnitřní struktura 8085

Na první pohled se od 8080A moc neliší – i 8085 má sadu registrů B, C, D, E, H, L, akumulátor A, Stack pointer SP, programový čítač PC, ALU, řídicí obvody, řadič… Navíc proti 8080 je rozšířena část řízení přerušení (o vstupy RST a TRAP), část sériového výstupu (SID, SOD) a zabudovaný generátor hodin.

Dole je vidět zmíněné rozdělení adresní sběrnice na dvě části – samostatných 8 horních bitů A15-A8, a multiplex pro spodních 8 bitů adresy / 8 bitů dat (AD7-AD0).

Řídicí signály mají následující funkce:

Signál Funkce
A8-A15 (výstup, třístavový) Horní část adresy. Během stavů HOLD, HALT a při RESETu je ve stavu vysoké impedance
AD0-AD7 (vstup/výstup, třístavový) Nižších osm bitů adresy, popřípadě satová sběrnice
ALE (výstup) Address Latch Enable. Oznamuje, že na vývodech AD0-AD7 je nižší část adresy (1). Pokud je 0, znamená to, že AD0-AD7 funguje jako datová sběrnice
S0, S1 (výstupy) Stavová informace. Spolu se signálem IO/M říká, jestli procesor čte instrukci, jestli čte / zapisuje data do paměti, jestli komunikuje s periferií, jestli obsluhuje přerušení nebo že je zastaven. V jednoduchých konstrukcích se nepoužívají.
IO/M (výstup) Oznamuje, jestli procesor hodlá komunikovat s pamětí (0), nebo s periferiemi (1)
/RD (výstup, třístavový) Pokud je 0, procesor čte data z vnějšího zařízení (paměti, portu). Vnější zařízení musí požadovaná data poslat na datovou sběrnici.
/WR (výstup, třístavový) Pokud je 0, procesor chce zapsat data, co poslal na datovou sběrnici, do portu nebo do paměti.
READY (vstup) V dobách, kdy paměti a periferie byly pomalejší než procesor, mohly poslat během cyklu čtení nebo zápisu signál „počkej, než budou data připravena“. Slouží k tomu právě vstup READY. Pokud je 1, procesor jede na plný výkon. Pokud je 0, procesor po nastavení signálu /RD či /WR počká, dokud nebude READY zase 1, pak teprve pokračuje dál. My ho klidně připojíme na 1 a budeme věřit, že moderní paměti jsou dost rychlé…
HOLD (vstup) Normálně 0. Pokud je nastaven na 1, procesor dokončí nejnutnější operaci (cyklus čtení nebo zápisu) a odpojí svoji datovou sběrnici, adresní sběrnici a signály /RD, /WR a IO/M. Odpojením mám na mysli přepnutí do stavu Z (vysoké impedance). Jakmile je procesor odpojen, potvrdí, že je vše hotovo, signálem HLDA. Jednoduché systémy tento signál nepoužívají, můžete jej připojit na log. 0
HLDA (výstup) Za normálního provozu 0. Pokud byl dán požadavek HOLD, tak se po dokončení nezbytných operacáí a odpojení sběrnic tento signál nastaví do log. 1.
INTR (vstup) Interrupt request, tedy Požadavek na přerušení. Procesor testuje stav tohoto signálu na konci každé instrukce a také ve stavu HALT (po instrukci HLT) a HOLD. Pokud je 0, nic se neděje, pokud je 1, začne proces obsluhy přerušení. Procesor přečte z datové sběrnice hodnotu a považuje ji za instrukci, kterou vykoná. Nejčastěji se posílají jednobytové instrukce RST, ale je možné poslat i tříbytovou instrukci CALL. O poslání instrukce se musí postarat vnější obvody, takzvané řadiče přerušení. Programem je možné zakázat vyvolání přerušení tímto signálem.
/INTA (výstup) Interrupt Acknowledge. Po příchodu požadavku přerušení INTR použije procesor výstup /INTA k načtení výše zmíněné instrukce (namísto signálu /RD)
RST5.5, RST 6.5, RST 7.5 (vstupy) Přímé vstupy přerušení. Fungují podobně jako signál INTR, ale nevyžadují celý ten opruz s načítáním instrukce pomocí /INTA. Místo toho si samy interně zařídí skok na patřičná místa. Stejně jako INTR dokážou „probudit“ procesor ze stavu HALT a HOLD. Programátor může tyto signály ignorovat pomocí speciální instrukce („maskování přerušení“)
TRAP (vstup) TRAP je podobný signálům RST x.5 s tím rozdílem, že toto přerušení nemůže programátor zamaskovat.
/RESET IN (vstup, Schmitt KO) Vstup nulování. Po startu systému nebo při havárii by měly vnější obvody tento signál, který je normálně v log. 1, přepnout do log. 0. Tím započne interní proces inicializace: procesor odpojí sběrnice, nastaví programový čítač na adresu 0000h, ukončí všechny případné čekací cykly a začne pracovat „od začátku“. Tento vstup je vybavený Schmittovým klopným obvodem, to znamená, že je možné k němu připojit přímo oblíbený obvod s rezistorem a kondenzátorem, který se postará o RESET při zapnutí napájecího napětí.
RESET OUT (výstup) Indikuje, že je procesor ve stavu RESET. Tento signál je synchronizovaný s hodinami a můžete ho použít jako systémový RESET pro zbytek systému.
X1, X2 (vstupy) Slouží k připojení hodinového krystalu. Jeho frekvence je interně vydělena dvěmi a výsledek dává systémový takt. Vstup X1 může být použit i jako vstup hodinového signálu z externího obvodu.
CLK (výstup) Systémové hodiny. Jejich frekvence je poloviční proti frekvenci na vstupu X1 (tedy třeba proti frekvenci připojeného krystalu)
SID (vstup) Sériový vstup. Hodnota na tomto vývodu je načtena do nejvyššího bitu akumulátoru pomocí instrukce RIM.
SOD (výstup) Sériový výstup. Hodnota na tomto vývodu je nastavena nebo nulována pomocí instrukce SIM.
Vcc Napájecí napětí. Nominálně 5 voltů, u CMOS verze může být někde mezi 3V a 6V.
GND Zem

V datasheetu (je jich spousta různých od různých výrobců, já bych doporučil datasheet od OKI, jejich čip nesl název MSM80C85AH) najdete i velmi důležitý graf, který ukazuje průběhy signálů na sběrnici. Podívejme se na něj spolu:

První řádek ukazuje hodinový signál. M1 je první strojový cyklus, T1 až T4 jsou jeho hodinové takty. Při vyzvedávání instrukce tedy procesor řídí výstupy takto:

  • T1: Nastaví horní část adresy instrukce na výstupy A8-A15, dolní část na výstupy AD0-AD7, a zároveň aktivuje signál ALE (Address Latch Enable). Tento signál řídí už zmíněný buffer mimo procesor, jehož úkolem je zapamatovat si právě spodní část adresy. Zároveň nastavuje signál IO/M do hodnoty 0, tedy „komunikace s pamětí“. Signály /RD a /WR jsou neaktivní, stavové signály nás nemusí zajímat. Se sestupnou hranou hodin v čase T1 se deaktivuje signál ALE a dolní část adresy zůstává zachycena v bufferu.
  • T2: Procesor přepíná signály AD0-AD7 na vstup dat a aktivuje signál /RD, což informuje okolní systém, že procesor hodlá číst (/RD) z paměti (IO/M je v log. 0). Paměť je připojena ke sběrnici a vybrána adresa.
  • T3: S náběžnou hranou hodin přečte procesor stav na datové sběrnici a začne jej vyhodnocovat coby instrukci. Poté deaktivuje signál /RD, takže se paměť může opět odpojit.
  • T4: Procesor dekóduje instrukci.

Dejme tomu, že instrukce potřebuje jeden osmibitový parametr. Ten je uložen, jak bývá zvykem, na následující adrese. Následuje tedy strojový cyklus M2, během něhož jsou čtena data z paměti. Když se podíváte zase na schéma, vidíte, že je téměř totožný s cyklem M1, až na to, že trvá pouhé tři takty – odpadá „dekódovací“ takt.

Přerušení

Pokud v systému nastane nějaká událost, která vyžaduje, aby se jí procesor bezodkladně věnoval (propukne požár, uživatel stiskne tlačítko, přijdou nová data, …), vyvolá takzvané přerušení. U 8085 k tomu slouží hned tři mechanismy.

První je identický jako u procesoru 8080 – vnější zařízení nastaví signál INTR, procesor si přečte z řadiče přerušení jednu instrukci a vykoná ji. Nepřekvapivě jde o instrukce skoku do podprogramu (pro programátory, zvyklé na vyšší jazyky: něco jako vyvolání handleru, volání funkce atd.) O správné poslání instrukce se musí postarat vnější obvody, většinou specializované obvody, nazývané řadiče přerušení.

U 8080 šlo tuto složitost zjednodušit pomocí obvodu 8228 – připojením jednoho z vývodů (INTA) přes rezistor 1K k napětí 12 voltů se z tohoto obvodu stal jednoduchý „řadič přerušení“, který po příchodu požadavku na přerušení poslal na sběrnici hodnotu FFh, což je hodnota, kterou si procesor dekóduje jako instrukci RST 7. (RST 7 uloží aktuální adresu na zásobník a udělá odskok na adresu 0038h, ale o tom víc později). 8085 tuto vymoženost nemá, takže buď použijete řadič přerušení, nebo si vystačíte s interními vstupy RSTx a TRAP.

Druhý způsob je použití vstupů RSTx. Jejich funkce je podobná té, co jsem popisoval u obvodu 8228 o odstavec výš – vygenerují si skokovou instrukci samy. Ono to není tak úplně doslova, protože mechanismus je lehce jiný, ale princip je stejný.

Vstupy RST 5.5 a RST 6.5 (asi klidně můžeme říkat pět a půl a šest a půl) jsou, podobně jako vstup INTR, pravidelně kontrolovány, a jsou-li ve stavu 1, procesor vyvolá přerušení.

Vstup RST 7.5 má, na rozdíl od předchozích, zabudovaný vnitřní klopný obvod, který reaguje na vzestupnou hranu. Výhoda je, že stačí jen krátký signál a procesor si jej inteně „podrží“ až do doby, kdy testuje přerušovací vstupy.

Třetí způsob je signál TRAP. Všechny předchozí způsoby přerušení může programátor zablokovat, „zamaskovat“ pomocí instrukce DI (Disable Interrupt) a povolit pomocí EI (Enable Interrupt). Pokud jsou přerušení zakázána (DI), procesor signály INTR a RST ignoruje. TRAP je výjimka, tento signál vyvolá přerušení i tehdy, když jsou zakázána. Proto se mu také říká nemaskovatelné přerušení.

Co se stane, když přijde naráz víc požadavků na přerušení? Procesor má zabudovaný jednoduchý mechanismus priorit, viz následující tabulka, a vykoná obslužnou rutinu pro požadavek s nejvyšší prioritou.

Signál Priorita Adresa, kde je uložena obslužná rutina Vyvoláno pomocí…
TRAP Nejvyšší (1) 0024h Vzestupná hrana nebo log. 1 během testování
RST 7.5 2 003Ch Vzestupná hrana (pozdržená)
RST 6.5 3 0034h Log. 1 během testování
RST 5.5 4 002Ch Log. 1 během testování
INTR Nejnižší (5) Podle poslané instrukce Log. 1 během testování

K dalšímu čtení

http://saundby.com/electronics/8085/

http://www.nostalcomp.cz/cvicny8080.php

Zapojení procesoru 8085

Takto bude vypadat srdce celého počítače. Dovolte jen pár poznámek:

V roli adresového bufferu je obvod IC2 typu 74573 (ať už ve verzi HC, HCT nebo ALS). Funkčně je shodný s obvodem 74373, až na jeden rozdíl: 373 má vývody přeházené, 573 má hezky všechny vstupy na jedné straně pouzdra a výstupy na druhé. Hodinový vstup je připojen na vývod ALE, povolovací vstup OE jsem připojil natvrdo k zemi. Mohl bych ho připojit na vývod HLDA a zajistit tak odpojení adresní sběrnice ve stavu HOLD, ale tento stav nebude náš počítač používat.

Nebudeme používat ani HOLD, ani READY, ani přerušení, proto jsou tyto vstupy připojeny na neutrální úroveň (READY je 1 – stále připraveno, HOLD a přerušení na 0). Z výstupů jsem nepoužil stavové S0, S1, výstup RESET OUT, a logicky ani HLDA a INTA. Stejně tak nezapojené zůstalo i sériové rozhraní – vstup SID je připojen k zemi, výstup SOD je volný. Můžete si k němu připojit LEDku přes rezistor a zkoušet si třeba bliknout…

Vlevo od procesoru jsou dva obvody. Níž je generátor hodinových pulsů s krystalem a dvěma kondenzátory. Krystal jsem zvolil o frekvenci 3,6864 MHz. Proč? Proč ne 4 nebo, cojávím, 27?

Zaprvé – frekvence nesmí být nižší než 1 MHz. Píšou to v datasheetu. Zadruhé – neměla by být vyšší než 10 MHz. To tam taky píšou. Ideální je někde okolo 4 MHz, protože procesor pak běží na příjemně pomalé frekvenci okolo 2 MHz, tedy zhruba tak, jak běžela originální 8080A.

Proč ale 3,6864 MHz? No protože pak bude procesor běžet na frekvenci 1,8432 MHz, tedy na poloviční.

Dobře, ale proč ne třeba 4 MHz?

No protože 1843200 Hz / 96 = 19200 a 1843200 Hz / 192 = 9600. Už svítá? Správně, 19200 a 9600 jsou standardní frekvence pro sériovou komunikaci. Z frekvence 1,8432 MHz je odvodíme bez problémů pomocí dělení celým číslem. Kdybychom chtěli tyto frekvence získat třeba z 4 MHz, museli bychom hodiny dělit koeficientem např. 208,3333 nebo 416,6666, a v přenosu by byly chyby. Takže tady raději oželím trochu výkonu, když vím, že mi to usnadní další zapojování.

A poslední věc: kondenzátory u krystalu! Jsou důležité k tomu, aby krystal kmital na správné frekvenci. Jejich kapacitu můžete buď spočítat, nebo vyčíst z datasheetu. Já z datasheetu vyčetl 56 pF, což se mi tedy zdálo jako obrovská kapacita. Nasadil jsem 33 pF, a i to bylo moc. Nakonec jsem nechal jen jeden kondenzátor 33 pF u vstupu X2. Pak se ukázalo, že 56 pF bylo z datasheetu CMOS verze a já měl použitou NMOS, kde se doporučují při těchto frekvencích kapacity okolo 7 pF.

Nad generátorem hodin je obvod pro /RESET. Pomocí kondenzátoru k zemi a rezistoru k napájecímu napětí je po zapnutí napájení na vstupu /RESET IN logická 0, dokud se kondenzátor pomalu nenabije. Vhodný poměr odporu a kapacity si můžete buď spočítat, nebo experimentálně vyzkoušet. Myslím, že rezistorem 10K a kondenzátorem 10M nic nezkazíte. Dejte systému trochu času na start, protože po zapnutí napájení ještě chvíli napětí kolísá. Díky tomuto triku je v tu dobu procesor stále ve stavu RESET, a když nastartuje, je napětí už ustálené.

Ještě víc vlevo je tlačítko, které připojuje vstup na zem. Je to magické tlačítko RESET, které náš počítač přivede k rozumu, pokud se náhodou někdy zapomene a skončí třeba v nekonečné smyčce. Díky kondenzátoru jsou odfiltrované i zákmity…

Procesor tedy máme pořešený. S okolním světem komunikuje pomocí adresní sběrnice, datové sběrnice, signálů IO/M, /RD, /WR a hodinového signálu CLK. To je opravdu všechno, víc není pro jednoduchý počítač potřeba.

Rubriky: Hardware | Štítky: , | Napsat komentář

Alpha: Seznam součástek

Níže najdete seznam součástek pro stavbu počítače Alpha. Integrované obvody seženete nejlépe na eBay nebo AliExpressu. Ty menší (74xx) i v ČR. Postupně začnu uveřejňovat návod na stavbu, tak si včas objednejte…

Kromě integrovaných obvodů budete potřebovat i pár diskrétních součástek.

Kondenzátory

2x 6,8pF keramický

1x 4M7 elektrolytický

10x 100nF keramický (filtrační k napájení)

Diody

1x 1N4004 nebo jiná „obyčejná“

1x LED

Rezistory

2x 330R

1x 10k

CPU

Rychlý klon 8085, třeba Mitsubishi M5L8085AP, ale nejlépe MSM80C85AHRS – CMOS verze. K němu krystal 3.6864 MHz

RAM

32k x 8 statická RAM typu 62256, výrobce např. Hitachi

EEPROM

Klasická Atmel 32kx8

Sériové rozhraní

MC68B50. Pokud neseženete verzi B, mohla by stačit i prostá MC6850

Logické obvody

Latch 74573, budič 74245 a NAND 7400. Všechno v HC/HCT/AC/ACT verzích

Volitelné

Paralelní rozhraní

Obvod 8255 v CMOS verzi, takže 82C55AP (vyrábí třeba NEC). K tomu jeden logický 74138, opět verze HC/HCT/AC/ACT

Rubriky: Hardware | Štítky: , , | Komentáře nejsou povolené u textu s názvem Alpha: Seznam součástek

Oživení

Před časem jsem na Facebooku a Twitteru napsal, že připravuju druhou knihu, tentokrát o stavbě osmibitových počítačů, a ptal jsem se jich, jaký procesor by je nejvíc zajímal. Dal jsem na výběr osvědčené kousky: Zilog Z80, MOS 6502, Motorolu 6809 a Intel 8085.

Po pravdě jsem se nechtěl pouštět hned na začátku do Z80 nebo 6809, to jsou hodně mocné procesory. Měl jsem vizi, že začnu úplnou klasikou, buď 6502, nebo 8080 – a protože s procesorem 8080 a jeho podpůrnými obvody je mrzení on so many levels, od toho, že se špatně shání po to, že se konstrukce zbytečně zesložiťuje, tak jsem místo něj nabídl 8085.

Že skoro nikdo nechtěl 6809 není divu, tenhle procesor skoro nikdo nezná. Ale překvapilo mě, že Z80 nebyl tak jasný vítěz (na FB tedy ano, ale tam byly jen dvě možnosti) a že se 8085 dlouho drželo na prvním místě. Až jsem si říkal, jestli se hlasující nespletli a nemysleli si, že jde o 8086… No a 6502 doplatila na iracionální odpor, který k němu česká obec počítačová, odkojená Sinclairy a vůbec Intelskými procesory, asi pociťuje.

Takže jsem nakonec sáhl po 8085. Ten procesor je výrazně vylepšená 8080 a až na multiplex adres s daty je jednoduše použitelná. Navíc na rozdíl od 6502, odděluje paměti a periferie do samostatných prostorů, což trochu zjednoduší konstrukci.

A tak jsem jednoho krásného dne sedl a začal konstruovat.

Procesor semhle, paměti támhle, mezi to adresní latch, budič a oddělovač datové sběrnice, obvod ACIA MC6850, LED na výstup SOD, aby to blikalo, když to má blikat, a nakonec 8255. Na pohled krása nesmírná, tak jsem to chvilku routoval v Eagle ručně, ale pak jsem si řekl, že na to kašlu, že to stejně udělají Číňani za čtyři koruny kus, tak jsem dal Autorouter, nechal doběhnout, okem jsem se pokochal, zděsil jsem se nad tím zuřivým taháním linek, a – děj se bůle voží!

Po čase dorazily procesory a další součástky, a i balíček desek. No a minulý víkend jsem tedy začal pájet.

Oživení, den první

Začal jsem hezky zvolna: patice pro procesor (přesněji dvě dutinkové lišty, mám s nimi dobré zkušenosti), patice pro paměti (měl jsem tu dvě „přesné patice“ DIL 28), bižuterie okolo RESETu (tlačítko, kondenzátory, dioda), krystal a dva rezonanční kondenzátory.

Kámen úrazu číslo 1: Hodnoty kondenzátorů jsem bral z datasheetu 8085, ovšem pro CMOS verzi. A pak, když jsem se pořádně podíval, co že to Číňan poslal, tak mě málem omyli: M5L8085AP! Tedy NMOS verze. Naštěstí až do 6 MHz, což je gut, ale stejně! Problém je, že NMOS verze chce kondenzátory 6,8 pF.

Proměřil jsem patice, jestli je napájecí napětí tam, kde má být. Bylo. Zapojil jsem procesor. Díky plošnému spoji jsem se nemusel starat o přerušovací signály, ty byly neutralizované. Zajímalo mě jen jestli bude kmitat oscilátor a jestli na výstupu CLK bude něco zajímavého. Bylo, přátelé, bylo to tam! Ještě jsem zkusil RESET. Fungoval taky.

Takže jsem osazoval dál. Zkusil jsem minimální verzi, tedy s adresovým latchem, oddělovačem datové sběrnice a pamětí EEPROM, kde byl jednoduchý blikací program, co měl blikat LEDkou s frekvencí 1 Hz, ale bez použití podprogramů (neosazoval jsem RAMku).

No a nedělo se nic. Samozřejmě, jak jinak… Teda respektive na sběrnicích cosi probíhalo, ale úplně divně, a výstup SOD byl pořád 0. No a po čase se i to divné změnilo…

Co naplat, podívám se po příčině. Koukám do schématu na to zapojení EEPROMky. Správně tam vede /ROMCS, správně jsou připojené vývody, správně je připojený signál /RD, správně je připojený signál /WR – moment, cože? Co tam má co dělat signál /WR? Tam má být logická 1!

Kámen úrazu číslo 2: Blbec!!! Třikrát na to koukám, RAM vlevo, ROM vpravo, a pak stejně zapojím /WR k jinému čipu. Takže RAM měla zakázaný zápis a ROM si vesele zapisovala. Strčil jsem EEPROMku do programátoru, pro forma ji přečetl – a tam byla tuna nesmyslů! Přepsal jsem si ji. Ale aspoň je vidět, že procesor nějak pracoval.

Přeškrábnul jsem jeden spoj a zapojil dva drátky. Furt nic.

Koukám na ta data, a pořád se mi zdálo, že na nich něco nesedí. Ven po datové sběrnici šly samé jedničky, dovnitř… ech… moment!

Kámen úrazu číslo 3: Blbec na kvadrát! Obousměrné budiče 245 mají povolovací vstup, ten jsem připojil na ALE, a pak vstup, co udává směr. Když je 0, tak pouští zleva doprava, když je 1, tak zprava doleva. Pamatuju se, jak jsem jedno oko upíral do datasheetu, druhé do Eaglu a přemýšlel: Když 1, tak data odsud sem, to znamená, že sem dám signál /RD, ten když je v 0, tak musí data jít takhle… Jdu se najíst, vrátím se, co jsem to… Jo aha, signál /WR, zapojím sem, moment, opravdu? No když je 0, tak… No a modří už vědí!

Přeškrábnul jsem spoj, zapájel drátek, spustil – SOD se nastavil do 1!

Aha, žije to! Juchů. Žije, ale neseje. Někde se to zacyklilo… Ale něco přeci proběhlo!

Vytáhl jsem logický analyzátor a začal měřit a detekovat. Pořád se mi zdálo, že tam je na sběrnici nějak moc FF. Tady mě mělo ťuknout – a taky ťuklo, ale jinam.

Vytáhnul jsem budič sběrnice a nahradil ho drátkama. Ať minimalizuju možná místa problémů. Pak jsem taky zkrátil program, jen na úplně nezbytnou smyčku, bez čekání. A běželo to! Ještě jsem přidal RAMku, abych mohl testovat složitější programy…

Už bylo deset večer, tak jsem další experimenty odložil na státní svátek.

Oživení, den druhý

Našel jsem ten zpropadený obvod 6850. Já věděl, že ho mám, věděl jsem i že ho mám v nepájivém poli, ale kde to pole je, to jsem netušil. Nakonec jsem ho našel a koukám, že to je verze MC6850. Tedy trabl, protože tato verze má garantovaný provoz do 1 MHz, a já tam cpu 1,8432 MHz. Potřebuju verzi MC68B50, která je určena pro provoz do 2 MHz. Grant Searle ale tvrdí, a já nemám důvod mu nevěřit, že mu na této frekvenci fungují i nonB verze. Tak uvidíme, zkusím to, a když ne, tak holt počkám na „béčkové“ čipy, co jsou už na cestě.

„Additionally, all of the standard 6850 chips that I have worked perfectly at the speeds required for this circuit even though the circuit requirement is faster than their specification. Therefore, you are unlikely to have any issues. However, I would recommend you buy the „B“ speed grade ACIA ie. 68B50 if possible.“ – Grant Searle

Připájel jsem tedy dutinkovou lištu coby patici pro 6850, do EEPROM nahrál „Hello world“ pro sériový port a jedeme testovat.

A samozřejmě že nic.

Logický analyzátor do ruky, osciloskop do druhé, popřipojovat, a jedeme!

Nakonec jsem sledoval adresy, jak jdou po adresní sběrnici, a data, co tam putují. A fakt: adresa 0, data $F3 – to je DI. Pak adresa 1, 2, 3 – LXI SP, $FFFF. Adresa 4, 5 – MVI A, $15. Takže to žije…

Na adresách 6 a 7 je OUT $DE – nastavení ACIA. Tady se na chvilku datová sběrnice rozkmitala…

Aha vlastně: ACIA už posílá data, ale neskončilo ALE. No jasně, oddělovač sběrnice tam není, jsou místo něj drátky. Drátky ven, oddělovač dovnitř, jedeme dál!

Všechno běží. 0, 1, 2, 3, 4, 5, 6, 7, $DE, 8, 9, A, B, C, D, E, D, D, C, B, 8, A, 9, 8, … A to je divné… Proč to počítá nahoru a dolů?

Na adresách 8, 9, A je LXI H, HELLO, na adresách B, C, D je CALL $1C. Jasně, E a D jsou adresy zásobníku v RAMce, kam si CALL ukládá návratovou adresu (protože jsem si inicializoval SP na hodnotu $FFFF a procesor nejdřív dekrementuje, pak ukládá). Pak je C – protože sleduju jen čtyři bity adresní sběrnice, tak to je 1D – a tam je instrukce MOV A,M.

Ale není. Podle dat tam je cosi, co má ve spodních bitech samé jedničky, tady $xF.

Tušení se stalo zřetelným! Z paměti to čte FF, což je instrukce RST 7. Ta uloží návratovou adresu na zásobník (C, B) a skočí na $0038. To je ta osmička. A tam se zase načte $FF, takže se zas ukládá na zásobník (A, 9)…

Paměť! Nejsou někde prohozené vývody? To vypadá na prohozené adresní vývody. Podle schématu je všechno OK, ještě to konzultuju s datasheetem. Všechno sedí…

Kámen úrazu číslo 4: Nepozornost! Koukám na plošný spoj, dívám se na nožičku po nožičce u EEPROMky, a – herdek, proč je propojené A4 a A5? A ke vstupu A5 nevede signál?! Aha, takže paměť místo adresy $1C, která byla správná, četla adresu $3C, kde už byly samé $FF!

Proškrábnutí, připájení drátku… Ještě to proměřím. Všechno sedí. Zasunu EEPROMku, ještě jednou to pro sichr proměřím a – moment, jeden vstup se mi zdá podivný! Jako by pískal tak napůl!

Kámen úrazu číslo 5: Pin v patici byl propojen, ale na nožičce paměti už signál nebyl. Na pinu jo, v nožičce ne. Herdek! Debilní „přesné patice“! Vypájet to už asi nepůjde. Ale pro příště a pro vás: Nepoužívejte je! Nejsem jediný, kdo před nimi varuje, a je moje blbost, že jsem varování nedbal!

Propojil jsem vývod paměti u poškozené dutinky se správným signálem a spustil stroj. Všechno běželo jak mělo, alespoň podle adres soudě.

Čímž se taky jaksi mimochodem vysvětlilo, proč blikání s časovací smyčkou neběželo, zato blikání plnou rychlostí ano: protože „full speed“ kód byl krátký a vešel se do 16 bajtů!

Připojil jsem jednu měřicí sondu na TxD – a tam se opravdu něco dělo!

Tak jsem, pln očekávání, připojil převodník USB-to-UART, pustil terminál – a nic…

Přitom podle měření to… echm… ale nějak pomalu… Tedy takty odpovídaly, jen ty časy, co ukazoval analyzátor, naznačovaly, že přenosová rychlost je 700 Bd. Jak je to možné?

No, dále viz Kámen úrazu 1. Oscilátor se rozkmital pomaleji. Stačilo vypnout a zapnout, a krásně to jelo na 28800. Ale budu muset snížit kapacitu, nebo počkat na CMOS verzi procesoru.

A když to jede mně, pojede to i vám! Od příštího týdne, jako takovou ochutnávku z nové knihy, zveřejním pár kapitol s konstrukcí tohoto počítače.

 

Rubriky: Hardware | Štítky: , , , , | Komentáře nejsou povolené u textu s názvem Oživení

Klávesnice 2018

Avizoval jsem trošku retropočítačování. A k tomu patří i postavení pár retrokousků…

Nechtěl jsem použít PS/2 a nechtěl jsem se ani matlat s velkou deskou a membránovou klávesnicí. Nakonec jsem vzal sadu padesáti tlačítek s hmatníkem a univerzální desku

50sets/lot Tactile Push Button Switch with hat Momentary Tact 12x12x7mm DIP Through-Hole 4pin Free shipping

Je to jednoduché – udělal jsem si matici 5×8, jako mělo ZX81 nebo ZX Spectrum, a pak jsem si uvědomil, že vlastně můžu přidat poměrně jednoduše dalších osm tlačítek do matice 6×8. A tak jsem je tam nacvakal, připravil jsem si popisky (hmatníky jsou 10×10 mm), nařezal, připojil, a bylo. Teď už jen nadrátovat matici zespodu…

Škoda že už nezbylo místo, jinak bych na desku integroval obvod 74138, převodník 3-na-8, a připojoval bych to celé via 3+6 = 9 vodičů + napájení. Teď holt použiju 12žilový kablík.

Možná by šlo ještě udělat nějaký kryt, vytisknout na 3D tiskárně, ať se tlačítka neviklají. Mají poměrně malý zdvih, a čtvercové hmatníky ani nejsou kdovíjak hezké, přiznám se, že obdélníčky by mi seděly lépe. Ale co už.

Jo a dvě tlačítka, SHIFT a SPACE, jsem zdvojil – čímž jsem vyplácal plných 50 tlačítek.

Rubriky: Hardware | Štítky: | Komentáře nejsou povolené u textu s názvem Klávesnice 2018