
    ROW0             EQU          P1.0
    ROW1             EQU          P1.1
    ROW2             EQU          P1.2            
    ROW3             EQU          P1.3

    CLMN0            EQU          P1.7
    CLMN1            EQU          P1.6
    CLMN2            EQU          P1.5
    CLMN3            EQU          P1.4
    DIGIT            DATA         30h    ;temporary storage of pressed key
    ALERT            EQU          P3.7   ;goes low when any key's pressed



org  0000h

    ljmp ks_main

org 0030h

;_________________________________________________________________
;----------SERIAL PORT INITIALISATION STARTS HERE-----------------
;_________________________________________________________________


s9k_main: mov tmod,#20h         ;timer_0 in mode2 (8bit auto reload)
          mov th1,#0fdh           ;set baud to 9600
          mov scon,#50h         ;serial mode1 (8bit data varialble baud)
          setb tr1                    ;start timer_0
          ret


;--------------SERIAL TRANSMIT SUBROUTINE-------------------------



tx_main:  mov sbuf,a
tx_loop:  jnb TI,tx_loop
          clr TI
          ret


;--------------SERIAL RECIEVE SUBROUTINE--------------------------



rx_main:  clr a
rx_loop:  jnb ri,rx_loop
          mov a, sbuf
	  clr ri
	  ret

;------------------------------20ms delay----------------------------------

delay_20ms: push 00
            push 01
            mov r0,#36
delay_20ms_loop1:  
            mov r1,#255
delay_20ms_loop2:
            djnz r1,delay_20ms_loop2
            djnz r0,delay_20ms_loop1 
            pop 01
            pop 00
            ret

;------------------------display subroutine--------------------------------

disp_message:       push acc

disp_message_loop1: mov a, #00h	; reset accumulator	
		    movc a,@a+dptr
		    cjne a,#00h,disp_message_loop2

		    pop acc
		    ret

disp_message_loop2: mov sbuf,a
                    acall tx_main
		    inc dptr
	            sjmp disp_message_loop1
		            
disp_pressed:DB"   Key pressed is:  ",00h

;----------------packed ascii to hex conversion--------------------

ascii2hex:       push acc
                  
		 mov a,DIGIT
		 subb a,#30h
		 mov b,a
		 anl a,#10h
		 cjne a,#00h,ascii2hex_loop2
		 mov a,b
				
ascii2hex_loop1: mov DIGIT,a
                 pop acc
		 ret

ascii2hex_loop2: mov a,DIGIT
                 subb a,#37h
		 sjmp ascii2hex_loop1
 
;------------------send pressed button via p3----------------------

send4x4_parallel: push acc
                  mov a,Digit
					 
		  rrc a
		  mov p3.5,c	   ;LSB
		  rrc a
		  mov p3.4,c
		  rrc a 
		  mov p3.3,c
		  rrc a
		  mov p3.2,c	   ;MSB
		 
		  pop acc
		  ret
;_________________________________________________________________
;-------------------------main code------------------------------
;_________________________________________________________________


ks_main:    mov p1,#0ffh					;make input ports
            ;mov p3,#00h	;make output ports; never make this mistake => 3.0 n 3.1 are serial pins
	    setb ALERT						              
            acall s9k_main
ks_main1:   mov p1,#0f0h                    ;all columns high n rows low
            mov a,p1
            anl a,#11110000b                ;consider only columns
            cjne a,#11110000b,ks_main1      ;initially check for all keys released
;-------------------------------------------------------------------                      
ks_loop1:   acall delay_20ms
            mov a,p1
            anl a,#11110000b                            ;scan columns
            cjne a,#11110000b,debounce         ;if key pressed, check debounce
            sjmp ks_loop1                       ;if not, keep checking for key pressed
;-------------------------------------------------------------------
debounce:   acall delay_20ms
            mov a,p1
            anl a,#11110000b 
            cjne a,#11110000b,check_row
            sjmp ks_loop1
;--------------------------------------------------------------------
check_row:  mov dptr,#disp_pressed
            acall disp_message
						
            clr ROW0
	    setb ROW1
	    setb ROW2
	    setb ROW3

	    mov a,p1
            anl a,#11111110b 			 ;test row zero
            cjne a,#11111110b,row_0
;--------------------------------------------------------------------			
	    setb ROW0
	    clr ROW1
	    setb ROW2
	    setb ROW3
			
            mov a,p1
            anl a,#11111101b 			 ;test row one
            cjne a,#11111101b,row_1
;---------------------------------------------------------------------
            setb ROW0
	    setb ROW1
	    clr ROW2
	    setb ROW3
			
            mov a,p1
            anl a,#11111011b			 ;test row two
            cjne a,#11111011b,row_2
;--------------------------------------------------------------------- 			
	    setb ROW0
	    setb ROW1
	    setb ROW2
	    clr ROW3
			
            mov a,p1
            anl a,#11110111b  		    ;test row three
            cjne a,#11110111b,row_3
;----------------------------------------------------------------------
            sjmp ks_loop1
;----------------------------------------------------------------------
row_0:      mov dptr,#disp_kcode0
             sjmp find_num

row_1:      mov dptr,#disp_kcode1
             sjmp find_num

row_2:      mov dptr,#disp_kcode2
             sjmp find_num
			
row_3:      mov dptr,#disp_kcode3
             sjmp find_num
;----------------------------------------------------------------------
find_num:   rlc a
            jnc found_num      ;which column is pressed/grounded
            inc dptr
            sjmp find_num
;----------------------------------------------------------------------
found_num:  clr ALERT ;notify main MC that key has been pressed
            
	    clr a
            movc a,@a+dptr
	    mov DIGIT,a
	    acall tx_main     ;send pressed button to serial port
	    acall ascii2hex
	    acall send4x4_parallel
			
	    setb ALERT  ;bring keypad module to waiting state
;-----------------------------------------------------------------------
            jmp ks_main1
;-----------------------------------------------------------------------
disp_kcode0:DB'0','1','2','3'
disp_kcode1:DB'4','5','6','7' 
disp_kcode2:DB'8','9','A','B' 
disp_kcode3:DB'C','D','E','F' 
;-----------------------------------------------------------------------

end   
