Go Down

Topic: Map button matrix to integers (Read 791 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]);
}


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.

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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy