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 support@ccsinfo.com

What is a simple way to verify only one bit in a byte is set
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rwyoung



Joined: 12 Nov 2003
Posts: 563
Location: Lawrence, KS USA

View user's profile Send private message Send e-mail

PostPosted: Tue Feb 17, 2004 11:26 am     Reply with quote

Somebody check me on this...

Just for the heck of it I re-did the algorithm I posted above for 8 bit data:

Code:
unsigned int8 bitcount1(unsigned int8 c)
{
  c = (c & 0x55) + ((c >> 1) & 0x55);
  c = (c & 0x33) + ((c >> 2) & 0x33);
  c = (c & 0x0f)  + ((c >> 4) & 0x0f);
  return (c);
}


This does work but with my copy of PCM (V3.184) it complies to 36 instructions including the function calling overhead. As "straight line" code it was 31 instructions, no loops, no jumps. Should all be single cycle instructions.

Code:
....................   c = (c & 0x55) + ((c >> 1) & 0x55);
025C:  MOVF   21,W
025D:  ANDLW  55
025E:  MOVWF  28
025F:  BCF    03.0
0260:  RRF    21,W
0261:  ANDLW  55
0262:  ADDWF  28,W
0263:  MOVWF  21
....................   c = (c & 0x33) + ((c >> 2) & 0x33);
0264:  MOVF   21,W
0265:  ANDLW  33
0266:  MOVWF  28
0267:  RRF    21,W
0268:  MOVWF  77
0269:  RRF    77,F
026A:  MOVLW  3F
026B:  ANDWF  77,F
026C:  MOVF   77,W
026D:  ANDLW  33
026E:  ADDWF  28,W
026F:  MOVWF  21
....................   c = (c & 0x0f)  + ((c >> 4) & 0x0f);
0270:  MOVF   21,W
0271:  ANDLW  0F
0272:  MOVWF  28
0273:  SWAPF  21,W
0274:  MOVWF  77
0275:  MOVLW  0F
0276:  ANDWF  77,F
0277:  MOVF   77,W
0278:  ANDLW  0F
0279:  ADDWF  28,W
027A:  MOVWF  21


Neutone's sequence of if(bit_test) statements will probably run faster but it will vary with number of increments. Mine will always run same speed.

I think Neutone's is a better general solution for a microcontroller that has good bit test operations like the PIC. Still it is interesting to see how just a bunch of ANDs, SHIFTS and ADDS can do the same thing.
_________________
Rob Young
The Screw-Up Fairy may just visit you but he has crashed on my couch for the last month!
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Tue Feb 17, 2004 1:18 pm     Reply with quote

rwyoung wrote:
Somebody check me on this...
Neutone's sequence of if(bit_test) statements will probably run faster but it will vary with number of increments. Mine will always run same speed.


I think the execution time is going to be fixed for the code I posted. The IF statements take 1 cycle when they don't jump and 2 when they do jump. Thats my understanding at least. I looked into doing a parity check like this and found that a better solution existed using shifts and XOR's. I found this method interesting and though somethinglike it might work for me now.

Code:

/***********************************************************
*    Solve for parity bit on USART 2                       *
***********************************************************/
/*#inline
Void Comm2_Parity(Int8 x)                                   // Solves parity for USART 2
{  if(TX9_2)                                                 // Only solve parity if it will be used
   {  #asm
      bcf TX9D2                                             // Start by assuming even parity
      btfss Comm2_Odd                                       // Make a test for odd parity
      bsf TX9D2                                             // Set odd parity
      swapf x, W                                            // http://www.mindhertz.com/Parity.php
      xorwf x, F                                            // http://www.mindhertz.com/Parity.php
      rrf x, W                                              // http://www.mindhertz.com/Parity.php
      xorwf x, F                                            // http://www.mindhertz.com/Parity.php
      btfsc x, 2                                            // http://www.mindhertz.com/Parity.php
      incf x, F                                             // http://www.mindhertz.com/Parity.php
      btfsc x, 0                                            // If bit 0 is
      btg TX9D2                                             // Toggle
      #endasm
   }
}*/


Last edited by Neutone on Tue Feb 17, 2004 3:34 pm; edited 1 time in total
rwyoung



Joined: 12 Nov 2003
Posts: 563
Location: Lawrence, KS USA

View user's profile Send private message Send e-mail

PostPosted: Tue Feb 17, 2004 1:26 pm     Reply with quote

In general, doesn't parity just tell you if there is an odd or even number of 1's (or 0's)? The simple XOR & shift parity test doesn't tell you how many 1's.

Anyway still think your 8 if-test_bit version is the most efficient when you weigh code space vs speed vs readability and you want to know exactly how many 1's are in an 8 bit word.

The book "Hacker's Delight" does have some spiffy tricks for doing other things like rounding up or down to the next power of 2 (good for zero-padded FFT) and quick bit-reversal (again, good for FFT stuff). Not the cheapest book I've ever bought but a fun read and useful stuff.
_________________
Rob Young
The Screw-Up Fairy may just visit you but he has crashed on my couch for the last month!
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Tue Feb 17, 2004 3:31 pm     Reply with quote

An improved binary search to see if one and only one bit is set in a byte b

if(b==0) goto err; /// if zero error ( no bit is set) if both the left and right nibble are non zero err
if(b>15 ) {
if (swap(b)>15) goto err; // both left and right nibbles have bits set
}
///one or more bits are in right most 4 bits either way 0000 xxxx

//now test for right 2bits left 2bits of rightmost nibble
b=b<<2; // first get it into this shape 00xx xx00

if (b >15){
if(swap(b)>15) goto err; // both left and right nibbles have bits set
}
///one or two bits are in right most 4 bits either 0000 xx00 or 0000 00xx
/// xx cannot be 11


if ((b==12) || (b==3) ) goto err;
/// its a winner only one bit was set in the byte
err:
/// it has none or more than one bit set
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
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