Home AMX User Forum NetLinx Studio

TP Feedback

jjamesjjames Posts: 2,908
I was shown a way on how to shorten mainline code by using FOR loops, rather than the way taught/shown in P1 & P2.

P1/P2 Feedback:
[dvTP,65]=(nCUR_PSET==1)
[dvTP,66]=(nCUR_PSET==2)
[dvTP,67]=(nCUR_PSET==3)
[dvTP,68]=(nCUR_PSET==4)
[dvTP,69]=(nCUR_PSET==5)

FOR-loop Feedback:
FOR(nLOOP=1;nLOOP<=LENGTH_ARRAY(PSET_BTNS);nLOOP++)
  [dvTP,PSET_BTNS[nLOOP]]=(nCUR_PSET=nLOOP)

Using the FOR loop way, you can go quite deep with nested FOR loops. I've been using FOR loops for feedback for quite some time, but am stumped with this one.

Here's how to do it the "P1/P2" way:
[dvTP,SRC_SEL_BTNS[1]] = (nCUR_SRC[1] = 1)
[dvTP,SRC_SEL_BTNS[2]] = (nCUR_SRC[1] = 2)
[dvTP,SRC_SEL_BTNS[3]] = (nCUR_SRC[2] = 1)
[dvTP,SRC_SEL_BTNS[4]] = (nCUR_SRC[2] = 2)
[dvTP,SRC_SEL_BTNS[5]] = (nCUR_SRC[3] = 1)
[dvTP,SRC_SEL_BTNS[6]] = (nCUR_SRC[3] = 2)

I know I would probably have to go two or three deep in a nested-FOR loop to achieve the same results, and for some reason - I just can't get it figured out.

Help please?

Comments

  • jjamesjjames Posts: 2,908
    Geez . . . talk about posting too quickly. About 5 minutes after my first post, I tried a few more things, and got it. Here's my result.
    FOR(nLOOP_COUNT1=1;nLOOP_COUNT1<=LENGTH_ARRAY(SRC_SEL_BTNS);nLOOP_COUNT1++) // LOOP BTNS
      FOR(nLOOP_COUNT2=1;nLOOP_COUNT2<=2;nLOOP_COUNT2++) // LOOP SOURCES
       [dvTP,SRC_SEL_BTNS[nLOOP_COUNT1]] = (nCUR_SRC[(nLOOP_COUNT1/3)+1] = nLOOP_COUNT2)
    
  • You should be able to achieve what you're looking for with a single loop as follows:
    FOR (nLoop = 1; nLoop <= LENGTH_ARRAY (PSET_BTNS); nLOOP++)
        [dvTP,SRC_SEL_BTNS[nLoop]] = (nCUR_SRC[(nLoop + 1) / 2] = 2 - (nLoop % 2))
    

    The (nLoop + 1) / 2 will cause the index into nCUR_SRC to increment every two passes. And the 2 - (nLoop % 2) will compare against 1 on odd numbered passes, and 2 on even numbered passes.
  • jjamesjjames Posts: 2,908
    Works Great!!

    Rob,

    Great! Thank you! As most programmers, I'm naturally lazy, and the less typing the better.

    I feel I'm almost to the point in my programming skill level that I'm getting confortable that my code works, so now it's a game to shorten the code. Almost like "Name That Tune" (I can name that tune in 3 notes) . . it's now "Write That Code" (I can do that in 2 lines). LOL

    Thanks again.
  • DHawthorneDHawthorne Posts: 4,584
    Depending on the project, I have done it both ways - discrete feedback per channel on independant lines, and the FOR loop approach. I see one advantage in the individual, line-by-line approach: it's easier to modify if one of your conditions becomes more complex than a simple equivalence, especially if the condition has variations. As soon as I have to put conditionals inside the loop to test what iteration I'm on, I start thinking about losing the loop. One other reason is readability, especially if someone else may need to service the code at a later date. A FOR loop with a lot of nested variables is not immediately transparent in its function. A line-by-line equivalence is, especially if you comment each line.
  • jjamesjjames Posts: 2,908
    Since I use an EXTENSIVE amount of arrays (pop-up names, power maps, input/output maps, you name it) the FOR loop is nearly perfect for my situations.

    A major problem I had before was that I would not comment my code, and that made it very difficult to read when I went back to see what's going on - especially when the first couple of jobs I was trying to find the "groove" of things and each job's code setup was different. So now I comment nearly everything and explain what's going on. This is especially true with my for loops in mainline. But anyway, like I said - I use A LOT of arrays, so FOR loops fit perfectly. And personally, if something changes in the code to where the FOR loop is out of whack, I'd rather spend the time and fix it than change one or two numbers in 20 to 30 lines of code.
    DHawthorne wrote:
    One other reason is readability, especially if someone else may need to service the code at a later date.
    Let's just hope no one has to service my code at a later date, because if they can't understand a feedback FOR loop, that should be the least of their worries on working with my code.
  • DHawthorneDHawthorne Posts: 4,584
    jjames wrote:
    Since I use an EXTENSIVE amount of arrays (pop-up names, power maps, input/output maps, you name it) the FOR loop is nearly perfect for my situations.

    A major problem I had before was that I would not comment my code, and that made it very difficult to read when I went back to see what's going on - especially when the first couple of jobs I was trying to find the "groove" of things and each job's code setup was different. So now I comment nearly everything and explain what's going on. This is especially true with my for loops in mainline. But anyway, like I said - I use A LOT of arrays, so FOR loops fit perfectly. And personally, if something changes in the code to where the FOR loop is out of whack, I'd rather spend the time and fix it than change one or two numbers in 20 to 30 lines of code.


    Let's just hope no one has to service my code at a later date, because if they can't understand a feedback FOR loop, that should be the least of their worries on working with my code.
    I do too, am usually a FOR loop works for me too. But sometimes, even I can't figure out what the heck I was doing at first glance when I go back to an older project. So there are times I go for readability over efficiency, because I know I may have to go back to it at a time when my head is no longer full of everything that is going on, and it will be easier to deal with.

    Here's an example:
    [dvMain_CP[nCP_Count],  99] = (nVauxIO_State[nControlledZone_CP[AUDIO_MODE][nCP_Count]][1] == SYSTEM_OFF)
    
    That's one line to a source selection feedback. There are arrays that are indexes to an index in there. The nCP_Count index is incremented in a FOR loop. I could have nested another FOR loop for the 99, [1] and SYSTEM_OFF (and other input values) as well, and got it in a single line, but instead opted to put a half dozen lines like that in my original loop just so I could take on look at it later and know exactly what was going on.
  • jjamesjjames Posts: 2,908
    DHawthorne wrote:
    I could have nested another FOR loop for the 99, [1] and SYSTEM_OFF (and other input values) as well, and got it in a single line, but instead opted to put a half dozen lines like that in my original loop just so I could take on look at it later and know exactly what was going on.

    Ahh - I see what you're saying. I thought you meant something like the P1/P2 example I posted earlier. Sorry.
  • Chip MoodyChip Moody Posts: 727
    I used to use FOR loops for button feedback. Then - at least on the Axcent3, I believe it applies to NetLinx as well - I tested a long series of button feedback statements both ways and timed it.

    It runs faster without the FOR loop. So you can say the FOR loop method is more efficient coding-wise, but not execution-wise...

    - Chip
  • jjamesjjames Posts: 2,908
    Chip Moody wrote:
    It runs faster without the FOR loop. So you can say the FOR loop method is more efficient coding-wise, but not execution-wise...
    Very interesting - I'll have to test that out!! Thanks for the info - I'll get back later on with what I find.
  • TurnipTruckTurnipTruck Posts: 1,485
    I would second the motions that feedback events occuring in DEFINE_PROGRAM should exist only as discrete statements. It is MUCH easier to understand your code now and in the future. Further, it is Netlinx programming philosophy to minimize thinking in DEFINE_PROGRAM.

    I draw the line at:

    IF (such and such) ON[feedback channel]
    ELSE OFF[feedback channel]

    FOR loops in DEFINE_PROGRAM are the creation of loops within a loop that run non-stop, not the most graceful programming technique. Nested loops should only run when system events dictate.

    As someone who has been at this since well back into the Axcess days, Netlinx has really done wonders for my programming efficiencies.
  • DHawthorneDHawthorne Posts: 4,584
    I don't put anything but the simplest feedback in DEFINE_PROGRAM anymore. It doesn't hurt, by the way to put as many discrete channel equivalencies as you like in there - the master tracks if a channel is on, and won't resend it every pass. Turn it into a FOR loop, and you have added processing. Make it a virtual device or an array, and it does go out every pass (which can greatly bog down performance). But something like this:

    [dvRelay, RELAY_AMP] = (bSystemState <> FALSE)

    - costs you nothing.
  • alexanboalexanbo Posts: 282
    One thing I've noticed the other day with feedback is don't use any port other then 1 on a virtual device in a feedback statement. I tried to be fancy and use the second port of a virtual device to accept feedback and it totally bogged the system down as the master kept sending it on commands over and over again.

    I also don't use for loops for feedback but write out each discrete line, which is pretty quick with the ALT-lasso thing and sequential renumber. If for whatever reason that for loop didn't complete in one pass of mainline you'd have problems.
  • DHawthorneDHawthorne Posts: 4,584
    I would love to see a full documentation of the differences between real and virtual devices. I've learned by trial and error some things to avoid, but it would be a timesaver to have everything spelled out so we could know what we can do and what we can't. Some behavior simply is not as expected.
  • dchristodchristo Posts: 177
    alexanbo wrote:
    If for whatever reason that for loop didn't complete in one pass of mainline you'd have problems.

    Could you elaborate on this?

    --D
  • alexanboalexanbo Posts: 282
    I was just thinking that if mainline completed before the for loop that it would start another for loop and eventually back up the processor. Of course thinking about it, perhaps mainline would wait to make sure the for loop completed before going on it's next pass.
  • dchristodchristo Posts: 177
    That's not how Mainline works. It runs to completion. A For-loop in Mainline won't be interupted. There was a thread a while back (and some testing data) about using Long_While's in Mainline and the potential to be in the same loop multiple times (but I don't remember the outcome right off hand).

    --D
Sign In or Register to comment.