InfiniTime.git

ref: 0ce98c7ac7ba66acaf504be9bb042796e12f2733

src/components/settings/Settings.cpp


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
#include "Settings.h"
#include <cstdlib>
#include <cstring>

using namespace Pinetime::Controllers;

struct SettingsHeader {
  uint8_t isActive; // 0xF1 = Block is active, 0xF0 = Block is inactive
  uint16_t version; // Current version, to verify if the saved data is for the current Version
};

#define HEADER_SIZE sizeof(SettingsHeader)

Settings::Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash {spiNorFlash} {
}

void Settings::Init() {

  // Load default settings from Flash
  LoadSettingsFromFlash();
}

void Settings::SaveSettings() {

  // verify if is necessary to save
  if (settingsChanged) {
    SaveSettingsToFlash();
  }
  settingsChanged = false;
}

bool Settings::FindHeader() {
  SettingsHeader settingsHeader;
  uint8_t bufferHead[sizeof(settingsHeader)];

  for (uint8_t block = 0; block < 10; block++) {

    spiNorFlash.Read(settingsBaseAddr + (block * 0x1000), bufferHead, sizeof(settingsHeader));
    std::memcpy(&settingsHeader, bufferHead, sizeof(settingsHeader));
    if (settingsHeader.isActive == 0xF1 && settingsHeader.version == settingsVersion) {
      settingsFlashBlock = block;
      return true;
    }
  }
  return false;
}

void Settings::ReadSettingsData() {
  uint8_t bufferSettings[sizeof(settings)];
  spiNorFlash.Read(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings));
  std::memcpy(&settings, bufferSettings, sizeof(settings));
}

void Settings::EraseBlock() {

  spiNorFlash.SectorErase(settingsBaseAddr + (settingsFlashBlock * 0x1000));
}

void Settings::SetHeader(bool state) {
  SettingsHeader settingsHeader;
  uint8_t bufferHead[sizeof(settingsHeader)];
  settingsHeader.isActive = state ? 0xF1 : 0xF0;
  settingsHeader.version = settingsVersion;

  std::memcpy(bufferHead, &settingsHeader, sizeof(settingsHeader));
  spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000), bufferHead, sizeof(settingsHeader));
}

void Settings::SaveSettingsData() {
  uint8_t bufferSettings[sizeof(settings)];
  std::memcpy(bufferSettings, &settings, sizeof(settings));
  spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings));
}

void Settings::LoadSettingsFromFlash() {

  if (settingsFlashBlock == 99) {
    // Find current Block, if can't find use default settings and set block to 0 ans save !
    if (FindHeader()) {
      ReadSettingsData();
    } else {
      SaveSettingsToFlash();
    }
  } else {
    // Read Settings from flash...
    // never used :)
    ReadSettingsData();
  }
}

void Settings::SaveSettingsToFlash() {

  // calculate where to save...
  // mark current to inactive
  // erase the new location and save
  // set settingsFlashBlock

  // if first time hever, only saves to block 0 and set settingsFlashBlock

  if (settingsFlashBlock != 99) {
    SetHeader(false);
  }

  settingsFlashBlock++;
  if (settingsFlashBlock > 9)
    settingsFlashBlock = 0;

  EraseBlock();
  SetHeader(true);
  SaveSettingsData();
}