Announcement

Collapse
No announcement yet.

XON XOFF on the COM Ports

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

  • XON XOFF on the COM Ports

    I am trying to talk to a very old machine running OS-9.

    It uses XON XOFF for letting me know when the buffers are full.

    When they send me a 0x13 I should stop, and when they send 0x11
    I need to start.

    I do not know how to do this with PB35/DOS. I need it to
    respond quickly - within a couple of characters.

    It seems like this is just the opposite of what the
    buffer is for. I need to send one character, check for a XOFF,
    and if none send the next character. If there is an XOFF
    then do not send the next character, and wait for an XON.

    I could probably do this if I could detect if the COM port
    Output Buffer was empty. But I don't know how to do that either.

    The required speed is 9600 bps, but I would like it to
    run faster if I can stop the output quick enough. The program
    I am replacing sometimes sends 10 characters or more after the
    XOFF and as a result sometimes data is lost.

    Is it as simple as setting the buffer size to 1?

    Kip

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

  • #2
    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)


    ------------------
    There are no atheists in a fox hole or the morning of a math test.
    If my flag offends you, I'll help you pack.

    Comment


    • #3
      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

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

      Comment


      • #4
        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

        Comment


        • #5
          I got the last = wrong in the long equivalence...

          XON = 17 Decimal
          XOFF = 19 Decimal

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

          Comment


          • #6
            > 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.



            ------------------
            There are no atheists in a fox hole or the morning of a math test.
            If my flag offends you, I'll help you pack.

            Comment


            • #7
              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

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

              Comment


              • #8
                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.



                ------------------
                There are no atheists in a fox hole or the morning of a math test.
                If my flag offends you, I'll help you pack.

                Comment


                • #9
                  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?




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

                  Comment


                  • #10
                    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

                    Comment


                    • #11
                      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


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

                      Comment


                      • #12
                        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

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

                        Comment


                        • #13
                          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

                          Comment


                          • #14
                            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).]
                            http://www.allthingsspiny.co.uk

                            Comment


                            • #15
                              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.



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

                              Comment


                              • #16
                                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

                                Comment


                                • #17
                                  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.

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

                                  Comment


                                  • #18
                                    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

                                    Comment


                                    • #19
                                      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]
                                      Mike Luther
                                      [email protected]

                                      Comment


                                      • #20
                                        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

                                        Comment

                                        Working...
                                        X