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

faster bit_set and bit_clear?

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








faster bit_set and bit_clear?
PostPosted: Tue Sep 29, 2009 10:09 am     Reply with quote

Hi,
Is there a faster way to do this:

Code:
   for (i=12;i;) {
      mcp3201_clk = 1;
      i--;
      if (mcp3201_dout) bit_set(read,i); else bit_clear(read,i);
      mcp3201_clk = 0;
   }


I want to keep the timing the same for each "read", hence why there is a bit_clear instead of a read = 0 at the beginning. That one threw me for a while!
It's still quite slow, even at 40MHz. mcp3201_clk, dout are #bit'ed to the port address.
Any ideas much appreciated.
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Sep 29, 2009 10:41 am     Reply with quote

I not sure if its applicable but a while back we were trying to make the
fastest bit-reverser function. I felt one of the best ways was simple test and
set for each combination. Any type of loop seemed to slow it down.
Can this be applied in your case?
http://www.ccsinfo.com/forum/viewtopic.php?t=23364&highlight=reverse+bits
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Tue Sep 29, 2009 3:08 pm     Reply with quote

A computed bit-set operation is very slow.

i.e. find a way to make
bit_set(read,i);

become

bit_set(read,3);

Why are you doing this instead of setting/clearing the bottom bit of the variable and then rotating it? Or actually, rotating first and then setting/clearing, because the last bit you'll see is bit 0 and you don't want any rotation after that. Also, start with the variable 'read' set to zero, so there's no need to clear any bit.

Something like (if I'm getting it right):
Code:


  read = 0;
  for (i = 12; i; i--)
  {
    mcp3201_clk = 1;
    read <<= 1;
    if (mcp3201_dout)
      bit_set(read, 0);
    mcp3201_clk = 0;
  }


And yes, if you want to be as fast as possible, don't use a loop at all. Just a sequence of 12 blips to the clock line interspersed with tests of the data line and setting bits.

Note that testing a bit and setting a different bit if it's high (or low) compiles to only 2 assembly instructions.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

another way
PostPosted: Tue Sep 29, 2009 6:59 pm     Reply with quote

This is a core fragment of how I read that type of device - even though it was coded for a 16 BIT TI/BB ADC:
Code:

//    ADS8320,25,26   +16 bits unipolar    A/D
//    ADS8317 is +/- 15 bits
// #define ADCclock  PIN_E2
// #define ADCstart  PIN_E0
// #define ADCdata   PIN_E1

int16 adcresult;
  for (i=0;i<15;i++){
     output_high(ADCclock);  // now after rising edge
     ADC_result |= input(ADCdata); //   OR input pin with 16bit int
     output_low(ADCclock);   // produce a new lo-to-high clock
     ADC_result<<1;         // and shift that bit allong toward MSB
  }
// get the last LSB but NO shift
     output_high(ADCclock);
     ADC_result |= input(ADCdata); //   OR input pin with 16bit int
     output_low(ADCclock);


There is obviously other before and after stuff
but this gets to your question I think.
Guest








PostPosted: Wed Sep 30, 2009 7:32 am     Reply with quote

Thanks. Interesting reading. I will investigate your ideas. I will also time the options ideas, the shift idea is elegant.

John, I used to set read = 0 like you suggest but spent rather a long time racking my brain as to why my program slowed down the larger the voltage presented to the ADC! Finally figured that set_bit takes quite a bit of time and the more "1"'s in the data stream the slower the procedure took! I really want a nice constant time no matter what the contents of the data.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Wed Sep 30, 2009 7:45 am     Reply with quote

i forgot to mention - you of course need to do

ADCresult=0;

before starting the read .

also - the way it is structured - ADC clock has a decently even duty
cycle based on the disitribution of the actual instructions.
Guest








PostPosted: Wed Sep 30, 2009 7:57 am     Reply with quote

Code:
....................    for (i=0;i<11;i++) {
033C:  CLRF   64
033E:  MOVF   64,W
0340:  SUBLW  0A
0342:  BNC   0356
....................       mcp3201_clk = 1;
0344:  BSF    F82.3
....................       delay_cycles(1);
0346:  NOP   
....................       read |= mcp3201_dout;
0348:  MOVLW  00
034A:  BTFSC  F82.4
034C:  MOVLW  01
034E:  IORWF  4D,F
....................       mcp3201_clk = 0;
0350:  BCF    F82.3
....................       read<<1;
....................    }


The compiler warns that "Code has no effect" for the read<<1 line and indeed no code is generated for it? Strange? PIC18F2520 compiled with 4.099. Any ideas?
Guest








PostPosted: Wed Sep 30, 2009 8:02 am     Reply with quote

no assignment!

Code:
read = read << 1;
Guest








PostPosted: Wed Sep 30, 2009 8:16 am     Reply with quote

I've moved the shift to get rid of the delay_cycles(1), needed as I am not using the compilers auto TRIS function.

Code:
....................    for (i=0;i<12;i++) {
033C:  CLRF   64
033E:  MOVF   64,W
0340:  SUBLW  0B
0342:  BNC   035A
....................       mcp3201_clk = 1;
0344:  BSF    F82.3
....................       read<<=1;
0346:  BCF    FD8.0
0348:  RLCF   4D,F
034A:  RLCF   4E,F
....................       read |= mcp3201_dout;
034C:  MOVLW  00
034E:  BTFSC  F82.4
0350:  MOVLW  01
0352:  IORWF  4D,F
....................       mcp3201_clk = 0;
0354:  BCF    F82.3
....................    }


The advantage of this is all 12 bits can be clocked into read within the for loop (the down side is the first shift is wasted).

It looks like if I get rid of the for loop completely and make the code "messy" I will save 4 instructions each bit read!
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