; Multiplication Table x2 to x9
; Max output is Decimal 99
;
; start date = 5.05.2013
; phase 1: Make use of the 7 seg display routine
; phase 2: initial trial 6.05.2013
; phase 3: tested with John's "MULT codes" on 10.05.2013
;
org 00h
jmp start
org 1bh
jmp T1_isr
org 100h
sa equ 01h
sb equ 02h
sc equ 04h
sd equ 08h
se equ 10h
sf equ 20h
sg equ 40h
sdp equ 80h
;
d_flag bit 20h.0 ; disp flag
ovf bit 20h.2 ; overflow flag
button bit p2.7 ; button
sav_tl1 equ 30h ; temp for T1L
sav_th1 equ 31h ; temp for T1H
unit_dig equ 32h ; unit digit disp pattern
ten_dig equ 33h ; tenth digit disp pattern
m_cand equ 34h ; multiplicand
product equ 35h
unit equ R2 ; unit digit
tenth equ R3 ; tenth digit
hund equ R4
;
start:
mov SP,#0x80 ; move stack to upper RAM 0x80
call init
call display ; display them
nxt_num:
mov M_cand,#01 ; init multiplicand
but_loop:
call delay_200ms ; debounce button
jb button,but_loop ; button not pressed, loop
call mult ; do multiplication
call chk_product ; check if product out of range
jb ovf,nxt_num ; O.O.R. goto next number
call bin2BCD ; convert binary to BCD
call display ; convert to 7S pattern
call delay_200ms
call delay_200ms
jmp but_loop ; wait for next button press
mult: mov a,p2 ; get multiplier
anl a,#0x0f ; mask of upper nibble
mov b,m_cand ; get multiplicand
mul ab ; do the multiplication
mov product,a ; discard MSB byte
inc m_cand ; multiplicand +1
ret ; Acc is LSB of product
chk_product:
clr ovf ; clear overflow flag
mov a,product
cjne a,#99,$+3 ; Is product <100?
jc chk_exit ; yes
setb ovf ; set over flow flag
chk_exit: ret
BIN2BCD:
mov B,#0x64 ;divisor = 100
div AB ;divide value in accumulator by 100
mov HUND,A ;store integer in HUND register
mov A,B ;transfer remainder to accumulator
mov B,#0x0A ;divisor = 10
div AB ;divide value in accumulator by 10
mov TENTH,A ;store integer in TEN register
mov UNIT,B ;store remainder in ONE register
ret ;done
display:
mov a,r2
movc a,@a+dptr ; get number patter for display
mov unit_dig,a
mov a,r3
movc a,@a+dptr ; get number patter for display
mov ten_dig,a
ret
init:
mov DPTR,#TABLE ; dptr = 7 segment table address
mov unit, #0 ; unit digit
mov tenth, #0 ; tenth digit
mov TMOD,#0x10 ; set up timer1 for 10mS
mov TL1,#0xf0 ; Mode=1
mov TH1,#0xd8 ; 0xD8F0 is 10ms counting
mov sav_tl1,#0xf0
mov sav_th1,#0xd8
setb tr1 ; start timer1
setb et1 ; enable timer1 interrupt
setb ea ; enable global interrupt
ret
T1_isr:
PUSH ACC
PUSH PSW
PUSH DPH
PUSH DPL
clr TR1 ;stop timer1
mov TL1,sav_tl1 ;restore t1
mov TH1,sav_th1
setb TR1 ;start timer1
cpl d_flag ;toggle d_flag
jb d_flag,upper ;1=upper 0=lower
lower: clr p3.0 ;switch off both digits
clr p3.1
mov p1,unit_dig ;get new value
setb p3.0 ;turn on lower digit
sjmp isr_exit
upper: clr p3.0 ;switch off both digits
clr p3.1
mov p1,ten_dig ;get new value
setb p3.1 ;turn on upper digit
isr_exit:
clr TF1 ;clear timer1 flag
POP DPL
POP DPH
POP PSW
POP ACC
reti
;
; 7 segment pattern table
;
table: db sa+sb+sc+sd+se+sf ; 0
db sb+sc ; 1
db sa+sb+sg+se+sd ; 2
db sa+sb+sc+sd+sg ; 3
db sb+sc+sf+sg ; 4
db sa+sc+sd+sf+sg ; 5
db sa+sc+sd+se+sf+sg ; 6
db sa+sb+sc ; 7
db sa+sb+sc+sd+se+sf+sg ; 8
db sa+sb+sc+sd+sf+sg ; 9
delay_200ms:
mov r4,#0ffh
sjmp delay
delay_20ms:
mov r4,#1
loop0: djnz r4,loop0
ret
delay:
loop2: mov r5,#04Fh
loop1: djnz r5,loop1
djnz r4,loop1
ret
end