Page 1 of 1
Serial fun with the 6551
Posted: Sun Jun 28, 2015 2:01 pm
by lenzjo
I'm having a problem with the WDC65C51. It won't transmit until it receives something. At startup it is supposed to transmit a header message and then wait for input. What it actually does is nothing until I press a key, then it transmits the header. Then I press another key and the first key shows up on the screen. It always lags a character behind.
Setup:
I am using an
FT232RL FTDI USB to TTL Serial Converter to connect to the PC running
TeraTerm on Win7. USB are the only serial ports I have. Just to try and get this working I am not using flow control or interrupts. I have attached my software. I did find the post by floobydust, thank you very much, and I added the delay to the putch subroutine.
I have tested the FTDI by bridging the Tx & Rx lines and typing, no problem, characters appear as I type them. So that kind of tells me that TeraTerm and the FTDI are working properly. That leaves the software, I've tried different methods including having the putch and getch as inline code. nothing worked until this afternoon when I accidentally hit the keyboard and the header appeared. I have trimmed the sw down to the bare essentials and still cannot see any obvious, at least to me, errors.
Can someone please look over the code, maybe a fresh pair of eyes can see the mistake?
Re: Serial fun with the 6551
Posted: Sun Jun 28, 2015 3:32 pm
by JenniferDigital
I've just had a quick glance at your code and noticed you're checking the TXE bit.
Don't check that the TX buffer is empty at all with the WDC version of the 6551. The hardware has a bug in it that means the bit is stuck. Just add a delay to ensure that the char is transmitted fully before reloading. Also I tied DSRB and DCDB to ground. Not sure if I needed to but it works.
Just a qualifier though. I'm still new to this part myself but got it working in the end. Since I'm running my homebrew computer at just 2MHz at the moment I've gone and used a Rockwell version but I can imagine using the WDC version should I push the clock rate up beyond 2MHz.
Re: Serial fun with the 6551
Posted: Sun Jun 28, 2015 4:07 pm
by lenzjo
I've just had a quick glance at your code and noticed you're checking the TXE bit.
Don't check that the TX buffer is empty at all with the WDC version of the 6551. The hardware has a bug in it that means the bit is stuck. Just add a delay to ensure that the char is transmitted fully before reloading.
You know that's what I thought, the whole explanation for using the delay etc. But then floobydust includes the test in his
example code. So I don't know. I'll try it anyway, see if it makes a difference.
Also I tied DSRB and DCDB to ground. Not sure if I needed to but it works.
Done that, as well as CTSB tied to gnd for now.
Re: Serial fun with the 6551
Posted: Sun Jun 28, 2015 5:56 pm
by lenzjo
Well slap me with a kipper!! I took out the TXE bit test and the dam thing works now. Shoulda followed my instinct in the first place, and thanks DigitalDunc for that extra nudge in that direction.
Now a second, related, question. I want to do hardware handshaking, RTS/CTS. But the pinout for the FTDI converter(link in first post) is DTR, RxD, TxD, Vcc, CTS and GND.
Do I connect DTR to DSR(ACIA) & DCD(ACIA) and CTS to RTS(ACIA)?
Or should I tie it's DTR to GND and bring down RTS from the pcb and tie that to CTS(ACIA) and CTS to RTS(ACIA)?
Re: Serial fun with the 6551
Posted: Sun Jun 28, 2015 6:17 pm
by floobydust
Use a standard 5-wire null modem configuration:
1- Tie RXD from the FTDI to TXD on the 65C51
2- Tie TXD from the FTDI to RXD on the 65C51
3- Tie CTS from the FTDI to RTS on the 65C51
4- Tie RTS from the FTDI to CTS on the 65C51
5- Tie DCD, DTR, DSR together on the FTDI
6- Tie DCD, DTR, DSR together on the 65C51
7- Ensure the FTDI ground line is tied to system ground (same as the 65C51)
This is how I use the FTDI DB9-TTL Uart/USB interface with the 65C51.
Check the LOT Code # on the W65C51 and see if it matches the one in my post to confirm the problem chip... and also note that WDC updated the W65C51 datasheet recently that shows this problem in the errata, albeit they got it backwards.
Re: Serial fun with the 6551
Posted: Sun Jun 28, 2015 10:25 pm
by lenzjo
1, 2 and 7 already done, 3, 4 and 6 will do, 5 - got only DTR & DCD but that should be alright... yes?
The numbers I can make out on the chip are:
WDC65C51N6
A6A749.1
1016G015
I have the Oct 24th, 2014 datasheet, in the errata it says:
Transmitter Data Register Empty
The W65C51N will not properly set Bit 4 of the Status Register to indicate the Transmitter Data Register is empty. Determining when to send the next byte would need to be done by using the transmit interrupt or having a software delay loop based on the baud rate used.
Would it not be better to use the transmit interrupt, then the processor could get on with something else instead of the delay having to be tuned to both processor speed and baud rate?
Re: Serial fun with the 6551
Posted: Sun Jun 28, 2015 10:36 pm
by GARTHWILSON
With a very quick look, the only thing that jumps out that's actually wrong is:
Code: Select all
lda ACIA_STAT ; Get Status
and ACIA_RXF ; Rx full bit
and the same thing with "and ACIA_TXE." You need the "#" in there, otherwise you get an address and a ZP addressing mode, instead of a literal to AND the byte with.
Other things are just simplifications and streamlining. For example, the reset vector can be made to just point to MAIN instead of a place labeled RST_VEC that just has jmp MAIN, and the interrupt vectors could both go to the same RTI. Also:
Code: Select all
lda $00
sta ACIA_STAT ; Reset the ACIA
can be replaced with STZ ACIA_STAT. The processor comes out of reset with D clear and I set anyway, so there's no need to CLD and SEI to start. You're initially loading X and A with 0 which is unnecessary because you then immediately proceed to load something else in, without using the 0.
Code: Select all
jsr WAIT_6551 ; required Delay
rts
can be replaced with JMP WAIT_6551. Actually, you can go further than that, because since WAIT_6551 is next, you can also skip the JMP instruction and just include a comment that WAIT_6551 must remain next. Going even further, you're always done with A when you get there, so you can use A for a loop index in the wait routine and not push and pull Y.
Using my
structure macros, I would write,
Code: Select all
MAIN: LDX #$FF
TXS
JSR INIZ_ACIA
CLI
MSG: LDX #0
BEGIN
LDA MSG_HDR,X
WHILE_NOT_ZERO
JSR PUTCH
INX
REPEAT
BEGIN
JSR GETCH
CMP #$0D
IF_EQ
JSR PUTCH
LDA #$0A
END_IF
JSR PUTCH
AGAIN
MSG_HDR: .BYTE "TLC-MBC Monitor v0.1 - 27/06/15", $0D, $0A, $00
;-------------
GETCH: BEGIN ; Read one char from ACIA.
UNTIL_BIT ACIA_STAT, 3, IS_SET ; (You could also name the bit, but it should
; return the bit number, not its value.)
LDA ACIA_DATA
RTS
;-------------
PUTCH: PHA
BEGIN
UNTIL_BIT ACIA_STAT, 4, IS_SET
PLA
STA ACIA_DATA ; WAIT_6551 must be next.
;-------------
WAIT_6551:
PHX
FOR_A $10, DOWN_TO, 0
FOR_X $6B, DOWN_TO, 0
NEXT_X
NEXT_A
PLX
RTS
;-------------
which results in slightly fewer bytes of assembler output.
If you want to use an interrupt to tell you when it's ok to feed another byte to the transmit register, you can use a VIA timer (T1 or T2), and then the processor can do something useful while waiting.
Re: Serial fun with the 6551
Posted: Mon Jun 29, 2015 2:55 am
by floobydust
Like I said, WDC shows the Xmit bug in the latest datasheet, albeit they have it backwards, despite me diagnosing the problem completely and sharing my findings with them and the forum here. As a result, you can not use the Xmit bit flag for anything as it's stuck active. There are only two choices; use a delay routine when sending a character to allow the 65C51 to complete sending a character before sending another, or use a 65C22 timer to provide the interrupt and apply it towards the 65C51 driver routine (which is a kludge but more efficient).
Note that you do indeed have the defective WDC 65C51 chip, sorry (I have about 15 of them in DIP and PLCC). Note that Receive IRQ routines will work fine, just the Transmit is the problem and will not work with ANY existing 6551/65C51 coding due to the nature of the defect.
Re: Serial fun with the 6551
Posted: Mon Jun 29, 2015 6:29 am
by BigDumbDinosaur
There are only two choices; use a delay routine when sending a character to allow the 65C51 to complete sending a character before sending another, or use a 65C22 timer to provide the interrupt and apply it towards the 65C51 driver routine (which is a kludge but more efficient).
Three choices, actually: the two you mentioned, and 3) use something other than a 6551 and get out of the Stone Age when it comes to TIA-232 I/O processing. In my curmudgeonly opinion, the 6551 has absolutely nothing to recommend it. André Fachat has successfully adapted the 16550 to the 65xx bus, and Marco Demont, I and some others have adapted NXP industrial UARTs. These UARTs will run circles around a 6551 and will not require programming kludges to compensate for device defects.
Re: Serial fun with the 6551
Posted: Mon Jun 29, 2015 7:58 am
by lenzjo
@GARTHWILSON
Good catch with the #. I caught it too last nite when I got it to work
Code: Select all
0171 84B1 GETCH ; Read one char from ACIA
0172 84B1 A9 08 lda #ACIA_RXF
0173 84B3 GETCH_LOOP
0174 84B3 2C 01 81 bit ACIA_STAT ; Test Status
0175 84B6 F0 FB beq GETCH_LOOP ; not yet
0176 84B8 AD 00 81 lda ACIA_DATA ; read char
0177 84BB 60 rts
0178 84BC
0179 84BC
0180 84BC PUTCH ; Write one char to ACIA
0181 84BC 8D 00 81 sta ACIA_DATA ; and write it
0182 84BF 20 C4 84 jsr WAIT_6551 ; required Delay
0183 84C2 60 rts
I'm still in 6502 land as far as opcodes are concerned, I have yet to read up on the STZ and others available. Haven't used MC since about '84 so I'm a little rusty, plus I have been looking for a decent assembler, I'm using TASM for now. I miss Brevity, but once this is a usable computer I want to update and get Brevity working on it.
The current code is very un-optomised as it is testing code only, it is nowhere near to being done.
@ floobydust
Thanks for the advice, as you can see I'm using the delay for now.
@ BigDumbDinosaur
Four choices actually

I have a Synertek 6551 from way back when, needs testing to see if it's still good to go. Can't remember why now, but in the past I never used 65xx peripheral chips with the 6502, I used the 8255 to get three ports from the space of 2, and I used the 6850 when and if I needed serial stuff. The only reason I have a 65c51 and 65c22 now is that when I got the 65c02 I thought I may as well try the CMOS versions see if I like 'em or not. So far the 65c22 is okay, but the 65c51 is leaving a bad taste in my mouth, so I may well revert to the 6850 as I still have a couple of them, I might even try a Z80-SIO for kicks.
Re: Serial fun with the 6551
Posted: Mon Jun 29, 2015 8:41 am
by GARTHWILSON
plus I have been looking for a decent assembler, I'm using TASM for now. I miss Brevity, but once this is a usable computer I want to update and get Brevity working on it.
In case you want more to evaluate, I have a
list of assemblers, most (but not all) free.
One of the lines there goes to another, longer list. At least a couple of the assemblers--and very capable ones to boot--were written by 6502.org forum members.
Four choices actually

I have a Synertek 6551 from way back when, needs testing to see if it's still good to go. Can't remember why now, but in the past I never used 65xx peripheral chips with the 6502, I used the 8255 to get three ports from the space of 2, and I used the 6850 when and if I needed serial stuff. The only reason I have a 65c51 and 65c22 now is that when I got the 65c02 I thought I may as well try the CMOS versions see if I like 'em or not. So far the 65c22 is okay, but the 65c51 is leaving a bad taste in my mouth, so I may well revert to the 6850 as I still have a couple of them, I might even try a Z80-SIO for kicks.
The NMOS 6551 has a couple of bugs that were fixed in the CMOS 65c51 (until WDC introduced a couple more!). I have not had any trouble with the non-WDC 65c51's, although it would have been nice to separate at least a couple of the command functions. I guess they merged them to avoid having to add another register-select bit. The 6850 does not have an onboard baud-rate generator, and I see that as a major deficiency.
There are plenty of other options though. The
MAX3100 is a 14-pin UART that interfaces to the processor through
SPI. If you already have SPI planned, this would be a nice way to go. I've tried it and like it so I will probably use that one in the future. It has 8-byte transmit and receive buffers and takes less board space than the 6551. Part of its design is specifically to also be
IrDA-capable (for infrared communications). The
MAX3110E is the same thing with line drivers and receivers built in (saving even more board space), and it doesn't need any support parts like the popular MAX232 line driver/receiver IC does.
The only bug in the 65c22 VIA is one that will affect very few users. I have lots of circuits for interfacing things through the VIA on the
circuit potpourri page of the 6502 primer.
Re: Serial fun with the 6551
Posted: Mon Jun 29, 2015 11:02 am
by lenzjo
Thanks for that list of assemblers, I missed it when I went thru your guide, I shall have a look at it this evening.
I haven't exactly got SPI "planned" but it and I2C have been on my mind thanks to my playing around with the Arduino. As it stands I have a working 6522 and 6551 for the "mother board". The 6551 is there just to get the system up and running, I don't like being tethered to one computer just so I can use another. My immediate plans are to add a hex keypad, already built (20-key at the moment but may grow) and display, 6 "digit" (got some TIL305s and DL57s). SPI and/or I2C would certainly save some pins.
Yeah... the MAX3100 is a very tempting option, which in turn is twisting my arm towards SPI even more.
Re: Serial fun with the 6551
Posted: Wed Jul 01, 2015 8:00 pm
by BigDumbDinosaur
The 6850 does not have an onboard baud-rate generator, and I see that as a major deficiency.
Also, the 6850 has no FIFOs and is a slow part, suitable only for systems with low Ø2 rates. The lack of FIFOs (like the 6551) means that the system has to have good interrupt performance in order to efficiently process high baud rates. Unfortunately, the slow access times of the 6850 work against interrupt performance.