Bit Masking

I may be making an idiotic mistake here but please bear with me and i’ll try to give as much info as possible
The short version is I can’t figure out bitmasking

When called, a function called REG_KEYINPUT returns a value which by default is 0x3FF, the keys are defined as

KEY_A = (1<<0),	/*!< keypad A button */
KEY_B = (1<<1),	/*!< keypad B button */

when button A is pressed REG_KEYINPUT returns 0x3FE
when button B is pressed REG_KEYINPUT returns 0x3FD
when button A+B is pressed REG_KEYINPUT returns 0x3FC
nothing wrong there

Now this is the bit i dont understand

	scanKeys();
	iprintf("\x1b[19;0HREG_KEYINPUT = %X ",REG_KEYINPUT);
	iprintf("\x1b[18;0H%X ",KEY_A);
				
switch (REG_KEYINPUT)
	{
		case 0x3fe: iprintf("\x1b[5;0HA Pressed      ");
		break;
		case KEY_B: iprintf("\x1b[5;0HB Pressed      ");
		break;		
		default: iprintf("\x1b[5;0HNothing Pressed ");
		break;
	}

The first case works because i’ve given it a value for A, but the second case doesn’t work, probably becasue it’s defined as being bit 1, what i’de like is to able to say is

case KEY_B: do something

but don’t know how to do it without lots of if statements which isn’t ideal.
I hope this makes some sense

Thanks in advance

You can’t do it with a switch because that looks for discrete values.

More like:

if (REG_KEYINPUT & KEY_A)
  {
  // blah
  }


if (REG_KEYINPUT & KEY_B)
  {
  // blah
  }

Since they are not mutually exclusive, you don’t use “else”. And you don’t use “switch”.

Try this:

switch ((~REG_KEYINPUT) & (KEY_A | KEY_B)) {
  case KEY_A: //do something
  case KEY_B: //do something else
  case (KEY_A | KEY_B): //then something else
}

KEY_A and KEY_B need to be defined.

Thanks Nick, thats the way i was doing it, there are 10 keys in total, thats alot of if's, i though switch would be more efficient.

@dhenry

switch ((~REG_KEYINPUT) & (KEY_A | KEY_B)) {
  case KEY_A: //do something
  case KEY_B: //do something else
  case (KEY_A | KEY_B): //then something else
}

Didn't quite have the desired action but it did make me realise what i was doing wrong

This does work, for single keypresses only for now

switch (0x3FF - REG_KEYINPUT)
    {
        case KEY_A: iprintf("\x1b[5;0HA Pressed      ");
        break;
        case KEY_B: iprintf("\x1b[5;0HB Pressed      ");
        break;          
        default: iprintf("\x1b[5;0HNothing Pressed ");
        break;
    }

I realised i should be taking the returned value from the default value to give the key pressed

(0x3FF - REG_KEYINPUT)

Thanks again

If you use dhenry's approach be prepared for a lot of typing:

case (KEY_A | KEY_B): //then something else
case (KEY_A | KEY_C): //then something else
case (KEY_A | KEY_D): //blah
case (KEY_A | KEY_E): //blah
case (KEY_A | KEY_F): //blah

case (KEY_A | KEY_B | KEY_C): //blah
case (KEY_A | KEY_C | KEY_D): //blah
case (KEY_A | KEY_D | KEY_E): //blah
case (KEY_A | KEY_E | KEY_F): //blah
case (KEY_A | KEY_F | KEY_G): //blah

And so on. It doesn't lend itself to this situation.

P18F4550: there are 10 keys in total, thats alot of if's ...

Ten in fact.

switch (0x3FF - REG_KEYINPUT)

That approach is less generic, as it requires that REG_KEYINPUT has to return something in its last 10 digits. The approach I gave you allows the returned bits to be anywhere (in REG_KEYINPUT).

And it is also quite easy to detect key changes.

yes i see your point, but for now there are ten keys and no multiple combinations are required, but i'll try it both ways using IF statements as well

What I typically do in this case is something like this:

#define KEY1  (1<<0)
#define KEY2  (1<<1)
...
#defiine KEYs (KEY1 | KEY2 | ...)

  switch ((~key_read()) & KEYs) {
    case KEY1: //do something
    case KEY2: //do something else
  }
...

It is easier to read and to maintain, but it is slower - which usually isn’t important for human interactions.

As long as you don't need to handle multiple keys being depressed simultaneously, I don't see why you can't just define a const for the return value corresponding to each key pressed in isolation and put those in a switch statement, pretty much as you were doing.

If you want to handle multiple keys then I would use a loop, bitshift and bitmask to test whether each bit was set and call a function to handle that keypress; in that function you could use a switch (key number) to determine which of the buttons was being dealt with.