Let’s start at the beginning!
It looks as though your ‘hex bashing’ and understanding of the instruction set at the hex level for the processor is pretty good – so I will stick with that for my code so that I hope I won’t confuse you! This takes me back to my youth!
If you can get into assembler programming at the mnemonic level – you will find this much easier and less error prone. You can download pretty good cross-assemblers for Windows or Linux (or whatever your flavour of operating system is) and use your favourite text editor to create the assembler programs, assemble them (and even test them) and then download the resulting binary or hex file to your IMSAI machine for final running. The main advantages are that you can thoroughly comment your program, the assembler handles all the addresses for the jump instructions for you and when your program cr*ps out on your IMSAI you go back to your PC and fix it quite simply. Anyhow, that’s for another day – back to your problem…
I assume you have downloaded, read and understand the technical manual for the Intel 8251 chip? If not, download it from “
http://www.datasheetcatalog.org/datasheet/Intel/mXtyswx.pdf”. The name of the PDF file looks a bit funny – so this might be a “once only” download. If so, just do a search for the 8251 datasheet from Intel.
The first thing is not to hit RESET at any point! If the RESET button is wired to the reset pin of the 8251 (which it probably is) hitting reset will cause any previous initialisation to be thrown away. If you are setting up the 8251, then pressing reset and expecting it to work you will be very disappointed…
I agree with Chuck that there could be some cr*p sent to the 8251 after reset but before you actually send it something in rare cases – although I would say that this is a design flaw that you are working around.
I am also confused by your initialisation sequence.
I am assuming here that you are starting your programs at address 0000.
0000 3E <MODE> ; LD A,<MODE>
0002 D3 03 ; OUT (3),A
0004 3E 37 ; LD A,<COMMAND1>
0006 D3 03 ; OUT (3),A
0008 3E 27 ; LD A,<COMMAND2>
000A D3 03 ; OUT (3),A
000C DB 03 ; WAITLP: IN A,(3)
000E E6 04 ; AND <TXEMPTY>
0010 CA 0C 00 ; JZ WAITLP (WAIT FOR TXEMPTY)
0013 3E 41 ; LD A,<ASCII_A>
0015 D3 02 ; OUT (2),A
0017 C3 0C 00 ; JMP WAITLP
(I am a Z80 nut so my mnemonics are in Z80-speak).
So, what does my program do?
<MODE> should be setup to suit your desired number of stop bits, parity, parity enable/disable and character length. Obviously, this value must be setup correctly to match your terminal. The key thing is that the last TWO BITS of <MODE> should be set to ‘10’ (binary). This sets the UART to asynchronous mode (rather than synchronous mode) and divides the externally-supplied baudrate clock by 16. This is the usual default. If you change this value, then the indicated baudrates may not be as expected. So, to set up 2 stop bits, EVEN parity, partity enabled and 8 data bits you would have a <MODE> value of ‘FE’
<COMMAND1> sets Request To Send (RTS), clears the error flags, enables the receiver, sets Data Terminal ready (DTR) and enables the transmitter.
<COMMAND2> does the same but disables the reset of the error flags. Issuing two commands like this is the correct initialisation procedure as this configures the 8251 and resets any errors. If you are writing a receive routine then you should be looking for any parity, framing or overrun errors if they exist and take action accordingly.
I look at bit 3 (TxEMPTY) rather than bit 0 (TxRDY) in my test.
So, my hex code for the above code (loaded into location 0000) would be:
3E FE D3 03 3E 37 D3 03 3E 27 D3 03 DB 03 E6 04 CA 0C 00 3E 41 D3 02 C3 0C 00
The next thing is the hardware handshake lines. I generally interconnect the hardware handshake lines if they are not in use. On a 25-way D connector this would be to link pins 4-5 (RTS [Request To Send] / CTS [Clear To Send]) and pins 6-8-20 (DSR [Data Set Ready] / CD {Carrier Detect] / DTR [Data Terminal Ready]). Do this at the SIO connector end. If the 8251 is expecting the Clear To Send signal before it transmits anything – and it isn’t actually wired up – then the 8251 will wait for a very long while! Linking 4-5 (RTS/CTS) and driving RTS in software (bit 5 of the COMMAND byte) should fool the 8251 into transmitting something.
Before wiring up the terminal I would actually check that the terminal is happy with only TX, RX and GND being wired up. Strap just pins 2 to 3 on the terminal and check that when you type on the keyboard that the characters you type actually appear on the display. If so, remove the 2-3 link and make sure the characters stop when you type some more!
The other thing to check is to make sure that transmit of the terminal is wired to receive of the SIO and vice-versa. Use an LED (with a series resistor) or a multimeter to find the the ‘strong’ source of voltage. This should be the transmit line in each case. I use a green LED in inverse parallel with a red LED and both LEDs in servies in series with a 330 Ohm resistor. Connect one end to pin 7 (ground) and use the other end as a sensor lead. One or the other of the LEDs should light up when it is connected to the transmit line. If my description doesn’t make sense I can post a schematic diagram.
Don’t forget that I/O ports 2 and 3 are for SIA ‘A@ and not ‘B’ (i.e. is the terminal connected to the correct connector).
After that we are looking into either a major hardware fault or a major configuration fault. I assume you already know if the I/O space between 00 and 0F is unused apart from the SIO board?
If you have a debug monitor on your S100 board that can input and output bytes to selected I/O ports then you can always use the debug monitor to output bytes manually rather than under program control.
Hope this is of some help to you.
Dave