USB op de TRS-80

Jos Weijenberg heeft uitgebreid en succesvol geëxperimenteerd met een snelle seriële verbinding, zie blz. 12-27. Dat blijkt goed te werken, maar de koppeling vereist 3 “stappen”: de TRS-80 printerpoort, een Tiny R8C microcontroller met wat aanvullende logica en een RS-232 naar USB kabel. Het was vooral de Tiny R8C die deze manier van communiceren voor sommigen minder aantrekkelijk maakte. En ja, ook al ontberen de moderne computers een echte RS232 en printerpoort, eerder genoemde sommigen hebben voor communicatie doeleinden met de TRS-80 nog wel een ouder ATX beestje staan...
Op zich is er niets op een extra interfaceje tegen, maar kon het dan niet anders, meer direct van de TRS-80 naar USB?. Extra hardware op de TRS-80, knutselen is een van de doelstellingen van de Vereniging... Na de bijeenkomst in mei 2008, met door omstandigheden slechts 2 leden, soms moet je met weinigen zijn voor een grote impuls, werd er toch maar eens op internet gezocht naar USB specificaties. Misschien was dat allemaal niet zo erg ingewikkeld en hadden anderen het wiel al lang uitgevonden. Dat bleek een schot in de roos.
Een lang verhaal kort: Vinculum (www.vinculum.com) bleek een chip te produceren die goed kan babbelen met USB devices, waaronder BOMS (Bulk Only Mass Storage; een willekeurig apparaat, waar alleen een heleboel data op staat, of te wel USB memory sticks, externe harde schijven, etc.). Op zich hadden we aan zo’n surface mount chipje met veel pennetjes als hobbyist niet veel. Echter, ook daar had Vinculum in voorzien met de opsteekprintjes Vdip1 en Vdip2. Voor ons doel, te weten een USB interface op de TRS-80, voldoet de Vdip1. De grote broer, de Vdip2, konden we links laten liggen. De Vdip1 past op een standaard 24-pens IC-voet en is uitgerust met een USB connector geschikt voor onder andere een BOMS (bulk only mass storage). De vondst van de Vdip1 en Vdip2 werd snel rondgestuurd.
In juni had Jacques Verveer het idee helemaal opgepakt en alle Vinculum documentatie bestudeerd. Meer nog: hij had het aansluitschema voor de TRS- 80 al klaar. De Vdip1 werkt in principe op 3.3V. Dat wordt op het printje zelf gemaakt vanuit een standaard +5V voeding. Bovendien zijn vrijwel alle inputs van de Vdip1 “5 volt safe”. Dat wil zeggen dat de Vdip1 met gewone TRS-80 logica aangestuurd kan worden, ook al is dat bij hoog-uit al gauw een spanning groter dan de Vdip1 voedingsspanning van 3.3V. Alleen voor de Reset* was dit niet gespecificeerd, zodat aangenomen moest worden dat deze ingang niet bestand zou zijn tegen een input van 5V. Zoiets kan gemakkelijk overkomen worden met een open collector uitgang. Een open collector uitgang wordt hoog gehouden door een pull-up weerstand en zonodig actief laag gemaakt. De simpelste, namaak, open collector uitgang bestaat uit een diode. Op de Vdip1 is de Reset* met een pull-up weerstand van 47k met de 3.3V voeding verbonden.
In de praktijk bleek de diode ter verkrijging van een “open collector” uitgang goed te werken en was er geen speciale open collector driver nodig. Op deze manier kon de interface beperkt blijven tot 5 ic’s: een 245 databus buffer, een 368 voor het uitlezen van de status, en een 08, 32 en 138 voor adres decodering en overige logische functies. Kortheidshalve verwijzen we naar het schema.
Wel zij nog opgemerkt dat het niet toegestaan is naar de Vdip te schrijven of van de Vip te lezen als de bijbehorende status signalen “inactief” zijn. In geval van eventuele software fouten werd deze bescherming in de hardware opgeno- men: lezen en schrijven kan alleen als de Vdip dit actief toestaat (twee OR poorten in de RD* en WR* lijnen). Ten einde er voor te zorgen dat de databus nog even actief blijft na afloop van het WR signaal naar de Vdip1, wordt dit signaal voor de uitschakeling van de 245 nogmaals geïnverteerd, en niet recht- streeks afgetakt van de OR poort uitgang (qua niveau hetzelfde WR* signaal).
Na wat wikken en wegen, wel of niet wachten tot na de zomer, knutselen hoort toch bij lange winteravonden, kon het enthousiasme niet meer getemperd worden: in vier avonden werd een proef-exemplaar gebouwd. Alle onderdelen, inclusief een “doorvoer-connector” voor de TRS-80 systeembus, gaan op een printje van +/- 5 x 7 cm. Het printje past achter op het Model-I toetsenbord (mits deze voorzien is van een double-row header, wat so wie so nodig is voor een betrouwbare verbinding met de expansion interface). Na aansluiten van de TRS-80-USB interface wordt de expansion interface weer aangesloten op de double-row header op de achterkant van het USB-interface printje. De 5-volt voeding werd afgetapt in de Video-connector van de TRS-80 (die 5-volt is daar bedoeld voor het inschakelen van de video-monitor). Hardware klaar.
In drie stappen werd het programma Vdip2/bas geschreven (= versie 2, geteld vanaf versie 0 de 3e versie). In deze versie is het programma bedoeld voor instructie en kopiëren van bestanden tussen de TRS-80 en de USB-stick. Het programma werkt goed, zij het dat er nogal wat aandacht besteed moest worden aan de optimalisatie van de snelheid van kopiëren. Zie hiervoor Tijdtabel 1. Had Vdip0/bas ruim 2 minuten nodig voor het kopiëren van 8 kb data van de TRS-80 naar de Vdip1, met Vdip1/bas was dat teruggelopen tot 17 sec en met Vdip2 duurde het nog slechts 4 seconden. De winst van Vdip0 naar Vdip1/bas was te danken aan een korte machinetaal routine. In Vdip0 werd de inhoud van een sector volledig met Basic naar de Vdip1 gestuurd (per sector 256 x OUT DA%, byte). Een korte machinetaal routine is dan 7.5x sneller (128 s/ 17 s).
Tijdtabel 1. Tijd nodig voor het schrijven van 8 kb van TRS-80naar Vdip1
Opmerkingen bij Tijdtabel 1:
- TRS-80 Model I met 2.5x speedup en 204 kb Ramdisk.
- Het gebruik van een kleine machinetaal routine om telkens 256 bytes van de TRS-80 sector buffer naar de Vdip1 te schrijven (Vdip1/bas), maakt het programma zo’n 7.5x sneller dan de voorafgaande versie (Vdip0/bas) waarbij dit geheel in Basic ging (in Basic: OUT Vdip- data-register, PEEK(buffer)).
- Met versie 1 (Vdip1/bas) duurt het schrijven van 8 kb data naar de USB-stick altijd nog 17 sec. Dit kon nog eens 4x sneller door in versie 2 (Vdip2/bas) de Vdip module slechts 1 schrijfopdracht per bestand te geven, ipv. een schrijfopdracht per sector van 256 bytes (Vdip1/bas). Daarmee is de Vdip1 opeens lekker snel: nog maar 4 sec voor het kopiëren van 8 kb. Uit de testen blijkt dat Basic 2 sec nodig heeft voor het lezen van de data uit de Ramdisk en vervolgens zijn er nogmaals 2 sec nodig voor het opsturen naar de Vdip en verwerking in de Vdip (samen 4 sec voor de gehele kopie)
Toch was het vreemd dat de Vdip1 17 sec nodig zou heben voor het inlezen van 8 kb data. De oplossing was de Vdip1 in één commando de gehele file-lengte op te geven, ipv. een commando per 256 bytes. In andere woorden: 8kb naar de Vdip1 kopiëren in 32 blokken van 256 bytes (32x het commando WRF 256) duurt 17 sec; met één commando (WRF 8192) duurt het 4 sec. Vanzelfsprekend is er voor de TRS-80 geen verschil. Het Basic programma leest telkens één sector en stuurt de inhoud naar de Vdip1.
In het voorgaande hebben we gezien hoe na twee stappen het schrijven naar de Vdip1 geoptimaliseerd kon worden. Omdat we bij het kopiëren naar de Vdip1 op de TRS-80 gebruik konden maken van “GET” (samen met OPEN “D”, 2, filename.ext) waren we aan die zijde verzekerd van een optimale leessnelheid.
Bij kopiëren naar de TRS-80 werd al voorvoeld dat de TRS-80 kant het grootste probleem zou zijn. Schrijven op de TRS-80 met PUT is sneller dan PRINT #. Maar met PUT is het niet mogelijk een bestand van willekeurige lengte te schrijven: files zijn altijd n x 256 bytes. Daarom werd toch eerst naar PRINT # gekeken (Vdip1/bas). Dat was teleurstellend. Een 25 kb bestand kopiëren duurde 20 sec (zie Tijdtabel 2). Uiteindelijk zijn we toch uitgekomen op PUT (25 kb schrijven in 9 sec), maar helaas met de onelegante oplossing van het aanpassen van de EOF in het File Control Block (FCB) met een drietal POKEs. Het is niet anders.
Omdat er een verschil is in ASCII bestanden tussen TRS-80 (cr) en ATX computers (crlf) werd er ook voorzien in Acopy van de ATX computer naar de TRS-80. Daarbij wordt wel gebruik gemaakt van PRINT #, andere oplossingen zijn veel ingewikkelder. Omdat er dan veel meer PRINT’s nodig zijn, is het kopiëren relatief langzaam (ACopy 40 sec, versus 9 sec van Copy). Het 25 kb bestand telt 100 sectoren, oftewel 100 PUT’s met Copy, maar wel 329 regels, of te wel 329 PRINT #jes met ACopy. Eventueel toch maar voorafgaand aan de Copy een bestand van crlf naar cr converteren op de ATX computer? Overigens, anders dan bij gewone tekst bestanden (b.v. te editen met LeScript), is voor Basic de crlf geen probleem (de lf wordt kennelijk genegeerd)!
In Tijdtabel 2 staan de metingen met meerdere testen (Newdos Copy, Basic Save) en 2 verschillende manieren van het schrijven van het TRS-80 doelbestand (Print # (Vdip1/bas) en Put met aanpassen van EOF (Vdip2/bas)). In Tijdtabel 2 werd een bestand van 25 kb gebruikt (Vdip2/bas). Dat de ASCII-copy betrekkelijk lang duurt accepteren we voorlopig maar. Overigens, alleen Vdip0/bas werd op de TRS-80 geschreven. Met Vdip0 kon op rudimentaire wijze data van de ATX naar de TRS-80 over gezet worden. Hiervoor werd gebruik gemaakt van de Log file functionaliteit. Vervolgens werden Vdip1 en Vdip2/bas op de ATX computer geschreven. Een beetje flauw misschien, maar de ATX (programma) editors zijn voor huis-, tuin- en keuken gebruik toch iets krachtiger dan LeScript (voor ons de enig algemeen bruikbare editor op de TRS-80). Met de ATX kon ook gemakkelijker gebruikt gemaakt worden van extra afdrukmogelijkheden: een ATX (laser) printer is inmiddels gemakkelijker in het gebruik dan TRS-80 printers met uitgedroogde inktlinten.
Tja, nu nog Vdip versie 3. Voor zover dat nodig is natuurlijk. Zolang gewerkt kan worden met een Ramdisk of Harddisk kan Vdip2/bas best voldoen: rechttoe rechtaan kopiëren van bestanden gaat dan snel genoeg (het is dan vooral de Vdip1 zelf die de limiterende factor is). Voor gebruik met floppy’s vraagt Vdip2/bas veel geduld. Dan zal versie 3 moeten gaan voorzien in grotere machinetaal routines met buffering van b.v. een hele track (evt. dubbelzijdig, dubbeldensity, of te wel een buffer van 36 sectoren, 9216 bytes). Maar 6 sectoren bufferen (het aantal dat bij dubbel-density in één omwenteling gelezen of geschreven kan worden) zal al een enorme vooruitgang beteken. Een en ander vanzelfsprekend met uitstel van de verify-read naar óf verify-read per gebuf- ferde hoeveelheid data, óf een verify-read achteraf van het gehele bestand.
Van deVdip1 wordt nu één USB poort gebruikt, n.l. de poort voor aansluiting van de BOMS (Bulk Only Mass Storage). Toch eens kijken wat er gedaan kan worden met een muis, aangesloten op de 2e USB poort van de Vdip1 (zie de Vdip1 documentatie, de Vdip1 voorziet wel in de signalen voor de 2e USB connector, maar de connector zelf moest op het interface printje komen, hier precies passend naast de 24-pens ic voet en onder de USB-connector op de Vdip1). Mogelijk dat er een muis bij kan en dan kopiëren met verslepen van bestanden... Dat zou lachen zijn.
Wat zijn de mogelijkheden van de Vdip1? Daarvoor verwijzen we naar de lijst met commando’s op de volgende pagina’s. Om kort te gaan, alle gebruikelijke File commando’s zijn mogelijk: in dos termen cd, md, rmdir, type en rename en natuurlijk programma functies als file open, read, write, seek en close. Daarmee is het mogelijk bestanden naast sequentieel ook random te lezen. Random schrijven lijkt niet mogelijk te zijn: na iedere schrijfopdracht wordt de EOF aangepast, waarmee alle data na de geschreven sector de facto als verloren beschouwd moeten worden. Verder zijn er nog vele andere commando’s, waaronder de zeker interessante debug com- mando’s. Ze maken het mogelijk een willekeurige BOMS sector te lezen en te analyseren, b.v. Master Boot record, FAT tabellen, Root directory, etc.
Wat zijn de beperkingen van de Vdip1? De minst hinderlijke beperkingen zijn een FAT device met 8.3 bestandsnamen. Ook met 8.3 bestandnamen kan niet zomaar alles overgezet worden naar de TRS-80, waar in bestandsnamen alleen letters en cijfers mogen. De Vdip1 als TRS-80 schijf gebruiken kan alleen in combinatie met een Ramdisk. Gesteld dat je de TRS-80 opgestart krijgt, dan zou je met een diskette-image op een USB-stick deze als (write-protected) drive 0 kunnen gebruiken. Voor snel en makkelijk werken worden dan de meest gebruikte (o.a. de systeem bestanden) naar de Ramdisk gekopieerd. Vervolgens wordt er op de Ramdisk gewerkt. Extra en/of gewijzigde bestanden kunnen dan met Copy functie van Vdip2/bas als losse bestanden naar (en van) de USB-stick gekopieerd worden, die dan als aparte files opgeslagen worden, buiten de write-protected opstart-diskette image. In de TRS-80 zouden voor het benaderen van USB-stick bestanden mogelijk ook omgeleide cassette commando’s als Cload, Csave en Print #-1 gebruikt kunnen worden, maar of dat voordeel biedt boven kopiëren van en naar een Ramdisk met Vdip2/bas... Wacht, er is nog een optie: als de 1e sector van de disk-image file op de USB-stick bekend zou zijn, en als de image-file in één reeks sectoren geschreven zou zijn, kan er met de Vdip debug commando’s SD en SW naar hartelust gelezen en geschreven kunnen worden...
Kopiëren van en naar de Vdip1 met het programma Vip2/bas vraagt nogal wat code. Met commentaar (en spaties tussen alle Basic woorden en variabelen) is het 25 kb groot. In gecomprimeerde vorm (commentaar weg en spaties zoveel mogelijk verwijderd) is het programma altijd nog 8 kb. En dan heeft het slechts rudimentaire fout-afhandeling. Daarom lijkt het benaderen van een BOMS op de Vdip1 en deze gebruiken als TRS-80 disk geen gemakkelijk begaanbare weg. Zoals eerder gezegd, waarschijnlijk alleen via de debug commando’s SD en SW voor het lezen en schrijven van 512-bytes sectoren. Afd. West.
