Hello, Guest the thread was viewed3.6k times and contains 36 replies

last post from dmantione at the

Uridium-Modul mit speicherbaren Hiscores

  • Moin,


    wird langsam mal Zeit für ein Update. Liegt ja nun schon alles ein paar Wochen hier rum.


    Zu allererst möchte ich mich für meine Dummheit in Post #6 entschuldigen. Die Read Access Time stimmt zwar, aber da habe ich die Rechnung ohne PLA und Co. gemacht. Dann sieht das nämlich alles schon ganz anders aus. Nämlich viel schlechter! Die notwendige Bedingung PHI2 == 1 && IO1 == 0 sind der Killer. Was für 'n mieser Fehler meinerseits.


    OK, also war dem Ganzen als reine Softwarelösung nicht beizukommen. Die paar konfigurierbaren Look-Up Tables im AVR Dx haben mich nicht weitergebracht. Zu viele Einschränkungen und Verlust dringend benötigter IO Pins. Übrigens ist dieses CCL (Configurable Custom Logic) Feature kein neues, exclusives Feature der AVR Dx, ich kannte es lediglich nicht von den älteren Bausteinen. Wie auch, nie was mit den Teilen gebaut. Mein letztes Microcontroller Projekt war ein 8051 basierter GameBoy Kopierer. Das war irgendwann in den 90ern. Neueinstieg dann vor ca. einem Jahr mit dem Pi Pico.


    Zurück zum Thema: Was in Software zu langsam ist, macht man halt in Hardware. Ich hatte da 'ne komische Idee. Ich verknote die Kontrollsignale derart, dass das Ergebnis mir direkt das High-Byte des Pointers des entsprechenden Handlers liefert. Mal schauen...


    Um diesen Decoder zu bauen benötigte ich jeweils einen 74HCT04, HCT08 & HCT32, also INV, AND & OR Gates. Die in der Tabelle angegebenen x3..0 gehen direkt auf den PORTC des AVR. Günstigerweise hat der nur 4bit und die MSBs werden immer als 0 gelesen. Die letzte Spalte zeigt die sich ergebenen Startadressen der Handler. $0000 ist tabu, da das der Reset-Vektor ist und tatsächlich ist auch minimales Setup notwendig.


    Der Idle-Handler sieht dann so aus:

    Code
    1. .org 256
    2. in ZH,VPORTC_IN
    3. ijmp

    Das sind dann 1 + 2 Takte. Daraus ergibt sich eine Latency von 3..5 Takten.


    Der Handler fürs Schreiben des Magic Desk Registers sieht so aus:

    Code
    1. .org 512
    2. in r_magic,VPORTA_IN
    3. lsl r_magic
    4. out VPORTD_OUT,r_magic
    5. in ZH,VPORTC_IN
    6. ijmp

    Der Datenbus des Cartridge ist an PORTA angeschlossen, die Address-MSBs & EXROM, also das, was beim Magic Desk aus dem Register kommt, an PORTD. Der ist nur von [7:1] ausgeführt, daher der lsl. Wichtig ist halt sofort den Datenbus zu sichern, der Rest ist unkritisch fürs Timing. Also kommt zu den Takten für den Idle Handler ein weiterer bei einem Write Handler hinzu. Macht also: 4..6 Takte.


    Und jetzt kommt der kritische Read Handler, Beispiel "Flash Ctrl & LED":

    Code
    1. .org 1536
    2. out VPORTA_DIR,r_c_ff ; set data port to ouput
    3. out VPORTA_OUT,r_led ; apply data to port
    4. flr_loop:
    5. in r_func, VPORTC_IN
    6. cpi r_func, $01 ; wait until function switches to idle
    7. brne flr_loop
    8. out VPORTA_DIR,r_c_00 ; set data port to input
    9. in ZH,VPORTC_IN
    10. ijmp

    Wir schalten also den Datenbus auf treibend, legen den Wet des Registers an, warten darauf, das der Decoder sagt wir sind wieder "idle" und schalten dann den Datenport wieder auf Eingang. Die Loop hatte ich erstmal so gebaut, einige NOPs wären vermutlich ausreichend, bzw. sogar genauer. Bis wir die Daten anlegen kommen also 2 weitere Takte hinzu. Macht fürs Lesen 5..7 Takte.


    Auf alles kommen noch 2 Takte für die Synchronisation von PORTC hinzu. Damit intern auch alles schön ist und keine Metastabilitäten an den Registern auftreten. Also:


    Schreiben: 6..8 Takte

    Lesen: 7..9 Takte


    Wir haben eine 24MHz Clock die auch noch ein wenig Abweichung haben kann, sagen wir mal das macht eine Cycle-Time von 42ns. Über das CLKCTRL_OSCHFTUNE Register können wir den Oscillator insgesamt um nochmal ca. 12% schneller machen. Dann landen wir rechnerisch bei 26,88 MHz also ca. 37ns


    Daraus folgt:


    Schreiben: 222..296ns Delay

    Lesen: 259..333ns Delay


    Da kommt noch ein bisschen was hinzu, denn der Decoder braucht auch noch etwas Zeit aber OK.. soweit die Theorie.


    Aber jetzt erstmal was anderes. Im ersten Post habe ich ja von einem Testadapter gesprochen. Den hatte ich mir dann ungefähr so vorgestellt:



    Pi Pico, Levelshifter für den Datenbus, fertig. Bevor ich mit dem Fädeln angefangen habe dann glücklicherweise doch mal in die Datenblätter geschaut. Was? Weder der AVR im 5V Betrieb noch das Flash sind 3,3V tollerant! Oh nein! Da ich dann keine Lust hatte noch weitere 2 oder 3 Levelshifter zu verfädeln habe ich mich kurzerhand entschlossen die Beardboards rauszukramen und dort dann alles zu verstöpseln:



    Kann man da überhaupt was erkennen? Mitte links die drei Logikbausteine, dann der AVR und rechts das unverkabelte Flash. Es war halt noch nicht so weit. OK.. zum Testen wird es reichen. Kleines Testprogramm in MicroPython geschrieben und die komische Idee "Ich lege das High-Byte des Pointers auf 'n Port und springe direkt dahin" hat tatsächlich funktioniert! Ultrakrass! Aus der Firma 'n Oszi ausgeliehen und bisschen gemessen. Worst-Case-Latency beim Lesen 356ns. Das passt ziemlich gut mit dem theoretischen Wert überein. Ich war zufrieden. Noch. Dann habe ich am 64er die Latency von PHI2 rising zu IO1 falling gemessen. Wa? Tatsächlich um die 80ns? Im Ernst? Pfff...


    Im 6510 Datenblatt ist PHI2 mit min. 420ns und max. 510 angegeben, bei 1MHz. Wir sind etwas langsamer Rechnen wir einfach mal mit 460ns. Abzüglich der 80ns IO1 Delay bleiben 380ns. Also um und bei 20ns (380-356) Setup-Time. Das wird nicht reichen. Ich vermute damit landen wir stark in der geht/geht-nicht Zone und das möchte ja nun wirklich niemand.


    Fazit: Ich glaube ich suche mir einen anderen Weg. Letztendlich sind mir 4 ICs (Decoder + AVR) auch zuviel für das Vorhaben. Vielleicht kann sich jemand von den 64er Gurus dazu äussern. Es gibt doch sicherlich Erfahrungswerte bezgl. Setup-Time. Bitte entsprechende Kollegen evtl. auf diesen Beitrag stubsen. Ich bin noch nicht sooo lange dabei, könnte mir aber vorstellen, dass skoe & kinzi evtl. etwas dazu sagen können.


    Einen anderen Weg habe ich, glaube ich, schon gefunden. GMod2.. gibt es ja auch erst ein paar Jahre und keiner von Euch hat bescheid gesagt! :D


    Respekt an alle, die bis hierhin gelesen haben!


    Euer,

    l-z-o

  • Alter !

    Was für ein Aufwand 🙈

    Vlt. sollte ich mich doch einfach mal hinsetzen und das Math64 Modul bisl umbasteln 🙂

    Aktull ists ein 32K Modul + 8K RAM.

    Sollte klappen daraus 64K + 8K RAM zu machen.

    Problem ist nur, dass die Highscore Daten im Bereich $8000 - $A000 liegen müssen.

    Ggf. müsste ich das Spiel versuchen zu patchen.

  • Ja.. eigentlich war der Drops schon gelutscht als klar war, dass es ohne zusätzliche Hardware nicht geht. Ich wollte aber unbedingt wissen, ob die Geschichte mit dem Decoder funktioniert.


    Jetzt bestelle ich erstmal und bau 'n Gmod2 Modul. Das ist übersichtlich. 1x HCT139, 1x HCT273, 1x MIcrowire EEPROM mit 2kByte. Passt in ein TFW8b Stumpy-Case und Code-Beispiele gibt es bei icomp. Das Case ist mir halt wichtig, weil da habe ich noch 'n paar von. :D


    Bis dahin versuch ich mal 'ne EasyFlash Version von Uridium hinzubekommen.


    Was mir noch einfällt. Ich hatte letztens in einem Post eine Expansionport Prototypen Karte gesehen an die draussen ein grosses Breadboard gesteckt war. Ich finde das nicht mehr! Das war aber hier im Forum. Jemand eine Ahnung?

  • Moin!


    tl;dr - löppt - zumindest im VICE


    Nach meinem letzten Post hat sich ein lieber Forenkollege bei mir gemeldet und mir seinen nicht aufgebauten GMod2-Bausatz von dmantione angeboten. Hab ich gerne angenommen, nur musste zuerst mal Uridium entsprechend angepasst werden. Das hab ich dann auch iwie hinbekommen (siehe Anhänge) :D


    uridium-gmod2.crt  uridium-gmod2-eeprom.bin


    Gestartet wird das so:

    Code
    1. x64sc -cartcrt uridium-gmod2.crt -gmod2eepromrw -gmod2eepromimage uridium-gmod2-eeprom.bin


    Das .crt ist etwas länger, da ich es mit dem Protovision cartconv erstellt habe. Das hängt halt das EEPROM hinten mit dran. Das scheint VICE aber gekonnt zu ignorieren oder ich kann es nicht bedienen. Die Wahrscheinlichkeit ist groß.


    Bitte als Pre-Release ansehen. Die Grundfunktionalität, also EEPROM lesen & schreiben, ist vorhanden. Es fehlt allerdings eine Initialisierungs/Rücksetzfunktion, ein Plausibilitätscheck mit automatischem Initialisieren, ein Menu, Sicherung auf Floppy etc.


    Ahso.. ggf. auf die richtigen Knöpfe in der GMod2 Maske von Vice achten.



    Vielleicht schaffe ich am Wochenende den Bausatz zusammen zu löten und das Spiel auf real HW zu testen. Ausserdem habe ich jetzt natürlich den Wunsch die 512KByte vom Modul voll zu kriegen und ein ensprechendes Multi-Cartridge-Image zu basteln.


    Ich geh erstmal mit der Hündin, bis dann,

    l-z-o

  • Das SwinSID übertaktet den Atmega auf 32MHz und trotzdem ist es unmöglich, vom SID zu lesen, einer der Gründe, warum das SwinSID kein POTX/POTY kann. Vielleicht in der Zukunft mit einem modifizierten Design.


    Es überrascht mich also nicht, dass dies mit dem Mikrocontroller nicht möglich ist. Man kann natürlich auch einen sehr schnellen Mikrocontroller verwenden, z. B. den STM32F405 im Kung Fu Flash. Das Problem bleibt, dass es unmöglich ist, den Bus so zu benutzen, wie er sein sollte, man benutzt IO1 für das Timing, während der 6510 den Bus an PHI2 liest. Der KFF ist daher z.B. nicht mit dem Mega65 kompatibel, und auch mit dem C128 kann es wegen der unterschiedlichen PLA-geschwindigkeit Probleme geben.


    Mikrocontroller haben ihre Berechtigung, aber es gibt meiner Meinung nach noch keine Alternative zu echten hardwarebasierten Cartridges, und da ein Spielmodul mit alle C64-hardware kompatibel sein muss, ist echte Hardware meiner Meinung nach notwendig für ein Spielcartridge.

  • Von meiner Seite aus war es ein Versuch mit möglichst wenig Bauteilen ein Modul mit Hi-Score Speicher Option zu bauen. Ist ja schon daran gescheitert, dass ich dann noch externe Gatter hinzufügen musste. Hatte vorher auch schon über reine HW Lösungen nachgedacht, dabei aber immer ein I2C EEPROM im Hinterkopf und kein Microwire. Eine Lösung mit kleinem CPLD wäre auch gut möglich gewesen, hätte ich vielleicht gemacht, wenn ich dann nicht auf GMod2 gestossen wäre.


    Hätte ich GMod2 gekannt oder eher gefunden, hätte ich es auch gleich verwendet, weil es nämlich genau, exakt, perfekt das ist, was ich haben möchte.


    Hätte, hätte, Fahrradkette... :D


    Man kann es sogar vom C64/128 aus programmieren! Bräuchte ich nicht unbedingt, finde das aber trotzdem witzig und ist natürlich praktisch für grössere Spielstände oder ähnliches. Macht bestimmt Spass damit rum zu spielen. Freue ich mich schon drauf.


    Könnte mir auch vorstellen ein Re-Design vom PCB zu machen. Evtl. mit SMD Logik und DIL Flash oder Eprom für ein "Modul besonderer Bauart".


    Jedenfalls, vielen Dank dmantione für dein GMod2 Design! Stammt die Idee eigentlich von dir oder hast du das icomp Design aufgegriffen und verbessert?

  • Individual Computers gebührt die meiste Anerkennung für das Design des Gmod2, aber ich probiere niemals ein Design 1-zu-1 kopieren. Für die DIY-version wollte ich THT-komponenten, aber die 74HC1G125, die IComps Cartridge verwendet, ist nicht in THT verfügbar. Die Verwendung eines 74HC125 mit nur einem der 4 Ports genutzt erschien mir nicht sehr elegant, also entwarf ich eine Schaltung mit einem Transistor, um das EEPROM mit dem C64-Bus zu verbinden. Außerdem kann meine Cartridge von den meisten C64-hauptplatinen aus programmiert werden, während die von IComp nur auf einem Assy 250469 programmiert werden kann. Auch mein Flashprogramm ist komplett selbst entworfen und was ich gehört habe, kann es mehr als das von IComp.

  • Das Problem bleibt, dass es unmöglich ist, den Bus so zu benutzen, wie er sein sollte, man benutzt IO1 für das Timing, während der 6510 den Bus an PHI2 liest.

    Ich erwähne gerne an dieser Stelle nochmal den RP2040 bzw. RP2350, mit dessen Leistung und DMA und PIOs ist Timing in den hier nötigen Größenordnungen durchaus möglich, und günstig ist das Ding auch noch.

  • Ich erwähne gerne an dieser Stelle nochmal den RP2040 bzw. RP2350, mit dessen Leistung und DMA und PIOs ist Timing in den hier nötigen Größenordnungen durchaus möglich, und günstig ist das Ding auch noch.

    Ich mag den Pi Pico auch gerne. Es kommt halt immer auf die Anwendung an. GMod2 funktioniert mit ein paar Bauteilen und ohne extra Firmware. Finde ich für diese Aufgabe attraktiver. Mit dem AVR wäre es für mich OK gewesen aber für 'n RP2040 braucht man noch Spannungsregler, Pegelwandler, Oszillator? QFN löten ist auch nicht jedermanns Sache. Selbst bei Verwendung eines kleinen Boards werden noch Pegelwandler benötigt. Wäre mir zu aufwendig gewesen. Preis ist für mich hier nebensächlich.

  • GMod2-Modul gelötet!



    Flashsoftware war auf dem Flash selbst drauf, sehr praktisch! :)

    Etwas Verwirrung beim ersten Flashvorgang. Das ging so schnell!


    dmantione : In der Funktion flash_detect() wird flashseccnt nicht auf seccnt[flashidx] gesetzt und daher immer der Defaultwert von 8 ausgegeben.


    Bin daher von einer Sektorgrösse von 64k ausgegangen (Size-Angabe elegant ignoriert) und habe nur einen Sektor programmiert. War 'n bisschen wenig. :D


    Nachdem ich dann ausreichend 4k-grosse Sektoren geschrieben hatte lief auch alles auf Anhieb. Die Flashsoftware gefällt mir sehr gut!


    Was mir weniger gefällt:

    • Das PCB hat keine Aussparungen für zusätzlichen halt an den "Zapfen" des TFW8b Stumpy-Cases. OK, dafür passt es auch in andere Modulgehäuse. Bin ja schon froh, dass es überhaupt in ein Stumpy-Case passt.
    • Leider kein ENIG :(

    Netter Nebeneffekt: Da man zum Patchen des Spiels erstmal die De-Cruncher los werden muss, startet das Spiel entsprechend schnell. Das Video ist trotzdem zu gross für 'nen Upload.


    Damit ist dann das Projekt "Uridium-Modul mit speicherbaren Hiscores" bis auf einige Komfortfunktionen in der Software prinzipiell abgeschlossen. Momentan sitze ich an "Krakout" und habe mich dort schon der De-Cruncher entledigt. Anschliessend mache ich mir vielleicht Gedanken, wie man am Elegantesten Multi-Game-GMod2-Cartridges baut, die man dann auch nach belieben zusammenstellen kann. Vielleicht. ;)


    Vielen Dank nochmals an Panther & dmantione :thumbup:

  • Selbst bei Verwendung eines kleinen Boards werden noch Pegelwandler benötigt.

    Beim RP2040 sind die (meisten) Pins inoffiziell 5V-tolerant und beim RP2350 offiziell. Selbst bei Bus Contention sollte nichts passieren, soweit ich das sehe, weil dann entweder die Pads des RP in die Strombegrenzung gehen oder die NMOS-Highside dicht macht. Gibt einige Leute, die die 2040 ohne Pegelwandler verbaut haben, bisher ohne irgendwelche Problemmeldungen.

  • Ah, danke, ich werde das überprüfen.

    Was mir weniger gefällt:

    • Das PCB hat keine Aussparungen für zusätzlichen halt an den "Zapfen" des TFW8b Stumpy-Cases. OK, dafür passt es auch in andere Modulgehäuse. Bin ja schon froh, dass es überhaupt in ein Stumpy-Case passt.
    • Leider kein ENIG :(

    Ich habe gestern Abend eine Bestellung für einen Gmod2 mit ENIG erhalten. Ich weiß nicht, ob du das warst, aber so habe ich auch Platinen mit ENIG. Ich habe auch die Platine 0,5 mm breiter gemacht, so dass die es besser in den Stumpy-gehäuse klammt, dass deiner erster Kommentar denke ich löst. Die ENIG-Platinen haben bereits diese neue Breite, die Nicht-ENIG-Platinen werden sie auch bekommen, sobald ich eine neue Charge bestelle.


    Meiner Meinung nach sollte Gmod2 von mehr Entwicklern in Betracht gezogen werden. In vielerlei Hinsicht ist das Gmod2 einfach ein besseres Modul als das EasyFlash. Deshalb finde ich es toll, dass du dieses Spiel auf Gmod2 übertragt hat. :)

  • dmantione : In der Funktion flash_detect() wird flashseccnt nicht auf seccnt[flashidx] gesetzt und daher immer der Defaultwert von 8 ausgegeben.

    Handelt es sich um dieselbe Version des Quellcodes? Ich glaube mich zu erinnern, dass ich in der Vergangenheit eine Änderung daran vorgenommen habe. (Die Version auf meiner Webseite ist aktuell.)


    Auf jedem fall, in der aktuellen Version enthält flash_detect den folgenden Code:

    Code
    1.    if (flashseccnt!=seccnt[flashidx]) {      
    2. flashseccnt=seccnt[flashidx];                                                                                      
    3.      strout("seca=0 secz=");                                                                      
    4.      seca=0;
    5.      secz=flashseccnt-1;
    6.    }
  • Ich habe gestern Abend eine Bestellung für einen Gmod2 mit ENIG erhalten. Ich weiß nicht, ob du das warst, aber so habe ich auch Platinen mit ENIG. Ich habe auch die Platine 0,5 mm breiter gemacht, so dass die es besser in den Stumpy-gehäuse klammt, dass deiner erster Kommentar denke ich löst. Die ENIG-Platinen haben bereits diese neue Breite, die Nicht-ENIG-Platinen werden sie auch bekommen, sobald ich eine neue Charge bestelle.


    Meiner Meinung nach sollte Gmod2 von mehr Entwicklern in Betracht gezogen werden. In vielerlei Hinsicht ist das Gmod2 einfach ein besseres Modul als das EasyFlash. Deshalb finde ich es toll, dass du dieses Spiel auf Gmod2 übertragt hat. :)

    Oh, ENIG ist verfügbar und etwas breiter. Sehr gut! 8o


    Das EEPROM beim GMod2 ist halt einfacher zu handhaben als Flash.


    Bei Flash teilt man idealerweise einen Sektor in X Spielstände- / Hiscoretabellen-Records auf. Bei einem Update markiert man den aktuellen Eintrag als ungültig, setzt also ein Flag auf 0, und schreibt den neuen Eintrag dahinter. Dann muss man nicht bei jedem Update den Sektor erst löschen und "belastet" immer die gleichen Speicherstellen mit Löschvorgängen. So in der Art würde ich es zumindest machen. Ach, ich habe gerade auf deiner Website gelesen, dass du das ganz genau so siehst. ;)


    Für das Meiste reicht GMod2 völlig aus, EasyFlash ist (oder war) halt sehr populär und hat auch seine Vorzüge. (Ein EasyFlash 1CR brauche ich auch noch unbedingt).


    Auf jedem fall, in der aktuellen Version enthält flash_detect den folgenden Code:

    Code
    1.    if (flashseccnt!=seccnt[flashidx]) {      
    2. flashseccnt=seccnt[flashidx];                                                                                      
    3.      strout("seca=0 secz=");                                                                      
    4.      seca=0;
    5.      secz=flashseccnt-1;
    6.    }

    Ich meinte die Stelle ein paar Zeilen dadrüber. Zeile 711 & 712:

    Code
    1. strout("Sector cnt: ");
    2. numout(flashseccnt);

    Zu dem Zeitpunkt ist flashseccnt noch nicht aktualisiert. ;)