Comp24
My computer for year 2024
Comp24-ideas
2024.01.30 07:32:40 - 2025.10.21 10:57:40 end HW Gilhad

1   Comp24-ideas

  • Schema-8bitComp.png
    Schema-8bitComp.png

2   Cards

  • Expansion card is connected via system bus.
  • Every physical card will consist of
    • ID - on this signal it enables its ID on data lines for Read
      • 74HC245 + pullups/pulldowns, set direction and Enable connected to ID signal
      • need for test, if card is present and what type it is
      • more card may return same ID, if they are of same type
    • I/O - basic enable for the whole card, A[0..4] select registers (may be divided between more devices) (not all must present)
      • 6522 VIA - 16 regs, 2 CS - best fit - 2 may be used
      • 6821 PIA - 4 regs, 3 CS - up to 4 with +1 decode
      • 6850 ACIA - 2 regs, 3 CS - up to 8 with +2 decode
      • budu rad, kdyz se mi podari tam tuhle trojici dostat jednou, s LEDkama a s RS obvodem ono to zabere hodně místa
  • video
  • sdílená RAM a Arduina
    • Mega umí nativně rozšířenou RAM, ale potřebuje na to extra rychlý 74AHC373, protože sdílí data a adresy
    • já bych spíš použil 3 porty (2xaddr+1xdata) kde to je o něco pomalejší, ale pokud to udělám ve strojáku, pořád by to mělo být dost rychle a bez chytáků
    • na základní video by asi stačila ATMEGA328p (UNO a pod.) se 2K+ RAM (text a pár fontů/spritů),
      • 1334 bytů pro text 46*29, 9*128=1.128K na půl font, může být ve flash
      • 2.25K na plný font
      • ideál je 4K+ pro text i s uživatelským fontem (pro hry)
      • na grafiku potřebuju asi 12K+ RAM (a velký datový tok při přenosech, možná 2 výměnné RAM?)
    • těch sdílených by mohlo být víc, jedna (dvě) pro video, jedna pro FS, dvě pro vypalování EEPROM, libovolně rozšiřujících
    • jedno arduino pro video, jiné pro FS a obecný I/O (a klidně příkazy typu I2C(123):3(45,56,78):5() - pošle 3 data, přečte 5 z dané adresy, podobně SPI, serial, PS/2 ... )
  • Zajímavé obvody
    • IDT7201 - FIFO - krásné, ale co s tím?

3   HomeMegaFORTH branistorm

Potrebuju vymyslet (a popsat) rozhrani mezi 8bitovym pocitacem (CPU) a dvema Arduiny (A a B), ktere bude delat CPLD nazvane GLUE (jako lepidlo, ktere spojuje jednotlive casti). Ze strany CPU pujde o dve dvojice registru - (status_L, addr_L) a (status_H, addr_H) A dvojici registru pro chipy - status_A a status_B Ze strany Arduin půjde o signály privadene na jejich I/O piny

Z pohledu CPU jsou v jeho pameti dve okna o velikosti 8kB (dolni (Low) na adrese 0x8000 a horni(High) na adrese 0xA000) do kterych je neco namapovane

Jsou tri chipy RAM, kazdy ma 128kB (RAM_A sdilena s Arduinem A, RAM_B sdilena s Arduinem B, RAM_C pouze pro CPU)

Kdyz chce CPU pouzit v nejakem okne nejakou pamet, zapise do prislusneho registru (napr. addr_L) pozadovanou adresu jako byte ve tvaru aa00bbbb, kde bity aa udavaji o ktery chip jde (00 RAM_C, 01 RAM_A, 10 RAM_B) a bity bbbb udavaji o kterych 8kB v ramci chipu pujde (4 horni bity adresy). (Důsledek - pro přirozené prázdné mapování by systém měl při startu namapovat do dolního okna 0000 0100 = 4 a do horního 0000 0101 = 5, stejně tak CPU, pokud se jen chce vzdát RAM. Na druhou stranu jiným mapováním lze přepsat i "ROM" i paměť pod "devices" i použít paměť nad 64kB) (Zda GLUE zvládne při resetu toto mapování je otázka, púředpokládejme raději stav po resetu za nedefinovaný.) (Poznámka: vzhledem ke způsobu mapování RAM_C nedochází ke kolizím, ale je možno si různě podrazit nohy zápisem do jiné části RAM - přepsat další instrukci, přepsat zásobník, zero page, nebo jakoukoli jinou nezdobu.)

Nasledne CPU cte v cyklu odpovidajici stavovy registr (status_L), dokud tento neukaze, ze je mozno dotycne okno pouzivat. Stavovy registr ma nasledujici bity 000wm0c bit C je vlastneno CPU - 0 znamena pamet neni jeste pridelena, 1 pamet pridelena je M znamena modified, 1 znamena ze od minuleho prideleni byla pamet modifikovana Arduinem W je Wanted - 1 znamena, ze Arduino by do te pameti chtelo psat (treba mezitim dosla nejaka nova data zvenku)

CPU take kdykoli muze cist stavovy registr chipu (status_A/status_B), s nasledujicimi bity 00dwmac bit A je vlastneno Arduinem - 1 znamena ano bit C je vlastneno CPU - 1 znamena ano M znamena modified, 1 znamena ze od minuleho prideleni byla pamet modifikovana Arduinem W je Wanted - 1 znamena, ze Arduino by do te pameti chtelo psat (treba mezitim dosla nejaka nova data zvenku) D je dirty - CPU tam zapsalo, ale Arduino to jeste necetlo

Pokud CPU namapuje nejakou RAM (jakozto chip), pak mu patri az do chvile, kdy bude v obou oknech namapovano neco jineho (cimz se CPU toho chipu zase vzda)

Obdobne to bude fungovat pro Arduina, Arduino si nemuze pripojit RAM, pokud ji vlastni CPU. Pokud si Arduino pripoji nejakou RAM, tak ji vlastni (a CPU si ji nemuze namapovat), dokud se ji nevzda. Kdyz si Arduino pripoji RAM, tak se predpoklada, ze ji precetlo a zapsalo. Arduino potrebuje vedet, jestli CPU do te pameti zapsalo a jestli ji CPU chce.

A potrebuju pro kazde Arduino vymyslet signaly, aby to mohlo takhle fungovat (potrebuje vedet, jestli je jeho RAM volna, jestli ji CPU chce, jestli ji CPU zapsalo)

A cele to nejak rozumne popsat.

4   Big Picture

  • 2025.10.21 11:00:32 CPU si bude s Arduinem předávat kus paměti, kam si budou psát vzkazy. CPU zadá požadavky, Arduino oznámí ne/splnění.
    • sdílená RAM je rozdělená na BLOKy
    • na jejím začátku je systémový BLOK(1), obsahující adresu prázdného BLOK(0), CPU BLOK(2) a Arduino BLOK(3/4) a možná i další systémová data
    • na začátku bude nějaké místo vyhrazené na stav Arduina (jako jestli má nezpracované vstupy, kolik požadavků ještě visí, kolik failnulo, kde začíná blok s jeho odpověďmi a tak podobně), bude to mít nějakou stálou strukturu, + to bude BLOK(3) pro Arduino_A a BLOK(4) pro Arduino_B
    • na začátku bude nějaké místo vyhrazené na stav CPU , + to bude BLOK(2)
    • tyto první dva BLOKy na sebe bezprostředně navazují(?) a mají pevnou(?) délku, každý zakládá vlastní řetězec
    • BLOK začíná hlavičkou (délka16,další12,segment4,typ8,reserved16)=8B a následují data délky délka16 (0..FFFF byte)
      • další12 je 2B adresa v rámci 8kB s počátkem na začátku RAM/okna
      • segment4 je 1B číslo 8kB bloku RAM (tohle CPU zadává při požadavku na namapování dolu/nahoru) začínající 00 (a končící 0F pro 128kB RAM)
      • nevyužité bity zapisující musí nastavit na 0 (aby čtení bylo jednoduché a nemuselo kontrolovat nic)
      • BLOK může překročit hranice i více segmentů, neměl by překročit vršek RAM (pokud to nastane, jde o o chybu a nedefinovaný stav - viz nasal daemons)
      • typ8 je 1B číslo typu bloku, následující čísla jsou rezervovaná:
        • 0 - BLOK(0) je prázdný
        • 1 - systémový BLOK(1), obsahující adresu prázdného BLOK(0), CPU BLOK(2) a Arduino BLOK(3/4) a možná i další systémová data
        • 2 - CPU
        • 3 - Arduino_A
        • 4 - Arduino_B
        • FF - vyhražený BLOK (plánovaný pro případné rozšiřování typů)
      • o udržování systému BLOKů se stará každý uživatel, prázdné bloky se dají libovolně rozdělovat, spojovat a alokovat pro další použití, dealokace BLOKu se dělá jeho zařazením do seznamu prázdných a nastavením typu 0
      • odkaz na blok 0:0 je NULL

5   Scénář

5.1   Signály

5.1.1   GLUE -> CPU

  • C_HALT - HALT pro CPU, možná doprovázen BREQ/DMA, Active LOW
  • C_DATA[0..7] - data (oba směry) - registry

5.1.2   CPU -> GLUE

  • BA,BS - pokud oba HIGH, CPU neblokuje sběrnice a DMA může běžet
  • C_ADDRESS[0..15] - adresa
  • C_DATA[0..7] - data (oba směry) - registry
  • C_R/W - požadavek na RAM/DEVICE
  • CLOCK - E, možná i Q? pro kvalifikování C_R/W

5.1.3   Arduino_A -> GLUE

  • A_HALT - Arduino chce zastavit CPU a udělat mu DMA

5.2   Normální stav

  • GLUE převádí CLOCK + C_R/W na R,W pro RAM/DEVICE
  • GLUE dekóduje adresu pro RAM/DEVICE a nastavuje RAM_C OE/ChipSelect a GA[13..15] je podle C_ADDRESS[13..15] a GA16 je 0
  • DEVICE jsou připojené paralelně k RAM_C a mají vlastní OE/ChipSelect
  • CPU si normálně funguje, Arduina si normálně fungují a nikdo nic nesdílí/nepožaduje

5.3   CPU chce použít sdílenou oblast

  • (Analogicky pro low/high a Arduino_A/Arduino_B)
  • (Na začátku by měl BIOS při bootu namapovat RAM_C, ideálně nativně, ale stejně je lepší si to udělat v programu explicitně)
  • CPU zapíše do registru addr_L (nebo addr_H) požadovanou adresu ve tvaru aa00bbbb
  • GLUE při tomto zápisu:
    • uloží C_DATA do registru
      • ale nejdřív zkontroluje, jestli (addr_L a addr_H mají stejné aa* bity ) NEBO (addr_L a požadovaná adresa mají stejné aa* bity )
        • pokud ne, tak odmapuje starou oblast (asi někde něco nastaví, teď nevím)
    • pokud aa==00, nastaví status_L (nebo status_H) 000wm0b na w=0 m=0 a c=1 čímž paměť přidělí (RAM_C jde vždy a Arduina s ní nic nedělají (DMA se nepočítá))
    • pokud aa==11 nastane nedefinovný stav (nemáme další systém)
    • pokud aa==01 jde o Arduino_A (jinak o Arduino_B)
      • tohle se vlastně dělá kdykoli je aa!=0 a A_SHARE_GRANTED == LOW a ownership == Arduino_A
      • pokud je A_SHARE_GRANTED == LOW
        • nastaví ownership (interní RS) na CPU
        • upraví status_A
        • nastaví status_L na status_A (možná se přesměruje podle ownershipu?)
  • CPU příležitostně čte status_L, dokud nebude c==1 (nedostane RAM přidělenou) (Pokud mezitím zapíše do téhož registru, jde se od začátku)
    • číst ho nemusí, ale jen tam se dozví, zda paměť už dostal, nebo ne
    • CPU může žádat na obou oknech takřka naráz a pak čekat na přidělení prvního
    • a samozřejmě může žádat na obou to samé a dostat to, ničemu to nevadí (ale asi ani nepomáhá, i když při kopírování z jednoho BLOKu do jiného, nebo jiné podobné transformaci mají dvě okna - zdroj a cíl - docela smysl i když se náhodou sejdou)
  • C_ADDRESS ukazuje do jednoho z oken (řekněme Low)
    • GLUE to zjistí
    • pokud není c==1 tak to nějak zahodí, nebo zignoruje (nedefinovný nasal daemons)
    • podle aa* bude posílat signály tam nebo onam takto:
      • A16 je výstup
      • první b jde do A16
      • ostatní jdou do GA[15..13]

5.4   BOOT

  • zapne se napájení
  • Reset linky jsou díky kondenzátorům chvilku dole, čili je signalizován Reset
  • A_HALT
    • pokud není Arduino_A připojeno, je díky pulup 100k rezistoru u GLUE nahoře, C_HALT je nahoře=neaktivní a vše jede normálně (viz Po Resetu)
    • pokud je Arduino_A připojeno je díky pulldown 3k3 rezistoru v Arduino_A dole - GLUE tedy nastaví C_HALT dolů=aktivní a CPU je haltnuté (a Reset je v CPU signalizován a uložen pro zpracování)
      • C_HALT je dole, tedy GLUE neřídí paměť a device podle C_ADDRESS, čeká na Arduino_A
  • GLUE nasdílí RAM_C ale Arduina nemají Shared Ram (není Selected)???
  • Skončil MasterReset/Reset
    • Arduina bootují (bootloader, setup, ... ) chvíli se nic neděje, pak začnou jednat (Arduino_B nedělá nic zajímavého)
    • A_SHARE_REQUEST je defaultně stažený na LOW=nežádá o RAM_A
    • nastaví si A_SHARED_SELECT HIGH=neaktivní
    • Arduino_A se vzbudilo a stáhne aktivně A_HALT dolů (kde je díky jeho pulldownu) a začne plnit RAM_C, tedy Zápis do RAM_C

5.5   Zápis / Čtení RAM_C

  • Arduino_A se vzbudilo a stáhne aktivně A_HALT dolů
  • GLUE tedy nastaví C_HALT dolů=aktivní (a možná i BREQ/DMA? ) a CPU je haltnuté (nebo brzy bude, no v extra blbém případě po asi 20 taktech CPU = IRQ, tedy asi 5 uS, pro Arduino tedy 80 taktů )
  • BA & BS je nahoře, tedy GLUE neřídí paměť a device podle C_ADDRESS, čeká na Arduino_A
    • Arduino_A nastaví (a GLUE to kvůli BA & BS akceptuje, jinak ne):
      • A_SHARED_SELECT HIGH=neaktivní (ať si nepřepisuje Shared RAM)
      • Shared_Address na adresu
      • pro zápis Shared_Data na hodnotu
      • A_G_A_DIR na výstup
      • A_G_D_DIR na výstup pro zápis (na vstup pro čtení)
      • A_G_ENABLE na TRUE
        • když je A_G_ENABLE == TRUE (a C_HALT dolů=aktivní) GLUE nastavuje:
          • A_S_ENABLE na neaktivní
          • A16 na INPUT
          • GA_16 podle A16
          • GA[13..15] dá na HiZ (nastaví je Arduino přez 245)
          • RAM_C R/W podle A_G_D_DIR
          • RAM_C CS na aktivní
          • G_A_DIR podle A_G_A_DIR
          • G_D_DIR podle A_G_D_DIR
          • G_OE na aktivní
      • pro čtení zde Arduino_A přečte Shared_Data (čtení lze cyklit tady zapisováním nových Shared_Address a následným čtením Shared_Data)(zápis ne, kvůli neatomičnosti změn při zapnutém enable)
      • A_G_ENABLE na FALSE
        • když je A_G_ENABLE == FALSE (a C_HALT dolů=aktivní) GLUE nastavuje:
          • RAM_C CS na neaktivní
          • G_OE na neaktivní
          • A16
          • pustí na normální hodnoty A_S_ENABLE, GA_16, RAM_C R/W, G_A_DIR, G_D_DIR
      • tím je hodnota zapsána a opakuje se pro všechny další
  • Arduino_A vytáhne aktivně A_HALT nahoru
  • GLUE tedy nastaví C_HALT nahoru=neaktivní a CPU se rozběhne a pokračuje (nebo resetuje, pokud byl reset)
  • pokud Arduino_A drží A_HALT dole, nebere se ohled na B_HALT a Arduino_B ostrouhá a neví o tom (což může vést ke konfliktům, zvláště pokud Arduino_B zapisuje delší data než Arduino_A a tak u jeho dat platí jen konec = nadměrné zápisy)
  • Jak čtení, tak zápis může proběhnout i jindy než po resetu, pak to funguje jako DMA, je potřeba dát CPU čas dokončit instrukci

5.6   Zápis / Čtení RAM_A

  • Arduino_A chce sdílenou paměť, nastaví tedy A_SHARE_REQUEST na HIGH a čeká, kdy GLUE nastaví A_SHARE_GRANTED na HIGH
    • GLUE:
      • A_SHARE_GRANTED je normálně LOW = nepřiděleno
      • pokud je A_SHARE_REQUEST HIGH a ownership (interní RS) u Arduina, drží A_SHARE_GRANTED na HIGH (duplicita, no action)
      • pokud není ownership u Arduina a bity aaxxxxxx v addr_L ani v addr_H nejsou 01* přehodí se ownership na Arduino a nastaví se A_SHARE_GRANTED na HIGH