$MOD51
    DSEG
    Org 30H
Milidetik:   Ds  1
Detik:       Ds  1
Menit:       Ds  1
Jam:         Ds  1
TabelDesimal:   Ds  2
    CSEG
ROM     EQU     0000
        Org     ROM                   ;Reset Vector
    Ajmp    Start           ;
        Org     ROM+3                   ;External Interrupt 0 Vector
    Ajmp    INTR0
        Org     ROM+0BH                   ;Timer 0 Interrupt Vector
    Ajmp    Timer0_Interrupt
        Org     ROM+13H                   ;External Interrupt 1 Vector
    Ajmp    INTR1
        Org     ROM+1BH                   ;Timer 1 Interrupt Vector
    Reti                ;
        Org     ROM+23H                   ;Serial Interrupt Vector
    Reti

Start:
    Lcall   Init_LCD        ;Inisial LCD
    Acall   ResetWaktu      ;Reset variabel waktu

    Mov TMOD,#01            ;Timer 0 16 bit counter
    Acall   ResetTimer0     ;Atur nilai Timer 0 agar overflow setiap 10mS
    Setb    EA              ;
    Setb    ET0             ;Aktifkan Interupsi Timer 0
    Setb    TR0             ;Aktifkan Timer 0
    Setb    EX0             ;Aktifkan Interupsi External 0
    Setb    EX1             ;Aktifkan Interupsi External 1
    Ajmp    $

ResetWaktu:
    Mov MiliDetik,#00
    Mov Detik,#00
    Mov Menit,#00
    Mov Jam,#00
    Ret

;Timer 0 diberi nilai DC00H atau -2400H
;Timer 0 akan overflow setiap 2400H atau 9216 hitungan
;Setiap hitungan (cycle) = 12/Nilai Crystal atau 12/11059200
;12/11059200 x 9216 = 10mS
ResetTimer0:
    Mov TH0,#0DCH
    Mov TL0,#00H
    Ret

;Interupsi terjadi setiap 10 mS
;Nilai Waktu ditampilkan di display setiap 10 mS
Timer0_Interrupt:
    Clr ET0
    Push    ACC
    Push    B
    Push    PSW
    Push    06H
    Push    00H
    Acall   ResetTimer0
    Acall   DisplayWaktuLCD
    Inc Milidetik
    Mov A,Milidetik
    Cjne    A,#100,KeluarTimer0
    Mov Milidetik,#00
    Inc Detik
    Mov A,Detik
    Cjne    A,#60,KeluarTimer0
    Mov Detik,#00
    Inc Menit
    Mov A,Menit
    Cjne    A,#60,KeluarTimer0
    Mov Menit,#00
    Inc Jam
    Mov A,Jam
    Cjne    A,#24,KeluarTimer0
    Mov Jam,#00
KeluarTimer0:
    Pop 00H
    Pop 06H
    Pop PSW
    Pop B
    Pop ACC
    Setb    ET0
    Reti


DisplayWaktuLCD:
    Lcall   PosisiAwal_LCD
    Mov A,Jam
    Acall   LCDDesimal
    Mov A,#':'
    Lcall   Kirim_Karakter
    Mov A,Menit
    Acall   LCDDesimal
    Mov A,#':'
    Lcall   Kirim_Karakter
    Mov A,Detik
    Acall   LCDDesimal
    Mov A,#':'
    Lcall   Kirim_Karakter
    Mov A,Milidetik
    Acall   LCDDesimal
    Ret

; Menampilkan nilai hexa menjadi bentuk desimal ASCII pada LCD
LCDDesimal:
    Mov R0,#TabelDesimal
    Mov TabelDesimal,#00
    Mov TabelDesimal+1,#00
    Lcall   Konversi1bDesimal
    Mov R0,#TabelDesimal+1
    Mov A,@R0
    Add A,#30H
    Lcall   Kirim_karakter
    Dec R0
    Mov A,@R0
    Add A,#30H
    Lcall   Kirim_Karakter
    Ret

;INTERUPSI EXTERNAL 1
;Digunakan untuk mereset waktu Stop Watch
INTR1:
    Clr EX1
    Push    B
    Mov B,#0FFH
    Djnz    B,$
    Pop B    
    Acall   ResetWaktu
    Acall   DisplayWaktuLCD
    Jnb INT1,$
    Setb    EX1
    Reti
    
;INTERUPSI EXTERNAL 0
;Digunakan untuk mengaktif/non aktifkan waktu Stop Watch
INTR0:
    Clr EX0
    Push    B
    Mov B,#0FFH
    Djnz    B,$
    Pop B    
    Cpl ET0
    Jnb INT0,$
    Setb    EX0
    Reti

    $Include(HD44780.asm)
    $Include(Delay_1d.asm)
    $Include(HexASCII.asm)
    $Include(Hexdec1b.asm)
    END