Define_function
SCOTTYP
Junior Member
Hi, I finished programmer 2 about a year and half ago and only do AMX projects about every third month so becoming proficient has been a slow process. In my class we briefly went over define function but did not discuss it a whole lot or use one in class. I was wondering if anyone had some code handy that I could analyze to get a better feel for what context to use it. Forgive me but I havent been able to find my book from the class since my last move and in netlinx studios the definition is not very detailed. Any help is greatly appreciated.
Comments
-
I use functions *extensively* in my programs. I like to explain it this way: if you have the exact same block of code in your program more than once, use a function. Duplicated code is a huge pet peeve of mine. Looking through someone else's program (or some of my early work) and seeing page after page of similar blocks of code repeated over and over again is painful to see.
Here is a very simple example of a function:(*********************************************) (* INFO: Screen control *) (* *) (*********************************************) define_function fn_screen (integer iCmd) { switch(iCmd) { case SET_PWR_ON: { pulse[dv_RELAY, RELAY_SCREEN_DN] [dv_TPs, TP_SCREEN_DN] = 1 } case SET_PWR_OFF: { pulse[dv_RELAY, RELAY_SCREEN_UP] [dv_TPs, TP_SCREEN_UP] = 1 } } }
Some might say that creating a function for something as simple as pulsing a relay to drop a screen is overkill. I disagree. I can drop the screen with one line of code as needed (fn_screen (SET_PWR_ON)) throughout my program. Now let's say this particular screen only drops while the relay is held closed...I can change my function one time, and no matter how many times in my program I need to drop the screen, they all still work. If you hard code "pulse[dv_RELAY, RELAY_SCREEN_DN]" instead of using a function, you have to search through your code and replace it.
This is just a very simple example, but it makes my point (hopefully!). I rarely control a device directly from a button push, rather I have a button push call a function to control a device (or send the command to a module). Early on I ran into too many times of needing to do "something", and putting it in a button push....only later needing to do that same "something" somewhere else. DO_PUSH is a hack (in most cases, in my opinion) to achieve the same result, creating a function is the more elegant solution. -
The function above could also be written as a define_call, which you may have used before. Aside from the different syntax (fn_screen() vs. CALL 'fn_screen'), functions also have the ability to return a value:
// input: 0-64 output: 0-255 define_function INTEGER scaleVolume(INTEGER vol) { return (vol*255)/64 }
This can be used in an expression like so: SEND_LEVEL dvTP, 1, scaleVolume(inputLevel)
The principal is the same -- reduce duplicated code, especially when you might need to change that code in the future. Even if you only use it once, it lets you write self-documenting code by putting a name on that particular expression or calculation. -
AHHH, thankyou both....The picture is getting a little clearer. Im going to try and re write some of a project I just did to get some practice. I work at a college so on slower days its always fun going back to some of my older programs and updating them with the tidbits I get from these forums.
-
And of course you can call multiple functions during a command. Such as . . .
SEND_COMMAND dv_TP[fnGET_PANEL(nZone)], "'@TXT-',GET_LAST(nPresets),',',fnSavePreset(GET_LAST(nPresets))"
Where blue words are system functions and the red ones would be user defined . . . just giving a visual reference.
And Colzie - I completely agree with the modifying once and forget about it idea, rather than searching through code and looking for your PULSE command. Good point! -
Data from Function to a Structure
This post has been very helpful with explanations of functions. What I am having problems with is getting data out of the function, assigining it to a structure, and then using that data to do something. I was trying to do something simple like add two numbers and then do a SEND_LEVEL with the result for practice. The example in the book is not very helpful. This is my function:DEFINE_FUNCTION TestFunction() { LOCAL_VAR FirstNumber FirstNumber = FirstNumber + 2 }
I know I have to define a structure and then use the dot operator to start assigning values from the function, but my values never change. I don't use functions very often, but when I do, I usually follow this format:DEFINE_FUNCTION INTEGER TestFunction(INTEGER VALUE) { LOCAL_VAR RESULT RESULT = VALUE + 2 RETURN RESULT } DEFINE EVENT BUTTON_EVENT[dvTP,1] { PUSH: { nTEST = TestFunction(2) } }
Doing it that way, a press of TP 1 will change nTest to 4. I guess I am missing a step somewhere while trying to pass and and use data from a structure. Any help with that would be much appreciated. Thanks in advance. -
Here is a sample, but I warn you that I am just writing this in the post, I am not using the compiler to test it, so there could be a few typos.
The concept should be sound tho.define_type structure _sTest{ char sName[25] char sData1[50] char sData2[50] integer nValue1 integer nValue2 integer nValueArray[10] } define_variable _sTest uTest _sTest uTestArray[50] define_function integer fnDoubleValue(integer value){ return (value*2); } define_function integer fnRandomMultiply(integer value){ return (value*(random_number(10)+1)); } define_function char[25] fnRandomName(){ stack_var char names[5][25]; names[1] = 'Joe Bob'; names[2] = 'Bobby Sue'; names[3] = 'Tommy Lee'; names[4] = 'John'; names[5] = 'Cindy'; return names[Random_Number(5)+1]; } define_function fnPopulateTest(){ stack_var integer x; uTest.nValue1 = random_number(200); uTest.nValue2 = fnDoubleValue(uTest.nValue1); uTest.nValueArray[1] = random_number(10); for(x=2;x<=length_array(uTest.nValueArray);x++){ uTest.nValueArray[x] = fnRandomMultiply(uTest.nValueArray[x-1]) } uTest.sData1 = "'Record created at:',time"; uTest.sData2 = "'Record created on:',date"; } define_event button_event[dvTp,1]{ Push:{ stack_var integer x; for(x=1;x<=length_array(uTestArray);x++){ fnPopulateTest(); uTestArray[x] = uTest; } } } button_event[dvTp,2]{ Push:{ stack_var integer x; x = random_number(50)+1; send_string 0,"'#Random Record Number ',itoa(x),'#'" send_string 0,"'Name:',uTestArray[x].sName"; send_string 0,"uTestArray[x].sData1"; send_string 0,"uTestArray[x].sData2"; send_string 0,"'Value1:',itoa(uTestArray[x].nValue1)"; send_string 0,"'Value2:',itoa(uTestArray[x].nValue2)"; send_string 0,"'Value Array:',itoa(uTestArray[x].nValueArray[1],',', itoa(uTestArray[x].nValueArray[2],',', itoa(uTestArray[x].nValueArray[3],',', itoa(uTestArray[x].nValueArray[4],',', itoa(uTestArray[x].nValueArray[5],',', itoa(uTestArray[x].nValueArray[6],',', itoa(uTestArray[x].nValueArray[7],',', itoa(uTestArray[x].nValueArray[8],',', itoa(uTestArray[x].nValueArray[9],',', itoa(uTestArray[x].nValueArray[10]"; } }
Hopefully this addresses the topics you wanted.
Jeff -
This is a good example for many things!
I know Jeff didn't test this but at a glance (and I could be wrong), I don't think button PUSH dvTp,1 will work. I seem to remember you can't get an array_length form a defined structure. You could just change the FOR loop max "length_array(uTestArray)" to a number for testing.Spire_Jeff wrote: »define_event button_event[dvTp,1]{ Push:{ stack_var integer x; for(x=1;x<=length_array(uTestArray);x++){ fnPopulateTest(); uTestArray[x] = uTest; } } }
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