//======================== Sub-Program "CustomKeypad" ===========================
//============= Deklarasi Library-variabel-konstanta terkait KEYPAD =============
#include <Keypad.h>
const byte baris = 4; //deklarasi jumlah baris pada keypad
const byte kolom = 4; //fdeklarasi 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); 

//============================ Sub-Program "MENU " ==============================
//============ Deklarasi Library-variabel-konstanta terkait LCD-I2C =============
#include <LiquidCrystal_I2C.h> //deklarasi penggunaan library
LiquidCrystal_I2C lcd(0x27, 16, 2); //set alamat LCD & 16 kolom 2 baris
#define PB 12  //deklarasi tombol PB ke pin 7 pada Arduino
#define Buz 13 //deklarasi Buzzer ke pin 4 pada Arduino
char dataTombol;

//====================== Sub-Program "Jam dengan Delay " ========================
//======== Deklarasi Library-variabel-konstanta terkait Penghitungan Jam ========
#include <TM1637Display.h>
#define CLK 10   // deklarasi pin CLK terhubung ke pin 8 Arduino
#define DIO 11   // deklarasi pin DIO terhubung ke pin 9 Arduino
//Inisialisasi library TM1637Display dengan nama display
TM1637Display display(CLK, DIO); //inisialisasi objek "display"

uint8_t data[]={0xff,0xff,0xff,0xff }; //deklarasi var array data[], nyalakan semua
uint8_t blank[]={0x00,0x00,0x00,0x00 };//deklarasi var array blank[], matikan semua
int det, m1, m2, h1, h2; //deklarasi variabel detik, menit dan jam
int jam; //deklarasi variabel jam menyatukan m1, m2, h1 dan h2
bool colonFlag = false; // deklarasi variabel tipe boolean

void setup() {
  //tidak ada baris koding SETUP untuk Sub-Program "CustomKeypad"
  //============================ Sub-Program "Menu" ==============================
  //== pendefinisian pin PB, resistor pull-up, inisiasi LCD & yang terkait dg menu
  pinMode(PB, INPUT);         //set pin PB sbg input
  pinMode(PB, INPUT_PULLUP);  //aktifkan resistor pull-up internal  
  lcd.init();                 //inisiasi lcd
  lcd.backlight();            //nyalakan lampu backlight
  kataPembukaan();            //tampilkan beberapa kalimat pembukaan

  //====================== Sub-Program "Jam dengan Delay" ========================
  //== setting brightness dan clear TM1637, set default jam = 21:30
  display.setBrightness(0x0f);    //set kecerahan display
  display.setSegments(data);     //nyalakan semua segmen
  delay(500);
  display.clear();
  m1=0; m2=3; h1=1, h2=2; //set jam 21:30
}

void kataPembukaan() {
  lcd.print("  Jam Digital   "); //tampilkan kata pembuka
  lcd.setCursor(0,1);            //pindahkan kursor
  lcd.print("  Dengan Delay  "); //tampilkan kata pembuka
  delay(2000);
  //-----------------------------------------------------------------
  lcd.home();                    //pindahkan kursor ke pojok kiri atas
  lcd.print("Tekan tombol PB "); //tampilkan kata petunjuk
  lcd.setCursor(0,1);            //pindahkan kursor
  lcd.print("utk setting Jam "); //tampilkan kata petunjuk
  delay(2000);
  lcd.clear();                   //menghapus tulisan
  lcd.noBacklight();             //matikan display
}

void menuSet() {
  lcd.backlight();               //nyalakan lampu backlight;
  lcd.print("Puluhan Jam :   "); //tampilkan kata petunjuk
  lcd.setCursor(0,1);            //pindahkan kursor
  lcd.print(" Satuan Jam :   "); //tampilkan kata petunjuk
  lcd.setCursor(14, 0); //pindahkan kursor ke kolom 14, baris 0
  lcd.blink();          //kursor berkedip pd posisi kolom 14, baris 0
  
  tungguKeypad();
  lcd.setCursor(14, 0); //pindahkan kursor ke kolom 14, baris 0
  lcd.noBlink();        //matikan blink
  h2=dataTombol-48;     //salin ke variabel puluhan jam (h2)  
  lcd.print(h2);        //tulis puluhan jam ke LCD
  lcd.setCursor(14, 1); //pindahkan kursor ke kolom 14, baris 1
  lcd.blink();          //kursor berkedip pd posisi kolom 14, baris 1

  tungguKeypad(); 
  lcd.noBlink();        //matikan blink
  h1=dataTombol-48;     //salin ke variabel satuan jam (h1)
  lcd.print(h1);        //tulis satuan jam ke LCD
  delay(2000);

  lcd.home(); //pindahkan kursor ke pojok kiri atas
  lcd.print("Puluhan Min :   "); //tampilkan kata petunjuk
  lcd.setCursor(0,1);            //pindahkan kursor
  lcd.print(" Satuan Min :   "); //tampilkan kata petunjuk
  lcd.setCursor(14, 0); //pindahkan kursor ke kolom 14, baris 0
  lcd.blink();          //kursor berkedip pd posisi kolom 14, baris 0

  tungguKeypad();  
  lcd.noBlink();        //matikan blink
  m2=dataTombol-48;     //salin ke variabel puluhan menit (m2)
  lcd.print(m2);        //tulis puluhan menit ke LCD
  lcd.setCursor(14, 1); //pindahkan kursor ke kolom 14, baris 1
  lcd.blink();          //kursor berkedip pd posisi kolom 14, baris 1

  tungguKeypad(); 
  lcd.noBlink();        //matikan blink
  m1=dataTombol-48;     //salin ke variabel satuan menit (m1)
  lcd.print(m1);        //tulis satuan menit ke LCD
  delay(2000);

  lcd.clear();         //hapus seluruh teks pada LCD
  lcd.setCursor(0, 0); //pindahkan kursor ke kolom 0, baris 0
  lcd.print("Setting selesai");
  lcd.setCursor(5, 1); //pindahkan kursor ke kolom 5, baris 1  
  lcd.print(h2); lcd.print(h1); lcd.print(":"); 
  lcd.print(m2); lcd.print(m1);
  delay(2000);
}

void loop() {
  for(det = 0; det <= 60; det++) {
    int stat_PB=1; //konstanta status penekanan tombol PB = 1
    stat_PB = digitalRead(PB); //baca status pin digital PB
  	if (stat_PB==0) {          //jika tombol ditekan maka stat_PB=0
    	stat_PB==1;              //kembalikan status PB menjadi 1
    	menuSet();               //eksekusi fungsi menuSet
    	lcd.noBlink();           //matikan blink
    	lcd.clear();             //hapus display
    	lcd.noBacklight();	     //matikan display
    }
    delay(930);// untuk mengatur kecepatan kenaikan variabel det
    //-----------------------------------------------
    jam =  (h2*1000) + (h1*100) + (m2*10) + (m1);
    if(colonFlag) {
      colonFlag =! colonFlag; //merubah true ke flase atau sebaliknya
      display.showNumberDecEx(jam,0x40);//tampilkan jam & nyalakan colon
    }
    else {
      colonFlag =! colonFlag; //merubah true ke flase atau sebaliknya
      display.showNumberDecEx(jam,0x00);//tampilkan jam & matikan colon
    }
    //-----------------------------------------------
    if(det==60) {    // jika det=60 maka
      det=0; m1++;   // det=0 dan m1=m1+1

      if(m1==10) {  // jika m1=10 (satuan menit), maka
        m1=0; m2++; // m1=0 dan m2=m2+1(naikkan puluhan menit)
        
        if(m2==6) {           // jika m2=6 (puluhan menit)
          m2=0; m1=0; h1++;   // m2=0, m1=0 dan h1=h1+1 (satuan jam)
          if(h2==2 && h1==4) {// jika h2=2 dan h1=4 (jam 24), maka
            h2=0; h1=0; m1=0; m2=0; //h2=0, h1=0, m1=0, m2=0
          }
          if(h1==10) {        // jika h1=10 (satuan jam), maka
           h2++;             // h2=h2+1 (puluhan jam)
           h1=0; m2=0; m1=0; // h1=0, m2=0, m1=0
          }
        }
      }
    }
  }
}

void tungguKeypad() {
  dataTombol = customKeypad.getKey();//baca data tombol 
    while (dataTombol == NO_KEY){   //jika tombol tidak ditekan terbaca NO_KEY
      dataTombol = customKeypad.getKey(); //tunggu disini hingga tombol ditekan
    }   
    tone(Buz,440); delay(50); noTone(Buz);
}
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
4-Digit Display
sevseg1:CLK
sevseg1:DIO
sevseg1:VCC
sevseg1:GND
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
bz1:1
bz1:2
vcc2:VCC
gnd2:GND
gnd1:GND
gnd3:GND
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
vcc1:VCC
keypad1:R1
keypad1:R2
keypad1:R3
keypad1:R4
keypad1:C1
keypad1:C2
keypad1:C3
keypad1:C4