$MOD51
 DSEG
 Org 60H


VAR_JAM:  DS 1
VAR_MENIT: DS 1
VAR_DETIK: DS 1
VAR_JAMTEMP: DS 1
VAR_MENITTEMP: DS 1
VAR_DETIKTEMP: DS 1

    CSEG
Hex_ASCII2   EQU 002EH             
;Konversi Hexa ke 2 byte ASCII
;- Akumulator diisi bilangan hexa yang akan dikonversi
;Hasil:
;- Akumulator menyimpan nibble atas
;- Register B menyimpan nibble bawah


Delay_1detik   EQU 0090H             
;Menunda waktu selama 1 detik (timer 0 digunakan)

Delay_500mS   EQU 0099H             
;Menunda waktu selama 500 mS (timer 0 digunakan)

Delay_100mS   EQU 00A2H             
;Menunda waktu selama 100 mS (timer 0 digunakan)

Delay_5mS   EQU 00B4H             
;Menunda waktu selama 5 mS (timer 0 digunakan)

Init_Serial   EQU 00ECH             
;Inisialisasi Port Serial 9600 bps

Serial_Out   EQU 00FCH             
;Kirim nilai akumulator ke port serial

Serial_In   EQU 0104H             
;Ambil data dari port serial dan simpan di akumulator

;KirimPesan_Serial  EQU 010CH             
;Kirim data di alamat yang ditunjuk oleh DPTR hingga data 0F
;- DPTR diisi dengan alamat dari data yang akan dikirim
;- Memori yang diakses adalah memori CODE/PROGRAM

Filter    EQU 0118H             
;Menentukan besaran data apakah berada di dalam atau di luar nilai setpoint
;- R7 diisi nilai max
;- R6 diisi nilai min
;- besaran data di akumulator
;Hasil:
;- Carry flag akan set bila besaran berada di luar nilai setpoint


;=============
;HD44780
;=============
GeserDisplay_Kanan  EQU 05BDH             
;Menggeser tampilan LCD HD44780 ke kanan

GeserDisplay_Kiri  EQU 05C4H             
;Menggeser tampilan LCD HD44780 ke kiri

Posisi_Awal   EQU 05CBH             
;Mengatur posisi cursor LCD ke posisi awal

GeserCursor_Kiri  EQU 05D2H             
;Menggeser Cursor LCD ke kiri

GeserCursor_Kanan  EQU 05D9H             
;Menggeser Cursor LCD ke kanan

KirimPesan_LCD   EQU 05E0H             
;Mengirim data di alamat yang ditunjuk oleh DPTR ke LCD hingga data 0F
;- DPTR diisi dengan alamat awal data yang dikirim
;- Akhir data adalah 0FH

Init_LCD   EQU 05ECH             
;Inisialisasi LCD

Kirim_Perintah   EQU 062BH             
;Mengirim data ke register perintah LCD
;- Data diisi di akumulator

Kirim_Karakter   EQU 064AH             
;Mengirim data ke register data LCD
;- Data diisi di akumulator

Baris2    EQU 0654H             
;Memindah posisi cursor ke baris 2


AmbilScanCode EQU 865H
InitKeyboard EQU 8C4H
capslockLED EQU 8DDH
SWIINT          EQU  0F41H
ROM      EQU  2000H

ALAMAT_RTC  EQU 6000H
LShift           EQU    12H
CapsLock         EQU    58H
RShift           EQU    59H
JAM   EQU 04H
MENIT   EQU 02H
DETIK   EQU 00H
REGA   EQU 0AH
REGB   EQU 0BH
REGC   EQU 0CH
REGD   EQU 0DH
KbdData   Bit P1.4
KbdClock  Bit INT0
Shift_Flag  bit 7fh
Esc_Flag  bit 7eh

 ORG 2000H
 LJMP START 

 ORG 2003H
 LCALL ADA_KEYBOARD
 RETI

 ORG 2030H
CLRSCR:
 PUSH ACC
 MOV A,#0DH
 LCALL SERIAL_OUT
 LCALL DELAY_5MS
 LCALL DELAY_5MS
 POP ACC
 RET


INIT_RTC:
 MOV DPL,#REGA
 MOV A,#20H
 MOVX @DPTR,A
 MOV DPL,#REGB
 MOV A,#02H
 MOVX @DPTR,A
 RET

KIRIM_LCD:
 LCALL HEX_ASCII2
 LCALL KIRIM_KARAKTER
 MOV A,B
 LCALL KIRIM_KARAKTER
 RET


ADA_keyboard:
 CLR EA
 CLR EX0
 clr esc_flag
 acall edit_jam
 jb esc_flag,Ada_Key_ESC
 acall edit_menit
 jb esc_flag,Ada_Key_ESC
 acall edit_detik
Ada_Key_ESC:
 acall ambilwaktu
ADA_KEYBOARD_FINIS:
 SETB EA
 SETB EX0
 RET

cek_enter:
 mov a,b
 cjne a,#0Ah,cek_bukanenter
 setb c
 sjmp cek_enterfinis
cek_bukanenter:
 clr c
cek_enterfinis:
 ret

cek_esc:
 cjne a,#0dh,cek_bukanesc
 setb esc_flag
 sjmp cek_escfinis
cek_bukanesc:
 clr esc_flag
cek_escfinis:
 ret

edit_jam:
 mov var_jam,#0
 mov var_menit,#0
 mov var_detik,#0
edit_jampuluhan:
 Acall AmbilKeyboard  ;Ambil data dari keyboard
 Jnc edit_jambukanenter
 mov b,a
 mov r7,#'2'
 mov r6,#'0'
 lcall filter
 jc edit_jamcek_enter
 mov a,b
 lcall serial_out
 mov a,b
 anl a,#0fh
 swap a
 anl var_jam,#0fh
 orl var_jam,a
 acall Tampil_LCD
 lcall delay_100ms
 clr c
edit_jamsatuan:
 Jb KbdClock,$  ;Tunggu clock keyboard
 Acall AmbilKeyboard  ;Ambil data dari keyboard
 Jnc edit_jambukanenter
 mov b,a
 mov r7,#'9'
 mov r6,#'0'
 lcall filter
 jc edit_jamcek_enter
 mov a,b
 lcall serial_out
 mov a,b
 anl a,#0fh
 anl var_jam,#0f0h
 orl var_jam,a
 acall Tampil_LCD
 lcall delay_100ms
 clr c
 Jb KbdClock,$  ;Tunggu clock keyboard
 sjmp edit_jampuluhan
edit_jamcek_enter:
 acall cek_enter
 jnc edit_jamcekescp
 sjmp edit_jamfinish
edit_jamcekescp:
 acall cek_esc
 jnb esc_flag,edit_jambukanenter
 lcall delay_500ms
 sjmp edit_jamout
edit_jambukanenter:
 lcall delay_100ms
 clr c
 Jb KbdClock,$  ;Tunggu clock keyboard
 sjmp edit_jampuluhan
edit_jamfinish:
 lcall delay_500ms
 mov a,#':'
 lcall serial_out
edit_jamout:
 clr c
 ret

edit_menit:
edit_menitpuluhan:
 Jb KbdClock,$  ;Tunggu clock keyboard
 Acall AmbilKeyboard  ;Ambil data dari keyboard
 Jnc edit_menitbukanenter
 mov b,a
 mov r7,#'6'
 mov r6,#'0'
 lcall filter
 jc edit_menitcek_enter
 mov a,b
 lcall serial_out
 mov a,b
 anl a,#0fh
 swap a
 anl var_menit,#0fh
 orl var_menit,a
 acall Tampil_LCD
 lcall delay_100ms
 clr c
edit_menitsatuan:
 Jb KbdClock,$  ;Tunggu clock keyboard
 Acall AmbilKeyboard  ;Ambil data dari keyboard
 Jnc edit_menitbukanenter
 mov b,a
 mov r7,#'9'
 mov r6,#'0'
 lcall filter
 jc edit_menitcek_enter
 mov a,b
 lcall serial_out
 mov a,b
 anl a,#0fh
 anl var_menit,#0f0h
 orl var_menit,a
 acall Tampil_LCD
 lcall delay_100ms
 clr c
 Jb KbdClock,$  ;Tunggu clock keyboard
 sjmp edit_menitpuluhan
edit_menitcek_enter:
 acall cek_enter
 jnc edit_menitcekescp
 sjmp edit_menitfinish
edit_menitcekescp:
 acall cek_esc
 jnb esc_flag,edit_menitbukanenter
 lcall delay_500ms
 sjmp edit_menitout
edit_menitbukanenter:
 lcall delay_100ms
 clr c
 Jb KbdClock,$  ;Tunggu clock keyboard
 sjmp edit_menitpuluhan
edit_menitfinish:
 lcall delay_500ms
 mov a,#':'
 lcall serial_out
edit_menitout:
 clr c
 ret

edit_detik:
edit_detikpuluhan:
 Jb KbdClock,$  ;Tunggu clock keyboard
 Acall AmbilKeyboard  ;Ambil data dari keyboard
 Jnc edit_detikbukanenter
 mov b,a
 mov r7,#'7'
 mov r6,#'0'
 lcall filter
 jc edit_detikcek_enter
 mov a,b
 lcall serial_out
 mov a,b
 anl a,#0fh
 swap a
 anl var_detik,#0fh
 orl var_detik,a
 lcall Tampil_LCD
 lcall delay_100ms
 clr c
edit_detiksatuan:
 Jb KbdClock,$  ;Tunggu clock keyboard
 Acall AmbilKeyboard  ;Ambil data dari keyboard
 Jnc edit_detikbukanenter
 mov b,a
 mov r7,#'9'
 mov r6,#'0'
 lcall filter
 jc edit_detikcek_enter
 mov a,b
 lcall serial_out
 mov a,b
 anl a,#0fh
 anl var_detik,#0f0h
 orl var_detik,a
 lcall Tampil_LCD
 lcall delay_100ms
 clr c
 Jb KbdClock,$  ;Tunggu clock keyboard
 sjmp edit_detikpuluhan
edit_detikcek_enter:
 acall cek_enter
 jnc edit_detikcekescp
 acall setwaktu
 sjmp edit_detikfinish
edit_detikcekescp:
 acall cek_esc
 jnb esc_flag,edit_detikbukanenter
 lcall delay_500ms
 sjmp edit_detikout
edit_detikbukanenter:
 lcall delay_100ms
 clr c
 Jb KbdClock,$  ;Tunggu clock keyboard
 sjmp edit_detikpuluhan
edit_detikfinish:
 lcall delay_500ms
 acall clrscr
edit_detikout:
 clr c
 ret


AmbilKeyboard:
 Acall Ambil_scancode  ;
 Cjne A,#0F0H,Kybd_TidakLepas ; 
 Jb KbdClock,$  ;Keyboard dilepas
 Acall Ambil_scancode  ;

 Cjne A,#LShift,Bukan_LShiftlepas ;Shift dilepas?
 Ajmp Komplemen_ShiftFlg  ;Ya! Komplemen Shift Flag

Bukan_LShiftlepas: 
 Cjne A,#RShift,Bukan_Shiftlepas ;A<>RShift, bukan Shift kiri
      ;atau shift kanan dilepas
Komplemen_ShiftFlg:
 cpl Shift_Flag   

Bukan_Shiftlepas:
 Clr C
 Ret

Kybd_TidakLepas:
 Cjne A,#Lshift,Bukan_Lshifttekan ;Shift Kiri ditekan?
 Ajmp Komplemen_ShiftFlg  ;Komplemen Shift Flag

Bukan_LShifttekan:
 Cjne A,#RShift,Bukan_RShifttekan ;Shift Kanan ditekan?
 Ajmp Komplemen_ShiftFlg  ;Komplemen Shift Flag

Bukan_RShifttekan:
 Cjne A,#CapsLock,BukanCapsLock ;Caps Lock ditekan
 Ajmp Komplemen_ShiftFlg  ;Komplemen Shift Flag

BukanCapsLock:
 Acall Konversi_Scancode  ;Konversi scan code table
 Setb C
 Ret

Ambil_scancode:
 Push 00H
 CLR    A    ;Tunggu ada Interrupt keyboard
 JNB    KbdClock,$   ;Level high
 Mov R0,#08H
ambil_scancode2:    ;Ambil data dari P1.4 setiap
 JB     KbdClock,$   ;kali interrupt keyboard transisi
 MOV    C,KbdData   ;low
 RR     A    ;Geser Acc A
        MOV     ACC.7,C                          ;Simpan data di bit 7 Acc A
 JNB    KbdClock,$   ;Tunggu Int0 high
 Djnz R0,ambil_scancode2  ;Lakukan 8x
 Jb KbdClock,$   ;Buang Stop Bit
 Jnb KbdClock,$   ;
 Jb KbdClock,$   ;
 Jnb KbdClock,$   ;
 Pop 00H
 Ret   

SetWaktu:
 MOV DPTR,#ALAMAT_RTC
 MOV DPL,#JAM
 MOV A,VAR_JAM
 MOVX @DPTR,A
 MOV DPL,#MENIT
 MOV A,VAR_MENIT
 MOVX @DPTR,A
 MOV DPL,#DETIK
 MOV A,VAR_DETIK
 MOVX @DPTR,A
 Ret

AmbilWaktu:
 MOV DPTR,#ALAMAT_RTC+REGC
 MOVX A,@DPTR
 ANL A,#080H
 JNB ACC7,AmbilWaktu
 CLR ACC7
 MOVX @DPTR,A
 MOV DPTR,#ALAMAT_RTC
 MOV DPL,#JAM
 MOVX A,@DPTR
 MOV VAR_JAM,A
 MOV DPL,#MENIT
 MOVX A,@DPTR
 MOV VAR_MENIT,A
 MOV DPL,#DETIK
 MOVX A,@DPTR
 MOV VAR_DETIK,A
 Ret

Tampil_LCD:
 Lcall Posisi_Awal
 MOV A,VAR_JAM
 LCALL KIRIM_LCD
 MOV A,#':'
 LCALL KIRIM_KARAKTER
 MOV A,VAR_MENIT
 LCALL KIRIM_LCD
 MOV A,#':'
 LCALL KIRIM_KARAKTER
 MOV A,VAR_DETIK
 LCALL KIRIM_LCD
 LCALL POSISI_AWAL
 ret

START:
 MOV DPTR,#ALAMAT_RTC
 ACALL INIT_RTC
 MOV DPTR,#ALAMAT_RTC+REGA
 MOV A,#20H
 MOVX @DPTR,A
 INC DPTR
 MOV A,#12H
 MOVX @DPTR,A
 LCALL INIT_LCD
 Clr shift_flag  ;Kondisi flag shift 0 
 Lcall Init_Serial
 SETB EA
 SETB EX0

ULANG:
 Acall AmbilWaktu
 Acall Tampil_LCD
 lcall delay_100ms
 lcall delay_100ms
 SJMP ULANG

Konversi_ScanCode:
 Mov DPTR,#TabelKeyboard ;Isi DPTR dengan alamat awal 
 Movc A,@A+DPTR  ;TabelKeyboard
 Ret

TabelKeyboard:
 DB 00
 DB 0F9H  
 DB 00
 DB 0F5H,0F3H,0F1H,0F2H,0FCH ;Function Key, FC = F12
 DB 00H    
 DB 0FAH,0F8H,0F6H,0F4H  ;FA=F10
 DB 0C0H ;Tab (Special Code)
 DB '~' ;~
 DB 00H
 DB 00H
 DB 0C1H ;AltL (Special Code)
 DB 0C2H ;ShiftL (Special Code)
 DB 00H
 DB 0C3H ;CtrlL (Special Code
 DB 'q1'
 DB 00H,00H,00H
 DB 'zsaw2'
 DB 00H,00H
 DB 'cxde43'
 DB 00H,00H
 DB ' vftr5'
 DB 00H,00H
 DB 'nbhgy6'
 DB 00H,00H,00H
 DB 'mju78'
 DB 00H,00H
 DB ',kio09'
 DB 00H,00H
 DB './l;p-'
 DB 00H,00H,00H
 DB 2CH   ; '
 DB 00H
 DB '[='
 DB 00H,00H
 DB 0C5H 
 DB 0C6H
 DB 0AH  ;Enter
 DB ']'
 DB 00H
 DB '\'
 DB 00H,00H,00H,00H,00H,00H,00H,00H
 DB 08H  ;BackSpace
 DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H
 DB 0DH  ;Esc
 DB 00H
 DB 0FBH  ;Function Key F11
 DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H
 DB 0F7H  ;Function Key
        END


