// Eeprom sketch 4: Use an SFBChecksum to automatically initialize 
// missing or invalid EEPROM data.

#define DATA_ADDR 1234
struct MyPersistentData {       // MyPersistentData is the actual data we care about
  u32 aInt;                     //  Whatever you want
  float aFloat;                 //  to save goes in
  u8 aByte;                     //  here..
};
struct MyEepromData {           // but MyEepromData is what we actually store in the EEPROM
  SFBChecksum cs;               // It has a checksum..
  MyPersistentData theData;     // ..as well as the data we care about
};

MyEepromData eepromBuf;         // A place in RAM to hold the data

void checksumData(SFBChecksum cs) {
  SFBChecksumInit(cs);          // Init the checksum we were given, then add
  SFBChecksumAddBytes(cs,       // the MyPersistentData part of eepromBuf to it
                      (char*) &eepromBuf.theData, 
                      sizeof(eepromBuf.theData));
}

void saveData() {                // Here whenever we have new data to write
  checksumData(eepromBuf.cs);    // First, get a valid checksum for the data
  eepromWrite(DATA_ADDR, (u8*) &eepromBuf, sizeof(eepromBuf));  // Then write everything
}

void loadOrInitialize() {
  eepromRead(DATA_ADDR, (u8*) &eepromBuf, sizeof(eepromBuf));   // Load eepromBuf

  SFBChecksum check;            // Scratch checksum
  checksumData(check);          // Compute checksum of existing EEPROM data

  if (!SFBChecksumEqual(check,eepromBuf.cs)) { // If stored CS doesn't match, initialize..
    eepromBuf.theData.aInt = 100;     // Some initial value for aInt
    eepromBuf.theData.aFloat = 1.234; //  ditto
    eepromBuf.theData.aByte = '!';    //  ditto
    saveData();                       // Stash initialized values
  }
}

void setup() { 
  setLogFace(ALL_FACES);              // Send logging everyway
  loadOrInitialize();                 // Go for EEPROM data
}

void loop() { 
  if (buttonDown()) {                 // Report and update values
    logNormal("aInt=%d aFloat=%f aByte=%c\n",  
              eepromBuf.theData.aInt,
              eepromBuf.theData.aFloat,
              eepromBuf.theData.aByte);
    ++eepromBuf.theData.aInt;         // Make some changes 
    eepromBuf.theData.aFloat = eepromBuf.theData.aInt/100.0; // Ditto
    saveData();                       // Update checksum and store         
    while (buttonDown()) delay(1);    // Wait for button up
  }
}
