Demo entry 6783739

erefre

   

Submitted by anonymous on Feb 19, 2019 at 21:46
Language: ca65 assembler. Code size: 5.1 kB.

; Appendix F: Lab 1, Exercise 6, Keypad, Yevhenii Diomidov


.FLAG KEYPAD_EN, P3.5   ; keypad enabled, active low
.FLAG KEYPAD_DA, P3.4   ; data available
.EQU KEYPAD_DATA, P1    ; data in low 4 bits

.ORG 00h
    ljmp start

.ORG 100h
start:
    lcall init
    main_loop:
        lcall crlf                      ; initial new line
        
        lcall getnumber
        mov R6, A                       ; read the first number to R6
        
        lcall getnumber
        mov R7, A
        
        getop_loop:
            lcall getkeypad             ; read the operator
            cjne A, #15, notminus       ; if it's a minus:
                mov A, #'-'
                lcall sendchr           ;     print '-'
                lcall crlf              ;     go to next line
                mov A, R6
                clr C
                subb A, R7              ;     do the subtraction
                lcall sendnumber        ;     print the result
                sjmp main_loop          ;     read the next pair of numbers
            notminus:
            cjne A, #14, getop_loop     ; if it's neither a plus nor a minus, read the next operate
                mov A, #'+'
                lcall sendchr           ;     print '+'
                lcall crlf              ;     go to next line
                mov A, R6
                add A, R7               ;     do the addition
                lcall sendnumber        ;     print the result
                sjmp main_loop          ;     read the next pair of numbers


init:
    mov TMOD, #00100000b ; no hardware gate, timer, mode 2; not using timer 0
    mov TCON, #01000000b ; use timer 1, not use timer 0 ; no interrupts
    mov TH1,  #253       ; ~9600 baud
    mov SCON, #01110000b ; 8-bit UART; reception enabled; no 9th bit; interrupt flags not set
    mov KEYPAD_DATA, #0FFh
    ret

    
getkeypad:                              ; reads a digit from keypad to A, >=10 if not a digit
    keypad_loop:
    jnb KEYPAD_DA, keypad_loop          ;     wait for keydown
    
    clr KEYPAD_EN
    mov A, KEYPAD_DATA                  ;     read the data
    setb KEYPAD_EN
    
    keypad_loop2:
    jb KEYPAD_DA, keypad_loop2          ;     wait for keyup
    
    anl A, #0Fh                         ;     clear upper nibble
    mov DPTR, #keytable
    movc A, @DPTR + A                   ;     map the key code using the key table
    ret


getnumber:                              ; reads a number from 3-digit keypad to A
    mov R0, #0                          ;     current number
    mov R1, #3                          ;     remaining digits
    getnumber_loop:
        lcall getkeypad                 ;     read a button
        mov R2, A
        add A, #-10
        jnc getnumber_valid_digit       ;     if it's not a digit...
            cjne R1, #3, getnumber_undo ;     ... and we haven't typed anything yet:
            ljmp getnumber_loop         ;         do nothing and read the next digit

            getnumber_undo:             ;     if it's not a digit and we have typed something:
            mov A, #'\b'
            lcall sendchr               ;         go back 1 character
            mov A, #' '
            lcall sendchr               ;         replace it with a space
            mov A, #'\b'
            lcall sendchr               ;         and go back again

            inc R1                      ;         increment the number of remaining digits
            mov A, R0
            mov B, #10
            div AB                      ;         divide by 10 to get rid of the last digit
            mov R0, A
            sjmp getnumber_loop         ;         read the next digit

        getnumber_valid_digit:          ;     if it is a digit:
        mov A, R2
        lcall senddigit                 ;         print it
        
        mov A, R0
        mov B, #10
        mul AB                          ;         multiply our number by 10
        add A, R2                       ;         and add the new digit to it
        mov R0, A
    djnz R1, getnumber_loop             ;     if we have less than 3 digits, read another one
    lcall crlf                          ;     new line
    mov A, R0
    ret


sendchr:                ; writes a character from A to serial, preserves A
    clr TI
    mov SBUF, A
    txloop:
    jnb TI, txloop
    ret


senddigit:              ; writes a digit from A to serial, preserves A
    add A, #'0'
    lcall sendchr
    add A, #-'0'
    ret
    

sendnumber:             ; writes a 3-digit number from A to serial
    mov B, #100
    div AB
    lcall senddigit
    mov A, B
    mov B, #10
    div AB
    lcall senddigit
    mov A, B
    lcall senddigit
    sjmp crlf


crlf:                   ; writes \r\n to serial
    mov A, #13
    lcall sendchr
    mov A, #11
    lcall sendchr
    ret

keytable: 
.DB  1,  2,  3, 10 ; 123A
.DB  4,  5,  6, 11 ; 456B
.DB  7,  8,  9, 12 ; 789C
.DB 15,  0, 14, 13 ; *0#D

This snippet took 0.01 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).