Retró rovat IV/C: Hosszú, nem kék vagy piros, nem csuklós... Pedig busz!

Most nézem, az előzmény éppen a Fedora 18 megjelenése utáni, most meg épp a 19-es upgrade-en vagyok túl. (Megy az idő...) A FedUp szépen tette a dolgát, egy apró bakitól (nem volt elég hely a /boot-on) eltekintve eseménytelenül frissült a cucc. (Vagyis volt még egy: az nvidia sofőrjét le kellett kompletten szednem, majd újra visszaraknom, mert nem indult a grafikus felület.)

Megmaradt a „szeretett” régi GRUB-om is. (Most nem állok neki (újra...) sírni, hogy mi a bajom a G2-vel, nem ez a téma.) Tehát a frissítés meséjétől most (is) eltekintenék... Van egyébként is mit folytatni.

Az előző körben valahol ott maradt abba a mese, hogy összeállt a hardver, rajta az IEEE-488 interfésszel:

A CPLD-ben nem volt elég hely ahhoz, hogy a komplett GPIB¹ controller beleférjen, az adatbusz hajtásához be kellett építeni egy tárolót. (Az olvasás a CPLD-n keresztül megy egyébként; ha lenne „nagyobb” logikám, beleférne a hajtás is.) Ez egy 74HC574, ami egy 8-as élvezérelt tároló. A busz fele OC-s hajtás kéne, ez meg vonalmeghajtós Tri-State, ami tulajdonképpen még el is menne... De! Az SFD1001-ben (ezt akarom illeszteni...) a buszt kezelő MC3446 IC-k egyrészt ~OC-s jellegűek, másrészt nem nagyon lehet már beszerezni ilyet. Ha programírás közben elrontok egy adatirányt, akkor azt kockáztatom, hogy esetleg tönkreteszem a drive-ban lévő meghajtókat, ami – hogy is mondjam – nem szerencsés. Emiatt a kimeneteket OC-síteni kellene. Talán létezik ilyen tároló OC-s kimenettel is, de én egyrészt nem ismerek egyet sem, másrészt nincs a fiókban, van viszont pár 7407, ráadásul SO-14 tokban, amit el is tudok rejteni (cserébe szívás összeforrasztani, de csináltam ennél már cudarabb dolgot is). A 7407 6 db. OC-s vonalmeghajtót tartalmaz, emiatt nekem kettő tok is kell, de mivel elég kicsik, elférnek. A bekábelezett állapotban nem sok látszik belőlük (jobbra fent, a csatlakozó alatt...), mert a „gubanc” pont felettük van.

(¹: A busz eredetileg HP-IB néven született, mivel a Hewlett-Packard fejlesztette (Hewlett-Packard Interface Bus) a saját műszereik összekötésére. Azután licencelhetővé tették mások számára, ekkor nevezték át GPIB-re (General Purpose Interface Bus). Ezután az IEEE szabványosította 488-as számon, innen van a szabvány IEEE-488 név. De erről többet mond a Wikipedia. A tömörség miatt én maradok a GPIB névnél.)

A kreálmány hardveresen működik, a KERNAL módosítást is sikerült hozzá megcsinálni. Ezt a fejlesztést régen csak úgy tudtam volna megoldani, hogy „módosítás + EPROM programozás + próba”, mindezt annyiszor, ameddig jó nem lesz. (A mai kor követelményeinek megfelelően most használhatnék FLASH-t is, de azt is programozni kell. Mondjuk törölni legalább egyszerű és gyors...) A gép „módosítása” viszont itt is igen nagyot segített, mivel a BASIC+KERNAL helyére is tudok RAM-ot lapozni, így az égetést simán megúsztam. Valójában nem számoltam, hogy hányadik próbálkozás lett a kb. végleges, de sok. (Ennyi EPROM-ot törölni... Grrr.... :) )

Régen volt nekem egy „külső” interfészem ehhez a feladathoz, valamerre még meg is van. Egy 6821 PIA a „lelke”, az egész egy C64-es kártya alapján készült. Anno, amikor az SFD1001 meglett, kaptam hozzá azt a kártyát is. Abban volt egy EPROM, ami a gép KERNAL-ját bővítette ki, hogy lehessen vele ezt a fajta meghajtót is használni. Elég mókás a cucc, mivel „hibás” a kód. Valamilyen speciális módon kellett volna használni? Azért is kaptam meg „igen olcsón” a pakkot, mert a volt tulaja szerint nem működött. Emlékeim szerint két feltételes ugrást kellett kicserélni az ellenkezőjére (BMI helyett BPL vagy fordítva, az eszközszámot, vagy a másodlagos címet ellenőrizte, hogy negatív-e, ami pedig mindig pozitív... Valami ilyen rémlik...), utána egyből beindult... :) Sejtésem szerint a gép KERNAL-ja is mókolt lehetett, amivel működnie kéne, de ez – ha csak rá nem ismer valaki – már nem fog kiderülni. Anno ezt a programot „reserve engineering”-eltem, ez alapján csináltam meg a plus/4-hez illesztést. Viszont sikerült egy hibát akkor „belevarázsolni” a működésbe: a cucc néha „eldobta a kapcsolatot”. Ezt onnan lehetett észrevenni, hogy a „feladat” (mindig valamilyen lemezolvasás) anélkül fejeződött be, hogy végrehajtódott volna. (Pl. kértem egy „DIRECTORY”-t, majd „visszakaptam a BASIC-et” anélkül, hogy listázódott volna. Következő próbára már jó volt.) Ezt akkor a PIA számlájára írtam, ugyanis van neki egy „tulajdonsága”. („Ez nem bug, ez feature!”) A hibajelenségből az látszik, hogy ez a „kapcsolateldobás” akkor következik be, amikor a buszon adatirányt vált a kód. (Kimegy a DIR parancs a meghajtó fele, majd visszafele el kellene szedni a kapott adatokat tőle.) A PIA meg olyan, hogy ha a port(ok) adatirány-regiszterébe egy vonalat bemenetről kimenetre állítok, akkor az adatregiszter hozzá tartozó bitje „0” értékű lesz automatikusan. Ha nekem a vonalon magas szint kell, akkor az irányállítás UTÁN az adatregisztert is be kell állítani. Ráadásul a PIA adat ill. adatirány regisztere ugyanazon a címen látszik, a vezérlőregiszter egyik bitje dönti el, hogy melyikhez fér hozzá a CPU. Tehát a vonal bemenetről magas kimenetre állítása így néz ki:

  • Adatirány-regiszter kiválasztása
  • Irány átállítása kimenetre
  • Adatregiszter kiválasztása
  • Kimenetre állított vezeték magasra állítása

Mókás... :) De emiatt egy „kis időre” alacsony lesz a vonal a magas előtt. Hogy miért is kellene nekem kimenetre állítás után magas szint? Mert a GPIB olyan, hogy az aktív szint (amikor a vonal a meghatározott funkciót jelzi) alacsony. Mindig, amikor a PIA adatirány-regiszterében „matatok”, az épp akkor kimenetre állított vonalak „belerúgnak” egyet a buszba, ami nem túl szerencsés. Ráadásul ha pont irányállítás közben esik be egy megszakítás, akkor „elég hosszú ideig” állhat fent abnormális állapot a buszon. Ennek a hibajelenségnek akkor nem jártam jobban utána, mert a jelenség relatíve ritka volt (10-ből 1? :) ).

Miután elkészült a HW, előszedtem a régi illesztőkártya program forrásait. (Jó móka volt a plus/4-en futó Turbo/Macro Assembler forrásait átalakítani / átpakolni pc-re. :) Ahogy nézem, valami wines cucc még van is rá, én egy „kicsit” máshogy oldottam meg.) Majd szépen átírtam az új hardvernek megfelelően. Sokat egyszerűsödött, a CPLD-ben olyan interfészt implementáltam, amit könnyű használni. Néhány apróbb hiba kijavítása után, tádámm: működik!

(Tesztlemez teszt tartalommal; az azért látszik, hogy nem egy 664 blokkos 1541-es korongról van szó.) Viszont van egy gond: az „eszközleszakadós” hibát remekül sikerült áthozni az új hardverre is. Akkor viszont nem úgy rossz a cucc, ahogy eredetileg gondoltam, mivel a mostani interfész tuti nem rugdos fölöslegesen semmilyen vonalat. A helyzet a négyütemű motor első üteme. Lehet debuggolni...

Az első interfész – te jó ég – ~20 éve készült. Nem emlékszem már rá, hogy a GPIB működéséről a doksikat honnan szedtem össze, akkor még nem volt (elérhető) internet. Valamilyen könyvből volt az alap, az tuti. (Még az is rémlik, hogy valamilyen Commodore géppel vagy perifériával kapcsolatos, de nem GPIB-s dolog volt, csak – ha már szóba került – leírták ennek az alapjait is.) De ez leginkább a hardveres rész volt csak, a szoftvert az „eredeti” kártya visszafejtéséből raktam össze.

A „terv” az lett, hogy most, a bazi nagy Internet birtokában keresek valami dokumentációt, ami részletesen leírja, hogy a hardver szintjén hogyan működik a busz. Ebből esetleg tudok majd következtetni, hogy hol van elbökve a jelenlegi implementációm. De a keresgéléssel nem igazán jutottam olyan leíráshoz, ami nekem kellene. A bőség zavara... A találatok jelentős részében pécés (illetve USB-s) GPIB csatolót akartak eladni, a másik része ilyen interfészek dokumentációja. Ami valamennyire hasznos, találtam pár szakdolgozatot, ahol valaminek (leginkább valamilyen műszernek) a csatolását oldották meg, ezekben a „részletes” dokumentáció a „hardver fölötti” szinttel foglalkozik, a „fizikai szint” leírása kimerül annyiban, hogy egy-egy BYTE átvitele alatt mi történik. De hogy mi a kiindulási állapot, mi hogyan alakul ki a buszon, adatirányokkal összefüggő dolgok, ezekről egy árva kukk se szól. Ezt az éppen kiválasztott GPIB vezérlő elintézi. Magát a vezérlőt meg (érdekes módon) senki sem implementálta. A keresgélés legjobb eredményeként még talán ezt a könyvet találtam, amiben a legrészletesebben megvan az ami érdekelt volna. És ez teljesen témába vág; a PET (Personal Electronic Transactor) egy régi Commodore cucc. A busz működéséről elég részletes diagramok vannak, tele időzítésekkel (ami nekem „nem fontos”), cserébe az irányváltások körüli rész ebben sincs agyondokumentálva.

Igazán jó doksi (a fent említetten kívül) nem jött velem szembe, arról nem is beszélve, hogy magyarul aztán pláne semmi sincs. Sőt: arról meg aztán végképp nincs semmi, hogy mondjuk mi történik akkor (magán a buszon), ha mondjuk egy fájlt akarok betölteni vagy kimenteni.

Ami itt jön, az ismét elég „száraz” anyag, újfent „jegyzet magamnak” stílusú.

Tehát van a GPIB, illetve a rá kapcsolódó eszközök. A buszon funkció szerint 3 fajta eszköz lehet: beszélő/Talker, hallgató/Listener, illetve vezérlő/Controller. (Ez utóbbira az irányító kifejezés talán jobb lenne (ha már fordítunk :) ), de a vezérlő névvel már találkoztam, úgyhogy maradok ennél.) Egyszerre a buszon egy darab vezérlő lehet; „ő” osztja ki a parancsokat. (Legalábbis egy időben egy vezérlő lehet „aktív”, ez esetünkben mindig az egy darab számítógép.) A többi eszköznek minimum hallgatónak kell lennie, ebben az esetben csak adatokat tud fogadni. (Ilyen lehet pl. egy igen buta nyomtató, mivel csak hallgató üzemmódban még hibakódot se tud visszaküldeni a vezérlőnek.) A perifériák zöme ezért hallgató ill. beszélő is lehet. Hogy melyik, azt a vezérlő dönti el a megfelelő un. felcímzéssel. A vezérlő, amikor éppen „nem vezérel”, akkor hallgatót vagy beszélőt játszik. Minden eszköznek van egy „egységszáma” (Device Number), ez alapján tudja a vezérlő megszólítani. Az egységszám általában (bizonyos határok között) változtatható. (A Commodore drive-jai 8..15, a nyomtatók 4..5.) A szabvány 15 eszközt enged egyszerre a buszra kapcsolni.

Hardver oldaláról 16 jelvezeték van összesen (költséghatékony... :) ), ami 3 csoportra oszlik:

  • DIO8..DIO1 – 8 darab adatvezeték
  • DAV, NRFD, NDAC – 3 darab handshake vonal
  • ATN, EOI, SRQ, REN, IFC – 5 darab vezérlőjel

A jelek TTL kompatibilis szintekkel dolgoznak, minden vonalat OC-s meghajtók „tolnak”. Az alacsony szintek tehát hajtottak, a magas szintet viszont a vonalak „terminálása” produkálja. (Legalábbis az SFD1001-ben lévő MC3446 meghajtók így működnek. Van direkt GPIB meghajtóból „Push-Pull”-t tudó verzió is (75160/75161 páros), viszont ott is van OC-s terminált kimenet. De maradjunk csak a „sima” verziónál.) Emiatt az én GPIB vezérlőm is OC-s módon hajt, bár a „komplett terminálást” elhagytam, csak a táp fele vannak a vonalak „felhúzva”. A „terminálás” viszont nem kapcsolható ki (mármint a GPIB-s eszközökön, úgy általában), emiatt egy érdekes „hiba” van a logikában. A buszra több eszköz is felfűzhető, de az összes eszközben ott a „terminálás”, ami ilyen esetben párhuzamosan kapcsolódik. Az SFD1001-ben levő meghajtó IC elvileg 48mA-t tud, a 15 párhuzamosan kapcsolt ellenállást meg kellene tudnia hajtani. Viszont a saját cuccom ennyire nem „erős”, de ettől most nyugodtan eltekinthetek, ugyanis ÖSSZESEN nem láttam eddig 15 GPIB-s eszközt, nem hogy nekem lenne. Rá meg pláne nem akarom kapcsolni az interfészemre. Egyszerre. :)

A busz negatív logikás, ami azt jelenti, hogy az „igaz”, vagy „aktív” szint minden esetben a ~0V (tehát amikor az OC-s kimenetek hajtanak). Ez annyira így van, hogy még az adatvezetékeken is az alacsony szint jelenti a logikai „1”-et. No de milyen jelekből is áll a busz? (A jelek leírásában a „vezérlő” az maga a buszt vezérlő hardver, nem a vezérlő szoftver.)

  • IFCInterFace Clear : Ez a busz hardveres RESET jele, a vezérlő hajtja, a többi periférián ez bemenet. Esetünkben a számítógép RESET vonala kapcsolja, amikor az aktív, az IFC is aktív (tehát alacsony) lesz. Ez a perifériákon bemenet, az SFD1001-ben a belső „reset” vonalat kapcsolja, tehát nem szoftver figyeli.
  • RENRemote Enable : „Távirányítás” engedélyezése. A vezérlő hajtja. Ez a vonal arra lenne jó, hogy az adott eszközt „távirányított” módba kapcsolja. Amikor ez aktív, akkor a készüléken esetlegesen lévő kezelőszervek kitiltódnak, és a GPIB buszon keresztül vezérelhető a megfelelő parancsokkal minden. Nyilván ehhez olyan periféria kell, aminél ennek van értelme, például egy műszer. Amiknél nem értelmezhető ez a funkció (mint az SFD1001...) ott ez a jel nincs használva. A Commodore GPIB vezérlői ezt a jelet nem tudják kapcsolgatni, fixen alacsonyra (tehát aktívra) van kötve. A meghajtókban nincs is bekötve.
  • SRQService ReQuest : Kiszolgálás kérelem. Ezt a perifériák hajt(hat)ják, a vezérlő fogadja. Ha valamelyik eszköznek „fáj a hasa”, ezt a vonalat aktívba húzza. Ez a vezérlőben kiválthat akár egy megszakítást is, de pollingolva is figyelheti a szoftver benne. Itt ez részletkérdés, mert a Commodore meghajtói ezt a vonalat nem használják, az SFD1001-ben be sincs kötve.
  • ATNATtentioN : Figyelem, az eszköz fel/lecímzése következik. A vezérlő hajtja, a perifériák figyelik. Amikor a vezérlő aktívba húzza, az ÖSSZES periféria nekiállja hallgatni a buszt. Miután az eszközcímzés megtörtént, azok a perifériák, akiknek „nem szól” a parancs, szépen „leszállnak” a buszról, addig nem kell egyiknek sem kommunikálni, ameddig az ATN-nel újra címzés nem jön.
  • DAVDAta Valid : Adat érvényes. A beszélő (Talker) hajtja, a hallgató(k) (Listener(-ek)) figyeli(k). Ha aktív, az adatvonalakon (DIOx) érvényes adat van.
  • NRFDNot Ready For Data : Nincs kész a hallgató az adatfogadásra. Ha ez a vonal aktív, a buszon lévő hallgató(k közül legalább egy) még nem tud adatot fogadni. A beszélő figyeli, a hallgató hajtja.
  • NDACNo Data ACcepted : Nincs még az adat elfogadva. Ha ez a vonal aktív, a buszon lévő hallgató(k közül legalább egy) még nem fogadta el az adatot. A beszélő figyeli, a hallgató hajtja.
  • EOIEnd Or Identify : Vége vagy azonosítás. A vonal két funkcióval bír:
    • Normál kommunikáció alatt a beszélő hajtja, ha az adott BYTE átvitele alatt aktívba húzza, akkor ezzel jelzi az adatátvitel végét. (Ez az utolsó BYTE.)
    • Ha egy periféria az SRQ vezetékkel kiszolgálást kér, akkor a vezérlőnek el kell döntenie, hogy a buszon melyik eszköznek is van mondanivalója. Ezt egyrészt megteheti úgy, hogy felcímezve végigkérdezgeti az összes perifériát a buszon, hogy ő kér-e kiszolgálást (polling), de ez lassú. A gyorsabb megoldás az, hogy az ATN vezeték aktívba húzásakor az EOI-t is aktiválja (ilyenkor a vezérlő hajtja a vonalat, nem a periféria (/-ák)), ekkor a „kiabáló” eszköz a hozzá rendelt adatvonalat (DIOx) aktívba húzza. (Vagy valami ilyesmi.) Ezzel gyorsan megállapítható a kérelmet okozó eszköz. Az, hogy melyik egységszámhoz melyik adatvezeték tartozik, azt előtte a megfelelő parancsokkal fel kell konfigurálni (tehát nem fix, nem kapcsolóval állítható), ill. magát a „párhuzamos lekérdezés”-t is engedélyezni kell előtte. Erről több konkrétumom nincs, mivel a Commodore meghajtói az SRQ-t nem használják, úgyhogy az Identify funkciója a vezetéknek nincs használva.
  • DIO8..DIO1Data I/O : A 8 bites kétirányú adatvezeték-csoport, értelemszerűen a beszélő hajtja, a hallgató(k) figyeli(k).

A hallgató esetén mindig lehet több periféria is, ezért ez többes számban szerepel, de természetesen ugyanez zajlik le akkor is, amikor csak egy hallgató figyeli a beszélőt. Az egyszerű adatátvitel valahogy így néz ki:

Első lépésként az összes hallgató elengedi az NRFD vonalat („a”). Mivel az aktív állapot azt jelenti, ami a neve, így az elengedett vezeték ennek az ellenkezőjét, azt, hogy az eszköz már kész az adatátvitelre. Ez az OC-s hajtás miatt CSAK akkor lesz magas, ha MINDEN hallgató periféria KÉSZ az adatfogadásra. Ezután (vagy előtte, ez részletkérdés) a beszélő kirakja a küldendő adatot a DIO8..DIO1 vonalakra („b”) majd a DAV vezetéket alacsonyra állítja („c”), ezzel jelezve, hogy „érvényes az adat, tessék elszedni”! Amikor ezt a hallgatók érzékelik, akkor az NRFD vonalat alacsonyra húzzák („d”, nincs kész a következő adat fogadására a periféria). Majd beolvassák az adatbusz 8 bitjét, eltárolják, majd elengedik az NDAC vonalat („e”). Ez itt azt jelenti, hogy az adat el van fogadva (a „nincs elfogadva” negáltja), de az OC-s hajtás miatt ez a magas szint is csak akkor alakulhat ki, ha az összes periféria elfogadta az adatot. A logika azt diktálja, hogy az adatvonalaknak eddig az állapotig kell stabilnak maradniuk. (Tehát a DAV alacsonyba menetele előtt kell beállniuk, és az NDAC magas szintjének az érzékelése után változhat csak meg.) Ha a beszélő érzékeli az NDAC magas állapotát („e”), elengedi a DAV-ot („f”). (Illetve ettől a ponttól kezdve a DIOx vonalak állapota megváltozhat („g”).) Erre a hallgatók lehúzzák az NDAC-ot alacsonyra („h”, nincs adatelfogadás), majd elengedik az NRFD-t („j”) akkor, amikor már készek a következő adatot elfogadni. Így elkezdődik az egész elölről.

Ennek a kifordított logikának (az aktív (alacsony) jelszint a funkció NEM mivoltát jelzi) a – nem éppen mellékes – mellékterméke az, hogy az adatátvitel sebessége MINDIG a LEGLASSABB eszköz tempójához igazodik, mivel mindig az fogja a vonalat utoljára elengedni. Jó trükk... :)

Körülbelül ennyi az, ami az általános doksikból kiderül a busz hardveres működéséről. Viszont a busz „Szabad” (Idle) állapota úgy néz ki, hogy az ÖSSZES vezeték INAKTÍV, tehát el van engedve. Az ábrán viszont az látszik, hogy az NRFD ill. az NDAC vezeték is aktívban kezdi a ciklust, majd úgy is fejezi be. Valami innen erősen hiányzik. Ez pedig az eszköz felcímzése, amikor azt „mondja meg” a vezérlő, hogy ki kivel hogyan kommunikál:

Az első lépés az ATN, a vezérlő ezt a vonalat alacsonyra húzza („a”), ezzel jelzi a buszon lévő perifériáknak, hogy figyeljenek, mert eszközcímzés jön. Erre az ATN alacsony szintre az összes periféria automatikusan alacsonyba húzza az NRFD („c”) és az NDAC („b”) vonalát. Hogy erre mennyi idő van, az jó kérdés, de az biztos, hogy az SFD1001-ben ehhez a lépéshez egy külön hardver tartozik, ami a CPU-n futó programtó teljesen függetlenül alacsonyba rántja ezt a két vonalat. Ill. még azt is megteszi, hogy elengedi a komplett adatbuszt, hogy az se zavarjon be. Tehát ez a lépés („a”) automatikusan alacsonyba rakja ezt a két vonalat („b”, „c”). Az ATN aktiválása okozhat egyébként a perifériáknál megszakítást is, de ha van ilyen „hardveres rásegítés”, akkor egy kicsit „ráér” még foglalkozni a periféria a felcímzés átvételével. Ez egy olyan állapot (NRFD és NDAC alacsony), amikor a periféria „szabályosan” várakoztathatja a vezérlőt, itt nincs semmilyen TimeOut. Viszont ha az ATN aktiválása után ez a két vonal magas marad, az egyértelműen azt jelenti, hogy nincs egy periféria se a buszon. (Ilyenkor jön a kedvenc „?DEVICE NOT PRESENT ERROR.” hibaüzenet.) Viszont ha ott van legalább egy eszköz, akkor az NRFD / NDAC páros alacsony lesz, majd amikor a leglassabb periféria is „odaér”, hogy foglalkozzon a felcímzéssel, az NRFD vonal magas lesz („d”). Innentől a busz állapota már olyan mint az előző ábrán, annyi különbséggel, hogy az ATN aktív. Első lépésben a „mód + cím” kerül kiküldésre, utána (ha kell), a „másodlagos cím”. (Ezek magyarázata később...). Majd az ATN visszaáll magasra. Ettől a ponttól kezdve azok az eszközök, akiknek „nem szól” a „feladat”, „lekapcsolódnak a buszról”. (Nem fizikailag, mert „ott lógnak” elektromos szempontból továbbra is, hanem az NRFD/NDAC vonalakat (meg minden mást is) „elengedik”, és egész addig nem foglalkoznak a buszon történő forgalommal, ameddig újra ATN aktív állapot nem lesz.)

Ez így eddig szép és jó. Viszont arról még nem szólt a „fáma”, hogy milyen módon zajlik le egy irányváltás? Ha a vezérlő beszélőnek címez fel egy eszközt, akkor megfordul az adatáramlás iránya. A felcímzés alatt a vezérlő küld adato(ka)t az eszköz(ök) felé, ekkor a DIOx, DAV vonalakat hajtja ő, az NRFD, NDAC vonalakat meg a másik fél. Utána a felcímzett eszköznek át kell venni a DIOx, DAV hajtását, az NRFD, NDAC vonalakat meg figyelnie kell, ezeket a vezérlő (vagy a hallgató) fogja hajtani. No de ez hogy zajlik? A „régi” kódban ezzel különösebben nem foglalkoztam (az eredeti C64-es cucc szerzője se), csak simán bemenetre / kimenetre állítottam ami kell, aztán vártam az adatot. (Most arról az esetről van ugye szó, amikor a számítógép a felcímzés beszélő állapotából vált hallgató állapotba.) Na, ennek a végeredménye a „leszakadós” jelenség. Dokumentáció keresés közben viszont „beleszaladtam” egy kis „mellékesnek tűnő” dologba. (Talán ez is a PET-es könyvben van, most nem találom...) Arról van szó, hogy az adatátvitel közben az NRFD / NDAC vonalakból mindkettő NEM LEHET EGYSZERRE MAGAS. Ez az állapot a busz „tétlen” (Idle) állapota, kommunikáció alatt ez az állapot nincs megengedve. Az én implementációmban meg semmi se garantálja, hogy amikor „átveszem” ezen vonalak hajtását, akkor még a meghajtó is alacsonyba tartja. Az irányváltás végéig lehet egy olyan időszak, amikor a periféria MÁR, én meg MÉG NEM HAJTOM ezen vonalak egyikét sem. Na, ez már egy „használható nyom”. Egy kicsit át kellett túrni a kódot, hogy ezt az „apró” kellemetlenséget megszüntessem, de megérte! Azóta nem találkoztam „leszakadással”. Meg még ahhoz is lettek ötleteim, hogy a régi PIA-s megoldást hogyan lehetne javítani, de azért annak a megvalósításába nem kezdtem bele. Szóval hogy is néz ki az az irányváltás? (Innentől kezdve az van leírva, amit én kreáltam. Huba esetén kérek bugriportot! :) )

(Eredetileg ezt a részt egy kicsit elbonyolítottam, de közben egy egyszerűbb megoldást kipróbálva az is tökéletesnek tűnik.) A vezérlő a DAV aktiválása után megvárja, míg az eszközök aktiválják az NRFD-t, utána – jelezvén az adat átvételét – kikapcsolják az NDAC hajtását („a”). (Eredetileg a vezérlő itt bekapcsolta az NRFD aktiválását („1”), ezzel átvette annak a hajtását, de ez még ráér.) Ezután a vezérlő a DAV-ot elengedi („b”), eddig semmi különös, ez egy sima adatátvitel. A trükk most jön: a DAV elengedése után az adatvonalakat is elengedi, hogy tudjon a külső eszköz adatot rakni a buszra („c”), az NRFD / NDAC hajtását bekapcsolja („d” / „e”, ezeket valamilyen kombinációban itt még az éppen címezendő eszköz is hajtja), majd ezek után elengedi az ATN-t („f”). Az NRFD / NDAC hajtását azért lehet itt, és nem korábban („1”) átvenni, mert ameddig az ATN alacsony, addig az eszközöknek fogadni kell a címző adatokat, tehát legalább az NDAC vonalat hajtaniuk kell. Ezért még így is biztosítva van, hogy az irányváltás alatt ez a két vonal nem lesz egyszerre magas. Innentől már minden megszokott, csak a szerepek cserélődtek fel: ha a hallgató (ami esetünkben így a vezérlő lett) felkészült az adatfogadásra, elengedi az NRFD-t („g”), erre az újdonsült beszélő kirakja az adatát a DIO vonalakra („h”), majd lehúzza a DAV vonalat („j”), stb.

Vissza van még az adatátvitel befejezése, amit a beszélő az EOI segítségével jelez:

Ez a legbonyolultabb (-nak tűnő) rész az egészben, de annyira azért nem vészes, mint aminek látszik. A beszélő (mint mindig) vár az NRFD kikapcsolására. Amikor a hallgató (ami esetünkben most a vezérlő is egyben, ami meg a számítógép) elengedi az NRFD-t („a”), akkor a beszélő egyrészt aktiválja az EOI-t („i”, ez lesz az utolsó adat), másrészt az adatát kirakja a DIOx vonalakra („b”), majd a DAV-ot alacsonyra húzza („c”). Erre a hallgató az NRFD-t aktiválja („d”), beolvassa a DIOx-ről az adatot, „megjegyzi” az EOI-t, és elengedi az NDAC-ot („e”). (Az EOI figyelését természetesen minden BYTE beolvasásánál megteszi az éppen aktuális hallgató, innen tudja, hogy az éppen beolvasott adat az utolsó-e.) Erre a lépésre („e”) a beszélő elengedi a DAV-ot („f”), a DIOx vonalakat, és az EOI-t is, erre meg a hallgató húzza alacsonyba ismét az NDAC vonalat („g”). Ez idáig egy teljesen szokványos adatátvitel, kivéve, hogy az EOI aktív volt. Itt kezdődik az „érdekesség”... Amikor a hallgató az NDAC vonalat ismét aktiválta („g”), akkor a vezérlő (aki lehetett az eddigi hallgató is!) aktiválja az ATN-t („k”), erre a buszon levő eszközök alacsonyra húzzák az NRFD / NDAC vonalakat („n” és „m”). Ez a buszon újfent „nem látszik”, mert az eddigi hallgató (ami a számítógép) eddig is alacsonyba tartotta ezeket a vonalakat. De ezen a ponton (ATN aktiválása („k”) UTÁN, „n”/”m” ponton) EL KELL ENGEDNIE őket, mert az eszközök már átvették a hajtást. De ha majd elengedik, akkor magasra kell tudniuk menni a vonalaknak. Ha ez az elengedés megtörtént, akkor minden irány visszaállt olyanra, hogy a vezérlő végre tudja hajtani az adatátvitelt.

Innen már ismét „minden sima”: az eszközök hallgatnak, ha a leglassabb is ráér, az NRFD vonal magas lesz („p”), erre a vezérlő kirakja a DIOx vonalakra az „UnTalk” kódot („q”, eszköz lecímzése, magyarázat később), aktiválja a DAV-ot („r”). Erre az eszközök alacsonyba húzzák az NRFD-t („s”), majd elszedik az adatot, elengedik az NDAC-ot („t”). Erre a vezérlő kikapcsolja a DAV hajtását („u”), utána a DIOx vonalakat is elengedi („w”). A DAV végére („u”) az eszközök újra aktiválják az NDAC-ot („v”). Ezt a vezérlő figyeli, erre kikapcsolja az ATN hajtását („x”). Amikor az ATN magas lesz, az eszközök elengedik az NRFD / NDAC vonalakat („y”, „z”), mivel a lecímzés erre utasítja őket. Így visszaáll az alap „szabad” (Idle) állapot a buszon.

A hardveres rész valahogy így működik. Ezt azért is „volt jó” most így elemezgetni, mert pár részen módosítottam is közben a „kezelőprogramon”, optimalizálódott egy kicsit, meg most már kb. azt is csinálja, amit ide leírtam. :) A módosításokat közben persze teszteltem is, működik szépen a cucc. Egyébként (most már) nem külön kezelőszoftverről van szó, hanem az eredeti KERNAL olyan módosításáról, hogy a gyári soros rutinok lettek erre szépen lecserélve. Mivel a működési logika ugyanaz, csak a fizikai réteg más, így elég egyszerű volt beilleszteni. A soros rutinok hosszabbak, ráadásul a saját interfészem úgy készült, hogy „könnyű legyen programozni”, így az ahhoz tartozó kód „egész rövid”. Még az eredeti rutin belépési pontok is megmaradtak. (A 6821-es interfésznél a hely volt körülbelül elég, ott a rutinok kezdőcímeit esély sem volt megtartani, így a KERNAL-t több helyen kellett módosítani, amit anno „kézzel” kellett minden build alkalmával megtenni. Itt szó sincs ilyesmiről, szerencsére.)

De az igazi poén ide a végére jön: a tesztelések megvoltak, éppen „rajzolom” az utolsó ábrát, amikor...

...szerencsétlen SFD1001 „meghalta magát”. :-| „Csak” be volt kapcsolva. Annyit vettem észre, hogy nekiállt forogni a lemez. Mi van? „Reset”? De az SFD nem forgatja a lemezt „reset” alatt. Kértem tőle egy „Status”-t (PRINT DS$), erre a szokásos „00, OK,00,00,0” sorral válaszolt. Kértem egy listát a benne levő lemezről (DIRECTORY), ebbe viszont szépen belefagyott. Majd egy valódi „reset” után már csak hibakódot villog. Hát... Mondjuk 30 év az csak 30 év. (1983. évinél újabb gyártású alkatrészt nem találtam benne, szóval lehet ténylegesen is annyi...) Tervben volt, hogy esetleg írok ennek a működéséről is egy összefoglalót (mint az 1541-ről), de ezután azt össze kell kössem egy javítással. A hibáról most nem akarok tippelgetni, de amit sejtek, az nem túl jó.

Na de „haladjunk”. Az eddig tárgyalt buszról mintázta a Commodore anno a gépben gyárilag lévő soros buszt. De az „olcsósított változat” vajon hogy néz ki?

Itt 5 jelvezeték van összesen:

  • RESETReset : alaphelyzetbe állító jel. Funkciója megegyezik a GPIB IFC jelével. A gép „reset” állapotában aktív, a perifériákon ez bemenet, ott a hardveres „reset”-re van kötve, tehát nem szoftverből figyelik.
  • SRQService ReQuest : Kiszolgálás kérelem. Funkcióban a GPIB SRQ-ja, itt sincs használva. (A C64 tudná figyelni ezt a vonalat, mert legalább be van kötve. A plus/4-ben még ennyi sincs. Használni nem használja tudtommal semmilyen gyári periféria, az 1541-ben sincs kiépítve.) Elvileg a perifériák hajtanák, a vezérlő figyelné.
  • ATNATtentioN : Figyelem, az eszköz fel/lecímzése következik. Funkcióban a GPIB ATN-je, ugyanarra a célra van itt is használva. A vezérlő hajtja, a perifériák figyelik.
  • CLKCLocK : Órajel, a buszon levő adatokat (amik itt bitek) ezzel érvényesíti.
  • DATDATa : Adatvezeték, ezen a vezetéken csorognak az adatbitek.

A CLK, DAT ill. ATN jeleknek a különböző állapotai határozzák meg, hogy éppen mi történik, de ez szigorúan „sorrendi logika”. Az éppen aktuális pillanatnyi állapotból nem sok minden derül ki, folyamatosan figyelni kell.

A vonalak elektromos hajtás szempontjából egyrészt sokkal egyszerűbbek, mivel nincs külön speciális „Commodore Soros port meghajtó”, másrészt meg nincs különbség, mert a logika itt is ugyanaz. Az eszközök a vonalat csak alacsonyra tudják húzni, a magas szintet felhúzó ellenállások biztosítják, amik több eszköz esetén ugyanúgy párhuzamosan kapcsolódnak. (Hogy mennyi eszközt lehet párhuzamosan „felfűzni”, az jó kérdés, ez 15-öt egész biztosan nem visel el.) A vonalon csak akkor alakul ki magas szint, ha mindenki „elengedi” azt. A tényleges adatátvitel a CLK / DAT vonalakon zajlik, ezeket a vezérlő és mindegyik periféria képes hajtani ill. figyelni is. Az ATN-t a perifériák csak figyelik. (Az SRQ ugyebár nem használatos, a RESET meg a kommunikációban nem vesz részt, ezért csak a fennmaradó három vonal az, ami most érdekes.)

Az „alap” adatátvitel a következő:

A „köztes időkben” (1-1 BYTE átvitele között) a két vonal alacsony. De „nem akárhogy!” :) Az éppen aktuális beszélő húzza alacsonyra a CLK vonalat, a hallgató(k) meg a DAT-ot. Amikor a beszélő adatot akar küldeni, akkor magasra engedi a CLK-t („a”). A hallgató(k) ezt látva (meg ha felkészült(ek) az adatfogadásra) elengedi(k) a DAT-ot („b”). Itt („a” után, „b” előtt) addig lehet várakoztatni a beszélőt, ameddig szükséges, nincs TimeOut. (A GPIB NRFD funkciója kb...) Amikor a beszélő a DAT vonal magasát („b”) észreveszi, akkor „záros határidőn belül” el kell kezdenie az adatküldést (erről majd később), ami a következőképpen zajlik: először alacsonyra húzza a CLK-t („c”), majd közvetlenül ezután kirakja a soron következő bitet a DAT vonalra („d”). (Először a B0 (LSB), majd a többi szépen sorban. A vonal olyan szintre áll be, mint a bit értéke. Tehát ha magas akkor „1”, ha alacsony akkor „0” a küldött bit.) Ezután „vár egy kicsit”. (Ilyen 40 órajelciklus körüli időről van szó, de a gép órajele meg nem állandó, szóval maradjon a pontos idő az „egy kicsit”.) Ha ez letellett, a CLK vonalat magasra kapcsolja („e”). A hallgatók a magas szint érzékelésére eltárolják a DAT vonal állapotát (egy bit az adatból), majd várnak (a következő CLK felfutásra). A beszélő ismét „vár egy kicsit”, majd a CLK vonalat alacsonyra („g”), a DAT vonalat meg magasra kapcsolja („f”). „Kideríti”, hogy mi a következő bit, azt kirakja a DAT vonalra („h”), majd „vár egy kicsit”, CLK magasra („j”), ezt a hallgatók tárolják... Ez addig folytatódik, ameddig az utolsó (MSB) ki nem kerül a DAT-ra (ami ugyebár a nyolcadik). A végén, a CLK magas („k”) után ismét „egy kis várás”, majd a CLK alacsonyra („m”) illetve a DAT magasra engedése jön („l”). Ekkor a hallgatónak a DAT vonalat alacsonyra kell húznia („n”), ezzel nyugtázza az adat átvételét (GPIB NDAC...). Erre azért van idő, a plus/4 (mint beszélő) úgy ~2000 órajelciklust vár erre. Ha a nyugtázás elmarad, az „TimeOut” hiba. Ha minden rendben, akkor a busz vissza is állt a kezdőállapotra, amikor a beszélő a CLK-t, a hallgató(k) meg a DAT-ot tartják alacsonyban. Amikor „sok adat megy”, akkor ez a szekvencia ismétlődik. Az látszik a fentiekből, hogy nincs „handshake” a bitek átvitelekor, a hallgató(k)nak folyamatosan kell figyelniük, különben lemaradnak (IRQ kiszolgálás beesése nem fér bele).

Viszont a busz alapállapota itt is az, hogy mindegyik vonal elengedett, tehát magas. Ez az „üzem közbeni” állapot hogyan alakul ki? Itt is a felcímzés a történet lényege:

A vezérlő először a CLK vonalat („a”), majd közvetlenül utána a ATN vonalat is („b”) alacsonyra húzza. Az ATN alacsonyra („b”) az összes periféria alacsonyra húzza a DAT vonalat („c”). Ehhez van egy spéci belső logikájuk, ami a programtól függetlenül megcsinálja ezt a DAT alacsonyat. (Ez ismerős valahonnan... :) ) Amikor az eszköz programja „odaér”, hogy foglalkozzon a felcímzéssel, akkor „átveszi” a DAT hajtását ettől a spéci logikától (így már nem az ATN alacsonya kényszeríti a DAT-ot alacsonyba, hanem direkt a szoftver). Amikor ez megtörténik, akkor máris kialakult a busz „üzem közbeni” állapota, a CLK-t a vezérlő (itt most beszélő) hajtja, a DAT-ot meg a hallgató (ilyenkor MINDEN ESZKÖZ hallgat, mert az ATN aktív). Ha a vezérlő el akarja kezdeni a „cím + mód” küldését, magasra engedi a CLK-t („d”), erre – miután felkészültek a címzés fogadására – magasba engedik a perifériák a DAT-ot („e”). Erre egyből elkezdi a bitek kiküldését a vezérlő („f”), de ez már ugyan az mint a normál adatátvitelnél. Az egyetlen különbség az ATN alacsony állapota.

A perifériák ATN kezelő logikájának van egy „mellékhatása”, mégpedig az, hogy amikor megváltozik az ATN szintje, a DAT vonalat automatikusan alacsonyba húzza. Ekkor a periféria szoftverének gondoskodnia kell a „logika általi alacsony” kikapcsolásáról, hogy el tudja engedni ezt a vonalat akkor, amikor kell. Viszont ATN változás csak a BYTE-ok átvitele közbeni időben van megengedve, akkor, amikor úgyis alacsony a DAT, és addig maradhat alacsony, ameddig „jólesik” (ezzel várakoztatva a beszélőt). Illetve ha a busz „szabad” (Idle) állapotban van, viszont akkor meg pont „szükséges” ez a viselkedés.

Itt is érdekes az eszköz beszélőnek történő felcímzése, a „hajtásirányok” változása miatt:

A vezérlő a felcímző BYTE utolsó bitjének a kivitele után magasra rakja a CLK-t („a”), „vár egy kicsit”, majd a CLK-t alacsonyba („c”) és a DAT-ot magasba kapcsolja. Erre a hallgatók nyugtázásul a DAT-ot lehúzzák alacsonyra („d”). Eddig minden sima, ez egy egyszerű átvitelvég. A vezérlő ezután bekapcsolja a saját DAT hajtását („e”). Ez a buszon „nem látszik”, mivel az eszközök is alacsonyba tartják (még). Ezután magasra kapcsolja az ATN-t („f”), majd elengedi a CLK-t („g”). Itt nekiáll várakozni, míg a CLK magas. Amikor a felcímzett periféria lehúzza („h”), akkor fejeződik be az irányváltás. A „j”, „k”, „l”, „m”, „n” már a „normális” adatátvitel, csak éppen a szerepek cserélődtek fel.

Pár előforduló eset még vissza van. Az egyik az, amikor egy beszélőtől „vissza kell venni” a buszt a lecímzéshez:

A vezérlő hallgatót játszik és a DAT vonalat hajtja, a beszélő meg a CLK-t. Ezt kell átfordítani. A vezérlő a DAT vonalat elengedi („a”), majd utána a CLK vonalat alacsonyra húzza („b”). De ez eddig is alacsony volt, mivel a beszélő ott tartotta, tehát ez a buszon nem fog változást előidézni. Majd ezután az ATN vonalat alacsonyba húzza (jelezve a címzést...), erre a perifériák automatikusan alacsonyba húzzák a DAT-ot. Ennyi. A hajtások ezzel átfordultak olyanra, hogy a vezérlő tud adni (ha egyből el akarná kezdeni, a DAT alacsonnyal a perifériák várakoztathatják...), a többiek hallgatnak. Beáll az „üzem közbeni” állapot, az „e”, „f”, „g”, „h”, „j”, „k”, „l”, ... már a normál adatátvitel szerint zajlik (egész pontosan a felcímzéses módon).

Van még a GPIB EOI-ból az End funkció, ez egy „érdekes” eset:

A beszélő magasra engedi a CLK vonalat („a”), jelezve az adatátviteli szándékát. Erre a hallgató, ha kész az adatfogadásra, elengedi a DAT-ot („b”). Eddig semmi különös. A normál átvitelnél említettem, hogy a DAT magasra „záros határidőn belül” el kell kezdenie a beszélőnek az adatok kiküldését. Itt viszont nem ez történik. A DAT magas („b”) esetén a beszélő nekiáll várakozni. Ha a „záros határidő” (ez az 1541 esetében pl. 256 körüli órajelciklus) letelik, a hallgató újra alacsonyba húzza a DAT-ot („c”), „vár egy kicsit”, majd ismét elengedi („d”). A beszélő a DAT vonal ezen impulzusára várakozik. Ezt az impulzust a hallgató generálja, és ez az EOI vonal End funkciója, ezt „meg is jegyzi magának”. Ha a beszélő kivárta ezt az impulzust („c” → „d”), akkor elkezdi az adatátvitelt a szokásos módon. CLK alacsony („e”), adatbit kirakása a DAT-ra („f”), „kis várás”, CLK magasra („g”)... De ez már a normál adatátvitel.

Ami még vissza van, az az adatátvitel befejezése funkció, ez az eszköz lecímzése, ezután a busz alaphelyzetbe áll:

A kiküldött kód az utolsó, az ATN aktív, mivel lecímzés zajlik. Ez a kód még simán kikerül a buszra, az utolsó bit átadása („a”) után a CLK alacsonyra („c”), a DAT magasra („b”) kapcsolódik, utána az eszköz nyugtázza az adatátvitelt („d”). Így a busz visszaáll az „üzem közbeni” állapotra. Ekkor a vezérlő az ATN vonalat elengedi („e”), vár egy kicsit, majd elengedi a CLK vonalat („g”). Az ATN elengedésére az eszköz elengedi az addig alacsonyan tartott DAT-ot „valamikor”. Ezzel visszaáll a busz a „tétlen” (Idle) állapotba.

Körülbelül ennyi a „Commodore Serial” busz hardveres működése. Az előző részben volt egy „kis” mese az 1551-es meghajtó TCBM buszáról. Annak a működése ezekhez képest pofonegyszerű, de ha már rajzolgatok ilyen „szép” idődiagramokat, akkor ide kívánkozik az is.

Az 1551-ben két (!) fajta szekvencia van, az egyiknél a gép küld adatot a meghajtó fele, a másiknál visszafele jön adat. Amiatt ilyen egyszerű a működés, mert ez valójában nem is igazi „busz”, csak egy sima pont-pont kapcsolat. Hajtásirány szempontjából csak a 8 adatbit forog.

Ezen vonalakból áll a „busz”:

  • DATA(7..0)Data : Adatvonalak, ezt alapesetben a plus/4 hajtja. Amikor „visszafele” (a meghajtóból a gép fele) jön adat, akkor forgatja az adatirányt. Az átviendő adat kerül majd ki a vonalakra, amelyik bit magas, az „1”, amelyik alacsony, az „0”.
  • ACK(DAV)ACKnowledge : Elfogadás. Ezt a vonalat mindig a plus/4 hajtja, az 1551 figyeli. A gép ezzel „fogadtatja el” a meghajtóval a következő lépést.
  • DAV(ACK)DAta Valid : Adat érvényes. A plus/4 figyeli, az 1551 hajtja.
  • STATUSStatus : 2 bites állapot. Az 1551 hajtja, adatátvitel közben ezzel jelez a gép fele, ha „valami nyűgje van” (pl. EOI).

A kommunikáció az előző részben „ki lett vesézve”, itt csak egy zanzásított összefoglaló következik. Minden átviteli ciklust a gép kezd, a meghajtó erre reagál. Ez így van akkor is, amikor a meghajtó küld adatot a gépnek. (Az előzőekben a gép fogadáskor „csak” várakoztathatta a küldőt, de a küldő kezdeményezett. Itt ilyen esetben is a gép a kezdeményező.)

Először jöjjön az, amikor a plus/4 küld adatot az 1551-nek:

A gép kirakja a DATA vonalakra a „ciklus módjelző” értékét („a”), ami most $81, $82 vagy $83 lehet. → A meghajtó alacsonyba kapcsolja a DAV(ACK) vonalat („b”). → A gép kirakja a meghajtónak ténylegesen elküldendő adatot a DATA vonalakra („c”), majd az ACK(DAV) vonalat alacsonyra állítja („d”). → A meghajtó eltárolja a DATA-n kapott BYTE-ot, beállítja a STATUS-t („e”), majd magasra kapcsolja a DAV(ACK) vezetéket („f”). → A gép megjegyzi a STATUS-t, visszaállítja $00-ra a DATA-t („g”), majd magasra kapcsolja az ACK(DAV) jelet („h”). → A meghajtó törli a STATUS-t („j”).

Egyszerű, de időigényes. A „ciklus módjelző” négy fajta lehet:

  • $81 – Az adat valamilyen címzés lesz. (Előző verziók „mód + cím” értéke az ATN-es ciklus első adata.)
  • $82 – Az adat másodlagos cím lesz. (ATN-es ciklus második adata.) Hogy ezt miért jó külön megkülönböztetni, az jó kérdés, mivel az ATN-es kódokból önmagában kiderül, hogy az esetleg másodlagos cím lesz...
  • $83 – Az adat „normális” adat lesz. (ATN inaktív ciklus.)
  • $84 – A ciklus olvasás, tehát az 1551 fog a gép fele adatot küldeni.

Ebből a fenti ciklus az első hármat használhatja, a negyedik a másik irány lesz, az majd mindjárt. Ami esetleg feltűnhet, hogy nincs EOI (ez nekem már ilyen néven marad meg...) ebben a megvalósításban. A logikába ugyan beleférne, mert simán lehetne egy olyan „ciklus módjelző”, ami az „EOI-s adat” lenne, de nincs. Valójában nincs is szükség rá, mert a gép minden adatátvitel végén végrehajt egy lecímzést, ebből a meghajtó egyértelműen tudja, hogy nem lesz több adat. Visszafele ez nem ilyen egyszerű, ott viszont van „vége” jelzés.

Az 1551-től történő adatfogadás:

A gép kirakja a $84-es „ciklus módjelző”-t a DATA-ra („a”), ezzel jelzi, hogy részéről ADATFOGADÁS kezdődik. → A meghajtó alacsonyra kapcsolja a DAV(ACK) vezetéket („b”). → A gép bemenetre állítja a DATA összes vezetékét („c”), majd az ACK(DAV) vonalat alacsonyra húzza („d”). → A meghajtó beállítja a STATUS-t („f”), kimenetre állítja a DATA-t a saját részéről (mostantól az 1551 hajtja, nem a gép) és kirakja rá a gép számára küldendő adatot („e”), majd magasra állítja a DAV(ACK) vonalat („g”). → A gép beolvassa és eltárolja a DATA-t és a STATUS-t, majd magasra kapcsolja az ACK(DAV) vonalat („h”). → A meghajtó a saját oldalán bemenetre állítja a DATA vonalakat („j”), majd alacsonyra húzza a DAV(ACK) jelet („k”). → A gép kimenetre kapcsolja a DATA-t és $00 értékre állítja („m”), majd újra alacsonyra állítja az ACK(DAV) vonalat („n”). → A meghajtó magasra kapcsolja a DAV(ACK) vonalat („p”) és törli a STATUS-t („q”). → A gép a DAV(ACK) magasára („p”) reagálva magasra kapcsolja az ACK(DAV) vonalat („r”), ezzel befejezve az adatátvitelt.

Ezen irány alatt – amikor az 1551 küld a gép fele adatot – kell valami, amivel az adatok végét jelezni lehet. (EOI...) Erre a STATUS vezetékek %11 állapotát használja a rendszer, ami alapállapotban %00.

A hardveres adatátvitelekről egyelőre ennyit.

Na de mi a búbánat az a fel/le/össze/vissza CÍMZÉS? Meg mi a MÁSODLAGOS CÍM? Meg ilyenek? Ami most jön, az az összes eszközre vonatkozik, amik a fenti buszok valamelyikét használják.

A GPIB-n, illetve a Commodore-féle soros buszon is több eszköz lehet. (A TCBM-en ugyebár csak egy, de a logikát ott is meghagyták, tehát az egy olyan busznak felel meg, amire „pillanatnyilag” csak egy eszköz csatlakozik. Nyilván hardveresen nem is csatlakozhat több.) Ahhoz, hogy az eszközök meg tudják különböztetni, hogy mikor kinek kell kommunikálni, kell valamiféle „azonosítás”. Az „eszközszám”, „egységszám” (Device Number) erre a célra szolgál. A buszra kapcsolódó eszközök közül mindnek van egy saját (általában valamilyen határok között beállítható) száma. Ez a szám egy 5 bites érték, tehát 0..31 tartományba esik, két egyforma egy időben nem lehet jelen. DE! A Commodore az első négyet „lefoglalta” a számítógépeiben saját célra. (0: Keyboard, 1: Datasette, 2: Serial port, 3: Display.) Ez „csak” annyit jelent, hogy a 0..3 címek „megszólítása” nem jut ki a buszra, ezt a KERNAL máshogy kezeli. A 4 ill. afölötti egységszámokat keresi csak a gép a „külvilágban”. Alapesetben a 4..5 egységszám tartozik a nyomtatóhoz, 8..11 (..15) meg a meghajtóhoz. Illetve az eszközszámból a 31-es sem használható, az foglalt a lecímzéshez (lásd később).

Amikor a buszra első lépésben kikerül a „mód + cím”, akkor ebből a „cím” rész maga az egységszám. Ez a BYTE valahogy így néz ki:

  • B7..B5 – Mód: %001: hallgató (Listener), %010: beszélő (Talker)
  • B4..B0 – Egységszám, 4..30 ($04..$1E)

Tehát a hallgatók „száma” $24..$3E, a beszélőké pedig $44..$5E tartományba esik. Ha például egy alap 8-as eszközszámú meghajtónak akarok adatokat küldeni, akkor $28 lesz a felcímző BYTE értéke. Ha fogadni akarok tőle, akkor $48. A lecímzés egyszerű: a 31-es egységszám van erre fenntartva. $3F: UnListen kód, vége a hallgatásnak, $5F: UnTalk kód, vége a beszédnek. Ezek „globális” kódok, az összes eszközre érvényesek.

A másodlagos cím valójában másodlagos parancs lenne, ez $60..$FF tartományba esik, és mindig eszközfüggő a működésük. Nem is mindig van rá szükség. A meghajtók esetében viszont kell az... (Itt most a Commodore-féle meghajtók másodlagos címeiről lesz szó.) A SECONDARY ADDRESS alsó 4 bitje egy-egy un. csatornát jelöl ki. Ez arról szól, hogy ha egy fájlt megnyit a meghajtó, akkor ahhoz hozzárendel egy puffert (még a meghajtón belül). Ez a puffer azért kell, mert a meghajtó csak 1-1 blokkal tud dolgozni, átmenetileg ebben a pufferben vannak az adatok. Az SFD1001-nél ebből van 15 (15 db. 256 BYTE-os terület), az 1541/1551 esetében jóval kevesebb, talán 5? (A pufferek lehetséges számával arányos az, hogy hány fájl lehet egyszerre nyitva. Mármint a meghajtó részéről!) A csatornák száma 0..14. a 15-ös csatorna a „parancs-csatorna”, ezen keresztül lehet kiadni a meghajtónak az egyéb parancsokat, pl. a lemez formázását, illetve lekérdezéskor ez a „válaszcsatorna”, esetleg a „hibacsatorna”, ha valami „baj van”, innen tudható meg hogy mi. Illetve van még két kitüntetett szerepű csatorna, a 0-ást lehet használni betöltéskor (LOAD), az 1-est mentéskor (SAVE). De ez csak az alsó 4 bit. A fölső 4 bit a következő értékeket veheti fel:

  • %0110: $60..$6F tartomány: akkor van használva, ha az adott csatornával van valamilyen kommunikáció.
  • %1111: $F0..$FF tartomány: akkor van használva, ha egy fájlt akar a gép megnyitni. Ennek a segítségével küldi el a fájlnevet a gép a meghajtónak.
  • %1110: $E0..$EF tartomány: az előzőleg megnyitott fájt ezzel lehet lezárni.

(A szabvány ezeket a tartományokat külön nevezi, a $20..$3F tartomány a LAG (Listener Address Group), a $40..$5F pedig a TAG (Talk Address Group), a $60..$FF tartomány az SCG (Secondary Command Group). A felcímzés közben előfordulHATó összes BYTE önmagában is értelmezhető, a 256 variációs lehetőség mindig a meghatározott csoportba esik. Ezeken felül van még jó pár kód, ami a szabvány szerint „jelent valamit”, de ezek itt nincsenek implementálva.)

Mindez mit is jelent a gyakorlatban? Amit eddig leírtam, azt szerintem még én se érteném elolvasás után, nem árt néhány példa. Első körben egy sima LOAD ”TESZT”,8 parancs következik. Ebben a fájlban legyen egy darab $55-ös BYTE, ami a memóriában $1001-re kerülne.

Kezdődik a fájl megnyitásával, ez a 0-ás csatornához hozzárendeli a „TESZT” nevű fált:

  • ATN + $28 : Felcímzés, 8-as egység, az eszköz hallgató lesz (Listen)
  • ATN + $F0 : Másodlagos cím: a 0-ás csatornához a következő fájt rendelje hozzá a meghajtó
  • ......$54 : „T”
  • ......$45 : „E”
  • ......$53 : „S”
  • ......$5A : „Z”
  • EOI + $54 : „T” – Fájlnév karakterei, az utolsó BYTE „bejelölve”
  • ATN + $3F : Lecímzés (UnListen)

Ezután „el kell hozni” az adatokat:

  • ATN + $48 : Felcímzés, 8-as egység, az eszköz beszélő lesz (Talker)
  • ATN + $60 : Másodlagos cím, a 0-ás csatornából jöjjenek az adatok
  • ......$01 : 1. BYTE a fájlból: cím ($1001) alsó része, már a meghajtótól jön
  • ......$10 : 2. BYTE a fájlból: cím ($1001) felső része
  • EOI + $55 : 3. BYTE a fájlból: az egy BYTE-nyi adatunk, jelezve, hogy vége
  • ATN + $5F : Lecímzés (UnTalk), ezt már ismét a gép küldi

A végét érzékelve a gép a lecímzéssel befejezi az adatok áthozását. Viszont a 0-ás csatornához még mindig hozzá van rendelve a ”TESZT” nevű fájl, ezt „le kell zárni”:

  • ATN + $28 : Felcímzés, 8-as egység, az eszköz hallgató lesz (Listen)
  • ATN + $E0 : Másodlagos cím: a 0-ás csatorna lezárása
  • ATN + $3F : Lecímzés (UnListen)

Ahhoz, hogy ezt így történjen, kell egy fájl a lemezen ”TESZT” néven. De hogyan kerül ez oda?

Először itt is meg kell nyitni a megfelelő csatornát:

  • ATN + $28 : Felcímzés, 8-as egység, az eszköz hallgató lesz (Listen)
  • ATN + $F1 : Másodlagos cím: az 1-es csatornához a következő fájt rendelje hozzá a meghajtó
  • ......$54 : „T”
  • ......$45 : „E”
  • ......$53 : „S”
  • ......$5A : „Z”
  • EOI + $54 : „T” – Fájlnév karakterei, az utolsó BYTE „bejelölve”
  • ATN + $3F : Lecímzés (UnListen)

Utána át kell küldeni az adatokat, ami a fájlba kerül:

  • ATN + $28 : Felcímzés, 8-as egység, az eszköz hallgató lesz (Listen)
  • ATN + $61 : Másodlagos cím: az 1-es csatornába mennek az adatok
  • ......$01 : 1. BYTE a fájlba: cím ($1001) alsó része
  • ......$10 : 2. BYTE a fájlba: cím ($1001) felső része
  • EOI + $55 : 3. BYTE a fájlba: az egy BYTE-nyi adatunk, jelezve, hogy vége
  • ATN + $3F : Lecímzés (UnListen)

Ezután a maghajtóval le kell záratni a fájlt (különben lesz egy 0 hosszúságú, nem lezárt fájl a lemezen):

  • ATN + $28 : Felcímzés, 8-as egység, az eszköz hallgató lesz (Listen)
  • ATN + $E1 : Másodlagos cím: az 1-es csatorna lezárása
  • ATN + $3F : Lecímzés (UnListen)

Ez így mind szép és jó. De mi van, ha mégsem? Azaz ha van valami hiba? (Nincs a meghajtóban lemez, nem található a fájl, stb...) A rendszerben látszólag nincs olyan jel, adat vagy bármi, amivel a külső eszköz erről a tényről a gépet tájékoztathatná. Persze meg van ez oldva, még ha nem is túl elegánsan.

Először is, talán érdemes pár szót vesztegetni a KERNAL eseménykezelésére. Azok a rutinok, amik a fel/lecímzéseket, illetve az adatátviteleket kezelik, ~mindig visszatérnek. Hogy a futásuk alatt történt-e valamilyen esemény, azt egy speciális memóriacímen eltárolják. Ennek a memóriának neve is van, ez a Status, vagy röviden ST. A plus/4 esetében ez a $0090-es memóriacímen található, a „PRINT ST” BASIC parancs ennek a tartalmát adja vissza. Ennek a BYTE-nak a bitjeihez külön-külön van valamilyen „esemény” rendelve. A fenti kommunikációt megvalósító KERNAL rutinok az ST bitjeit NEM törlik, csak be tudják állítani. Törölni „kézzel” kell. Annyi általában elmondható, hogy „normális működés közben” az értéke $00. Hibakezelésnél az a feladat, hogy minden egyes lépés (címzés, adatátvitel) után meg kell vizsgálni az állapotát, ha <> $00, akkor „valami van”. Hogy mi az a valami? Az ST azon bitjei, amik most jelentenek valamit:

  • B7: „DEVICE NOT PRESENT” – Egység nincs jelen
  • B6: EOI – Az adat az utolsó
  • B1: Időtúllépés adat fogadásakor
  • B0: Időtúllépés adat küldésekor

A maradék 4 bit itt nem számít, azok a „magnó” esetén vannak csak használva. A B7 az egyértelmű: ha a megcímezendő eszközt nem éri el a KERNAL, ez 1 lesz. A B6 is egyszerű: ha 1, akkor a bejövő adatok közül megjött az utolsó is. (Pl. betöltésnél ezt a bitet kell vizsgálni minden BYTE áthozása után, innen derül ki, hogy van-e még vissza.) A B1 ill. B0 az, ami most érdekes lesz, ugyanis ezzel jelzi a KERNAL azt, hogy az adott feladatot a meghajtó hogyan oldotta meg. De hogyan is „állítódik be” ez a két bit?

A legegyszerűbb eset az 1551-nél van, a TCBM busz két STATUS vezetéke ehhez a két bithez van hozzárendelve. Amennyiben az állapotuk %11, akkor az EOI (B6) állítódik 1-be, %10 ill. %01 esetén a B1 / B0. (Minden egyes adatátviteli ciklusnál a STATUS két bitje „beállítódik” az ST két (illetve az EOI-val együtt három) bitjébe. Nem úgy másolódik oda, mert az alacsony vonal nem törli az ST hozzá tartozó bitjét, csak a magas állítja 1-re.) Bonyolultabb az eset a soros portnál, illetve a GPIB-nél, mivel ott nincs ehhez semmilyen külső hardveres segítség.

A sima soros verziónál adatfogadáskor annyi történik, hogy a beszélő magasra engedi a CLK-t, jelezvén az adatküldési szándékát. Erre a vezérlő elengedi a DAT-ot, jelezve hogy jöhet az adat. A beszélő meg ahelyett, hogy elkezdené küldeni az adatokat, csak vár... Először lejár az az idő, amire a vezérlő megcsinálja az EOI regisztrálását, de a beszélő még ezután is csak vár... Majd a vezérlő ha megunta :), akkor regisztrál egy „Időtúllépés adat fogadásakor” jelzést az ST-ben. Néha szükség van a vezérlő várakoztatására (pl. be kell olvasni a következő blokkot...). Ekkor a beszélő csak simán nem kezdi el az adatküldést. Ha hibát akar jelezni, akkor elkezdi, de nem fejezi be. Ronda... :) De az adatkiküldés még randább. Ha valami miatt a meghajtó nem tudja fogadni az adatot (mentésnél nincs lemez a meghajtóban, pl...) akkor simán 1-be rakja a DAT-ot, amire egy „DEVICE NOT PRESENT” jelzés keletkezik. :)

A GPIB esetén is vannak érdekességek. Adatfogadáskor a beszélő egyszerűen nem kezdi el az adatküldést (DAV nem megy alacsonyba). Ha egy bizonyos ideig nem kezdi el a ciklust, az sima TimeOut esemény, az ST B1 beáll. Viszont a vezérlő várakoztatására itt is szükség lehet. Ez is elég ronda... Amikor a beszélő várakoztatni akar, akkor az előző átviteli ciklust nem fejezi be. (A DAV alacsony marad addig, ameddig a következő adat rendelkezésre nem áll.) Ezen a ponton nincs időzítés, addig lehet a DAV aktív, ameddig jólesik. :) Adatküldésnél a vezérlő a DAV aktiválása után várja, hogy a hallgató elszedje az adatot, majd beállítsa a NRFD / NDAC vonalakat a megfelelő módon. Na, erre várhat... :) Ennek is egy „DEVICE NOT PRESENT” jelzés lesz a jutalma.

A KERNAL alap buszkezelő rutinjai ezeket a hibákat „adják vissza”, a „fölötte levő réteg” ad ezeknek tényleges hibaüzenetet. De az csak „találgatás”, valódi hibakód a gép számára nem áll ezek után sem rendelkezésre. Azt úgy lehet megtudni, hogy a meghajtó hibacsatornáját le kell kérdezni, ott „elmagyarázza” szövegesen is a „baját”. Ez egy kicsit – hogy is mondjam – nehézkes. Elegánsnak semmi esetre se nevezném... :)

Nos... Valahogy így zajlanak ezek a dolgok. Az egész „borzalmasan lassú”, a Commodore mérnökei úgy gondolhatták, hogy „Nem baj, a Dear Customer ráér”. Manapság már nem jutnának messzire ezzel a hozzáállással. Annak idején elég sok bénaságot elnéztünk a hardvernek, örültünk hogy működött valahogy. A hiányzó sebességet szoftverből pótoltuk, ahol csak lehetett. Ma a hardveresek törik össze magukat, hogy megfelelő sebességgel menjen minden, a szoftveresek állnak úgy hozzá a feladatokhoz, hogy a Dear Customer majd vesz gyorsabb hardvert. :)

A fenti dolgok nagy része természetesen szimplán kitaláció, de a valósággal való bármilyen egyezés nem csak a véletlen műve.

Ide a végére egy (nekem legalábbis) jó hír: az SFD1001-em köszöni szépen, jól van. Szerencsére „csak” az egyik CPU fáradt el benne, azt kicserélve egyből elindult.

„Irodalom”:

balagesz

---

2013.08.05.
2013.09.15. GPIB irányváltás egyszerűsítése, hibakezeléssel kapcsolatos kiegészítés
2015.08.02. Wavedrom név + link javítás
2019.12.10. D8.

Hozzászólások

Szenzációs, öröm volt olvasni az egészet, köszönöm! :)

Az övé, mert ÉRT HOZZÁ!

Apropó, nem tudom, hogy ilyesmi témában van-e valami tudományos folyóirat (bár miért ne lenne?), nem gondolkodtál még el rajta, hogy valami külföldi lapban publikáld ezeket? Akár még egy phd is megállna ebből, "miért ne?" alapon.

----------------------------------------------------------
"One should strive to achieve; not sit in bitter regret."
www.xonotic.org

Hogyne. Műszaki körökben nem tudom, van-e ilyen, de gyógyszerészetben simán létezik. mármint cikk.

Nomeg itt azért nem kevés programozás és kísérletezés is volt.

----------------------------------------------------------
"One should strive to achieve; not sit in bitter regret."
www.xonotic.org

Azert ne legyunk naivak; ez egy 25-30 eves (!) technika. Az informatikaban ennek a tizede alatt is akkorat valtoznak a dolgok, hogy ihaj. Eleg keves embert erdekel ez a tema... A "miert ne?" kerdes az jo. Sajnos az angolom erosen konvergal a nulla fele, igen sokat kene fejlodni meg csak a gondolatahoz is. :) (Bar erre inkabb a :( illik.)

bus, akarom mondani, sub.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. 

Üdv!

Szép leírás!
A 1551-es kommunikációval kapcsolatban szeretnék kérdezni.

A paddle mindenképp szükséges a meghajtóval való kommunikációhoz?
A sz.gép és a paddle közötti adatfolyam lekövethető oly módon, mint a leírásodban van?
Pl.: A gép kirakja a DATA vonalakra a „ciklus módjelző” értékét („a”), ami most $81, $82 vagy $83 lehet. .
Akkor a sz.gép és a paddle között is ez az érték jelenik meg? ($81...)
Ha mindenképp kell akkor mennyiért gyártanál le egy darabot belőle?
Márpedig biztos kell, mert a 1541-hez megcsináltad. -.-
Lenne egy 1551-es maghajtó aminek hiányzik a paddle-e.
S ha tudnám hogy valamilyen módon hozzájutnék, (legyártod, vagy kellő információk birtokában
és is legyártom a nyákot és felprogramozom a hardvert) akkor megvenném. :)

Üdv!

A paddle természetesen szükséges; a benne levő hardver maga az interfész. Nem csak egy sima csatlakozó átalakítás. (A soros porthoz tartozó elektronika alapból be van építve a gépbe, de az 1551 által használt TCBM busz nincs kiépítve, azt valósítja meg a paddle.)

A gép és a meghajtó közötti kommunikáció "lekövethető", de ez azokon a vezetékeken "látszik", ami a paddle meg a meghajtó között van. Emiatt ez nem hagyható ki a történetből.

Gyártani? Hány darab kellene belőle? 100? :) (Az ilyen drótozgatásos történet jó móka, de annyi vele a munka, hogy ezt másnak eszembe se jutna bevállalni, nincs az a pénz... :) ) Az eredeti hogy tudott "elveszni"? Összeszerelt állapotban egyik oldalon sincs bonthatóra kialakítva a kábelezés. Amúgy itt találsz még információt a működésről, magában a paddle-ben nincs semmi ördöngösség, ha csak az nem, hogy az egyik IC nem szerezhető be. (A másik se, de arra van megoldás.) Azt ki lehet váltani egy CPLD-vel (mint itt), de ha most kellene ilyet terveznem, nem tudom mit használnák fel hozzá. (Az itt használt típust sem gyártják már, hurrá... :-| )

Szerk.: Egyébként mi a cél? "Csak működjön", vagy a teljes kompatibilitás is fontos? Az eredeti felállásban csak a 8 adatvonal iránya változik adatátvitel közben, ott is egyszerre mind. A többi vonal iránya fix, így az adatirány-regisztereket nem szükségszerű implementálni, az adathoz meg elég egy bit. Úgy az eredeti KERNAL rutinok már tudják használni a meghajtót, de hogy a "lelkes amatőr kóderek" milyen módon használták a hardvert, az jó kérdés. Ehhez elég lehet "pár" tároló / meghajtó IC, nem kell szükségszerűen (bármilyen) PLD. Az a kérdés, hogy mit tudsz te megcsinálni? Elmesélek én bármit... :-D

Csak 1db. kellene. Én nem csináltam vele semmit. Azt Sidi-től kellene megkérdezni, mert ő kínálta eladásra a paddle nélküli meghajtót.
Cél a meghajtó teljes rehabilitása lenne. :) Hogy mit vagyok képes legyártani? Bármit amihez van kapcsolási rajz meg program. Az Eagle-el mindent meg tudok rajzolni! :). Nekiálltam a CPLD lelkivilágának felderítésének, mert az írásodat alapján az nem is olyan nehéz. De.... :) Ha elkészülne, biztos még sokszor "zaklatnálak" a kérdéseimmel.

"Rehabilitáció"? :-D Ismerős szitu. (Én is "szeretem" a működőképes kövületeket, nem az számít hogy "gyári állapotú" legyen, inkább működjön. Még ha értelme sok nincs is... :) ) Kipróbált (!) kapcsolási rajzot azt ne kérj tőlem; a CPLD-s fejlesztés egyik nagy előnye, hogy - természetesen bizonyos megkötésekkel - szabadon lehet a bekötésekkel variálni. (A CPLD "lelkivilága", legalábbis egy jelentős része pont ezekről a megkötésekről szól.) Ha a működéssel kapcsolatban bármilyen kérdésed merülne fel, arra szívesen válaszolok.

Elkezdtem a paddle nyáklap szerkesztését.
Azt írtad,hogy a gyártó megszüntette az 5V.-os CPLD gyártását.
Valami más alternatíva a helyettesítésére? Ha már mindent helyettesítesz valamivel!:)
A paddle nyák érintkezőinek megtervezése kicsit körülményes volt mert már rég
terveztem nyákot.
Azt nem értem ,ha ennyi tudással rendelkezel akkor miért nem fejlesztesz? Azt írod ,hogy minek, meg kinek! Tapasztalatom szerint sok őrült van a világon, aki az újdonságokra kapható, lásd C64.
Jó a pluszi nem C64, de nekem ez volt az első gépem és mindennél többet ér még ha sokan nem is szeretik!

http://imagizer.imageshack.us/v2/1024x768q90/909/lXYpzQ.png

Közben sikerült fellelnem egykét helyen XC95108, 9572-t is! Hurrá! :)

Az XC95xx-es szériát a 3.3V-os verzióval lehet úgy-ahogy helyettesíteni, de ebből a legkisebb verzió létezik csak PLCC tokozásban. (A többi leginkább valamilyen QFP, ahhoz meg mindenképpen nyákot kell csinálni, proto-s módon nem szerelhetők.) A szériának amúgy van egy nagyon nagy előnye, a teljesen rugalmas kimenet-engedélyező logika, ami miatt az ilyen kihelyettesítésekhez ideális tud lenni. Egyéb gyártóktól más típusokat annyira nem ismerek, de amit láttam, ott nincs meg ez a szabadság.

A paddle-nyák szerkesztéséhez... Ha már CPLD-ben gondolkozol, az XC9572 tökéletesen elegendő a feladatra, én is azzal csináltam meg. ("Elfekvő" készletekből egy darabig biztosan lehet még venni, de a gyártást megszüntették, a gyártó az oldalán már nem is listázza.) De ha már CPLD; ennek a toknak van elegendő "erőforrása" arra is, hogy a komplett paddle áramkör a címdekóderrel együtt belefér, fölösleges az FPLA helyettesítését külön megcsinálni.

(Tervezgetni azért szoktam dolgokat, de a plus/4-es "társadalmat" sajnos nem lehet összehasonlítani méretben egy C64-gyel, egészen mások a mennyiségek. Azért persze tervek vannak. :) )