//============= Deklarasi Library-variabel-konstanta terkait KEYPAD =============
#include <Keypad.h>
const byte baris = 4; //deklarasi jumlah baris pada keypad
const byte kolom = 4; //deklarasi jumlah kolom pada keypad

//deklarasi pemetaan data untuk setiap tombol pada keypad
char hexaKeys[baris][kolom] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte pinBaris[baris] = {2,3,4,5}; //deklarasi pin baris pada keypad
byte pinKolom[kolom] = {6,7,8,9}; //deklarasi pin kolom pada keypad
//inisialisasi objek baru bernama customKeypad
Keypad customKeypad = Keypad(makeKeymap(hexaKeys),pinBaris,pinKolom,baris,kolom); 

//============ Deklarasi Library-variabel-konstanta terkait LCD-I2C =============
#include <LiquidCrystal_I2C.h>   //deklarasi penggunaan library
LiquidCrystal_I2C lcd(0x27,16,2);//deklarasi objek lcd dg almt LCD & kolom-baris
#define Buz 13 //deklarasi Buzzer ke pin 13 pada Arduino
char dataTombol;

//========   Deklarasi Library-variabel-konstanta terkait Library RTC    ========
#include <DS3231.h>
#include <Wire.h>
DS3231 myRTC; //deklarasi nama objek myRTC
int pulHour, satHour, pulMinute, satMinute; //data  entry dari keypad
int second, minute, hour;  //deklarasi variabel detik, menit dan jam
bool CenturyBit = false;   //penanda overflow tahun 2099 ke 2100 tdk digunakan
bool h12Flag; bool pmFlag; //deklarasi variabel boolean utk mode 12h/24h 
//================================================================================
void setup() {
  Wire.begin(); //mengaktifkan protokol Two Wire Interface (TWI) / I2C
  //========================== Setup LCD & Tombol PB =============================
  lcd.init();                    //inisiasi lcd
  lcd.backlight();               //nyalakan lampu backlight
  kataPembukaan();               //tampilkan beberapa kalimat pembukaan
  //=============================== Setup RTC ====================================
  myRTC.setYear(23);             //set tahun = 2023
  myRTC.setMonth(10);            //set bulan = 10 (Oktober)
  myRTC.setDate(22);             //set tanggal = 22
  myRTC.setDoW(3);               //set Date of Weak = 3 
  myRTC.setClockMode(false);     //set mode 24h
} //==============================================================================
void kataPembukaan() {
  lcd.print("  Jam Digital   "); //tampilkan kata pembuka
  lcd.setCursor(0,1);            //pindahkan kursor ke kolom-0 baris-1
  lcd.print("  RTC--DS3231   "); //tampilkan kata pembuka
  delay(2000);
  //-------------------------
  lcd.home();                    //pindahkan kursor ke pojok kiri atas
  lcd.print(" Tekan tombol-A "); //tampilkan kata petunjuk
  lcd.setCursor(0,1);            //pindahkan kursor
  lcd.print("  utk set Jam   "); //tampilkan kata petunjuk
  delay(2000);  lcd.clear();     //menghapus seluruh tulisan
  //-------------------------
  lcd.print(" Tekan tombol-B "); //tampilkan kata petunjuk
  lcd.setCursor(0,1);            //pindahkan kursor ke kolom-0 baris-1
  lcd.print(" utk set Tanggal"); //tampilkan kata petunjuk
  delay(2000);  lcd.clear();     //menghapus seluruh tulisan
  //-------------------------
  lcd.print(" Tekan tombol-C "); //tampilkan kata petunjuk
  lcd.setCursor(0,1);            //pindahkan kursor ke kolom-0 baris-1
  lcd.print(" utk set 12h/24h"); //tampilkan kata petunjuk
  delay(2000);  lcd.clear();     //menghapus seluruh tulisan
} //==============================================================================

void setJam() {  //fungsi untuk setting jam
  lcd.clear();
  lcd.print("Setting Jam : "); //tampilkan kata petunjuk
  lcd.setCursor(0,1);          //pindahkan kursor ke kolom-0 baris-1
  lcd.print("Setting Menit:"); //tampilkan kata petunjuk
  lcd.blink();                 //kursor berkedip
  //-------------------------
  lcd.setCursor(14, 0);        //pindahkan kursor ke kolom-14, baris-0
  tungguKeypad();              //tunggu keypad ditekan, data tersaji pd dataTombol
  if (dataTombol=='*') {goto keluar;}//jika '*' ditekan, exit dari menu setJam
    pulHour=dataTombol-48;     //kurangi 48 d dan salin ke variabel puluhan hour   
    lcd.print(pulHour);        //tulis puluhan jam ke LCD
  tungguKeypad();
    satHour=dataTombol-48;     //kurangi 48 d dan salin ke variabel satuan hour   
    lcd.print(satHour);        //tulis satuan jam ke LCD
  hour = (pulHour*10)+satHour; //gabung pul jam & sat jam mjd satu data desimal
  myRTC.setHour(hour);         //set jam 
  //-------------------------
  lcd.setCursor(14, 1);        //pindahkan kursor ke kolom-14, baris-1
  tungguKeypad();              //tunggu keypad ditekan, data tersaji pd dataTombol
    pulMinute=dataTombol-48;   //kurangi 48 d dan salin ke variabel puluhan Minute
    lcd.print(pulMinute);      //tulis puluhan Minute ke LCD
  tungguKeypad();              //tunggu keypad ditekan, data tersaji pd dataTombol
    satMinute=dataTombol-48;   //kurangi 48 d dan salin ke variabel satuan Minute
    lcd.print(satMinute);      //tulis satuan Minute ke LCD
  minute=(pulMinute*10)+satMinute;//gabung pul menit & sat menit mjd data desimal
  myRTC.setMinute(minute);     //set menit
  myRTC.setSecond(0);          //set detik=00
  //-------------------------
  lcd.noBlink();               //matikan blink
  delay(2000);  lcd.clear();   //hapus seluruh teks pada LCD
  lcd.setCursor(0, 0);         //pindahkan kursor ke kolom-0, baris-0
  lcd.print("Setting selesai"); delay(2000); 
  keluar: lcd.clear();         //label keluar untuk exit dari fungsi setJam()
}

void setTanggal() {
  lcd.clear(); lcd.print("Menu Set Tanggal"); delay(2000); 
  //tulis disini kode program untuk setTanggal
}
void set_AMPM()   { 
  lcd.clear(); lcd.print("Menu Set 12h/24h"); delay(2000); 
  //tulis disini kode program untuk set AM/PM
}

void tungguKeypad() {
  dataTombol = customKeypad.getKey();     //baca data tombol 
    tone(Buz,440); delay(50); noTone(Buz);//bunyikan buzzer pd frekuensi 440Hz
    while (dataTombol == NO_KEY) {        //jika tombol tidak ditekan terbaca NO_KEY
      dataTombol = customKeypad.getKey(); //tunggu disini hingga tombol ditekan
    }   
    tone(Buz,440); delay(30); noTone(Buz);
}

void loop() {
  int DoW;     //variabel lokal utk menyimpan pembacaan DoW dari RTC
  dataTombol = customKeypad.getKey();           //baca data tombol keypad
  switch (dataTombol) {
    case 'A': setJam(); lcd.clear(); break;     //menu setJam
    case 'B': setTanggal(); lcd.clear(); break; //menu setTanggal
    case 'C': set_AMPM(); lcd.clear(); break;   //menu set_AMPM
  }
  //-------------------------
  //membaca data jam, menit, detik dan hari (DoW)
  hour = myRTC.getHour(h12Flag, pmFlag); //baca angka jam dari RTC
  minute = myRTC.getMinute();            //baca angka menit dari RTC
  second = myRTC.getSecond();            //baca angka detik dari RTC
  DoW = myRTC.getDoW();         //baca angka kode nama hari dari RTC
  //-------------------------
  //menulis nama hari dari pembacaan Date of Week (DoW)
  lcd.home();
  switch (DoW) {
    case 1: lcd.print("Senin");  break;
    case 2: lcd.print("Selasa"); break;
    case 3: lcd.print("Rabu");   break;
    case 4: lcd.print("Kamis");  break;
    case 5: lcd.print("Jumat");  break;
    case 6: lcd.print("Sabtu");  break;
    case 7: lcd.print("Minggu"); break; }  
  lcd.print(",");     //tulis koma setelah nama hari
  //-------------------------
  //menulis tanggal DD-MM-YY pd kolom-8 baris-0
  lcd.setCursor(8,0); lcd.print(myRTC.getDate()); lcd.print("-");
  lcd.print(myRTC.getMonth(CenturyBit)); lcd.print("-"); 
  lcd.print(myRTC.getYear()); 
  //menambahkan angka 0 jika angka jam, menit & detik < 2 digit
  lcd.setCursor(0,1);
  if (hour<10)   { lcd.setCursor(0,1); lcd.print("0"); }
  lcd.print(hour); lcd.print(":"); 
  if (minute<10) { lcd.setCursor(3,1); lcd.print("0"); }
  lcd.print(minute); lcd.print(".");
  if (second<10) { lcd.setCursor(6,1); lcd.print("0"); }
  lcd.print(second); 
  lcd.setCursor(9,1); lcd.print("T="); lcd.print(myRTC.getTemperature());
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5