Jump to content
  • entries
    11
  • comments
    44
  • views
    13,289

Parallel Port Interfacing Using Extended Basic On The TI 99/4A Computer

Vorticon

1,356 views

As some of you know, I am constantly experimenting with interfacing the TI 99/A computer to the real world, and I am very fond of using the parallel port for that purpose because it is very easy to interface and program. That said, that kind of use of the parallel port does require low level programming, generally using assembly language, although one could achieve the same thing using either TurboForth or FbForth. This means that you are essentially out of luck unless you know how to program in assembly or Forth. But not anymore!
I have written a set of assembly language routines accessible directly from Extended Basic which allow you to communicate at the low level with the parallel port, thus allowing you to focus on the interfacing part. In this blog entry, I will detail the hardware as well as the software required to achieve successful interfacing.

First off, before we start discussing the software side of things, we need to have some sort of physical experimentation set up connected to the parallel port. The parallel connector on the RS232 card is a 16 pin proprietary connector primarily meant to connect to a Centronics parallel printer. The easiest way to go about this is to get hold of a TI printer cable which you can purchase here: http://www.connectworld.net/cgi-bin/cabled/L0810?. However, it is pricey, and you might check Ebay or AtariAge as an alternative. You can of course make your own as well if you are so inclined.
Next cut off the Centronics end, strip the ends of the wires, and solder them to a DB25 connector (either male or female) just so:

blogentry-25753-0-56127300-1484702816_thumb.jpg
You can also use crimp type DB25 connectors if you don't want to solder, but I find that the latter provides a more sturdy connection. Pin 1 is the wire with the red stripe, and pin 16 is the last wire on the other side. The DB25 connector pins are numbered from 1 to 25, so you will only use 16 of them. Match the pin numbers with the proper wire on the cable. It is fiddly work, but well worth the effort. Once completed, you can get a parallel port breakout connector off of Amazon or Ebay, making sure that it mates with the sex of the connector on the cable:

blogentry-25753-0-05755100-1484273137_thumb.jpg
blogentry-25753-0-82045200-1484702828_thumb.jpg

Now you should have easy access to all the parallel port pins. Just connect jumper cables from the breakout connector to a breadboard and off you go. Let's briefly describe the pinouts of the parallel port:

Pin	I/O	Function	Access1	O	HANDSHAKEOUT	CRU bit 22	I/O	D7 (lsb)	Byte >50003	I/O	D64	I/O	D55	I/O	D46	I/O	D37	I/O	D28	I/O	D19	I/O	D0 (msb)10	I	HANDSHAKEIN	CRU bit 211	-	Ground	-12	O	+5V via 10 Ohm	-13	I	SPAREIN	CRU bit 314	O	SPAREOUT	CRU bit 315	O	+5V via 1 KOhm	-16	-	Ground	-


The parallel port is bidirectional, meaning that it can be used for input or for output. It has 8 data lines D7-D0 corresponding to pins 2-9 which will be the main pins you will use for your projects. There are 2 input only lines (HANDSHAKEIN AND SPAREIN - pins 10 and 13) and 2 output only lines (HANDSHAKEOUT AND SPAREOUT - pins 1 and 14). There are also 2 +5V sources (pins 12 and 15), but I usually prefer to use an external power source for my projects. The remaining pins (11 and 16) are ground.
As you can see, it is quite a versatile port with plenty of possibilities. I have used it to control a robotic arm, to drive a slot car and to connect to a raspberry Pi camera for vision experiments to name a few.
A little further down, I will give you a practical example on how to use that set up and demonstrate how easy it is to experiment with it.

But for now, I'll discuss the use of Extended Basic to control the parallel port. What you will need is the Extended Basic cartridge, 32K RAM, RS232 card and a disk drive. Download the attached disk image and transfer it to a real floppy disk or a Lotharek drive. It contains the assembly language routines required by Extended Basic for low-level parallel port access. You can peek at the code here if you want.

** XB PIO LOW LEVEL CONTROL UTILITIES ****          JANUARY 2017              ****       BY WALID MAALOULI            **        DEF  DATOUT,DATIN,HSKIN,HSKOUT,SPRIN,SPROUTPIO    EQU  >5000             PIO PORT DATA ADDRESSFAC    EQU  >834A             FLOATING POINT ACCUMULATOR ADDRESSXMLLNK EQU  >2018NUMASG EQU  >2008NUMREF EQU  >200CREGSTR BSS  8                 STORAGE FOR RETURN REGISTERS ** SEND DATA OUT TO DATA LINESDATOUT MOV  R11,@REGSTR       MOV  R13,@REGSTR+2       MOV  R14,@REGSTR+4       MOV  R15,@REGSTR+6       BL   @PIOINI       CLR  R0       LI   R1,1              SELECT ARGUMENT 1 FROM XB CALL       BLWP @NUMREF           FETCH ARGUMENT AND PLACE IN FAC       BLWP @XMLLNK       DATA >12B8             CONVERT ARGUMENT TO INTEGER       SBZ  1                 SET PIO PORT TO OUTPUT       MOVB @FAC+1,@PIO       SEND BYTE TO PIO PORT       B    @RETURN ** RECEIVE DATA FROM DATA LINESDATIN  MOV  R11,@REGSTR       MOV  R13,@REGSTR+2       MOV  R14,@REGSTR+4       MOV  R15,@REGSTR+6       BL   @PIOINI       SBO  1                 SET PIO PORT TO INPUT       MOVB @PIO,R2           GET BYTE FROM PIO PORT INTO R2       CLR  @FAC       MOVB R2,@FAC+1         MOVE RECEIVED BYTE TO LOW BYTE OF FAC       BLWP @XMLLNK       DATA >0020             CONVERT BYTE TO FLOATING POINT NUMBER       CLR  R0       LI   R1,1              SELECT ARGUMENT 1 FROM XB CALL       BLWP @NUMASG           ASSIGN NUMBER TO SELECTED ARGUMENT       B    @RETURN ** SEND BIT TO HANDSHAKEOUT LINEHSKOUT MOV  R11,@REGSTR       MOV  R13,@REGSTR+2       MOV  R14,@REGSTR+4       MOV  R15,@REGSTR+6       BL   @PIOINI       CLR  R0       LI   R1,1              SELECT ARGUMENT 1 FROM XB CALL       BLWP @NUMREF           GET VALUE FROM ARGUMENT INTO FAC       BLWP @XMLLNK       DATA >12B8             CONVERT VALUE TO INTEGER       MOV  @FAC,R2       CI   R2,1       JNE  HSKRST       SBO  2                 SET HANDSHAKEOUT LINE TO LOGIC 1       B    @RETURNHSKRST SBZ  2                 SET HANDSHAKEOUT LINE TO LOGIC 0       B    @RETURN ** RECEIVE LOGIC STATUS OF HANDSHAKEIN LINEHSKIN  MOV  R11,@REGSTR       MOV  R13,@REGSTR+2       MOV  R14,@REGSTR+4       MOV  R15,@REGSTR+6       BL   @PIOINI       TB   2                 READ LOGIC STATUS OF HANDSHAKEIN LINE       JNE  HSKIN0       LI   R2,1       JMP  SNDVALHSKIN0 CLR  R2SNDVAL MOV  R2,@FAC       BLWP @XMLLNK       DATA >0020             CONVERT LINE BIT VALUE TO FLOAT NUMBER       CLR  R0       LI   R1,1              SELECT ARGUMENT 1 FROM XB CALL       BLWP @NUMASG           SEND LOGIC STATUS TO ARGUMENT 1       B    @RETURN ** SEND BIT TO SPAREOUT LINESPROUT MOV  R11,@REGSTR       MOV  R13,@REGSTR+2       MOV  R14,@REGSTR+4       MOV  R15,@REGSTR+6       BL   @PIOINI       CLR  R0       LI   R1,1              SELECT ARGUMENT 1 FROM XB CALL       BLWP @NUMREF           PLACE VALUE OF ARGUMENT 1 INTO FAC       BLWP @XMLLNK       DATA >12B8             CONVERT ARGUMENT VALUE TO INTEGER       MOV  @FAC,R2       CI   R2,1       JNE  SPRRST       SBO  3                 SET THE SPROUT LINE       B    @RETURNSPRRST SBZ  3                 RESET THE SPROUT LINE       B    @RETURN ** RECEIVE LOGIC STATUS OF THE SPRIN LINESPRIN  MOV  R11,@REGSTR       MOV  R13,@REGSTR+2       MOV  R14,@REGSTR+4       MOV  R15,@REGSTR+6       BL   @PIOINI       TB   3                 READ THE LOGIC STATE OF THE SPRIN LINE       JNE  SPRIN0       LI   R2,1       JMP  SNDVALSPRIN0 CLR  R2       JMP  SNDVAL ** INITIALIZE RS232 CARDPIOINI LI   R12,>1300         PLACE RS232 CARD CRU ADDRESS IN R12       SBO  0                 ACTIVATE CARD       SBO  7                 TURN CARD LED ON       RT ** RETURN TO XBRETURN SBZ  7                 TURN CARD LED OFF       SBZ  0                 INACTIVATE RS232 CARD       MOV  @REGSTR,R11       MOV  @REGSTR+2,R13       MOV  @REGSTR+4,R14       MOV  @REGSTR+6,R15       RT        END




The first thing your program should include are these 2 lines:

CALL INIT
CALL LOAD("DSKx.PIOLIB")

Replace the x with the drive number where the file resides. These statements load up the utilities needed to control the parallel port. The following is a description of the actual control statements you will have available:

CALL LINK("DATOUT",n)
n is an integer between 0 and 255 and can be an explicit number or a numeric variable. The number is converted to binary and put out on the 8 data lines of the parallel port. This will allow you to control any or all of the data lines just by selecting the appropriate number. A discussion of the conversion between decimal and binary is beyond the scope of this blog, but the information is easy to obtain online and to understand.

CALL LINK("DATIN",var)
var is a numeric variable. This call will read the data lines of the parallel port, convert them to a decimal number, and place it in the variable. Based on the number returned, you will be able to tell which data lines were active.

CALL LINK("SPROUT",n)
n can be either 0 or 1, thus making the SPROUT line either low or high respectively.

CALL LINK("SPRIN",var)
var is a numeric variable. This call returns the logic state of the SPRIN line, 1 for high, 0 for low.

CALL LINK("HSKOUT",n)
n can be either 0 or 1, thus making the HSKOUT line either low or high respectively.

CALL LINK("HSKIN",var)
var is a numeric variable. This call returns the logic state of the HSKIN line, 1 for high, 0 for low.


That's it! With these calls, you will be able to take complete control of the parallel port at the low level.

Now for the fun part :) I'm going to demonstrate all these routines in action. I created a setup using LED's connected to the parallel port which will provide a visual demonstration of the XB commands. Here's the basic circuit:

blogentry-25753-0-20029400-1484683366_thumb.jpg

blogentry-25753-0-83917400-1484683778_thumb.jpg

There is no need for an external power supply in this case because the circuit draws very little current. However, for more advanced interfacing, an external power supply will likely be needed. Note that the LED labeled D9 in the picture above should actually be D7.

For starters, here's a simple XB program that asks you to input a number between 0 and 255, and outputs it to the parallel port, lighting up the appropriate LED. It's a good way to brush up on your decimal to binary conversion knowlege :)

10 CALL CLEAR20 CALL INIT30 CALL LOAD("DSK5.PIOLIB")40 CALL LINK("DATOUT",0) :: CALL LINK("HSKOUT",0) :: CALL LINK("SPROUT",0)50 INPUT "ENTER NUMBER: ":N :: IF N<0 OR N>255 THEN 5060 CALL LINK("DATOUT",N) :: GOTO 50


Line 40 clears all the data and signal lines. This is important because the initial state of the lines when you start the computer up is unpredictable.

This next program exercises all the output lines by playing a game of ping pong between the HANDSHAKEOUT and SPAREOUT lines. First the HSKOUT LED lights up and throws the "ball" which travels along the data LED's. When it reaches the end, the SPROUT line lights up in turn to throw it back to the SPROUT LED. And so on and so forth.

10 CALL CLEAR20 CALL INIT30 CALL LOAD("DSK5.PIOLIB")40 CALL LINK("DATOUT",0) :: CALL LINK("HSKOUT",0) :: CALL LINK("SPROUT",0)50 CALL LINK("SPROUT",0) :: CALL LINK("HSKOUT",1)60 FOR I=0 TO 770 CALL LINK("HSKOUT",0)80 N=2^I :: CALL LINK("DATOUT",N)90 FOR DELAY=1 TO 10 :: NEXT DELAY100 NEXT I110 CALL LINK("SPROUT",1)120 FOR I=7 TO 0 STEP-1130 CALL LINK("SPROUT",0)140 N=2^I :: CALL LINK("DATOUT",N)150 FOR DELAY=1 TO 10 :: NEXT DELAY160 NEXT I170 GOTO 50


The main thing to understand here is that each data LED, from the LSB to the MSB, is represented by the value 2x, with x going from 0 to 7 for an 8 bit data bus. So 20 is 1, and the LSB LED lights up. Next, 21 is 2, and the second LED lights up, etc... Again this is basic binary notation. So in the program, line 50 lights up the HSKOUT LED and shuts off the SPROUT LED. Then it turns off the HSKOUT LED and starts a sequential lighting of the data LED's from 20 to 27. Once it gets to the end, the SPROUT LED lights up, then it turns off and the data LED's are sequentially lit in reverse from 27 to 20, then the cycle starts over.

This last program demonstrates the HANDSHAKEIN AND SPAREIN lines:

10 CALL CLEAR20 CALL INIT30 CALL LOAD("DSK5.PIOLIB")40 CALL LINK("HSKIN",HSK) :: CALL LINK("SPRIN",SPR)50 PRINT "HSK: ";HSK;"  SPR: ";SPR60 GOTO 40


All it does is poll the HSKIN and SPRIN lines and display their status. For this test, you need to supply a 5V power source to the setup in order to provide a logic state to the input lines. The same process is applicable to the data lines when used for input.

These XB demo programs are included on the attached disk as well. Here's a video demonstrating all 3 programs in action on real hardware:

https://youtu.be/NNFkgXqQR7A

You should now have all the needed information and tools to go ahead and start experimenting with connecting your TI to the real world. You are only bound by your imagination! Feel free to ask for help if you run into any snags.

  • Like 1


1 Comment


Recommended Comments

Wowza!!! I was in the middle of writing some low oevel routines to.do just this!!! But you have saved me a bunch of work.

 

Thanks, Vorticon!!

Share this comment


Link to comment
Guest
Add a comment...

×   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...