NikolaiRadke / Nokolino_diy

The small and naughty MP3 monster. DIY version.
http://www.monstermaker.de
Apache License 2.0
19 stars 5 forks source link

Wo wird der EEPROM initialisiert? #2

Closed Brickhub closed 6 years ago

Brickhub commented 6 years ago

Noch sind meine Teile zum Nachbauen nicht angekommen - da habe ich etwas Zeit mir den Code anzuschauen und eventuell etwas daraus zu lernen - wie z.B. die Verwendung des EEPROMs (Den habe ich bisher noch nie benutzt). Wenn ich den Code richtig verstanden habe, sollte doch zu Anfang auf der Adresse 0 eine 2 stehen und auf Adresse 2 eine 0. Wo wird das gesetzt? Wenn der EEPROM initial auf 0 gesetzt wird (Vermutung) dann fehlen doch folgende Zeilen:

// Randomize number generator address=eeprom_read_word(0); // Read EEPROM address if (address == 0) { address = 2; eeprom_write_word(0,2); } seed=eeprom_read_word(address); // Read seed

NikolaiRadke commented 6 years ago

Danke für den Hinweis. Du hast völlig recht, des EEPROM wurde vorher von mir mit einem Hilfsprogramm initialisiert, das habe ich hier vergessen. Nun überlege ich, ob ich Deinen Code einfüge und auf das Tool verzichte. Allerdings gibt es da ein Problem. Zunächst ist das EEPROM von ATMEL-Chip werkseitig mit 255 beschrieben. Ich könne also nach 65535 abfragen. Das geht aber nur, wenn das EEPROM "jungfäulich" ist.

Was meinst Du?

Brickhub commented 6 years ago

Im Prinzip ist es egal bei welcher Adresse man startet, sie sollte halt nur >= 2 sein und darf nicht max_address übersteigen. Mann kann dann auch mit einem alten Datenmüll starten. Ich würde das ganze dann so vorschlagen:

// Randomize number generator address=eeprom_read_word(0); // Read EEPROM address if ((address < 2) || (address > max_address)) { // Hier kommt man nur beim ersten Aufruf hin, wenn die initiale EPROM-Füllung unpassend ist address = 2 eeprom_write_word(0,address); eeprom_write_word(address,0); // Optional, man kann auch mit dem zufälligen Wert im EPROM starten } seed=eeprom_read_word(address); // Read seed if (seed>900) // After 900 write-cyles move to another address { // to keep the EEPROM alive seed = 0; (address>max_address)? address=2:address+=2; eeprom_write_word(0, address); } randomSeed(seed); seed++; eeprom_write_word(address,seed); // Save new seed for next startup

NikolaiRadke commented 6 years ago

Das ist schlau. Die zweite (address>max_address)-Abfrage ist dann überflüssig, am Ende des Zyklus greift dann ja Deine Abfrage.

Danke! Ist eigebaut und sieht jetzt so aus:

// Randomize number generator
  address=eeprom_read_word(0);       // Read EEPROM address
  if ((address < 2) || (address > max_address))             
  {                                  // Initialize EEPROM for first use or after end of cycle
    address = 2;                     // Starting address
    eeprom_write_word(0,address);    // Write starting address
    eeprom_write_word(address,0);    // Write seed 0
  }
  seed=eeprom_read_word(address);    // Read seed
  if (seed>900)                      // After 900 write-cyles move to another address
  {                                  // to keep the EEPROM alive
    seed=0;
    address+=2;
    eeprom_write_word(0,address);
  }
  randomSeed(seed);                  // Randomize
  seed++;                            // New seed
  eeprom_write_word(address,seed);   // Save new seed for next startup
}

Viele Grüße,

Nikolai

NikolaiRadke commented 6 years ago

Dabei habe ich auch gleich max_address angepasst: Der Attiny85 hat 512 Bytes und der ATtiny45 256 Bytes. Bin von der Hälfte ausgegangen.

Brickhub commented 6 years ago

Die zweite (address>max_address)-Abfrage ist dann überflüssig Hmm, ja, das wollte ich zuerst auch vorschlagen. Aber address wird nacht der Erhöhung und vor der nächsten Überprüfung noch einmal verwendet. Es ist unkritisch, wenn max_address+2 immernoch eine gültiege Adresse ist. Das darf man dann nicht vergessen, wenn man mal max_address an andere MCUs anpassen möchte. Deshalb würde ich hier die Abfrage lieber doch beibehalten. Oder man verschiebt den Block mit seed-Erhöhung und Speicherung vor den seed>900 Block (in den dann aber auch ein eeprom_write_word(address,0); eingefügt werden muss, was im Grunde auch wieder eine Code-Verdoppelung bedeuten würde.

Brickhub commented 6 years ago

Oder noch einfacher: Man prüft auf if ((address < 2) || (address > max_address - 3)) Dann darf max_address der größten Adresse entsprechen, was die Definition erklärlicher machen würde. Beim Arduino gibt es da EEPROM.length() in der <EEPROM.h> - geht das auch bei den ATtinys? Dann könnte man die Definition komplett einsparen.

NikolaiRadke commented 6 years ago

Das ist natürlich die eleganteste Lösung! Der Compiler jedenfalls meckert nicht bei EEPROM.length():

// Randomize number generator
  address=eeprom_read_word(0);       // Read EEPROM address
  if ((address<2) || (address>(EEPROM.length()-3)))             
  {                                  // Initialize EEPROM and size for first use or after end of cycle
    address = 2;                     // Starting address
    eeprom_write_word(0,address);    // Write starting address
    eeprom_write_word(address,0);    // Write seed 0
  }
  seed=eeprom_read_word(address);    // Read seed
  if (seed>900)                      // After 900 write-cyles move to another address
  {                                  // to keep the EEPROM alive
    seed=0;
    address+=2;
    eeprom_write_word(0,address);
  }
  randomSeed(seed);                  // Randomize
  seed++;                            // New seed
  eeprom_write_word(address,seed);   // Save new seed for next startup

Danke für Deine Hilfe!

Brickhub commented 6 years ago

Ja, so sieht das super aus.