Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
12/24/99 11:17
Read: times


 
#1086 - RE: 32bit maths on 8052
Hi Igor,

This is the code we are currently working on.

There is a call from a high level language to this routine, the HLL sends a 16 bit speed request,
this routine returns two things:
1.) The highest power of two in the speed ( ctr, a byte)
2.) The timer reload value (Divideby, a 16 bit word)

The timer reload is equivalent to (($1000000 SHR (14-ctr) )/ speed) + MinIntPeriod

The highest power of two is extracted by rotating the sixteen bit speed through the carry flag
Then you will see we have a lookup table to find the numerator of the expression, and are left
with the divide to do.

The 16 and 32 bit math ops are from an Intel App note published in 1988. They operate on a 32 bit
number with 16 bit ones, so I can divide, multiply add and subtract a 16 bit number on a 32 bit
number.

Lets see this fast divide routine !

Very best regards

Steve




;MAth library functions for controller project
NAME viscomath

PUBLIC frequency,speed
PUBLIC ?frequency?byte,?speed?byte

Visc_data SEGMENT DATA
Visc_code SEGMENT CODE
rseg visc_data

MinIntPeriod EQU 6000

?frequency?byte: DS 0
freqA: DS 2
freqB: DS 2
divideby: DS 2

?Load_16?byte: DS 2
?Load_32?byte: DS 4
?Mul_16?byte: DS 2
?Div_16?byte: DS 2
?Add_16?byte: DS 2
?Sub_16?byte: DS 2
?Add_32?byte: DS 4
?Sub_32?byte: DS 4

OP_0: DS 1 ;lsb
OP_1: DS 1
OP_2: DS 1
OP_3: DS 1 ;msb
ctr: DS 1

TMP_0: DS 1
TMP_1: DS 1
TMP_2: DS 1
TMP_3: DS 1

?speed?byte: ds 0
spspeed: DS 2
DummyW: DS 2
DummW2: DS 1

RSEG visc_code

Speed: ;Calculate timer reloads and step divisor for a motor speed
;Speed is passed in multiples of the minimum speed in speed and speed+1
;First calculate the highest power of 2 in the number.
MOV ctr,#255
MOV A,spspeed+1
JZ rotateLSB ;There is a MSB
MOV ctr,#7 ;So there must be at least 2^7 in the word
loop_msb:
CLR C
RRC A ;rotate
INC CTR
JNZ loop_msb
SJMP endstep

rotateLSB:MOV A,spspeed
loop_lsb:
CLR C
RRC A
inc ctr
JNZ loop_lsb
endstep:

MOV r0,dummw2
MOV @r0,ctr

MOV A,ctr
RL A
RL A
RL A

MOV op_3,#0
MOV op_2,#0
MOV op_1,#0
MOV op_0,#0

MOV DPH,#HIGH(lookup)
MOV DPL,#LOW(lookup)
JMP @A+DPTR

Lookup: MOV op_1,#40h
sjmp endlook
NOP
NOP
NOP
MOV op_1,#80h
sjmp endlook
NOP
NOP
NOP
MOV op_2,#1
sjmp endlook
NOP
NOP
NOP
MOV op_2,#2
sjmp endlook
NOP
NOP
NOP
MOV op_2,#4
sjmp endlook
NOP
NOP
NOP
MOV op_2,#8
sjmp endlook
NOP
NOP
NOP
MOV op_2,#10h
sjmp endlook
NOP
NOP
NOP
MOV op_2,#20h
sjmp endlook
NOP
NOP
NOP
MOV op_2,#40h
sjmp endlook
NOP
NOP
NOP
MOV op_2,#80h
sjmp endlook
NOP
NOP
NOP
MOV op_3,#1
sjmp endlook
NOP
NOP
NOP
MOV op_3,#2
sjmp endlook
NOP
NOP
NOP
MOV op_3,#4
sjmp endlook
NOP
NOP
NOP
MOV op_3,#8
sjmp endlook
NOP
NOP
NOP
MOV op_3,#10h

endlook: NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP


;divided big number by appropriate power of two

MOV R1,spspeed+1 ;load divisor
MOV R0,spSpeed
LCALL Div_16
;divided by speed to give counter load
MOV ?add_16?byte,#High(MinIntPeriod)
MOV ?add_16?byte+1,#Low(MinIntPeriod)
LCALL ADD_16
MOV r0,dummyW
MOV @r0,op_0
inc r0
MOV @r0,op_1
RET


frequency:
;the ratio of frequency A to frequency B is calculated;.
;The result is returned in freq result as a 32bit number



Add_16:
;Add the 16 bits supplied by the caller to the OP registers
CLR C
MOV A,OP_0
ADDC A,?Add_16?byte+1 ;low byte first
MOV OP_0,A
MOV A,OP_1
ADDC A,?Add_16?byte ;high byte + carry
MOV OP_1,A
MOV A,OP_2
ADDC A,#0 ;propagate carry only
MOV OP_2,A
MOV A,OP_3
ADDC A,#0 ;propagate carry only
MOV OP_3,A
RET

Add_32:
;Add the 32 bits supplied by the caller to the OP registers
CLR C
MOV A,OP_0
ADDC A,?Add_32?byte+3 ;lowest byte first
MOV OP_0,A
MOV A,OP_1
ADDC A,?Add_32?byte+2 ;mid-lowest byte + carry
MOV OP_1,A
MOV A,OP_2
ADDC A,?Add_32?byte+1 ;mid-highest byte + carry
MOV OP_2,A
MOV A,OP_3
ADDC A,?Add_32?byte ;highest byte + carry
MOV OP_3,A
RET

Sub_16:
;Subtract the 16 bits supplied by the caller to the OP registers
CLR C
MOV A,OP_0
SUBB A,?Sub_16?byte+1 ;low byte first
MOV OP_0,A
MOV A,OP_1
SUBB A,?Sub_16?byte ;high byte + carry
MOV OP_1,A
MOV A,OP_2
SUBB A,#0 ;propagate carry only
MOV OP_2,A
MOV A,OP_3
SUBB A,#0 ;propagate carry only
MOV OP_3,A
RET

Sub_32:
;Subtract the 32 bits supplied by the caller to the OP registers
CLR C
MOV A,OP_0
SUBB A,?Sub_32?byte+3 ;lowest byte first
MOV OP_0,A
MOV A,OP_1
SUBB A,?Sub_32?byte+2 ;mid-lowest byte + carry
MOV OP_1,A
MOV A,OP_2
SUBB A,?Sub_32?byte+1 ;mid-highest byte + carry
MOV OP_2,A
MOV A,OP_3
SUBB A,?Sub_32?byte ;highest byte + carry
MOV OP_3,A
RET

Mul_16:
;Multiply the 32 bit OP with the 16 value supplied
MOV TMP_3,#0 ;clear out upper 16 bits
MOV TMP_2,#0
;Generate the lowest byte of the result
MOV B,OP_0
MOV A,?Mul_16?byte+1
MUL AB
MOV TMP_0,A ;low-order result
MOV TMP_1,B ;high-order result
;now generate the next higher order byte
MOV B,OP_1
MOV A,?Mul_16?byte+1
MUL AB
ADD A,TMP_1 ;low-order result
MOV TMP_1,A ;save
MOV A,B ;get high-order result
ADDC A,TMP_2 ;include carry from previous operation
MOV TMP_2,A ;save
JNC Mul_loop1
INC TMP_3 ;propagate carry into TMP_3
Mul_loop1:
MOV B,OP_0
MOV A,?Mul_16?byte
MUL AB
ADD A,TMP_1 ;low-order result
MOV TMP_1,A ;save
MOV A,B ;get high-order result
ADDC A,TMP_2 ;include carry from previous operation
MOV TMP_2,A ;save
JNC Mul_loop2
INC TMP_3 ;propagate carry into TMP_3
Mul_loop2:
;Now start working on the 3rd byte
MOV B,OP_2
MOV A,?Mul_16?byte+1
MUL AB
ADD A,TMP_2 ;low-order result
MOV TMP_2,A ;save
MOV A,B ;get high-order result
ADDC A,TMP_3 ;include carry from previous operation
MOV TMP_3,A ;save
;now the other half
MOV B,OP_1
MOV A,?Mul_16?byte
MUL AB
ADD A,TMP_2 ;low-order result
MOV TMP_2,A ;save
MOV A,B ;get high-order result
ADDC A,TMP_3 ;include carry from previous operation
MOV TMP_3,A ;save
;Now finish off the highest order byte
MOV B,OP_3
MOV A,?Mul_16?byte+1
MUL AB
ADD A,TMP_3 ;low-order result
MOV TMP_3,A ;save
;Forget about the high-order result, this is only 32 bit math!
MOV B,OP_2
MOV A,?Mul_16?byte
MUL AB
ADD A,TMP_3 ;low-order result
MOV TMP_3,A ;save
;Now we are all done, move the TMP values back into OP
MOV OP_0,TMP_0
MOV OP_1,TMP_1
MOV OP_2,TMP_2
MOV OP_3,TMP_3
RET

Div_16:
;This divides the 32 bit OP register by the value supplied
;R0 div_16 msb, R1 div_16 lsb
MOV R7,#0
MOV R6,#0 ;zero out partial remainder
MOV TMP_0,#0
MOV TMP_1,#0
MOV TMP_2,#0
MOV TMP_3,#0

; MOV R1,?Div_16?byte ;load divisor
; MOV R0,?Div_16?byte+1
MOV R5,#32 ;loop count
;This begins the loop
Div_loop:
CALL Shift_D ;shift the dividend the return MSB in C
MOV A,R6 ;shift carry into LSB of partial remainder
RLC A
MOV R6,A
MOV A,R7
RLC A
MOV R7,A
;now test to see if R7:R6 >= R1:R0
CLR C
MOV A,R7 ;subtract R1 from R7 to see if R1 < R7
SUBB A,R1 ;A=R7-R1, carry set if R7<R1
JC Cant_sub
;at this point R7>R1 or R7=R1
JNZ Can_sub ;jump if R7>R1
;if R7=R1, test for R6>=R0
CLR C
MOV A,R6
SUBB A,R0 ;A=R6-R0, carry set if R6<R0
JC CANT_SUB
Can_sub:
;Subtract the divisor from the partial remainder
CLR C
MOV A,r6
SUBB A,r0 ;A= r6-r0
MOV r6,A
MOV A,r7
SUBB A,r1 ;a =R7-R1-borrow
MOV r7,A
SETB C
jmp quot
Cant_sub:
;Shift 0 into the quotient
CLR C
QUOT: ;shift carry into the quotient
CALL shift_q ;test for competition
djnz r5,div_loop ;Now we're all done, move the temp values back into op
MOV op_0,tmp_0
MOV op_1,tmp_1
MOV op_2,tmp_2
MOV op_3,tmp_3
RET

SHIFT_D:;shift the dividend one bit to the left and return the result in C
CLR C
MOV A,op_0
RLC A
MOV op_0,A
MOV A,OP_1
RLC A
MOV op_1,A
MOV A,op_2
RLC A
MOV op_2,A
MOV A, OP_3
RLC A
MOV op_3,A
RET

SHIFT_Q:; Shift the quotient one bit left and return result in C
MOV A,tmp_0
RLC A
MOV tmp_0,A
MOV A,TMP_1
RLC A
MOV tmp_1,A
MOV A,tmp_2
RLC A
MOV tmp_2,A
MOV A, TMP_3
RLC A
MOV TMP_3,A
RET

END.





List of 7 messages in thread
TopicAuthorDate
32bit maths on 8052            01/01/70 00:00      
RE: 32bit maths on 8052            01/01/70 00:00      
RE: 32bit maths on 8052            01/01/70 00:00      
RE: 32bit maths on 8052            01/01/70 00:00      
RE: 32bit maths on 8052            01/01/70 00:00      
RE: 32bit maths on 8052            01/01/70 00:00      
RE: 32bit maths on 8052            01/01/70 00:00      

Back to Subject List