Announcement

Collapse
No announcement yet.

XON XOFF on the COM Ports

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Donald Darden
    replied
    The maximum transfer rate of 9600 may well exceed the ability of
    some equipment, forcing it to return an XOFF signal when it
    cannot accept any more data. XOFF is suppose to tell YOU to
    quit sending data to it -- it could still have some data to
    send back to you, which it will do so. Which explains why you
    see more data coming back after the XOFF signal.

    The XOFF signal is not exact. Typically, the XOFF signal is
    triggered when the receive buffer is about 3/4ths full, meaning
    it can still accept some data beyond that point. The XON signal
    is usually triggered when the buffer falls to only 1/4th full.
    Between these two levels, you should be able to sustain a fairly
    regular flow of data.

    Depending upon the actions of the machine, it may go long
    periods where it has other tasks to perform and cannot remove
    data from the receive buffer. So the XOFF flag goes up. You
    have to wait until it clears with the XON flag before sending
    it more data.

    Sending data in smaller increments can be of some help if you
    then wait to see if the machine is trying to signal you in
    between. The optimum size of your output should be set at just
    under half of the target machine's buffer size - That way you
    should trigger an XOFF automatically so that you can then
    wait for the next XON. Between the 1/4th buffer when the XON
    occurs and the 1/2 buffers size that you send, you should not
    exceed 3/4ths of the target machine's capacity. The under 1/2
    size works so that the first and second groups together will
    not exceed the full buffer size.

    Note that the 1/4th and 3/4th levels are arbitrary - different
    designers could have selected other trigger points. You may
    have to read up on the machines or experiment for best results.

    If you need to work with several ports at once, you might need
    to look at a third party communications library, such as the
    ones from MarshallSoft. Check out the 3rd party links on the
    home page. These are very robust, and give you lots of added
    ports capability.

    PowerBasic is far more powerful and flexable than the QBASIC
    and QuickBASIC products from MicroSoft. Anything that you can
    do with those languages can be done as well or better in
    PowerBASIC, but you need to get into the language a bit to
    find out yourself. Be assured that your efforts will not be
    wasted. PowerBASIC also includes an inline assembler capability,
    whereas the MicroSoft products could only use data statements
    and poke them into memory, or use BLOAD to haul in a binary
    file. That means you can do all your development right within
    PowerBasic, which is not really true for QBASIC or QuickBASIC.





    ------------------
    Old Navy Chief, Systems Engineer, Systems Analyst, now semi-retired

    Leave a comment:


  • Tom Hanlin
    replied
    I wish I could answer that. But, it's in the class of generic questions.
    I haven't run into a similar problem myself, I haven't seen your code, and
    the nature of the problem offers no suggestions to me. Provide more data or
    forever hold your peace.


    ------------------
    Tom Hanlin, PowerBASIC Staff
    Opinions expressed may not be those of my employer or myself

    Leave a comment:


  • Mike Luther
    replied
    Tom,

    Is this why I've never been able to yet implement the IRMAN TV handheld
    button control in PB 3.5's comm routines?

    [quote]
    Local output buffers may be full without the UART buffers being full.
    The BASIC statements get priority. DOS wasn't much at multitasking, and
    local events might have to wait for a convenient time to run. Try to
    bear in mind that the original PC had a 4.77 MHz CPU, and was "16 bits"
    wide mostly in an advertising sense. Things have changed a little but,
    oddly enough, there hasn't been tremendous pressure to update old DOS
    designs.

    It's a safe bet that DOS BASIC "events" didn't necessarily trigger until
    the current "line" finished whatever it was doing. In some cases, that
    could be quite a while.
    [/quote)

    Working in OS/2's DOS-VDM session, I have only a one byte sent to the
    device to initiate it, and a one byte sent back from the device reply
    to initiate it. It has been a long time since I tried to implement the
    units here. And I do have Ray Gwinn's PMLM utility for OS/2 which will
    let me see exactly the complete byte by byte I/O both ways for any
    given comm port. Without looking at the old research right now my
    memory is that I saw the output byte go down the port to the unit and
    the return byte come back in the port. But I could never get that
    single byte passed back to the program through PB to finish the init
    job for the device.

    ------------------
    Mike Luther
    [email protected]

    Leave a comment:


  • Tom Hanlin
    replied
    Maybe. The PB/Dos manual says there are comm I/O buffers. I can put it
    up for review by R&D.

    Local output buffers may be full without the UART buffers being full.
    The BASIC statements get priority. DOS wasn't much at multitasking, and
    local events might have to wait for a convenient time to run. Try to
    bear in mind that the original PC had a 4.77 MHz CPU, and was "16 bits"
    wide mostly in an advertising sense. Things have changed a little but,
    oddly enough, there hasn't been tremendous pressure to update old DOS
    designs.

    It's a safe bet that DOS BASIC "events" didn't necessarily trigger until
    the current "line" finished whatever it was doing. In some cases, that
    could be quite a while.

    ------------------
    Tom Hanlin, PowerBASIC Staff
    Opinions expressed may not be those of my employer or myself

    Leave a comment:


  • Paul Dixon
    replied
    Tom,
    <<Is there a way to detect if the output buffer on a COM port is empty?>>

    If the UART has no data to send then there is no data in any transmit buffer since, if there was, it would have replenished the UART FIFO long before the UART registers became empty.
    The UART triggers the next reload while the FIFO still has bytes in the queue waiting to send to make sure this happens so there are no gaps in transmission.

    If I remember right, PB/DOS doesn't have any output buffer anyway so the UART registers are all there is.

    Paul.

    ------------------

    Leave a comment:


  • Tom Hanlin
    replied
    The UART output bits may be a useful hint but, they won't tell you
    whether PB's own I/O buffers are empty. Might work.

    I find that my old PBWiz library did come with its own telecomm support.
    You can check the buffer states and, possibly, do your own modifications
    (some assembly-language experience may be required). PBWiz is owned and
    sold by http://infoms.com/ these days -- it's been years since they've
    updated their web site but, as far as I know, they're still operational.
    A key limitation is, PBWiz only supported a single comm port at a time,
    last I looked. But, it was very good at dealing with the one comm port...

    ------------------
    Tom Hanlin, PowerBASIC Staff
    Opinions expressed may not be those of my employer or myself

    Leave a comment:


  • Paul Dixon
    replied
    Kip,
    <<Is there a way to detect if the output buffer on a COM port is empty?>>

    If you look directly at the registers in the UART chip (the one that's doing the serial communications for you) Bit 6 of register 5 is set (=1) when the transmitter FIFO and Transmitter shift register are empty.

    If your program is running in DOS or Win3.x/Win9x then you can look at this bit directly.
    WinNT/XP might not let you.

    Paul.



    ------------------

    Leave a comment:


  • alan norman
    replied
    Here's some rough but working Xon / Xoff code in PBDOS V3
    It should at least provide an Idea,

    Code:
    'Serial transmitter using Xon/Xoff
    Bytes = 10000 ' transmit 10K characters
    Comport$ = "1"
    %XON  = 17
    %XOFF = 19
    %TRUE  = 1
    %FALSE = -1
    $COM  1024
    
    M% = Freefile
    CLS
    
    ON COM(val(Comport$)) gosub testchar
    
    c$="COM"+Comport$+":9600,n,8,1,RS,CS0,DS0,CD0,PE"
    open C$ AS #M%
    COM(VAL(Comport$)) ON  'set trapping on
    for I&= 0 to bytes
     X$=CHR$(32+(I& MOD 90))
     PRINT #M%,X$;
     'delay to allow trap to work ???
     for D&=1 to 40000:incr J:next
    next
    
    Close #1
    end
    
    testchar:
    
    COM(VAL(Comport$)) OFF 'set trapping off
    locate 2,1:? "Trap triggered"
    XF% = %FALSE
    
    do
     if LOC(M%)>0 then
      Y$=INPUT$(1,M%)  'collect a character
      Select Case ASCII(Y$)
            CASE %XOFF
              XF% = %TRUE
              locate 3,1:? "XOFF RECIEVED"
            CASE %XON
              XF% = %FALSE
              locate 3,1:? "XON  RECIEVED"
            CASE ELSE
              'drop all others
      END SELECT
     else
      delay 0.25 ' waiting for XON
     end if
    loop until XF% = %FALSE
    
    COM(VAL(Comport$)) ON  'set trapping on
    
    return
    Alan


    ------------------
    http://www.allthingsspiny.co.uk

    [This message has been edited by alan norman (edited November 15, 2004).]

    Leave a comment:


  • Tom Hanlin
    replied
    PB/DOS doesn't offer a way to find out how many characters are in the
    output buffer. I can put it on the wish list. In the meantime, other
    than doing your own timing, all I can suggest is a third-party comm
    driver. At worst, it should certainly be possible to find one that
    comes with source code that you can modify. I'll see if I can rummage
    around a bit this evening.


    ------------------
    Tom Hanlin, PowerBASIC Staff
    Opinions expressed may not be those of my employer or myself

    Leave a comment:


  • Kip Moravec
    replied
    I just reread my original post. This was never answered.

    Is there a way to detect if the output buffer on a COM
    port is empty?

    Kip

    ------------------

    Leave a comment:


  • Kip Moravec
    replied
    I checked all the code in your library and there is nothing
    that impliments XON/XOFF.

    ----------------

    It looks like there is not a delay or sleep function that
    works for 1 millisecond.

    So is the only way to impliment a delay like you suggest is to
    use the MTIMER function and loop until it is greater than the
    number I need for the character rate?

    Kip


    ------------------

    Leave a comment:


  • Tom Hanlin
    replied
    Kip, 9600 bps would be about 960 characters per second. Just use a timer
    to make sure that you're not sending the next character before the first
    character has a chance to clear.

    You might also check the Downloads section for other comm solutions.

    http://www.powerbasic.com/files/pub/pbdos/telecom/

    ------------------
    Tom Hanlin, PowerBASIC Staff
    Opinions expressed may not be those of my employer or myself

    Leave a comment:


  • Kip Moravec
    replied
    The machine is a FUJI MCS-16F. It is designed to program
    SMT machines. FUJI has made it very difficult to get past
    the applications program and into the guts of the OS to change
    anything.

    It has about 10 Serial ports which have pinouts different than
    the standard PC. We have built a cable to convert it. It can talk
    to up to 8 machines at 9600 bps. each on its own serial port.
    They talk to the machines, (upload and download files) at 9600
    bps all day.

    The parameters we can get to allow us to change the baud rate to
    2400, 4800, 9600, 19200, 34600 bps. I have tried going at 2400
    baud with a faster computer and have still lost data. I believe the
    problem is the serial port buffer is to big and too many characters
    are sent after the XOFF.

    When I am downloading a file, the reciever only sends XON/XOFF.
    It does not echo what is sent. It does not acknowledge an end of
    line. Nothing until the end of file string is sent.


    I want to send one character at a time, wait for the output buffer
    to clear, check for incoming characters, then send the next character.
    That can't be that hard can it? I know it is not efficient, but
    how do I do it?




    ------------------

    Leave a comment:


  • Mel Bishop
    replied
    Okay. If all you are doing is transferring files from one
    machine to another, what I would do:

    Have the sending machine get a "packet" of data from the file.
    The size of the packet will depend on the size of your buffer(s).
    Send that packet to the receiving machine. After the receiver
    gets the packet and processes it, have it send a signal to the
    transmitter that its ready for the next packet.

    You will have to write two programs, one for the transmitter and
    one for the receiver, but PB/DOS can do this quite readily.

    *******

    Another thought: If you can load DOS 6.x (even from a floppy),
    set up INTERLNK/INTERSVR and use that. I've used it quite
    successfully in the past.



    ------------------

    Leave a comment:


  • Kip Moravec
    replied
    It is a 1988 vintage machine running 3 wire RS-232 (no CTS/RTS).
    Right now the only computer that works transferring the data
    down is a 350 MHz Pentium. Running Windows 98 (First Edition)
    I can not make faster computers work with the existing QBASIC
    program which I do not have the source for.

    It goes along pretty well then sends a XOFF, sometimes for
    less than a second, and sometimes for as long as 10 seconds.

    I am downloading files to the machine. They range from 7K to
    about 70K. I can watch the protocol with a simple protocol
    analyser. I can see the XOFF, I can see how many characters
    are sent after the XOFF. I can see the XON.

    I can put a delay after every line, but it looks like the
    machine I am talking to stops in different places for
    different lengths of time. The XON/XOFF needs to work.

    Rather than argue the merits of doing what I must do, how about
    giving me a way to do it on Power Basic, or I will have to go
    to some other language. I can do this no problem with a
    microcontroller, I can't do it with a PC, and Power Basic, yet.

    Kip

    ------------------

    Leave a comment:


  • Mel Bishop
    replied
    > I guess my C roots are showing

    Oops! You were talking apples and I was thinking oranges. But
    both are still fruit. Oh well....

    Another possibility: Check your old machine and see if hardware
    flow control is available. If not, see if you can change its
    output buffer and its associated parameters.



    ------------------

    Leave a comment:


  • Kip Moravec
    replied
    I got the last = wrong in the long equivalence...

    XON = 17 Decimal
    XOFF = 19 Decimal

    ------------------

    Leave a comment:


  • Tom Hanlin
    replied
    C/R doesn't, eh, "enter" into it.

    0x13 = &H13 --> CHR$(19), which is Control-S, or <XOFF>.
    0x11 = &H11 --> CHR$(17), which is Control-Q, or <XON>.

    If you need to stop within just a few characters, it sounds like
    something is broken on the other end. It should be able to send an
    <XOFF> at speed well before it's in danger of running out of buffer
    space. Doesn't sound like it was designed to handle 9600 bps.

    Then again, maybe it's not really an issue. Start by not worrying
    about the output buffer, and see if it becomes a problem. Give
    first priority to reading incoming data, and dribble out the output
    at just a character or so a time, before going back to check the
    input buffer.

    If the output buffer turns out to be a problem, you can add a timer
    to make sure that you're not sending characters out faster than the
    line can actually handle. That way, the buffer will never have the
    chance to fill.

    ------------------
    Tom Hanlin, PowerBASIC Staff
    Opinions expressed may not be those of my employer or myself

    Leave a comment:


  • Kip Moravec
    replied
    I guess my C roots are showing.

    0x13 means 13 Hex = 19 Decimal = chr$(19) = Control S on the Keyboard = XON.


    0x11 means 11 Hex = 17 Decimal = chr$(11) = Control Q on the Keyboard = XOFF.

    I use hexadecimal because that is what the protocol analyzer
    provides, and I am more used to it for control codes than decimal.

    Kip

    ------------------

    Leave a comment:


  • Mel Bishop
    replied
    For the actual characters for xoff/xon, check out:
    http://searchnetworking.techtarget.c...213406,00.html

    0x13 is a c/r (Enter key). I don't know where your old machine
    got its protocol, but chr$(13) is not the standard software flow
    control protocol.

    If you can't change their protocol and have to use theirs, you
    may try something like:

    t$ = input$(1,#1) example from your comm port
    if t$ = xoff$ then gosub IdleUntil ' to empty out the buffer(s)


    ------------------

    Leave a comment:

Working...
X