Working around the W65C51 transmit buffer empty bug
Re: Working around the W65C51 transmit buffer empty bug
For those still wanting to use the W65c51, warts and all, the idea of externally counting time and feeding back a signal to the /DSR input is a good one. There's an easier way to do it, however, which will work in most practical configurations with less "gubbins". I think I have it down to two dedicated ICs, plus an inverter that might be left over from somewhere else in the design.
My solution would be to use a 74HC40103 (an 8-bit presettable down-counter) to count pulses of the RxC clock, which the W65c51 presents as an output if neither Rx nor Tx are configured to use an external clock. With both configured for the internal clock, both also run at the same baud rate, and the RxC output pulses at 16x rate. The external clock input feature is primarily used to explicitly synchronise one ACIA to another, or to run at a non-standard baud rate such as for MIDI, so for most applications RxC will accurately reflect the Tx clock.
In 8N1 format (10 bit times per frame), and 16 clock pulses per bit, each byte transmitted takes 160 pulses. This can be hardwired into the '40103 preset, or you could play it safe by presetting it to 192 instead (12 bit times); either option straps two pins high ($A0 and $C0 respectively) and the rest low. An active-low pulse on the /PL pin will load this value into the counter independently of the RxC clock. Tie /MR and /PE high to prevent spurious presets.
When the counter expires, it will pull the /TC output low. Feed this through an inverter and back to the /TE input, so it will stop counting at zero and keep /TC asserted, then resume counting when the preset is loaded. No additional flipflop is required to hold this status. Either the active-low direct or active-high inverted /TC drives /DSR on the W65c51. The /DSR status bit then replaces the TxBUSY status bit as previously described.
As well as saving several ICs, the major advantage of this approach is that you don't need to change anything to support different baud rates or frame formats, largely because the RxC clock is automatically varied by the ACIA for you. The 192 preset (12 bit times) is enough to cover an 8-bit byte, a parity bit, and two stop bits - a maximum combination which I'm not sure the W65c51 even supports in the first place. Smaller frame sizes will also work with this preset, but there will be slight gaps between characters and the transmission rate will be correspondingly reduced.
My solution would be to use a 74HC40103 (an 8-bit presettable down-counter) to count pulses of the RxC clock, which the W65c51 presents as an output if neither Rx nor Tx are configured to use an external clock. With both configured for the internal clock, both also run at the same baud rate, and the RxC output pulses at 16x rate. The external clock input feature is primarily used to explicitly synchronise one ACIA to another, or to run at a non-standard baud rate such as for MIDI, so for most applications RxC will accurately reflect the Tx clock.
In 8N1 format (10 bit times per frame), and 16 clock pulses per bit, each byte transmitted takes 160 pulses. This can be hardwired into the '40103 preset, or you could play it safe by presetting it to 192 instead (12 bit times); either option straps two pins high ($A0 and $C0 respectively) and the rest low. An active-low pulse on the /PL pin will load this value into the counter independently of the RxC clock. Tie /MR and /PE high to prevent spurious presets.
When the counter expires, it will pull the /TC output low. Feed this through an inverter and back to the /TE input, so it will stop counting at zero and keep /TC asserted, then resume counting when the preset is loaded. No additional flipflop is required to hold this status. Either the active-low direct or active-high inverted /TC drives /DSR on the W65c51. The /DSR status bit then replaces the TxBUSY status bit as previously described.
As well as saving several ICs, the major advantage of this approach is that you don't need to change anything to support different baud rates or frame formats, largely because the RxC clock is automatically varied by the ACIA for you. The 192 preset (12 bit times) is enough to cover an 8-bit byte, a parity bit, and two stop bits - a maximum combination which I'm not sure the W65c51 even supports in the first place. Smaller frame sizes will also work with this preset, but there will be slight gaps between characters and the transmission rate will be correspondingly reduced.
Re: Working around the W65C51 transmit buffer empty bug
I managed to distill this into a diagram:
Re: Working around the W65C51 transmit buffer empty bug
Nice and compact, I think you ought to AND in PHI2 though on the PL signal, otherwise it could get triggered erroneously while the buses transition.
Re: Working around the W65C51 transmit buffer empty bug
If that proves necessary, it could be done by substituting a /WE signal (which most systems will have anyway) for the R/W input to the trigger circuit. Same gates otherwise.
Re: Working around the W65C51 transmit buffer empty bug
Chromatix wrote:
the major advantage of this approach is that you don't need to change anything to support different baud rates
Here's another spin -- one of many possible -- on the supporting logic.
-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
https://laughtonelectronics.com/Arcana/ ... mmary.html
Re: Working around the W65C51 transmit buffer empty bug
Just a thought that occurred while reading about this hardware bug. I haven't seen it suggested by anyone else so apologies if it's there somewhere but I've missed it.
Since the Rx side of the W65C51 works as expected and can be used with interrupts, why not flog a dead horse back to life with another dead horse? What I mean is this: use a second W65C51's RxD input to monitor the TxD output of the main chip. Then use the second chip's 'Rx register full' interrupt to indicate that the character has been sent - a pretty fair replacement for the broken 'Tx register empty' interrupt.
I'm designing a breadboard circuit to test this and I think in practice it will be simpler to dedicate one chip to providing the Tx function, using its Rx half as the monitor, and dedicating the other chip to providing just the Rx function.
Disadvantages: Needs an extra ACIA chip and occupies PCB space. Not suitable for replacing existing 6551s. Needs its own I/O address space.
Advantages: Uses only one extra chip, though quite a big one. Existing interrupt driven code should be easy to adapt. Not dependent on timers or polling loops and is independent of PHI2 and baud rate.
Since the Rx side of the W65C51 works as expected and can be used with interrupts, why not flog a dead horse back to life with another dead horse? What I mean is this: use a second W65C51's RxD input to monitor the TxD output of the main chip. Then use the second chip's 'Rx register full' interrupt to indicate that the character has been sent - a pretty fair replacement for the broken 'Tx register empty' interrupt.
I'm designing a breadboard circuit to test this and I think in practice it will be simpler to dedicate one chip to providing the Tx function, using its Rx half as the monitor, and dedicating the other chip to providing just the Rx function.
Disadvantages: Needs an extra ACIA chip and occupies PCB space. Not suitable for replacing existing 6551s. Needs its own I/O address space.
Advantages: Uses only one extra chip, though quite a big one. Existing interrupt driven code should be easy to adapt. Not dependent on timers or polling loops and is independent of PHI2 and baud rate.
Re: Working around the W65C51 transmit buffer empty bug
John_M wrote:
Disadvantages: Needs an extra ACIA chip and occupies PCB space. Not suitable for replacing existing 6551s. Needs its own I/O address space.
Advantages: Uses only one extra chip, though quite a big one. Existing interrupt driven code should be easy to adapt. Not dependent on timers or polling loops and is independent of PHI2 and baud rate.
My plan would be to solder one directly on-top of another and just bring out the relevant tx/rx and select pins. you could put pads on the underlying PCB for these 3 pins if needed. I did that with 2 x 32KB RAM chips on my original Ruby 6502 board, so no reason why it might not work here...
Cheers,
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: Working around the W65C51 transmit buffer empty bug
drogon wrote:
That's an interesting idea and I might just try it as I have a bunch in a tube otherwise unused...
- John
Re: Working around the W65C51 transmit buffer empty bug
I guess you can also use some of the other pins on the extra one as general purpose output pins. Be careful with all the output pins if you solder them together.
You could also connect TX and RX together on the same chip instead of connecting them between chips.
However if you do have a VIA then it is extremely easy to connect up PB6 and get the interrupts you need from that, so I do recommend that route.
You could also connect TX and RX together on the same chip instead of connecting them between chips.
However if you do have a VIA then it is extremely easy to connect up PB6 and get the interrupts you need from that, so I do recommend that route.
Re: Working around the W65C51 transmit buffer empty bug
gfoot wrote:
You could also connect TX and RX together on the same chip instead of connecting them between chips.
- John
- BigDumbDinosaur
- Posts: 9428
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Working around the W65C51 transmit buffer empty bug
John_M wrote:
Since the Rx side of the W65C51 works as expected and can be used with interrupts, why not flog a dead horse back to life with another dead horse?
Better yet, why not use a UART that actually works right?
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Working around the W65C51 transmit buffer empty bug
I know your views on the subject, BDD, and respect them. I even posted my diagram in monochrome in your honour, having spent a long time reading before posting. To answer your question, I want to do it this way because I think it might work; because I haven't seen anyone else suggest it; because I have, along with many readers of this thread, a small collection of the chips that would otherwise sit there doing nothing; because, if it works, anyone using this method will need to buy twice as many W65C51s which will rapidly deplete the stocks and signal to WDC that the chip is an amazing success after all and cause them to worry about running out and consider that making a new batch with all bugs fixed would be a great and profitable idea; but mostly because I've decided it's what I want to do, for the sheer enjoyment of it. Isn't that what it's all about, anyway? 
Re: Working around the W65C51 transmit buffer empty bug
John_M wrote:
I know your views on the subject, BDD, and respect them. I even posted my diagram in monochrome in your honour, having spent a long time reading before posting. To answer your question, I want to do it this way because I think it might work; because I haven't seen anyone else suggest it; because I have, along with many readers of this thread, a small collection of the chips that would otherwise sit there doing nothing; because, if it works, anyone using this method will need to buy twice as many W65C51s which will rapidly deplete the stocks and signal to WDC that the chip is an amazing success after all and cause them to worry about running out and consider that making a new batch with all bugs fixed would be a great and profitable idea; but mostly because I've decided it's what I want to do, for the sheer enjoyment of it. Isn't that what it's all about, anyway? 
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Re: Working around the W65C51 transmit buffer empty bug
gfoot wrote:
You could also connect TX and RX together on the same chip instead of connecting them between chips.
It's fairly simple to implement an output routine which always expects an immediate echo, though of course with a single part you can't have full duplex operation... but incoming data can always be handled *unless* you've just sent a byte.
Neil
- BigDumbDinosaur
- Posts: 9428
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Working around the W65C51 transmit buffer empty bug
John_M wrote:
To answer your question, I want to do it this way because I think it might work; because I haven’t seen anyone else suggest it;
Oh, don’t get me wrong. I’m curious to see how your idea pans out. I don’t think the question is whether it will work. The unknown is how well it will work.
Some notes:
- Due to the 6551’s brain-dead design, CTSB, DCDB and DSRB must all be asserted to get full-duplex operation.
- Diodes D1 and D2 are superfluous, as the 65C61’s IRQB is open-collector (the WDC 65C22S is the one with a totem-pole IRQB). In any case, the 1N4148 would have too much forward drop to get reliable operation when either UART asserts IRQ.
- The 10K pullup on the IRQ line is too high a value—the circuit will be noise-sensitive. My recommendation would be a value between 2.2K and 3.3K.
- It might be beneficial to insert some delay between TxD and RxD on U1, given that the TxD “stuck” flag bug is the result of some sort of race condition in the device’s design. Some MOS Technology peripheral devices have had an occasional problem with failing to interrupt when two events are within one or two Ø2 cycles of each other.
Quote:
...if it works, anyone using this method will need to buy twice as many W65C51s which will rapidly deplete the stocks and signal to WDC that the chip is an amazing success after all and cause them to worry about running out and consider that making a new batch with all bugs fixed would be a great and profitable idea...
Quite the fantasy you have there, my friend.
x86? We ain't got no x86. We don't NEED no stinking x86!