Which array triggered button? (How do you do your grids/matrixes?)
travis
Junior Member
say you have a couple arrays of button numbers and you stack them on a button event, how can you figure out which array the button is in?
[code]
DEFINE_CONSTANT
btns1[] = [1,16,99]
btns2[] = [13,2,5]
BUTTON_EVENT[tp,btns1]
BUTTON_EVENT[tp,btns2]
{
PUSH:{
//was this btns1 or btns2?
}
}
[code]
if the buttons are in some kind of order, you can do math to figure it out, but is there any trick for GET_LAST or something like that?
This must come up all the time for grids of buttons, like a matrix switcher.
I did it with a bunch of math, but it was pain. At least now I have an include of a bunch of Grid functions.
I'm coming back to it a few months later, thinking there must be an easy way. But when I started, it turned out to be just as much work.
[code]
DEFINE_CONSTANT
btns1[] = [1,16,99]
btns2[] = [13,2,5]
BUTTON_EVENT[tp,btns1]
BUTTON_EVENT[tp,btns2]
{
PUSH:{
//was this btns1 or btns2?
}
}
[code]
if the buttons are in some kind of order, you can do math to figure it out, but is there any trick for GET_LAST or something like that?
This must come up all the time for grids of buttons, like a matrix switcher.
I did it with a bunch of math, but it was pain. At least now I have an include of a bunch of Grid functions.
I'm coming back to it a few months later, thinking there must be an easy way. But when I started, it turned out to be just as much work.
Comments
-
I don’t know if you can figure it out. I surprised something like that compiles. I wouldn’t approach it that way because it seems illogical, at least to me. What advantage do you have with stacking those arrays? How about just 1 button event with 1 array?travis wrote:say you have a couple arrays of button numbers and you stack them on a button event, how can you figure out which array the button is in?
Here is one generic way to tell what row and column was pushed inside an array of grid buttons and it’s easily configurable.DEFINE_DEVICE dvTp = 10001:1:0 DEFINE_CONSTANT INTEGER nGridButtons[] = { 11,12,13,14,15, // row 1 columns 1-5 21,22,23,24,25, // row 2 columns 1-5 31,32,33,34,35 // row 3 columns 1-5 } INTEGER nNumberOfRows = 3 INTEGER nNumberOfColumns = 5 DEFINE_EVENT BUTTON_EVENT[dvTP,nGridButtons] { PUSH: { INTEGER index INTEGER row INTEGER column index = GET_LAST(nGridButtons) row = index / nNumberOfColumns IF (index % nNumberOfColumns) {row++} IF (index % nNumberOfColumns = 0) {column = nNumberOfColumns} ELSE {column = (index % nNumberOfColumns)} SEND_STRING 0,"'BUTTON.INPUT.CHANNEL = ',ITOA(BUTTON.INPUT.CHANNEL)" SEND_STRING 0,"'Index = ',ITOA(index)" SEND_STRING 0,"'Row = ',ITOA(row)" SEND_STRING 0,"'Column = ',ITOA(column)" } }
I’ve seen a better way of doing this calculation but I can’t remember where or how:row = index / nNumberOfColumns IF (index % nNumberOfColumns) {row++}
If anyone knows please post it. -
You could try
BUTTON_EVENT[tp,0] { PUSH:{ SELECT { ACTIVE(get_last(btns1)): { // } ACTIVE(get_last(btns2)): { // } } -
You could try
BUTTON_EVENT[tp,0] { PUSH:{ SELECT { ACTIVE(get_last(btns1)): { // } ACTIVE(get_last(btns2)): { // } }
I don't think that will work. -
That's the approach I took.Joe Hebert wrote: »I don’t know if you can figure it out. I surprised something like that compiles. I wouldn’t approach it that way because it seems illogical, at least to me. What advantage do you have with stacking those arrays? How about just 1 button event with 1 array?
Here is one generic way to tell what row and column was pushed inside an array of grid buttons and it’s easily configurable.DEFINE_DEVICE dvTp = 10001:1:0 DEFINE_CONSTANT INTEGER nGridButtons[] = { 11,12,13,14,15, // row 1 columns 1-5 21,22,23,24,25, // row 2 columns 1-5 31,32,33,34,35 // row 3 columns 1-5 } INTEGER nNumberOfRows = 3 INTEGER nNumberOfColumns = 5 DEFINE_EVENT BUTTON_EVENT[dvTP,nGridButtons] { PUSH: { INTEGER index INTEGER row INTEGER column index = GET_LAST(nGridButtons) row = index / nNumberOfColumns IF (index % nNumberOfColumns) {row++} IF (index % nNumberOfColumns = 0) {column = nNumberOfColumns} ELSE {column = (index % nNumberOfColumns)} SEND_STRING 0,"'BUTTON.INPUT.CHANNEL = ',ITOA(BUTTON.INPUT.CHANNEL)" SEND_STRING 0,"'Index = ',ITOA(index)" SEND_STRING 0,"'Row = ',ITOA(row)" SEND_STRING 0,"'Column = ',ITOA(column)" } }
I’ve seen a better way of doing this calculation but I can’t remember where or how:row = index / nNumberOfColumns IF (index % nNumberOfColumns) {row++}
If anyone knows please post it.
Took me way too long, but here are my functions with no IFsDEFINE_FUNCTION INTEGER F_BTN_IS_IN_ROW(INTEGER _btn, INTEGER _numRows){ RETURN (_btn - 1) % (_numRows) + 1 } DEFINE_FUNCTION INTEGER F_BTN_IS_IN_COL(INTEGER _btn, INTEGER _numRows){ RETURN (_btn - 1 ) / (_numRows) + 1 }
These are for the other way to align the grid (sometimes you aren't the one who numbers things):
{
1,4,7,
2,5,8,
3,6,9
} -
These are for the other way to align the grid (sometimes you aren't the one who numbers things):
{
1,4,7,
2,5,8,
3,6,9
}
If you are referring to the code I posted, it doesn't matter what the button numbers are. Button numbers themselves don't mean a thing in this case, they're just used as placeholders. It will work with whatever button numbers, whatever amount of rows, and whatever amount of columns. Aside from the constants, the code doesn't need to change. -
Took me way too long, but here are my functions with no IFs
DEFINE_FUNCTION INTEGER F_BTN_IS_IN_ROW(INTEGER _btn, INTEGER _numRows){ RETURN (_btn - 1) % (_numRows) + 1 } DEFINE_FUNCTION INTEGER F_BTN_IS_IN_COL(INTEGER _btn, INTEGER _numRows){ RETURN (_btn - 1 ) / (_numRows) + 1 }
I don't think those functions will work. Try pushing button 15 (button index 5) and it should be row 1 column 5. The functions above will return row 2 column 2. -
I don't think I would bother with grids. You don't necessarily have to model the code to the device's characteristics. In your example, I would just have two button events rather than stacking them. Then you always know which channel number was from which array. I will store data in a 2 dimensional array (grid) but since they don't work in button events I'll just use one array for button presses. I very rarely stack button events, since that design has inherent problems as you have discovered.
Paul -
Yeah, I tested this morning and it does wierd crap that I can't even explain.Joe Hebert wrote: »I don't think that will work.
Even trying it like this so that the arrays are built into the event table works in the same bizarre manner.DEFINE_EVENT //BUTTON EVENT TP_ANI_ARRAY BUTTON_EVENT[vTest,nBtns1] BUTTON_EVENT[vTest,nBtns2] { PUSH: { SELECT { ACTIVE(get_last(nBtns1))://{1,16,99} { SEND_STRING 0,"'TEST btns1 BTN-[ ',itoa(get_last(nBtns1)),' ] :DEBUG<',itoa(__LINE__),'>'"; } ACTIVE(get_last(nBtns2))://{13,2,5}; { SEND_STRING 0,"'TEST btns2 BTN-[ ',itoa(get_last(nBtns2)),' ] :DEBUG<',itoa(__LINE__),'>'"; } ACTIVE(1): { SEND_STRING 0,"'TEST btns(1) BTN-[ ',itoa(BUTTON.INPUT.CHANNEL),' ] :DEBUG<',itoa(__LINE__),'>'"; } } } } -
Not that I would ever approach this issue the way the OP did in the first place... But I think I would just do two button events with the different arrays and call it "done"
-
Straight out of my 2010 Programmer re-Certification Practical exam:
INTEGER cSw_Btns[] = {11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, 41, 42, 43, 44, 51, 52, 53, 54, 61, 62, 63, 64, 71, 72, 73, 74, 81, 82, 83, 84, 91, 92, 93, 94, 101, 102, 103, 104, 111, 112, 113, 114, 121, 122, 123, 124} BUTTON_EVENT [tpSwitch, cSw_Btns] { PUSH: { STACK_VAR INTEGER Input STACK_VAR INTEGER Output Input = Button.Input.Channel / 10 Output = Button.Input.Channel % 10 SEND_STRING dvSwitch, "ITOA(Input), '*', ITOA(Output), 'S'" } }This is not limited to numbers below 10, just change your divisor. It is much easier to understand in increments of 10 however. Does require consecutive button numbers, but that is no big deal IMO. Why write two button events and use a variable to store the value of the first one triggered when you can do it all in one event? On the other hand I don't really find occasion to use a grid of buttons very often. -
ah, those functions i posted are for a little different scenario...
DEFINE_CONSTANT INTEGER OFFSET = 13 INTEGER NUM_ROWS = 10 INTEGER nGrid3[] = { 14,24,34,44,54,64,74,84,94,104,114,124 ,15,25,35,45,55,65,75,85,95,105,115,125 ,16,26,36,46,56,66,76,86,96,106,116,126 ,17,27,37,47,57,67,77,87,97,107,117,127 ,18,28,38,48,58,68,78,88,98,108,118,128 ,19,29,39,49,59,69,79,89,99,109,119,129 ,20,30,40,50,60,70,80,90,100,110,120,130 ,21,31,41,51,61,71,81,91,101,111,121,131 ,22,32,42,52,62,72,82,92,102,112,122,132 ,23,33,43,53,63,73,83,93,103,113,123,133 } DEFINE_EVENT BUTTON_EVENT[dv_TPs, nGrid3] { PUSH:{ LOCAL_VAR INTEGER chan LOCAL_VAR INTEGER ROW3 LOCAL_VAR INTEGER COLUMN3 //GL3 = GET_LAST(nGrid3) chan = BUTTON.INPUT.CHANNEL ROW3 = F_BTN_IS_IN_ROW(chan-offset, NUM_ROWS) COLUMN3 = F_BTN_IS_IN_COL(chan-offset, NUM_ROWS) SEND_STRING 0, "'BTN-', itoa(BUTTON.INPUT.CHANNEL), ' ROW-', ITOA(row3), ' COL-', ITOA(column3)" } }Line 1 (11:52:02.850):: BTN-23 ROW-10 COL-1 Line 2 (11:52:10.031):: BTN-133 ROW-10 COL-12 Line 3 (11:52:33.601):: BTN-124 ROW-1 COL-12 Line 4 (11:52:40.312):: BTN-14 ROW-1 COL-1 Line 5 (11:52:59.195):: BTN-69 ROW-6 COL-6
I'm going to write another set to work with GET_LAST... -
PROGRAM_NAME='test' include'config' //include'incGrid' DEFINE_CONSTANT INTEGER OFFSET = 13 INTEGER NUM_ROWS = 10 INTEGER NUM_COLS = 12 INTEGER nGrid3[] = { 14,24,34,44,54,64,74,84,94,104,114,124 ,15,25,35,45,55,65,75,85,95,105,115,125 ,16,26,36,46,56,66,76,86,96,106,116,126 ,17,27,37,47,57,67,77,87,97,107,117,127 ,18,28,38,48,58,68,78,88,98,108,118,128 ,19,29,39,49,59,69,79,89,99,109,119,129 ,20,30,40,50,60,70,80,90,100,110,120,130 ,21,31,41,51,61,71,81,91,101,111,121,131 ,22,32,42,52,62,72,82,92,102,112,122,132 ,23,33,43,53,63,73,83,93,103,113,123,133 } DEFINE_FUNCTION INTEGER F_BTN_IS_IN_ROW(INTEGER _btn, INTEGER _numRows){ RETURN (_btn - 1) % (_numRows) + 1 } DEFINE_FUNCTION INTEGER F_BTN_IS_IN_COL(INTEGER _btn, INTEGER _numRows){ RETURN (_btn - 1 ) / (_numRows) + 1 } DEFINE_FUNCTION INTEGER F_IDX_IS_IN_ROW(INTEGER _btn, INTEGER _numCols){ RETURN (_btn - 1) / (_numCols) + 1 } DEFINE_FUNCTION INTEGER F_IDX_IS_IN_COL(INTEGER _btn, INTEGER _numCols){ RETURN (_btn - 1 ) % (_numCols) + 1 } DEFINE_EVENT BUTTON_EVENT[dv_TPs, nGrid3] { PUSH:{ LOCAL_VAR INTEGER chan LOCAL_VAR INTEGER ROW3 LOCAL_VAR INTEGER COL3 LOCAL_VAR INTEGER COLUMN3 LOCAL_VAR INTEGER GL3 GL3 = GET_LAST(nGrid3) chan = BUTTON.INPUT.CHANNEL ROW3 = F_BTN_IS_IN_ROW(chan-offset, NUM_ROWS) COLUMN3 = F_BTN_IS_IN_COL(chan-offset, NUM_ROWS) SEND_STRING 0, "'BTN-', itoa(BUTTON.INPUT.CHANNEL), ' ROW-', ITOA(row3), ' COL-', ITOA(column3)" ROW3 = F_IDX_IS_IN_ROW(GL3,NUM_COLS) COL3 = F_IDX_IS_IN_COL(GL3,NUM_COLS) SEND_STRING 0, "'BTN-', itoa(BUTTON.INPUT.CHANNEL), ' ROW-', ITOA(row3), ' COL-', ITOA(column3)" } }Line 1 (12:17:33.416):: BTN-14 ROW-1 COL-1 Line 2 (12:17:33.417):: BTN-14 ROW-1 COL-1 Line 3 (12:17:37.341):: BTN-124 ROW-1 COL-12 Line 4 (12:17:37.341):: BTN-124 ROW-1 COL-12 Line 5 (12:17:41.318):: BTN-133 ROW-10 COL-12 Line 6 (12:17:41.319):: BTN-133 ROW-10 COL-12 Line 7 (12:17:44.641):: BTN-23 ROW-10 COL-1 Line 8 (12:17:44.643):: BTN-23 ROW-10 COL-1
-
Straight out of my 2010 Programmer re-Certification Practical exam:
INTEGER cSw_Btns[] = {11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34, 41, 42, 43, 44, 51, 52, 53, 54, 61, 62, 63, 64, 71, 72, 73, 74, 81, 82, 83, 84, 91, 92, 93, 94, 101, 102, 103, 104, 111, 112, 113, 114, 121, 122, 123, 124} BUTTON_EVENT [tpSwitch, cSw_Btns] { PUSH: { STACK_VAR INTEGER Input STACK_VAR INTEGER Output Input = Button.Input.Channel / 10 Output = Button.Input.Channel % 10 SEND_STRING dvSwitch, "ITOA(Input), '*', ITOA(Output), 'S'" } }This is not limited to numbers below 10, just change your divisor. It is much easier to understand in increments of 10 however. Does require consecutive button numbers, but that is no big deal IMO. Why write two button events and use a variable to store the value of the first one triggered when you can do it all in one event? On the other hand I don't really find occasion to use a grid of buttons very often.
How did you work the feedback on this problem? -
Call the Switch_Feedback() function from wherever you like to trigger feedback from.
DEFINE CONSTANT INTEGER NumSwOuts = 4 DEFINE_VARIABLE VOLATILE INTEGER Sw_State[NumSwOuts] DEFINE_FUNCTION INTEGER FIND_Sw_Response(CHAR Buffer[], CHAR Response[]) { STACK_VAR LONG Len STACK_VAR LONG Count Len = LENGTH_ARRAY(Buffer) FOR (Count = 1; Count <= Len; Count++) { IF (Buffer[Count] == 'S' OR Buffer[Count] == 'X') { Response = LEFT_STRING(Buffer, Count) REMOVE_STRING(Buffer, Response, 1) RETURN TRUE } } RETURN FALSE } DEFINE_FUNCTION Switch_Feedback() { STACK_VAR INTEGER Len STACK_VAR INTEGER Count STACK_VAR INTEGER Input STACK_VAR INTEGER Output Len = MAX_LENGTH_ARRAY(cSw_Btns) FOR (Count = 1; Count <= Len; Count++) { Input = cSw_Btns[Count] / 10 Output = cSw_Btns[Count] % 10 [tpSwitch, cSw_Btns[Count]] = Sw_State[Output] == Input } } DEFINE_EVENT DATA_EVENT [dvSwitch] { ONLINE: { SEND_COMMAND dvSwitch, 'SET BAUD 9600,N,8,1 485 DISABLE' SEND_COMMAND dvSwitch, 'HSOFF' } STRING: { STACK_VAR CHAR Response[32] STACK_VAR INTEGER Output WHILE (FIND_Sw_Response(Sw_RxBuffer, Response)) { SELECT { ACTIVE (RIGHT_STRING(Response, 1) == 'S'): { Output = ATOI(REMOVE_STRING(Response, 'IN', 1)) IF (Output > 0 AND Output <= NumSwOuts) { Sw_State[Output] = ATOI(Response) } } } } } } -
say you have a couple arrays of button numbers and you stack them on a button event, how can you figure out which array the button is in?
DEFINE_CONSTANT btns1[] = [1,16,99] btns2[] = [13,2,5] BUTTON_EVENT[tp,btns1] BUTTON_EVENT[tp,btns2] { PUSH:{ //was this btns1 or btns2? } } [code] if the buttons are in some kind of order, you can do math to figure it out, but is there any trick for GET_LAST or something like that? This must come up all the time for grids of buttons, like a matrix switcher. I did it with a bunch of math, but it was pain. At least now I have an include of a bunch of Grid functions. I'm coming back to it a few months later, thinking there must be an easy way. But when I started, it turned out to be just as much work.[/QUOTE] This is easy, and I stack EVENTS when I can. It makes sense when you have similar functions, although there are other (cleaner) ways to do it. Here is my solution: [Code] DEFINE_CONSTANT btns1[] = [1,16,99] btns2[] = [13,2,5] BUTTON_EVENT[tp,btns1] BUTTON_EVENT[tp,btns2] { PUSH: { STACK_VAR INTEGER intButton STACK_VAR INTEGER intLoop STACK_VAR INTEGER intButtonArray intButton = BUTTON.INPUT.CHANNEL FOR(intLoop = 1; intLoop <= LENGTH_ARRAY(btns1); intLoop++) { IF(intButton == btns1[intLoop]) { intButtonArray = 1 BREAK } ELSE IF(intButton == btns2[intLoop]) { intButtonArray = 2 BREAK } } SEND_STRING 0, "'Button number ',ITOA(intButton), 'from "btns',ITOA(intButtonArray), '" array was pushed!'" } } -
I would scrub the loop and just use two get_last.
nBtn1 = get_last (btns1);
nBtn2 = get_last (btns2);
if theres a match one var will be 0 and the other will hold the index value. Then if/else if -
I would scrub the loop and just use two get_last.
nBtn1 = get_last (btns1);
nBtn2 = get_last (btns2);
if theres a match one var will be 0 and the other will hold the index value. Then if/else if
I stopped using the GET_LAST function a year or so ago, when I was getting inconsistent results from it with the code I was writing at that time. Of course I don't recall the exact issue I was a having, but I stopped trusting some innate Netlinx functions because they sometimes didn't work as expected, and became very frustrating to track down.
There was another one that was giving me fits but I can't remember it at the moment.
I suppose maybe the issues I encountered with those functions have since been resolved.
Given a consistent result, I agree your recommendation would be simpler.
Categories
- All Categories
- 2.5K AMX General Discussion
- 922 AMX Technical Discussion
- 514 AMX Hardware
- 502 AMX Control Products
- 3 AMX Video Distribution Products
- 9 AMX Networked AV (SVSI) Products
- AMX Workspace & Collaboration Products
- 3.4K AMX Software
- 151 AMX Resource Management Suite Software
- 386 AMX Design Tools
- 2.4K NetLinx Studio
- 135 Duet/Cafe Duet
- 248 NetLinx Modules & Duet Modules
- 57 AMX RPM Forum
- 228 MODPEDIA - The Public Repository of Modules for Everyone
- 943 AMX Specialty Forums
- 2.6K AMXForums Archive
- 2.6K AMXForums Archive Threads
- 1.5K AMX Hardware
- 432 AMX Applications and Solutions
- 249 Residential Forum
- 182 Tips and Tricks
- 146 AMX Website/Forums
