Go Down

Topic: Map button matrix to integers (Read 753 times) previous topic - next topic

a.mlw.walker

Hi Everyone, I have a button matrix - 64 buttons, below is some data from pressing the buttons down. I need to turn each buttons matrix position into an integer.
The first value is the integer I need to convert to, the second is the row and the third is the column. I have sampled just  a section of the button matrix presses.
Please can someone help me with the algorithm to map to the integer. I cant get something that will work for all instances:

Code: [Select]

I   C       R
----------------
48: 0x04 : 0x08
49: 0x04 : 0x04
50: 0x04 : 0x02
51: 0x04 : 0x01

52: 0x05 : 0x80
53: 0x05 : 0x40
54: 0x05 : 0x20
55: 0x05 : 0x10
56: 0x05 : 0x08
57: 0x05 : 0x04
58: 0x05 : 0x02
59: 0x05 : 0x01

60: 0x06 : 0x80
61: 0x06 : 0x40
62: 0x06 : 0x20
63: 0x06 : 0x10
64: 0x06 : 0x08
65: 0x06 : 0x04
66: 0x06 : 0x02
67: 0x06 : 0x01

68: 0x07 : 0x80
69: 0x07 : 0x40
70: 0x07 : 0x20
71: 0x07 : 0x10
72: 0x07 : 0x08

Thanks

HazardsMind

My GitHub:
https://github.com/AndrewMascolo?tab=repositories

a.mlw.walker

The problem with using the keypad library is I have to trial and error what row and what column values are what button pressed, and then store it in a map. From my test data there is clearly a pattern, so i would rather the algorithm that maps from one to the other and would like some help figuring it out, if anyone can help
Thanks

a.mlw.walker

So i was successfuly in mapping the posiiton in the array to the midi. now I am interested in optimizing polling the key matrix. Please can anyone suggest improvements to the following polling algorithm:

Code: [Select]

void KeyMatrix::pollKeys() {
uint8_t cRows = 0, cCols = 0;
for (uint8_t maskRows = 1; maskRows != 0; maskRows += maskRows) {
PORTK = ~maskRows; //low one col with all others pull-up
_delay_us(10); //after setting the state of a pin there may need to be a delay
if (~PINH != 0) {
for (uint8_t maskCols = 1; maskCols != 0; maskCols += maskCols) {
if (~PINH & maskCols) {
ATOMIC_BLOCK(ATOMIC_FORCEON)
{
button[cRows][cCols].time = flagmS;
}
button[cRows][cCols].isPressed = true;
} else
button[cRows][cCols].isPressed = false;
if (cRows > 4){
sendNote(cRows, cCols);
}

cCols++;
}
cCols = 0;
}
cRows++;
}
}


Thanks

HazardsMind

Both
Quote
for (uint8_t maskCols = 1; maskCols != 0; maskCols += maskCols) {

and
Quote
for (uint8_t maskRows = 1; maskRows != 0; maskRows += maskRows) {

Make no sense.

maskCols / Rows will never be nor get to zero to exit the for loops, because your starting at 1 and incrementing. You could just have easily wrote "for(;;)"

How does this work?
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

mixania

How can you map readings of buttons to ints if they are boolean readings? They only have on/off states. However if you are talking about mapping them in the sense of their position, then consider using a multiple dimension array.

http://arduino.cc/forum/index.php?topic=44228.0

Or here is an example:

Code: [Select]

array [x][y] {
boolean read = digitalRead(array [x][y]);
}

Arduino Uno R3
Mac OSX Lion

HazardsMind

#6
Mar 18, 2013, 02:19 pm Last Edit: Mar 18, 2013, 03:58 pm by HazardsMind Reason: 1
Code: [Select]
array [x][y] {
boolean read = digitalRead(array [x][y]);
}

That does not make sense either. You cannot read 2 pins at the sametime with just one digital read. I don't know, maybe we finally can, and I just didn't get the memo.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

a.mlw.walker

Firstly you can read two pins at the same time, infact you can read 8 if you read the whole port:

uint8_t a = PINB;

would read the whole of PINB into a.

Secondly:
Quote

Both
Quote
for (uint8_t maskCols = 1; maskCols != 0; maskCols += maskCols) {
and
Quote
for (uint8_t maskRows = 1; maskRows != 0; maskRows += maskRows) {
Make no sense.

maskCols / Rows will never be nor get to zero to exit the for loops, because your starting at 1 and incrementing. You could just have easily wrote "for(;"

How does this work?

Is also not true.
When you bit shift a mask so the left so that the one goes off the end, what value do you think the mask is equal to?
Yes! 0.
i.e
take the following:
value = 0b00000001;
If I shift:
value = (1 << 7);
I get 0b10000000;
Shift it one more value to the left and now value = 0.

Quote

How can you map readings of buttons to ints if they are boolean readings?

Very easily. A boolean value firstly is just a 1 or a 0, not an on/off. This is just a way for us to think about it - like true false. It just so happens that it can be stored in 1 bit. That doesnt stop an integer being able to store it. You may need a cast but so what?
Secondly, I never said anything about an int.
Infact if I had thoguth it was necessary to the problem I would have displayed that button is a struct:
Code: [Select]

struct data {
unsigned int time;
bool isPressed;
bool wasPressed;
uint8_t midiNote;
};

see bools...

Anyway, I think I cracked it, so thank you for the efforts.

mixania


That does not make sense either. You cannot read 2 pins at the sametime with just one digital read. I don't know, maybe we finally can, and I just didn't get the memo.


Maybee, we both didn't get the memo :D But what I meant in my code is reading the value of a button that is on a specific X Y coordinate. A 2D array must be used for this to work.
Arduino Uno R3
Mac OSX Lion

HazardsMind

Quote
You cannot read 2 pins at the sametime with just one digital read
Direct port manipulation is different, that I know you can read multiple pins, but with a regular Digital/Analog read, you can't.

You should probably post your full code.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

a.mlw.walker

#10
Mar 20, 2013, 12:12 pm Last Edit: Mar 20, 2013, 12:18 pm by a.mlw.walker Reason: 1
OK.
This is my class (.cpp):
Code: [Select]

KeyMatrix::KeyMatrix(Serial *serial, Midi *midi) {
this->serial = serial;
this->serial->printf("key matrix setup\n");
this->midi = midi;

//Prepare the rows for reading
DDRH = 0b00000000; //All Ts are inputs
PORTH = 0b11111111; //All pullups enabled
//read from PINH

DDRK = 0b11111111;//MK and BR are outputs - one is pulled low at a given time.
PORTK = 0b11111111; //Set them high for now. We can pull one low when scanning.
for (uint8_t i = 0; i < 8; i++) {
for (uint8_t j = 0; j < 7; j++) {
button[i][j].isPressed = false;
button[i][j].wasPressed = false;
button[i][j].midiNote = 12 + i*8 + (7-log(j)/log(2));
}
}
}

void KeyMatrix::pollKeys() {
uint8_t cRows = 0, cCols = 0;
for (uint8_t maskRows = 1; maskRows != 0; maskRows += maskRows) {
PORTK = ~maskRows; //low one col with all others pull-up
_delay_us(10); //after setting the state of a pin there may need to be a delay
if (~PINH != 0) {
for (uint8_t maskCols = 1; maskCols != 0; maskCols += maskCols) {
if (~PINH & maskCols) {
ATOMIC_BLOCK(ATOMIC_FORCEON)
{
button[cRows][cCols].time = flagmS;
}
button[cRows][cCols].isPressed = true;
} else {
button[cRows][cCols].isPressed = false;
}
if (cRows >= 4 && cCols != 0){
sendNote(cRows, cCols);
}

cCols++;
}
cCols = 0;
}
cRows++;
}
}

void KeyMatrix::sendNote(uint8_t cRows, uint8_t cCols){

if (button[cRows][cCols].isPressed != button[cRows][cCols].wasPressed) {
//needs to be changed for midi output once debugging has confirmed the correct thing is occuring:
serial->printf("i: %d, j: %d. Time: %u, Note: %u\n",cRows, cCols, (button[cRows][cCols].time - button[cRows-4][cCols].time), button[cRows][cCols].midiNote);//output the midi note & add to arpeggiator array?
button[cRows][cCols].wasPressed = button[cRows][cCols].isPressed;
}
}

In terms of compilation everything works. I dont have access to the header file from where I am, but the struct that you need the details of is in my previous post.
This line:
Code: [Select]

button[i][j].midiNote = 12 + i*8 + (7-log(j)/log(2));

is trying to map the matrix location to the integer value I am trying to get out, however if j is zero I have problems...

I have not used Arduino methods here as i want it to be as fast as possible to poll, hence my use of masks. However the fact that I am incrementing cRows and cCols worries me that I may be losing any benefits.

Go Up