#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#include "icon_bmp.h"


#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3c ///< See datasheet for Address; In This Case it is 0x3c
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


// Moving Gear Animation Code use as a loader screen
// OLED Animation: settings
// Code auto-generated by https://wokwi.com/animator, graphics by icons8.com
int frame = 0;
#define FRAME_DELAY (42)
#define FRAME_WIDTH (48)
#define FRAME_HEIGHT (48)
#define FRAME_COUNT (sizeof(frames) / sizeof(frames[0]))
//see icon_bmp.h for arrays
//
const int epd_bitmap_allArray_LEN = 8;
const unsigned char* epd_bitmap_allArray[8] = {
  epd_bitmap_Alt_icon_oled_17x28,
  epd_bitmap_Battery_icon_oled_40x29,
  epd_bitmap_Temp_icon_for_oled_17x28,
  epd_bitmap_visiontech_2,
  epd_bitmap_Battery_empty,
  epd_bitmap_Battery_full,
  epd_bitmap_Battery_low,
  epd_bitmap_Battery_medium
};


  float temp;              // Read Temp. from BMP280
  float alt;               // Read Altitute from BMP280
  float altFt;             // Convert Alt value in Meter to Feet
  const byte batPin = A0;   // Read Battery Voltage
  const byte swPin = 5;     // Push Button Connected
  byte page = 0;            // Default Page Screen
  const byte hiTempAd = 0;  // EEPROM Address to save HIGHEST TEMP
  const byte loTempAd = 4;  // EEPROM Address to save LOWEST TEMP
  const byte hiAltAd = 8;   // EEPROM Address to save HIGHEST ALTITUTE
  float hiTemp;            // EEPROM Variable to save HIGHEST TEMP
  float loTemp;            // EEPROM Variable to save LOWEST TEMP
  float hiAlt;             // EEPROM Variable to save HIGHEST ALTITUTE

void setup() {
  Serial.begin(9600);
  pinMode(swPin, INPUT_PULLUP);
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.drawBitmap(0, 11, epd_bitmap_visiontech_2, 128, 37, 1);
  display.display();// Display VisionTech Logo
  delay(1500);
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(40, 5);
  display.print("MINI");
  display.setCursor(10, 35);
  display.print("ALTIMETER");
  display.display();// Display MINI ALTIMETER
  delay(1500);

  //Only wokwi.com Simulator debuging purpose, Not for Final Code, 
  temp = 30.5;
  alt = 170.4;
  altFt = alt*3.28;
  EEPROM.put(hiTempAd,hiTemp);
  EEPROM.put(loTempAd,loTemp);
  EEPROM.put(hiAltAd,hiAlt);
  // Delete Above six Lines of code before uploading to actual Board

  //Show Movin Gear Animation as a loader screen for 3 Sec
  while (millis()<=6000){
    display.clearDisplay();
  display.drawBitmap(40, 8, frames[frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
  display.display();
  frame = (frame + 1) % FRAME_COUNT;
  delay(FRAME_DELAY);
  }
}
  

void loop() {

   checkSwitchStatus();
   mainPage();                    //by default display mainPage menu

}



void checkSwitchStatus(){

 if (!digitalRead(swPin)){       //When Button is Pressed change screen page 
    page++;
    updatePage();
    delay(1000);
    while (!digitalRead(swPin));
  }
}

void updatePage(){                //Changes screen with each button press

  switch(page){
    case 0:
    page=1;
      break;

    case 1:
    highTempfx();
      break;

    case 2:
    lowTempfx();
      break;

    case 3:
    highAltfx(); 
      break;

    case 4:
    batVoltfx();
    page=0;
      break;

    }
  }

void mainPage(){           // mainPage contains all the structure and act as a loop funtion 

  hiTemp = EEPROM.get(hiTempAd, hiTemp);   //get recorded hihest temp from EEPROM
  loTemp = EEPROM.get(loTempAd, loTemp);  //get recorded lowest temp from EEPROM
  hiAlt = EEPROM.get(hiAltAd, hiAlt);     //get recorded hihest altitute from EEPROM

  if (temp>hiTemp){
  hiTemp = temp;
  EEPROM.put(hiTempAd,hiTemp);
  delay(10);
  }
  if (temp<loTemp){
  loTemp = temp;
  EEPROM.put(loTempAd,loTemp);
  delay(10);
  }
  if (alt>hiAlt){
  hiAlt = alt;
  EEPROM.put(hiAltAd,hiAlt);
  delay(10);
  }

  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.drawBitmap(0, 0, epd_bitmap_Temp_icon_for_oled_17x28, 20, 28, 1);//Thermometer Icon
  display.drawBitmap(0, 35, epd_bitmap_Alt_icon_oled_17x28, 20, 28, 1);//Altitute Icon
  
  display.setCursor(30, 5);
  display.print(temp,1);    //Print current Temp in *C
  display.print(" ");
  display.print((char)247); // degree symbol 
  display.print("C");

  display.setCursor(30, 32);
  display.print(altFt,0);   // Print Current Altitute in Feet
  display.print(" ft");

  display.setCursor(35, 55);
  display.setTextSize(1);
  display.print(alt,1);    // Print Current Altitute in Meter
  display.print(" Mtr");
  display.display();

  delay(50);               // for smooth run in loop
}

void highTempfx(){         // Display HIGHEST Temp Page
  
    display.clearDisplay();
  display.setTextColor(WHITE);
  display.setCursor(15, 5);
  display.setTextSize(2);
  display.println("HIGH TEMP");
  display.setCursor(27, 35);
  display.print(hiTemp,1);
  display.print(" ");
  display.print((char)247); // degree symbol 
  display.print("C");
  display.display();
}

void lowTempfx(){             // Display LOWEST Temp Page
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setCursor(20, 5);
  display.setTextSize(2);
  display.println("LOW TEMP");
  display.setCursor(27, 35);
  display.print(loTemp,1);
  display.print(" ");
  display.print((char)247);       // degree symbol 
  display.print("C");
  display.display();
}

 void highAltfx(){                // Display HIGHEST Altitute Page
  float highalt = alt;
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setCursor(15, 5);
  display.setTextSize(2);
  display.println("HIGH ALT.");
  display.setCursor(5, 32);
  display.print((hiAlt*3.28),1);  //Display HIGHEST Alt in feet
  display.print(" ft");
  display.setTextSize(1);
  display.setCursor(40, 55);
  display.print(hiAlt,1);        //Display HIGHEST Alt in meter
  display.print(" Mtr");
  display.display();
 }

 void batVoltfx(){               // Display Battery Volt and perentage Page
  int x = analogRead(batPin);
  float volt = x * (5.0 / 1023.0);          //Convert analog value to Voltage
  int batPer = map(x,655, 870, 0, 100);    //convert 3.25v to 4.25 volt into 0 to 100%
    
    
    if (batPer >= 10 && batPer <= 25){   // Battery Empty Icon
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.drawBitmap(42, 17, epd_bitmap_Battery_empty, 40, 30, 1);    // Battery Empty Icon
  display.setTextSize(2);
  display.setCursor(42, 50);
  display.print(volt,1);        //Print Voltage
  display.print("v");
  display.setCursor(47, 0);
  display.print(batPer);        //Print Percentage
  display.print("%");
  display.display();

  }
  else if (batPer > 25 && batPer <= 50){     // Battery Low Icon
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.drawBitmap(42, 17, epd_bitmap_Battery_low, 40, 30, 1);    // Battery Low Icon
  display.setTextSize(2);
  display.setCursor(42, 50);
  display.print(volt,1);        //Print Voltage
  display.print("v");
  display.setCursor(47, 0);
  display.print(batPer);        //Print Percentage
  display.print("%");
  display.display();

  } 
  else if (batPer > 50 && batPer <= 75){     // Battery Medium Icon
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.drawBitmap(42, 17, epd_bitmap_Battery_medium, 40, 30, 1);    // Battery Medium Icon
  display.setTextSize(2);
  display.setCursor(42, 50);
  display.print(volt,1);        //Print Voltage
  display.print("v");
  display.setCursor(47, 0);
  display.print(batPer);        //Print Percentage
  display.print("%");
  display.display();

  } 
  else if (batPer > 75 && batPer < 100){                   // Battery Full Icon
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.drawBitmap(42, 17, epd_bitmap_Battery_full, 40, 30, 1);    // Battery Full Icon
  display.setTextSize(2);
  display.setCursor(42, 50);
  display.print(volt,1);        //Print Voltage
  display.print("v");
  display.setCursor(47, 0);
  display.print(batPer);        //Print Percentage
  display.print("%");
  display.display();

  } 
  else if (batPer < 10){      //Below 10% SoC print LOW! with Battery Empty Icon
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.drawBitmap(42, 17, epd_bitmap_Battery_empty, 40, 30, 1);
  display.setTextSize(2);
  display.setCursor(42, 50);
  display.print(volt,1);
  display.print("v");
  display.setCursor(42, 0);
  //display.print(batPer);
  display.print("LOW!");
  display.display();
  
  } else if (batPer >= 100){      //Above 100% Soc Print Charged with Battery Full Icon
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.drawBitmap(42, 17, epd_bitmap_Battery_full, 40, 30, 1);
  display.setTextSize(2);
  display.setCursor(42, 50);
  display.print(volt,1);
  display.print("v");
  display.setCursor(23, 0);
  //display.print(batPer);
  display.print("CHARGED");
  display.display();
  
  }
 }