Truncated match.
PICList
Thread
'fast % routine'
2000\02\24@205608
by
Tony Nixon
Hi all,
I need a fast 0 - 255 -> % routine
Eg Byte value = 89
% value = 34
89 / 255 * 100
I did this routine - any others??
Value in W on entry
Result in PcntH on return
ToPcnt movwf PCntH
movwf tempL
clrf PCntL
bcf status,carry
rrf PCntH
rrf PCntL
rrf PCntH
rrf PCntL
rrf PCntH,w
movwf tempH
rrf PCntL,w
call addup
clrf tempH
bcf status,carry
rlf tempL
rlf tempH
rlf tempL
rlf tempH
movf tempL,w
call addup
return
addup addwf PCntL
btfsc status,carry
incf PCntH
movf tempH,w
addwf PCntH
return
--
Best regards
Tony
http://www.picnpoke.com
spam_OUTsalesTakeThisOuT
picnpoke.com
2000\02\24@214213
by
Scott Dattalo
|
On Fri, 25 Feb 2000, Tony Nixon wrote:
> Hi all,
>
> I need a fast 0 - 255 -> % routine
>
> Eg Byte value = 89
> % value = 34
>
> 89 / 255 * 100
>
> I did this routine - any others??
>
> Value in W on entry
> Result in PcntH on return
>
> ToPcnt movwf PCntH
<big snip>
You mean like this:
;*******************************************************************
;scale_hex2dec
; The purpose of this routine is to scale a hexadecimal byte to a
;decimal byte. In other words, if 'h' is a hexadecimal byte then
;the scaled decimal equivalent 'd' is:
; d = h * 100/256.
;Note that this can be simplified:
; d = h * 25 / 64 = h * 0x19 / 0x40
;Multiplication and division can be expressed in terms of shift lefts
;and shift rights:
; d = [ (h<<4) + (h<<3) + h ] >> 6
;The program divides the shifting as follows so that carries are
automatically
;taken care of:
; d = (h + (h + (h>>3)) >> 1) >> 2
;
;Inputs: W - should contain 'h', the hexadecimal value to be scaled
;Outputs: W - The scaled hexadecimal value is returned in W
;Memory: temp
;Calls: none
scale_hex2dec
MOVWF temp ;Hex value is in W.
CLRC ;Clear the Carry bit so it doesn't affect RRF
RRF temp,F
CLRC
RRF temp,F
CLRC
RRF temp,F ;temp = h>>3
ADDWF temp,F ;temp = h + (h>>3)
RRF temp,F ;temp = (h + (h>>3)) >> 1
ADDWF temp,F ;temp = h + ((h + (h>>3)) >> 1)
RRF temp,F
CLRC
RRF temp,W ;d = W = (h + (h + (h>>3)) >> 1) >> 2
RETURN
?
Scott
2000\02\24@225823
by
Tony Nixon
2000\02\24@233843
by
Scott Dattalo
|
On Fri, 25 Feb 2000, Tony Nixon wrote:
> Scott Dattalo wrote:
>
> > You mean like this:
> [snip]
>
>
> Gee Scott, what took you so long :-))
Well, the first one was a fast mod routine and then it dawned on me you
meant percentage :).
If you look closely, it doesn't do exactly what you asked. The one I
posted divides (implicitly) by 256 while you were asking for 255. The
error is quite small, but if necessary can be removed.
You're asking for
p = x * 100/255
and I gave you a solution for
p' = x * 100/256
but you can do a little arithmetic:
p = x * 100/256 * (256/255)
= p' * (256/255)
= p' * (1 + 1/255)
= p' + p'/255
and,
1/255 = 1/(-1+256) = 1/256 * ( 1 + 1/256 + 1/256/256 + ...)
p = p' + p'/256 + p'/256/256 + ...
Now since p' is going to be less than 100, then the first correction is
going to be less than 1/2 and there will be no rounding. Hence the answer
IS the same. However, if you wanted a fractional result, well here you go.
Looks like you get a repeating fraction much like you get when you divide
by 9 (10 - 1 instead of 256 - 1).
Scott
2000\02\24@235542
by
Tony Nixon
Scott Dattalo wrote:
> Well, the first one was a fast mod routine and then it dawned on me you
> meant percentage :).
I actually tested the routine with 256 and it doesn't make a great deal
of difference (if any). I was going to dump it into Excel, but no time
yet.
Thanks anyway, I've already implemented it.
--
Best regards
Tony
http://www.picnpoke.com
sales
KILLspampicnpoke.com
2000\02\25@003330
by
John Orhan
Hi Guys,
Could you explain that one more time for the dummy?
John
{Original Message removed}
2000\02\25@023354
by
Nikolai Golovchenko
|
Nice done, Scott!
To add, if Tony needs a little better precision (especially for higher
values of input byte), one more term should be added, so that
d = (((h >> 3 + h) >> 3 + h) >> 1 + h) >> 2 = h * (1/4 + 1/8 + 1/64 +
1/512)
This adds only 6 cycles, and reduces errors from 51 to 11 cases per
all combinations of input (in both routines absolute errors are small,
+-1).
> MOVWF temp ;Hex value is in W.
> CLRC ;Clear the Carry bit so it doesn't affect RRF
RRF temp,F
CLRC
RRF temp,F
CLRC
RRF temp,F
ADDWF temp, F
{Quote hidden}> RRF temp,F
> CLRC
> RRF temp,F
> CLRC
> RRF temp,F ;temp = h>>3
> ADDWF temp,F ;temp = h + (h>>3)
> RRF temp,F ;temp = (h + (h>>3)) >> 1
> ADDWF temp,F ;temp = h + ((h + (h>>3)) >> 1)
> RRF temp,F
> CLRC
> RRF temp,W ;d = W = (h + (h + (h>>3)) >> 1) >> 2
> RETURN
Nikolai
On Friday, February 25, 2000 Scott Dattalo wrote:
{Quote hidden}> On Fri, 25 Feb 2000, Tony Nixon wrote:
>> Hi all,
>>
>> I need a fast 0 - 255 -> % routine
>>
>> Eg Byte value = 89
>> % value = 34
>>
>> 89 / 255 * 100
>>
>> I did this routine - any others??
>>
>> Value in W on entry
>> Result in PcntH on return
>>
>> ToPcnt movwf PCntH
> <big snip>
> You mean like this:
> ;*******************************************************************
> ;scale_hex2dec
> ; The purpose of this routine is to scale a hexadecimal byte to a
> ;decimal byte. In other words, if 'h' is a hexadecimal byte then
> ;the scaled decimal equivalent 'd' is:
> ; d = h * 100/256.
> ;Note that this can be simplified:
> ; d = h * 25 / 64 = h * 0x19 / 0x40
> ;Multiplication and division can be expressed in terms of shift lefts
> ;and shift rights:
> ; d = [ (h<<4) + (h<<3) + h ] >> 6
> ;The program divides the shifting as follows so that carries are
> automatically
> ;taken care of:
> ; d = (h + (h + (h>>3)) >> 1) >> 2
> ;
> ;Inputs: W - should contain 'h', the hexadecimal value to be scaled
> ;Outputs: W - The scaled hexadecimal value is returned in W
> ;Memory: temp
> ;Calls: none
> scale_hex2dec
> MOVWF temp ;Hex value is in W.
> CLRC ;Clear the Carry bit so it doesn't affect RRF
> RRF temp,F
> CLRC
> RRF temp,F
> CLRC
> RRF temp,F ;temp = h>>3
> ADDWF temp,F ;temp = h + (h>>3)
> RRF temp,F ;temp = (h + (h>>3)) >> 1
> ADDWF temp,F ;temp = h + ((h + (h>>3)) >> 1)
> RRF temp,F
> CLRC
> RRF temp,W ;d = W = (h + (h + (h>>3)) >> 1) >> 2
> RETURN
> ?
> Scott
2000\02\25@053806
by
Michael Rigby-Jones
This was done last year some time IIRC. I offered a simmlar (although
nowhere near as good as Scotts solution) that also divided by 256 instead of
255. There was a long thread regarding "fixing" this error, I'll have to
trawl through the archives and see what the conclusion was...
Cheers
Mike
> {Original Message removed}
2000\02\25@093716
by
Jason Harper
> I need a fast 0 - 255 -> % routine
>
> Eg Byte value = 89
> % value = 34
>
> 89 / 255 * 100
The fastest routine, of course, would be a 256 byte lookup table...
Assuming that code space is also a concern, try this: it's a bit shorter
than the other solutions I've seen posted. Note that it actually
calculates input * 102 / 256, but due to roundoff errors it produces 100
for an input of 255, so it should do the job for you.
percentify
; input in W, output in temp
movwf temp
bcf status,c
rrf temp,f ;temp = input * 128 / 256
addwf temp,f ;carry/temp = input * 384 / 256
rrf temp,f ;temp = input * 192 / 256
bcf status,c
rrf temp,f ;temp = input * 96 / 256
swapf temp,w
andlw 0x0F ;w = input * 6 / 256
addwf temp,f ;temp = input * 102 / 256
;or: addwf temp,w for result in w
return
Jason Harper
2000\02\27@181313
by
Dmitry Kiryashov
|
Hi Scott.
Nice code ;-)
{Quote hidden}> scale_hex2dec
>
> MOVWF temp ;Hex value is in W.
> CLRC ;Clear the Carry bit so it doesn't affect RRF
> RRF temp,F
> CLRC
> RRF temp,F
> CLRC
> RRF temp,F ;temp = h>>3
> ADDWF temp,F ;temp = h + (h>>3)
> RRF temp,F ;temp = (h + (h>>3)) >> 1
> ADDWF temp,F ;temp = h + ((h + (h>>3)) >> 1)
> RRF temp,F
> CLRC
> RRF temp,W ;d = W = (h + (h + (h>>3)) >> 1) >> 2
>
> RETURN
>
> ?
Possible realization of 1 + 1/256 + ... correction.
;1/256 * (1 + 1/256) =~ 0.999985 / 255 ;
scale255to100: ;25 = 16+8+1
clrf temp ;int
clrf temp1 ;frac
addwf temp,F ;1
rrf temp,F ;/2
rrf temp1,F
rrf temp,F ;/4
rrf temp1,F
rrf temp,F ;/8
rrf temp1,F
addwf temp,F ;8
rrf temp,F ;/16
rrf temp1,F
addwf temp,F ;16
rrf temp,F ;/32
rrf temp1,F
rrf temp,W ;/64
rrf temp1,F
;
; movwf temp2 ;1/256/256 if longer tail
; movwf temp3 ;1/256/256/256 is required
; etc...
;
addwf temp1,F ;1 + 1/256 correction
btfss temp1,7 ;either round if >= 0.5
skpnc ;or take carry
addlw 1 ;temp1 holds frac part
;
; movwf temp ;answer is either W or temp
return
If >=0.5 correction isn't required <btfss temp1,7> line
should be commented.
WBR Dmitry.
More... (looser matching)
- Last day of these posts
- In 2000
, 2001 only
- Today
- New search...