6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 10:14 pm

All times are UTC




Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Tue Sep 24, 2024 12:23 pm 
Offline

Joined: Wed Apr 02, 2003 9:18 pm
Posts: 33
I know that the forum is mostly agreed that newer UART solutions are better, but I'm constrained at the moment by what I have available, which is a NXP PC16550DV :) Here's it's datasheet:

I've connected the 16550 much like this example with some chip selection differences (CS0 and CS1 tied to +5v, and controlled by /CS2). The input is fed directly to the 16550's serial in (SIN) pin through a CP2101 USB<->Serial adapter, and the output (SOUT) fed directly back to the CP2101. For some reason, I'm not getting predictable results...in fact, the input is correct but the output is...weird.

I've attached two images showing a logic analyzer capture of the serial lines. In one, it's clear that the letter 'a' was typed, but the output was TWO 'a' characters. Sometimes they appear as 'aa', others as 'Aa'. It gets weirder with other characters such as 'U', which outputs a 0xFF plus the original 'U' character. I've attached the captures as images to this post.

To me this smells like something to do with flow control, but I've gone over my code many times and I can't pinpoint the problem. I'm hoping someone here might have had the same experience, or can immediately spot what is happening.

I've probed the RD and WR logic, which works just fine with the attached SRAM, and I can verify that I am receiving the character correctly as well as transmitting the same single character to the 16550. Something in the chip is wonky. I've tried three different 16550s, and each display the same issue. It's not completely unheard of to get a bad batch of chips though. I've also as a last resort attempted to set up a small delay between character transmits, to no avail.

Anyway, any pointers would be very well received. I'm open to trying anything. My code (using ca65) is below.

Code:
.setcpu         "65816"
.smart          on

UART_RXTX   = $df10      ; DLAB=0
UART_IER   = $df11      ; DLAB=0
UART_DLL   = $df10      ; divisor latch low, DLAB=1
UART_DLH   = $df11      ; divisor latch high, DLAB=1
UART_IIR   = $df12      ; Irq Ident. Reg., read only
UART_FCR   = $df12      ; FIFO Ctrl Reg., write only
UART_LCR   = $df13      ; Line Ctrl Reg
UART_MCR   = $df14      ; Modem Ctrl Reg
UART_LSR   = $df15      ; Line Status Reg
UART_MSR   = $df16      ; Modem Status Reg
UART_SCR   = $df17      ; 'scratchpad', i.e. unused

;;;
;;; macros
;;;
.macro  longa
    rep #%00100000
.endmacro

.macro  longr
    rep #%00110000
.endmacro

.macro  longx
    rep #%00010000
.endmacro

.macro  shorta
    sep #%00100000
.endmacro

.macro  shortr
    sep #%00110000
.endmacro

.macro  shortx
    sep #%00010000
.endmacro

.segment "CODE"

.proc   main: near
    cld         ; clear decimal mode
    sei         ; no interrrupts
    clc
    xce         ; go to native mode
    shorta
    longx
    .a8
    .i16
    ldx #$01ff
    txs         ; reset stack pointer

    ; ordered according to Intel's docs
    lda #%00000111
    sta UART_FCR        ; Enable and clear FIFOs, trigger at 1 byte

    lda #%00000011
    sta UART_LCR        ; 8N1

    stz UART_IER        ; no interrupts (polled mode)

    ora #%10000000
    sta UART_LCR        ; turn on DLAB flag to set baud rate

    lda #3              ; divisior of 3 ($03) is 38400 with 1.8432 MHz xtal
    sta UART_DLL
    lda #0
    sta UART_DLH

    lda UART_LCR
    and #%01111111
    sta UART_LCR        ; turn off DLAB flag

    stz UART_MCR        ; reset DTR, RTS

    ; input
in_loop:
    lda UART_LSR
    bit #%00000001      ; bit 0 set = data available
    beq in_loop
    lda UART_RXTX

    ; output
    pha
out_loop:
    lda UART_LSR
    bit #%00100000            ; bit 5 set = tx ready
    beq out_loop
    pla
    sta UART_RXTX

    ldx #$80
break_loop:
    dex
    bne break_loop

    jmp in_loop
.endproc


Attachments:
File comment: Capture of the letter 'a'
U.png
U.png [ 14.2 KiB | Viewed 1020 times ]
File comment: Capture of the letter 'U'
a.png
a.png [ 14.84 KiB | Viewed 1020 times ]
Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 25, 2024 5:57 pm 
Offline

Joined: Wed Apr 02, 2003 9:18 pm
Posts: 33
For future reference...all of the issues I had were caused from enabling the FIFO. I didn't realize that by leaving the FIFO disabled it would work character-at-a-time.

Now that the issue is resolved, I guess it's on to learn how to program for the FIFO :)


Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 25, 2024 7:11 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1385
Yes, the FIFO can be a different thing. I've not written any support routines for the 16550, but dabbled with the 8250 and 16450 back in the 80's...

Some years ago, I ditched the 6551 and started with the SCC2691 and later to the SC28L92 DUART. I also found coding for the FIFO a bit interesting but nothing difficult. I eventually enabled the full FIFOs in the SC28L92 and that's what I'm planning to stick with going forward.

Not sure if any of this helps, but my SC28L92 BIOS code is on github.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 25, 2024 9:13 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8513
Location: Midwestern USA
floobydust wrote:
Yes, the FIFO can be a different thing. I've not written any support routines for the 16550, but dabbled with the 8250 and 16450 back in the 80's...

In fact, there was at least one version of the 16550 in which enabling the FIFO actual broke operation.  I don’t recall the gory details, but think that was an issue prior to the 16550C.

As for the 8250 and 16450, those things are almost as primitive as the 6850 and 6551.

Quote:
Some years ago, I ditched the 6551 and started with the SCC2691 and later to the SC28L92 DUART. I also found coding for the FIFO a bit interesting but nothing difficult. I eventually enabled the full FIFOs in the SC28L92 and that's what I'm planning to stick with going forward.

I got familiar with the NXP 26- and 28-series UARTS back in 1990 and never looked back.  Although NXP has since discontinued those series, Exar and TI continue to be second sources for the 26C92 and 28L92.  I consider the 28L92 to be superior to anything in the 16--- family, especially since the 28L92 has the sub-microsecond counter/timer (C/T).  Both Kevin and I use the C/T to generate a jiffy IRQ for timing purposes—it’s very stable.

FIFO usage isn’t at all difficult once you understand the principles—it’s a simple looping operation in assembly language.

Attachment:
File comment: Receiver Access During IRQ
rxd_isr_flow_small.gif
rxd_isr_flow_small.gif [ 81.63 KiB | Viewed 646 times ]
Attachment:
File comment: Transmitter Access During IRQ
txd_isr_flow_small.gif
txd_isr_flow_small.gif [ 35.92 KiB | Viewed 646 times ]

The 28L92’s FIFOs can be configured to be 16-deep and the device can be set up to interrupt at one of several fill levels.  I have my receivers set to interrupt when there are 12 or more datums in the FIFO, which tactic minimizes the risk of a data overrun (as does use of CTS/RTS handshaking).  I have the transmitters set to interrupt only when the FIFO is empty, which makes it possible to load 16 datums into each transmitter in a single interrupt and then go on to something else.  Can you say “greatly improved transmit throughput?”  :D

Judicious use of the FIFOs will substantially reduce interrupt activity and enhance overall system throughput.  I can simultaneously run all four serial ports on POC V1.3 at 115.2 KbpS in both directions without bogging down the machine, even at the relatively slow Ø2 rate of 4 MHz (usually, Ø2 is 16 MHz).  Efficient eight-channel serial I/O using the 28L92 (four of them) is possible in a system running at 8 MHz or better.

Quote:
Not sure if any of this helps, but my SC28L92 BIOS code is on github.

Also, there is some information around here on using the 28L91 and 28L92 in a 65xx system.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Thu Sep 26, 2024 9:44 am 
Offline
User avatar

Joined: Tue Feb 28, 2023 11:39 pm
Posts: 257
Location: Texas
I got FIFO working on my 16C550C; which was a nice to have over the 6551, but also without the receive flag bug. However, when I swapped the 6502 with a 65816, the IC just about lost it's mind. (Nothing else changed, just the CPU).

Not sure why, but best guess I have is that the multiplexed address/data was confusing the one I have. The 6551 was fine with the swap; I haven't tried the 26L92s I have sitting around. Partially because I haven't wanted to bother with trying to interface a 44 PLCC to the breadboard setup.


Top
 Profile  
Reply with quote  
PostPosted: Thu Sep 26, 2024 2:53 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8513
Location: Midwestern USA
Yuri wrote:
I got FIFO working on my 16C550C; which was a nice to have over the 6551, but also without the receive flag bug. However, when I swapped the 6502 with a 65816, the IC just about lost it's mind. (Nothing else changed, just the CPU).

Not sure why, but best guess I have is that the multiplexed address/data was confusing the one I have. The 6551 was fine with the swap; I haven't tried the 26L92s I have sitting around. Partially because I haven't wanted to bother with trying to interface a 44 PLCC to the breadboard setup.

Are you using the 65C816’s VDA and VPA signals to qualify memory and I/O accesses?  The 6551 “understands” most of the 65C816 bus cycle and can (usually) get by without such qualification.  The 16550 does not “understand” the 816 bus cycle—at a minimum, you need to qualify the 16550 chip select with VDA so it isn’t spooked during “dead” cycles that put bogus addresses on the bus.

Also, how are you qualify reads and writes to the 16550?  What works with the 6551 isn’t going to fly with a part that “understands” only the Intel bus cycle.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Thu Sep 26, 2024 4:20 pm 
Offline
User avatar

Joined: Tue Feb 28, 2023 11:39 pm
Posts: 257
Location: Texas
BigDumbDinosaur wrote:
Yuri wrote:
I got FIFO working on my 16C550C; which was a nice to have over the 6551, but also without the receive flag bug. However, when I swapped the 6502 with a 65816, the IC just about lost it's mind. (Nothing else changed, just the CPU).

Not sure why, but best guess I have is that the multiplexed address/data was confusing the one I have. The 6551 was fine with the swap; I haven't tried the 26L92s I have sitting around. Partially because I haven't wanted to bother with trying to interface a 44 PLCC to the breadboard setup.

Are you using the 65C816’s VDA and VPA signals to qualify memory and I/O accesses?  The 6551 “understands” most of the 65C816 bus cycle and can (usually) get by without such qualification.  The 16550 does not “understand” the 816 bus cycle—at a minimum, you need to qualify the 16550 chip select with VDA so it isn’t spooked during “dead” cycles that put bogus addresses on the bus.

Also, how are you qualify reads and writes to the 16550?  What works with the 6551 isn’t going to fly with a part that “understands” only the Intel bus cycle.



I did not qualify anything with the VDA and VPA pins, all I did was swap the 6502 with the 65816 in my bread board. Mostly as an experiment to see if it would work.

That being said, the read/write signals are coming off of a 74HC139 which is using PHI2 to gate the RD/ and WR/ values.

I'll take a gander at the VDA and VPA pins.

EDIT: Ignore the fact that the schematic says "LS" I forgot to change it when I was quickly drawing that up in KiCAD, I am in fact using an HC part in that circuit.

EDIT2: Corrected diagram:
Attachment:
Screenshot 2024-09-26 132027.png
Screenshot 2024-09-26 132027.png [ 16.88 KiB | Viewed 563 times ]


(This is what I get for going fast..... >_< )


Top
 Profile  
Reply with quote  
PostPosted: Thu Sep 26, 2024 10:51 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8513
Location: Midwestern USA
The 74HC139 is a little on the slow side for that particular use, but is probably okay.  On the other hand, with no VDA qualification, there’s an excellent chance the 16550 is being adversely affected by false bus cycles generated by the 65C816.  You’d have the same problem if there were an NMOS 6502 in the circuit, as without VDA and VPA qualification, the 816’s bus behavior is like that of the NMOS part (something that Apple demanded of the 816 to support their stupidly-designed disk subsystem).

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 27, 2024 1:37 am 
Offline
User avatar

Joined: Tue Feb 28, 2023 11:39 pm
Posts: 257
Location: Texas
BigDumbDinosaur wrote:
The 74HC139 is a little on the slow side for that particular use, but is probably okay.  On the other hand, with no VDA qualification, there’s an excellent chance the 16550 is being adversely affected by false bus cycles generated by the 65C816.  You’d have the same problem if there were an NMOS 6502 in the circuit, as without VDA and VPA qualification, the 816’s bus behavior is like that of the NMOS part (something that Apple demanded of the 816 to support their stupidly-designed disk subsystem).



Mmmm.... lovely.

Yea, the 139 & 138 are the parts I had on hand when I built this along with the 8KB ROM, it worked out well.

The 16550 is still very unhappy with this even with the qualifications though. The little LCD is quite happy with things though, so I'm fairly sure the wiring is right.

Here's the revisions (complete with both the 139 and 138)

May have to break down and get some 1508s.


Attachments:
Screenshot 2024-09-26 203430.png
Screenshot 2024-09-26 203430.png [ 77.42 KiB | Viewed 546 times ]
Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 27, 2024 6:44 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8513
Location: Midwestern USA
The VDP connection on the HC138 is not doing anything useful for you.  The 74HC139 used to generate /RD and /WD is likely keeping those signals asserted too long after the fall of the clock.  I suspect (without seeing the circuit running on the bench) that your timing is too skewed relative to Ø2 to produce reliable results.  Can you try replacing the 74HC hardware with 74AHC?

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 27, 2024 7:07 pm 
Offline
User avatar

Joined: Tue Feb 28, 2023 11:39 pm
Posts: 257
Location: Texas
BigDumbDinosaur wrote:
The VDP connection on the HC138 is not doing anything useful for you.  The 74HC139 used to generate /RD and /WD is likely keeping those signals asserted too long after the fall of the clock.  I suspect (without seeing the circuit running on the bench) that your timing is too skewed relative to Ø2 to produce reliable results.  Can you try replacing the 74HC hardware with 74AHC?


No ACH139's in my parts bin. However, I have some ATF16V8C PLDs which are rated at 5ns.

ATF16V8C Datasheet

Reworking it now to use that instead; also means I can ditch the '138, and the '00, at least for this breadboard test setup.


Top
 Profile  
Reply with quote  
PostPosted: Sat Sep 28, 2024 2:07 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8513
Location: Midwestern USA
Yuri wrote:
No ACH139's in my parts bin. However, I have some ATF16V8C PLDs which are rated at 5ns.

That ought to work.  Make sure the VCC and ground connections to the PLD are robust.  Those things eat a lot of electrons.  :D

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sat Sep 28, 2024 5:42 am 
Offline
User avatar

Joined: Tue Feb 28, 2023 11:39 pm
Posts: 257
Location: Texas
BigDumbDinosaur wrote:
Yuri wrote:
No ACH139's in my parts bin. However, I have some ATF16V8C PLDs which are rated at 5ns.

That ought to work.  Make sure the VCC and ground connections to the PLD are robust.  Those things eat a lot of electrons.  :D


Yea! I noticed! Rails dropped by about .5V when I had it plugged in. Overall I'm pretty sure the power in this bread board setup is pushing the limits.

o_O

That being said! I finally got everything working again after replacing all those ICs with the PLD.

Seems there is no change. The PLD is checking the VDA (code below), but still the 16550 just spews garbage when the 65816 is in there.

If I tie the VDA pin high and put the 6502 back in, it's perfectly happy with life.

Code:
Name     SigMaster;
PartNo   EBSSPI00;
Date     9/27/2024;
Revision 06;
Designer Bryce Simonds;
Company  Firesun Media;
Assembly None;
Location ;
Device   g16v8a;

/* *************** INPUT PINS *********************/

PIN 1 = CLK;
PIN 2 = RWb;  // Read/Write(bar)

PIN 3 = VDA;
//PIN 4 = VDP;

PIN 5 = A14;
PIN 6 = A13;
PIN 7 = A12;
PIN 8 = A11;
PIN 9 = A10;

PIN 11 = OE; // A15

/* *************** OUTPUT PINS *********************/

PIN 12 = !RD;
PIN 13 = !WR;
PIN 14 = !ROM;
PIN 15 = !VIA;
PIN 16 = !UART;
PIN 17 = LCD;
PIN 18 = !DEV0;
PIN 19 = !DEV1;

/* *************** Logic *********************/

RD = CLK & RWb;
WR = CLK & !RWb;

ROM = OE & A13 & A14;

VIA  = OE & VDA & !A10 & !A11 & !A12 & !A13 & !A14;
UART = OE & VDA &  A10 & !A11 & !A12 & !A13 & !A14;
LCD  = OE & VDA & !A10 &  A11 & !A12 & !A13 & !A14 & CLK;
DEV0 = OE & VDA &  A10 &  A11 & !A12 & !A13 & !A14;
DEV1 = OE & VDA & !A10 & !A11 &  A12 & !A13 & !A14;


Top
 Profile  
Reply with quote  
PostPosted: Sat Sep 28, 2024 9:23 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8513
Location: Midwestern USA
What’s the purpose of defining A15 as OE in your GAL code?  To me, that’s unnecessarily confusing, since all chip-select equations are evaluating address bus conditions (and VDA for the I/O block), and you are not defining the GAL’s output-enable features anywhere in your code.

I would use the FIELD keyword to define the address bus, e.g., FIELD addr = [A15..10]; in your application, which makes for more concise expressions in your output equations.  I would then write the UART chip select equation as UART = VDA & addr:['h'84xx], which is much easier to understand, and less likely to be in error due to forgetting to use a negation (!) where needed.  Similarly, I would define the ROM chip select as ROM = addr:['h'Exxx];, which, again, is much easier to understand.

Also conspicuous by its absence is any definition for RAM.  Is there no RAM in this system?  Also, it would be very helpful if you posted a full schematic, not bits and pieces.

Yuri wrote:
Rails dropped by about .5V when I had it plugged in.

You need to fix that power problem—a loss of a half-volt under load is unacceptable, in my opinion.  It wouldn’t surprise me if you also have a ground bounce problem in this unit.

Something else to consider would be adding a bus transceiver to isolate the data bus from the 65C816 during Ø2 low.  I’m speculating as to whether or not that would help—data bus contention right after Ø2 goes high is a potential problem with the 816.  If that is happening, you should be able to see its effects on the scope by monitoring VCC at the 816, with the scope being triggered by the rise of Ø2.

I have a feeling your breadboard construction is behind most of your problems.  Also, do you have a bypass capacitor at each chip?

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sat Sep 28, 2024 10:36 pm 
Offline
User avatar

Joined: Tue Feb 28, 2023 11:39 pm
Posts: 257
Location: Texas
BigDumbDinosaur wrote:
What’s the purpose of defining A15 as OE in your GAL code?  To me, that’s unnecessarily confusing, since all chip-select equations are evaluating address bus conditions (and VDA for the I/O block), and you are not defining the GAL’s output-enable features anywhere in your code.


Namely because the datasheet has that pin labelled as OE; easy enough to change.

Quote:
I would use the FIELD keyword to define the address bus, e.g., FIELD addr = [A15..10]; in your application, which makes for more concise expressions in your output equations.  I would then write the UART chip select equation as UART = VDA & addr:['h'84xx], which is much easier to understand, and less likely to be in error due to forgetting to use a negation (!) where needed.  Similarly, I would define the ROM chip select as ROM = addr:['h'Exxx];, which, again, is much easier to understand.


Figured there was a better way to do it; but it was late, I was tired, and this is what my two brain cells could conjure up at that hour.

I did have the foresight to test the logic of the PLD itself on another breadboard, so I know it works. (For the record, I'm not planning to keep this on a PLD/Breadboard)

Quote:
Also conspicuous by its absence is any definition for RAM.  Is there no RAM in this system?  Also, it would be very helpful if you posted a full schematic, not bits and pieces.


RAM is the lower 32K of the 64K address space, and is controlled directly by the A15 line. I'll draw up a full schematic; lost the previous one.

Quote:

Yuri wrote:
Rails dropped by about .5V when I had it plugged in.

You need to fix that power problem—a loss of a half-volt under load is unacceptable, in my opinion.  It wouldn’t surprise me if you also have a ground bounce problem in this unit.


Entirely possible; I've tortured these bread boards for a while now, so there's no telling what condition they actually are in. That being said, this is what I noticed when I put JUST the PLD on a breadboard all by itself and connected my bench supply to it.

(Could be I have a bad bench supply? Maybe my multi meter is being wack? IDK, I'm sure I have the less than ideal set of equipment here.)

Quote:
Something else to consider would be adding a bus transceiver to isolate the data bus from the 65C816 during Ø2 low.  I’m speculating as to whether or not that would help—data bus contention right after Ø2 goes high is a potential problem with the 816.  If that is happening, you should be able to see its effects on the scope by monitoring VCC at the 816, with the scope being triggered by the rise of Ø2.


Yea, I threw a '245 in there to see if that would help, but no luck with that either. I even went as far as moving back to a single stepped clock and manually pulsing the write line.

On the 6502 there's a bit a junk I see on the data lines that comes through, but the UART seems fine with that.

The 65816 looks absolutely perfect as far as I can tell, and yet it just sends junk. The scope shows it just absolutely blasting the bits as fast as possible even though I set it down to 1200.

Quote:
I have a feeling your breadboard construction is behind most of your problems.  Also, do you have a bypass capacitor at each chip?


No doubt, been wanting to get off the breadboard for a while. Though seems really odd that it is reliably working on the 6502 without any issues what-so-ever, but completely looses it when the 65816. I'd think I'd seem more random issues if the breadboards were at fault. *shrug*

Yes, I've put caps all over the place, as close to the power rails of the chips as I can reasonably get them.


I finally threw up my hands and broke out the 44 LCC breakout board and hooked up one of the SC26C92s I have.

Got that working just fine with both the 6502 and the 65816.

At this point the CPUs @ 2MHz are just blasting the characters so fast it's overrunning the TX buffer at 1200 baud, no surprise, but easy to fix in software.

(Full schematic will be forth coming once I get it drawn up)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 30 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: