Jump to content
BeeryMiller

RS232 Programming

Recommended Posts

I need some insight to understand a few things.

 

I'm working with the My-Term source code. I've never been great with the RS232 programming and have always relied on the code of others and their comments to figure out how they were sending and getting characters from the RS232 port.

 

Is there something special with any of the bits programmers are doing to establish Flow Control? Or is it just a matter of polling the RS232 with enough frequency to capture the characters.

Specifically, I am trying to make sure I do not drop any characters from the RS232 using the Lantronix UDS-10. I know at both 19.2K and 38.4K I can drop some characters when I am using Telnet to another telnet BBS. Is there something I can do to prevent those loss of characters?

 

FWIW, I am using the cable specified in Tim's Port document for cable setup.

 

Thanks for any feedback.

 

Beery

 

 

 

Share this post


Link to post
Share on other sites

Can you not use RTS/CTS handshaking? If you have, say a 64 byte receive buffer, you drop CTS when you have, say, 58 characters in the buffer. That way the UDS should stop sending before you overrun your buffer. Response latency of the UDS 10 (i.e. how long it takes to obey your request to stop) will probably be a function of the baud rate.

 

99% of folk implement RS232 as a three-wire, but it's far better to implement 5 wire (data with RTS/CTS) if you can.

Share this post


Link to post
Share on other sites

Can you not use RTS/CTS handshaking? If you have, say a 64 byte receive buffer, you drop CTS when you have, say, 58 characters in the buffer. That way the UDS should stop sending before you overrun your buffer. Response latency of the UDS 10 (i.e. how long it takes to obey your request to stop) will probably be a function of the baud rate.

 

99% of folk implement RS232 as a three-wire, but it's far better to implement 5 wire (data with RTS/CTS) if you can.

 

 

The hardware handshakes are ideal until you discover you are communicating with a system that is slow to recognize them.

 

I have had that happen in the old days.

Share this post


Link to post
Share on other sites

From my page on ninerpedia:

 

Software handshaking is within the responsibility of the applications that use the serial connection; it is implemented by sending control bytes (X-ON, X-OFF) over the data line.

Hardware handshaking is possible at two levels:

  • using RTS and CTS,
  • using DTR and DSR.

The difference between both is that RTS/CTS handshaking has immediate effect on the transmission of the UART (a cleared CTS line turns off the transmitter of the UART) while DTR/DSR are handled by interrupts that are signaled to the application.

Share this post


Link to post
Share on other sites

From my page on ninerpedia:

 

Software handshaking is within the responsibility of the applications that use the serial connection; it is implemented by sending control bytes (X-ON, X-OFF) over the data line.

Hardware handshaking is possible at two levels:

  • using RTS and CTS,
  • using DTR and DSR.

The difference between both is that RTS/CTS handshaking has immediate effect on the transmission of the UART (a cleared CTS line turns off the transmitter of the UART) while DTR/DSR are handled by interrupts that are signaled to the application.

 

Let's explore this comment a bit further. As my intentions are for Telnetting purposes with the potential one could either be using the Lantronix UDS-10 or the Wifi2Modem, which method (RTS/CTS or DTR/DSR) would be preferred with a reasonable expectation no characters would be lost? I assume this is setting a bit on the RS232?

 

Listed below is the RS232 code MyTerm is using. Can someone comment what would need to be changed? There is an approximate 8K circular buffer as is right now and I see some places in the program I can speed up character acquisition.

 

Any thoughts appreciated.

 

 

*

* INIT Initialize RS232
*
INIT0 MOV @CRUBAS,R12 Get CRU base
LIMI 0 No interrupts
SBO 0 Turn on RS232 card
MOV R12,R9 Save CRU base
MOV @PORTDT,R12 Get port address
SBO 31 Start initialization
LI R0,>20 Delay counter
INIT1 DEC R0 Waste time
JNE INIT1 Keep waiting
SBZ 13 Start data initialization
MOV @PARIDT,R1 Get parity data
LDCR R1,8 Set parity
MOV @BAUDDT,R1 Get baud rate data
LDCR R1,12 Set baud rate
MOV R9,R12 Get CRU base
SBZ 0 Turn off RS232 card
RTWP Return to caller
*
* GETRS Get a Character from the RS232 Port
*
GETRS0 LIMI 0 No interrupts
BL @GETRS1 Do routine
RTWP Return to caller
GETRS1 MOV @CRUBAS,R12 Get CRU base
SBO 0 Turn on RS232 card
MOV R12,R9 Save CRU base
MOV @PORTDT,R12 Get port address
TB 21 Is a character waiting?
JNE GETRS3 No, Return to caller
STCR R10,8 Yes, Get character
SBZ 18 Tell RS232 we have it
ANDI R10,>7F00 Strip off high bit
MOV @CPOINT,R8 Get buffer pointer
MOVB R10,*R8+ Store character
CI R8,>6000 End of memory?
JL GETRS2 No, Skip this
LI R8,BUFF Loop to start of buffer
GETRS2 MOV R8,@CPOINT Store buffer pointer
SETO @CFLAG Set buffer flag
GETRS3 MOV R9,R12 Get CRU base
SBZ 0 Turn off RS232 card
RT Return to caller
*
* ECHO Echo a Character Over RS232 Port
*
ECHO0 MOV @PORTDT,@RTSVPT Save port address
ECHO0A MOVB *R13,R0 Get character
MOV @PORTDT,R12 Get port address
ANDI R12,>FF00 Get CRU base
LIMI 0 No interrupts
SBO 0 Turn on RS232 card
MOV R12,R9 Save CRU base
MOV @PORTDT,R12 Get port address
SBO 16 Start character send
ECHO1 TB 22 Is RS232 ready?
JNE ECHO1 No, Keep waiting
LDCR R0,8 Yes, Send character
SBZ 16 Tell RS232 we're ready
MOV R9,R12 Get CRU base
SBZ 0 Turn off RS232 card
MOV @RTSVPT,@PORTDT Restore port address
RTWP Return to caller

Share this post


Link to post
Share on other sites

I'm making some headway as of last night with the RTS/CTS handshaking. Still not quite getting what I want, but a lot closer. I did determine why my 38.4K baud transfers were failing with the addition of some inline error reporting and have been successful at versions of MDOS with a few temporary fixes. What I need now is a short hex to decimal display routine shorter than the one I am using. That will fix one issue and show the progress of the file transfer with a counter.

 

Beery

Share this post


Link to post
Share on other sites

I'm making some headway as of last night with the RTS/CTS handshaking. Still not quite getting what I want, but a lot closer. I did determine why my 38.4K baud transfers were failing with the addition of some inline error reporting and have been successful at versions of MDOS with a few temporary fixes. What I need now is a short hex to decimal display routine shorter than the one I am using. That will fix one issue and show the progress of the file transfer with a counter.

 

Beery

 

Is there a specific reason yo use 38.4k?

 

In my experience that is a pretty fast data rate for a slow machine. Without a interrupt driven receive I would think you would do better down at 9600 or below with a machine like the TI-99.

Share this post


Link to post
Share on other sites

 

Let's explore this comment a bit further. As my intentions are for Telnetting purposes with the potential one could either be using the Lantronix UDS-10 or the Wifi2Modem, which method (RTS/CTS or DTR/DSR) would be preferred with a reasonable expectation no characters would be lost? I assume this is setting a bit on the RS232?

 

Listed below is the RS232 code MyTerm is using. Can someone comment what would need to be changed? There is an approximate 8K circular buffer as is right now and I see some places in the program I can speed up character acquisition.

 

Any thoughts appreciated.

 

 

Also when looking at your buffer code, I think you can replace 4 instructions with 1 AND immediate instruction if you make your buffer size a power of 2.

* Original code
       MOV  @CPOINT,R8   Get buffer pointer
       MOVB R10,*R8+     Store character
       CI   R8,>6000     End of memory?
       JL   GETRS2       No, Skip this
       LI   R8,BUFF      Loop to start of buffer
* possible (un-tested) replacement code for
* buffer wrapping
* Assumes buffer is >2000 bytes in size

       MOVB R10,*R8+     Store character
       AI   R8,>1FFF        binary wrap R8
Edited by TheBF
  • Like 1

Share this post


Link to post
Share on other sites

 

Is there a specific reason yo use 38.4k?

 

In my experience that is a pretty fast data rate for a slow machine. Without a interrupt driven receive I would think you would do better down at 9600 or below with a machine like the TI-99.

 

 

Pushing the limits and finding out first-hand 'what can be' is a common human trait. With that in mind, faster could be a reason in itself.

 

Share this post


Link to post
Share on other sites

 

 

Pushing the limits and finding out first-hand 'what can be' is a common human trait. With that in mind, faster could be a reason in itself.

 

 

:) I will accept that as a noble goal.

 

With serial communication I lean toward reliability over absolute speed so I am biased.

Share this post


Link to post
Share on other sites

 

:) I will accept that as a noble goal.

 

With serial communication I lean toward reliability over absolute speed so I am biased.

 

I've got a couple of purposes here. One, I am wanting to get the maximum reliable transfer speed. I know 38.4K is possible, because Tim has done it. Once I have that part completed and I am satisfied I can sustain those transfer rates, I want to add multi-file transfer capability. That way, I can backup the Geneve to a BBS area or to an emulated MAME image of a Geneve running on another computer and not have much to worry about a hard drive crash or other equipment failure. File transfers at 38.4K will be 4 times quicker than a 9600 baud transfer.

Share this post


Link to post
Share on other sites

 

 

Also when looking at your buffer code, I think you can replace 4 instructions with 1 AND immediate instruction if you make your buffer size a power of 2.

* Original code
       MOV  @CPOINT,R8   Get buffer pointer
       MOVB R10,*R8+     Store character
       CI   R8,>6000     End of memory?
       JL   GETRS2       No, Skip this
       LI   R8,BUFF      Loop to start of buffer
* possible (un-tested) replacement code for
* buffer wrapping
* Assumes buffer is >2000 bytes in size

       MOVB R10,*R8+     Store character
       AI   R8,>1FFF        binary wrap R8

 

Interesting idea. I'm going to have to think on this one a bit more. Actually, my buffer is < 8K as it is whatever space is left between my program space up to >6000. Right now, the program ends at either >5100 or around >5500. I need to check the GenLink statement to see if the value it is reporting the code file size, or end of the file of file size + >0400 for the start of the program. As I add more code, that buffer gets smaller.

 

MyTerm uses other 8K pages for logging buffer, screen buffers. Within the code/program space, I have buffers for the ANSI character definitions from 128 to 255 and space for a reverse video character definition so that text can be highlighted for Menus. I may be able to drop/move those storage buffers into another video page. Come to think of it, I may be able to do the same thing with the phone directory listing as well.

 

I remember years ago I asked Ron Walters how he was able to do some screen pop-ups so quickly. He had repetitive MOVB *R1+,*R2+ (16X, 32X, or 64X) instructions so there was minimal looping. All, just video moves. Made a huge difference in speed.

 

Beery

Share this post


Link to post
Share on other sites

Which method are you currently using to receive characters - polling or interrupt?

 

At 38.4Kbps maximum throughput you need to be able to receive at approximately 3,840 characters/second. Your rendering routine needs to be able to display (or process, in the case of escape sequences) at a decent speed to minimize buffer overflows and lost characters. If your display/processing is slower than the character reception routine, you will eventually hit the wall. TIMXT (the TI f18a terminal emulator) uses a 4K circular buffer which is a reasonably good size at 38.4k, though it still drops characters for long displays or complicated ANSI processing.

 

One thing I notice about your routine is that it has no apparent overflow protection. If your buffer wraps before you can display what is in the buffer, you will lose the entirety of what is there when the pointer wraps. To avoid this you can check/track the buffer position or keep track of how many characters are in the buffer, and then decide if you want to ignore any received characters when the buffer is full.

Share this post


Link to post
Share on other sites

A version for the SAMS might eliminate the buffer overflow issues. ;) Even using a small part of it, 48K, 64K or a 96K scroll back buffer would be awesome!

Share this post


Link to post
Share on other sites

The code I am using was originally from MyTerm and no overflow protection as you mentioned was present. At the 2400 to 9600 baud rates back then, and no ANSi, I do not think overflows were much of a concern. At these higher rates, they are. As such, I believe I am going to have to modify some buffers from their 8K capacity to something along the 4K size. I will have to step carefully with that part as there are some hard coded addresses I will need to make sure I catch.

 

Right now, I am strictly polling. I have not went back to the interrupt driven code yet. I wrapped up the phone dialer portion of the code, and added TIm's ANSI character definitions from 128 to 255. That gives me some nicer displays on my BBS. There was a start on the ANSI sequences by Riccio on the original code, but he just layed the initial groundwork with the control and escape sequences or VT-52 that I can then build upon for the ANSI work. The first thing I need to do is make sure I capture correctly the ANSI detect sequence and give it a proper response before I build any further. I've played with that a bit, but not sure if I am losing a byte when I first connect, or I am not terminating the response correctly.

 

Either way, my focus now has been to resolve the Xmodem transfer issue at 38.4K. With minimal feedback to the screen, I can sustain for about 200 sectors the transfer of MDOS. Eventually, at about 75% of the time, I get an overflow on the RS232 port bringing it to a halt on large files. As I sit here writing this, it just made me think about something I saw in one of the original video routines I questioned to myself last night. I may need to comment out a line and that may resolve the overflow issue and allow things to sync back up.

Share this post


Link to post
Share on other sites

Hardware Handshaking for the 9902 Receive side?

 

I am not the sharpest knife in the drawer, but when I look at TMS9902 data sheet, I see only hardware handshake control for when I want to send data.

I can control the RTS line to signal that TI-99 wants to send.

I cannot see anything that relates to preventing a sender from sending data TO the TI-99.

What am I missing?

 

Use case:

I want to prevent the PC from sending source code while TI-99 is digesting a line in the input buffer and then enable sending when Forth is ready to swallow the next line.

 

 

 

 

 

 

Share this post


Link to post
Share on other sites

You should be able to control the CTS line (outgoing, since the TI is a DCE) via CRU operation (bit 5, base >1300).

  • Like 1

Share this post


Link to post
Share on other sites
3 hours ago, mizapf said:

You should be able to control the CTS line (outgoing, since the TI is a DCE) via CRU operation (bit 5, base >1300).

OK I will give that a try.

 

Thanks!

Share this post


Link to post
Share on other sites

Looks like you shouldn't look exclusively at the 9902 datasheet anyway.  You're talking to an entire RS232 card with supporting hardware, not just a chip.  Well, not unless you're experimenting with the chip directly.

 

http://www.unige.ch/medecine/nouspikel/ti99/cru.htm#rs232

 

The 9902 itself only has a CTS input from the terminal.  It doesn't enforce any of its own flow control.

Share this post


Link to post
Share on other sites
2 minutes ago, ChildOfCv said:

Looks like you shouldn't look exclusively at the 9902 datasheet anyway.  You're talking to an entire RS232 card with supporting hardware, not just a chip.  Well, not unless you're experimenting with the chip directly.

 

http://www.unige.ch/medecine/nouspikel/ti99/cru.htm#rs232

 

The 9902 itself only has a CTS input from the terminal.  It doesn't enforce any of its own flow control.

Thank you.  That was my error.  I was looking at the chip doc only.  The card is the key.

 

 

Share this post


Link to post
Share on other sites
On 2/21/2018 at 12:35 PM, BeeryMiller said:

I remember years ago I asked Ron Walters how he was able to do some screen pop-ups so quickly. He had repetitive MOVB *R1+,*R2+ (16X, 32X, or 64X) instructions so there was minimal looping. All, just video moves. Made a huge difference in speed.

I know this is an old item but I noticed that in the Ramdisk (RAMBO) slideshow demo, Gary dynamically generates 6000+ MOVB instructions to copy picture image data to vdp ram. Takes up a lot of space but the image pops very quickly.

  • Like 3

Share this post


Link to post
Share on other sites

That's one way to get it done for sure.

 

8 hours ago, InsaneMultitasker said:

I know this is an old item but I noticed that in the Ramdisk (RAMBO) slideshow demo, Gary dynamically generates 6000+ MOVB instructions to copy picture image data to vdp ram. Takes up a lot of space but the image pops very quickly.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...