CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Divide by 12

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

Divide by 12
PostPosted: Tue Jun 28, 2005 8:36 pm     Reply with quote

Hi all,

I need to divide a long by 12 inside a fast int handler, so any scratch register usage needs to be avoided.

Does anyone knows about a clever way to do this?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 29, 2005 1:05 am     Reply with quote

I don't about a clever way, but you could make your divide-by-12
routine with ASM code. Then create some global variables that
are used only by that code. (You can use C variables in code).
In this way, you avoid using the CCS library routines and their
scratch variables.

You can get the ASM code from the CCS library by compiling
a test program with an int16 variable divided by 12. You can
see the CCS code by commenting out the #nolist statement
at the top of your PIC's .H file.

Another source for ASM division code is on this page:
http://www.piclist.com/cgi-bin/constdivmul.exe
To generate code for Divide-by-12, enter .08333 into the box
for Multiply by Constant. For the Input Register Size, enter 16
because that's your variable size. If you want reasonable
accuracy the generated code can get fairly long. Maybe
it's best to use the CCS code.
Ttelmah
Guest







PostPosted: Wed Jun 29, 2005 2:42 am     Reply with quote

It would help if you said 'what' you need to divide by twelve. Answers will differ for an int, int16 etc..
Remember that using a fast handler, does not mean that you cannot use scratch registers, it just means that _you_ have to save these yourself.
You can get a pretty close approximation to /12, by taking the value >>4, plus the value >>5. Not 'exact', but for low numbers in the integer range, it may be 'close enough'...

Best Wishes
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Wed Jun 29, 2005 9:46 am     Reply with quote

Quote:
It would help if you said 'what' you need to divide by twelve. Answers will differ for an int, int16 etc..


It is there... "I need to divide a LONG by 12".

When I said that it shouldn't use the scratch registers it was because the way I write the code, FAST means fast... so saving and restoring must be avoided if possible.

I would place the division in main, but there is not enough time to run it right after the return from the interrupt. There isn't any priority control over the tasks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 29, 2005 5:26 pm     Reply with quote

I don't know if it can be done quickly with 16-bit variables on an 8-bit PIC.
Here's a page with some C code that consists of shifts and adds.
http://www.hackersdelight.org/divcMore.pdf
I converted the Divide-by-12 code to a CCS test program.
With PCH vs. 3.188, the routine takes about 100 instructions.

Code:
#include <18F452.h>
#fuses XT, WDT, NOPROTECT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

int16 divu12(int16 n)
{
int16 q, r;
q = (n >> 1) + (n >> 3);
q = q + (q >> 4);
q = q + (q >> 8);
q = q + (q >> 16);
q = q >> 3;
r = n - q*12;
return q + ((r + 4) >> 4);
// return q + (r > 11);
}

//===========================================
void main(void)
{
int16 result;

result = divu12(65535);

printf("%lu\n\r", result);

while(1);
}
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Wed Jun 29, 2005 6:14 pm     Reply with quote

Thank you all for the time and effort to help me.

It seems that result = (int16>>4) + (int16>>5) - (int16>>7) is close enough for the application.

It just need some work so it won't use any scratch register.

Something like:

Code:
   temp1 = var_to_divide>>4;
   temp2  = temp1>>1;

   result   = temp1 + temp2;
   temp1  = temp2>>2;
   result -= temp1;
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group