#include <Arduino.h>
 
const uint32_t NVM_Offset = 0x290000;
uint8_t FLASH_Address = 0;
 
// Define The LED Output GPIO Pin & Button Input GPIO Pin
#define LED_GPIO 5
#define BTN_GPIO 35
 
// Global Variables For Button Reading & Debouncing
int ledState = LOW;
int btnState = LOW;
int lastBtnState = LOW;
int lastDebounceTime = 0;
int debounceDelay = 50;
 
template<typename T>
void FlashWrite(uint32_t address, const T& value) {
  ESP.flashEraseSector((NVM_Offset+address)/4096);
  ESP.flashWrite(NVM_Offset+address, (uint32_t*)&value, sizeof(value));
}
 
template<typename T>
void FlashRead(uint32_t address, T& value) {
  ESP.flashRead(NVM_Offset+address, (uint32_t*)&value, sizeof(value));
}
 
void setup() {
  Serial.begin(115200);
  pinMode(LED_GPIO, OUTPUT);
  pinMode(BTN_GPIO, INPUT);
  FlashRead<int>(FLASH_Address, ledState);
  Serial.println(ledState);
  digitalWrite(LED_GPIO, ledState);
}
 
void loop() {
  int reading = digitalRead(BTN_GPIO);
  if (reading != lastBtnState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != btnState) {
      btnState = reading;
      if (btnState == HIGH) {
        ledState = !ledState;
        digitalWrite(LED_GPIO, ledState);
        FlashWrite<int>(FLASH_Address, ledState);
        Serial.println("State Changed & Saved To FLASH!");
      }
    }
  }
  lastBtnState = reading;
}