Home AMX User Forum AMX General Discussion

Switch (n) in a Define_Call?

Hi all...

Banging my head against something obvious maybe? (most likely)

I can not get the following to execute. It should be just a little routine to trigger page flips on a bunch of KPs.

It is inside of a sub-routine and everything else inside the CALL runs.

Does a SWITCH not hold up in a CALL? I would use a GET_LAST but I need to trigger all KPs to page flip except for the one that is triggering this CALL.

I thought this would be the easiest way - skiproom is the varible of the room I don't want to page flip,

This is a cut from inside the routine. The wait is to give some other things before a chance to catch up.

WAIT 4
{
FOR(nCount = 1; nCount <= 11; nCount ++)
{
IF(nCount<>SkipRoom)
{
Switch (nCount)
{
Case 1:
{
SEND_COMMAND dvDMS1, " 'PAGE-IntercomReply' "
}

Case 2:
{
SEND_COMMAND dvDMS2, " 'PAGE-IntercomReply' "
}
// etc down to dvDMS11
}
}
}
}

Comments

  • Joe HebertJoe Hebert Posts: 2,159
    PyroGuy wrote: »
    Does a SWITCH not hold up in a CALL?
    SWITCH CASE does not work inside a WAIT.

    It's a bug that's been documented before (I'll post the link if I can find it) and I guess it hasn't been fixed yet.

    Try the same code but use SELECT ACTIVE instead.
  • jjamesjjames Posts: 2,908
    Okay . . . LET'S START THIS ALL OVER!! LMAO!!!!

    So, if SkipRoom is a variable - couldn't it change by the time the WAIT expires?
  • PyroGuyPyroGuy Posts: 121
    SKIPROOM is a variable that is set at the beginning of the CALL. The WAITS are just to give the swr time to get itself setup. The SKIPROOM isn't going to change unless the CALL is re-initiated from a different keypad (SKIPROOM = Keypad #)

    I'm going to give Select Active a shot. I was actually considered hard coding a dozen IF statements this was driving me nuts.

    Thanks
  • jjamesjjames Posts: 2,908
    PyroGuy wrote: »
    SKIPROOM is a variable that is set at the beginning of the CALL. The WAITS are just to give the swr time to get itself setup. The SKIPROOM isn't going to change unless the CALL is re-initiated from a different keypad (SKIPROOM = Keypad #)

    Well . . . since it's still a variable and it is possible that another keypad can reinitiate the CALL, however unlikely, I'd highly recommend the good practice of evaluating then wait. I wouldn't care if it was 1/10 of a second delay of the evaluation - it's a good habit to get into when you have WAITs and you're evaluating.

    I'd highly suggest you do something like this:
    FOR(nCount = 1; nCount <= 11; nCount ++)
    {
    	IF(nCount<>SkipRoom)
    	{
    		Switch (nCount)
    		{
    			Case 01:{WAIT 4{SEND_COMMAND  dvDMS1, " 'PAGE-IntercomReply' "}}
    			Case 02:{WAIT 4{SEND_COMMAND  dvDMS2, " 'PAGE-IntercomReply' "}}
    			Case 03:{WAIT 4{SEND_COMMAND  dvDMS3, " 'PAGE-IntercomReply' "}}
    			Case 04:{WAIT 4{SEND_COMMAND  dvDMS4, " 'PAGE-IntercomReply' "}}
    			Case 05:{WAIT 4{SEND_COMMAND  dvDMS5, " 'PAGE-IntercomReply' "}}
    			Case 06:{WAIT 4{SEND_COMMAND  dvDMS6, " 'PAGE-IntercomReply' "}}
    			Case 07:{WAIT 4{SEND_COMMAND  dvDMS7, " 'PAGE-IntercomReply' "}}
    			Case 08:{WAIT 4{SEND_COMMAND  dvDMS8, " 'PAGE-IntercomReply' "}}
    			Case 09:{WAIT 4{SEND_COMMAND  dvDMS9, " 'PAGE-IntercomReply' "}}
    			Case 10:{WAIT 4{SEND_COMMAND dvDMS10, " 'PAGE-IntercomReply' "}}
    			Case 11:{WAIT 4{SEND_COMMAND dvDMS11, " 'PAGE-IntercomReply' "}}
    		}                                
    	} 
    }
    
  • Why Not a DEV Array?

    Forgetting about the Wait for a minute, and also forgetting that SkipRoom MAY change before wait execution, Why not "clean up" the code a bit? Create a "_DMS_Device_Array_", and do something like:


    WAIT 4
    {
    FOR(nCount = 1; nCount <= 11; nCount ++)
    {
    IF(nCount<>SkipRoom)
    {
    SEND_COMMAND _DMS_Device_Array_[nCount], " 'PAGE-IntercomReply' "
    }
    }
    }

    No Need For a SWITCH/CASE or SELECT/ACTIVE or IF/IF/IF....ect...
  • jjamesjjames Posts: 2,908
    Indeed - I'd go with a DEV array as well. But the problem with a DEV arrays and WAITs is that you'll still need to break them out since each can have their own WAIT.
  • Forgive me If I am missing something....(I haven't had my daily quota of coffee yet)

    Why would each DMS need its own wait? Isn't the wait for "other things"?
  • jjamesjjames Posts: 2,908
    In Kenny's example - there's only one wait. It can't be applied multiple times.

    Wife is looking at me nastily cuz we're late to a birthday party . . . . could someone please explain what I mean a bit more in depth? :D
  • Joe HebertJoe Hebert Posts: 2,159
    jjames wrote: »
    could someone please explain what I mean a bit more in depth? :D
    I can?t do it.

    I?m here to promote the existence of the SWITCH CASE inside a WAIT bug.

    Anything else I say might be considered a conflict of interest.
  • jjames wrote: »
    . . . . could someone please explain what I mean a bit more in depth? :D

    Me neither...Its too early to activate my mind reading helmet...

    I Keed.....I Keed!!!!!
  • viningvining Posts: 4,368
    jjames is looking at his version of the code with the waits are inside the loop and each case would have its own wait since every case could be evaluated as true during the loop and kenny's code used a single wait before the loop as did the original post.

    So you guys are discussing two different pieces of code.

    Joe Hebert wrote:
    I?m here to promote the existence of the SWITCH CASE inside a WAIT bug.
    I think in the past to get around this I would have the wait execute a function call which contained the switch case and other time I probably just gave up with out realizing the cause of the problem and did a select active as you previously suggested. I also find that the switch case in general has a lot of quirky behavior problems which cause me to favor select active which always seems to function as advertised.

    What's that other switch case problem? A single char case at the begining of the switch that used to make me bang my head against the wall.
  • jjamesjjames Posts: 2,908
    Okay - I have a few minutes.

    Basically what I'm saying is that if you wait and then evaluate, you run the risk of evaluating the wrong value. Where as if you evaluate and then wait, you'll always get the result you want. I don't care about SWITCH...CASE or SELECT...ACTIVE, it's the WAIT 4 that bothers me.

    What if the function is called 3 times in a row, one right after another? By the time the WAIT expires and you evaluate the value, the first two calls won't activate, but the last will.

    So - I'm promoting evaluation before waits. I don't care which way you evaluate it.
  • PyroGuyPyroGuy Posts: 121
    Wow - impressive when a Jr can create an interesting thread! Thanks for the info - I picked up a few ideas.

    The Select Active approach didn't work (well it did - but not the way I wanted it to) - code often does that! I want a "complile_as_desired" function to go along with the regular "complile_as_written".

    I like the dev array suggestion and may put it in a future revision. Since this had to get out to the client quickly, I realized the issue was with the wait and looked further at the code.

    The wait 1,2,3, and 4 were just to allow 'other things' to get done so as a wise programmer once told me, keep it simple. It put the FOR loop as the first thing to execute in the CALL, no wait required, and everything else happens after that. It really doesn't matter WHEN the KP flip happens, before or after the switcher settings, so call me a chicken, but I just avoided the problem by dodging it.

    Thanks to all for the suggestions - the info is good to add to my arsenal.

    Cheers & Thanks!
  • Joe HebertJoe Hebert Posts: 2,159
    SWITCH CASE can be a bumpy road

    Just for the record, here?s a thread from a little over a year ago with posted code that proves that SWITCH CASE in a WAIT doesn?t work and that it generates run time errors. Same code with SELECT ACTIVE works fine.

    http://amxforums.com/showthread.php?t=3821

    Here is a different type of scenario that shows another quirk with SWITCH CASE:

    This example compiles fine:
    DEFINE_FUNCTION SwitchCase1 (integer x) {
      //will compile
       SWITCH (x) {
          CASE 0: {}
          CASE 256: {}      
       }
    }
    

    This example, strange as it may seem, does not compile. It generates the error: Duplicate CASE values in SWITCH statement. Say what? The error doesn?t say say what, I said that.
    DEFINE_FUNCTION SwitchCase2 (integer x) {
      //will not compile
      //any number that is a multiple of 256 will generate the error.
       SWITCH (x) {
          CASE 256: {}
          CASE 0: {}      
       }
    }
    

    If you drive down the SWITCH CASE road you must be cautious of the pot holes.
  • ColzieColzie Posts: 470
    Joe Hebert wrote: »
    It generates the error: Duplicate CASE values in SWITCH statement.

    I have seen this error for unknown reasons! I didn't realize there was some (crazy) logic behind it.

    What are the conditions for this? A multiple of the first case? Only 256? I use switch/case ALL the time and only rarely have problems.

    I'd like to know a bit more about this one so I can swerve around it ;)
  • Spire_JeffSpire_Jeff Posts: 1,917
    Joe Hebert wrote: »
    DEFINE_FUNCTION SwitchCase2 (integer x) {
      //will not compile
      //any number that is a multiple of 256 will generate the error.
       SWITCH (x) {
          CASE 256: {}
          CASE 0: {}      
       }
    }
    

    I wonder if switch()..case is treating the case values as 8 bit integers? Have you tried a case 1: and a case 257: to see if the same problem exists?

    Jeff
  • ColzieColzie Posts: 470
    Spire_Jeff wrote: »
    I wonder if switch()..case is treating the case values as 8 bit integers? Have you tried a case 1: and a case 257: to see if the same problem exists?

    Jeff

    Indeed,
    switch (x)
    {
    	case 257: {}
    	case 1: {}
    }
    
    throws the same error.
  • Joe HebertJoe Hebert Posts: 2,159
    This will cause the duplicate error also:
       SWITCH (x) {
          CASE 25701: {}
          CASE 101: {}      
       }
    
    So it appears if the top case minus the lower case divided by 256 equals a whole number then the error occurs.

    25701 ? 101 = 25600
    25600/256 = 100 = error

    Weird eh?
  • Spire_JeffSpire_Jeff Posts: 1,917
    Joe Hebert wrote: »
    This will cause the duplicate error also:
       SWITCH (x) {
          CASE 25701: {}
          CASE 101: {}      
       }
    
    So it appears if the top case minus the lower case divided by 256 equals a whole number then the error occurs.

    25701 ? 101 = 25600
    25600/256 = 100 = error

    Weird eh?

    Seems like it's a case of the Switch() only comparing the first 8 bits. Maybe tech support could talk to engineering and get a better understanding of how things work under the hood. With that understanding, it should be easier to formulate a list of limitations for switch()..case statements.

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Spire_Jeff wrote: »
    Seems like it's a case of the Switch() only comparing the first 8 bits.
    Correct (punny and more succinct :) ), but only if the top case is larger than the bottom case. If you reverse the cases then it compiles fine.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Joe Hebert wrote: »
    Correct (punny and more succinct :) ), but only if the top case is larger than the bottom case. If you reverse the cases then it compiles fine.

    Since I have not experimented with this at all, I am wondering: It compiles without problems, but does it run without problems?

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Spire_Jeff wrote: »
    It compiles without problems, but does it run without problems?
    Runs fine.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Joe Hebert wrote: »
    Runs fine.

    Thanks Joe, my faith in Switch() has been restored. Next time I am talking with tech support, I will try to remember to mention this and see if they can fix the compiler.

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Spire_Jeff wrote: »
    Thanks Joe, my faith in Switch() has been restored.
    I?m glad yours is; mine?s not.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Joe Hebert wrote: »
    I?m glad yours is; mine?s not.

    I never said exactly how much faith I have in switch()..case, just that it is restored :) I really only use switch()..case on a very limited basis. If I am dealing with more than 5 or 10 possibilities, I try to look at what I am asking it to do and see if there is a way to break it down further or approach it from a different angle.

    On occasion tho, I have used a switch()..case with values over 10, but not higher than 250.

    Jeff
  • ColzieColzie Posts: 470
    As I mentioned, I use switch/case a lot, and definitely with values > 256. So to prove to myself it is just a compiler bug I wrote this test program. As expected, I received the correct string in my Diagnostics window for each case.

    And naturally (!) if case 256: is moved before case 0:, or case 25601: is moved before case 1:, it will not compile.
    define_function fn_switch_case (integer i)
    {
    	switch (i)
    	{
    		case 0:		send_string 0, "'case=0'"
    		case 1:		send_string 0, "'case=1'"
    		case 256:	send_string 0, "'case=256'"
    		case 25601:	send_string 0, "'case=25601'"
    	}
    }
    
    
    define_event
    
    button_event[10001:1:1, 1]
    button_event[10001:1:1, 256]
    button_event[10001:1:1, 25601]
    {
    	push:
    	{
    		fn_switch_case (button.input.channel)
    	}
    	
    	release:
    	{
    		fn_switch_case (0)
    	}
    }
    


    Spire_Jeff, I believe you are correct.
    Spire_Jeff wrote:
    Seems like it's a case of the Switch() only comparing the first 8 bits.
    ...at compiler.

    I am curious of the other problems with switch/case. I know the limitation of not being able to fall through to lower cases (implied break), and I am now reminded of not being able to use switch/case in a wait...what other problems are there?
  • DHawthorneDHawthorne Posts: 4,584
    What it sounds like is happening to me is that the compiler internally does a type cast on the case values if they span the range of a single data type. By making them all the same data type, it can compare them more readily, but you have all the other issues inherent with type casting such as lost high-order bits, etc.
  • Found a similar issue if with strings in the past - make sure your longest string is the first case.

    Won't work
    switch(cCharacter)
    {
      case 'ROBIN': return(nSIDEKICK)
      case 'BATMAN'': return(nSUPERHERO)               
      DEFAULT:return(nBADGUY)
    }
    
    


    Will work
    switch(cCharacter)
    {
      case 'BATMAN'': return(nSUPERHERO)               
      case 'ROBIN': return(nSIDEKICK)
      DEFAULT:return(nBADGUY)
    }
    
    
  • Spire_JeffSpire_Jeff Posts: 1,917
    Ok, I just talked with tech support and, like a lot of people here, they are aware of the problem. The only way to fix it is an upgrade to the compiler, which is not in the works as of right now. So, be aware of the limitations when using switch()..case, or just use select..active :)

    Jeff
Sign In or Register to comment.