which bit is set in a byte?

Dear Forum,

There's a function "bit()"; computing me the value of a specified bit, for example bit(6) = 64.

How can I do this the other way round?

In my case I have a byte telling me which one of 8 inputs caused an interrupt, so each time only one bit is set.

I'd like to get a number from 0 to 7 telling me which input has caused the interrupt I can loop through all bits, but is there a faster and simpler solution?

funct(16) = 4
funct(32) = 5
funct(64) = 6

regards,
Martin

Use a mask on your byte, examine bit 1 to see if it is set.
Using the index in a 'for' loop to see if the bit is set.
If not, shift the byte to the right, repeat.

.

I'd like to get a number from 0 to 7 telling me which input has caused the interrupt

How do you subsequently use the numbers 0 to 7 ?

what is this? PCINT on an AVR?

How are you getting this data? Presumably you're reading off the PINx register of the corresponding port; you need to handle the case where multiple pins are asserted, and the case where you get an interrupt because the value on the pin has returned to it's idle value... Your assumption that only one bit would be set is invalid unless the hardware somehow restricts which pins can be asserted simultaneously.

I read from an MCP23017 with a Mega 2560.

INTFA/INTFB is the interrupt flag register.

INTCAPA/INTCAPB contains the current state / captured values

Oh, then that's easy, just loop through the bits as suggested above.

The inverse function of f(x) = 2^x is log(x)/log(2)

See this:

#include <math.h>

void setup() {
byte t[] = {1, 2, 4, 8, 16, 32, 64, 128};
Serial.begin(9600);
for (byte i = 0 ; i < 8 ; i++)
  Serial.println(int(log(t[i])/0.6931));
}

void loop() {
}

Jacques

thanks to everyone!

this is what I was looking for: number = log(fnMCP23017Read(INFTFA))/log(2);

school math is long time ago... :frowning:

looping through 8 bits might be almost as fast...

A binary search would be quicker, assuming only one bit is set.

abalone:
thanks to everyone!

this is what I was looking for: number = log(fnMCP23017Read(INFTFA))/log(2);

school math is long time ago... :frowning:

looping through 8 bits might be almost as fast...

Checking 8 bits is going to be much faster than performing floating-point logarithm and division operations.

Checking 8 bits is going to be much faster than performing floating-point logarithm and division operations.

I have to agree on that.

Jacques

C has a built-in function for this: __builtin_clz() (count leading zeros ); it should use special instructions if the particular CPU happens to have them (ARM CM3 has a "clz" instruction (by CM0 doesn't!)), or do the loop (or perhaps some other "better" algorithm) if not. There are similar built-in functions for finding the first one from the LSB.