#define e_lcd  0x27 // endereço do display.
#define e_reles  0x20 // endereço do PCF8574.
#define PCF8574_INITIAL_VALUE  0b00000000 // 76543210 = 0b00000000 ... 0b11111111 -> 0 ... 255
#define sdcard_pin 15
#define bdir_pin 4
#define boka_pin 16
#define besq_pin 17
//#define clk_t 8 // clock tela
//#define cs_t  7 // chip select tela
//#define mosi_t  11 // r/w tela
#define vrefcorr 1126400L // 1081344L = 1.056*1024*1000

#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <PCF8574.h>
#include <RTClib.h>
#include <SdFat.h>

LiquidCrystal_I2C lcd(e_lcd, 16, 2);
PCF8574 reles(e_reles);
RTC_DS1307 rtc;
SdFat32 sd;
File32 file;
char txt[16];

//U8G2_ST7920_128X64_1_SW_SPI u8g2(U8G2_R0, /* clock=*/ clk_t, /* data=*/ mosi_t, /* CS=*/ cs_t, /* reset=*/ U8X8_PIN_NONE); // fake (software) spi
//U8G2_ST7920_128X64_1_HW_SPI u8g2(U8G2_R0, /* CS=*/ cs_t, /* reset=*/ U8X8_PIN_NONE); // spi
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0); // SSD1306 i2c

int analogPin = A7;

unsigned long t = 0;
unsigned long lt = 0;
float val = 0;
int tick = 62;
int xs[62];
int res = 125 / tick;
int xc = 0;
int o_xc = 0;
int avg_sample = 10;
int adelay = 0;
int ddelay = 0;
byte bs = 0b00000000;
int bt = 0;
uint8_t draw_state = 0;
DateTime now;
DateTime ini;

void u8g2_prepare(void) {
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.setFontRefHeightExtendedText();
  u8g2.setDrawColor(1);
  u8g2.setFontPosTop();
  u8g2.setFontDirection(0);
  u8g2.drawFrame(0, 0, u8g2.getDisplayWidth(), u8g2.getDisplayHeight() );
  u8g2.drawStr( 2, 1, "Graf Analog");
  int maxv = map(661, 0, 1023, 10, 60);
  u8g2.drawLine(2, 10, 2, 61);
  u8g2.drawLine(2, 61, 125, 61);
  u8g2.drawLine(2, 70 - maxv, 125, 70 - maxv);
}

void u8g2_line(uint8_t a) {
  for (int i = 1; i < a; i = i + 1) {
    int x0 = map(xs[i], 0, 1023, 10, 60);
    int x1 = map(xs[i - 1], 0, 1023, 10, 60);
    u8g2.drawLine((tick - a + i)*res, (70 - x0), (tick - a - 1 + i)*res, (70 - x1));
  }

}

void draw(void) {
  u8g2_prepare();
  u8g2_line(draw_state);
}


long rA(int pin) {
   return analogRead(pin);
}

void checkb() { // controle de botoes bits 2 - esquerda / 1 - ok / 0 - direita; bt = tempo de aperto (max 10 seg = 100)
  byte a = 0b00000000;
  byte b = 0b00000000;
  byte c = 0b00000000;

  if (digitalRead(besq_pin) == LOW) {
    a = 0b00000100;
  } else {
    a = 0b00000000;
  }
  if (digitalRead(boka_pin) == LOW) {
    b = 0b00000010;
  } else {
    b = 0b00000000;
  }
  if (digitalRead(bdir_pin) == LOW) {
    c = 0b00000001;
  } else {
    c = 0b00000000;
  }
  byte bm = a | b | c;
  if (bs == bm) {
    if (bt < 100) {
      bt++;
    }
  } else {

    bt = 0;
  }
  bs = bm;
}

void setup(void) {
  //Iniciar Display Menu
  lcd.init();
  Wire.beginTransmission(e_lcd);
  if (Wire.endTransmission() != 0) {
    pinMode(LED_BUILTIN, OUTPUT);
    while (1) {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(200);
      digitalWrite(LED_BUILTIN, LOW);
      delay(200);
    }
  }
  lcd.clear();
  lcd.setBacklight(HIGH);
  lcd.setCursor(0, 0);
  lcd.print("   e-PAC v1.0   ");
  //Iniciar 8-Reles (PCF8574)
  lcd.setCursor(0, 1);
  lcd.print("    8-Reles?    ");
  reles.begin();
  delay(200);
  if (!reles.isConnected()) {
    lcd.setCursor(0, 1);
    lcd.print("    8-Reles#    ");
    pinMode(LED_BUILTIN, OUTPUT);
    while (1) {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(200);
      digitalWrite(LED_BUILTIN, LOW);
      delay(200);
    }
  } else {
    lcd.setCursor(0, 1);
    lcd.print("    8-Reles!    ");
    delay(200);
  }
  //Iniciar Display GFX
  lcd.setCursor(0, 1);
  lcd.print("      GFX?      ");
  u8g2.begin();
  delay(200);
  Wire.beginTransmission(0x3c);
  if (Wire.endTransmission() != 0) {
    lcd.setCursor(0, 1);
    lcd.print("      GFX#      ");
    pinMode(LED_BUILTIN, OUTPUT);
    while (1) {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(200);
      digitalWrite(LED_BUILTIN, LOW);
      delay(200);
    }
  } else {
    lcd.setCursor(0, 1);
    lcd.print("      GFX!      ");
    delay(200);
  }
  //Iniciar Relogio
  lcd.setCursor(0, 1);
  lcd.print("      RTC?      ");
  bool clockf = rtc.begin();
  delay(200);
  if (!clockf) {
    lcd.setCursor(0, 1);
    lcd.print("      RTC#      ");
    pinMode(LED_BUILTIN, OUTPUT);
    while (1) {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(200);
      digitalWrite(LED_BUILTIN, LOW);
      delay(200);
    }
  } else {
    lcd.setCursor(0, 1);
    if (! rtc.isrunning()) {
      rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //CAPTURA A DATA E HORA EM QUE O SKETCH É COMPILADO
      //rtc.adjust(DateTime(2018, 7, 5, 15, 33, 15)); //(ANO), (MÊS), (DIA), (HORA), (MINUTOS), (SEGUNDOS)
      lcd.print("Data/hora ajust");
      delay(2000);
    }
    lcd.setCursor(0, 1);
    now = rtc.now();
    sprintf(txt,"%02d/%02d/%04d %02d:%02d", now.day(), now.month(),now.year(),now.hour(),now.minute());
    lcd.print(txt);
    delay(5000);
    lcd.setCursor(0, 1);
    lcd.print("      RTC!      ");
    delay(200);
  }
  //Iniciar SDcard
  lcd.setCursor(0, 1);
  lcd.print("    SD-card?    ");
  bool sdf = sd.begin(sdcard_pin, SD_SCK_MHZ(4));
  delay(200);
  if (!sdf) {
    lcd.setCursor(0, 1);
    if (sd.card()->errorCode()) {
      lcd.print("    SD-card#: FI");
    } else if (sd.vol()->fatType() == 0) {
      lcd.print("    SD-card#: SC");
    } else {
      lcd.print("    SD-card#: ??");
    }
    pinMode(LED_BUILTIN, OUTPUT);
    while (1) {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(200);
      digitalWrite(LED_BUILTIN, LOW);
      delay(200);
    }
  } else {
    lcd.setCursor(0, 1);
    lcd.print("    SD-card!    ");
    delay(200);
  }/**/
  pinMode(bdir_pin, INPUT_PULLUP);
  pinMode(besq_pin, INPUT_PULLUP);
  pinMode(boka_pin, INPUT_PULLUP);
  memset(xs, 0, sizeof(tick));
  lcd.setCursor(0, 1);
  lcd.print("  Tudo Pronto!  ");
  delay(1000);
  lcd.clear();
  t = millis();
  ini = rtc.now();
}

void loop(void) {
  now = rtc.now();
  t = millis();
  if (ddelay < 5) {
    ddelay++;
  } else {
    ddelay = 0;
    // picture loop
    u8g2.firstPage();
    do {
      draw();
    } while ( u8g2.nextPage() );

    draw_state++;
    // delay between each page
    lcd.setCursor(0, 0); // Coloca o cursor do display na coluna 1 e linha 1
    lcd.print("Menu");
    lcd.setCursor(5, 0);
    lcd.print(now.unixtime()-ini.unixtime());
    lcd.setCursor(0, 1);
    lcd.print("Val:");
    lcd.setCursor(5, 1);
    lcd.print(val * 5.0 / 1024);
    lcd.setCursor(10, 1);
    lcd.print(bt);
    lcd.setCursor(15, 1);
    lcd.print(int(bs));

    reles.write8(t % 256);
  }

  //is it time check the switches ?
  if (t - lt >= 50)
  {
    //restart the TIMER
    lt = t;

    checkb();
  }

  if (adelay < 5) {
    adelay++;
  } else {
    adelay = 0;
    val = rA(analogPin);
    xs[draw_state] = val;
    if ( draw_state >= tick - 1 ) {
      draw_state = 0;
      memset(xs, 0, sizeof(tick));
      lcd.clear();
    }
  }


}
PCF8574Breakout
GND5VSDASCLSQWRTCDS1307+