Searching \ for '[PIC] Divide by 10' in subject line. ()
Help us get a faster server
FAQ page: techref.massmind.org/techref/microchip/math/index.htm?key=divide
Search entire site for: 'Divide by 10'.

Exact match. Not showing close matches.
'[PIC] Divide by 10'
2006\02\22@085205 by

Hi,

I want a 8 bit number divide by 10 (ten).
I need the quotient and the remain.

Which is the fastest ASM code for pic 16f877?

Many thanks!!!

Balazs

___________________________________________________________________________
[origo] klikkbank lakossági számlacsomag havi 199 Ft-ért, bankkártya éves díj nélkül!
http://www.klikkbank.hu

Jáhn Balázs wrote:

> I want a 8 bit number divide by 10 (ten).
> I need the quotient and the remain.
>
> Which is the fastest ASM code for pic 16f877?

I don't know, but I'd look at piclist.com first. Considering the history of
this list, I'm pretty sure there's a routine that is at least close to
optimal.

Gerhard
At 01:08 PM 2/22/2006 -0300, you wrote:
>Jáhn Balázs wrote:
>
> > I want a 8 bit number divide by 10 (ten).
> > I need the quotient and the remain.
> >
> > Which is the fastest ASM code for pic 16f877?
>
>I don't know, but I'd look at piclist.com first. Considering the history of
>this list, I'm pretty sure there's a routine that is at least close to
>optimal.
>
>Gerhard

Or just use a LUT, if "fastest" is really the criterion. You can do quotient
and remainder in a single 14-bit word, obviously, so only 3% of your memory
would be required for the table. Max quotient is 25 and maximum remainder is
9, so 6 and 4 bits respectively. With 8 bits allowed for the quotient, no
shifting would be required. This will work any divisor from 1 to 32
inclusive.

Best regards,

Spehro Pefhany --"it's the network..."            "The Journey is the reward"
speffinterlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com
->> Inexpensive test equipment & parts http://search.ebay.com/_W0QQsassZspeff

Jáhn Balázs wrote:
> Hi,
>
> I want a 8 bit number divide by 10 (ten).
> I need the quotient and the remain.
>
> Which is the fastest ASM code for pic 16f877?
>
> Many thanks!!!
>
> Balazs
>
> ___________________________________________________________________________
> [origo] klikkbank lakossági számlacsomag havi 199 Ft-ért, bankkártya éves díj nélkül!
> http://www.klikkbank.hu
>
>
>
>
Given that the dividend is only an 8 bit value to start with (stored in
W), and assuming it is in range 0-255....
snippet puts quotient in "quotient", and remainder in W

movwf  dividend         ; w contains the dividend
clrf        quotient
movlw   10
subwf    dividend,f
btfss      STATUS,0   ; check for positive (Carry bit).
goto      \$+3               ; result is negative
incf       quotient,f
goto      \$-4

best case makes this 8 cycles, worst case is 25*6 + 8 = 158 cycles.

Otherwise, have a look at app note 544 which may help...

Rolf

P.S. I have not tested this code ....
'8-bit BIN to DEC' converter.

To perform the fastest possible 8-bit BIN to DEC conversion:

Use variables TMP,TMP1,. W (entry value):

1. If W greater than 99, subtract off 100,  incr TMP (to 1), otherwise
set tmp=0. The remainder is now in W.

2.  If W is now greater than 99, increment TMP. Do NOT alter
W.

3. W is now 7 bits. Lookup W in a 128-element RETLW table.
results: the ONES place is in the lower nibble of W, the TENS place
is in the upper nibble of W, the 100s place is in TMP.

The table is simply 128 RETLW elements; for the entry value
of h'10', the retlw value is h'16'; for an entry of  h'63', the retlw
value is h'99'; for an entry of h'64', the retlw value is h'00', etc
etc.

This will be an example, W has the value on entry:

8Bin2Dec:
clrf       tmp
btfss    status,c
incf    tmp,f         ;   =1 if > 99 (no overflow)
btfss    tmp,0
addlw    d'100'   ; fix W if < 100.
btfss    status,c
incf    tmp,f         ;   =2 if > 199 (no overflow)
retlw   h'00'         ;element 1    [000]
.
.
.
.
(n)
retlw  h'27'         ;element 128   [127]

This is the fastest code for all PIC16F, 12 words actually
executed, but uses 139 words of code space.

An alternative is to simply subtract 100s then subtract 10s.
uses LOTS of machine cycles, but is sparing of code space..

--Bob

Jáhn Balázs wrote:

{Quote hidden}

--
Note: To protect our network,
attachments must be sent to
attachengineer.cotse.net .
http://beam.to/azengineer
Spehro has it right- to use the code access capability of the
F877 allows the LUT to handle all of it, i.e. 2 bits for 100s, 4
bits for tens, 4-bits for ones places, a total of 10 bits. BUT, it uses
over 260 code words. Would run about 9 cycles to extract a
lookup value, however, faster than my earlier suggestion.

--Bob

Bob Axtell wrote:

{Quote hidden}

--
Note: To protect our network,
attachments must be sent to
attachengineer.cotse.net .
http://beam.to/azengineer
Jáhn Balázs writes:
> I want a 8 bit number divide by 10 (ten).
> I need the quotient and the remain.
>
> Which is the fastest ASM code for pic 16f877?

For an 8 bit dividend a look up table is practical.  Since you
want the remainder, two look up tables.  You won't get faster than
that.  If you also care about code space, then things get more
interesting.

Bill

On Wed, Feb 22, 2006 at 02:50:53PM +0100, J?hn Bal?zs wrote:
> Hi,
>
> I want a 8 bit number divide by 10 (ten).
> I need the quotient and the remain.
>
> Which is the fastest ASM code for pic 16f877?

Simple. Table lookup. Costs 512 instructions for the RETLWs and 2 or so
instructions for the setup for the jump. Something along the lines of:

org        0x01ff                ; Start on instruction short of 256 instruction
; boundary. How can this be done in a
; relocatable fashion?
retlw        0                ; 0/10 = 0
retlw        0                ; 1/10 = 0
; ... up to 9 then
retlw        1                ; 10/10 = 1
retlw        1                ; 11/11 = 1

and so forth.

BAJ
On Wed, Feb 22, 2006 at 11:58:26AM -0500, Rolf wrote:
{Quote hidden}

I would suggest that this would not qualify as "fast". A lookup table
encoded either as RETLWs or as instructions would have an average and best
time of better than 8 cycles.

BAJ
This is a good illustration of how you need to know the machine "guts" to
know how best to implement something, and a good illustration of how higher
level languages would hide that from you.
Rochester, 22 februari 2006.

I know this wasn't part of the original question, but in some cases
you might want to approximate the result, to get a fast result with
minimum memory usage. A possible approximation could be to multiply by
3/32 (or 13/128 for enhanced accuracy).

Such a multiplication could be done by:

3/32: result = (x+8)>>4 + (x+16)>>5 (mean error: 0.80, max: 2)
13/128: result = (x+8)>>4 + (x+16)>>5 + (x+64)>>7 (mean error: 0.34, max: 1)

Or, if you wish to reduce the additions due to rounding:

3/32: result = (x>>3 + x>>4 + 1)>>2 (mean error: 1.05, max: 3)
13/128: result = (x>>3 + x>>4 + x>>6 + 1)>>2 (mean error: 0.34, max: 1)

Greetings,
Maarten Hofman.

On Wed, Feb 22, 2006 at 10:41:34AM -0700, Bob Axtell wrote:
> Spehro has it right- to use the code access capability of the
> F877 allows the LUT to handle all of it, i.e. 2 bits for 100s, 4
> bits for tens, 4-bits for ones places, a total of 10 bits. BUT, it uses
> over 260 code words. Would run about 9 cycles to extract a
> lookup value, however, faster than my earlier suggestion.

As a compromise you could save about half that space (at the cost of a
few cycles) by first right-shifting, dividing by 5 using a half-size
LUT, and adding the LSB back into the remainder at the end.

Chris
Bob Axtell wrote:

>'8-bit BIN to DEC' converter.

I wasn't carefull, and I don't tell everything sorry.

In my variable there are only  00h-63h (0d-99d). And I want divide it by
10... I tought there is a very simple method, but I don't know it.

So, it seems the fastest method is the the LOOKUP table, it takes a few
cycles but more than 100 rows, the shortest (row) method is more than
100 cycles.

Balazs

___________________________________________________________________________
[origo] klikkbank lakossági számlacsomag havi 199 Ft-ért, bankkártya éves díj nélkül!
http://www.klikkbank.hu

On Thu, Feb 23, 2006 at 10:50:27AM +0000, Chris Emerson wrote:
> On Wed, Feb 22, 2006 at 10:41:34AM -0700, Bob Axtell wrote:
> > Spehro has it right- to use the code access capability of the
> > F877 allows the LUT to handle all of it, i.e. 2 bits for 100s, 4
> > bits for tens, 4-bits for ones places, a total of 10 bits. BUT, it uses
> > over 260 code words. Would run about 9 cycles to extract a
> > lookup value, however, faster than my earlier suggestion.
>
> As a compromise you could save about half that space (at the cost of a
> few cycles) by first right-shifting, dividing by 5 using a half-size
> LUT, and adding the LSB back into the remainder at the end.

I didn't see anything the original spec that indicated that compromise was
necessary. The OP threw out the word fastest. Space be damned! ;-)

BAJ

----- Original Message ----

{Quote hidden}

look at app note an544
www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011088

there are 4 ways described to do this without tables
fastest: Binary to BCD (8 bit) 10 words  62 cycles 1 byte scratch  unused

Peter van Hoof
Jáhn Balázs writes:
> In my variable there are only  00h-63h (0d-99d). And I want divide it by
> 10... I tought there is a very simple method, but I don't know it.
>
> So, it seems the fastest method is the the LOOKUP table, it takes a few
> cycles but more than 100 rows, the shortest (row) method is more than
> 100 cycles.

Here's an intermediate speed, and intermediate program store
use, version, between LUT versions and shift and loop versions in both
dimensions.

Since you know that the dividend is less than 100:

div10        movwf        rem        ; Assumes called with dividend in W, and that
movlw        D'80'        ; rem and quo.
subwf        rem,W        ; rem >= 80?
BNC        div10a        ; No (rem-80 borrowed)
movwf        rem        ; Remove 80 from rem (could have subwf rem,F)
bsf        quo,3        ; "add" 8 to quotient
div10a        movlw        D'40'
subwf        rem,W        ; What's left in rem >= 40?
BNC        div10b
movwf        rem
bsf        quo,2        ; "add" 4 to quotient
div10b        movlw        D'20'
subwf        rem,W
BNC        div10c
movwf        rem
bsf        quo,1
div10c        movlw        D'10'
subwf        rem,W
BNC        div10d
movwf        rem
bsf        quo,0
div10d                        ; Quotiend now in quo, remainder in rem
swapf        quo,W        ; One way to return is as BCD, quotient to high
iorwf        rem,W        ; nibble and the remainder in the low nibble.
return

The time for everything, including call and return, is max 32
cycles, min 28 cycles (28 plus the number of one bits in the quotiend).
If you don't want it as a subroutine, and you're happy to read your
results from rem and quo, and the dividend is already in a file register
that you're happy to use as rem, then the range, still including the
clearing of quo, is 21 to 25 cycles.

Except for the hack of creating a two digit BCD return value,
and interpreting the quotiend as binary, rathern than BCD, this
actually works for dividends up to 159.  If you want dividends up to
the whole unsigned byte (255), you could include a compare with 160
stage before the compare with 80 stage.  The extra stage adds 6 cycles
if it sets the bit and 5 if it doesn't.  If you want a BCD quotient,
then use 100 instead of 160 to work for dividends up to 199, or add
both a 200 and 100 section for dividends up to 255.

Bill
On Thu, 2006-02-23 at 06:48 -0800, Peter van Hoof wrote:

> look at app note an544
> http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011088
>
>
> there are 4 ways described to do this without tables
> fastest: Binary to BCD (8 bit) 10 words  62 cycles 1 byte scratch  unused

When Peter says that the fastest way to solve this problem without tables
takes 62 cycles, what he really means is that the fastest way an544 solves
this problem takes 62 cycles. Of course, there are faster non-table
solutions out there. One in particular takes 18 cycles.

SWAPF   bin, W                ;w  = A0*16+A1
ADDWF   bin, W                ;w  = A0+A1
ANDLW   00001111b        ;w  = A0+A1 % 16
SKPNDC                        ;if A0+A1 > 16
ADDLW  0x16                ;  w  += 16
SKPNDC                        ;if w % 16 > 10
ADDLW  0x06                ;  w  += 6
SKPDC                        ;if w < 10
ADDLW  -0x06                ;  w  -= 6

BTFSC   bin,4
ADDLW   0x16 - 1 + 0x6
SKPDC

BTFSC   bin, 5

BTFSC   bin, 6

; result is in W

And the algorithm is described:

Scott
Jáhn Balázs wrote:

{Quote hidden}

Exactly Correct, John.

--
Note: To protect our network,
attachments must be sent to
attachengineer.cotse.net .
http://beam.to/azengineer

Two straighforward approached conversions.
( both out of head, not tested though )

Might try to optimize it later :)

;        byte/10 : x is original number
;        y is result, w is remain

clrf        y
movfw        x

addlw        -D'160'        ;getting two bits of hundreds
rlf        y,F
btfss        y,0

rlf        y,F
btfss        y,0

rlf        y,F
btfss        y,0

rlf        y,F
btfss        y,0

rlf        y,F
btfss        y,0

;        hex2bcd : x is original number
;        y has hunds and tens, W has ones left

clrf        y
movfw        x

addlw        -D'200'        ;getting two bits of hundreds
rlf        y,F
btfss        y,0

rlf        y,F
btfss        y,0

addlw        -D'80'        ;getting four bits of tens
rlf        y,F
btfss        y,0

rlf        y,F
btfss        y,0

rlf        y,F
btfss        y,0

rlf        y,F
btfss        y,0

Code space can be squeezed as

clrf        y

movlw        const_1
call        convert

movlw        const_2
call        convert
;...

convert
subwf        x,F
rlf        y,F
btfss        y,0
return

WBR Dmitriy.

JÂhn BalÂzs wrote:
{Quote hidden}

>
> I want a 8 bit number divide by 10 (ten).
> I need the quotient and the remain.
>
> Which is the fastest ASM code for pic 16f877?

Multiply by 1/10

<www.piclist.com/cgi-bin/constdivmul.exe?Acc=ACC&Bits=8&endian=little
&Const=.1&ConstErr=0.5&Temp=TEMP&cpu=pic16>

; ACC = ACC * 0.1
; Temp = TEMP
; ACC size = 8 bits
; Error = 0.5 %
; Bytes order = little endian
; Round = no

; ALGORITHM:
; Clear accumulator
; Add input / 16 to accumulator
; Add input / 32 to accumulator
; Add input / 256 to accumulator
; Add input / 512 to accumulator
; Move accumulator to result
;
; Approximated constant: 0.0996094, Error: 0.390625 %

;     Input: ACC0, 8 bits
;    Output: ACC0, 5 bits
; Code size: 17 instructions

cblock
ACC0
endc

;copy accumulator to temporary
movf    ACC0, w

;shift accumulator right 1 times
clrc
rrf     ACC0, f

;shift accumulator right 3 times
rrf     ACC0, f
clrc
rrf     ACC0, f
clrc
rrf     ACC0, f

;shift accumulator right 1 times
rrf     ACC0, f

;shift accumulator right 4 times
swapf   ACC0, w
andlw   0x0F
movwf   ACC0
skpnc
bsf     ACC0, 4

; Generated by http://www.piclist.com/cgi-bin/constdivmul.exe (1-May-2002 version)
; Thu Feb 23 18:29:05 2006 GMT

<www.piclist.org/techref/postbot.asp?by=time&id=piclist\1996\06\11\16
0057a>

http://www.piclist.com/techref/microchip/math/div/index.htm

---
jamesnewtonpiclist.com  1-619-652-0593 phone
http://www.piclist.com/member/JMN-EFP-786
PIC/PICList FAQ: http://www.piclist.com

On Thu, 23 Feb 2006, Chris Emerson wrote:

{Quote hidden}

N/10 = N/8 - N/32 + N/128 ( - N/640 ... )

The terms before the parentheses are enough for 8 bits.

Peter
part 1 967 bytes content-type:TEXT/PLAIN; CHARSET=X-UNKNOWN; FORMAT=flowed (decoded quoted-printable)

On Thu, 23 Feb 2006, [ISO-8859-2] Jáhn Balázs wrote:

> Bob Axtell wrote:
>
>> Another way to ask this question is to ask for an
>> '8-bit BIN to DEC' converter.
>
> I wasn't carefull, and I don't tell everything sorry.
>
> In my variable there are only  00h-63h (0d-99d). And I want divide it by
> 10... I tought there is a very simple method, but I don't know it.

N/10 = N/8 - N/32 + N/128

; untested code, isochronous, 13 clocks (11 if FN_GT_127 is
; undefined)
; input is Fn, output is Fy, Fn emerges divided by four
swapf        Fn,w        ; W = Fn/16
andlw        0x0F
movwf        Fy        ; Fy = N/16
rrf        Fy,f        ; Fy = N/32
comf        Fy,f
incf        Fy,f        ; Fy = - N/32
#ifdef FN_GT_127
btfsc        Fn,7
incf        Fy,f        ; Fy = - Fn/32 + Fn/128
#endif
rrf        Fn,f
rrf        Fn,f
rrf        Fn,w
andlw        0x1F        ; W = Fn/8
addwf        Fy,f        ; Fy = Fn/8 - Fn/32 + Fn/128

I am sure that one of the geniuses will optimize this.

Peter

part 2 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

James Newton, Host wrote:
>>I want a 8 bit number divide by 10 (ten).
>>I need the quotient and the remain.
>>
>>Which is the fastest ASM code for pic 16f877?
>
>
> Multiply by 1/10

<snip>

What about the remainder? Peter's solution has a similar problem.

Scott
On Feb 23, 2006, at 12:41 PM, Peter wrote:
>
> N/10 = N/8 - N/32 + N/128
>
I believe the original posting said that he needed the remainder
as well...

BillW
At 01:55 PM 2/23/2006 -0800, you wrote:
>James Newton, Host wrote:
> >>I want a 8 bit number divide by 10 (ten).
> >>I need the quotient and the remain.
> >>
> >>Which is the fastest ASM code for pic 16f877?
> >
> >
> > Multiply by 1/10
>
><snip>
>
>What about the remainder? Peter's solution has a similar problem.
>
>Scott

Scott's method gives the exact quotient and remainder packed in a single byte
in just 18 cycles. I suspect that's unbeatable (without a LUT). And it is
just a special case of his routine in the piclist source code library.

Best regards,

Spehro Pefhany --"it's the network..."            "The Journey is the reward"
speffinterlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com
->> Inexpensive test equipment & parts http://search.ebay.com/_W0QQsassZspeff

Scott Dattalo  Sent: 2006 Feb 23, Thu 13:55
>
> James Newton, Host wrote:
> >>I want a 8 bit number divide by 10 (ten).
> >>I need the quotient and the remain.
> >>
> >>Which is the fastest ASM code for pic 16f877?
> >
> >
> > Multiply by 1/10
>
> <snip>
>
> What about the remainder? Peter's solution has a similar problem.
>

Oops. Yep, the OP did say remainder was needed. Looks like your solution is
optimal. The only problem with it is that I can't understand how it works.
<grin> The comments stop around the point where the comments are really
starting to get necessary...

Just for the record, here is Scott's solution again:

> {Original Message removed}
Scott Dattalo wrote

>Of course, there are faster non-table
>solutions out there. One in particular takes 18 cycles.

Scott, it's perfect for me, thank you!

And thank you for everybody who "sad" any tip for me. :-)

Thanks

Balazs

___________________________________________________________________________
[origo] klikkbank lakossági számlacsomag havi 199 Ft-ért, bankkártya éves díj nélkül!
http://www.klikkbank.hu

On Thu, 23 Feb 2006, Scott Dattalo wrote:

> What about the remainder? Peter's solution has a similar problem.

I missed that requirement ... and your excellent solution (I see
digests).

Peter
Hi Scott.

I believe input value range for hex is limited to 0..99d for procedure
shown in your post and there is straight coded solution with 18 clocks
as well for that case ( I'm getting so lazy I guess .. :)

;       hex2bcd : x is original number
;       y has tens, W has ones left

movfw   x
clrf    y        ;we can even reuse x here..

addlw   -D'80'  ;getting four bits of tens
rlf     y,F
btfss   y,0

rlf     y,F
btfss   y,0

rlf     y,F
btfss   y,0

rlf     y,F
btfss   y,0

>From the other hand if we scale it up ( extra 8 clocks/words see the
previous post ) to get hundreds as well converted it will be 2 clocks
/words shorter than procedure discussed at :

WBR Dmitry.

Scott Dattalo wrote:
{Quote hidden}

On Sat, 2006-02-25 at 04:28 -0500, Dmitriy Kiryashov wrote:
> Hi Scott.
>
> I believe input value range for hex is limited to 0..99d for procedure
> shown in your post and there is straight coded solution with 18 clocks
> as well for that case ( I'm getting so lazy I guess .. :)

Yes Dmitriy, you must be getting lazy. Why can't you squeeze this down to
12 instructions? :)

I like your solution better than mine, because it's a) shorter and b)
easier to understand!

Scott

Hi Scott.

16 perhaps ? :)

Scott Dattalo wrote:
{Quote hidden}

With input value in range 00..63h(99.) I don't see the reason
why second skpndc check is required ? When dc flag is generated
in first instance maximum resulting value is 0x5 + 0xF = 0x14
I think these two lines can be safely omitted.

WBR Dmitry.

PS.

And final steps 0x40 -> 0x60 and 0x20 -> 0x30
are begging for some optimization as well. :)

{Quote hidden}

> -
Hi folks.

Scott inspired me how to shrink it down to 14 clocks/words :)
My intuition says it would be quite difficult to squize it down
to golden number of 12 :) ( perhaps some other time .. ) so I'm
leaving it the way it is now.

;input value <bin> are in range 0 .. 99d, result in W.

rrf     bin,W   ;0x40 -> 0x60 , 0x20 -> 0x30
andlw   0x30
movwf   temp

swapf   bin,W
btfsc   bin,4
addlw  5      ;max <= 5 + 5
andlw   0x0F

skpndc

skpdc

WBR Dmitry.

Scott Dattalo wrote:
{Quote hidden}

> -

More... (looser matching)
- Last day of these posts
- In 2006 , 2007 only
- Today
- New search...