ESP32 als Modul-Emulator für den C64

Gast #6999994
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
Gast #7000026
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
Gast #7000085
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
Gast #7000105
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
#7000114
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?!
#7000116
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.
Gast #7000144
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.
Gast #7000229
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
Gast #7000299
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.
Gast #7000570
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
#7000586
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).
#7000594
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.
Beitrag #7000668 wurde von einem Moderator gelöscht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren