Shop OBEX P1 Docs P2 Docs Learn Events
Parallax Serial Terminal - Disable If Not Connected? — Parallax Forums

Parallax Serial Terminal - Disable If Not Connected?

Hey guys,
I have a device that communicates with the Parallax Serial Terminal (PST) for debugging purposes. Most of the program executes sequentially, so when there is a lot of data/traffic occurring, the PST creates extra delay in various functions.
It got me thinking... if I don't have the USB prop plug connected, its still creating this same delay in my program isn't it?

If this is the case, would I have to have 2 separate programs (one for debugging, and one for production that has all of the PST stuff stripped out?)
How are you guys handling this?
Thanks and any help/advice is greatly appreciated!

Comments

  • Mahonroy wrote: »
    Hey guys,
    If this is the case, would I have to have 2 separate programs (one for debugging, and one for production that has all of the PST stuff stripped out?)
    How are you guys handling this?

    Basically yes.

    One alternative is to use a dummy serial driver. I've attached my version of "Parallax Serial Terminal.spin" which has all the methods but the methods don't do anything (except the "RxCount" method).

    I use this as the RxCount:
    PUB RxCount
    
      result := 1
    

    This allow my "Press any key to start." beginning to keep the program from stopping.
      repeat
        waitcnt(clkfreq / 2 + cnt)
        Pst.Str(string(11, 13, "Press any key to start."))
        result := Pst.RxCount
      until result  
      result := Pst.RxFlush
    

    The dummy methods still slow the program down a bit but not nearly as much as the original serial methods.




  • Duane DegnDuane Degn Posts: 10,588
    edited 2016-04-29 23:51
    Another option would be to use conditional compilation.

    The Propeller Tool doesn't support conditional compilation but you can kind of fake it by using code like the code below.
    PUB CheckLogTimer | intervalTicks, frozenLoggerFlag
    '' Called from "MainSensorLoop".
    
      intervalTicks := logInterval208 * Header#SECOND
    
      result := cnt - logTimer210
    
      {Start Debug CheckLogTimer}
      Serial.Strs(USB_PORT, string("intervalTicks = "))
      Serial.Dec(USB_PORT, intervalTicks)
      Serial.Str(USB_PORT, string(", cnt - logTimer210 = "))
      Serial.Dece(USB_PORT, result)
      {Debug CheckLogTimer End}
      
      if result > intervalTicks or result < 0    
        logTimer210 += intervalTicks
        {Start Debug CheckLogTimer}
        Serial.Strse(USB_PORT, string("Yes Write", 11, 13))
        {Debug CheckLogTimer End}
       
        frozenLoggerFlag := activeLoggerFlag212
        if frozenLoggerFlag & START_LOG_BIT_1
          {Start Debug CheckLogTimer}
          Serial.Strse(USB_PORT, string("Yes Write", 11, 13))
          {Debug CheckLogTimer End}
          if previousSensorLoggerFlag & START_LOG_BIT_1
            WriteLog
          else 
            StartLog
    
        previousSensorLoggerFlag := frozenLoggerFlag
        
    

    In the above code all the serial calls would be executed but if I use "search and replace" and replace all the "{Start Debug CheckLogTimer}" text with "{{Start Debug CheckLogTimer}" and all the "{Debug CheckLogTimer End}" text with "{Debug CheckLogTimer End}}", then the serial calls are commented out.

    This has the benefit of not only increasing the speed of the program but it also frees up the memory used by the code.

    I have a list of these "Start" and "End" indicators listed at the bottom of my program. Here are a few examples:
      {{Start Debug FindFlashBackupLoc}{Debug FindFlashBackupLoc End}}
      {{Start Debug StartLog}{Debug StartLog End}}
      {Start Debug CheckLogTimer}{Debug CheckLogTimer End} 
      ' Only the debug code in the "CheckLogTimer" method is active in this example.
    

    I use this list with search and replace to either enable or disable debugging code. I can disable all the debugging code by replacing all instances of "{Start Debug" with "{{Start Debug" and replacing "End}" with "End}}". (I then have to replace some instances of "{{{" with "{{" and replace "}}}" with "}}".)

    I'm not trilled with my techniques of enabling and disabling debugging code but I don't know of a better way of doing this using the Propeller Tool. I'd be very interested to learn what other techniques people use.

    BTW, the serial object my examples use includes a lock. This is why there are calls to "Serial.Strs" and the like. "Strs" is method which both sets the lock and calls the normal "Str" method. Using locks like this allows me to use the serial driver from multiple cogs (and since all the variables are in the DAT section, I can use it from multiple objects).
  • I detect that the USB is present and set a flag accordingly by one or a combination of means:
    -- Test that 5 volts is present, easy to do with an on-board FT chip but not with a Prop plug.
    -- With a 4.99kΩ pulldown resistor on the rx line, test Prop pin p31. It will be low if the FTchip or Prop plug are not connected, and high when connected. A relatively low resistance pulldown (like 5k) is necessary.
    -- By user input at reset

    The serial interface and debug should be funneled through relatively few methods so that there need be only a few tests of the USB-present flag.

    If the USB is not present the code can even shut down the serial port cog to save power. One has to be sure that there are no uncovered calls to certain serial methods that will lock up if the pasm is not running.
  • ElectrodudeElectrodude Posts: 1,657
    edited 2016-04-30 20:36
    If you want to be able to enable and disable it at runtime without inserting tests in your code everywhere, you could add something like these untested disable and reenable methods to "Parallax Serial Terminal.spin". It sets the tx_tail and rx_head variables to invalid values that will make the Char and RxCheck methods always think there's more room or data in the buffer. It fills the receive buffer with spaces, but you can change that by changing the bytefill line.
    PUB disable
    
      ifnot cog ' return now if it was never started
        return
    
      cogstop(cog - 1)  ' stop serial cog, but don't clear cog so reenable knows it was started once
    
      bytefill(@rx_buffer, " ", BUFFER_LENGTH) ' fill receive buffer with spaces
    
      tx_tail~~ ' set tx_tail to -1 to fool Char into thinking there's always room in the buffer
      rx_head~~ ' set rx_head to -1 to fool RxCheck into thinking there's always room in the buffer
    
    PUB reenable : okay
    
      if cog == 0 or tx_tail <> -1 ' return now if it wasn't first started and then disabled
        return
    
      ' reset buffers
      tx_tail~
      tx_head~
      rx_tail~
      rx_head~
    
      ' restart cog
      okay := cog := cognew(@entry, @rx_head) + 1
    

    You'll also need to modify RxCount like so, to make it not return 0 every BUFFER_LENGTH-th byte:
    PUB RxCount : count
    {{Get count of characters in receive buffer.
      Returns: number of characters waiting in receive buffer.}}
    
      if tx_tail == -1 ' if it's disabled
        return 1 ' maybe returning BUFFER_LENGTH or something would be better?
    
      count := rx_head - rx_tail
      count -= BUFFER_LENGTH*(count < 0)
    
  • How about a loop which is either run once for debug code, or not at all if production code.
    CON
    
    ' set DBG = 1 for DEBUG code, set DBG to 0 for no debug
    DBG = 0
    
    VAR
    
    long  x, y ,z    
    
    PUB myFunc(a,b,c) | retCode
    
      retCode := DBG  
      
      repeat DBG
        x := a
        y := b
        z := c
    
      return retCode 
    
  • Thanks a lot for all of the info! I think I like the idea of swapping in a dummy PST the best. This way I can keep all of the code the same.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2016-05-02 15:00
    I detect that the USB is present and set a flag accordingly by one or a combination of means:
    -- Test that 5 volts is present, easy to do with an on-board FT chip but not with a Prop plug.
    -- With a 4.99kΩ pulldown resistor on the rx line, test Prop pin p31. It will be low if the FTchip or Prop plug are not connected, and high when connected. A relatively low resistance pulldown (like 5k) is necessary.
    -- By user input at reset

    Tracy,

    With an on-board FTDI chip you can also (at the cost of an I/O pin) monitor the link status GPIO pin from the FTDI chip for connect status. I think I would do this is my program was more based on availability of the connection for more than just debugging.

  • Tracy AllenTracy Allen Posts: 6,664
    edited 2016-05-03 04:42
    Hi Chris, which GPIO you mean for link status? There isn't a dedicated pin for that purpose, so it must be one of the configurable CBUS pins. The closest option seems to be pwren#, is that it? It goes low when the FT chip is fully enumerated on the USB bus but not in suspend mode. It is sometimes used to turn on peripherals that draw up to 1/2A from USB, or to enable a battery charger up to the same limit. But it could also act as a signal to the Prop that the USB is connected and ready to talk. I'm using pwren# often for a battery charger, but have thought about using a second instance to help distinguish a dumb charger from a real USB bus. The pwren# signal can be dissociated from the bcd# (battery charge detect) signal. No point in having the user interface running when there is only a dumb charger connected.

  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    Tracy,

    Correct. CBUS3 defaults to PWREN#.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2016-05-03 16:50
    Understood. Though, I'll note that I'm using the FT231X instead of the FT232R, and it does not include pwren# among its defaults. That has to be configured using the FTprog.exe utility.

    @Mahoney, on focus, I agree that substituting the dummy PST like Duane suggested in the first post could be the most carefree option. That is, so long as there aren't weird timing or other issues introduced by that very debugging or lack thereof!
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    Interesting. CBUS3 is SLEEP# on the FT231X. Well, what I suggested isn't very useful for most applications and consumes and I/O pin, but it's nice to know you have options. =)
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2016-05-03 18:03
    In the case of the PropPlug being plugged in or not, I think you could just force the Rx line low for a few machine cycles, then tri-state the line and see if it comes back high very quickly. If there's a pull-up on that line, the timing for returning high vs. being driven high is a little more critical, though. Also, if the PropPlug is connected and receiving data, that test might not work. But in the case of PST, the line is idle unless someone is keying stuff in.

    Also, if there is no pull-up on Rx, connecting a 10K resistor between Tx and Rx will allow you to check for an echo on Rx. If there's an echo when you activate Tx, no PropPlug. Of course, without any pull-ups or Tx or Rx, the phantom reset becomes a problem.

    -Phil
  • Oh yes, the notorious phantom reset. 1) not a problem with a pulldown on the p31 rx data line, I don't understand why people want to use a pullup there. 2) a pulldown there makes it easy to test for presence of the Prop plug/FT23x and to start the serial object or not, thus avoiding phantom reset.

    PhiPi phantom reset exposé
    http://forums.parallax.com/discussion/comment/847328/#Comment_847328
  • I just run a search and replace all on "pst." and change it to "'pst.". This effectively remarks all of the calls to the debugger and prevents it from being started without changing any of the code. Not fancy but easy.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2016-05-08 19:18
    Oh yes, the notorious phantom reset. 1) not a problem with a pulldown on the p31 rx data line, I don't understand why people want to use a pullup there. 2) a pulldown there makes it easy to test for presence of the Prop plug/FT23x and to start the serial object or not, thus avoiding phantom reset.

    I've always liked pull-ups on P30 and P31, since that's the default marking condition, and it cures the phantom reset -- but not in a very nice way. However, in the case of detecting the presence of a USB-powered FTDI device, a pull-down on P31 (and no pull-up on P30) is a clever way to do it. Thanks, Tracy! If you use that circuit, though, you have to be diligent not to activate P30 unless you detect the FTDI chip on P31, else the phantom reset will occur.

    -Phil
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    Phil,

    I could be wrong, but I don't think the FT231X has that reset issue when energizing the RX line.
Sign In or Register to comment.