Shop OBEX P1 Docs P2 Docs Learn Events
Case function DOESNT work BUT IF (then) DOES — Parallax Forums

Case function DOESNT work BUT IF (then) DOES

stelath_shadow9stelath_shadow9 Posts: 23
edited 2013-10-23 09:49 in Propeller 1
Having an issue with this code but cant figure out what it is. when I run this code nothing happens when I send in a "u" or an "a" serially. HOWEVER (please see next code below)
CON   
VAR
  byte char 
   
OBJ
  bs2   : "bs2"


pub here
    repeat
      char:= bs2.serin_char(1,9600,1,8) 'makes char the same as character coming in
       case char  'checks char against following cases
         "u":     ' executes subroutine "this"
           this
         "a":
           that     'executes subroutine "that"


Pri this        'blinks LED on and off 2 times
dira [14]~~
 repeat 4
       
        !outa[14]
        waitcnt(8_000_000+cnt)
here
    
pri that        'blinks LED on and off forever
    dira[14]~
    repeat 
       
       !outa[14]
        waitcnt(8_000_000+cnt)



When I execute this code everything works EXCEPT for the "a" command. When I send an "a" it still excutes the same as sending "u". So I know that this works but just not for the case function for some reason. AND not with the ELSE..IF function. Any ideas?
CON   
VAR
  byte char 
   
OBJ
  bs2   : "bs2"


pub here
    repeat
      char:= bs2.serin_char(1,9600,1,8) 'makes char the same as character coming in
       if char:= "u"     ' executes subroutine "this"
           this
       elseif "a"
           that     'executes subroutine "that"


Pri this        'blinks LED on and off 2 times
dira [14]~~
 repeat 4
       
        !outa[14]
        waitcnt(8_000_000+cnt)
here
    
pri that        'blinks LED on and off forever
    dira[14]~
    repeat 
       
       !outa[14]
        waitcnt(8_000_000+cnt)  


Comments

  • Dave HeinDave Hein Posts: 6,347
    edited 2013-10-19 07:25
    In the "that" method use ~~ instead of ~. ~~ will set P14 for output. ~ will set P14 for input.

    Change "if char:= "u"" to "if char == "u"". Change "elseif "a"" to "elseif char == "a"". The way you have it currently both expression will evaluate to true.
  • stelath_shadow9stelath_shadow9 Posts: 23
    edited 2013-10-19 08:55
    Dave Hein wrote: »
    In the "that" method use ~~ instead of ~. ~~ will set P14 for output. ~ will set P14 for input.

    Change "if char:= "u"" to "if char == "u"". Change "elseif "a"" to "elseif char == "a"". The way you have it currently both expression will evaluate to true.
    CON   VAR
      byte char 
       
    OBJ
      bs2   : "bs2"
    
    
    pub here
        repeat
          char:= bs2.serin_char(1,9600,1,8) 'makes char the same as character coming in
           if char == "u"     ' executes subroutine "this"
               this
           elseif char =="a"
               that     'executes subroutine "that"
    
    
    Pri this        'blinks LED on and off 2 times
    dira [14]~~
     repeat 4
           
            !outa[14]
            waitcnt(8_000_000+cnt)
    here
        
    pri that        'blinks LED on and off forever
        dira[14]~~
        repeat 
           
           !outa[14]
            waitcnt(8_000_000+cnt)
    
    
    

    This unfortunately didnt work. The result was nothing happened when "a" or "u" was pressed.:depressed:
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-10-19 09:01
    What's the "here" for in the code below?
    Pri this        'blinks LED on and off 2 times
    dira [14]~~
     repeat 4
           
            !outa[14]
            waitcnt(8_000_000+cnt)
    [b]here[/b]
    
    If you're trying to return to here, you don't need it. Subroutines return automatically after their last statement executes.

    -Phil
  • stelath_shadow9stelath_shadow9 Posts: 23
    edited 2013-10-19 09:04
    What's the "here" for in the code below?
    Pri this        'blinks LED on and off 2 times
    dira [14]~~
     repeat 4
           
            !outa[14]
            waitcnt(8_000_000+cnt)
    [B]here[/B]
    
    If you're trying to return to here, you don't need it. Subroutines return automatically after their last statement executes.

    -Phil

    I think that is just left over code from my earlier attempts. I just overlooked it. It shouldnt be there
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-10-19 09:07
    Sooo ... what happens when you get rid of it? (Also CON and VAR should be on separate lines. And if you don't declare any CONstants, you don't need the CON line at all. But you really do need to declare your clock stuff, especially if you have serial I/O.)

    -Phil
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-10-19 11:03
    (Also CON and VAR should be on separate lines. And if you don't declare any CONstants, you don't need the CON line at all. But you really do need to declare your clock stuff, especially if you have serial I/O.)

    I bet these were on two different lines. The first line break often gets deleted when posting code (at least in Chrome). I often have to go back and fix code I've posted.

    I agree with Phil about needing clock settings to use serial input output.
  • AribaAriba Posts: 2,690
    edited 2013-10-19 19:00
    I think the problem is that the baudrate is not exact. You need to set the crystal frequency and PLL in the CON section, something like
    CON
      _clkmode  = xtal1 + pll16x
      _xinfreq  = 5_000_000
    
    Without that the Propeller runs with the internal RC oscillator, which can result in wrong characters from serin.

    Andy
  • stelath_shadow9stelath_shadow9 Posts: 23
    edited 2013-10-19 23:51
    Ariba wrote: »
    I think the problem is that the baudrate is not exact. You need to set the crystal frequency and PLL in the CON section, something like
    CON
      _clkmode  = xtal1 + pll16x
      _xinfreq  = 5_000_000
    
    Without that the Propeller runs with the internal RC oscillator, which can result in wrong characters from serin.

    Andy
    If Im not using a crystal is there a way to set the clock on the internal RC oscillator?

    But this is starting to stray away from the original issue. The true issue I am having with this is not the serin command. that works. Ive tested it and it works fine with the IF command. However it is when i am trying to use CASE that nothing seems to work anymore. I dont understand why one would work but the other doesnt
  • stelath_shadow9stelath_shadow9 Posts: 23
    edited 2013-10-19 23:52
    Sooo ... what happens when you get rid of it? (Also CON and VAR should be on separate lines. And if you don't declare any CONstants, you don't need the CON line at all. But you really do need to declare your clock stuff, especially if you have serial I/O.)

    -Phil

    Deleting the "here" part of that line had no change in performance
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-10-19 23:57
    That wasn't the most important part of my comment. The part about the clock settings is likely more germane to your problems.

    -Phil
  • stelath_shadow9stelath_shadow9 Posts: 23
    edited 2013-10-20 00:22
    Sooo ... what happens when you get rid of it? (Also CON and VAR should be on separate lines. And if you don't declare any CONstants, you don't need the CON line at all. But you really do need to declare your clock stuff, especially if you have serial I/O.)

    -Phil

    So you're saying I need to define a constant for my clock settings even if I am not using an external oscillator/crystal? My only question to that is the same as the original post "why does the IF statement work in receiving serial in just fine and executing commands just fine but when I use the CASE function, and send a command, nothing happens? Not trying to argue, but I really don't see how one of these codes is receiving serial input and executing code, but when I change the function to a variation of the same thing ( or at least thats what that prop manual says, is that case and IF...then statements are almost the same thing.) It no longer works. for a rough example. If I use the following code (which is not going to be gramactically perfect, I just want to show the process)

    char:= charin 'serin a character and make the variable "char" equal to the character detected
    If char:= "a" ' if the variable "char" is "a" then turn on the LED
    turn on LED
    this code will work

    char:= charin 'serin a character and make the variable "char" equal to the character detected
    case char ' if the variable "char" is "a" then turn on the LED
    "a": turn on LED

    this code will not work....so whats happening between the 2. why would one code need clock references to work but the other doesnt?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-10-20 00:36
    If you're not using an external oscillator or crystal, chances are you will not have success with serial I/O. The reason is that timing is critical, and the Prop's interanl RC oscillator has a rather wide frequency range. My suspicion is that the difference between the case and if cases may have been coincidental, unless you're able to repeat it reliably, alternating between the two several times in sequence. In any event, how about posting your two programs again in their entirety, complete with all the corrections recommended in the posts above?

    -Phil
  • stelath_shadow9stelath_shadow9 Posts: 23
    edited 2013-10-20 02:32
    If you're not using an external oscillator or crystal, chances are you will not have success with serial I/O. The reason is that timing is critical, and the Prop's interanl RC oscillator has a rather wide frequency range. My suspicion is that the difference between the case and if cases may have been coincidental, unless you're able to repeat it reliably, alternating between the two several times in sequence. In any event, how about posting your two programs again in their entirety, complete with all the corrections recommended in the posts above?

    -Phil
    No no its repeatable! I can switch between the 2 and the If function works but the case function doesn't

    THIS WORKS
    VAR  byte char 
       
    OBJ
      bs2   : "bs2"
     pst:"parallax serial terminal"
    
    pub start
     pst.start(9600)
       here
    
    
    pub here
        repeat
          char:= pst.charin 'makes char the same as character coming in
            If char:= "u"
              this
    
    
    Pri this        'blinks LED on and off 4 times
    dira [14]~~
     repeat 4
           
            !outa[14]
            waitcnt(8_000_000+cnt)
    
    
    )
    


    THIS DOES NOT WORK
    
    
    
    
    
                      
      
    VAR
      byte char 
       
    OBJ
      bs2   : "bs2"
    
    
       pst:"parallax serial terminal"
    pub start
     pst.start(9600)
       here
    
    pub here
        repeat
          char:= pst.charin 'makes char the same as character coming in
            case char
              "u":
                 this
        
           
    
    
    
    
    Pri this        'blinks LED on and off 4 times
    dira [14]~~
     repeat 4
           
            !outa[14]
            waitcnt(8_000_000+cnt)
    
    And the only difference between the 2 is the IF versus CASE function.
  • kuronekokuroneko Posts: 3,623
    edited 2013-10-20 03:37
    Your IF example only works because it's cheating. You should use if char == "u" for comparisons, := is an assignment which equates to not equal 0, i.e. TRUE. This has been commented on already in the first reply.

    It's really down to the clock speed. The BS2 object calculates its baudrate internals based on clkfreq which defaults to 12MHz but using RCFAST can give you anything between 8 and 20MHz. On my demoboard I can get away with long[0] := 13_000_000 (13MHz). You could try something in that range for now but in the long run a crystal is just easier.
  • stelath_shadow9stelath_shadow9 Posts: 23
    edited 2013-10-20 05:56
    kuroneko wrote: »
    Your IF example only works because it's cheating. You should use if char == "u" for comparisons, := is an assignment which equates to not equal 0, i.e. TRUE. This has been commented on already in the first reply.

    It's really down to the clock speed. The BS2 object calculates its baudrate internals based on clkfreq which defaults to 12MHz but using RCFAST can give you anything between 8 and 20MHz. On my demoboard I can get away with long[0] := 13_000_000 (13MHz). You could try something in that range for now but in the long run a crystal is just easier.


    so, out of curiosity what would happen if i use FREQOUT on one pin to XIN? could I trick the prop into thinking there was a crystal?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-10-20 08:29
    so, out of curiosity what would happen if i use FREQOUT on one pin to XIN? could I trick the prop into thinking there was a crystal?
    No, that won't work. You need to use an accurate timebase for serial I/O. Also, did you notice that kuroneko's admonisiton about if char == "u" was the same as that offered by Dave Hein in post #2? (Both are correct, BTW.) Anyway, timing is everything in this case, and you really do need to add a crystal or external oscillator to get reliable performance from serial I/O.

    -Phil
  • cavelambcavelamb Posts: 720
    edited 2013-10-20 13:09
    So just out of curiosity, why doesn't the case statement work?

    Is the BS2 object returning capitols?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-10-20 13:11
    None of the programs work, actually. It's because the RC timebase is too inaccurate to support serial I/O.

    -Phil
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-10-20 13:20
    cavelamb wrote: »
    So just out of curiosity, why doesn't the case statement work?

    Is the BS2 object returning capitols?

    Actually the case example is the one that does work but because of the timing problem repeatedly mentioned, there aren't any valid characters received. The "if" version appears to work since it's esentially using "if true" so any character (even the invalid ones) entered will satisfy the conditional.
  • stelath_shadow9stelath_shadow9 Posts: 23
    edited 2013-10-21 01:46
    Duane Degn wrote: »
    Actually the case example is the one that does work but because of the timing problem repeatedly mentioned, there aren't any valid characters received. The "if" version appears to work since it's esentially using "if true" so any character (even the invalid ones) entered will satisfy the conditional.

    I am 99% sure that Phil and duane are right. I didn't realize that typing in ANY character would actually trigger my code. So I was under the false assumption my program was working one way but not the other. That being said, I will have to wait until I get my hands on a crystal (something I am not able to do where I am located) BUT, once I do I'll re try the project with the case statement and see where I end up. But I am going to set this thread to solved.
  • SapiehaSapieha Posts: 2,964
    edited 2013-10-21 02:06
    Hi stelath_shadow9

    It NOT need be correctly 5MHz.

    If You have any crystal that are between 3 - 7 MHZ You can use that ---- If You adjust settings acordingly
    I am 99% sure that Phil and duane are right. I didn't realize that typing in ANY character would actually trigger my code. So I was under the false assumption my program was working one way but not the other. That being said, I will have to wait until I get my hands on a crystal (something I am not able to do where I am located) BUT, once I do I'll re try the project with the case statement and see where I end up. But I am going to set this thread to solved.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-10-21 06:30
    stelath, try this code at the beginning of your program. It will measure the bit time of the serial port, and will set the variable baudrate to the measured baud rate. Just type a carriage return after you first start up the program. This will allow you to use the serial port without a crystal. Keep in mind that the internal clock frequency is temperature dependent. The clock frequency remains fairly stable as long as the temperature doesn't change, but it will change if the temperature changes.
    dat
    getbitcycles  waitpeq         zero, mask
                  mov             start, cnt
                  waitpeq         mask, mask
                  mov             stop, cnt
                  sub             stop, start
                  wrlong          stop, par
                  jmp             #$
    
    stop          long            0
    start         long            0
    zero          long            0
    mask          long            $80000000
    
    pub here | baudrate
      repeat until result
      baudrate := clkfreq/result
        repeat
          char:= bs2.serin_char(1,baudrate,1,8) 'makes char the same as character coming in
          ...
    
  • PaulPaul Posts: 263
    edited 2013-10-23 06:19
    Some hundred years ago when I was just learning the propeller I ran into something similar. It appears that the CASE statement takes up more memory than the IF statement and by assigning more memory to the program my spin code started working.
    Probably not the case here as I don't see how to assign more memory to stelath's program. I'll look around to see if I can come up with my oddball code.

    Paul
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-10-23 09:49
    stelath, here's a version of your code that incorporates the changes suggested by others, and my serial bit-time measurement code. It also uses FullDuplexSerial instead of the BS2 functions. I looked at the serial methods in the BS2 object, and it appears to have some timing offsets that are hard coded for 80 MHz. I think it has problems operating at a lower frequency like 12 MHz.

    The CON section has constants defined for the LED pin, and the serial tx and rx pins. You should change these to match your hardware. If you don't have serial transmit wired up just specify an unused pin for transmit.

    When the program first starts up push the ENTER key so that it can measure the serial bit time.
    CON
      LED_PIN = 15
      RX_PIN  = 31
      TX_PIN  = 30
       
    VAR
      byte char 
       
    OBJ
      fds   : "FullDuplexSerial"
    
    pub here | baudrate
        cognew(@getbitcycles, @result)
        repeat until result
        baudrate := clkfreq/result
        fds.start(RX_PIN, TX_PIN, 0, baudrate)
        repeat
           
           char:= fds.rx 'makes char the same as character coming in
           fds.tx(char)
    
           case char  'checks char against following cases
             "u":     ' executes subroutine "this"
               this
             "a":
               that     'executes subroutine "that"
    
    
    Pri this        'blinks LED on and off 2 times
    dira [LED_PIN]~~
     repeat 4
           
            !outa[LED_PIN]
            waitcnt(8_000_000+cnt)
        
    pri that        'blinks LED on and off 4 times
        dira[LED_PIN]~~
        repeat 8 
           
           !outa[LED_PIN]
            waitcnt(4_000_000+cnt)
    
    ' This PASM code measures the bit time of the serial port
    ' You must enter a character with a 1 in the LSB and a 0
    ' in the second bit, such as a CR
    dat
    getbitcycles  waitpeq         zero, mask
                  mov             start, cnt
                  waitpeq         mask, mask
                  mov             stop, cnt
                  sub             stop, start
                  wrlong          stop, par
                  jmp             #$
    
    stop          long            0
    start         long            0
    zero          long            0
    mask          long            $80000000
    
Sign In or Register to comment.