Retró rovat V: Ez is kerreg, viszont legalább kuriózum...

Újra itt volt a Mikulás, én meg adós vagyok még – leginkább magamnak – az SFD1001 (Single Floppy Drive?) körbejárásával. (Hosszú lesz, ígérem! :) ) Ez még nagyobb kuriózum, mint a C128. Gyors keresésem a neten nem hozott valami értelmes találatdömpinget, nem egy túl ismert meghajtóról van szó. (Ellentétben az 1541 típussal...) Annyira, hogy a „kiadás” időpontja sem tiszta.

A fenti Wiki oldal szerint 1984/85 a készítés éve, viszont a meghajtóban lévő elektronikán ©1983 látható:

Ezen felül a nyákon található alkatrészek (IC-k) közül az összesen 1983 vagy előbbi dátumkód szerepel. Számomra emiatt inkább az 1983-as év tűnik a megfelelő dátumnak, de ez csak annyiból érdekes, hogy az idén 30 éves a stuff. (Vajon mi lesz a mai kütyükkel 30 év múlva? Ha aktuális lesz, visszatérek rá, ígérem! :) ) Ez a 30 év amiatt is figyelemre méltó, hogy még működnek az akkor felprogramozott EPROM-ok. (Ugyan a korabeli Commodore gépekben maszkprogramozott ROM-okat találni, de ebben például van egy EPROM is, erről majd később.) Most direkt nem keresek EPROM adatlapot, de ilyen 10 év körüli „garantált” idők rémlenek, ameddig megtartják a programozás után a tartalmat (természetesen a „legrosszabb körülmények” között). A régi cuccokat talpra állítóknak lassan erre is oda kell majd figyelni... De vissza a „kuriózumságra”: erre utal a sorozatszám is, ez az 5219-es számú nyák, a külső típusmatricán meg még ennél is kisebb szám szerepel:

Igen, ez a 4742. darab. Ahhoz elég magas ez, hogy valami kezdő széria legyen (tehát az 1983-as „piaci bevezetés” még inkább valószínű), ahhoz meg elég alacsony, hogy ne egy igazi tömegterméket sejtsek mögötte. Azért jó látni olyan eszközt, amin még Made in Japan felirat szerepel, nem PRC.

Az ilyen régiségek úgy szoktak érdekelni, ha természetesen működnek is. Én inkább vagyok a „híve” a működőképes állapotnak, mintsem a kizárólag gyári alkatrészekből álló (autentikus), de esetleg rossz eszköznek. (Annak ellenére, hogy valódi használati értékük már nincs, mégis „jó érzés”, ha működik valami. Tudom, ez vagyok én...) A múltkori „elemezgetés” közben viszont a saját példányom úgy döntött, hogy tovább már nem hajlandó a biteket tologatni, és szépen elpusztult. Egy olyan jelenséget produkált amit eddig még sosem láttam: hibakódot villogtatott. Ez azért „furcsa”, mert ahhoz, hogy a firmware idáig eljusson (ti. fusson az a kód, ami a hibakódot „morzézza”), ahhoz az elektronika egy igen jelentős részének működnie kell, és ami hibás, az sem „foghatja a buszt”. Ez az állapot viszont ritkán áll elő, sajnos. Ráadásul ez az SFD1001, és az én esetemben hatványozottan igaz, no de csak sorjában. A LED villogások száma alapján a következő hibák lehetnek:

  • 1: Zero Page 6532 UC1,UE1
  • 2: ROM $E000-$EFFF 2364 UL1
  • 3: ROM $C000-$DFFF 2364 UH1
  • 5: Zero Page 6530 6502 UK3 UH3
  • 6: Common RAM $1000-$13FF 2114 UC4,UC5
  • 7: Common RAM $2000-$23FF 2114 UD4,UD5
  • 8: Common RAM $3000-$33FF 2114 UE4,UE5
  • 9: Common RAM $4000-$43FF 2114 UF4,UF5
  • 10: Controller ROM 6530 6502 UK3 UH3

Ez a lista (Disk drive error codes szekció) ugyan a 8050/8250 meghajtókról szól, de az SFD1001 tulajdonképpen egy egy lemezt kezelő 8250, bitre azonos DOS-szal. A hibakódok itt is ugyanezek, a lehetséges hibás IC-k pozíciószámai mondjuk nem stimmelnek, de ez legyen a legnagyobb gubanc.

Az én meghajtóm ebből az 5-ös kódot villogta, ami – mondjuk úgy – nem csalt mosolyt az arcomra. Ez az FDC-hez tartozó 6530, vagy 6502 tokot jelenti. Viszont tapasztalat szerint ha kiveszem az FDC-s CPU-t, akkor a „fő” CPU végtelen várakozási ciklusba kerül, így nem lesz villogás. (A DOS alapján nem világos hogy miért is van így, még „nem másztam bele” a témába.) Tehát igen furmányos módon kell annak a CPU-nak meghalnia, hogy legyen utána hibakód. (Ha esetleg nem világos, hogy miről szövegelek: a meghajtóban két CPU van, az egyiket jelzi lehetségesen hibásnak, a másik meg villogtat ilyenkor.) Emiatt én a 6502 hibásságára „nem fogadtam volna nagy összegben”.

Inkább a 6530 tűnt esélyesnek, ez volt a „szomorkodás” oka. Ez a tok egy RRIOT, azaz egy ROM / RAM / I/O / TIMER modult is magába foglaló IC. Beszerezni elég esélytelen. A ROM része természetesen „maszkprogramozott”, de ez a része nem lényeges, mivel AMÚGY SEM KÉSZÜLT az SFD1001-be való RRIOT. :) A meghajtóban lévő IC egy plusz nyákon van elhelyezve, és „ki van peccselve” a ROM-ja, a hozzá tartozó kód egy külső EPROM-mal van implementálva. (Az lehetett a terv, hogy ha meglesz a megfelelő darabszám, akkor majd készül hozzá RRIOT, a plusz kiegészítést így el lehet hagyni. Mivel megmaradt, ez is jelzi a széria „nagyságát”.) Tehát a RRIOT ROM tartalma nem lehet probléma, van viszont más is. Ennek a „dögnek” nem csak az 1K-nyi ROM tartalma maszkprogramozható, hanem a belső dekóder logika egy része is. (Milyen külső vezérlőjel kombinációkra milyen belső részegység engedélyeződjön.) Emiatt hiába nem kell a belső ROM, más készülékben lévő RRIOT nagy valószínűséggel mégsem használható. (Nehogy esély legyen egy cserére... Ez direkt szívatás így? :) )

Itt már láttam a „szomorú sorsomat”, hogy újra előszedhetem a kedvenc pákámat, illetve játszhatok „CPLD fejlesztőst”, de előtte még kipróbáltam azt, hogy felcseréltem a két 6502-est egymással. Ebben az esetben bekapcsoláskor nem volt semmilyen villogás. Ez már fél siker, a hibásnak vélt példányt kicserélve egy NOS Rockwell 6502A-ra, szépen elindult. Így a javítást elég hamar sikerült letudni, pedig már kezdtem beleélni magam egy „saját” 6530 implementálásába. (Az SFD-ben eléggé egyszerű módon vannak ezek a periféria IC-k használva, az egész funkcionalitást amúgy sem kellene megvalósítani.) De ez most – szerencsére vagy sem – elmarad.

Na de miről is írtam már ennyit? Erről ni:

A jobb oldali „kopásnyomot” leszámítva csak poros, meg sem látszik rajta a felnőtt kor. Na de nem kívülről csodálni vagyunk itt, viszont most – eltérően az eddig megszokottaktól – kezdeném inkább az „alapoktól”:

A táp rész mechanikai felépítése eltér az 1541-től, ott a „fő” nyákra van felszerelve az egyenirányítás + pufferek + áteresztő stabilizátorok. Itt ez kapott egy külön nyákot „egy szinttel lejjebb”. A hűtőborda a fém tartó keretre is fel van csavarozva, ráadásul hővezető pasztával vannak összerakva. (Ez a „zsír” még mindig puha / kenhető állagú, mintha nem is 30 éves lenne. Ilyet se láttam még...) Emiatt ezt inkább nem bontom meg jobban. Amúgy jópofa ez a „szerelő keret”, ez még az 1541-nél (a régi típusnál, tehát az ilyen házba levőnél) ill. 1551-nél is megvan. Azután valahogy „kiment a divatból”. (Azok a fránya költségek...) Erre van felcsavarozva minden kütyü, majd a külső házba ennél fogva egy egységként van beszerelve. („Élő szövet a fémvázon”. Ja, nem. :) ) Maga a táp itt is egy sima áteresztős feszültségstabilizátor, melegszik is ahogy szokott:

Előtérben a két Graetz-híd rajtuk külön hűtőbordával, mögöttük a pufferek, a háttérben a két stabilizátor IC. (SI3052V ill. SI3122V, ezek 2A-es 7805/7812-nek felelnek meg.) Ezek a szokásos két feszültséget állítják elő, egy +5V-ot illetve egy +12V-ot. De mi jön még ebbe a keretbe? Például a mechanika:

Ez sem egy „szimpla eset”. A mechanika formája amúgy nagyon is emlékeztet valamire:

Kísérteties a hasonlóság. A bal oldali az SFD1001-é, a jobb oldali egy sima „pc-s” nagy floppy meghajtó egy kissé szétborítva, mindkettőről hiányzik a fej fölött lévő takaró. Még a fejkábel csatlakozó kiosztása is egyforma, mondjuk a csatlakozó mérete nem. :) Persze nem akkora csoda a hasonlóság, mindkettő Panasonic/Matsushita. A fehér mechanika már egészen „új”, a fejet vonóorsó mozgatja. Az SFD-nél még a szokásos léptetőmotor + acélszalag kombináció a felépítés, de itt is van egy csavar a dologban. A „szabvány” HD-s meghajtók 96 TPI-s sűrűségűek. A Commodore gondolt egy merészet, az ő nagy sűrűségű meghajtóik 100 TPI-s mechanikájúak. Esélytelen a csere, ha mondjuk egy fejhibával futnák össze. (Ami nem egy elképzelhetetlen történet amúgy, a kezeim között eddig két 1551 is megfordult ezzel a hibával, de az SFD-nél nem akarok ezzel találkozni...) Nem véletlen a HD-s meghajtóval való hasonlítás, mert az SFD-ben levő fej 77 sávot ír/olvas oldalanként. „Hivatalosan” valamilyen speciális lemezt kellene hozzá használni (NEM DS-HD-t!), de szerencsére bármelyik jobb minőségű DS-DD-s korong megteszi.

A lemezt egy „direktmotor” forgatja, mindezt 1983-ban. (Ezek után mi a búbánatnak szívatta a felhasználóit a Commodore a későbbi meghajtóiban a lapos szíjas hajtással? Gondolom olcsóbb volt...) A sebesség – a szokásos – 300 RPM, ez is egy eltérés a pc-s HD-s meghajtók 360-as értékéhez képest. A mechanikának amúgy van index-lyuk illetve Track00 érzékelője is. A DOS – természetesen – egyiket se használja, ez is „kerreg” ha úgy hozza a sors. (Ráadásul a fejet a firmware gyorsabban mozgatja az 1541-es alap sebességnél, a „zörgés” meglehetősen csúnyának hangzik, de normális.)

A keretre már csak a „mini méretű” elektronika jön rá:

A csatlakozók is a helyükre csatlakoztatva, erre már csak a tető jön, és össze is állt a cucc. Ez a „mini méretű” elektronika egy komplett alkatrésztemető, mindenesetre megér egy elemzést. Az SFD1001 – mint említettem – egy fél 8250-es meghajtó. A 8250 egy két lemezt kezelő „csöppség”, ez meg egyszerre egy lemezt tud forgatni. Ez a „felezés” a külső méreteken igencsak tetten érhető, de az elektronikán nem igazán látszik. Valójában a fejek kezelését segítő MUX/DEMUX elektronika fele kell csak (pár tranzisztor / dióda / ellenállás elmaradhat), meg a másik mechanika léptetőmotor meghajtása hagyható el. Aztán körülbelül ennyi. Ami talán tényleg spórolás, az a fej olvasó erősítője, a duál meghajtóban az „sima” műveleti erősítős felépítésű, itt meg bekerült egy erre a célra tenyésztett IC-be. Illetve az író elektronika meghajtó egy része egy vastagréteg hibrid IC-be költözött, de ezek jók lennének a régi meghajtóban is, emiatt nem számít. Ezért aztán ez a készülék sem lehetett túl olcsó. Valójában nem is értem az egészet: a Commodore-nak ott volt a MOS (megvették őket kilóra), tehát volt egy saját csiptervező / gyártó részlegük. (Abba most ne menjünk bele, hogy a MOS által gyártott félvezetők hírhedtek voltak megbízhatóság terén...) Simán tervezhettek / gyárthattak volna megfelelő ASIC-eket a feladatra (ezt később más meghajtókhoz meg is tették), ehelyett ez tele van általános perifériavezérlőkkel / kapuáramkörökkel. Az elején emlegetett RRIOT talán egy lépés ebbe az irányba, de mindenesetre fura... (Ha esetleg a csiptervezés annyira lassú folyamat volt, hogy „nem érte meg”, az is sokat elárul... :) ) Eléggé „szedett-vedett” benyomást kelt a tervezés, de erre lesz még később is példa.

No de hogy is működik a vas?

A „fő” egységeket bekereteztem. Első körben talán a sárga színnel bekeretezett órajel-generátorról essen pár szó. Az alapórajel – ellentétben az 1541 16 MHz-es frekvenciájával – itt 12 MHz. Ez első körben leosztódik hárommal, majd a maradék még kétszer kettővel. Az így kapott 50%-os kitöltési tényezőjű 1 MHz-es négyszögjel lesz a processzorok órajele. Ebből az osztó áramkörből még „kijön” a 12 MHz kettes osztása, ez a 6 MHz-es frekvencia van tovább osztva 16, 15, 14 illetve 13-mal, ebből jön ki a kívánt bitsebesség, amit a lemezre íráskor / onnan olvasáskor alkalmaz az elektronika. Tehát (már) itt is megvan a négyféle bitsebesség, mint amit az 1541 használ. Viszont ahhoz képest hogyan is állnak ezek a bitsebességek?

  • 12MHz/2/16 = 375000.00 BPS (Legkisebb sűrűség a belső sávokon)
  • 12MHz/2/15 = 400000.00 BPS
  • 12MHz/2/14 = 428571.71 BPS
  • 12MHz/2/13 = 461538.46 BPS (Legnagyobb sűrűség a külső sávokon)

(Érdekesség: az órajel-generátor áramkörében van egy nyákfóliából kialakított Jumper (S19 / S20), ezzel az író/olvasó elektronika 6 MHz-es órajelét át lehet állítani 4 MHz-re. Átkapcsolva pont olyan bitsebességek jönnek ki mint az 1541-nél. Megfelelő mechanikával ugyanez az elektronika tudná kezelni az 1541-es meghajtó által írt formátumot, persze kell a hozzá való firmware is.) A lemez 300 RPM-mel forog, ez 5 fordulat másodpercenként. A fenti bitsebességeket így 5-tel osztva kijön, hogy egy sávon hány bit fér el az adott bitsebességnél.

Ez a meghajtó is ugyanúgy GCR módon rögzíti az adatokat mint az (immár sokadszor emlegetett) 1541, sőt, a felírt blokkok felépítése is teljesen azonos. Azért két említésre méltó különbség akad: az egyik, hogy a fejléc meg az adatrész hossza nincs kiegészítve olyan méretűre, hogy osztható legyen a BYTE-szám 4-gyel, mivel itt nincs ennek jelentősége. (Erről később.) A másik, hogy mégis van kiegészítés, ez simán hozzáadódik a fejrész meg az adatrész közötti GAP számhoz, de ez meg több mint az 1541 esetében, itt 20 BYTE-nyi GCR kód íródik ki a szektorok fejléce és az adatrésze közé. Ennyi adat birtokában már kiszámítható, hogy mindenestül hány bitnyi adat egy komplett szektor:

  • 40 bit szinkron
  • 10 bit szektorfejléc azonosító ($08 GCR-ben)
  • 10 bit szektorfejléc ellenőrző összege
  • 20 bit szektor / sávszám
  • 20 bit lemez ID
  • 200 bit GAP (20 db. $0F GCR-ben)
  • 40 bit szinkron
  • 10 bit szektor adatrész azonosító ($07 GCR-ben)
  • 2560 bit adat (256 BYTE GCR-ben)
  • 10 bit ellenőrző összeg

Ez összesen 2920 bit. Ezek után jön „valamennyi” GAP, majd a következő szektorral kezdődik az egész elölről. Ez a „valamennyi” GAP elég sok, már a fejléc / adatrész közötti szám is jóval több mint az 1541 92 bitje (9 db. 8 bites BYTE + a fejléc használaton kívüli „kerekítő” 2 db. BYTE-ja GCR-ben). A szektorok közötti körülbelüli GAP mennyisége is kiszámolható, ezen adatokon felül csak a sávon levő szektorok száma kell. Ez kiderül a használati útmutató megfelelő fejezetéből:

  • 1..39 / 78..116 → 29 szektor
  • 40..53 / 117..130 → 27 szektor
  • 54..64 / 131..140 → 25 szektor
  • 65..77 / 141..154 → 23 szektor

Így már kiszámítható a GAP-szám, amit a meghajtó is úgy számol ki (pontosabban fogalmazva: „megméri”), méghozzá a lemez formázása alatt. (Ezért is olyan lassú.) Csak matekozni kell:

  • 375000.00 BPS / 5 = 75000 bit sávonként; 23 * 2920 = 67160 → 7840 bitnyi össz GAP / 23 = 340 bitnyi GAP a szektorok között
  • 400000.00 BPS / 5 = 80000 bit sávonként; 25 * 2920 = 73000 → 7000 bitnyi össz GAP / 25 = 280 bitnyi GAP a szektorok között
  • 428571.71 BPS / 5 = 85714 bit sávonként; 27 * 2920 = 78840 → 6874 bitnyi össz GAP / 27 = 254 bitnyi GAP a szektorok között
  • 461538.46 BPS / 5 = 92307 bit sávonként; 29 * 2920 = 84680 → 7627 bitnyi össz GAP / 29 = 263 bitnyi GAP a szektorok között

A sávonkénti össz GAP méretből azért látszik, hogy 2 szektorral több férne el, ha nem lennének ennyire nagyra véve. Van ráhagyás bőven, az biztos. Egy kicsit viszont elkanyarodtam a témától, ez talán az író/olvasó logikához tartozna.

A sötétkék keretben az IFC/IP 6502-ese van, „ő” felelős a számítógéppel való kommunikációért illetve a lemezen a fájlrendszer kezeléséért. A szektorok írása / olvasása már nem ennek a toknak a feladata, „ő” csak kiosztja a munkát, „más” elvégzi helyette. Ez a CPU futtatja a CBM DOS-t, annak is a 2.7-es verzióját. Ezt a pirossal bekeretezett két, egyenként 8 KBYTE kapacitású ROM tartalmazza. (Érdekesség ismét: a 8K-s EPROM-ok (pl. 2764) már 28 lábú tokban vannak. Ezek a ROM-ok meg 24 lábúak, az egyik engedélyező lábuk „el van használva” címnek, így fért csak el a kisebb tokban. Ha EPROM-ra kellene kicserélni őket, a megfelelő bekötést néhány nyákos Jumper átpakolásával el lehet érni.) Ez a 16K a CPU számára a $C000..$FFFF tartományban látszik.

A processzorhoz kapcsolódik ezen kívül még 4 KBYTE RAM, ez a lila keretben látható. A CPU számára látható RAM memóriatérkép így néz ki:

  • $1000..$13FF: RAM első 1K-s szelete
  • $2000..$23FF: RAM második 1K-s szelete
  • $3000..$33FF: RAM harmadik 1K-s szelete
  • $4000..$43FF: RAM negyedik 1K-s szelete

A címdekódolás olyan, hogy $1400..$1FFF tartományban az első 1K még háromszor ismétlődik, illetve ugyanez a séma igaz a másik három 1K-s szeletre is. (Azért szívesen megkérdezném a motivációjáról azt, aki ezt így találta ki... :) Miért jó, hogy nem egyben látszik a 4K? Mondjuk az első 2K-t így lehet $1C00..$23FF tartományban látni egyben is, illetve a második 2K-t $3C00..$43FF között, de akkor is fura. Ráadásul úgy rémlik, mintha ezt a trükköt a DOS-nak is alkalmaznia kell valamerre, szóval tényleg érthetetlen a kialakítás.) Ami elsőre feltűnhet ANNAK, aki programozott már 6502-es (vagy deriváltjai) processzort: hol van az un. nulláslap? (ZP, ZeroPage) Vagy a verem? Természetesen nem vesztek el, csak nem ez a 4K-nyi RAM tartalmazza őket.

A külvilág fele valamilyen periféria segítségével lehet kommunikálni, ez két darab 6532-es típusszámú RIOT csippel van megoldva. Ezek és az IEEE-488 interfész meghajtói vannak a világoskék keretben. A név a RAM / I/O / TIMER szavakból jön, ez majdnem az, mint ami miatt az elején „sírtam” egy sort. A jó hír: ezek NEM programozott cuccok, tehát az összes 6532 csereszabatos egymással. (Mivel nincs benne ROM, amit „programozni” kéne, így a dekódoló logika variálhatóságát sem erőltették, szerencsére.) A RIOT-okban egyenként van 128 BYTE memória, a kettőben összesen 256 BYTE. Ez valahova kelleni fog... :) Ez a 256 BYTE van „bekapuzva” a $0000..$00FF (ZP) illetve $0100..$01FF (STACK) memória tartományba. (Igen, a veremben látszik a nulláslap és viszont. De a DOS a nulláslap „felső” címeit már nem használja, a vermet meg nem tölti „túl tele”, így nem íródik felül az egyik a másik által, hiába van „átfedés”.) Az I/O rész 16 vezetékből (két 8 bites portból) áll, az egyik RIOT I/O része teljes egészében a GPIB DIO8..1 vonalait kezeli. Az egyik port kimenet, ezzel lehet a vonalak hajtását be/kikapcsolni. A másik bemenet, amin a vonalak éppen aktuális állapota olvasható. Ez a „kettősség” az egész meghajtóra jellemző amúgy, nincsenek benne olyan belső buszok, amiknek az adatirányát szoftverből kellene kapcsolgatni. Ahol két irányban is mehetnek adatok a logika szerint, ott a két iránynak külön busz van kiépítve. Ezért is tartalmaz az elektronika ekkora nyákot / ennyi alkatrészt. Cserébe nincs „adatirány-para”, hogy esetleg „összehajt” két áramkör hibás programozás miatt. A másik RIOT kezeli ugyanilyen módon a GPIB maradék jeleit, de azok között van ami csak bemenet, van ami egyáltalán nincs használva, tehát ott „nem megy el” mind a 16 vezeték erre. Az IEEE-488 busz meghajtását MC3446-os tokok végzik, ezek kifejezetten GPIB vonalmeghajtók, OC-s kimenettel, integrált terminálással.

A 6J pozíciószámú RIOT regiszterei / címei:

  • $0200: PortA adatregiszter, a GPIB DIO8..1 vonalak AKTUÁLIS állapotát lehet itt beolvasni. Mivel a GPIB negált logikájú, a beolvasott adat tényleges értéke a bitek megfordítása után áll elő!
  • $0201: PortA adatirány regiszter, fixen $00-ra van állítva, így a PortA MINDIG BEMENET!
  • $0202: PortB adatregiszter, a GPIB DIO8..1 vonalak hajtását lehet be/kikapcsolni ezen keresztül. Ami itt 1, az a vonal „el van engedve” a GPIB-n, ami 0, az alacsonyra van húzva. A negált logika miatt itt is a kiküldendő adat fordítottját kell a regiszterbe írni! Ahhoz, hogy a buszról adatot lehessen fogadni, azt előtte „el kell engedni” egy, ebbe a regiszterbe írt $FF értékkel!
  • $0203: PortB adatirány regisztere, fixen $FF-re van állítva, így a PortB MINDIG KIMENET!
  • $0204/$0206 olvasása: Timer értéke (A cím 3-as bitje 0, ez TILTJA a Timer IRQ-t!)
  • $0205/$0207 olvasása: Interrupt Flags Register: Megszakítás állapotregisztere
  • $0204/$0205 írása: A PA7-en történő változás hatására nem generálódik IRQ
  • $0206 írása: PA7 lefutó él generálhat IRQ-t
  • $0207 írása: PA7 felfutó él generálhat IRQ-t
  • $0208..$020B: Ugyanaz mint a 0, 1, 2 ill. 3-as regiszter ($0200..$0203)
  • $020C/$020E olvasása: Timer értéke (A cím 3-as bitje 1, ez ENGEDÉLYEZI a Timer IRQ-t!)
  • $020D/$020F olvasása: Interrupt Flags Register: Megszakítás állapotregisztere
  • $0210..$0213: Ugyanaz mint a 0, 1, 2 ill. 3-as regiszter ($0200..$0203)
  • $0214 írása: /1-es előosztó bekapcsolása + Timer beállítása, Timer IRQ tiltása
  • $0215 írása: /8-as előosztó bekapcsolása + Timer beállítása, Timer IRQ tiltása
  • $0216 írása: /64-es előosztó bekapcsolása + Timer beállítása, Timer IRQ tiltása
  • $0217 írása: /1024-es előosztó bekapcsolása + Timer beállítása, Timer IRQ tiltása
  • $0218..$021B: Ugyanaz mint a 0, 1, 2 ill. 3-as regiszter ($0200..$0203)
  • $021C írása: /1-es előosztó bekapcsolása + Timer beállítása, Timer IRQ engedélyezése
  • $021D írása: /8-as előosztó bekapcsolása + Timer beállítása, Timer IRQ engedélyezése
  • $021E írása: /64-es előosztó bekapcsolása + Timer beállítása, Timer IRQ engedélyezése
  • $021F írása: /1024-es előosztó bekapcsolása + Timer beállítása, Timer IRQ engedélyezése

Ez csak egy „nagyjából így van” táblázat, a TIMER konfigurálás része a (R)RIOT-nak eléggé horrorisztikus, bizonyos funkciókat címvezeték (!) kapcsol, egy rossz helyről történő olvasással akár ki is tiltható vagy engedélyezhető egy megszakítás. (Érdemes az adatlapot átnézni ez ügyben.)

A 4J pozíciószámú RIOT:

  • $0280: PortA adatregiszter, írható/olvasható.
    • B7: Bemenet, a GPIB ATN vezeték negáltja. (A RIOT a PortA B7 változására tud IRQ-t generálni, ezért van ez idekötve.)
    • B6: Bemenet, GPIB DAV vonal figyelése
    • B5: Bemenet, GPIB EOI vonal figyelése
    • B4: Kimenet, GPIB DAV vonal hajtása (1: elengedi, 0: alacsonyra húzza)
    • B3: Kimenet, GPIB EOI vonal hajtása (1: elengedi, 0: alacsonyra húzza)
    • B2: Kimenet, RFDO – GPIB NRFD vonal hajtása (1: elengedi, de az ATN beleszólhat a működésbe)
    • B1: Kimenet, DACO – GPIB NDAC vonal hajtása (0: elengedi, de az ATN beleszólhat a működésbe)
    • B0: ATNA (ATN Ack), a bejövő ATN nyugtázása. (0: normál működés) Ha az eszköz fele fel/lecímzés jön, akkor (miután felkészült az adatfogadásra) ezzel kell „nyugtázni” a „figyelmeztetést”.
  • $0281: PortA adatirány regiszter, fixen $1F-re van állítva
  • $0282: PortB adatregiszter, írható/olvasható
    • B7: Bemenet, GPIB NRFD vonal figyelése
    • B6: Bemenet, GPIB NDAC vonal figyelése
    • B5: Kimenet, a POWER / ERROR LED vezérlése (0: Zölden, 1: Pirosan világít)
    • B4: Kimenet, a működést visszajelző (ACT0) LED vezérlése (1: világít)
    • B3: Kimenet, nem használt (ACT1, a duál meghajtóknál az 1-es eszköz működését jelző LED vezérlése (1: világít))
    • B210: Bemenetek, az egységszám beállítására szolgáló 3 bit. (%000: 8-as, %001: 9-es, ...)
  • $0283: PortB adatirány regisztere, fixen $38-ra van állítva
  • $0284..$029F: Timer/Interrupt konfigurálás, lásd a 6J RIOT leírását

A CPU-nak megszakítást ezen utóbbi RIOT tud csak okozni, itt is az ATN-re van „ráugrasztva” mint az 1541-nél. Azért látszik, hogy ezek a régi meghajtók voltak az ősei... :) NMI-t semmi sem tud okozni, a CPU ezen lába simán magas szinten van (inaktív). RESET-et egyrészt előállít a saját RESET áramköre, de a GPIB IFC jele is kiválthat ilyet, ezt a vonalat szoftverből nem lehet figyelni. Említésre méltó még a PortB 2/1/0 bitje, ezekkel állítható be az egységszám 8..15 (!) tartományban. (A nyákon a RIOT mellett van 3 db, alapállapotban zárt nyákos Jumper kialakítva, ezeket elvágva állítható az egységszám. A Commodore „hivatalos” doksijában azt a megoldást írják, hogy a Dear Customer vegye ki a RIOT-ot a foglalatából, hajtsa ki a 3 láb közül azokat, amik a megfelelő egységszámot jelentik, majd így rakja vissza az IC-t a helyére. :) )

Nagyjából ennyi. De van itt valami „hiányosság”, mintha nem lenne teljes az összkép... Mégis, hogyan olvassa akkor a lemezt ez a processzor? Nem titok, sehogy. Azt egy másik CPU végzi. De azzal hogyan kommunikál? Egyszerű: a RAM-on keresztül. Ugyanis a 4K-nyi memóriát a másik CPU is látja, ez megosztott közöttük, méghozzá egy igen „frappáns” megoldással. A képen lilával bekeretezett részen, az SRAM-okon kívül található még 4 db. 74LS157-es 2-to-1 multiplexer is. A két CPU címbusza közül a megfelelő időben a megfelelőét kapcsolják rá az SRAM-ok cím vezetékeire. A trükk viszont most jön: úgy van a kapcsolás felépítve, hogy a két CPU nem zavarja egymást. Ennek megértéséhez kell egy kis 6502 „technikai ismeret”. A 6502 egy olyan „állatfajta”, aminél az órajel olyan sebességű, hogy minden ciklusban végrehajtódik egy memóriaciklus is. Tehát NINCS osztás. Amikor egy órajelciklus elkezdődik, akkor kikerül az elérendő cím a címbuszra. Ez a cím az egész ciklus alatt kinn marad. Viszont az adatbusz csak az órajelciklus második felétől kezdve aktív, ekkorra (ennek a végére) kell a perifériáknak előállítani / eltárolni az adatot, ami a ciklusban előállt. A „frappáns” megoldás abból áll, hogy a második számú CPU (FDC) az első órajelének a NEGÁLTJÁT kapja meg órajel gyanánt, így az adatbusz a cikluson belül hol az egyik, hol a másik CPU részéről aktív. Emiatt a két CPU adatbuszát simán közösíteni lehet. A RAM címmultiplexereit is ez az órajel kapcsolgatja, így mindig az aktuális CPU címe jelenik meg a címvonalain. Persze elő kell még állítani a RAM-ok _CS illetve _WE jeleit is, de az is ilyen módon „multiplexelve” van. Ugyan a RAM felől nézve 2 MHz-es a busz, de az meg „bírja”. (Ezt a „trükköt” (ti. a CPU egy ciklusa alatt két memóriaciklust lehet elsütni) a Commodore az összes mikrogépében használta.) Ez egy olyan apróság, ami kifejezetten tetszik.

Az FDC-hez tartozó CPU és periféria áramkörök vannak a képen világoszölddel bekeretezve, a „feltűnően nem MOS” áramkör a cserélt 6502-es CPU. Érdekesség: ennek a CPU-nak csak az A12..A0 vonalai vannak bekötve, az A15/A14/A13 nincs. Emiatt ez a CPU 8 KBYTE méretet lát a memóriából. (Vagyis „látja” mind a 64 K-t, de egy 8 K-s szelet ismétlődik 8-szor egymás után. Még jó, hogy a 6504 (aminek csak 13 címvezetéke van) más okból kifolyólag kevés ide, azt nem cseréltem volna ki „fiókban talált” alkatrésszel.) Ennek a CPU-nak a memóriatérképe így néz ki:

  • $0400..$07FF: RAM első 1K-s szelete
  • $0800..$0BFF: RAM második 1K-s szelete
  • $0C00..$0FFF: RAM harmadik 1K-s szelete
  • $1000..$13FF: RAM negyedik 1K-s szelete

Itt – szerencsére? – már egybefüggő a memóriatartomány. Az 1K-k sorrendje azonos a másik CPU táblázatának sorrendjével. Viszont itt is megvan a nulláslap / verem látszólagos hiánya, persze ez a CPU sem maradt ezek nélkül. Itt a RRIOT RAM-ja szolgáltatja ezeket, viszont meglehetősen szűkösek a körülmények. Az egy szem RRIOT-ban 64 BYTE RAM van összesen, ez van a $0000..$003F illetve $0100..$013F tartományba bekapuzva. Itt is igaz az, ami a másik CPU-nál: a veremben látszik a nulláslap és viszont. Csak itt jóval „szűkebb” a mozgástér... Ennek a CPU-nak a programkódját a RRIOT-ban lévő 1K-nyi ROM szolgáltatná, de ez van „kipeccselve” némi elektronikával, és kihelyettesítve egy EPROM-mal. (A zölddel bekeretezett részen ez a „patch” látható az extra felépítésen.) Ezt a ROM-ot $FC00..$FFFF tartományban látja a CPU. Illetve mindegyik 8K-s lap végén látszik a címdekódolás „butítása” miatt, de ezen a címen „fut” a kód, az utasításokban lévő fix címek erre a területre mutatnak. (Azért „kell” itt, a memória „tetején” lennie, mert a 6502 a RESET illetve IRQ (meg NMI) vektorokat az $FFFA..$FFFF címekről tölti be.)

A nagy kérdés: vajon mire is elég ez az 1K-nyi kódmemória? Egyrészt sok mindenre, másrészt pár dologra nem. Ami benne van: a mechanika kezelése (lemezforgató motor elindítása, leállítása időzítve, a fej megfelelő sebességű mozgatása, ezek szép IRQ hatására futó feladatok), a lemezen levő szektorok olvasása / írása / ellenőrzése, pufferekben lévő kódvégrehajtás. Na de mi hiányzik? Két igen fontos rutin. Az egyik: a bekapcsoláskori önteszt és a perifériák összes inicializálása. Igen, még a portok irányának a beállítása sincs benne! A probléma úgy van megoldva, hogy az FDC processzora a RESET után nekiáll várakozni. A „fő” CPU lefuttatja a RAM tesztelését, majd ebbe a (közös) memóriába bemásolja az FDC teszt / inicializációs rutinját, majd „értesíti” erről ezt a processzort. Erre az elindítja ezt a RAM-ba másolt rutint, ami elvégzi a tesztelést, ha mindent rendben talált, inicializálja a perifériákat majd visszatér a ROM-os rutin futtatásához. Szép... A másik hiányzó rutin a komplett lemez formázás, az is a fent leírt módon hajtódik végre. Ez a két rutin is van majdnem 1 KBYTE összesen, tehát NAGYON NEM ELÉG a RRIOT ROM-ja a feladathoz. Felmerül a kérdés, hogy vajon miért csinálták mégis így? Miért „erőltették” a RRIOT használatát, ami nem hogy nem elég a feladatra, de még nem is készült idevaló verzió? :-D

A ROM-ban lévő kód is „érdekes” egy kicsit, ugyanis a benne lévő rutinok 2 mechanika minden feladatát elvégzik. Olyan, mintha a duál mechanikás gépé lenne ez is, egy apró módosítással. Az elejére – szó szerint – bele van „taknyolva” egy vizsgálat, ami ha azt látja, hogy a második – nem kiépített – mechanikához tartozó bármilyen parancsot kapott, azonnal egy „NO SYNC” hibakódot ad vissza. (Ez a hibakód normál körülmények között például akkor jön, ha nincs formázott lemez a meghajtóban.) De ettől függetlenül minden benne van hagyva a második mechanika kezeléséből. (Ugyanúgy tologatja a nem létező fejet, kapcsolgatja a motort... Csak nem jut el olyan parancs hozzá, ami be is kapcsolná ezeket a részeket.)

Így bő 30 év távlatából (és az itt látottak alapján) had „okoskodjak” egy kicsit. Kezdésnek kellene 1 K üres terület a 16 K-nyi DOS ROM-ban. Ha jól megnézem, simán össze lehet szedni annyit. Ha ez a „megfelelő” helyre lenne csoportosítva, ide be lehetne rakni a RRIOT – itt ugyan „kipeccselt”, de ugyanúgy – 1 K-nyi ROM-ját. Ezek után, ha a multiplexerekkel „közösített” címbuszon nem csak az SRAM lógna hanem a ROM is (a megfelelő „bedrótozással” simán megoldható, hogy a 16K egy kisebb szelete látsszon, ne az egész), akkor az FDC programja is futhatna ebből, az így már közös ROM-ból. Ezzel az egész el-nem-készült RRIOT-os marhaságtól megkímélhettek volna mindenkit, helyette be lehetett volna pakolni egy „mezei” RIOT-ot. Legalább lett volna 128 BYTE-nyi nulláslap / verem. :) (Kicsit olyan érzésem van, mintha a „van egy csomó fajta perifériánk, használjunk minél több típust” szlogen mentén készült volna az egész.)

A világoszölddel bekeretezett területen látszik még egy IC amiről nem volt eddig szó, ez nem más mint egy 6522 VIA. (Ez ugyanaz, mint amiből az 1541-ben van kettő.) A RRIOT perifériakezelő részével együtt „ők ketten” intézik a mechanika illetve a lemez író / olvasó elektronikájának a kezelését.

A (z eredetileg) 3E pozíciószámú RRIOT:

  • $0080: PortA adatregiszter, a fej fele menő 8 bites adatot ide kell kiírni, ezt fogja valamilyen módon felírni az író logika a lemezre íráskor.
  • $0081: PortA adatirány regisztere, fixen $FF-re van állítva, így a PortA MINDIG KIMENET!
  • $0082: PortB adatregisztere, írható/olvasható
    • B7: Nem használt (Ez a portláb megosztott az IRQ vonallal, itt ebben a szerepben van használva, programozható portlábként NEM HASZNÁLHATÓ!)
    • B6: Bemenet, S/D, alacsonyra van kötve az S4 Jumperrel. Az inicializáció folyamán ellenőrzi ezt a lábat, ez dönti el hogy egy (Single, SFD1001) vagy két (Dual, 8050/8250) lemezes a meghajtó.
    • B5: Nem használt (Ez a portláb megosztott a _CS2 vonallal, ez a tok „egyik” engedélyező jele, programozható portlábként NEM HASZNÁLHATÓ!)
    • B4: Kimenet, ODD-HD, fejkiválasztó jel, ezzel tud a mechanika alsó / felső feje között kapcsolgatni. Az inicializáció folyamán először bemenetként konfigurálja, majd megnézi, hogy alacsony-e. Ha alacsony, akkor egy fejes(ek) a meghajtó(k), egy oldalas a lemezkezelés. (8050-es típusú meghajtónál ezzel jelzi az egyoldalasságot.)
    • B3: Bemenet, WPS, az írásvédelmi „kivágás” állapota. 0: írás ENGEDÉLYEZVE!
    • B2/B1: Kimenetek, DS1/DS0, a négy fajta bitsűrűség beállítása
    • B0: Kimenet, DRVSEL, meghajtó kiválasztása dupla lemezes meghajtó esetén (8050/8250)
  • $0083: PortB adatirány regisztere, fixen $17-re van állítva. (Ha egyfejes meghajtónak van konfigurálva, akkor $07)
  • $0084..$009F: Timer/Interrupt konfigurálás, lásd a 6J RIOT leírását

Az 5E pozíciószámú VIA (a leírás egy része az 1541-es meséből van):

  • $0040: "ORB": PortB regiszter, írható/olvasható.
    • B7: Bemenet, SYNC vonal figyelése. Ha 0, SYNC-et olvas éppen az olvasó logika!
    • B6: Kimenet, PULL SYNC vonal. Olvasás előtt 0-ba kell állítani, majd ha megjött a SYNC, utána vissza kell kapcsolni 1-be. Az olvasó elektronika ezzel „szinkronizálja össze magát” a lemezről jövő bitfolyammal.
    • B5: Kimenet, MTR0, a meghajtó lemezforgató motorját ezzel lehet kapcsolni, 0: motor bekapcsolva
    • B4: Kimenet, nem használt (MTR1, a másik mechanika lemezforgató motorját ezzel lehet kapcsolni, 0: motor bekapcsolva)
    • B3/B2: Kimenetek, fejmozgató léptetőmotor vezérlése (%00, %01, %10, %11, $00... sorrendben kapcsolgatva a fej az egyik, visszafele a másik irányba lép)
    • B1/B0: Kimenetek, nem használtak (a másik mechanika fejmozgató léptető motorjának a vezérlése)
  • $0041: "ORA": PortA regiszter, a fej felől jövő adat itt olvasható be
  • $0042: "DDRB": PortB adatirány regiszter, fixen $7F-re van állítva
  • $0043: "DDRA": PortA adatirány regiszter, fixen $00-ra van állítva, a PortA MINDIG BEMENET!
  • $0044: "T1L-L" íráskor / "T1C-L" olvasáskor, B7..0. Olvasáskor törli a T1 IRQ-t (megszakítás nyugtázása).
  • $0045: "T1L-H" íráskor / "T1C-H" olvasáskor, B15..8. Ennek beírása újraindítja az időzítőt a beállított értéktől, ill. törli a T1 IRQ-t. Az 1-es 16 bites időzítő (Timer) kezdőértéke ezen regisztereken keresztül állítható be (írás) ill. az időzítő aktuális értéke ellenőrizhető (olvasás).
  • $0046: "T1L-L": írható/olvasható, B7..0. Olvasáskor NEM törli a T1 IRQ-t.
  • $0047: "T1L-H": írható/olvasható, B15..8. Beíráskor NEM indul újra az időzítő, de a T1 IRQ-t törli. Az 1-es időzítő kezdőértéke ezen regisztereken keresztül IS beállítható, ill. ezen érték itt olvasható vissza. Az időzítő üzemmódjának a beállítása az "ACR"-en keresztül történik.
  • $0048: "T2L-L" íráskor / "T2C-L" olvasáskor (B7..0). Olvasása törli a T2 IRQ-t (megszakítás nyugtázása).
  • $0049: "T2C-H" íráskor / olvasáskor (B15..8). Ennek beírása újraindítja az időzítőt a beállított értékről, ill. törli a T2 IRQ-t. A 2-es 16 bites időzítő (Timer) kezdőértéke ezen regisztereken keresztül állítható be, ill. az időzítő aktuális értéke itt olvasható vissza. Az időzítő üzemmódjának a beállítása az "ACR"-en keresztül történik.
  • $004A: "SR": Shift-regiszter. Soros-párhuzamos, ill. párhuzamos-soros átalakító. Írható (kimeneti regiszter) / olvasható (bemeneti regiszter). A regiszter üzemmód beállítása az "ACR"-en keresztül történik.
  • $004B: "ACR": Auxiliary Control Register, időzítők ill. Shift-regiszter konfigurálása, írható/olvasható. $01-re van beállítva:
    • B7/B6: T1 időzítő üzemmódja ("00": Egyszer fut majd megáll, kimenet (PB7) tiltva)
    • B5: T2 időzítő üzemmódja ("0": kimenet (PB6) tiltva)
    • B4/B3/B2: Shift-regiszter üzemmódja ("000": Shift-regiszter tiltva)
    • B1: PortB Latch vezérlése ("0": normál mód, tárolás tiltva)
    • B0: PortA Latch vezérlése ("1": tárolás ENGEDVE, a VIA tárolja az olvasó logika felől jövő adatot, ugyanúgy mint az 1541-nél)
  • $004C: "PCR": Pheripheral Control Register (Alapállapot: $FC), CA1, CA2, CB1, CB2 jelek konfigurálása, írható/olvasható.
    • B7/B6/B5: CB2 üzemmódja ("111": CB2 kimenet és MAGAS), ez a láb az R/W jel az író / olvasó logika felé! 1: olvasás, 0: írás!
    • B4: CB1 üzemmód (mindig bemenet, "1": felfutó élre generál IRQ-t), EROR, nem használt (hibás kód olvasásakor jelez vele az olvasó logika)
    • B3/B2/B1: CA2 üzemmódja ("110": CA2 kimenet és ALACSONY), MODESEL, 0 esetén GCR kódolás van kiválasztva
    • B0: CA1 üzemmód (mindig bemenet, "0": Lefutó élre generál IRQ-t), READY, ezen vonal segítségével tárolja a PortA a bemeneti állapotát
  • $004D: "IFR": Interrupt Flag Register: Amelyik IRQ forrás aktív, a hozzá tartozó bit "1". A CPU innen tudja megállapítani, hogy melyik "egység" (periféria) okozta a megszakítás kérelmet. Törölni (nyugtázni) vagy a megfelelő periféria "megfelelő" elérésével, vagy ebbe a regiszterbe, az adott bitbe 1-et írva lehet.
  • $004E: "IER": Interrupt Enable Register: amelyik bit "1", a hozzá tartozó periféria IRQ-ja engedélyezve van. (Alapállapot: $00: minden tiltva.) Írható (speciális módon) / olvasható.
  • $004F: "ORA": PortA regiszter, írható/olvasható. Ugyan az mint a $0041, azzal a különbséggel, hogy az olvasása nem törli a PortA-hoz tartozó IRQ-t.

Ezen két perifériavezérlő (RRIOT / VIA) segítségével „irányítja” a mechanikát illetve az író / olvasó logikát az FDC processzora. A 6502 RESET-je ugyanaz mint a „fő” processzoré, egyszerre indulnak újra. NMI-t ez a CPU sem tud kapni, ráadásul IRQ-t is csak a RRIOT generálhat, a VIA megszakításkérő lába nincs bekötve. A CPU SO lábára itt is a READY jel van kötve (mint az 1541-nél), ha az író / olvasó logika kész egy „adattal”, akkor ezen keresztül jelez (beállítódik a „V” státuszbit).

Az elektronika további boncolásához itt van még egy kép:

A pirossal bekeretezett rész a fejmozgató léptetőmotor meghajtása; szóra sem érdemes. A világoskékkel – nagyjából – körberajzolt rész annál inkább. Ez az „alkatrésztemető” nem más, mint az író / olvasó logika. A közepén egy ROM-mal (5C pozíciószámú 24 lábú jószág). Ez a logika azért ilyen bonyolult, mert tud egy olyat, amit az 1541 nem: írás és olvasás alatt is „röptében” konvertál a BIN és a GCR kódolás között. Íráskor 8 bites bináris adatot kap, ezt 10 bites GCR-ben írja fel a lemezre. Ugyanezt visszafele: a 10 bites lemezről olvasott GCR kódolású adatokból 8 bites bináris adatot készít, ezt fogja átadni a CPU-nak. (Mivel ez hardveresen kezeli a 10-es bitcsoportokat, ezért nincs szükség a fejrész illetve adatrész hosszának azon módon történő kiegészítésére, hogy 4-gyel osztható legyen BYTE-ban a hossz.) Az oda-vissza konverziós táblát a ROM tartalmazza, viszont itt is van egy kis „ügyeskedés”. Olvasáskor sima ügy lenne a dolog: a bejött 10 bites adat rákerül a 10 címvezetékére, a 8 adatvezetékén meg megjelenik a 8 bites bináris adat. (Természetesen nem teljesen így működik... :) ) Írásnál viszont 8 bit kerülne a címekre, de a ROM adatbuszának a szélessége továbbra is 8 bites. Viszont 10 bit kellene a GCR értéknek. A megoldás igen „ügyesre” sikerült. Megvizsgálva a BIN-GCR táblázatot...

$0: %0000 - %01010
$1: %0001 - %01011
$2: %0010 - %10010
$3: %0011 - %10011
$4: %0100 - %01110
$5: %0101 - %01111
$6: %0110 - %10110
$7: %0111 - %10111
$8: %1000 - %01001
$9: %1001 - %11001
$A: %1010 - %11010
$B: %1011 - %11011
$C: %1100 - %01101
$D: %1101 - %11101
$E: %1110 - %11110
$F: %1111 - %10101

...észrevehető egy – most igencsak fontos – összefüggés: mind a 16 értéknél a bináris szám 3. bitje (B2) megegyezik a GCR kód 3. bitjével (G2). Ha ugyanaz a kimeneti bit mint a bemeneti, akkor nem kell eltárolni. :) Sőt: mivel nem az egyik oldalon előforduló „kombináció” adja a másik oldali végeredményt, így ez oda-vissza működik! A ROM (ami 2 KBYTE) két táblázatot tartalmaz, egyet olvasáshoz, egyet íráshoz.

Olvasáskor a 10 bites GCR kódot (G9..G0) megkapja az A9..A0 címvezetékeire (az A10 címvezetéke ilyenkor magas, így ez egy 1024 elemű táblázat), a kimenetein meg megjelenik a 8 bitnyi bináris adatból 6 bit (D0, D1, D3, D4, D5, D7 bitek az adatból, ezek rendre a ROM D0, D1, D2, D4, D5, D6 vonalain látszanak). A maradék két bit (D2, D6) jön GCR kód megfelelő bitjeiből (G2, G7). Ekkor a ROM fennmaradó két adatbitjéből az egyik (D3) azt jelzi, hogy érvényes-e az a GCR kód, ami a címvezetékein van. (1: érvényes, 0: hibás. A GCR kód 10 bites, ez egy 8 bites bináris értéket reprezentál. Tehát a GCR 1024 variációjából csak 256 kombináció helyes, a többi érvénytelen.) Ez a „hibajel” lesz majd az EROR, ami a VIA CB1-es bemenetére van kötve. (A CB1 beállított élváltozására a VIA IRQ-t tudna generálni, de ez – az IRQ vonal bekötésének hiánya miatt – nem valósulhat meg. Viszont az IFR-ben „megőrződik” ez a tény, a szektor olvasás végén ellenőrizhető, hogy volt-e közben hibás kód. Ezt a firmware valójában nem használja, a fej/adatrész ellenőrző összegét elégnek érezték a tervezők. Az FDC rutinja is ezt teszi, a szektor-adatrész olvasása után ránéz erre a bitre az ellenőrző összeg vizsgálata előtt. A szektor fejrész olvasásakor viszont nem csinál ilyet...)

Az írás egy kicsit még ehhez képest is meg van kavarva, ugyanis van egy olyan érték (a GCR-ben hibás %1111111111), amit fel kell tudnia az elektronikának írni. (Ez a szinkron.) Tehát van 256 bináris kód, plusz még egy. Ez úgy lett megoldva, hogy az író logikát át lehet állítani DIREKT üzemmódra, mikor is NEM KONVERTÁLJA a bináris kódot GCR-be felírás alatt. (Ez azért DIREKT, mert „direkt” a szinkron felírására van. :) ) Ezt a VIA CA2-es lábán keresztül lehet kapcsolgatni, ez a MODESEL, 0 esetén a konverzió be van kapcsolva, 1 esetén ki. A szinkron írásánál ki kell kapcsolni a konverziót, majd a szokásos $FF értékeket kell kiírni. Valójában a kiírandó érték nem számítana, ugyanis a kódoló táblázatban ekkor minden értékhez %11111111 kimenet van beállítva. Ami miatt mégis lényeges: a 10 bitből a ROM csak 8-at szolgáltat, a maradék kettő (G2, G7) ebből az értékből (D2, D6) jön közvetlenül. A szinkron ilyen módon történő felírása után vissza kell kapcsolni a konverziót, a többi adat már úgy íródik ki. Na de a működés: íráskor a 8 bites bináris kód (D7..D0) kerül a ROM A8..A5 illetve A3..A0 címvezetékeire. (Hogy miért pont így, arról a tervezőt kellene megkérdezni... Annyi látszik, hogy ha a BYTE „fel van bontva” két 4 bites nibble-re, akkor a táblázat jól láthatóan „feloszlik” 16 értékenként. (16 db. konverziós érték, utána 16 db. %11111111 (szinkron) jön.) Ha „kézzel” készült ez a táblázat, talán egy kis segítség az átlátáshoz...) Az A4-re kerül a MODESEL jel (kell-e GCR-be kódolni vagy sem, 0: kell, 1: nem), az A9 ilyenkor 0, illetve az A10 is 0. (Ez vált az írás / olvasás táblázat között, az A9 fix értékével együtt így 2 db. 256 elemből álló táblázat a végeredmény.) A ROM adatkimenetein ilyenkor megjelenik a 10 bites GCR kódból 8 bit, (G9, G8, G6, G5, G4, G3, G1, G0), a maradék két bit (G7, G2) meg jön a „forrás” bináris számból (D6, D2).

Ezt a ROM-ot „etetni kell” címekkel, de ebből két fajta is van. Olvasáskor a fej felől jövő adatokat egy 10 bites shift-regiszter tárolja (5B / 6B, 74LS164-ek). Ebből az adatból képződik még a SYNC jel is, ezt egy 13 bemenetű NAND kapu állítja elő (2D, 74LS133). Ez a 10 bites adat egy rakás multiplexeren (3D, 3C, 4C, 74LS157-ek) keresztül kerül a ROM címbemeneteire olvasásnál. Íráskor ugyanezek a multiplexerek a RRIOT PortA vonalait kapcsolják a ROM címbemeneteire. Az adatkimenetek két fele vannak „eldrótozva”. Egyrészt egy 10 bites shiftregiszter kapja meg őket (6E, 6F, 74LS165, 74LS194, 8 adatbit a ROM-tól, kettő a RRIOT-tól), ez generálja íráskor a „bitstream”-et, ami alapján a fej írja az adatokat a lemezre. Másrészt ezt az adatot (szépen összefésülve a ROM hat adatbitjét az olvasáshoz használt shiftregiszter megfelelő két bitjével) megkapja a VIA a PortA bemeneteire, olvasáskor innen lehet majd elszedni a GCR-ből dekódolt adatot.

Ezenfelül ez az elektronika tartalmaz még egy bitszámlálót az olvasáshoz / íráshoz, amivel a lemezre / lemezről ki / bekerült biteket számolja. Ezt a (csak olvasáskor, szinkront érezve aktív) SYNC jel törli, ezzel biztosítva, hogy ne legyen elcsúszás. Aztán van még egy „bitfrekvencia-generátor”, ez egy osztó ami a bejövő 6MHz-et osztja a bitsebességnek megfelelően 16, 15, 14 vagy 13-mal. Ennek a kimenete lépteti íráskor a kimeneti shift-regisztert. Olvasáskor viszont egész más a helyzet. Ekkor a világoszölddel bekeretezett áramkör generálja a léptetéshez szükséges órajelet. Sokat nem tudok mondani róla, mivel nem világos hogy hogyan működik. :) (Egyrészt eléggé analóg a „drága”, az meg nem az erősségem. Másrészt a kapcsolási rajz „rosszul”, nem túl informatív módon van megrajzolva. Harmadrészt ráadásul eléggé rossz minőségű a szkennelés, jobban járnék ha újrarajzolnám. Majd egyszer...) Bemenetnek megkapja a fej felől jövő digitális jelsorozatot (azt, ami „minden mágnesestér változásnál egy impulzus”), megkapja a két bitsebesség állító jelet, illetve a PULL SYNC-et (VIA PortB6). Ezekből (illetve egy visszacsatolásból) előállítja azt az órajelet, amivel olvasáskor a bemeneti shift-regisztert lépteti. Ez majd megér egy komolyabb vizsgálatot, de ahhoz igen sok energiát kell még gyűjtenem. :) (Lassan kezd sok lenni a „még megvizsgálni” terület, eh...)

Ez ugyan már analóg volt, de érdemes még pár szót ejteni a bitsebesség illetve a CPU sebesség viszonyáról. Az 1541-ben 32, 30, 28 illetve 26 processzoros órajelciklus alatt jön meg / megy ki egy adat, ennyi ideje van a CPU-nak hogy elszedje / kirakja azt. Az SFD1001-nél is ugyanúgy 1 MHz-es a processzor órajele, de a bitsebességek másfélszeresek. Cserébe nem 8 hanem 10 bitenként kell csak „ügyködni”, így a következő idők jönnek ki:

  • 12000000 / 2 / 16 / 10 = 37500 BYTE másodpercenként, 1000000 / 37500 = 26.6 órajelciklus
  • 12000000 / 2 / 15 / 10 = 40000 BYTE másodpercenként, 1000000 / 40000 = 25.0 órajelciklus
  • 12000000 / 2 / 14 / 10 = 42857 BYTE másodpercenként, 1000000 / 42857 = 23.3 órajelciklus
  • 12000000 / 2 / 13 / 10 = 46153 BYTE másodpercenként, 1000000 / 46153 = 21.6 órajelciklus

Ugyan nem túl sok még a legnagyobb sem, de azért elég. Van még egy apró segítség: a VIA illetve a RRIOT regiszterei a nulláslapon érhetők el, így egy órajelciklussal rövidebb az ezeket olvasó / író utasítás.

Aztán ami még vissza van, az a lilával körberajzolt terület, ez a fej író / olvasó elektronika analóg része. Olvasáshoz szerencsére már tartalmaz egy integrált olvasó erősítőt (10A, HA16631P). Ez tartalmazza a műveleti erősítős fokozatot, a komparátort, illetve egy digitális szűrőt. A kimenetén már az a jel jelenik meg ami kell: amikor a lemezen a fej alatt a mágnesezési irány MEGVÁLTOZIK, ez jelenti az 1-es bitet, ekkor ad egy (beállított hosszúságú, bár a hossz nem lényeges) impulzust. Ezt kapja meg az olvasó elektronika digitális része, ez tulajdonképpen már a GCR kódolt adat, csak bitsorosan.

A 11B pozíciószámú vastagréteg hibrid IC az íráshoz szükséges „nagyáramú” (muhaha...) elektronikát tartalmazza (pár tranzisztor, diódák, ellenállások), ez a kör is a „szokásos” módon működik. Ha be van kapcsolva az írás (és nincs tiltva az írásvédelem által), akkor egyrészt a kiválasztott fej törlő tekercse töröl, másrészt ugyanennek a fejnek az egyik író tekercse valamilyen irányba beállítja a lemezen a mágnesezést. Ha az elektronika a bitfolyamból kap egy 1-es bithez tartozó impulzust, akkor átvált a másik író tekercsre, ami az előzőhöz képest ellentétes irányú mágnesezésre kapcsol át. Tehát az 1-es bitek mindig megfordítják a mágnesezés irányát, a 0-ák azonban nem változtatják meg. A GCR kódolás miatt azonban ilyen eset (0-ák) csak kétszer fordulhat elő egymás után.

A két fejet ugyanaz az olvasó erősítő „olvassa” illetve író meghajtó „írja”, a kapcsolgatás egy rakás diódával meg némi ügyességgel van megoldva. A fejekben lévő tekercseknek van egy közös pontja, ez van kapcsolgatva a megfelelő potenciálra. Annyira egyszerű ez a de/multiplexer, hogy a duál meghajtókban az összesen 4 fej ugyanígy van váltogatva, csak pár diódával / tranzisztorral / ellenállással kell hozzá több.

Úgy „nagy vonalakban” ennyit az elektronikáról, de itt is jó néhány oldalt még lehetne írni az apróságokról. Érdekes benyomások születtek a vizsgálódás alatt, a Commodore újabb elektronikái már sokkal „összeszedettebbek”, de sok ötlet „őse” már megtalálható itt is. Így látszik hogy „mi honnan jött”, pár újabb kütyüben látni néha olyan részleteket amik az „ősök” ismeretében már érthetők.

Ilyen téma a két CPU közötti kommunikáció is. Az IFC/IP a „főnök” a DOS-t futtatva, az FDC ennek a parancsait hajtja végre. Ezen parancsok természetesen a memória egy kijelölt területére kerülnek, ez az un. JOB-tár. A logika úgy van kitalálva, hogy a memóriában van pár 256 BYTE-os „puffer”, ahol az FDC egy-egy blokkal tud dolgozni. (Innen tudja beolvasni a lemezre íráskor, ide írja be olvasáskor, stb...) Ebből a pufferből az 1541-ben van talán 4? Az SFD1001-ben 15. Minden ilyen pufferhez tartozik egy BYTE, ahova az un. JOB-kódot (annak a parancsnak a kódját, amit végre kell hajtani) írja a DOS, illetve tartozik még hozzá néhány BYTE, ahova a parancshoz tartozó esetleges paraméterek kerülnek. Az 1541 esetében ez a paraméter 2 BYTE (TRACK + SECTOR száma), az SFD-nél 8 BYTE, ami a következő módon épül fel:

  • 0. BYTE: Lemez ID LO
  • 1. BYTE: Lemez ID HI
  • 2. BYTE: Track száma
  • 3. BYTE: Sector száma
  • 4. BYTE: ? (Az FDC nem használja)
  • 5. BYTE: ? (Az FDC nem használja)
  • 6. BYTE: ? (Az FDC nem használja)
  • 7. BYTE: ? (Az FDC nem használja)

A 4..7 BYTE-okat az FDC nem használja, viszont a 0..3 BYTE-ok pontosan azok az adatok, amik egy-egy szektor fejlécében szerepelnek. Amikor az FDC a kért blokk fejlécét keresi, ezekkel az adatokkal hasonlítja össze az éppen olvasottat. (Ha egyezik, megtalálta, ha nem, ...)

No de hol is vannak a pufferek? Íme egy szép táblázat, hogy mi merre van:

  • Szám|JOB-tár| Paraméterek: | Puffer(IFC):
  • ----+-------+--------------+-------------
  • 1...| $1003 | $1021..$1028 | $1100..$11FF
  • 2...| $1004 | $1029..$1030 | $1200..$12FF
  • 3...| $1005 | $1031..$1038 | $1300..$13FF
  • 4...| $1006 | $1039..$1040 | $2000..$20FF
  • 5...| $1007 | $1041..$1048 | $2100..$21FF
  • 6...| $1008 | $1049..$1050 | $2200..$22FF
  • 7...| $1009 | $1051..$1058 | $2300..$23FF
  • 8...| $100A | $1059..$1060 | $3000..$30FF
  • 9...| $100B | $1061..$1068 | $3100..$31FF
  • 10..| $100C | $1069..$1070 | $3200..$32FF
  • 11..| $100D | $1071..$1078 | $3300..$33FF
  • 12..| $100E | $1079..$1080 | $4000..$40FF
  • 13..| $100F | $1081..$1088 | $4100..$41FF
  • 14..| $1010 | $1089..$1090 | $4200..$42FF
  • 15..| $1011 | $1091..$1098 | $4300..$43FF

Tehát ha az FDC-vel meg akar az IFC/IP csináltatni valamit, akkor kiválaszt egy puffert. A hozzá tartozó adatokkal feltölti (ha kell, pl. íráskor), majd beállítja a pufferhez tartozó paraméterblokkban a paramétereket. Ezután a pufferhez tartozó JOB-tárba beírja a feladat parancskódját. Amikor az FDC végzett a parancs végrehajtásával, ezt a JOB-kódot lecseréli egy állapotkódra. Ebből tudható meg, hogy sikerült-e a feladat vagy sem. A JOB-kódot az állapotkódoktól az különbözteti meg, hogy a 7-es bitje a JOB-kódoknak mindig 1, a válaszkódoknak mindig 0. A következő JOB-kódok érvényesek:

  • $80: READ, szektor olvasása
  • $90: WRITE, szektor írása
  • $A0: VERIFY, szektor ellenőrzése
  • $B0: SEEK, sáv keresése
  • $C0: BUMP, fej 1-es sávra mozgatása
  • $D0: JUMP, program végrehajtása
  • $E0: EXECUTE, program végrehajtása, de előtte a kért sávra áll a fejjel

(Dupla meghajtónál (8050/8250) a „másik” mechanikára vonatkozó parancsok majdnem ugyanezek, ott a JOB-kódok 0-ás bitje 1. Tehát $81 a READ, $91 a WRITE, ... Ezekre a kódokra ez a meghajtó SYNC ERROR hibakóddal válaszol.) A parancsok végrehajtása utáni lehetséges válaszkódok:

  • $01: OK, minden rendben, a kért parancs végrehajtva
  • $02: HEADER (blokk fejrész) nincs meg
  • $03: SYNC nincs meg
  • $04: DATA (blokk adatrész) nincs meg
  • $05: DATA (blokk adatrész) ellenőrző összege hibás
  • $07: VERIFY hiba
  • $08: WPS aktív, a lemez írásvédett
  • $09: HEADER (blokk fejrész) ellenőrző összeg hibás
  • $0B: ID hiba (az olvasott blokk ID-je nem egyezik a várttal)
  • $10: DATA (blokk adatrész) olvasási hiba (EROR aktív)

Az 1541 esetében is ugyanezek a JOB illetve válaszkódok (kb...) vannak. Régen nem volt tiszta, hogy ott miért van így elbonyolítva a lemezkezelés. Mennyivel egyszerűbb lenne, ha a megfelelő paraméterekkel meghívnám pl. a READSECTOR szubrutint, aztán kész... Ez a „móka” ezekből a régi meghajtókból jön, ugyanis itt csak így lehet READSECTOR szubrutint hívni, mert azt NEM az a CPU hajtja végre, mint aki hívja. :) A JOB illetve válaszkódok közül talán csak a $B0, a SEEK érdemel magyarázatot. Ha egy szektort be akarok olvasni, akkor beírom a kiválasztott puffer paramétertárába a TRACK / SECTOR értékét, a hozzá tartozó JOB-tárba a $80, READ parancsot, majd... ...valószínűleg visszakapok egy $0B-s ID-hiba hibakódot. Mivel az ID-t is be kell állítani a paramétertáblába. Viszont ha még nem olvastam a lemezről egy szektort se, honnan tudhatnám, hogy mi a lemez ID-je? Az FDC programjának persze esze ágában sincs az olvasott ID-t bárhova is letárolni. Szívás... Erre a problémára van a $B0, SEEK parancs. Ez a kívánt sávra áll, DE a pufferhez tartozó paramétertáblába BELEÍRJA a szektorfejlécből kiolvasott ID-t. Így lehet azt megtudni. (A SEEK-nek amúgy nem lenne semmi haszna, mivel a sima READ / WRITE / ... parancsok ugyanúgy indítják a motort ha kell és a megfelelő sávra állnak, tehát nem kell ilyen módon előkészíteni semelyik parancs végrehajtását.)

Így, a vége felé a „múltkori” kérdésem azért ide kívánkozik: vajon működik a „dög”?

Igen, működik. (A (plus/4-es?) világ leggyorsabb SFD1001-es gyorstöltője akcióban. (Persze úgy nem kunszt nyerni, ha csak egy induló van, de akkor is! :) ))

Egy hardvert megismerni „belülről”, megfigyelni a működését regiszter szinten még egy egész érdekes dolog. Erre a számítógép esetén a legjobb eszköz a MONITOR, amivel a memóriát illetve az I/O területeket lehet mindenféle módon vizsgálni / piszkálni. A számítógépen futó MONITOR persze annak a memóriáját / hardvereit „mutogatja”, de én használok egy olyan bővítést, amivel a lemezmeghajtóé is látható, ha akarom. A MONITOR két alap funkciója, a memória olvasása és írása van ilyenkor „eltérítve”, hogy a meghajtót kezelje. Ehhez semmilyen hardveres trükk nem kell, a meghajtónak van két parancsa (M-R, M-W) amivel olvasni / írni lehet a memóriáját. (Meg egy harmadik (M-E), amivel kódot lehet futtatni.) Ez teljesen kiválóan üzemel, szépen vizsgálható „élőben” a DOS, a RAM... Viszont ezt a két parancsot az SFD1001 esetében – természetesen – az IFC/IP futtatja (mivel a DOS része). Emiatt csak a „fő” processzor címterében lehet „garázdálkodni”, de itt ugyanolyan érdekes (ha nem érdekesebb) lenne az FDC címtere. Azt viszont nem lehet elérni...

...vagy mégis? Az FDC-nek van egy JUMP nevű JOB-kódja, amivel meg lehet „kérni”, hogy futtassa le a pufferbe bemásolt programot. Ha egy olyan kódot futtatok, ami a közös RAM-területre másolja a megfelelő adatokat, akkor „körül lehet nézni” ott is. A megoldás: sima meghajtó memória írás / olvasás helyett le kell tölteni (M-W) egy programot, majd elindítani (M-E) azt. Ez a program elindít a JUMP JOB-kóddal egy rutint, amit már az FDC CPU-ja hajt végre. Ez megcsinálja az olvasást / írást, majd „jelez” az IFC/IP-nek, ami ilyenkor visszatér a DOS futtatásához. Amikor ez megtörténik, akkor már tudja fogadni a számítógép esetleges „kíváncsiskodását”, olvasásnál ilyenkor a közös RAM terület megfelelő részéről visszaolvasható az az adat, amit az adott címen az FDC „látott”. Kicsit nyakatekert, meg garantáltan nem fog sietni, de megoldható. A MONITOR-hoz a megfelelő rutinokat elkészítve valami ilyesmit akartam látni:

És igen, ott és úgy látszik a közös memória, ahol számítani rá, valóban látszik a nulláslap a veremben, ott vannak a perifériák, látszik a ROM... (A képen az utolsó két sorban a RRIOT regiszterei látszanak. A 3. BYTE az egyik sorban $80, a másikban $88. A kettő között annyi a különbség, hogy a második alkalommal kihúztam egy kicsit a lemezt a meghajtóból, így jelez a WPS, az írásvédelem kapuja.)

Hmmm... Kéne írni valami konklúziót... Van azért a „kütyüben” pár olyan funkció, amit kár, hogy a később készült meghajtók nem kaptak meg. (Éljen a költségcsökkentés!) Ilyen rész a GCR – BIN hardveres oda-vissza konvertálgatása, vagy a két fejes mechanika. De a magasabb írássűrűségről sem érdemes megfeledkezni... A GCR – BIN témát egy gyorsabb CPU-val már szoftverből is el lehet intézni „röptében”, ilyen meghajtó lett az 1551. Kétfejes mechanika az 1571-ben található, egyszer majd egy ilyet is „felboncolok”. :) Van még itt „anyag” bőven... Hát igen. Akit érdekel az ilyen téma, annak ez jó hobbi. :)

„Irodalom” (ami most igen rövid lesz, mert sok mindent nem találni):

balagesz

---

2013.12.08.
2013.12.17. Linkek, GCR (de)kóder pontosítása, stb.
2014.03.02. Elírás javítása
2015.08.02. Elírás javítása
2019.12.13. D8, EROR jel pontosítása

Hozzászólások

Huh, nem semmi leírás!

Én ilyen szinten nem értek a gépek működéséhez, de mégis végig szoktam olvasni az írásaidat, mert nagyon érdekesek és úgy vannak tálalva, hogy még nagyjából érthetőek a laikusok számára is :)

Volt szerencsem ilyen kutyun dolgozni '87 tajekan. :) Ezen ment a Balatonfenyvesi AG konyvelese, kb. 1000 fore. :)