Forum: Mikrocontroller und Digitale Elektronik ESP32 als Modul-Emulator für den C64


von Frank Niggemann (Gast)


Lesenswert?

Hallo zusammen :)

Ich habe mir eine Platine anfertigen lassen, mit der ich einen ESP32 
über Levelshifter an den Expansion-Port des C64 anschließen und mit 
allen benötigten Signalen verbinden kann.

Bisher programmiere ich dieses ESP32-WROOM-32-Board mit 38 Pins über die 
Arduino IDE. Ich möchte 8KB von den internen 520KB SRAM nutzen um damit 
einen ROM-Chip zu simulieren. Ich habe zwar herausgefunden, wie ich das 
Programm in C/C++ schreiben muss um mir ein entsprechend großes 
Byte-Array zu erstellen und wie ich das ROM-Image da hinein bekomme. 
Wenn ich nun aber über den Interrupt auf den Tackt des C64 warte, dann 
die Adresse bittweise einlese über A0-A15 und dann das Byte bitweise auf 
die Datenleitungen D0 bis D7 lege, dann ist das zu langsam.

Bei meinen Atmel-Chips konnte ich das damals im Atmel AVR-Studio 
deutlich leichter machen. Da habe ich einfach das Byte aus dem 
entsprechenden Register geladen oder in das entsprechende Register 
geschoben.

Ich stelle mir den Ablauf des Programms wie folgt vor:
- Warte auf Interrupt
- Lese Low Byte der Adresse von Adressbus
- Lese High Byte der Adresse von Adressbus
- Lese das Byte an dieser Adresse aus dem RAM
- Schreibe das Byte auf den Datenbus

Bei einem Atmega wüsste ich in etwa, wie ich das in Assembler machen 
kann. Leider ist dieser viel zu langsam für diese Aufgabe. Mit einem 
Cyvlone IV FPGA-Chip wäre die Geschwindigkeit kein Problem und da wüsste 
ich auch, wie ich das hinbekomme. Diese Lösung ist jedoch deutlich 
teurer und bringt einige andere einschränkungen mit sich, die ich dann 
anders lösen müsste.

Ich habe auch schon überlegt einen zusätzlichen SRAM-Chip zu verbauen, 
mit dem ich in der für den C64 irrelevanten Tackthälfte kommuniziere. 
Dann hätte ich bei dem zusätzlichen SRAM pro Tackt des C64 zwei 
Lese-Schreib-Zyclen. Einen für den C64 und einen für den ESP32.

Diese Lösung erscheint auf den ersten Blick leichter umsetzbar zu sein. 
Dem ist jedoch leider nicht so, weil ich dann für die Zeit, in der ich 
mit dem ESP32 auf den SRAM zugreife, die Verbindung zwischen dem SRAM 
und dem C64 "kappen" muss um eventuelle ungewollte Auswirkungen zu 
vermeiden. Dadurch wird die ganze Schaltung wieder komplexer und teurer.

Wenn jemand eine Lösung für das Problem kennt oder mir sagen kann, wie 
ich den Code auch in C/C++ für den ESP32 so effizient schreiben kann, 
dass ich den von mir gewünschten Programmablauf realisieren kann, dann 
bin ich für jeden Tipp dankbar :)

Gruß

Frank

von Frank Niggemann (Gast)


Lesenswert?

Ich habe vergessen bei meinen Beschreibungen zu erwähnen, dass der RAM 
im C64 eine Reaktionszeit von 100ns hat. Das bedeutet, dass das Signal 
innerhalb dieser Zeit auf den Datenleitungen liegen muss. Das 
zusätzliche SRAM hätte eine Reaktionszeit von max 12ns und die 
Levelshifter von max 33ns. Damit wären wir an dieser Stelle bei max 45ns 
in der Summe.

Gruß

Frank

von Jens M. (schuchkleisser)


Lesenswert?

Eine Echtzeit-RAM-Emulation dürfte unmöglich sein.
45 Nanosekunden hieße, das der mit 26MHz angetriebene ESP etwa einen 
Takt Zeit hätte sich zu kümmern.

Du brauchst ein Dualport-RAM, das du vom ESP aus beladen kannst, das auf 
der anderen Seite dann "normal" funktioniert.

von Pepe T. (pepe_t)


Lesenswert?

Jens M. schrieb:
> 26MHz

240 mhz meinst du?

Der C64 6502 ist ja ein 1 mhz ding, eine schnarchnase.

: Bearbeitet durch User
von Frank Niggemann (Gast)


Lesenswert?

Vielen Dank für deine Antwort Jens :)

Der ESP32 ist ein Dualcore Microcontroller, der mit 240MHz tacktet. Um 
die 100ns des C64 RAMs zu emulieren habe ich also 24 Tackte Zeit.

Das mit dem Dualport-RAM ist eine gute Idee. Das schaue ich mir mal an 
:)

Danke

Gruß

Frank

von Pepe T. (pepe_t)


Lesenswert?

Frank Niggermann schrieb:
> habe ich also 24 Tackte Zeit.

Un wo ist da das problem?
Um daten aus einem array auszulesen sollte das locker reichen.
Der esp32 ist aber nicht gerade die gute wahl für sowas.

: Bearbeitet durch User
von Mario M. (thelonging)


Lesenswert?

Frank Niggemann schrieb:
> dann die Adresse bittweise einlese über A0-A15 und dann das Byte
> bitweise auf die Datenleitungen D0 bis D7 lege, dann ist das zu langsam.

GPIO_IN_REG und GPIO_OUT_REG sind Deine Freunde.

von Pepe T. (pepe_t)


Lesenswert?

Frank Niggermann schrieb:
> - Warte auf Interrupt

Wozu das denn? Willst du nebenher noch eine webseite bedienen?

SCNR

: Bearbeitet durch User
von Frank Niggemann (Gast)


Lesenswert?

Danke für eure Antworten :)

@Jens M.: Ich habe mir gerade mal die Preise für Dualport-RAM angesehen 
und das würde den Gesamtpreis vervierfachen.

@Pepe T.: Das Problem ist, dass ich mit dem aktuellen Code deutlich mehr 
Tackte benötige, da ich jeden Port einzeln einlese ;) Warum ist ein 
ESP32 keine gute Wahl?

@Mario M.: Danke für den Hinweis. Ich werde mal damit rumexperimentieren 
und am Oszilloskop die Zeiten messen. :)

Gruß

Frank

von Jens M. (schuchkleisser)


Lesenswert?

Pepe T. schrieb:
> Jens M. schrieb:
>> 26MHz
>
> 240 mhz meinst du?

Auch mit 240MHz sind nur knapp 10 Takte um die Adresse zu holen, das 
Byte zu lesen und wieder auszugeben, that claps not.
Zumindest nicht wenn die Kiste noch was anderes machen soll, z.B. sich 
um typischen ESP-Kram wie WLAN zu kümmern.

Was ginge: den ganzen C64 in den ESP zu laden: 
https://github.com/rpsubc8/ESP32TinyC64

Frank Niggemann schrieb:
> Um
> die 100ns des C64 RAMs zu emulieren habe ich also 24 Tackte Zeit.

Oben schraubtest du 45ns.
Aber wenn wir jetzt damit anfangen, dann mal richtig nachgerechnet, denn 
ich hab mich oben auch vertan.
Normal ist es so das der Prozessor die Adresse anlegt und binnen 100ns 
muss die Antwort da sein, was der normale Chip schafft.
Du musst jetzt zuerst durch die Levelshifts (33ns), dann darf der ESP 
überlegen woher er die Daten zieht (a), das legt er an den echten RAM 
(b) der dann binnen 12ns liefert. Nun muss der ESP einlesen (c) und die 
Ports passend schalten (d), dann wieder zurück durch die Shifts (33ns).
33ns+a+b+12ns+c+d+33ns < 100ns.
a+b+c+d = <12ns.
Bei 240MHz dauert ein Clock 4,16ns, sollte der Chip tatsächlich einen 
Befehl pro Clock schaffen, bleiben also ganz knapp 3 Clocks über um ein 
Byte auszuliefern.
Nö, wird kein.
Oder überseh ich da was? Man mög mir erklären wo, anstatt wieder 56 
Minuspunkte zu vergeben... ;)

Wobei ich mich frage warum die Shifts so lange brauchen wenn das RAM 
quasi instant liefern kann, das ist doch weit komplexer?!

von Jens M. (schuchkleisser)


Lesenswert?

Frank Niggemann schrieb:
> Ich habe mir gerade mal die Preise für Dualport-RAM angesehen
> und das würde den Gesamtpreis vervierfachen.

Tjoa, wer braucht sowas schon noch heutzutage, und dann ist eh alles 
knapp und teuer. Mein aktueller Rekord: 3-Achs-Accelerometer, 
Mouserpreis knapp 4€, Verfügbar August 23. Jemand anders bietet die für 
208€ an, lagernd.
Da sind 40€ für einen Baustein aus den 90ern doch ein Schnapper.

von Stefan F. (Gast)


Lesenswert?

Ich würde nicht einfach davon ausgehen ausgehen, dass die I/O Pins genau 
so schnell getaktet sind, wie der CPU Kern.

2x Pin Toggeln per Software dauert offenbar 150ns.

https://www.instructables.com/Faster-ESP32/

von someone else (Gast)


Lesenswert?

Falscher Mikrocontroller. Der ESP32 ist beim PIN toggle eher gemütlich 
und "ungenau" bezgl. Timing.

Raspberry RP2040 könnte für deinen Zweck besser geeignet sein. Immerhin 
kann der mit Overclocking HDMI per Bitbanging.

https://github.com/Wren6991/picodvi

von Jim (Gast)


Lesenswert?

Müssen die Daten wirklich nach 100ns auf dem Bus liegen?
Der 6510 im C64 hat (in der PAL-Version) einen Systemtakt von 0,98 MHz.
Meines Erachtens sollte da nach Adreß-Setup mehr Zeit bleiben, bis der 
Datenbus gelesen wird, lt. Datenblatt kann die Memory Read Access Time 
bei 1 MHz Takt max. 575 ns lang sein.

von Mario M. (thelonging)


Lesenswert?

someone else schrieb:
> Raspberry RP2040 könnte für deinen Zweck besser geeignet sein.

Oder einen Teensy:
https://microcorelabs.wordpress.com/2021/03/20/eprom-emulator/

Ich persönlich würde ja einen Eprom-Emulator nehmen:
https://www.shotech.de/de/shoemu2-eprom-emulator-2716-to-27512.html

von Frank Niggemann (Gast)


Lesenswert?

@Stefan F.: Danke für den Hinweis. Das hilft mir weiter.

@someone else: Ich habe mir die Daten des RP2040 mal angesehen. Den 
hatte ich bisher nicht in Betracht gezogen. Eventuell hilft das weiter. 
Ich werde mir mal einen davon bestellen und schauen, ob es damit geht. 
Eventuell kann ich den auch als "Zwischenspeicher" nehmen. Dann hätte 
ich das WLAN des ESP32 und die schnelle schaltgeschwindigkeit des 
RP2040.

@Jim: Leider ist das nicht so einfach, da die restliche Hardware des C64 
ja auch noch eine unbekannte Anzahl X an Nanosekunden benötigt um das 
Signal zu verarbeiten. Daher wollte ich möglichst nah an die 100ns des 
verbauten RAMs dran kommen.

@Mario M.: Das mit dem Teensy hatte ich auch schon überlegt. Den hatte 
ich dann aber auf Grund des Preises erst einmal wieder verworfen.

@Jens M.: Wenn ich keinen separaten SRAM benötige, dann reichen die 
Zeiten der Levelshifter aus. Da habe ich noch mal geschaut und es gibt 
welche, die bei ca. 15ns liegen. Also hätte ich 2x15ns = 30ns für das 
Levelshifting und hätte 70ns Zeit für den ESP32. Die werden aber 
anscheinend nicht reichen, da der ja an den Ausgängen so langsam 
schaltet.

Vielen Dank an euch alle :)

Gruß

Frank

von Pepe T. (pepe_t)


Angehängte Dateien:

Lesenswert?

Frank Niggermann schrieb:
> Den hatte
> ich dann aber auf Grund des Preises erst einmal wieder verworfen.

Hast du den W806 schon mal angeschaut?
Oder den W801 mit WiFi ?

von asd (Gast)


Lesenswert?

Beachte dass beim C64 der Speicher auch vom Video-Chip angesprochen 
wird, immer abwechselnd. Der RAM muss also doppelt so schnell sein wie 
bei einer 1MHz CPU üblich.
Wenn du kein Dual-Port RAM nehmen willst kannst du ein normales RAM 
nehmen und das Timing so hin drehen dass der ESP32 das RAM 
schreibst/liest wenn weder CPU noch Videochip das machen (also das RAM 
ist dann so schnell wie bei einer 4MHz CPU nötig wäre). Wenn du nur hin 
und wieder das RAM zugreifen willst, kannst du die CPU auch per "HALT" 
Leitung in den Wartezustand schicken, dein RAM aktualisieren, dann die 
CPU weiter laufen lassen.

von Frank Niggemann (Gast)


Lesenswert?

@Pepe T.: Dieses Board kannte ich noch nicht und das scheint es nur als 
Import zu geben. Werde ich mir bei Zeiten mal anschauen :) Danke für den 
Tipp!

@asd: Das macht die ganze Sache natürlich schwieriger. Zumal der C64 am 
Expansion-Port keine Leitung "Halt" hat. Aber dazu habe ich hier etwas 
gefunden: 
https://codebase64.org/lib/exe/fetch.php?media=base:safely_freezing_the_c64.pdf

Danke

Gruß

Frank

von Rolf M. (rmagnus)


Lesenswert?

Frank Niggemann schrieb:
> Ich habe vergessen bei meinen Beschreibungen zu erwähnen, dass der RAM
> im C64 eine Reaktionszeit von 100ns hat.

Laut https://www.c64-wiki.de/wiki/RAM#Modifikationen_von_DRAM-Chips sind 
für den RAM Zugriffszeiten bis 350 ns ok.

Frank Niggemann schrieb:
> Ich stelle mir den Ablauf des Programms wie folgt vor:
> - Warte auf Interrupt

Die ganze Idee von Interrupts ist, dass man nicht warten muss. Wenn du 
eh wartest, brauchst du keinen Interrupt.

> - Lese Low Byte der Adresse von Adressbus
> - Lese High Byte der Adresse von Adressbus
> - Lese das Byte an dieser Adresse aus dem RAM
> - Schreibe das Byte auf den Datenbus

Pepe T. schrieb:
> Frank Niggermann schrieb:
>> habe ich also 24 Tackte Zeit.

"Takte"

> Un wo ist da das problem?
> Um daten aus einem array auszulesen sollte das locker reichen.

Die Frage ist, wie viel Zeit für die Reaktion auf den Interrupt drauf 
geht. Das wird vermutlich mit Abstand am meisten Zeit kosten (abgesehen 
offenbar vom eigentlichen Pinwackeln).

von Pepe T. (pepe_t)


Lesenswert?

Rolf M. schrieb:
> wie viel Zeit für die Reaktion auf den Interrupt drauf
> geht.

Wie du selber schreibst macht ein interrupt hier keinen sinn.
Ein kern soll das pollen, der andere macht wifi.
Die frage ist wie weit sich die dinger gegenseitig behindern.

Beim esp8266, für meine wärmepumpen-auslese-soft musste ich das wifi 
abschalten wenn's zeitkritisch wurde. Bei der 71 mal WS2812 anzeige 
musste ich sogar interrupts kurzzeitig sperren.

Das esp-wifi scheint bezüglich latenzzeit gutmütig zu sein.

: Bearbeitet durch User
Beitrag #7000668 wurde von einem Moderator gelöscht.
von Michael W. (miks)


Lesenswert?

Frank Niggemann schrieb:
> Tackthälfte

Frank Niggemann schrieb:
> pro Tackt

Frank Niggemann schrieb:
> 240MHz tacktet.

Frank Niggemann schrieb:
> 24 Tackte

Frank Niggemann schrieb:
> mehr
> Tackte

Es heißt: Takte - ohne ze-kah!

von Stefan F. (Gast)


Lesenswert?

Michael W. schrieb:
> Es heißt: Takte - ohne ze-kah!

Nur wenn man sie hören könnte, dürfte man sagen dass sie tickt und 
tackt.

(Ja: Deutsch ist unlogisch)

von mIstA (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> (Ja: Deutsch ist unlogisch)

Gut was will man schon von einer Sprache erwarten in der »etwas 
umfahren« das Gegenteil von »etwas umfahren« sein kann. ;)

von Joachim B. (jar)


Lesenswert?

und warum kein ATmega1284p?

mit 20MHz und 16kB SRAM sollte der doch passen auch 5V und du kennst 
dich mit AVR in ASM besser aus!

von Andreas R. (daybyter)


Lesenswert?

Mir fällt noch ein Cyclone 2 mini dev Board ein. 14 kb Blockram für so 
15,-?

Dafür gab es im forum64 sogar schonmal eine Platine.

Wenn es neuer sein soll, mal nach tang nano 9k suchen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.