Heiko Prüssing
Home
Projects
Blog
About
'MARVIN' - Ein MOS 6502 Selbstbau-Computer
2015-02-15
## What's that? 'MARVIN' ist ein 8-Bit DIY-Computer auf Basis des 6502 Prozessors von MOS Technology Inc. ![](bootmsgng.png) ## Inhalt 1. [Erste Schritte](#Einleitung) 2. [Der NOP-Generator](#NOPGenerator) 3. [RAM, ROM, VIA](#kap2) 4. [EPROM, UART und SPI](#kap3) 5. [Erste Software](#kap4) 6. [Der Basic - Interpreter](#kap5) 7. [SD-Kartenleser](#kap6) 8. [Sound mit dem SID](#sound) 8. [Nächste Schritte](#nextsteps) ![](marvin1.jpg) ###
Erste Schritte An einem langweiligen Sonntag-Nachmittag 2014 viel mir zufällig Daheim ein alter 8-Bit Prozessor "6502" von MOS-Technology bzw. Commodore in die Hände. Laut Aufdruck von 1983. Diesen hatte ich vor Jahren von einem alten VC-20 Board von Commodore "gerettet". Im Netz kursieren derzeit so einige Projekte, die mit diesem Prozessor einen kleinen Computer bauen. Das hat dann mein Interesse geweckt, so dass ich auch so etwas haben wollte. Und so ging's los. . . :-) ###
Der NOP-Generator Ein erster Schritt ist der "NOP-Generator" oder auch "Free Run" der CPU: Hierbei wird der Datenbus fest auf die Adresse $EA verdrahtet, welches beim 6502 dem Befehl "NOP" ("No operation") entspricht. Bei jedem Zugriff holt er sich dadurch den Befehl NOP und inkrementiert seinen Programm Counter um eins. Dann holt er sich den nächsten und bekommt wieder "NOP", usw. . . Dadurch läuft er einfach von $0000 bis $ffff durch seinen Adressraum und fängt dann vorn wieder damit an. Unendlich. Eigentlich ganz einfach: [![Foo](NOP-Generator-small.jpg)](NOP-Generator.jpg) Eigentlich ist nicht viel auf dem Board: * Ein paar LED's, die die Aktivität der Adressleitungen A15-A11 anzeigen * Ein Schwingkreis mit Taktteiler, der einen 4 MHz Takt genieriert und durch 4 Teilt (einen kleineren Quarz hatte ich nicht mehr). * Einen Resettaster Fertig. Läuft! :-) Alles eigentlich nicht so wild . . . ###
RAM, ROM, VIA... Die LED's blinken ja ganz toll, aber so ein richtiger Computer ist das noch nicht. Es muss also noch RAM und etwas ROM für ein Programm her. Damit der Computer aber auch mit seiner Außenwelt auch kommunizieren kann, musste noch ein Portbaustein "MOS 6522" her. An PA0 dieser VIA hab ich einfach eine weitere LED angeschlossen. Diese kann dann die Software an und aus schalten - Debugstufe 1 :-). Zusätzlich ein paar Standard-TTL's für die Adressdekodierung. Fertig. Als RAM kam zuerst ein 8kb Baustein (6264) zum Einsatz, der noch in einer Schublade lag. Später konnte ich ihn gegen einen 32KB Baustein austauschen. Als ROM kam ein alter 27128 (16kb) bzw. später ein 27512 (32kb) zum Einsatz. [![](Prototyp-small.jpg)](Prototyp.jpg) Bei der Adressdekodierung hab ich mich etwas von anderen Projekten inspirieren lassen. So sieht der aktuelle Adressraum aus: * $0000 - $7FFF: RAM * $8000 - $E7FF: ROM (low) * $E800 - $EFFF: IO VIA 6522 * $F000 - $FFFF: ROM (high) Dies passiert mit einer Handvoll diskreten TTL-Gattern, die noch Zuhause herumflogen. ###
EEPROM, EPROM, UART und SPI Eine Software war schnell geschrieben, die die LED blinken lies. Das EPROM hatte ich dann mit meinem alten C64-EPROMER ("PULSAR") gebrannt, den ich seit den 80ern habe. Aber es fehlte eine vollwertige serielle Schnittstelle, mit der man auch mehr machen kann. Auch ist das Brennen des EPROMs mit vorherigen UV-Löschen doch recht aufwendig. Leider habe ich keinen passenden UART (16550) oder ACIA (MOS6551) zur Hand, aber dafür ein paar Arduinos! :-) Daher habe ich einen "Arduino Micro" kurzerhand als UART und auch als EEPROM misbraucht, der an den IO-Ports der VIA hängt. Die VIA erledigt alles per Bitbanging. Als Kommunikationsprotokoll hab ich mich dann für SPI entschieden. Ich habe mir ein paar SPI-Register im Arduino ausgedacht, die entweder die EEPROM-Funktion oder die UART-Funktion anprechen. Das Programm für den 6502 kann ich dann einfach zusammen mit dem Arduino Code dort flashen. Der Arduino-SPI-UART überträgt oder empfängt Zeichen dann zum PC/Mac per USB. Auf dem Host kann ich dann ein ganz normales Terminal-Programm verwenden, um mit dem Rechner zu kommunizieren. Ein FIFO-Buffer in der Software macht ihn auch noch zudem schneller als jede 1541 am C64... :-) [![](Prototyp2-klein.jpg)](Prototyp2.jpg) Das SPI Protokoll ins Laufen zu bringen war dann doch schon etwas aufwendiger. Teilweise habe ich mir mit ein paar Simulatoren wie VICE weitergeholfen. Um die Diagnose weiter zu erhöhen habe ich zusätzlich die 8 höchsten Adressleitungen auf LED's gelegt. So kann man besser sehen, in welchen Adressbereich sich die CPU gerade herumtreibt. ###
Software muss her! Der WOZ-Monitor von Steve Wozniak aus dem Apple 1 schien mir als nächster Schritt recht brauchbar. Mit dem kleinen Monitor kann man sich schnell Speicherbereiche anschauen oder verändern und ein Programm ausführen lassen. Zusammen mit dem "Arduino-SPI-UART" kann man dann Befehle eingeben und die Ausgaben ansehen. Ich musste nur die IO-Funktionen an meinen UART anpassen: [![](ErsteKonsolenausgabe-small.png)](ErsteKonsolenausgabe.png) Allerdings ist die direkte Eingabe der Programme in Hex doch recht aufwendig. Eine Übertragung muss her! Dazu nahm ich die Übertragung per "Intel Hex Format" vor. Glücklicherweise gab es schon Erweiterungen des WOZ-Monitors hier, die ich als Grundlage verwenden konnte. Die Konvertierung des Binären Codes in das Format ist mit dem Tool "SRecord" recht einfach. Das Tool kann noch weit mehr. Ein Bauen aus dem Source ist dann doch schon recht aufwendig, da Berge an zusätzlichen Bib's gezogen werden. Außerdem verschluckte sich mein Arduino, wenn vom HOST in kurzer Zeit zu viel Zeichen an den Arduino gesendet werden, so dass ein anderes Übertragunsprotokoll her musste. Das gute alte XMODEM-Protokoll schien mir dazu recht brauchbar. Auch hier waren schon andere dabei, den WOZ-Monitor zu erweitern. Die Probleme mit dem Arduino konnt ich dann aber erst mit dem Update auf V1.0.6 Arduino lösen. Da gab es offensichtlich einen Bug in der Serial Class. Mit dem Upload der Programme per serieller Verbindung braucht man jetzt für ein neues 6502 Programm auch den Arduino nicht mehr neuzuflashen. Das ist schon mal ein guter Fortschritt. Die SPI-EEPROM Funktion des Arduinos ist also nicht mehr notwendig... ###
BASIC-Interpreter Was wäre ein 6502-Computer ohne BASIC-Interpreter? Zu der Hochzeit des Prozessors war faktisch bei allen Computern irgendwie BASIC möglich. Bei den meisten war es einfach eingebaut. Daher musste jetzt auch hier ein Basic her. Zur Auswahl stand bei mir die Verwendung des C64-Basic oder der EhBASIC von Lee Davison. Ich habe mich dann für letzteres entschieden. Nach ein paar Anpasungen für meinen "SPI-UART" lief auch dieser BASIC Interpreter auf dem Rechner: [![](basic-small.png)](basic.png) Das Lesen und Speichern von Programmen per LOAD und SAVE geht aber noch nicht. Wohin auch? Es gibt keinen angeschlossenen Datenträger, der ein Basic Programm aufnehmen könnten. Es muss also ein Massenspeicher her. Wie wäre es mit einer SD-Karte? Diese kann man gleich an den SPI Bus anschließen... ###
SD-Kartenleser Eine SD-Karte schien mir am einfachsten anzubinden, da SPI ja schon vorhanden ist. Allerdings läuft die SD-Karte mit 3.3V statt mit 5V wie der Arduino oder der VIA6522. Also musste ein Levelshift her, der die Pegel wandelt. Es gibt da mehrere Möglichkeiten. Ich habe mich für einen 74LS07 mit Open Collector Ausgänge entschieden. Dieser flog hier auch noch herum. So sieht der Level-Shifter aus: [![](SPILevelshifting-small.png)](SPILevelshifting.png) Nun nur noch schnell die Software zum Lesen der SD-Karte :-) Die Spezifikationen dazu zu verstehen ist nicht ganz einfach. Es gibt einen ganzen Sack voller Unterschiede zwischen den Kartentypen. Die richtige Reihenfolge der Kommandos war entscheidend. Es sollte mit einer mit 2GB und einer mit 8GB (SDHC) funktionieren und dann tat es das auch: [![](sdcardread.png)](sdcardread.png) Hier zu sehen der Bootsektor der ersten Partition darauf mit FAT32-Dateisystem. Es werden derzeit aber nur die rohen Sektoren gelesen. FAT32 ist dann nochmal eine andere Hausnummer. Dies muss aber doch erstmal warten. ###
Sound
- 13. Februar 2015 -
Mir juckte es die ganze Zeit in den Fingern, dass MARVIN auch Sound haben sollte. Nur Piepsen über eine Portleitung an der VIA wäre zu einfach und zu langweilig. Es muss schon richtiger Sound aus der 8-Bit Ära sein. Wie wäre es mit dem Sound Chip des C64 dem 6581? Genau das sollte es werden! Leider hatte ich keinen SID herumliegen. Einen C64 zur Organspende zu bewegen, war mir dann doch etwas zu riskannt. Außerdem benötigen die orginalen SID noch eine 2. Spannungsquelle: 12V oder 9V was das ganze etws verkompliziert. Zum Glück gibt es aber Nachbauten des SID's auf Basis eines ATmega88: [![](swinsid-small.jpg)](swinsid.jpg) Diese Laufen ja mit nur 5V. Für eine spätere Platinenversion ist dann noch diese Referenzspannung vorzusehen, aber im Moment reicht dann die 5V. Mit einer Leihgabe eines "SwinSID" war dann alles geritzt. Leider geht mir auf dem Steckbrett langsam der Platz aus und ich musste eine 2 Reihe einhängen: [![](marvin1.jpg)](marvin1.jpg) Da es jetzt 2 IO-Bausteine gibt (die VIA und der SID) musste ich die IO-Dekodierung noch etwas erweitern. Das habe ich mit einem 74LS138 gemacht, der den IO-bereich weiter dekodiert. Da ich kein Baustein erwarte, der mehr als 32 Register besitzt, bekommt jeder IO-Bereich genau 32 Bytes. Das sieht dann wie folgt im Speicher aus: * $E800 VIA * $E820 SID * $E840 (frei) * $E860 (frei) * $E880 (frei) * $E8a0 (frei) * $E8c0 (frei) * $E8e0 (frei) Für spätere Erweiterungen ist also noch genügend frei. Ein kurzes Testprogramm hab ich dann geschrieben, um dem SID bei $E820 einen Testton zu entlocken. Aber leider nix! Gar nix. Also den SwinSID nochmals ausgebaut und in einen C64 gesteckt. Tadellos! Nichts kaputt! Mhhh... Mit einem Multimeter die CS-Leitung zu dekodieren ist fast kaum möglich. Also musste doch ein Logic Analyzer her. Es gibt einfache günstige, die für mein Vorhaben geeignet sind. Hier hab ich dann einfach den "Logic Pirate" gekauft. Er kostet ganze 20 Euro und wird am PC/Mac angeschlossen. Bei der Analyse ist mir dann aufgefallen, dass die CS-Leitung vom SID auch geschaltet wird, aber es zu Zeitpunkten, an denen ich den SID gar nicht ansteuere, es auch zu ganz kurzen "Lows" auf der CS-Leitung kam. Sehr sporadisch. Seltsam... Zufällig bin ich dann im Netz über das hier gestolpert:
"GLITCH" oder "HAZARD"
Was wenn das bei mir auch passiert, da die Adressdekodierung auch mehrere Gatter hintereinander geschaltet verwendet? Und tatsächlich, ich habe "GLITCHES"! :-) An der Adressdekodierung etwas zu verändern ist schwierig. Man könnte auf GAL umsteigen oder CPLD's verwenden, aber das wäre jetzt ein zu größer Aufwand für das Problem. In der Schaltung ist mir dann aufgefallen, dass es ja eine Freigabeleitung gibt, die aber derzeit permanent auf Low liegt. Vielleicht gibt's eine Leitung an der CPU, die nach dem Adressanlegen auf Low geht? Die PHI2 Leitung des 6502 geht leider nicht, denn diese geht in dem Moment auf High. Aber es gibt die PHI1-Leitung von der CPU, die PHI2 nur invertiert ist. Genau die brauchte ich. Also schnell die Leitung von PHI1 an die Freigabeleitung des Adressdekoders angeschlossen. Alles wird nun mit dem Systemtakt synchronisiert. Die Schaltung sieht dann so aus: [![](adressdecoder.png)](adressdecoder.png) Im Login-Analyzer sieht jetzt alles gut aus. Testprogramm für den SID wieder starten und TADAAAAAA!!!! Ein Ton ertönt aus dem angeschlossen Lautsprecher! Ein sehr sehr einfaches Programmchen: ![](simplesid.jpg) Wie schön wäre es nun, wenn er einen SID-Tune vom C64 abspielen könnte? Leider liegt mein SID nicht bei $D400 wie beim C64 sondern bei $E820. Dann muss ein Konverterprogramm her, der die Adressen im SID-File einfach abändert. Dazu hab ich mir ein kleines C-Programm geschrieben, dass mir das Binärfile durchforstet und alle Assemblerbefehle schreibend auf $D400 bis $D420 auf meine Adressen abändert. Es gibt da ganz bestimmte Kombinationen, die man überprüfen kann. Eigentlich recht simpel. Das konvertierte SID File wird dann auf MARVIN übertragen und ein kleines Player-Programm dazu geschrieben, dass die Initialisierung macht und die Playroutine 50 Mal pro Sekunde anspringt (über einen VIA Timer) fertig. Er spielt!!!!! Ich hatte mir das Sound-File vom Spiel "1942" ausgesucht...Läuft tadellos. Mit "+" und "-" kann MARVIN zwischen den Liedern im File wechseln: ![](SIDPlayer.png) Der Player ist aber nun sehr speziell nur für das eine Lied. Man sollte die Konvertierung vielleicht besser auf MARVIN selbst machen, statt auf dem PC/MAC. Aber das ist dann Aufgabe für einen anderen Abend... :-) Aktuell sieht das Gesamtsystem folgendermaßen aus: [![](hardware.png)](hardware.png) ###
Nächste Schritte - Statt serielle Console zusätzlich per Wifi (ESP32)... - Das Steckbrett verlassen und MARVIN auf eine echte Platine bringen... Stay tuned...
- 3221 -