Forum: Mikrocontroller und Digitale Elektronik STM32F1xx: Wie GOL am "Leben" halten?


von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

mit inzwischen über 30 Jahren "Nerd-sein" hängt man sich ja auch ein 
paar bekloppte Sachen  an die Wand. Wer den 70iger Jahre Film "Computer 
Code P1" gesehen hat weiss warum.

Conways Game of Life läuft bei mir auf einer 24x32 Matrix mit 768 LEDs. 
Ebay Kracher mit 7219, wobei der noch ein Reset Problem hatte. Einfach 
an Spannung ist nicht, dann leuchten alle LEDS und nehmen keine Befehle 
an. Die Slew Rate muss größer sein, was ich durch dicke Elkos realisiert 
habe.

Aktuell halte ich das System am Leben indem ich zufällige unsichtbare 
Zelle einstreue, jeweils 2 pro Generation. Dann hört das Ganze nie auf. 
Das führt leider auch zu unschönen Blitzern einzelner Zellen. "Zufall" 
wird durch die 32 Bit RTC erzeugt und gelegentliches srand(GetRTC)

Ich würde noch gern erfassen wann ich eine statische Welt habe die sich 
nicht  mehr ändert. Hat da jemand eine Idee? Statische Welten blinken 
aber durchaus und haben 2 oder mehr Zyklen. Nur #ndern sie sich nicht 
mehr.

Christian

von Arne (Gast)


Lesenswert?

Die einzige Loesung, die mir dazu einfaellt: speicher so viele 
Generationen, wie in den RAM passen, in einem Ringpuffer, und vergleiche 
jede neue Generation mit den alten. Hast du einen Treffer, dann ist es 
zyklisch. Man koennte vielleicht noch einen Hash-Algorithmus einbauen 
und nur die Hashes speichern und vergleichen, dann passen mehr 
Generationen in den RAM. Um aber z.B. einen einzelnen Glider zu erkennen 
(sofern du an den Seiten wrap-around machst) braucht man schon einiges 
an RAM.

von Dirk K. (merciless)


Lesenswert?

Wenn ich GoL implementiert habe, dann habe
ich vor der Berechnung des nächsten Zyklus
den Status von einigen Zellen per Zufall
getoggelt. Wenn dann nach der Berechnung
die aktiven Zellen dargestellt werden,
blitzt da nichts mehr auf.
1
void Step() {
2
  Randomize();
3
  Calculate();
4
  DrawCells();
5
}

Für das Detektieren eines "statischen" Zustandes:
Du könntest die Anzahl der lebenden Zellen zählen.
Diese Anzahl sollte sich dann nicht mehr ändern.

merciless

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

Dirk K. schrieb:
> Für das Detektieren eines "statischen" Zustandes:
> Du könntest die Anzahl der lebenden Zellen zählen.

Das mache ich schon, die ändert sich aber bei manchen Pulsaren. Ich 
erfasse auch die Anzahl veränderter Zellen. Aber so richtig glücklich 
bin ich damit nicht. Das Ding ist nur Demo klar, aber auch die soll 
endlos laufen. Bisher erzeuge ich mit GodMode(x) umso mehr Zellen, je 
weniger es werden. Das erzeugt aber eben leider diese Blitzer eines 
einzelnen Punktes.

Arne schrieb:
> Die einzige Loesung, die mir dazu einfaellt: speicher so viele
> Generationen, wie in den RAM passen, in einem Ringpuffer, und vergleiche
> jede neue Generation mit den alten.

Die Idee ist auch nicht verkehrt. Habe 20kb RAM, wenn ich mit dem 
Bitbanding arbeite (bisher gings auch ohne....) frisst jede Matrix grad 
mal 12x8 = 96 Bytes. Falls überhaupt nötig, da auch 768 Bytes noch fast 
15 Mal rein passen.

von Larry (Gast)


Lesenswert?

Du koenntest einfach den Mittelwert der Stromaufnahme des Displays
messen. Bleibt der ueber einen gewissen Zeitraum konstant,
dann ist das Display entweder leer, oder sind nur noch "Blinker" da.

von foobar (Gast)


Lesenswert?

Anstatt nur einzelne Pixel zu setzen, könntest du auch ab und zu Glider 
von außen reinfliegen lassen oder in einem größeren leeren Block ein 
chaotisches Pattern (z.B. r-Pentomino) entstehen lassen.

von Christian J. (Gast)


Lesenswert?

foobar schrieb:
> Anstatt nur einzelne Pixel zu setzen, könntest du auch ab und zu Glider
> von außen reinfliegen lassen oder in einem größeren leeren Block ein
> chaotisches Pattern (z.B. r-Pentomino) entstehen lassen.

Zusammen mit der Erkennung der statischen Welt oben werde ich das mal 
ins Auge fassen. Ich schiebe ja nur 96 Bytes Bitstream in die Anzeige 
und da lassen sich 5 Streams locker speichern, die sich nicht 
wiederholen dürfen.
Ich hoffe mal, dass eine einfache XOR 32 Bit Quersumme sicher genug ist, 
werden sich schon nicht zwei so ändern, dass die gleich bleibt.

Das mit den Glidern ist schon schwieriger, die müssen ja in allen 4 
Varianten vorliegen damit sie auch alle Richtungen fliegen und an dem 
Feldrand überspringen zur anderen Seite. Außerdem muss es auch dafür 
Regeln geben, denn die sollen ja durch Kollisionen mit den Stillleben 
neue Strukturen erzeugen.

von Harry L. (mysth)


Lesenswert?

Christian J. schrieb:
> Ich hoffe mal, dass eine einfache XOR 32 Bit Quersumme sicher genug ist

Der STM32F1xx kann doch CRC in Hardware.
Ist doch perfekt für den Zweck.

von Christian J. (Gast)


Lesenswert?

Harry L. schrieb:
> Der STM32F1xx kann doch CRC in Hardware.
> Ist doch perfekt für den Zweck.

Wir backen erstmal kleine Brötchen, bevor die Hardwaregeschütze 
aufgefahren werden :-) Erst funktionieren, dann optimieren.
1
/*  -----------------------------------------------------------------------------
2
    Prüft ob, der aktuelle Datenstream schonmal eingespielt wurde in den letzten
3
    5 Perioden.
4
-------------------------------------------------------------------------------- */
5
    uint8_t history[5][DATA_SETS];
6
    uint8_t hPtr = 0;
7
8
static
9
int CheckForPeriod(uint8_t* source, size_t len)
10
{
11
    /* Puffer für 5 Perioden */
12
13
    /* Neuen Datenstrom in freien Bereich einspielen */
14
    for (int i = 0; i < DATA_SETS; i++)
15
        history[hPtr][i] = *(source++);
16
17
    /* Neuen Datenstrom gegen alle anderen vergleichen */
18
    int cmpPtr = (hPtr + 1) % 5;
19
    int check = 1, cnt = 0;
20
    do {
21
        check = memcmp((uint8_t*)&history[hPtr][0],(uint8_t*)&history[cmpPtr][0], len);
22
        cmpPtr = (cmpPtr + 1) % 5;
23
        cnt++;
24
    } while ((check !=0 ) && (cnt < 4));
25
26
    /* Zeiger auf nächste freie Reihe des Ringpuffers */
27
    hPtr = (hPtr + 1) % 5;
28
29
    if (!check)
30
        return 1;
31
32
    return 0;
33
}

von Christian J. (Gast)


Lesenswert?

So gehts schneller... leider werden bestimmte Raumschiffe aber nicht 
erkannt, da sie die Erkennung auf Stillleben nicht erfüllen. Dann segelt 
so eines ununterbrochen durch den Bildschirm.
1
static
2
int CheckForPeriod(uint8_t* source, size_t len)
3
{
4
    /* Puffer für 5 Perioden */
5
    static uint8_t hPtr = 0;
6
    static uint32_t HistoryCRC[5] = {1,2,3,4,5};
7
8
    /* CRC32 Summe bilden für aktuellen Datenstrom */
9
    CRC_ResetDR();
10
    uint32_t crc = CRC_CalcBlockCRC((uint32_t*) source, len/4);
11
    HistoryCRC[hPtr] = crc;
12
13
    /* Neuen Datenstrom gegen alle anderen vergleichen */
14
    int cmpPtr = (hPtr + 1) % 5;
15
16
    int cnt = 0;
17
    while ((HistoryCRC[cmpPtr] != crc ) && (cnt < 4)) {
18
        cmpPtr = (cmpPtr + 1) % 5;
19
        cnt++;
20
    };
21
22
    /* Ringpuffer rotieren */
23
    hPtr = (hPtr + 1) % 5;
24
25
    /* Cnt < 4, dann war Treffer */
26
    return ((cnt < 4) ? true:false);
27
}

von Hans (Gast)


Lesenswert?

Was ist denn das genau?

von Christoph M. (mchris)


Lesenswert?


von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

Hans schrieb:
> Was ist denn das genau?

Naja, wenn ich da so abends aus dem Bett drauf schaue macht es mich auf 
jeden Fall schnell müde, das Gewusel :-) Ein Spielzeug für Nerds, war 
1985 u.a. eine Übungsaufgabe im PASCAL Informatik Kurs auf dem Apple 
IIe.

von Dirk K. (merciless)


Lesenswert?

Rufe mal handofgod() auf, bevor die neue
Generation berechnet wird. Dann sollte da
auch nichts mehr aufblitzen.

merciless

von Christian (Gast)


Lesenswert?

Das ist doch der Fall. Displaymatrix bringt die Anzeige zum Leuchten. 
Dann ist die naexhste Generation schon berechnet worden. Ein bisschen 
Blitzen bleibt immer.

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.